Mercurial > hg
changeset 39891:b99903534e06
scmutil: accept multiple predecessors in 'replacements' (API)
This changeset makes 'cleanupnodes' accepts multiple predecessors as
`replacements` keys. The same as it accepts multiple successors as
`replacements` values. To avoid breaking all callers, the old and new ways are
currently valid at the same time. We'll deprecate and drop the old way later.
This change is the first step toward a better tracking of "fold" event in the
evolution history. While working on the "rewind" command (in the evolve
extension), we realized that first class tracking of folds are necessary.
We already have good tracking of splits. When walking the evolution history
from predecessors to successors, that makes for a clear distinction between
having multiple successors because of the actual splitting of a changeset or
content-divergences.
The "rewind" command allows restoring older evolution of a stack of
changesets. One of its mode walks the evolution history to automatically find
appropriate predecessors. This means walking from successors to predecessors.
In this case, we need to be able to make the same distinction between an
actual fold and other cases. So we will have to track folds explicitly.
This changesets only focus on making it possible to express fold at the
`cleanupnodes` API level. The actual tracking will be implemented later.
author | Boris Feld <boris.feld@octobus.net> |
---|---|
date | Thu, 27 Sep 2018 13:57:50 -0700 |
parents | 1c3f1491965f |
children | b55747ca518f |
files | mercurial/scmutil.py |
diffstat | 1 files changed, 40 insertions(+), 26 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/scmutil.py Thu Sep 27 13:54:37 2018 -0700 +++ b/mercurial/scmutil.py Thu Sep 27 13:57:50 2018 -0700 @@ -875,39 +875,52 @@ # translate mapping's other forms if not util.safehasattr(replacements, 'items'): - replacements = {n: () for n in replacements} + replacements = {(n,): () for n in replacements} + else: + # upgrading non tuple "source" to tuple ones for BC + repls = {} + for key, value in replacements.items(): + if not isinstance(key, tuple): + key = (key,) + repls[key] = value + replacements = repls # Calculate bookmark movements if moves is None: moves = {} # Unfiltered repo is needed since nodes in replacements might be hidden. unfi = repo.unfiltered() - for oldnode, newnodes in replacements.items(): - if oldnode in moves: - continue - if len(newnodes) > 1: - # usually a split, take the one with biggest rev number - newnode = next(unfi.set('max(%ln)', newnodes)).node() - elif len(newnodes) == 0: - # move bookmark backwards - roots = list(unfi.set('max((::%n) - %ln)', oldnode, - list(replacements))) - if roots: - newnode = roots[0].node() + for oldnodes, newnodes in replacements.items(): + for oldnode in oldnodes: + if oldnode in moves: + continue + if len(newnodes) > 1: + # usually a split, take the one with biggest rev number + newnode = next(unfi.set('max(%ln)', newnodes)).node() + elif len(newnodes) == 0: + # move bookmark backwards + allreplaced = [] + for rep in replacements: + allreplaced.extend(rep) + roots = list(unfi.set('max((::%n) - %ln)', oldnode, + allreplaced)) + if roots: + newnode = roots[0].node() + else: + newnode = nullid else: - newnode = nullid - else: - newnode = newnodes[0] - moves[oldnode] = newnode + newnode = newnodes[0] + moves[oldnode] = newnode allnewnodes = [n for ns in replacements.values() for n in ns] toretract = {} toadvance = {} if fixphase: precursors = {} - for oldnode, newnodes in replacements.items(): - for newnode in newnodes: - precursors.setdefault(newnode, []).append(oldnode) + for oldnodes, newnodes in replacements.items(): + for oldnode in oldnodes: + for newnode in newnodes: + precursors.setdefault(newnode, []).append(oldnode) allnewnodes.sort(key=lambda n: unfi[n].rev()) newphases = {} @@ -967,18 +980,19 @@ # NOTE: the filtering and sorting might belong to createmarkers. isobs = unfi.obsstore.successors.__contains__ torev = unfi.changelog.rev - sortfunc = lambda ns: torev(ns[0]) + sortfunc = lambda ns: torev(ns[0][0]) rels = [] - for n, s in sorted(replacements.items(), key=sortfunc): - if s or not isobs(n): - rel = (unfi[n], tuple(unfi[m] for m in s)) - rels.append(rel) + for ns, s in sorted(replacements.items(), key=sortfunc): + for n in ns: + if s or not isobs(n): + rel = (unfi[n], tuple(unfi[m] for m in s)) + rels.append(rel) if rels: obsolete.createmarkers(repo, rels, operation=operation, metadata=metadata) else: from . import repair # avoid import cycle - tostrip = list(replacements) + tostrip = list(n for ns in replacements for n in ns) if tostrip: repair.delayedstrip(repo.ui, repo, tostrip, operation, backup=backup)