Page MenuHomeFreeBSD

D40023.diff
No OneTemporary

D40023.diff

diff --git a/tools/tools/git/git-ghpr b/tools/tools/git/git-ghpr
new file mode 100755
--- /dev/null
+++ b/tools/tools/git/git-ghpr
@@ -0,0 +1,211 @@
+#!/usr/bin/env python3
+#
+# git-ghpr - Merge commits from github pull requests to main
+#
+# Copyright (c) 2023 M. Warner Losh <imp@FreeBSD.org>
+#
+# SPX-License-Identifier: MIT
+#
+# Some code taken verbatim (or lightly tweaked) from git-publish by
+# Stefan Hajnoczi <stefanha@gmail.com> licensed under MIT.
+
+import glob
+import datetime
+import locale
+import optparse
+import os
+import re
+import subprocess
+import sys
+
+VERSION = '0.0.1'
+#git-publish+
+
+# Encoding for command-line arguments
+CMDLINE_ENCODING = locale.getpreferredencoding()
+
+# Encoding for communicating with the Git executable
+GIT_ENCODING = 'utf-8'
+
+# Encoding for files that GIT_EDITOR can edit
+TEXTFILE_ENCODING = CMDLINE_ENCODING
+
+# As a git alias it is helpful to be a single file script with no external
+# dependencies, so these git command-line wrappers are used instead of
+# python-git.
+
+class GitError(Exception):
+ pass
+
+class GitHookError(Exception):
+ pass
+
+def popen_lines(cmd, **kwargs):
+ '''Communicate with a Popen object and return a list of lines for stdout and stderr'''
+ stdout, stderr = cmd.communicate(**kwargs)
+ stdout = re.split('\r\n|\n',stdout.decode(GIT_ENCODING))[:-1]
+ stderr = re.split('\r\n|\n',stderr.decode(GIT_ENCODING))[:-1]
+ return stdout, stderr
+
+def _git_check(*args):
+ '''Run a git command and return a list of lines, may raise GitError'''
+ cmdstr = 'git ' + ' '.join(('"%s"' % arg if ' ' in arg else arg) for arg in args)
+ if VERBOSE:
+ print(cmdstr)
+ cmd = subprocess.Popen(['git'] + list(args),
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ stdout, stderr = popen_lines(cmd)
+ if cmd.returncode != 0:
+ raise GitError('ERROR: %s\n%s' % (cmdstr, '\n'.join(stderr)))
+ return stdout
+
+def _git(*args):
+ '''Run a git command and return a list of lines, ignore errors'''
+ try:
+ return _git_check(*args)
+ except GitError:
+ # ignore git command errors
+ return []
+
+def _git_with_stderr(*args):
+ '''Run a git command and return a list of lines for stdout and stderr'''
+ if VERBOSE:
+ print('git ' + ' '.join(args))
+ cmd = subprocess.Popen(['git'] + list(args),
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ stdout, stderr = popen_lines(cmd)
+ return stdout, stderr, cmd.returncode
+
+def git_get_current_branch():
+ git_dir = git_get_git_dir()
+ rebase_dir = os.path.join(git_dir, 'rebase-merge')
+ if os.path.exists(rebase_dir):
+ branch_path = os.path.join(rebase_dir, 'head-name')
+ prefix = 'refs/heads/'
+ # Path names are encoded in UTF-8 normalization form C.
+ with open(branch_path, encoding=GIT_ENCODING) as f:
+ branch = f.read().strip()
+ if branch.startswith(prefix):
+ return branch[len(prefix):]
+ return branch
+ else:
+ return _git_check('symbolic-ref', '--short', 'HEAD')[0]
+
+GIT_TOPLEVEL = None
+def git_get_toplevel_dir():
+ global GIT_TOPLEVEL
+ if GIT_TOPLEVEL is None:
+ GIT_TOPLEVEL = _git_check('rev-parse', '--show-toplevel')[0]
+ return GIT_TOPLEVEL
+
+GIT_DIR = None
+def git_get_git_dir():
+ global GIT_DIR
+ if GIT_DIR is None:
+ GIT_DIR = _git('rev-parse', '--git-dir')[0]
+ return GIT_DIR
+
+def git_branch_exists(branch):
+ '''Check if the given branch exists'''
+ try:
+ _git_check('rev-parse', '-q', '--verify', branch)
+ return True
+ except GitError:
+ return False
+
+def setup():
+ '''Add git alias in ~/.gitconfig'''
+ path = os.path.abspath(sys.argv[0])
+ ret = subprocess.call(['git', 'config', '--global',
+ 'alias.ghpr', '!' + path])
+ if ret == 0:
+ print('You can now use \'git ghpr\' like a built-in git command.')
+
+#git-publish-
+
+def git_checkout(*args):
+ '''Return status of the tree'''
+ return _git_check('checkout', *args)
+
+def parse_args():
+
+ parser = optparse.OptionParser(version='%%prog %s' % VERSION,
+ usage='%prog [options] -- [common format-patch options]',
+ description='Do all the MFC tweaks needed when merging from main to stable/XX.',
+ epilog='Please report bugs to Warner Losh <imp@freebsd.org>.')
+ parser.add_option('-b', '--branch', dest='branch', default='PR',
+ help='branch to use [defaults PR]')
+ parser.add_option('--pr', dest='pr', default=None,
+ help='Pull request to land')
+ parser.add_option('--setup', dest='setup', action='store_true', default=False,
+ help='add git alias in ~/.gitconfig')
+ parser.add_option('--upstream', dest='upstream', default='freebsd',
+ help='Upstream remote name, defaults to freebsd')
+ parser.add_option('-v', '--verbose', dest='verbose',
+ action='store_true', default=False,
+ help='show executed git commands (useful for troubleshooting)')
+
+ return parser.parse_args()
+
+class FetchError(Exception):
+ pass
+
+def fetch(url, dst):
+ '''Try to fetch the specified URL'''
+ cmdstr = 'fetch ' + '-o ' + dst + ' ' + url
+ if VERBOSE:
+ print(cmdstr)
+ cmd = subprocess.Popen(['fetch', '-o', dst, url],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ stdout, stderr = popen_lines(cmd)
+ if cmd.returncode != 0:
+ raise FetchError('ERROR: %s\n%s' % (cmdstr, '\n'.join(stderr)))
+ return stdout
+
+def main():
+ global VERBOSE
+
+ options, args = parse_args()
+ VERBOSE = options.verbose
+
+ # Keep this before any operations that call out to git(1) so that setup
+ # works when the current working directory is outside a git repo.
+ if options.setup:
+ setup()
+ return 0
+
+ try:
+ git_get_toplevel_dir()
+ except GitError:
+ print('Unable to find git directory, are you sure you are in a git repo?')
+ return 1
+
+ if options.pr is None:
+ print('--pr is mandatory')
+ return 1
+
+ branch = 'PR-%s' % options.pr
+ if git_branch_exists(branch):
+ print('Still lamely requires a unique branch, and %s exists' % options.branch)
+ return 1
+
+ git_checkout('-b', branch, 'main')
+ tmp = '/tmp/%s.patch' % options.pr
+ fetch('https://patch-diff.githubusercontent.com/raw/freebsd/freebsd-src/pull/%s.patch' % options.pr,
+ tmp)
+ _git_check('am', '--ignore-date', tmp)
+
+ # Now, rebase this to main to add the trailers we need, but with an editor
+ # that s/-/ / in those trailers because git doesn't like trailers with
+ # spaces in the key value.
+ _git_check('rebase', '-i', 'main',
+ '--exec',
+ 'env EDITOR=$HOME/bin/git-fixup-editor git commit --amend --trailer "Reviewed-by: imp" --trailer "Pull-Request: https://github.com/freebsd/freebsd-src/pull/%s"' % options.pr,
+ )
+ print('I claim PR %s is now a series of commits ready for closer review' % options.pr)
+
+if __name__ == '__main__':
+ sys.exit(main())

File Metadata

Mime Type
text/plain
Expires
Tue, Apr 28, 8:22 AM (5 h, 58 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
32261374
Default Alt Text
D40023.diff (7 KB)

Event Timeline