Patchwork [01,of,10,v2] localrepo: don't refresh filecache entries that aren't in __dict__

login
register
mail settings
Submitter Idan Kamara
Date Jan. 10, 2013, 10:10 p.m.
Message ID <65504f14b760ed55e986.1357855848@idan>
Download mbox | patch
Permalink /patch/530/
State Accepted
Commit cfeab932cff7381a5282066d86b0282ed8f5537c
Delegated to: Kevin Bullock
Headers show

Comments

Idan Kamara - Jan. 10, 2013, 10:10 p.m.
# HG changeset patch
# User Idan Kamara <idankk86@gmail.com>
# Date 1355692382 -7200
# Node ID 65504f14b760ed55e9869eba44e0556b43ed8454
# Parent  a74101cd6965c33ef35e28cb69512b72c80fdc2f
localrepo: don't refresh filecache entries that aren't in __dict__

We call invalidate to remove properties from __dict__ because they're possibly
outdated and we'd like to check for a new version. Next time the property is accessed
the filecache mechanism checks the current stat info with the one recorded at the
last time the property was read, if they're different it recreates the property.

Previously we refreshed the stat info on all properties in the filecache when
the lock is released, including properties that are missing from __dict__. This
is a problem because:

  l = repo.lock()
  repo.P          # stat info S for P is recorded in _filecache
  <changes are made to repo.P indirectly, e.g. underlying file is replaced>
                  # P's new stat info = S'
  l.release()     # filecache refreshes, records S' as P's stat info

At this point our filecache contains P with stat info S', but P's version is
from S, which is outdated.

The above happens during _rollback and strip. Currently we're wiping the filecache
and forcing everything to reload from scratch which works but isn't the right
solution.

Patch

diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -1015,7 +1015,7 @@ 
             if hasunfilteredcache(self, '_phasecache'):
                 self._phasecache.write()
             for k, ce in self._filecache.items():
-                if k == 'dirstate':
+                if k == 'dirstate' or k not in self.__dict__:
                     continue
                 ce.refresh()