Patchwork [5,of,5] phase: attach phase to the transaction instead of the lock

login
register
mail settings
Submitter Pierre-Yves David
Date Aug. 7, 2014, 10:52 p.m.
Message ID <cd17100e1102a2296e45.1407451923@marginatus.alto.octopoid.net>
Download mbox | patch
Permalink /patch/5329/
State Accepted
Headers show

Comments

Pierre-Yves David - Aug. 7, 2014, 10:52 p.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david@fb.com>
# Date 1407445896 25200
#      Thu Aug 07 14:11:36 2014 -0700
# Node ID cd17100e1102a2296e45c8837b4b774371c80f1b
# Parent  ed5766a5d48982f9794683f594625ce663ca8f90
phase: attach phase to the transaction instead of the lock

The phase cache file is no longer written on lock release, it is now handled by
the transaction (as changeset and obsolescence markers are).

(Hooray)

As we stop relying on the lock to write phase, repo with no existing phase
information will need to wait for a phase move or a strip to happen in order to
get the first write in the `phaseroots` file. This explain the change in
test-inherit-mode.t.

This should not have any side effect but in very obscure case were people
interact with pre 2.1 and post 2.1 version of Mercurial on the same repo while
having MQ patches applied but the MQ extension disabled from time to time. A
case unlikely enough to not worth preserving the old behavior with awful hacks.
Matt Mackall - Aug. 8, 2014, 6:20 p.m.
On Thu, 2014-08-07 at 15:52 -0700, Pierre-Yves David wrote:
> # HG changeset patch
> # User Pierre-Yves David <pierre-yves.david@fb.com>
> # Date 1407445896 25200
> #      Thu Aug 07 14:11:36 2014 -0700
> # Node ID cd17100e1102a2296e45c8837b4b774371c80f1b
> # Parent  ed5766a5d48982f9794683f594625ce663ca8f90
> phase: attach phase to the transaction instead of the lock

These are queued for default, thanks.

Patch

diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -1087,12 +1087,10 @@  class localrepository(object):
         if l is not None and l.held:
             l.lock()
             return l
 
         def unlock():
-            if hasunfilteredcache(self, '_phasecache'):
-                self._phasecache.write()
             for k, ce in self._filecache.items():
                 if k == 'dirstate' or k not in self.__dict__:
                     continue
                 ce.refresh()
 
diff --git a/mercurial/phases.py b/mercurial/phases.py
--- a/mercurial/phases.py
+++ b/mercurial/phases.py
@@ -204,15 +204,17 @@  class phasecache(object):
         for phase, roots in enumerate(self.phaseroots):
             for h in roots:
                 fp.write('%i %s\n' % (phase, hex(h)))
         self.dirty = False
 
-    def _updateroots(self, phase, newroots):
+    def _updateroots(self, phase, newroots, tr):
         self.phaseroots[phase] = newroots
         self._phaserevs = None
         self.dirty = True
 
+        tr.addfilegenerator('phase', ('phaseroots',), self._write)
+
     def advanceboundary(self, repo, tr, targetphase, nodes):
         # Be careful to preserve shallow-copied values: do not update
         # phaseroots values, replace them.
 
         repo = repo.unfiltered()
@@ -225,11 +227,11 @@  class phasecache(object):
                 break # no roots to move anymore
             olds = self.phaseroots[phase]
             roots = set(ctx.node() for ctx in repo.set(
                     'roots((%ln::) - (%ln::%ln))', olds, olds, nodes))
             if olds != roots:
-                self._updateroots(phase, roots)
+                self._updateroots(phase, roots, tr)
                 # some roots may need to be declared for lower phases
                 delroots.extend(olds - roots)
             # declare deleted root in the target phase
             if targetphase != 0:
                 self.retractboundary(repo, tr, targetphase, delroots)
@@ -248,11 +250,11 @@  class phasecache(object):
                 raise util.Abort(_('cannot change null revision phase'))
             currentroots = currentroots.copy()
             currentroots.update(newroots)
             ctxs = repo.set('roots(%ln::)', currentroots)
             currentroots.intersection_update(ctx.node() for ctx in ctxs)
-            self._updateroots(targetphase, currentroots)
+            self._updateroots(targetphase, currentroots, tr)
         repo.invalidatevolatilesets()
 
     def filterunknown(self, repo):
         """remove unknown nodes from the phase boundary
 
diff --git a/tests/test-inherit-mode.t b/tests/test-inherit-mode.t
--- a/tests/test-inherit-mode.t
+++ b/tests/test-inherit-mode.t
@@ -118,11 +118,10 @@  group can still write everything
   00770 ../push/.hg/store/data/
   00770 ../push/.hg/store/data/dir/
   00660 ../push/.hg/store/data/dir/bar.i
   00660 ../push/.hg/store/data/foo.i
   00660 ../push/.hg/store/fncache
-  00660 ../push/.hg/store/phaseroots
   00660 ../push/.hg/store/undo
   00660 ../push/.hg/store/undo.phaseroots
   00660 ../push/.hg/undo.bookmarks
   00660 ../push/.hg/undo.branch
   00660 ../push/.hg/undo.desc