diff -r af9f40236037 -r ba53591d4aab hgext3rd/topic/discovery.py --- 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):