--- a/mercurial/phases.py Sat Oct 05 10:29:34 2019 -0400
+++ b/mercurial/phases.py Sun Oct 06 09:45:02 2019 -0400
@@ -123,8 +123,8 @@
_fphasesentry = struct.Struct('>i20s')
-INTERNAL_FLAG = 64 # Phases for mercurial internal usage only
-HIDEABLE_FLAG = 32 # Phases that are hideable
+INTERNAL_FLAG = 64 # Phases for mercurial internal usage only
+HIDEABLE_FLAG = 32 # Phases that are hideable
# record phase index
public, draft, secret = range(3)
@@ -135,7 +135,7 @@
# record phase names
cmdphasenames = ['public', 'draft', 'secret'] # known to `hg phase` command
phasenames = [None] * len(allphases)
-phasenames[:len(cmdphasenames)] = cmdphasenames
+phasenames[: len(cmdphasenames)] = cmdphasenames
phasenames[archived] = 'archived'
phasenames[internal] = 'internal'
# record phase property
@@ -143,10 +143,12 @@
remotehiddenphases = tuple(allphases[2:])
localhiddenphases = tuple(p for p in allphases if p & HIDEABLE_FLAG)
+
def supportinternal(repo):
"""True if the internal phase can be used on a repository"""
return 'internal-phase' in repo.requirements
+
def _readroots(repo, phasedefaults=None):
"""Read phase roots from disk
@@ -178,6 +180,7 @@
dirty = True
return roots, dirty
+
def binaryencode(phasemapping):
"""encode a 'phase -> nodes' mapping into a binary stream
@@ -190,6 +193,7 @@
binarydata.append(_fphasesentry.pack(phase, head))
return ''.join(binarydata)
+
def binarydecode(stream):
"""decode a binary stream into a 'phase -> nodes' mapping
@@ -206,6 +210,7 @@
headsbyphase[phase].append(node)
return headsbyphase
+
def _trackphasechange(data, rev, old, new):
"""add a phase move the <data> dictionnary
@@ -218,6 +223,7 @@
old = existing[0]
data[rev] = (old, new)
+
class phasecache(object):
def __init__(self, repo, phasedefaults, _load=True):
if _load:
@@ -230,7 +236,7 @@
def getrevset(self, repo, phases, subset=None):
"""return a smartset for the given phases"""
- self.loadphaserevs(repo) # ensure phase's sets are loaded
+ self.loadphaserevs(repo) # ensure phase's sets are loaded
phases = set(phases)
if public not in phases:
# fast path: _phasesets contains the interesting sets,
@@ -274,16 +280,22 @@
def replace(self, phcache):
"""replace all values in 'self' with content of phcache"""
- for a in ('phaseroots', 'dirty', 'opener', '_loadedrevslen',
- '_phasesets'):
+ for a in (
+ 'phaseroots',
+ 'dirty',
+ 'opener',
+ '_loadedrevslen',
+ '_phasesets',
+ ):
setattr(self, a, getattr(phcache, a))
def _getphaserevsnative(self, repo):
repo = repo.unfiltered()
nativeroots = []
for phase in trackedphases:
- nativeroots.append(pycompat.maplist(repo.changelog.rev,
- self.phaseroots[phase]))
+ nativeroots.append(
+ pycompat.maplist(repo.changelog.rev, self.phaseroots[phase])
+ )
return repo.changelog.computephases(nativeroots)
def _computephaserevspure(self, repo):
@@ -387,14 +399,15 @@
repo = repo.unfiltered()
- changes = set() # set of revisions to be changed
- delroots = [] # set of root deleted by this path
+ changes = set() # set of revisions to be changed
+ delroots = [] # set of root deleted by this path
for phase in pycompat.xrange(targetphase + 1, len(allphases)):
# filter nodes that are not in a compatible phase already
- nodes = [n for n in nodes
- if self.phase(repo, repo[n].rev()) >= phase]
+ nodes = [
+ n for n in nodes if self.phase(repo, repo[n].rev()) >= phase
+ ]
if not nodes:
- break # no roots to move anymore
+ break # no roots to move anymore
olds = self.phaseroots[phase]
@@ -403,11 +416,14 @@
if dryrun:
continue
for r in affected:
- _trackphasechange(phasetracking, r, self.phase(repo, r),
- targetphase)
+ _trackphasechange(
+ phasetracking, r, self.phase(repo, r), targetphase
+ )
- roots = set(ctx.node() for ctx in repo.set(
- 'roots((%ln::) - %ld)', olds, affected))
+ roots = set(
+ ctx.node()
+ for ctx in repo.set('roots((%ln::) - %ld)', olds, affected)
+ )
if olds != roots:
self._updateroots(phase, roots, tr)
# some roots may need to be declared for lower phases
@@ -420,14 +436,16 @@
return changes
def retractboundary(self, repo, tr, targetphase, nodes):
- oldroots = self.phaseroots[:targetphase + 1]
+ 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):
+ if (
+ self._retractboundary(repo, tr, targetphase, nodes)
+ and phasetracking is not None
+ ):
# find the affected revisions
new = self.phaseroots[targetphase]
@@ -440,7 +458,7 @@
roots = oldroots[phase]
revs = set(repo.revs('%ln::%ld', roots, affected))
affected -= revs
- else: # public phase
+ else: # public phase
revs = affected
for r in revs:
_trackphasechange(phasetracking, r, phase, targetphase)
@@ -457,8 +475,9 @@
repo = repo.unfiltered()
currentroots = self.phaseroots[targetphase]
finalroots = oldroots = set(currentroots)
- newroots = [n for n in nodes
- if self.phase(repo, repo[n].rev()) < targetphase]
+ newroots = [
+ n for n in nodes if self.phase(repo, repo[n].rev()) < targetphase
+ ]
if newroots:
if nullid in newroots:
@@ -469,12 +488,14 @@
# Only compute new roots for revs above the roots that are being
# retracted.
minnewroot = min(repo[n].rev() for n in newroots)
- aboveroots = [n for n in currentroots
- if repo[n].rev() >= minnewroot]
+ aboveroots = [
+ n for n in currentroots if repo[n].rev() >= minnewroot
+ ]
updatedroots = repo.set('roots(%ln::)', aboveroots)
- finalroots = set(n for n in currentroots if repo[n].rev() <
- minnewroot)
+ finalroots = set(
+ n for n in currentroots if repo[n].rev() < minnewroot
+ )
finalroots.update(ctx.node() for ctx in updatedroots)
if finalroots != oldroots:
self._updateroots(targetphase, finalroots, tr)
@@ -487,14 +508,15 @@
Nothing is lost as unknown nodes only hold data for their descendants.
"""
filtered = False
- nodemap = repo.changelog.nodemap # to filter unknown nodes
+ nodemap = repo.changelog.nodemap # to filter unknown nodes
for phase, nodes in enumerate(self.phaseroots):
missing = sorted(node for node in nodes if node not in nodemap)
if missing:
for mnode in missing:
repo.ui.debug(
'removing unknown node %s from %i-phase boundary\n'
- % (short(mnode), phase))
+ % (short(mnode), phase)
+ )
nodes.symmetric_difference_update(missing)
filtered = True
if filtered:
@@ -509,6 +531,7 @@
# (see branchmap one)
self.invalidate()
+
def advanceboundary(repo, tr, targetphase, nodes, dryrun=None):
"""Add nodes to a phase changing other nodes phases if necessary.
@@ -522,12 +545,14 @@
Returns a set of revs whose phase is changed or should be changed
"""
phcache = repo._phasecache.copy()
- changes = phcache.advanceboundary(repo, tr, targetphase, nodes,
- dryrun=dryrun)
+ changes = phcache.advanceboundary(
+ repo, tr, targetphase, nodes, dryrun=dryrun
+ )
if not dryrun:
repo._phasecache.replace(phcache)
return changes
+
def retractboundary(repo, tr, targetphase, nodes):
"""Set nodes back to a phase changing other nodes phases if
necessary.
@@ -540,6 +565,7 @@
phcache.retractboundary(repo, tr, targetphase, nodes)
repo._phasecache.replace(phcache)
+
def registernew(repo, tr, targetphase, nodes):
"""register a new revision and its phase
@@ -550,6 +576,7 @@
phcache.registernew(repo, tr, targetphase, nodes)
repo._phasecache.replace(phcache)
+
def listphases(repo):
"""List phases root for serialization over pushkey"""
# Use ordered dictionary so behavior is deterministic.
@@ -580,13 +607,14 @@
keys['publishing'] = 'True'
return keys
+
def pushphase(repo, nhex, oldphasestr, newphasestr):
"""List phases root for serialization over pushkey"""
repo = repo.unfiltered()
with repo.lock():
currentphase = repo[nhex].phase()
- newphase = abs(int(newphasestr)) # let's avoid negative index surprise
- oldphase = abs(int(oldphasestr)) # let's avoid negative index surprise
+ newphase = abs(int(newphasestr)) # let's avoid negative index surprise
+ oldphase = abs(int(oldphasestr)) # let's avoid negative index surprise
if currentphase == oldphase and newphase < oldphase:
with repo.transaction('pushkey-phase') as tr:
advanceboundary(repo, tr, newphase, [bin(nhex)])
@@ -597,6 +625,7 @@
else:
return False
+
def subsetphaseheads(repo, subset):
"""Finds the phase heads for a subset of a history
@@ -613,6 +642,7 @@
headsbyphase[phase] = [cl.node(r) for r in repo.revs(revset, subset)]
return headsbyphase
+
def updatephases(repo, trgetter, headsbyphase):
"""Updates the repo with the given phase heads"""
# Now advance phase boundaries of all but secret phase
@@ -626,6 +656,7 @@
if heads:
advanceboundary(repo, trgetter(), phase, heads)
+
def analyzeremotephases(repo, subset, roots):
"""Compute phases heads and root in a subset of node from root dict
@@ -637,26 +668,31 @@
repo = repo.unfiltered()
# build list from dictionary
draftroots = []
- nodemap = repo.changelog.nodemap # to filter unknown nodes
+ nodemap = repo.changelog.nodemap # to filter unknown nodes
for nhex, phase in roots.iteritems():
- if nhex == 'publishing': # ignore data related to publish option
+ if nhex == 'publishing': # ignore data related to publish option
continue
node = bin(nhex)
phase = int(phase)
if phase == public:
if node != nullid:
- repo.ui.warn(_('ignoring inconsistent public root'
- ' from remote: %s\n') % nhex)
+ repo.ui.warn(
+ _('ignoring inconsistent public root' ' from remote: %s\n')
+ % nhex
+ )
elif phase == draft:
if node in nodemap:
draftroots.append(node)
else:
- repo.ui.warn(_('ignoring unexpected root from remote: %i %s\n')
- % (phase, nhex))
+ repo.ui.warn(
+ _('ignoring unexpected root from remote: %i %s\n')
+ % (phase, nhex)
+ )
# compute heads
publicheads = newheads(repo, subset, draftroots)
return publicheads, draftroots
+
class remotephasessummary(object):
"""summarize phase information on the remote side
@@ -678,6 +714,7 @@
dheads = unfi.set('heads(%ln::%ln)', self.draftroots, remotesubset)
self.draftheads = [c.node() for c in dheads]
+
def newheads(repo, heads, roots):
"""compute new head of a subset minus another
@@ -703,8 +740,9 @@
new_heads.difference_update(affected_zone)
# revisions in the area have children outside of it,
# They might be new heads
- candidates = repo.revs("parents(%ld + (%ld and merge())) and not null",
- roots, affected_zone)
+ candidates = repo.revs(
+ "parents(%ld + (%ld and merge())) and not null", roots, affected_zone
+ )
candidates -= affected_zone
if new_heads or candidates:
# remove candidate that are ancestors of other heads
@@ -715,6 +753,7 @@
return pycompat.maplist(cl.node, sorted(new_heads))
+
def newcommitphase(ui):
"""helper to get the target phase of new commit
@@ -731,15 +770,15 @@
msg = _("phases.new-commit: not a valid phase name ('%s')")
raise error.ConfigError(msg % v)
+
def hassecret(repo):
"""utility function that check if a repo have any secret changeset."""
return bool(repo._phasecache.phaseroots[2])
+
def preparehookargs(node, old, new):
if old is None:
old = ''
else:
old = phasenames[old]
- return {'node': node,
- 'oldphase': old,
- 'phase': phasenames[new]}
+ return {'node': node, 'oldphase': old, 'phase': phasenames[new]}