diff options
-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) |