--- a/hgext3rd/topic/discovery.py Sat Mar 21 15:04:18 2020 +0100
+++ b/hgext3rd/topic/discovery.py Tue Apr 07 19:33:40 2020 +0200
@@ -133,6 +133,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
@@ -144,7 +184,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):