hgext3rd/topic/discovery.py
changeset 5276 8431bb224862
parent 5203 034d6d0efa7d
parent 5267 ba53591d4aab
--- 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):