From patchwork Mon Jul 6 03:41:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 240786 List-Id: U-Boot discussion From: sjg at chromium.org (Simon Glass) Date: Sun, 5 Jul 2020 21:41:51 -0600 Subject: [RFC PATCH 04/16] patman: Allow creating patches for another branch In-Reply-To: <20200706034203.2171077-1-sjg@chromium.org> References: <20200706034203.2171077-1-sjg@chromium.org> Message-ID: <20200706034203.2171077-5-sjg@chromium.org> Add a -b option to allow patches to be created from a branch other than the current one. Signed-off-by: Simon Glass --- tools/patman/control.py | 13 ++++++++----- tools/patman/func_test.py | 13 +++++++++++-- tools/patman/gitutil.py | 19 ++++++++++++++----- tools/patman/main.py | 2 ++ tools/patman/patchstream.py | 8 +++++--- 5 files changed, 40 insertions(+), 15 deletions(-) diff --git a/tools/patman/control.py b/tools/patman/control.py index a896c924b5..b48eac41fd 100644 --- a/tools/patman/control.py +++ b/tools/patman/control.py @@ -20,7 +20,7 @@ def setup(): """Do required setup before doing anything""" gitutil.Setup() -def prepare_patches(col, count, start, ignore_binary): +def prepare_patches(col, branch, count, start, ignore_binary): """Figure out what patches to generate, then generate them The patch files are written to the current directory, e.g. 0001_xxx.patch @@ -28,6 +28,7 @@ def prepare_patches(col, count, start, ignore_binary): Args: col (terminal.Color): Colour output object + branch (str): Branch to create patches from (None = current) count (int): Number of patches to produce, or -1 to produce patches for the current branch back to the upstream commit start (int): Start partch to use (0=first / top of branch) @@ -42,7 +43,7 @@ def prepare_patches(col, count, start, ignore_binary): """ if count == -1: # Work out how many patches to send if we can - count = (gitutil.CountCommitsToBranch() - start) + count = (gitutil.CountCommitsToBranch(branch) - start) if not count: sys.exit(col.Color(col.RED, @@ -50,9 +51,9 @@ def prepare_patches(col, count, start, ignore_binary): # Read the metadata from the commits to_do = count - series = patchstream.GetMetaData(start, to_do) + series = patchstream.GetMetaData(branch, start, to_do) cover_fname, patch_files = gitutil.CreatePatches( - start, to_do, ignore_binary, series) + branch, start, to_do, ignore_binary, series) # Fix up the patch files to our liking, and insert the cover letter patchstream.FixPatches(series, patch_files) @@ -158,9 +159,11 @@ def send(options): setup() col = terminal.Color() series, cover_fname, patch_files = prepare_patches( - col, options.count, options.start, options.ignore_binary) + col, options.branch, options.count, options.start, + options.ignore_binary) ok = check_patches(series, patch_files, options.check_patch, options.verbose) + its_a_go = ok or options.ignore_errors if its_a_go: email_patches( diff --git a/tools/patman/func_test.py b/tools/patman/func_test.py index 211952154a..588be73ef4 100644 --- a/tools/patman/func_test.py +++ b/tools/patman/func_test.py @@ -426,12 +426,21 @@ complicated as possible''') os.chdir(self.gitdir) # Check that it can detect the current branch - self.assertEqual(2, gitutil.CountCommitsToBranch()) + self.assertEqual(2, gitutil.CountCommitsToBranch(None)) col = terminal.Color() with capture_sys_output() as _: _, cover_fname, patch_files = control.prepare_patches( - col, count=-1, start=0, ignore_binary=False) + col, branch=None, count=-1, start=0, ignore_binary=False) self.assertIsNone(cover_fname) self.assertEqual(2, len(patch_files)) + + # Check that it can detect a different branch + self.assertEqual(3, gitutil.CountCommitsToBranch('second')) + with capture_sys_output() as _: + _, cover_fname, patch_files = control.prepare_patches( + col, branch='second', count=-1, start=0, + ignore_binary=False) + self.assertIsNotNone(cover_fname) + self.assertEqual(3, len(patch_files)) finally: os.chdir(orig_dir) diff --git a/tools/patman/gitutil.py b/tools/patman/gitutil.py index 29444bf8e9..b683481a57 100644 --- a/tools/patman/gitutil.py +++ b/tools/patman/gitutil.py @@ -49,17 +49,24 @@ def LogCmd(commit_range, git_dir=None, oneline=False, reverse=False, cmd.append('--') return cmd -def CountCommitsToBranch(): +def CountCommitsToBranch(branch): """Returns number of commits between HEAD and the tracking branch. This looks back to the tracking branch and works out the number of commits since then. + Args: + branch: Branch to count from (None for current branch) + Return: Number of patches that exist on top of the branch """ - pipe = [LogCmd('@{upstream}..', oneline=True), - ['wc', '-l']] + if branch: + us, msg = GetUpstream('.git', branch) + rev_range = '%s..%s' % (us, branch) + else: + rev_range = '@{upstream}..' + pipe = [LogCmd(rev_range, oneline=True), ['wc', '-l']] stdout = command.RunPipe(pipe, capture=True, oneline=True).stdout patch_count = int(stdout) return patch_count @@ -252,13 +259,14 @@ def Fetch(git_dir=None, work_tree=None): if result.return_code != 0: raise OSError('git fetch: %s' % result.stderr) -def CreatePatches(start, count, ignore_binary, series): +def CreatePatches(branch, start, count, ignore_binary, series): """Create a series of patches from the top of the current branch. The patch files are written to the current directory using git format-patch. Args: + branch: Branch to create patches from (None for current branch) start: Commit to start from: 0=HEAD, 1=next one, etc. count: number of commits to include ignore_binary: Don't generate patches for binary files @@ -277,7 +285,8 @@ def CreatePatches(start, count, ignore_binary, series): prefix = series.GetPatchPrefix() if prefix: cmd += ['--subject-prefix=%s' % prefix] - cmd += ['HEAD~%d..HEAD~%d' % (start + count, start)] + brname = branch or 'HEAD' + cmd += ['%s~%d..%s~%d' % (brname, start + count, brname, start)] stdout = command.RunList(cmd) files = stdout.splitlines() diff --git a/tools/patman/main.py b/tools/patman/main.py index 2432d31871..066754196e 100755 --- a/tools/patman/main.py +++ b/tools/patman/main.py @@ -31,6 +31,8 @@ from patman import test_checkpatch parser = OptionParser() parser.add_option('-H', '--full-help', action='store_true', dest='full_help', default=False, help='Display the README file') +parser.add_option('-b', '--branch', type='str', + help="Branch to process (by default, the current branch)") parser.add_option('-c', '--count', dest='count', type='int', default=-1, help='Automatically create patches from top n commits') parser.add_option('-i', '--ignore-errors', action='store_true', diff --git a/tools/patman/patchstream.py b/tools/patman/patchstream.py index 4fe465e9ab..2ea8ebcc3f 100644 --- a/tools/patman/patchstream.py +++ b/tools/patman/patchstream.py @@ -512,17 +512,19 @@ def GetMetaDataForList(commit_range, git_dir=None, count=None, ps.Finalize() return series -def GetMetaData(start, count): +def GetMetaData(branch, start, count): """Reads out patch series metadata from the commits This does a 'git log' on the relevant commits and pulls out the tags we are interested in. Args: - start: Commit to start from: 0=HEAD, 1=next one, etc. + branch: Branch to use (None for current branch) + start: Commit to start from: 0=branch HEAD, 1=next one, etc. count: Number of commits to list """ - return GetMetaDataForList('HEAD~%d' % start, None, count) + return GetMetaDataForList('%s~%d' % (branch if branch else 'HEAD', start), + None, count) def GetMetaDataForTest(text): """Process metadata from a file containing a git log. Used for tests