@@ -11,11 +11,13 @@ This tool is a Python script which:
- Runs the patches through checkpatch.pl and its own checks
- Optionally emails them out to selected people
-It also shows review tags from Patchwork so you can update your local patches.
+It also has some Patchwork features:
+- shows review tags from Patchwork so you can update your local patches
+- pulls these down into a new branch on request
It is intended to automate patch creation and make it a less
error-prone process. It is useful for U-Boot and Linux work so far,
-since it uses the checkpatch.pl script.
+since they use the checkpatch.pl script.
It is configured almost entirely by tags it finds in your commits.
This means that you can work on a number of different branches at
@@ -378,6 +380,17 @@ attracted another review each. If the series needs changes, you can update
these commits with the new review tag before sending the next version of the
series.
+To automatically pull into these tags into a new branch, use the -d option:
+
+ patman status -d mtrr4
+
+This will create a new 'mtrr4' branch which is the same as your current branch
+but has the new review tags in it. You can check that this worked with:
+
+ patman -b mtrr4 status
+
+which should show that there are no new responses compared to this new branch.
+
Example Work Flow
=================
@@ -174,11 +174,11 @@ def send(args):
args.limit, args.dry_run, args.in_reply_to, args.thread,
args.smtp_server)
-def patchwork_status(branch, count, start, end):
+def patchwork_status(branch, count, start, end, dest_branch, force):
"""Check the status of patches in patchwork
This finds the series in patchwork using the Series-link tag, checks for new
- comments / review tags and displays them
+ review tags, displays then and creates a new branch with the review tags.
Args:
branch (str): Branch to create patches from (None = current)
@@ -187,6 +187,9 @@ def patchwork_status(branch, count, start, end):
start (int): Start partch to use (0=first / top of branch)
end (int): End patch to use (0=last one in series, 1=one before that,
etc.)
+ dest_branch (str): Name of new branch to create with the updated tags
+ (None to not create a branch)
+ force (bool): With dest_branch, force overwriting an existing branch
Raises:
ValueError: if the branch has no Series-link value
@@ -203,4 +206,4 @@ def patchwork_status(branch, count, start, end):
# Import this here to avoid failing on other commands if the dependencies
# are not present
from patman import status
- status.check_patchwork_status(series, link, branch)
+ status.check_patchwork_status(series, link, branch, dest_branch, force)
@@ -90,6 +90,10 @@ AddCommonArgs(test_parser)
status = subparsers.add_parser('status',
help='Check status of patches in patchwork')
+status.add_argument('-d', '--dest-branch', type=str,
+ help='Name of branch to create with collected responses')
+status.add_argument('-f', '--force', action='store_true',
+ help='Force overwriting an existing branch')
AddCommonArgs(status)
# Parse options twice: first to get the project and second to handle
@@ -156,7 +160,8 @@ elif args.cmd == 'send':
elif args.cmd == 'status':
ret_code = 0
try:
- control.patchwork_status(args.branch, args.count, args.start, args.end)
+ control.patchwork_status(args.branch, args.count, args.start, args.end,
+ args.dest_branch, args.force)
except Exception as e:
print('patman: %s: %s' % (type(e).__name__, e))
if args.debug:
@@ -304,7 +304,48 @@ def ShowResponses(rtags, indent, is_new):
count += 1
return count
-def check_patchwork_status(series, url, branch):
+def CreateBranch(series, new_rtag_list, branch, dest_branch, overwrite):
+ if branch == dest_branch:
+ raise ValueError(
+ 'Destination branch must not be the same as the original branch')
+ repo = pygit2.Repository('.')
+ count = len(series.commits)
+ old_br = repo.branches[branch]
+ new_br = repo.branches.get(dest_branch)
+ if new_br:
+ if not overwrite:
+ raise ValueError("Branch '%s' already exists (-f to overwrite)" %
+ dest_branch)
+ new_br.delete()
+ target = repo.revparse_single('%s~%d' % (branch, count))
+ repo.branches.local.create(dest_branch, target)
+
+ num_added = 0
+ for seq in range(count):
+ basket = repo.branches.get(dest_branch)
+ cherry = repo.revparse_single('%s~%d' % (branch, count - seq - 1))
+
+ base = repo.merge_base(cherry.oid, basket.target)
+ base_tree = cherry.parents[0].tree
+
+ index = repo.merge_trees(base_tree, basket, cherry)
+ tree_id = index.write_tree(repo)
+
+ author = cherry.author
+ committer = cherry.committer
+ lines = []
+ for tag, people in new_rtag_list[seq].items():
+ for who in people:
+ lines.append('%s: %s' % (tag, who))
+ num_added += 1
+ message = cherry.message + '\n'.join(lines)
+
+ basket = repo.create_commit(
+ basket.name, cherry.author, cherry.committer, message, tree_id,
+ [basket.target])
+ return num_added
+
+def check_patchwork_status(series, url, branch, dest_branch, force):
patches = CollectPatches(series, url)
col = terminal.Color()
count = len(patches)
@@ -330,5 +371,12 @@ def check_patchwork_status(series, url, branch):
ShowResponses(base_rtags, indent, False)
num_to_add += ShowResponses(new_rtags, indent, True)
- print("%d new response%s available in patchwork" %
- (num_to_add, 's' if num_to_add != 1 else ''))
+ print("%d new response%s available in patchwork%s" %
+ (num_to_add, 's' if num_to_add != 1 else '',
+ '' if dest_branch else ' (use -d to write them to a new branch)'))
+
+ if dest_branch:
+ num_added = CreateBranch(series, new_rtag_list, branch,
+ dest_branch, force)
+ print("%d response%s added from patchwork into new branch '%s'" %
+ (num_added, 's' if num_added != 1 else '', dest_branch))
It is tedious to add review tags into the local branch and errors can sometimes be made. Add an option to create a new branch with the review tags obtained from patchwork. Signed-off-by: Simon Glass <sjg at chromium.org> --- tools/patman/README | 17 +++++++++++-- tools/patman/control.py | 9 ++++--- tools/patman/main.py | 7 +++++- tools/patman/status.py | 54 ++++++++++++++++++++++++++++++++++++++--- 4 files changed, 78 insertions(+), 9 deletions(-)