Skip to content
Snippets Groups Projects
Commit f7b4c7f7cb3b authored by Georges Racinet's avatar Georges Racinet
Browse files

GitLab tags removal: compare only on the GitLab side

Previously, the detection of tags removal was based
on back-converting to Mercurial the existing GitLab tags, which
cannot work in case of escaped names.

Instead, we perform the detection entirely on the GitLab side.
We can still have collisions, but there's not much that can be
done about it (except that publication rights will be necessary
to actually change a GitLab tag due to such a collision).

We also make it clear in the case the user does not have
sufficient permissions that the reported tag name is the
GitLab one, and can be slightly different from the Mercurial one.

Closes heptapod#464 (see there for the bad consequences)
parent 772fd263f7fb
No related branches found
No related tags found
2 merge requests!59Merged fix for heptapod#464 from stable branch,!58GitLab tags removal: compare only on the GitLab side
Pipeline #20208 passed
......@@ -834,10 +834,10 @@
changes = {}
repo = self.repo
end_tags = repo.tags()
all_tag_refnames = set()
for tag, sha in pycompat.iteritems(repo.tags()):
if repo.tagtype(tag) in (b'global', b'git'):
tag = tag.replace(b' ', b'_')
target = self.gitlab_sha_from_hg_sha(hex(sha))
if target is not None:
tag_refname = gitlab_tag_ref(tag)
......@@ -838,9 +838,10 @@
for tag, sha in pycompat.iteritems(repo.tags()):
if repo.tagtype(tag) in (b'global', b'git'):
tag = tag.replace(b' ', b'_')
target = self.gitlab_sha_from_hg_sha(hex(sha))
if target is not None:
tag_refname = gitlab_tag_ref(tag)
all_tag_refnames.add(tag_refname)
if check_ref_format(tag_refname):
before_sha = existing.get(tag_refname, ZERO_SHA)
if before_sha != target:
......@@ -857,5 +858,8 @@
b"Skipping export of tag '%s' because it "
b"has no matching git revision.\n" % tag)
# for removal, it is important that the comparison happens
# completely on one side of the mapping (here GitLab)
# see heptapod#464
for ref, target in existing.items():
ref_tag = gitlab_tag_from_ref(ref)
......@@ -860,6 +864,6 @@
for ref, target in existing.items():
ref_tag = gitlab_tag_from_ref(ref)
if ref_tag is not None and ref_tag not in end_tags:
if ref_tag is not None and ref not in all_tag_refnames:
changes[ref] = GitLabRefChange(ref=ref,
before=target,
after=ZERO_SHA)
......@@ -872,9 +876,12 @@
raise error.Abort(
b"You don't have sufficient permissions "
b"to create, modify or delete tags",
hint=b'Found %d tags affected by those changes, '
b'including : %s' % (len(changes),
util.format_bytes_list(abridged)))
hint=b'Found %d GitLab tags affected by those changes, '
b'including: %s. '
b'Note that GitLab tag names can be slightly '
b'different from the Mercurial tags due to escaping rules' % (
len(changes),
util.format_bytes_list(abridged)))
return changes
......
......@@ -317,6 +317,71 @@
assert not git_repo.tags()
def test_tags_escaping_removal(main_fixture):
wrapper = main_fixture.hg_repo_wrapper
git_repo = main_fixture.git_repo
notifs = main_fixture.gitlab_notifs
# a tag with a space character
hg_tag = b'Version 1.2.3'
git_tag = 'Version_1.2.3'
wrapper.command('tag', hg_tag)
wrapper.command('gitlab-mirror')
assert git_repo.tags() == {as_bytes(git_tag)}
tagged_git_sha, tagged_git_title = git_repo.commit_hash_title(git_tag)
assert tagged_git_title == b'default1'
branches = git_repo.branches()
assert list(branches) == [b'branch/default']
branch = branches[b'branch/default']
branch_git_sha1 = branch['sha']
changes = {}, {
b'refs/heads/branch/default': (ZERO_SHA, branch_git_sha1),
as_bytes('refs/tags/' + git_tag): (ZERO_SHA, tagged_git_sha),
}
assert notifs == [('pre-receive', changes), ('post-receive', changes)]
main_fixture.clear_gitlab_notifs()
# Pushing something else does not count as a tag modification.
# This asserts that heptapod#464 is fixed.
wrapper.commit_file('something-else')
wrapper.command('gitlab-mirror')
branch_git_sha2 = git_repo.branches()[b'branch/default']['sha']
changes = {}, {
b'refs/heads/branch/default': (branch_git_sha1, branch_git_sha2),
}
assert notifs == [('pre-receive', changes), ('post-receive', changes)]
main_fixture.clear_gitlab_notifs()
# Change is still possible
wrapper.command('tag', hg_tag, force=True)
wrapper.command('gitlab-mirror')
assert git_repo.tags() == {as_bytes(git_tag)}
branch_git_sha3 = git_repo.branches()[b'branch/default']['sha']
changes = {}, {
b'refs/heads/branch/default': (branch_git_sha2, branch_git_sha3),
as_bytes('refs/tags/' + git_tag): (tagged_git_sha, branch_git_sha2),
}
assert notifs == [('pre-receive', changes), ('post-receive', changes)]
main_fixture.clear_gitlab_notifs()
# Removal is still possible
wrapper.command('tag', hg_tag, remove=True)
wrapper.command('gitlab-mirror')
assert not git_repo.tags()
branch_git_sha4 = git_repo.branches()[b'branch/default']['sha']
changes = {}, {
b'refs/heads/branch/default': (branch_git_sha3, branch_git_sha4),
as_bytes('refs/tags/' + git_tag): (branch_git_sha2, ZERO_SHA),
}
assert notifs == [('pre-receive', changes), ('post-receive', changes)]
main_fixture.clear_gitlab_notifs()
def test_tags_obsolete(empty_fixture):
fixture = empty_fixture
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment