Page MenuHomePhabricator

No OneTemporary

diff --git a/contrib/devtools/github-merge.py b/contrib/devtools/github-merge.py
deleted file mode 100755
index e7146e369..000000000
--- a/contrib/devtools/github-merge.py
+++ /dev/null
@@ -1,284 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (c) 2016 The Bitcoin Core developers
-# Distributed under the MIT software license, see the accompanying
-# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-# This script will locally construct a merge commit for a pull request on a
-# github repository, inspect it, sign it and optionally push it.
-
-# The following temporary branches are created/overwritten and deleted:
-# * pull/$PULL/base (the current master we're merging onto)
-# * pull/$PULL/head (the current state of the remote pull request)
-# * pull/$PULL/merge (github's merge)
-# * pull/$PULL/local-merge (our merge)
-
-# In case of a clean merge that is accepted by the user, the local branch with
-# name $BRANCH is overwritten with the merged result, and optionally pushed.
-from __future__ import division, print_function, unicode_literals
-import os
-from sys import stdin, stdout, stderr
-import argparse
-import subprocess
-import json
-import codecs
-try:
- from urllib.request import Request, urlopen
-except:
- from urllib2 import Request, urlopen
-
-# External tools (can be overridden using environment)
-GIT = os.getenv('GIT', 'git')
-BASH = os.getenv('BASH', 'bash')
-
-# OS specific configuration for terminal attributes
-ATTR_RESET = ''
-ATTR_PR = ''
-COMMIT_FORMAT = '%h %s (%an)%d'
-if os.name == 'posix': # if posix, assume we can use basic terminal escapes
- ATTR_RESET = '\033[0m'
- ATTR_PR = '\033[1;36m'
- COMMIT_FORMAT = '%C(bold blue)%h%Creset %s %C(cyan)(%an)%Creset%C(green)%d%Creset'
-
-
-def git_config_get(option, default=None):
- '''
- Get named configuration option from git repository.
- '''
- try:
- return subprocess.check_output([GIT, 'config', '--get', option]).rstrip().decode('utf-8')
- except subprocess.CalledProcessError as e:
- return default
-
-
-def retrieve_pr_info(repo, pull):
- '''
- Retrieve pull request information from github.
- Return None if no title can be found, or an error happens.
- '''
- try:
- req = Request("https://api.github.com/repos/" +
- repo + "/pulls/" + pull)
- result = urlopen(req)
- reader = codecs.getreader('utf-8')
- obj = json.load(reader(result))
- return obj
- except Exception as e:
- print('Warning: unable to retrieve pull information from github: %s' % e)
- return None
-
-
-def ask_prompt(text):
- print(text, end=" ", file=stderr)
- stderr.flush()
- reply = stdin.readline().rstrip()
- print("", file=stderr)
- return reply
-
-
-def parse_arguments():
- epilog = '''
- In addition, you can set the following git configuration variables:
- githubmerge.repository (mandatory),
- user.signingkey (mandatory),
- githubmerge.host (default: git@github.com),
- githubmerge.branch (no default),
- githubmerge.testcmd (default: none).
- '''
- parser = argparse.ArgumentParser(description='Utility to merge, sign and push github pull requests',
- epilog=epilog)
- parser.add_argument('pull', metavar='PULL', type=int, nargs=1,
- help='Pull request ID to merge')
- parser.add_argument('branch', metavar='BRANCH', type=str, nargs='?',
- default=None, help='Branch to merge against (default: githubmerge.branch setting, or base branch for pull, or \'master\')')
- return parser.parse_args()
-
-
-def main():
- # Extract settings from git repo
- repo = git_config_get('githubmerge.repository')
- host = git_config_get('githubmerge.host', 'git@github.com')
- opt_branch = git_config_get('githubmerge.branch', None)
- testcmd = git_config_get('githubmerge.testcmd')
- signingkey = git_config_get('user.signingkey')
- if repo is None:
- print("ERROR: No repository configured. Use this command to set:", file=stderr)
- print("git config githubmerge.repository <owner>/<repo>", file=stderr)
- exit(1)
- if signingkey is None:
- print("ERROR: No GPG signing key set. Set one using:", file=stderr)
- print("git config --global user.signingkey <key>", file=stderr)
- exit(1)
-
- host_repo = host + ":" + repo # shortcut for push/pull target
-
- # Extract settings from command line
- args = parse_arguments()
- pull = str(args.pull[0])
-
- # Receive pull information from github
- info = retrieve_pr_info(repo, pull)
- if info is None:
- exit(1)
- title = info['title']
- # precedence order for destination branch argument:
- # - command line argument
- # - githubmerge.branch setting
- # - base branch for pull (as retrieved from github)
- # - 'master'
- branch = args.branch or opt_branch or info['base']['ref'] or 'master'
-
- # Initialize source branches
- head_branch = 'pull/' + pull + '/head'
- base_branch = 'pull/' + pull + '/base'
- merge_branch = 'pull/' + pull + '/merge'
- local_merge_branch = 'pull/' + pull + '/local-merge'
-
- devnull = open(os.devnull, 'w')
- try:
- subprocess.check_call([GIT, 'checkout', '-q', branch])
- except subprocess.CalledProcessError as e:
- print("ERROR: Cannot check out branch %s." % (branch), file=stderr)
- exit(3)
- try:
- subprocess.check_call([GIT, 'fetch', '-q', host_repo,
- '+refs/pull/' + pull + '/*:refs/heads/pull/' + pull + '/*'])
- except subprocess.CalledProcessError as e:
- print("ERROR: Cannot find pull request #%s on %s." %
- (pull, host_repo), file=stderr)
- exit(3)
- try:
- subprocess.check_call(
- [GIT, 'log', '-q', '-1', 'refs/heads/' + head_branch], stdout=devnull, stderr=stdout)
- except subprocess.CalledProcessError as e:
- print("ERROR: Cannot find head of pull request #%s on %s." %
- (pull, host_repo), file=stderr)
- exit(3)
- try:
- subprocess.check_call(
- [GIT, 'log', '-q', '-1', 'refs/heads/' + merge_branch], stdout=devnull, stderr=stdout)
- except subprocess.CalledProcessError as e:
- print("ERROR: Cannot find merge of pull request #%s on %s." %
- (pull, host_repo), file=stderr)
- exit(3)
- try:
- subprocess.check_call([GIT, 'fetch', '-q', host_repo,
- '+refs/heads/' + branch + ':refs/heads/' + base_branch])
- except subprocess.CalledProcessError as e:
- print("ERROR: Cannot find branch %s on %s." %
- (branch, host_repo), file=stderr)
- exit(3)
- subprocess.check_call([GIT, 'checkout', '-q', base_branch])
- subprocess.call([GIT, 'branch', '-q', '-D',
- local_merge_branch], stderr=devnull)
- subprocess.check_call([GIT, 'checkout', '-q', '-b', local_merge_branch])
-
- try:
- # Create unsigned merge commit.
- if title:
- firstline = 'Merge #%s: %s' % (pull, title)
- else:
- firstline = 'Merge #%s' % (pull,)
- message = firstline + '\n\n'
- message += subprocess.check_output([GIT, 'log', '--no-merges', '--topo-order',
- '--pretty=format:%h %s (%an)', base_branch + '..' + head_branch]).decode('utf-8')
- try:
- subprocess.check_call([GIT, 'merge', '-q', '--commit', '--no-edit',
- '--no-ff', '-m', message.encode('utf-8'), head_branch])
- except subprocess.CalledProcessError as e:
- print("ERROR: Cannot be merged cleanly.", file=stderr)
- subprocess.check_call([GIT, 'merge', '--abort'])
- exit(4)
- logmsg = subprocess.check_output(
- [GIT, 'log', '--pretty=format:%s', '-n', '1']).decode('utf-8')
- if logmsg.rstrip() != firstline.rstrip():
- print("ERROR: Creating merge failed (already merged?).", file=stderr)
- exit(4)
-
- print('%s#%s%s %s %sinto %s%s' % (ATTR_RESET + ATTR_PR, pull,
- ATTR_RESET, title, ATTR_RESET + ATTR_PR, branch, ATTR_RESET))
- subprocess.check_call([GIT, 'log', '--graph', '--topo-order',
- '--pretty=format:' + COMMIT_FORMAT, base_branch + '..' + head_branch])
- print()
- # Run test command if configured.
- if testcmd:
- # Go up to the repository's root.
- toplevel = subprocess.check_output(
- [GIT, 'rev-parse', '--show-toplevel']).strip()
- os.chdir(toplevel)
- if subprocess.call(testcmd, shell=True):
- print("ERROR: Running %s failed." % testcmd, file=stderr)
- exit(5)
-
- # Show the created merge.
- diff = subprocess.check_output(
- [GIT, 'diff', merge_branch + '..' + local_merge_branch])
- subprocess.check_call(
- [GIT, 'diff', base_branch + '..' + local_merge_branch])
- if diff:
- print("WARNING: merge differs from github!", file=stderr)
- reply = ask_prompt("Type 'ignore' to continue.")
- if reply.lower() == 'ignore':
- print("Difference with github ignored.", file=stderr)
- else:
- exit(6)
- reply = ask_prompt("Press 'd' to accept the diff.")
- if reply.lower() == 'd':
- print("Diff accepted.", file=stderr)
- else:
- print("ERROR: Diff rejected.", file=stderr)
- exit(6)
- else:
- # Verify the result manually.
- print(
- "Dropping you on a shell so you can try building/testing the merged source.", file=stderr)
- print("Run 'git diff HEAD~' to show the changes being merged.", file=stderr)
- print("Type 'exit' when done.", file=stderr)
- # Show pull number on Debian default prompt
- if os.path.isfile('/etc/debian_version'):
- os.putenv('debian_chroot', pull)
- subprocess.call([BASH, '-i'])
- reply = ask_prompt("Type 'm' to accept the merge.")
- if reply.lower() == 'm':
- print("Merge accepted.", file=stderr)
- else:
- print("ERROR: Merge rejected.", file=stderr)
- exit(7)
-
- # Sign the merge commit.
- reply = ask_prompt("Type 's' to sign off on the merge.")
- if reply == 's':
- try:
- subprocess.check_call(
- [GIT, 'commit', '-q', '--gpg-sign', '--amend', '--no-edit'])
- except subprocess.CalledProcessError as e:
- print("Error signing, exiting.", file=stderr)
- exit(1)
- else:
- print("Not signing off on merge, exiting.", file=stderr)
- exit(1)
-
- # Put the result in branch.
- subprocess.check_call([GIT, 'checkout', '-q', branch])
- subprocess.check_call(
- [GIT, 'reset', '-q', '--hard', local_merge_branch])
- finally:
- # Clean up temporary branches.
- subprocess.call([GIT, 'checkout', '-q', branch])
- subprocess.call([GIT, 'branch', '-q', '-D',
- head_branch], stderr=devnull)
- subprocess.call([GIT, 'branch', '-q', '-D',
- base_branch], stderr=devnull)
- subprocess.call([GIT, 'branch', '-q', '-D',
- merge_branch], stderr=devnull)
- subprocess.call([GIT, 'branch', '-q', '-D',
- local_merge_branch], stderr=devnull)
-
- # Push the result.
- reply = ask_prompt(
- "Type 'push' to push the result to %s, branch %s." % (host_repo, branch))
- if reply.lower() == 'push':
- subprocess.check_call([GIT, 'push', host_repo, 'refs/heads/' + branch])
-
-
-if __name__ == '__main__':
- main()

File Metadata

Mime Type
text/x-diff
Expires
Wed, Jan 29, 17:01 (10 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5053354
Default Alt Text
(11 KB)

Event Timeline