diff options
author | Konstantin Ryabitsev <konstantin@linuxfoundation.org> | 2022-09-30 14:16:45 -0400 |
---|---|---|
committer | Konstantin Ryabitsev <konstantin@linuxfoundation.org> | 2022-09-30 14:16:45 -0400 |
commit | 5166be6f9ac9e760c7c0407e643c8af0faf12bf9 (patch) | |
tree | c0cd2c97d6e374fe6fa3978ee0adff700ddd221b | |
parent | 601fdc2a68e023812fc3b47ef3c05da63a6093f8 (diff) | |
download | b4-master.tar.gz |
It is useful to be able to see the difference between the version that
you have previously sent and the current working branch. This is the
initial implementation that can be further improved to allow passing
range-diff options.
Signed-off-by: Konstantin Ryabitsev <konstantin@linuxfoundation.org>
-rw-r--r-- | b4/command.py | 4 | ||||
-rw-r--r-- | b4/ez.py | 102 | ||||
-rw-r--r-- | docs/contributor/prep.rst | 5 | ||||
-rw-r--r-- | man/b4.5 | 5 | ||||
-rw-r--r-- | man/b4.5.rst | 3 |
5 files changed, 86 insertions, 33 deletions
diff --git a/b4/command.py b/b4/command.py index 245bfd0..b16043e 100644 --- a/b4/command.py +++ b/b4/command.py @@ -266,6 +266,8 @@ def cmd(): help='Show current series revision number') spp_g.add_argument('--force-revision', metavar='N', type=int, help='Force revision to be this number instead') + spp_g.add_argument('--compare-to', metavar='vN', + help='Display a range-diff to previously sent revision N') spp_g.add_argument('--manual-reroll', dest='reroll', default=None, metavar='COVER_MSGID', help='Mark current revision as sent and reroll (requires cover letter msgid)') ag_prepn = sp_prep.add_argument_group('Create new branch', 'Create a new branch for working on patch series') @@ -308,7 +310,7 @@ def cmd(): sp_send.add_argument('--cc', nargs='+', help='Addresses to add to the Cc: list') sp_send.add_argument('--not-me-too', action='store_true', default=False, help='Remove yourself from the To: or Cc: list') - sp_send.add_argument('--resend', default=None, + sp_send.add_argument('--resend', metavar='vN', default=None, help='Resend a previously sent version of the series') sp_send.add_argument('--no-sign', action='store_true', default=False, help='Do not add the cryptographic attestation signature header') @@ -26,7 +26,7 @@ import gzip import io import copy -from typing import Optional, Tuple, List +from typing import Optional, Tuple, List, Union from email import utils from string import Template @@ -45,6 +45,8 @@ except ModuleNotFoundError: logger = b4.logger MAGIC_MARKER = '--- b4-submit-tracking ---' +# Make this configurable? +SENT_TAG_PREFIX = 'sent/' DEFAULT_COVER_TEMPLATE = """ ${cover} @@ -907,10 +909,7 @@ def print_pretty_addrs(addrs: list, hdrname: str) -> None: logger.info(' %s', b4.format_addrs([addr])) -def get_sent_tag_as_patches(tagname: str, revision: Optional[str] = None, - prefixes: Optional[List[str]] = None, - hide_cover_to_cc: bool = False - ) -> Tuple[List, List, List[Tuple[str, email.message.Message]]]: +def get_base_changeid_from_tag(tagname: str) -> Tuple[str, str, str]: gitargs = ['cat-file', '-p', tagname] ecode, tagmsg = b4.git_run_command(None, gitargs) if ecode > 0: @@ -926,12 +925,13 @@ def get_sent_tag_as_patches(tagname: str, revision: Optional[str] = None, if not matches: raise RuntimeError('Tag %s does not contain change-id info' % tagname) change_id = matches.groups()[0] - if revision is None: - matches = re.search(r'.*-v(\d+)$', tagname, flags=re.I | re.M) - if not matches: - raise RuntimeError('Could not grok revision number from %s' % tagname) - revision = matches.groups()[0] + return cover, base_commit, change_id + +def get_sent_tag_as_patches(tagname: str, revision: int, prefixes: Optional[List[str]] = None, + hide_cover_to_cc: bool = False + ) -> Tuple[List, List, List[Tuple[str, email.message.Message]]]: + cover, base_commit, change_id = get_base_changeid_from_tag(tagname) # First line is the subject csubject, cbody = cover.split('\n', maxsplit=1) cbody = cbody.strip() + '\n-- \n' + b4.get_email_signature() @@ -949,7 +949,7 @@ def get_sent_tag_as_patches(tagname: str, revision: Optional[str] = None, if revision != 1: prefixes.append(f'v{revision}') seriests = int(time.time()) - msgid_tpt = make_msgid_tpt(change_id, revision) + msgid_tpt = make_msgid_tpt(change_id, str(revision)) usercfg = b4.get_user_config() mailfrom = (usercfg.get('name'), usercfg.get('email')) @@ -1102,8 +1102,6 @@ def cmd_send(cmdargs: argparse.Namespace) -> None: auth_verify(cmdargs) return - # Should we make the sent/ prefix configurable? - tagprefix = 'sent/' mybranch = b4.git_get_current_branch() prefixes = cmdargs.prefixes if cmdargs.prefixes is None: @@ -1114,17 +1112,11 @@ def cmd_send(cmdargs: argparse.Namespace) -> None: cmdargs.hide_cover_to_cc = True if cmdargs.resend: - # We accept both a full tag name and just a vN short form - matches = re.search(r'^v(\d+)$', cmdargs.resend) - if matches: - revision = matches.groups()[0] - if mybranch.startswith('b4/'): - tagname = f'{tagprefix}{mybranch[3:]}-v{revision}' - else: - tagname = f'{tagprefix}{mybranch}-v{revision}' - else: - revision = None - tagname = cmdargs.resend + tagname, revision = get_sent_tagname(mybranch, SENT_TAG_PREFIX, cmdargs.resend) + + if revision is None: + logger.critical('Could not figure out revision from %s', cmdargs.resend) + sys.exit(1) prefixes.append('RESEND') try: @@ -1316,7 +1308,26 @@ def cmd_send(cmdargs: argparse.Namespace) -> None: reroll(mybranch, cover_msg) -def reroll(mybranch: str, cover_msg: email.message.Message, tagprefix: str = 'sent/'): +def get_sent_tagname(branch: str, tagprefix: str, revstr: Union[str, int]) -> Tuple[str, Optional[int]]: + revision = None + try: + revision = int(revstr) + except ValueError: + matches = re.search(r'^v(\d+)$', revstr) + if not matches: + # assume we got a full tag name, so try to find the revision there + matches = re.search(r'v(\d+)$', revstr) + if matches: + revision = int(matches.groups()[0]) + return revstr.replace('refs/tags/', ''), revision + revision = int(matches.groups()[0]) + + if branch.startswith('b4/'): + return f'{tagprefix}{branch[3:]}-v{revision}', revision + return f'{tagprefix}{branch}-v{revision}', revision + + +def reroll(mybranch: str, cover_msg: email.message.Message, tagprefix: str = SENT_TAG_PREFIX): # Prepare annotated tag body from the cover letter lsubject = b4.LoreSubject(cover_msg.get('subject')) cbody = cover_msg.get_payload() @@ -1328,11 +1339,7 @@ def reroll(mybranch: str, cover_msg: email.message.Message, tagprefix: str = 'se cover, tracking = load_cover(strip_comments=True) revision = tracking['series']['revision'] - if mybranch.startswith('b4/'): - tagname = f'{tagprefix}{mybranch[3:]}-v{revision}' - else: - tagname = f'{tagprefix}{mybranch}-v{revision}' - + tagname, revision = get_sent_tagname(mybranch, tagprefix, revision) logger.debug('checking if we already have %s', tagname) gitargs = ['rev-parse', f'refs/tags/{tagname}'] ecode, out = b4.git_run_command(None, gitargs) @@ -1458,6 +1465,38 @@ def force_revision(forceto: int) -> None: store_cover(cover, tracking) +def compare(compareto: str) -> None: + mybranch = b4.git_get_current_branch(None) + tagname, revision = get_sent_tagname(mybranch, SENT_TAG_PREFIX, compareto) + gitargs = ['rev-parse', tagname] + lines = b4.git_get_command_lines(None, gitargs) + if not lines: + logger.critical('CRITICAL: Could not rev-parse %s', tagname) + sys.exit(1) + prev_end = lines[0] + try: + cover, base_commit, change_id = get_base_changeid_from_tag(tagname) + except RuntimeError as ex: + logger.critical('CRITICAL: %s', str(ex)) + sys.exit(1) + prev_start = base_commit + curr_start = get_series_start() + strategy = get_cover_strategy() + if strategy == 'tip-commit': + cover_commit = find_cover_commit() + series_end = f'{cover_commit}~1' + else: + series_end = 'HEAD' + + gitargs = ['rev-parse', series_end] + lines = b4.git_get_command_lines(None, gitargs) + curr_end = lines[0] + grdcmd = ['git', 'range-diff', '%.12s..%.12s' % (prev_start, prev_end), '%.12s..%.12s' % (curr_start, curr_end)] + # We exec range-diff and let it take over + logger.debug('Running %s', ' '.join(grdcmd)) + os.execvp(grdcmd[0], grdcmd) + + def auto_to_cc() -> None: tocmdstr = None cccmdstr = None @@ -1589,6 +1628,9 @@ def cmd_prep(cmdargs: argparse.Namespace) -> None: if cmdargs.format_patch: return format_patch(cmdargs.format_patch) + if cmdargs.compare_to: + return compare(cmdargs.compare_to) + if is_prep_branch(): logger.critical('CRITICAL: This appears to already be a b4-prep managed branch.') sys.exit(1) diff --git a/docs/contributor/prep.rst b/docs/contributor/prep.rst index 61133d7..2a9f753 100644 --- a/docs/contributor/prep.rst +++ b/docs/contributor/prep.rst @@ -239,6 +239,11 @@ or modifying defaults for some of these flags. Forces the revision to a different integer number. This modifies your cover letter and tracking information and makes this change permanent. +``--compare-to vN`` **(v0.11+)** + This executes a ``git range-diff`` command that lets you compare the + previously sent version of the series to what is currently in your + working branch. + ``--manual-reroll MSGID`` Normally, your patch series will be automatically rerolled to the next version after a successful ``b4 send`` (see :doc:`send`). However, if @@ -523,7 +523,7 @@ Show all developer keys from the thread .INDENT 0.0 .TP .B usage: -b4 prep [\-h] [\-c | \-p OUTPUT_DIR | \-\-edit\-cover | \-\-show\-revision | \-\-force\-revision N | \-\-manual\-reroll COVER_MSGID] [\-n NEW_SERIES_NAME] [\-f FORK_POINT] [\-F MSGID] [\-e ENROLL_BASE] +b4 prep [\-h] [\-c | \-p OUTPUT_DIR | \-\-edit\-cover | \-\-show\-revision | \-\-force\-revision N | \-\-compare\-to vN | \-\-manual\-reroll COVER_MSGID] [\-n NEW_SERIES_NAME] [\-f FORK_POINT] [\-F MSGID] [\-e ENROLL_BASE] .TP .B options: .INDENT 7.0 @@ -546,6 +546,9 @@ Show current series revision number .BI \-\-force\-revision \ N Force revision to be this number instead .TP +.BI \-\-compare\-to \ vN +Display a range\-diff to previously sent revision N +.TP .BI \-\-manual\-reroll \ COVER_MSGID Mark current revision as sent and reroll (requires cover letter msgid) .UNINDENT diff --git a/man/b4.5.rst b/man/b4.5.rst index 072c107..073f32a 100644 --- a/man/b4.5.rst +++ b/man/b4.5.rst @@ -342,7 +342,7 @@ optional arguments: b4 prep ~~~~~~~ usage: - b4 prep [-h] [-c | -p OUTPUT_DIR | --edit-cover | --show-revision | --force-revision N | --manual-reroll COVER_MSGID] [-n NEW_SERIES_NAME] [-f FORK_POINT] [-F MSGID] [-e ENROLL_BASE] + b4 prep [-h] [-c | -p OUTPUT_DIR | --edit-cover | --show-revision | --force-revision N | --compare-to vN | --manual-reroll COVER_MSGID] [-n NEW_SERIES_NAME] [-f FORK_POINT] [-F MSGID] [-e ENROLL_BASE] options: -h, --help show this help message and exit @@ -352,6 +352,7 @@ options: --edit-cover Edit the cover letter in your defined $EDITOR (or core.editor) --show-revision Show current series revision number --force-revision N Force revision to be this number instead + --compare-to vN Display a range-diff to previously sent revision N --manual-reroll COVER_MSGID Mark current revision as sent and reroll (requires cover letter msgid) |