diff --git a/mercurial/phases.py b/mercurial/phases.py --- a/mercurial/phases.py +++ b/mercurial/phases.py @@ -392,32 +392,42 @@ self._retractboundary(repo, tr, targetphase, delroots) repo.invalidatevolatilesets() - def retractboundary(self, repo, tr, targetphase, nodes): + def retractboundary(self, repo, tr, targetphase, nodes, dryrun=None): oldroots = self.phaseroots[:targetphase + 1] if tr is None: phasetracking = None else: phasetracking = tr.changes.get('phases') repo = repo.unfiltered() - if (self._retractboundary(repo, tr, targetphase, nodes) - and phasetracking is not None): - - # find the affected revisions - new = self.phaseroots[targetphase] - old = oldroots[targetphase] - affected = set(repo.revs('(%ln::) - (%ln::)', new, old)) + changes = set() # set or revisions whose phase can be changed. + if dryrun: + getphase = repo._phasecache.phase + nds = [n for n in nodes + if getphase(repo, repo[n].rev()) < targetphase] + targetphroots = oldroots[-1] + affected = set(repo.revs('(%ln::) - (%ln::)', nds, targetphroots)) + changes.update(affected) + else: + if (self._retractboundary(repo, tr, targetphase, nodes) + and phasetracking is not None): - # find the phase of the affected revision - for phase in xrange(targetphase, -1, -1): - if phase: - roots = oldroots[phase] - revs = set(repo.revs('%ln::%ld', roots, affected)) - affected -= revs - else: # public phase - revs = affected - for r in revs: - _trackphasechange(phasetracking, r, phase, targetphase) - repo.invalidatevolatilesets() + # find the affected revisions + new = self.phaseroots[targetphase] + old = oldroots[targetphase] + affected = set(repo.revs('(%ln::) - (%ln::)', new, old)) + + # find the phase of the affected revision + for phase in xrange(targetphase, -1, -1): + if phase: + roots = oldroots[phase] + revs = set(repo.revs('%ln::%ld', roots, affected)) + affected -= revs + else: # public phase + revs = affected + for r in revs: + _trackphasechange(phasetracking, r, phase, targetphase) + repo.invalidatevolatilesets() + return changes def _retractboundary(self, repo, tr, targetphase, nodes): # Be careful to preserve shallow-copied values: do not update @@ -489,17 +499,24 @@ phcache.advanceboundary(repo, tr, targetphase, nodes) repo._phasecache.replace(phcache) -def retractboundary(repo, tr, targetphase, nodes): +def retractboundary(repo, tr, targetphase, nodes, dryrun=None): """Set nodes back to a phase changing other nodes phases if necessary. This function move boundary *backward* this means that all nodes are set in the target phase or kept in a *higher* phase. - Simplify boundary to contains phase roots only.""" + Simplify boundary to contains phase roots only. + + If dryrun is true then it will not perform any action and only returns + set of revision whose phase can be changed. + """ phcache = repo._phasecache.copy() - phcache.retractboundary(repo, tr, targetphase, nodes) - repo._phasecache.replace(phcache) + changes = phcache.retractboundary(repo, tr, targetphase, nodes, + dryrun=dryrun) + if not dryrun: + repo._phasecache.replace(phcache) + return changes def registernew(repo, tr, targetphase, nodes): """register a new revision and its phase