Patchwork [5,of,7] dirstate: add identity information to detect simultaneous changing in storage

login
register
mail settings
Submitter Katsunori FUJIWARA
Date June 9, 2017, 4:08 a.m.
Message ID <cbeddc126d25bff1adc2.1496981305@speaknoevil>
Download mbox | patch
Permalink /patch/21265/
State Accepted
Headers show

Comments

Katsunori FUJIWARA - June 9, 2017, 4:08 a.m.
# HG changeset patch
# User FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
# Date 1496981268 -32400
#      Fri Jun 09 13:07:48 2017 +0900
# Node ID cbeddc126d25bff1adc257a2ec9938763a449a95
# Parent  c14fcdcf528768538d1557b2ce0905db4c91bb85
dirstate: add identity information to detect simultaneous changing in storage

This identity is used to examine whether dirstate is simultaneously
changed in storage after previous caching (see issue5584 for detail).

util.cachestat can't be used for this purpose, because it has no
valuable information on Windows.

On the other hand, util.filestat can detect changing dirstate in
storage certainly, regardless of platforms.

    https://www.mercurial-scm.org/wiki/ExactCacheValidationPlan

Strictly speaking, if underlying filesystem doesn't support
ctime/mtime, util.filestat can't detect simultaneous changing in
storage as expected. But simultaneous changing on such (very rare)
platform can't be detected regardless of this patch series.

Therefore, util.filestat should be reasonable identity for almost all
usecases.

Patch

diff --git a/mercurial/dirstate.py b/mercurial/dirstate.py
--- a/mercurial/dirstate.py
+++ b/mercurial/dirstate.py
@@ -159,6 +159,11 @@  class dirstate(object):
         return self._copymap
 
     @propertycache
+    def _identity(self):
+        self._read()
+        return self._identity
+
+    @propertycache
     def _nonnormalset(self):
         nonnorm, otherparents = nonnormalentries(self._map)
         self._otherparentset = otherparents
@@ -426,6 +431,8 @@  class dirstate(object):
     def _read(self):
         self._map = {}
         self._copymap = {}
+        # ignore HG_PENDING because identity is used only for writing
+        self._identity = util.filestat(self._opener.join(self._filename))
         try:
             fp = self._opendirstatefile()
             try:
@@ -476,7 +483,8 @@  class dirstate(object):
         rereads the dirstate. Use localrepo.invalidatedirstate() if you want to
         check whether the dirstate has changed before rereading it.'''
 
-        for a in ("_map", "_copymap", "_filefoldmap", "_dirfoldmap", "_branch",
+        for a in ("_map", "_copymap", "_identity",
+                  "_filefoldmap", "_dirfoldmap", "_branch",
                   "_pl", "_dirs", "_ignore", "_nonnormalset",
                   "_otherparentset"):
             if a in self.__dict__:
@@ -741,6 +749,14 @@  class dirstate(object):
 
         self._dirty = True
 
+    def identity(self):
+        '''Return identity of dirstate itself to detect changing in storage
+
+        If identity of previous dirstate is equal to this, writing
+        changes based on the former dirstate out can keep consistency.
+        '''
+        return self._identity
+
     def write(self, tr):
         if not self._dirty:
             return