diff --git a/mercurial/phases.py b/mercurial/phases.py --- a/mercurial/phases.py +++ b/mercurial/phases.py @@ -352,7 +352,7 @@ _trackphasechange(phasetracking, rev, None, revphase) repo.invalidatevolatilesets() - def advanceboundary(self, repo, tr, targetphase, nodes): + def advanceboundary(self, repo, tr, targetphase, nodes, dryrun=None): """Set all 'nodes' to phase 'targetphase' Nodes with a phase lower than 'targetphase' are not affected. @@ -366,6 +366,17 @@ repo = repo.unfiltered() + rejected = list() # set of rejected nodes + changes = [set(), set(), set()] + # `changes` stores revs (whose phases will be changed) in three + # different sets where each set is for different phase and ordered + # from --public to --secret. + + # Find nodes that are not in a compatible phase and will be rejected + getphase = repo._phasecache.phase + rejected = [repo[n].rev() for n in nodes + if getphase(repo, repo[n].rev()) < targetphase] + delroots = [] # set of root deleted by this path for phase in xrange(targetphase + 1, len(allphases)): # filter nodes that are not in a compatible phase already @@ -377,6 +388,12 @@ olds = self.phaseroots[phase] affected = repo.revs('%ln::%ln', olds, nodes) + if dryrun: + faffected = filter(lambda x: getphase(repo, + repo[x].rev()) == phase, + affected) + changes[phase].update(faffected) + continue for r in affected: _trackphasechange(phasetracking, r, self.phase(repo, r), targetphase) @@ -387,6 +404,8 @@ self._updateroots(phase, roots, tr) # some roots may need to be declared for lower phases delroots.extend(olds - roots) + if dryrun: + return rejected, changes # declare deleted root in the target phase if targetphase != 0: self._retractboundary(repo, tr, targetphase, delroots) @@ -478,16 +497,30 @@ # (see branchmap one) self.invalidate() -def advanceboundary(repo, tr, targetphase, nodes): +def advanceboundary(repo, tr, targetphase, nodes, dryrun=None): """Add nodes to a phase changing other nodes phases if necessary. This function move boundary *forward* this means that all nodes are set in the target phase or kept in a *lower* 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 calculate + `rejected` and `changes`, where: + rejected - list of rejected nodes + changes - list of three sets (each for different phase and ordered + from --public to --secret) where each set contains those + revisions whose phases are changed or can be changed (depends + of dryrun value) from their current phase to targetphase. + + Returns `rejected` and `changes`. + """ phcache = repo._phasecache.copy() - phcache.advanceboundary(repo, tr, targetphase, nodes) - repo._phasecache.replace(phcache) + rejected, changes = phcache.advanceboundary(repo, tr, targetphase, nodes, + dryrun=dryrun) + if not dryrun: + repo._phasecache.replace(phcache) + return rejected, changes def retractboundary(repo, tr, targetphase, nodes): """Set nodes back to a phase changing other nodes phases if