# HG changeset patch
# User Durham Goode <durham@fb.com>
# Date 2014-03-24 22:43:15
# Node ID f49d60fa40a589e5d5fa26a476f9eb3c23767551
# Parent  2efdd186925d64b2c869c07ea27804a1c549ae20

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 @@ def strip(ui, repo, nodelist, backup="al
             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 @@ class basicstore(object):
     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 @@ class fncache(object):
             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 @@ class fncachestore(basicstore):
     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 @@ 2 different branches and a common ancest
   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"