phases: always write with a repo
authorPierre-Yves David <pierre-yves.david@octobus.net>
Tue, 20 Feb 2024 21:38:01 +0100
changeset 51404 04111ef08fb0
parent 51403 68289ed170c7
child 51405 12881244e48a
phases: always write with a repo In the future change that move the internal representation of phase-roots from node-id to rev-num, we will use a repository to translate revision numbers back to node at write time. Since that future change is quite complicated already, we do this small API change beforehand.
mercurial/bundlerepo.py
mercurial/localrepo.py
mercurial/phases.py
--- a/mercurial/bundlerepo.py	Tue Feb 20 17:18:15 2024 +0100
+++ b/mercurial/bundlerepo.py	Tue Feb 20 21:38:01 2024 +0100
@@ -269,7 +269,7 @@
     def _write(self, fp):
         raise NotImplementedError
 
-    def _updateroots(self, phase, newroots, tr):
+    def _updateroots(self, repo, phase, newroots, tr):
         self._phaseroots[phase] = newroots
         self.invalidate()
         self.dirty = True
--- a/mercurial/localrepo.py	Tue Feb 20 17:18:15 2024 +0100
+++ b/mercurial/localrepo.py	Tue Feb 20 21:38:01 2024 +0100
@@ -3363,7 +3363,7 @@
         # dirty after committing. Then when we strip, the repo is invalidated,
         # causing those changes to disappear.
         if '_phasecache' in vars(self):
-            self._phasecache.write()
+            self._phasecache.write(self)
 
     @unfilteredmethod
     def destroyed(self):
--- a/mercurial/phases.py	Tue Feb 20 17:18:15 2024 +0100
+++ b/mercurial/phases.py	Tue Feb 20 21:38:01 2024 +0100
@@ -103,6 +103,7 @@
 
 import struct
 import typing
+import weakref
 
 from typing import (
     Any,
@@ -367,7 +368,6 @@
             self._loadedrevslen = 0
             self._phasesets = None
             self.filterunknown(repo)
-            self.opener = repo.svfs
 
     def hasnonpublicphases(self, repo: "localrepo.localrepository") -> bool:
         """detect if there are revisions with non-public phase"""
@@ -466,7 +466,6 @@
         ph = self.__class__(None, None, _load=False)
         ph._phaseroots = self._phaseroots.copy()
         ph.dirty = self.dirty
-        ph.opener = self.opener
         ph._loadedrevslen = self._loadedrevslen
         ph._phasesets = self._phasesets
         return ph
@@ -476,7 +475,6 @@
         for a in (
             '_phaseroots',
             'dirty',
-            'opener',
             '_loadedrevslen',
             '_phasesets',
         ):
@@ -533,27 +531,36 @@
                 return phase
         return public
 
-    def write(self):
+    def write(self, repo):
         if not self.dirty:
             return
-        f = self.opener(b'phaseroots', b'w', atomictemp=True, checkambig=True)
+        f = repo.svfs(b'phaseroots', b'w', atomictemp=True, checkambig=True)
         try:
-            self._write(f)
+            self._write(repo.unfiltered(), f)
         finally:
             f.close()
 
-    def _write(self, fp):
+    def _write(self, repo, fp):
+        assert repo.filtername is None
         for phase, roots in self._phaseroots.items():
             for h in sorted(roots):
                 fp.write(b'%i %s\n' % (phase, hex(h)))
         self.dirty = False
 
-    def _updateroots(self, phase, newroots, tr):
+    def _updateroots(self, repo, phase, newroots, tr):
         self._phaseroots[phase] = newroots
         self.invalidate()
         self.dirty = True
 
-        tr.addfilegenerator(b'phase', (b'phaseroots',), self._write)
+        assert repo.filtername is None
+        wrepo = weakref.ref(repo)
+
+        def tr_write(fp):
+            repo = wrepo()
+            assert repo is not None
+            self._write(repo, fp)
+
+        tr.addfilegenerator(b'phase', (b'phaseroots',), tr_write)
         tr.hookargs[b'phases_moved'] = b'1'
 
     def registernew(self, repo, tr, targetphase, revs):
@@ -614,7 +621,7 @@
                 for ctx in repo.set(b'roots((%ln::) - %ld)', olds, affected)
             }
             if olds != roots:
-                self._updateroots(phase, roots, tr)
+                self._updateroots(repo, phase, roots, tr)
                 # some roots may need to be declared for lower phases
                 delroots.extend(olds - roots)
         if not dryrun:
@@ -697,7 +704,10 @@
             finalroots.update(updatedroots)
         if finalroots != oldroots:
             self._updateroots(
-                targetphase, {tonode(rev) for rev in finalroots}, tr
+                repo,
+                targetphase,
+                {tonode(rev) for rev in finalroots},
+                tr,
             )
             return True
         return False
@@ -717,7 +727,7 @@
         for targetphase, nodes in list(self._phaseroots.items()):
             filtered = {n for n in nodes if to_rev(n) >= strip_rev}
             if filtered:
-                self._updateroots(targetphase, nodes - filtered, tr)
+                self._updateroots(repo, targetphase, nodes - filtered, tr)
         self.invalidate()
 
     def filterunknown(self, repo: "localrepo.localrepository") -> None: