diff --git a/hgitaly/revision.py b/hgitaly/revision.py index d89850f0b6132b2bdf377b636e7a5da8cb2934bd_aGdpdGFseS9yZXZpc2lvbi5weQ==..bbca598ebf82d6f6ed17497f4c6b1de1cd8356b3_aGdpdGFseS9yZXZpc2lvbi5weQ== 100644 --- a/hgitaly/revision.py +++ b/hgitaly/revision.py @@ -65,6 +65,14 @@ :return: the changeset as a :class:`changectx` instance, or ``None`` if not found. """ + if CHANGESET_HASH_BYTES_REGEXP.match(revision): + try: + ctx = repo.unfiltered()[revision] + except error.RepoLookupError: + return None # voluntarily explicit + + return ctx if isinstance(ctx, changectx) else None + if revision == b'HEAD': revision = get_default_gitlab_branch(repo) if revision is None: @@ -93,9 +101,14 @@ if ctx is not None: return ctx + # direct GitLab tag name + ctx = tagged_changeset(repo, revision) + if ctx is not None: + return ctx + # direct GitLab branch name ctx = gitlab_branch_head(repo, revision) if ctx is not None: return ctx try: @@ -96,12 +109,9 @@ # direct GitLab branch name ctx = gitlab_branch_head(repo, revision) if ctx is not None: return ctx try: - # TODO we should probably give precedence to tags, as Mercurial - # does, although we should check what Git(aly) really does in - # case of naming conflicts ctx = scmutil.revsingle(repo.unfiltered(), revision) # ctx can be, e.g., workingctx (see heptapod#717) # The null node is not to be filtered (it may be used in diffs) diff --git a/tests_with_gitaly/test_commit.py b/tests_with_gitaly/test_commit.py index d89850f0b6132b2bdf377b636e7a5da8cb2934bd_dGVzdHNfd2l0aF9naXRhbHkvdGVzdF9jb21taXQucHk=..bbca598ebf82d6f6ed17497f4c6b1de1cd8356b3_dGVzdHNfd2l0aF9naXRhbHkvdGVzdF9jb21taXQucHk= 100644 --- a/tests_with_gitaly/test_commit.py +++ b/tests_with_gitaly/test_commit.py @@ -242,7 +242,38 @@ rpc_helper.normalize_responses(hg_resp, git_resp) assert hg_resp == git_resp - # TODO cases of collision/shadowing + # collision between branch and tag (test validity corroborated by checking + # agreement also on the tag ref full path) + wrapper.command('tag', b'tagbook', rev=ctx1.hex()) + wrapper.command('bookmark', b'tagbook', rev=ctx0.hex()) + wrapper.command('tag', b'branch/default', rev=ctx0.hex()) + wrapper.command('gitlab-mirror') + fixture.invalidate() # for the hg->git map + assert_compare(revision=b"refs/tags/tagbook") + assert_compare(revision=b"tagbook") + assert_compare(revision=b"refs/tags/branch/default") + assert_compare(revision=b"branch/default") + + # collision between tag and node id (full form and shortened) + # Notice how we do *not* run gitlab-mirror, as we need different tags on + # both sides. Also no sense using assert_compare() in that case either + # What matters here is that Gitaly and HGitaly behave identically, + # but for the sake of completeness, as of this writing, in Gitaly, + # tags have precedence over shortened commit ids, but not on full + # commit ids (same with a command-line Git, for what it's worth). + git_repo = fixture.git_repo + hg2git = rpc_helper.hg2git + hg_sha0, hg_sha1 = ctx0.hex(), ctx1.hex() + git_sha0, git_sha1 = hg2git(hg_sha0), hg2git(hg_sha1) + + for hg_sha_tag, git_sha_tag in ((hg_sha0, git_sha0), + (hg_sha0[:10], git_sha0[:10])): + wrapper.command('tag', hg_sha_tag, rev=hg_sha1) + git_repo.write_ref(b'refs/tags/' + git_sha_tag, git_sha1) + + assert rpc_helper.hg2git( + rpc_helper.rpc('hg', revision=hg_sha_tag).commit.id.encode() + ) == rpc_helper.rpc('git', revision=git_sha_tag).commit.id.encode() def test_compare_find_commits(gitaly_comparison):