From 6745d15662146ee1a086429b0cdf2d9dfb0fedd5 Mon Sep 17 00:00:00 2001 From: Matt Layman Date: Wed, 30 Mar 2022 01:08:52 -0400 Subject: [PATCH] Pick a tag if multiple tags exist on a SHA. Fixes #2311 --- pre_commit/commands/autoupdate.py | 15 +++++++++++++++ tests/commands/autoupdate_test.py | 18 ++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/pre_commit/commands/autoupdate.py b/pre_commit/commands/autoupdate.py index 938c22461..1fc464a2b 100644 --- a/pre_commit/commands/autoupdate.py +++ b/pre_commit/commands/autoupdate.py @@ -33,6 +33,20 @@ class RevInfo(NamedTuple): def from_config(cls, config: dict[str, Any]) -> RevInfo: return cls(config['repo'], config['rev'], None) + def get_best_candidate_tag(self, rev: str, git_repo: str) -> str: + """Get the best tag candidate. + + Multiple tags can exist on a SHA. Sometimes a moving tag is attached + to a version tag. Try to pick the tag that looks like a version. + """ + tags = cmd_output( + 'git', *git.NO_FS_MONITOR, 'tag', '--points-at', rev, cwd=git_repo, + )[1].split() + for tag in tags: + if '.' in tag and re.match(r'^[a-zA-Z0-9.]+$', tag): + return tag + return rev + def update(self, tags_only: bool, freeze: bool) -> RevInfo: git_cmd = ('git', *git.NO_FS_MONITOR) @@ -56,6 +70,7 @@ def update(self, tags_only: bool, freeze: bool) -> RevInfo: try: rev = cmd_output(*tag_cmd, cwd=tmp)[1].strip() + rev = self.get_best_candidate_tag(rev, tmp) except CalledProcessError: cmd = (*git_cmd, 'rev-parse', 'FETCH_HEAD') rev = cmd_output(*cmd, cwd=tmp)[1].strip() diff --git a/tests/commands/autoupdate_test.py b/tests/commands/autoupdate_test.py index 3a142661a..3806b0e48 100644 --- a/tests/commands/autoupdate_test.py +++ b/tests/commands/autoupdate_test.py @@ -103,6 +103,24 @@ def test_rev_info_update_tags_only_does_not_pick_tip(tagged): assert new_info.rev == 'v1.2.3' +def test_rev_info_update_tags_prefers_version_tag(tagged, out_of_date): + cmd_output('git', 'tag', 'latest', cwd=out_of_date.path) + config = make_config_from_repo(tagged.path, rev=tagged.original_rev) + info = RevInfo.from_config(config) + new_info = info.update(tags_only=True, freeze=False) + assert new_info.rev == 'v1.2.3' + + +def test_rev_info_update_tags_non_version_tag(out_of_date): + cmd_output('git', 'tag', 'latest', cwd=out_of_date.path) + config = make_config_from_repo( + out_of_date.path, rev=out_of_date.original_rev, + ) + info = RevInfo.from_config(config) + new_info = info.update(tags_only=True, freeze=False) + assert new_info.rev == 'latest' + + def test_rev_info_update_freeze_tag(tagged): git_commit(cwd=tagged.path) config = make_config_from_repo(tagged.path, rev=tagged.original_rev)