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

Post release merge of heptapod-0-12 into default

No related branches found
No related tags found
No related merge requests found
Pipeline #5848 passed
......@@ -21,7 +21,7 @@
tests-main:
stage: main
image: octobus/ci-py-heptapod
image: octobus/ci-py-heptapod:hpd-0.12
before_script: []
script:
- flake8 heptapod setup.py hgext3rd
......
......@@ -18,3 +18,4 @@
6dbc6fcd63b9b2119c68cf55bec4db4416f3c331 heptapod-0.12.0
8eb2109d97fbba92b618f10a66f4c4d07e558184 heptapod-0.12.1
94dbb4a5d46c00d108078146351fb6a9fd69c150 heptapod-0.12.2
b7094b457956f12130ad72cc580026c0635dec9a heptapod-0.12.3
......@@ -5,6 +5,7 @@
#
# SPDX-License-Identifier: GPL-2.0-or-later
import logging
from mercurial import hg
import os
import re
import requests
......@@ -146,7 +147,10 @@
def __init__(self, name, repo):
self.name = name
self.repo = repo
self.git_fs_path = self.repo.root[:-3] + '.git'
main_repo = hg.sharedreposource(self.repo)
if main_repo is None:
main_repo = self.repo
self.git_fs_path = main_repo.root[:-3] + '.git'
url = str(repo.ui.config(b'heptapod', b'gitlab-internal-api-url',
'http://localhost:8080'))
self.gitlab_internal_api_endpoint = url + '/api/v4/internal'
......
......@@ -10,6 +10,5 @@
all interesting things to do with Git.
"""
from dulwich.protocol import ZERO_SHA
from hgext3rd.topic.constants import extrakey
from hggit.git_handler import GitHandler
from heptapod import gitlab
......@@ -14,5 +13,6 @@
from hggit.git_handler import GitHandler
from heptapod import gitlab
from hgext3rd.evolve import headchecking
from mercurial.i18n import _
from mercurial.node import hex
from mercurial import (
......@@ -196,6 +196,9 @@
for _, bm in self._filter_for_bookmarks(all_bookmarks)}
for branch, hg_nodes in repo.branchmap().iteritems():
gb = self.git_branch_for_branchmap_branch(branch)
revs = [repo[n].rev() for n in hg_nodes]
ctxs = [repo[r]
for r in headchecking._filter_obsolete_heads(repo, revs)]
if ui.configbool('experimental',
'hg-git.prune-newly-closed-branches', True):
......@@ -199,6 +202,6 @@
if ui.configbool('experimental',
'hg-git.prune-newly-closed-branches', True):
hg_nodes = [n for n in hg_nodes if not repo[n].closesbranch()]
if not hg_nodes:
ctxs = [c for c in ctxs if not c.closesbranch()]
if not ctxs:
to_prune[git_branch_ref(gb)] = 'closed'
......@@ -204,3 +207,2 @@
to_prune[git_branch_ref(gb)] = 'closed'
hg_shas = {hex(n) for n in hg_nodes}
......@@ -206,4 +208,5 @@
hg_shas = {c.hex() for c in ctxs}
# We ignore bookmarked changesets because:
# - we don't want them in the 'wild' namespace
# - no other Git ref would be relevant for them
......@@ -244,6 +247,8 @@
return git_refs
def published_topic_latest_hg_sha(self, topic, ctx, log_before_ctx=None):
"""Rewrapping of `latest_topic_descendant` returning hg sha.
"""
ui = self.repo.ui
try:
after_ctx = self.latest_topic_descendant(topic, ctx)
......@@ -256,6 +261,14 @@
# since successor is public, chances to detect merge are good
return ctx.hex()
if after_ctx is None:
ui.warn("HeptapodGitHandler.published_topic_latest_hg_sha "
"inspecting public changeset %r for topic %r gave "
"inconsistent result: it's not in the expected topic. "
"This will trigger immediate pruning of the "
"topic Git branch" % (ctx, topic))
return None
ui.note('HeptapodGitHandler.published_topic_latest_hg_sha',
"updating published %r from %r to %r" % (
topic,
......@@ -293,8 +306,18 @@
return None
if before_ctx.phase() == phases.public:
return self.published_topic_latest_hg_sha(topic, before_ctx)
latest_sha = self.published_topic_latest_hg_sha(topic, before_ctx)
if latest_sha is not None:
return latest_sha
else:
# this is a corruption: resolving the Git branch for the topic
# actually gives us a changeset that does not bear that topic!
# This is what happened in heptapod#265.
# In that case, we return it unchanged. The changeset
# surely is an ancestor of the current named branch head
# GitLab's MR detection should thus work and eventually
# prune the corrupted Git branch for the topic.
return before_sha
try:
succctx = obsutil.latest_unique_successor(before_ctx)
except error.Abort as exc:
......@@ -314,8 +337,6 @@
succ_phase = succctx.phase()
if succ_phase == phases.public:
# not using succctx.topic() here because it is empty for
# public changesets
if succctx.extra().get(extrakey) == topic and not initial_import:
return self.published_topic_latest_hg_sha(
if not initial_import:
latest_sha = self.published_topic_latest_hg_sha(
topic, succctx, log_before_ctx=before_ctx)
......@@ -321,4 +342,6 @@
topic, succctx, log_before_ctx=before_ctx)
if latest_sha is not None:
return latest_sha
elif succ_phase == phases.draft:
# let's go over some reasons why there's no visible branch/topic
......@@ -581,6 +604,6 @@
its branch vanished.
This checks that there is one public head of the topic.
Otherwise the push should be refused as inconsistend.
Otherwise the push should be refused as inconsistent.
The changeset of ctx is assumed *not* to be filtered (aka, obsolete)
......@@ -585,7 +608,7 @@
The changeset of ctx is assumed *not* to be filtered (aka, obsolete)
(all current callers already have obsolescence information around) and
to belong to the topic. Raises Python standard LookupError otherwise.
(all current callers already have obsolescence information around).
If it does not belong to the topic, `None` gets returned.
"""
revs = self.repo.revs("heads(extra(topic, %s) and descendants(%d))",
topic, ctx.rev())
......@@ -593,7 +616,5 @@
raise MultipleDescendants(topic, ctx)
rev = revs.first()
if rev is None:
raise LookupError(
"Can't find public descendants of %r in topic %r" % (
ctx.hex(), topic))
return None
return self.repo[rev]
......@@ -221,11 +221,7 @@
config=common_config())
handler = HeptapodGitHandler(wrapper.repo, wrapper.repo.ui)
ctx = wrapper.write_commit('foo', message='foo0', return_ctx=True)
# this can happen only if ctx isn't itself in the wished topic
# which our current callers always ensure.
with pytest.raises(LookupError):
handler.latest_topic_descendant('sometop', ctx)
assert handler.latest_topic_descendant('sometop', ctx) is None
def test_generate_prune_changes_existing_unknown(tmpdir):
......
......@@ -84,6 +84,12 @@
def set_symref(self, name, target_ref):
self.path.join(name).write('ref: %s\n' % target_ref)
def set_branch(self, name, sha):
self.path.join('refs', 'heads', name).ensure().write(sha + '\n')
def get_branch_sha(self, name):
return self.path.join('refs', 'heads', name).read().strip()
def make_main_repo(path):
"""Make repo with 2 public revs; return wrapper, ctx of rev 0
......@@ -579,6 +585,53 @@
('post-receive', changes)]
def test_topic_clear_publish(tmpdir, monkeypatch):
"""The topic head seen from Git is public and has changed topic.
This is the test for heptapod#265
The starting point can be considered to be corrupted: any topic change
should have updated the Git branch for the topic. In this scenario
the change is a removal, wich should have pruned the Git branch, but
somehow the Git branch got updated to the new changeset, that doesn't
have a topic.
"""
notifs = []
monkeypatch.setattr(gitlab, 'Hook', recording_hook(notifs))
wrapper, base_ctx = make_main_repo(tmpdir.join('repo.hg'))
git_repo = GitRepo.init(tmpdir.join('repo.git'))
wrapper.write_commit('zz', message='in topic', topic='zzetop')
wrapper.command('gitlab-mirror')
branches_before = git_repo.branches()
assert extract_git_branch_titles(branches_before) == {
'branch/default': 'default1',
'topic/default/zzetop': 'in topic'}
wrapper.command('topics', rev=['.'], clear=True)
wrapper.command('gitlab-mirror')
wrapper.set_phase('public', ['.'])
git_repo.set_branch('topic/default/zzetop',
git_repo.get_branch_sha('branch/default'))
del notifs[:]
# This used to raise LookupError
wrapper.command('gitlab-mirror')
branches_after = git_repo.branches()
assert extract_git_branch_titles(branches_after) == {
'branch/default': 'in topic',
'topic/default/zzetop': 'in topic',
}
changes = {
'refs/heads/topic/default/zzetop': (
branches_after['branch/default']['sha'],
branches_after['branch/default']['sha'],
),
}
assert notifs == [('pre-receive', changes),
('post-receive', changes)]
def test_topic_branch_change(tmpdir, monkeypatch):
notifs = []
monkeypatch.setattr(gitlab, 'Hook', recording_hook(notifs))
......
Mercurial>=5.2,<5.4
hg-evolve>=9.2.1
hg-evolve>=9.3.1
hg-git>=0.8.13
requests
requests_unixsocket==0.2.0
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