# HG changeset patch # User Pierre-Yves David # Date 1586138518 -7200 # Node ID ba53591d4aab8c6265683446fc327209dfd4c12f # Parent af9f402360379636e90ac50cf4296446ddeeaca2 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. 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):