mercurial/phases.py
changeset 44558 fdc802f29b2c
parent 44470 9d2b2df2c2ba
child 45008 fa151f7af275
equal deleted inserted replaced
44557:81a873477feb 44558:fdc802f29b2c
   214         phase, node = _fphasesentry.unpack(entry)
   214         phase, node = _fphasesentry.unpack(entry)
   215         headsbyphase[phase].append(node)
   215         headsbyphase[phase].append(node)
   216     return headsbyphase
   216     return headsbyphase
   217 
   217 
   218 
   218 
       
   219 def _sortedrange_insert(data, idx, rev, t):
       
   220     merge_before = False
       
   221     if idx:
       
   222         r1, t1 = data[idx - 1]
       
   223         merge_before = r1[-1] + 1 == rev and t1 == t
       
   224     merge_after = False
       
   225     if idx < len(data):
       
   226         r2, t2 = data[idx]
       
   227         merge_after = r2[0] == rev + 1 and t2 == t
       
   228 
       
   229     if merge_before and merge_after:
       
   230         data[idx - 1] = (pycompat.xrange(r1[0], r2[-1] + 1), t)
       
   231         data.pop(idx)
       
   232     elif merge_before:
       
   233         data[idx - 1] = (pycompat.xrange(r1[0], rev + 1), t)
       
   234     elif merge_after:
       
   235         data[idx] = (pycompat.xrange(rev, r2[-1] + 1), t)
       
   236     else:
       
   237         data.insert(idx, (pycompat.xrange(rev, rev + 1), t))
       
   238 
       
   239 
       
   240 def _sortedrange_split(data, idx, rev, t):
       
   241     r1, t1 = data[idx]
       
   242     if t == t1:
       
   243         return
       
   244     t = (t1[0], t[1])
       
   245     if len(r1) == 1:
       
   246         data.pop(idx)
       
   247         _sortedrange_insert(data, idx, rev, t)
       
   248     elif r1[0] == rev:
       
   249         data[idx] = (pycompat.xrange(rev + 1, r1[-1] + 1), t1)
       
   250         _sortedrange_insert(data, idx, rev, t)
       
   251     elif r1[-1] == rev:
       
   252         data[idx] = (pycompat.xrange(r1[0], rev), t1)
       
   253         _sortedrange_insert(data, idx + 1, rev, t)
       
   254     else:
       
   255         data[idx : idx + 1] = [
       
   256             (pycompat.xrange(r1[0], rev), t1),
       
   257             (pycompat.xrange(rev, rev + 1), t),
       
   258             (pycompat.xrange(rev + 1, r1[-1] + 1), t1),
       
   259         ]
       
   260 
       
   261 
   219 def _trackphasechange(data, rev, old, new):
   262 def _trackphasechange(data, rev, old, new):
   220     """add a phase move the <data> dictionnary
   263     """add a phase move to the <data> list of ranges
   221 
   264 
   222     If data is None, nothing happens.
   265     If data is None, nothing happens.
   223     """
   266     """
   224     if data is None:
   267     if data is None:
   225         return
   268         return
   226     existing = data.get(rev)
   269 
   227     if existing is not None:
   270     # If data is empty, create a one-revision range and done
   228         old = existing[0]
   271     if not data:
   229     data[rev] = (old, new)
   272         data.insert(0, (pycompat.xrange(rev, rev + 1), (old, new)))
       
   273         return
       
   274 
       
   275     low = 0
       
   276     high = len(data)
       
   277     t = (old, new)
       
   278     while low < high:
       
   279         mid = (low + high) // 2
       
   280         revs = data[mid][0]
       
   281 
       
   282         if rev in revs:
       
   283             _sortedrange_split(data, mid, rev, t)
       
   284             return
       
   285 
       
   286         if revs[0] == rev + 1:
       
   287             if mid and data[mid - 1][0][-1] == rev:
       
   288                 _sortedrange_split(data, mid - 1, rev, t)
       
   289             else:
       
   290                 _sortedrange_insert(data, mid, rev, t)
       
   291             return
       
   292 
       
   293         if revs[-1] == rev - 1:
       
   294             if mid + 1 < len(data) and data[mid + 1][0][0] == rev:
       
   295                 _sortedrange_split(data, mid + 1, rev, t)
       
   296             else:
       
   297                 _sortedrange_insert(data, mid + 1, rev, t)
       
   298             return
       
   299 
       
   300         if revs[0] > rev:
       
   301             high = mid
       
   302         else:
       
   303             low = mid + 1
       
   304 
       
   305     if low == len(data):
       
   306         data.append((pycompat.xrange(rev, rev + 1), t))
       
   307         return
       
   308 
       
   309     r1, t1 = data[low]
       
   310     if r1[0] > rev:
       
   311         data.insert(low, (pycompat.xrange(rev, rev + 1), t))
       
   312     else:
       
   313         data.insert(low + 1, (pycompat.xrange(rev, rev + 1), t))
   230 
   314 
   231 
   315 
   232 class phasecache(object):
   316 class phasecache(object):
   233     def __init__(self, repo, phasedefaults, _load=True):
   317     def __init__(self, repo, phasedefaults, _load=True):
   234         if _load:
   318         if _load:
   398         self._retractboundary(repo, tr, targetphase, nodes)
   482         self._retractboundary(repo, tr, targetphase, nodes)
   399         if tr is not None and b'phases' in tr.changes:
   483         if tr is not None and b'phases' in tr.changes:
   400             phasetracking = tr.changes[b'phases']
   484             phasetracking = tr.changes[b'phases']
   401             torev = repo.changelog.rev
   485             torev = repo.changelog.rev
   402             phase = self.phase
   486             phase = self.phase
   403             for n in nodes:
   487             revs = [torev(node) for node in nodes]
   404                 rev = torev(n)
   488             revs.sort()
       
   489             for rev in revs:
   405                 revphase = phase(repo, rev)
   490                 revphase = phase(repo, rev)
   406                 _trackphasechange(phasetracking, rev, None, revphase)
   491                 _trackphasechange(phasetracking, rev, None, revphase)
   407         repo.invalidatevolatilesets()
   492         repo.invalidatevolatilesets()
   408 
   493 
   409     def advanceboundary(self, repo, tr, targetphase, nodes, dryrun=None):
   494     def advanceboundary(self, repo, tr, targetphase, nodes, dryrun=None):
   483                     roots = oldroots[phase]
   568                     roots = oldroots[phase]
   484                     revs = set(repo.revs(b'%ln::%ld', roots, affected))
   569                     revs = set(repo.revs(b'%ln::%ld', roots, affected))
   485                     affected -= revs
   570                     affected -= revs
   486                 else:  # public phase
   571                 else:  # public phase
   487                     revs = affected
   572                     revs = affected
   488                 for r in revs:
   573                 for r in sorted(revs):
   489                     _trackphasechange(phasetracking, r, phase, targetphase)
   574                     _trackphasechange(phasetracking, r, phase, targetphase)
   490         repo.invalidatevolatilesets()
   575         repo.invalidatevolatilesets()
   491 
   576 
   492     def _retractboundary(self, repo, tr, targetphase, nodes):
   577     def _retractboundary(self, repo, tr, targetphase, nodes):
   493         # Be careful to preserve shallow-copied values: do not update
   578         # Be careful to preserve shallow-copied values: do not update