head-checking: filter out obsolete heads when checking for new heads
This does not affect any tests right now, but this will be useful for the next
changeset. This is also the start of a more aggressive removal of obsolete
heads in places where it does not make sense to take them into account.
--- a/hgext3rd/topic/discovery.py Mon Apr 06 05:05:07 2020 +0200
+++ b/hgext3rd/topic/discovery.py Mon Apr 06 04:01:58 2020 +0200
@@ -139,6 +139,46 @@
repo.__class__ = oldrepo
+def _get_branch_name(ctx):
+ # make it easy for extension with the branch logic there
+ return ctx.branch()
+
+
+def _filter_obsolete_heads(repo, heads):
+ """filter heads to return non-obsolete ones
+
+ Given a list of heads (on the same named branch) return a new list of heads
+ where the obsolete part have been skimmed out.
+ """
+ new_heads = []
+ old_heads = heads[:]
+ while old_heads:
+ rh = old_heads.pop()
+ ctx = repo[rh]
+ current_name = _get_branch_name(ctx)
+ # run this check early to skip the evaluation of the whole branch
+ if not ctx.obsolete():
+ new_heads.append(rh)
+ continue
+
+ # Get all revs/nodes on the branch exclusive to this head
+ # (already filtered heads are "ignored"))
+ sections_revs = repo.revs(
+ b'only(%d, (%ld+%ld))', rh, old_heads, new_heads,
+ )
+ keep_revs = []
+ for r in sections_revs:
+ ctx = repo[r]
+ if ctx.obsolete():
+ continue
+ if _get_branch_name(ctx) != current_name:
+ continue
+ keep_revs.append(r)
+ for h in repo.revs(b'heads(%ld and (::%ld))', sections_revs, keep_revs):
+ new_heads.append(h)
+ new_heads.sort()
+ return new_heads
+
# Discovery have deficiency around phases, branch can get new heads with pure
# phases change. This happened with a changeset was allowed to be pushed
# because it had a topic, but it later become public and create a new branch
@@ -150,7 +190,9 @@
for b in repo.branchmap().iterbranches():
if b':' in b[0]:
continue
- data[b[0]] = len(b[1])
+ oldheads = [repo[n].rev() for n in b[1]]
+ newheads = _filter_obsolete_heads(repo, oldheads)
+ data[b[0]] = len(newheads)
return data
def handlecheckheads(orig, op, inpart):