mercurial/phases.py
changeset 51402 04111ef08fb0
parent 51401 68289ed170c7
child 51403 12881244e48a
equal deleted inserted replaced
51401:68289ed170c7 51402:04111ef08fb0
   101 """
   101 """
   102 
   102 
   103 
   103 
   104 import struct
   104 import struct
   105 import typing
   105 import typing
       
   106 import weakref
   106 
   107 
   107 from typing import (
   108 from typing import (
   108     Any,
   109     Any,
   109     Callable,
   110     Callable,
   110     Dict,
   111     Dict,
   365             # Cheap trick to allow shallow-copy without copy module
   366             # Cheap trick to allow shallow-copy without copy module
   366             self._phaseroots, self.dirty = _readroots(repo, phasedefaults)
   367             self._phaseroots, self.dirty = _readroots(repo, phasedefaults)
   367             self._loadedrevslen = 0
   368             self._loadedrevslen = 0
   368             self._phasesets = None
   369             self._phasesets = None
   369             self.filterunknown(repo)
   370             self.filterunknown(repo)
   370             self.opener = repo.svfs
       
   371 
   371 
   372     def hasnonpublicphases(self, repo: "localrepo.localrepository") -> bool:
   372     def hasnonpublicphases(self, repo: "localrepo.localrepository") -> bool:
   373         """detect if there are revisions with non-public phase"""
   373         """detect if there are revisions with non-public phase"""
   374         repo = repo.unfiltered()
   374         repo = repo.unfiltered()
   375         cl = repo.changelog
   375         cl = repo.changelog
   464         # Shallow copy meant to ensure isolation in
   464         # Shallow copy meant to ensure isolation in
   465         # advance/retractboundary(), nothing more.
   465         # advance/retractboundary(), nothing more.
   466         ph = self.__class__(None, None, _load=False)
   466         ph = self.__class__(None, None, _load=False)
   467         ph._phaseroots = self._phaseroots.copy()
   467         ph._phaseroots = self._phaseroots.copy()
   468         ph.dirty = self.dirty
   468         ph.dirty = self.dirty
   469         ph.opener = self.opener
       
   470         ph._loadedrevslen = self._loadedrevslen
   469         ph._loadedrevslen = self._loadedrevslen
   471         ph._phasesets = self._phasesets
   470         ph._phasesets = self._phasesets
   472         return ph
   471         return ph
   473 
   472 
   474     def replace(self, phcache):
   473     def replace(self, phcache):
   475         """replace all values in 'self' with content of phcache"""
   474         """replace all values in 'self' with content of phcache"""
   476         for a in (
   475         for a in (
   477             '_phaseroots',
   476             '_phaseroots',
   478             'dirty',
   477             'dirty',
   479             'opener',
       
   480             '_loadedrevslen',
   478             '_loadedrevslen',
   481             '_phasesets',
   479             '_phasesets',
   482         ):
   480         ):
   483             setattr(self, a, getattr(phcache, a))
   481             setattr(self, a, getattr(phcache, a))
   484 
   482 
   531         for phase in trackedphases:
   529         for phase in trackedphases:
   532             if rev in self._phasesets[phase]:
   530             if rev in self._phasesets[phase]:
   533                 return phase
   531                 return phase
   534         return public
   532         return public
   535 
   533 
   536     def write(self):
   534     def write(self, repo):
   537         if not self.dirty:
   535         if not self.dirty:
   538             return
   536             return
   539         f = self.opener(b'phaseroots', b'w', atomictemp=True, checkambig=True)
   537         f = repo.svfs(b'phaseroots', b'w', atomictemp=True, checkambig=True)
   540         try:
   538         try:
   541             self._write(f)
   539             self._write(repo.unfiltered(), f)
   542         finally:
   540         finally:
   543             f.close()
   541             f.close()
   544 
   542 
   545     def _write(self, fp):
   543     def _write(self, repo, fp):
       
   544         assert repo.filtername is None
   546         for phase, roots in self._phaseroots.items():
   545         for phase, roots in self._phaseroots.items():
   547             for h in sorted(roots):
   546             for h in sorted(roots):
   548                 fp.write(b'%i %s\n' % (phase, hex(h)))
   547                 fp.write(b'%i %s\n' % (phase, hex(h)))
   549         self.dirty = False
   548         self.dirty = False
   550 
   549 
   551     def _updateroots(self, phase, newroots, tr):
   550     def _updateroots(self, repo, phase, newroots, tr):
   552         self._phaseroots[phase] = newroots
   551         self._phaseroots[phase] = newroots
   553         self.invalidate()
   552         self.invalidate()
   554         self.dirty = True
   553         self.dirty = True
   555 
   554 
   556         tr.addfilegenerator(b'phase', (b'phaseroots',), self._write)
   555         assert repo.filtername is None
       
   556         wrepo = weakref.ref(repo)
       
   557 
       
   558         def tr_write(fp):
       
   559             repo = wrepo()
       
   560             assert repo is not None
       
   561             self._write(repo, fp)
       
   562 
       
   563         tr.addfilegenerator(b'phase', (b'phaseroots',), tr_write)
   557         tr.hookargs[b'phases_moved'] = b'1'
   564         tr.hookargs[b'phases_moved'] = b'1'
   558 
   565 
   559     def registernew(self, repo, tr, targetphase, revs):
   566     def registernew(self, repo, tr, targetphase, revs):
   560         repo = repo.unfiltered()
   567         repo = repo.unfiltered()
   561         self._retractboundary(repo, tr, targetphase, [], revs=revs)
   568         self._retractboundary(repo, tr, targetphase, [], revs=revs)
   612             roots = {
   619             roots = {
   613                 ctx.node()
   620                 ctx.node()
   614                 for ctx in repo.set(b'roots((%ln::) - %ld)', olds, affected)
   621                 for ctx in repo.set(b'roots((%ln::) - %ld)', olds, affected)
   615             }
   622             }
   616             if olds != roots:
   623             if olds != roots:
   617                 self._updateroots(phase, roots, tr)
   624                 self._updateroots(repo, phase, roots, tr)
   618                 # some roots may need to be declared for lower phases
   625                 # some roots may need to be declared for lower phases
   619                 delroots.extend(olds - roots)
   626                 delroots.extend(olds - roots)
   620         if not dryrun:
   627         if not dryrun:
   621             # declare deleted root in the target phase
   628             # declare deleted root in the target phase
   622             if targetphase != 0:
   629             if targetphase != 0:
   695 
   702 
   696             finalroots = {rev for rev in currentroots if rev < minnewroot}
   703             finalroots = {rev for rev in currentroots if rev < minnewroot}
   697             finalroots.update(updatedroots)
   704             finalroots.update(updatedroots)
   698         if finalroots != oldroots:
   705         if finalroots != oldroots:
   699             self._updateroots(
   706             self._updateroots(
   700                 targetphase, {tonode(rev) for rev in finalroots}, tr
   707                 repo,
       
   708                 targetphase,
       
   709                 {tonode(rev) for rev in finalroots},
       
   710                 tr,
   701             )
   711             )
   702             return True
   712             return True
   703         return False
   713         return False
   704 
   714 
   705     def register_strip(
   715     def register_strip(
   715         assert repo.filtername is None
   725         assert repo.filtername is None
   716         to_rev = repo.changelog.index.rev
   726         to_rev = repo.changelog.index.rev
   717         for targetphase, nodes in list(self._phaseroots.items()):
   727         for targetphase, nodes in list(self._phaseroots.items()):
   718             filtered = {n for n in nodes if to_rev(n) >= strip_rev}
   728             filtered = {n for n in nodes if to_rev(n) >= strip_rev}
   719             if filtered:
   729             if filtered:
   720                 self._updateroots(targetphase, nodes - filtered, tr)
   730                 self._updateroots(repo, targetphase, nodes - filtered, tr)
   721         self.invalidate()
   731         self.invalidate()
   722 
   732 
   723     def filterunknown(self, repo: "localrepo.localrepository") -> None:
   733     def filterunknown(self, repo: "localrepo.localrepository") -> None:
   724         """remove unknown nodes from the phase boundary
   734         """remove unknown nodes from the phase boundary
   725 
   735