Mercurial > hg-stable
diff mercurial/discovery.py @ 51646:6454c117c6a4 stable 6.8rc0
branching: merge default into stable for 6.8rc0
author | Raphaël Gomès <rgomes@octobus.net> |
---|---|
date | Mon, 24 Jun 2024 12:05:31 +0200 |
parents | 3a6fae3bef35 |
children |
line wrap: on
line diff
--- a/mercurial/discovery.py Thu Jun 13 09:52:39 2024 +0200 +++ b/mercurial/discovery.py Mon Jun 24 12:05:31 2024 +0200 @@ -18,6 +18,7 @@ bookmarks, branchmap, error, + node as nodemod, obsolete, phases, pycompat, @@ -98,29 +99,62 @@ def __init__( self, repo, commonheads=None, ancestorsof=None, missingroots=None ): - # at least one of them must not be set - assert None in (commonheads, missingroots) + # at most one of them must not be set + if commonheads is not None and missingroots is not None: + m = 'commonheads and missingroots arguments are mutually exclusive' + raise error.ProgrammingError(m) cl = repo.changelog + unfi = repo.unfiltered() + ucl = unfi.changelog + to_node = ucl.node + missing = None + common = None + arg_anc = ancestorsof if ancestorsof is None: ancestorsof = cl.heads() - if missingroots: + + # XXX-perf: do we need all this to be node-list? They would be simpler + # as rev-num sets (and smartset) + if missingroots == [nodemod.nullrev] or missingroots == []: + commonheads = [repo.nullid] + common = set() + if arg_anc is None: + missing = [to_node(r) for r in cl] + else: + missing_rev = repo.revs('::%ln', missingroots, ancestorsof) + missing = [to_node(r) for r in missing_rev] + elif missingroots is not None: # TODO remove call to nodesbetween. - # TODO populate attributes on outgoing instance instead of setting - # discbases. - csets, roots, heads = cl.nodesbetween(missingroots, ancestorsof) - included = set(csets) - discbases = [] - for n in csets: - discbases.extend([p for p in cl.parents(n) if p != repo.nullid]) - ancestorsof = heads - commonheads = [n for n in discbases if n not in included] + missing_rev = repo.revs('%ln::%ln', missingroots, ancestorsof) + ancestorsof = [to_node(r) for r in ucl.headrevs(missing_rev)] + parent_revs = ucl.parentrevs + common_legs = set() + for r in missing_rev: + p1, p2 = parent_revs(r) + if p1 not in missing_rev: + common_legs.add(p1) + if p2 not in missing_rev: + common_legs.add(p2) + common_legs.discard(nodemod.nullrev) + if not common_legs: + commonheads = [repo.nullid] + common = set() + else: + commonheads_revs = unfi.revs( + 'heads(%ld::%ld)', + common_legs, + common_legs, + ) + commonheads = [to_node(r) for r in commonheads_revs] + common = ucl.ancestors(commonheads_revs, inclusive=True) + missing = [to_node(r) for r in missing_rev] elif not commonheads: commonheads = [repo.nullid] self.commonheads = commonheads self.ancestorsof = ancestorsof self._revlog = cl - self._common = None - self._missing = None + self._common = common + self._missing = missing self.excluded = [] def _computecommonmissing(self): @@ -190,7 +224,12 @@ if len(missing) == len(allmissing): ancestorsof = onlyheads else: # update missing heads - ancestorsof = phases.newheads(repo, onlyheads, excluded) + to_rev = repo.changelog.index.rev + to_node = repo.changelog.node + excluded_revs = [to_rev(r) for r in excluded] + onlyheads_revs = [to_rev(r) for r in onlyheads] + new_heads = phases.new_heads(repo, onlyheads_revs, excluded_revs) + ancestorsof = [to_node(r) for r in new_heads] og.ancestorsof = ancestorsof if portable: # recompute common and ancestorsof as if -r<rev> had been given for