From 55f728eb9abb6225ae9ba77dfcdea27c9759f532 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 | 3 +++ pre_commit/git.py | 15 +++++++++++++++ tests/commands/autoupdate_test.py | 18 ++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/pre_commit/commands/autoupdate.py b/pre_commit/commands/autoupdate.py index 938c22461..d5352e5e7 100644 --- a/pre_commit/commands/autoupdate.py +++ b/pre_commit/commands/autoupdate.py @@ -59,6 +59,9 @@ def update(self, tags_only: bool, freeze: bool) -> RevInfo: except CalledProcessError: cmd = (*git_cmd, 'rev-parse', 'FETCH_HEAD') rev = cmd_output(*cmd, cwd=tmp)[1].strip() + else: + if tags_only: + rev = git.get_best_candidate_tag(rev, tmp) frozen = None if freeze: diff --git a/pre_commit/git.py b/pre_commit/git.py index 853f4b0d0..6fff8d2a9 100644 --- a/pre_commit/git.py +++ b/pre_commit/git.py @@ -229,3 +229,18 @@ def check_for_cygwin_mismatch() -> None: f' - python {exe_type[is_cygwin_python]}\n' f' - git {exe_type[is_cygwin_git]}\n', ) + + +def get_best_candidate_tag(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', *NO_FS_MONITOR, 'tag', '--points-at', rev, cwd=git_repo, + )[1].splitlines() + for tag in tags: + if '.' in tag: + return tag + return rev 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)