[PATCH 7 of 7 V3] fncache: clean up fncache during strips

Durham Goode durham at fb.com
Tue Apr 1 17:24:17 CDT 2014


# HG changeset patch
# User Durham Goode <durham at fb.com>
# Date 1395700995 25200
#      Mon Mar 24 15:43:15 2014 -0700
# Node ID 825e4770009035711ea6b1e9ac74ada80e4516c6
# Parent  a7b48af9ed3c28d20621406f90e7dddf3c4a3561
fncache: clean up fncache during strips

Previously the fncache was cleaned up at read time by noticing when it was out
of sync. This caused writes to happen outside the scope of transactions and
could have caused race conditions. With this change, we'll keep the fncache
up-to-date as we go by removing old entries during repair.strip.

diff --git a/mercurial/repair.py b/mercurial/repair.py
--- a/mercurial/repair.py
+++ b/mercurial/repair.py
@@ -134,6 +134,8 @@
             for i in xrange(offset, len(tr.entries)):
                 file, troffset, ignore = tr.entries[i]
                 repo.sopener(file, 'a').truncate(troffset)
+                if troffset == 0:
+                    repo.store.markremoved(file)
             tr.close()
         except: # re-raises
             tr.abort()
diff --git a/mercurial/store.py b/mercurial/store.py
--- a/mercurial/store.py
+++ b/mercurial/store.py
@@ -343,6 +343,9 @@
     def invalidatecaches(self):
         pass
 
+    def markremoved(self, fn):
+        pass
+
     def __contains__(self, path):
         '''Checks if the store contains path'''
         path = "/".join(("data", path))
@@ -421,6 +424,15 @@
             self._dirty = True
             self.entries.add(fn)
 
+    def remove(self, fn):
+        if self.entries is None:
+            self._load()
+        try:
+            self.entries.remove(fn)
+            self._dirty = True
+        except KeyError:
+            pass
+
     def __contains__(self, fn):
         if self.entries is None:
             self._load()
@@ -495,6 +507,9 @@
     def invalidatecaches(self):
         self.fncache.entries = None
 
+    def markremoved(self, fn):
+        self.fncache.remove(fn)
+
     def _exists(self, f):
         ef = self.encode(f)
         try:
diff --git a/tests/test-strip.t b/tests/test-strip.t
--- a/tests/test-strip.t
+++ b/tests/test-strip.t
@@ -336,6 +336,19 @@
   saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
   $ restore
 
+verify fncache is kept up-to-date
+
+  $ touch a
+  $ hg ci -qAm a
+  $ cat .hg/store/fncache | sort
+  data/a.i
+  data/bar.i
+  $ hg strip tip
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+  $ cat .hg/store/fncache
+  data/bar.i
+
 stripping an empty revset
 
   $ hg strip "1 and not 1"


More information about the Mercurial-devel mailing list