Patchwork [2,of,4,V2] localrepo: make invalidate avoid invalidating store inside transaction (API)

login
register
mail settings
Submitter Katsunori FUJIWARA
Date Sept. 11, 2016, 6:11 p.m.
Message ID <8f9b06ec1b6dbca4c330.1473617514@feefifofum>
Download mbox | patch
Permalink /patch/16586/
State Accepted
Headers show

Comments

Katsunori FUJIWARA - Sept. 11, 2016, 6:11 p.m.
# HG changeset patch
# User FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
# Date 1473617188 -32400
#      Mon Sep 12 03:06:28 2016 +0900
# Node ID 8f9b06ec1b6dbca4c3307dfedb23af46106b33a0
# Parent  a348b1f1c04a9aa2fe05205d3026b1f9d530ed48
localrepo: make invalidate avoid invalidating store inside transaction (API)

Before this patch, invalidate() discards in-memory fncache changes,
even inside transaction scope.

Such changes should be written out at closing transaction. Otherwise,
fncache might overlook newly added files. A file overlooked by
fncache isn't accessible via store vfs, even if it actually exists in
store.

On the other hand, a non-existing file in fncache is less harmful,
because fncachestore always examines whether a file actually exists or
not before access. Therefore, discarding in-memory changes can be
safely omitted.

It is typical case that repo.invalidate() in streamclone is executed
inside nested transaction.

This patch makes invalidate() avoid invalidating store inside
transaction.

This patch focuses on describing only how invalidate() changes own
behavior according to activity of transaction. Describing other detail
of invalidate() in docstr will be done in another series, which
refactors invalidate*() functions.

Patch

diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -1246,6 +1246,13 @@  class localrepository(object):
             delattr(self.unfiltered(), 'dirstate')
 
     def invalidate(self, clearfilecache=False):
+        '''Invalidates both store and non-store parts other than dirstate
+
+        If a transaction is running, invalidation of store is omitted,
+        because discarding in-memory changes might cause inconsistency
+        (e.g. incomplete fncache causes unintentional failure, but
+        redundant one doesn't).
+        '''
         unfiltered = self.unfiltered() # all file caches are stored unfiltered
         for k in self._filecache.keys():
             # dirstate is invalidated separately in invalidatedirstate()
@@ -1259,7 +1266,11 @@  class localrepository(object):
             except AttributeError:
                 pass
         self.invalidatecaches()
-        self.store.invalidatecaches()
+        if not self.currenttransaction():
+            # TODO: Changing contents of store outside transaction
+            # causes inconsistency. We should make in-memory store
+            # changes detectable, and abort if changed.
+            self.store.invalidatecaches()
 
     def invalidateall(self):
         '''Fully invalidates both store and non-store parts, causing the