aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKonstantin Ryabitsev <konstantin@linuxfoundation.org>2023-03-02 12:43:27 -0500
committerKonstantin Ryabitsev <konstantin@linuxfoundation.org>2023-03-02 12:43:27 -0500
commit5d0559ba9db20db3c7085f28467f338a8271fb19 (patch)
tree638ad623ff4683084ef562c83fc4eb0dc9883dd8
parent14a6165754778b83cdfb0b546f5bf23cecb84744 (diff)
downloadb4-5d0559ba9db20db3c7085f28467f338a8271fb19.tar.gz
ez: use full change-id when tagging sent revisions
I ran into a situation where I used the same branch name to send two independent patch series. When this happens, we have a collision for sent/tagname-vX, so avoid this by using the full change-id of the series to make the unique tag. This change is backwards-compatible, so it will check for both situations when performing compare-to or other operations. Signed-off-by: Konstantin Ryabitsev <konstantin@linuxfoundation.org>
-rw-r--r--b4/__init__.py16
-rw-r--r--b4/ez.py62
2 files changed, 53 insertions, 25 deletions
diff --git a/b4/__init__.py b/b4/__init__.py
index 88b1747..3123ff7 100644
--- a/b4/__init__.py
+++ b/b4/__init__.py
@@ -2962,13 +2962,25 @@ def git_range_to_patches(gitdir: Optional[str], start: str, end: str,
return patches
-def git_commit_exists(gitdir, commit_id):
+def git_commit_exists(gitdir: Optional[str], commit_id: str) -> bool:
gitargs = ['cat-file', '-e', commit_id]
ecode, out = git_run_command(gitdir, gitargs)
return ecode == 0
-def git_branch_contains(gitdir, commit_id):
+def git_revparse_tag(gitdir: Optional[str], tagname: str) -> Optional[str]:
+ if not tagname.startswith('refs/tags/'):
+ fulltag = f'refs/tags/{tagname}'
+ else:
+ fulltag = tagname
+ gitargs = ['rev-parse', fulltag]
+ ecode, out = git_run_command(gitdir, gitargs)
+ if ecode > 0:
+ return None
+ return out.strip()
+
+
+def git_branch_contains(gitdir: Optional[str], commit_id: str) -> List[str]:
gitargs = ['branch', '--format=%(refname:short)', '--contains', commit_id]
lines = git_get_command_lines(gitdir, gitargs)
return lines
diff --git a/b4/ez.py b/b4/ez.py
index ec8bf77..0c9eb6a 100644
--- a/b4/ez.py
+++ b/b4/ez.py
@@ -1268,13 +1268,18 @@ def cmd_send(cmdargs: argparse.Namespace) -> None:
tag_msg = None
cl_msgid = None
+ cover, tracking = load_cover(strip_comments=True)
if cmdargs.resend:
- tagname, revision = get_sent_tagname(mybranch, SENT_TAG_PREFIX, cmdargs.resend)
-
+ # Start with full change-id based tag name
+ tagname, revision = get_sent_tagname(tracking['series']['change-id'], SENT_TAG_PREFIX, cmdargs.resend)
if revision is None:
logger.critical('Could not figure out revision from %s', cmdargs.resend)
sys.exit(1)
+ if not b4.git_revparse_tag(None, tagname):
+ # Try initial branch-name only based version
+ tagname, revision = get_sent_tagname(mybranch, SENT_TAG_PREFIX, cmdargs.resend)
+
try:
todests, ccdests, patches = get_sent_tag_as_patches(tagname, revision=revision)
except RuntimeError as ex:
@@ -1285,7 +1290,6 @@ def cmd_send(cmdargs: argparse.Namespace) -> None:
else:
# Check if the cover letter has 'EDITME' in it
- cover, tracking = load_cover(strip_comments=True)
if 'EDITME' in cover:
logger.critical('CRITICAL: Looks like the cover letter needs to be edited first.')
logger.info('---')
@@ -1570,7 +1574,7 @@ def cmd_send(cmdargs: argparse.Namespace) -> None:
reroll(mybranch, tag_msg, cl_msgid)
-def get_sent_tagname(branch: str, tagprefix: str, revstr: Union[str, int]) -> Tuple[str, Optional[int]]:
+def get_sent_tagname(tagbase: str, tagprefix: str, revstr: Union[str, int]) -> Tuple[str, Optional[int]]:
revision = None
try:
revision = int(revstr)
@@ -1584,9 +1588,9 @@ def get_sent_tagname(branch: str, tagprefix: str, revstr: Union[str, int]) -> Tu
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
+ if tagbase.startswith('b4/'):
+ return f'{tagprefix}{tagbase[3:]}-v{revision}', revision
+ return f'{tagprefix}{tagbase}-v{revision}', revision
def reroll(mybranch: str, tag_msg: str, msgid: str, tagprefix: str = SENT_TAG_PREFIX):
@@ -1597,11 +1601,11 @@ def reroll(mybranch: str, tag_msg: str, msgid: str, tagprefix: str = SENT_TAG_PR
cover, tracking = load_cover(strip_comments=True)
revision = tracking['series']['revision']
- tagname, revision = get_sent_tagname(mybranch, tagprefix, revision)
+ change_id = tracking['series']['change-id']
+
+ tagname, revision = get_sent_tagname(change_id, 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)
- if ecode > 0:
+ if not b4.git_revparse_tag(None, tagname):
try:
strategy = get_cover_strategy()
if strategy == 'commit':
@@ -1744,12 +1748,21 @@ def show_info(param: str) -> None:
info[f'commit-{short}'] = subject
if 'history' in ts:
for rn, links in reversed(ts['history'].items()):
- tagname, revision = get_sent_tagname(mybranch, SENT_TAG_PREFIX, rn)
- try:
- cover, base_commit, change_id = get_base_changeid_from_tag(tagname)
- info[f'series-{rn}'] = '%s..%s %s' % (base_commit[:12], tagname, links[0])
- except RuntimeError:
- logger.debug('No tag matching %s', tagname)
+ tagname, revision = get_sent_tagname(ts.get('change-id'), SENT_TAG_PREFIX, rn)
+ tag_commit = b4.git_revparse_tag(None, tagname)
+ if not tag_commit:
+ logger.debug('No tag %s, trying with base branch name %s', mybranch)
+ tagname, revision = get_sent_tagname(mybranch, SENT_TAG_PREFIX, rn)
+ tag_commit = b4.git_revparse_tag(None, tagname)
+ if not tag_commit:
+ logger.debug('No tag matching revision %s', revision)
+ else:
+ try:
+ cover, base_commit, change_id = get_base_changeid_from_tag(tagname)
+ info[f'series-{rn}'] = '%s..%s %s' % (base_commit[:12], tag_commit[:12], links[0])
+ except RuntimeError as ex:
+ logger.debug('Could not get base-commit info from %s: %s', tagname, ex)
+
if param == '_all':
for key, val in info.items():
print('%s: %s' % (key, val))
@@ -1768,14 +1781,17 @@ def force_revision(forceto: int) -> None:
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:
+ cover, tracking = load_cover()
+ # Try the new format first
+ tagname, revision = get_sent_tagname(tracking['series']['change-id'], SENT_TAG_PREFIX, compareto)
+ prev_end = b4.git_revparse_tag(None, tagname)
+ if not prev_end:
+ mybranch = b4.git_get_current_branch(None)
+ tagname, revision = get_sent_tagname(mybranch, SENT_TAG_PREFIX, compareto)
+ prev_end = b4.git_revparse_tag(None, tagname)
+ if not prev_end:
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: