localrepo: resolve store and cachevfs in makelocalrepository()
authorGregory Szorc <gregory.szorc@gmail.com>
Wed, 12 Sep 2018 15:05:51 -0700
changeset 39697 98ca9078807a
parent 39696 9de1a1c83cd7
child 39698 f44187605315
localrepo: resolve store and cachevfs in makelocalrepository() This is mostly a code move and refactor. One change is that we now explicitly look for requirements indicating a share is being used rather than blindly try to read from .hg/sharedpath. Requirements *should* be all that is necessary to dictate high-level behavior and I'm not sure why the previous code was doing what it was. The previous code has been in place since 87d1fd40f57e (authored in 2009). And the commit immediately after that (971e38a9344b) introduced ``hg.share()`` and always wrote the ``shared`` requirement. And as far as I can tell, every revision of ``hg.share()`` since has written either the ``shared`` or ``relshared`` requirement. So I'm pretty sure we don't need to maintain BC by always looking for and honoring the ``.hg/sharedpath`` file even if a requirement isn't present. .. bc:: A repository will no longer use shared storage if it has a ``.hg/sharedpath`` file but no entry in ``.hg/requires`` saying it is shared. This change should not have any end-user impact, as all shared repos should have a ``.hg/requires`` file indicating this. Differential Revision: https://phab.mercurial-scm.org/D4573
mercurial/localrepo.py
--- a/mercurial/localrepo.py	Wed Sep 12 13:10:45 2018 -0700
+++ b/mercurial/localrepo.py	Wed Sep 12 15:05:51 2018 -0700
@@ -56,7 +56,7 @@
     revsetlang,
     scmutil,
     sparse,
-    store,
+    store as storemod,
     subrepoutil,
     tags as tagsmod,
     transaction,
@@ -454,6 +454,40 @@
     # At this point, we know we should be capable of opening the repository.
     # Now get on with doing that.
 
+    # The "store" part of the repository holds versioned data. How it is
+    # accessed is determined by various requirements. The ``shared`` or
+    # ``relshared`` requirements indicate the store lives in the path contained
+    # in the ``.hg/sharedpath`` file. This is an absolute path for
+    # ``shared`` and relative to ``.hg/`` for ``relshared``.
+    if b'shared' in requirements or b'relshared' in requirements:
+        sharedpath = hgvfs.read(b'sharedpath').rstrip(b'\n')
+        if b'relshared' in requirements:
+            sharedpath = hgvfs.join(sharedpath)
+
+        sharedvfs = vfsmod.vfs(sharedpath, realpath=True)
+
+        if not sharedvfs.exists():
+            raise error.RepoError(_(b'.hg/sharedpath points to nonexistent '
+                                    b'directory %s') % sharedvfs.base)
+
+        storebasepath = sharedvfs.base
+        cachepath = sharedvfs.join(b'cache')
+    else:
+        storebasepath = hgvfs.base
+        cachepath = hgvfs.join(b'cache')
+
+    # The store has changed over time and the exact layout is dictated by
+    # requirements. The store interface abstracts differences across all
+    # of them.
+    store = storemod.store(requirements, storebasepath,
+                           lambda base: vfsmod.vfs(base, cacheaudited=True))
+
+    hgvfs.createmode = store.createmode
+
+    # The cache vfs is used to manage cache files.
+    cachevfs = vfsmod.vfs(cachepath, cacheaudited=True)
+    cachevfs.createmode = store.createmode
+
     return localrepository(
         baseui=baseui,
         ui=ui,
@@ -462,6 +496,9 @@
         hgvfs=hgvfs,
         requirements=requirements,
         supportedrequirements=supportedrequirements,
+        sharedpath=storebasepath,
+        store=store,
+        cachevfs=cachevfs,
         intents=intents)
 
 def gathersupportedrequirements(ui):
@@ -581,7 +618,8 @@
     }
 
     def __init__(self, baseui, ui, origroot, wdirvfs, hgvfs, requirements,
-                 supportedrequirements, intents=None):
+                 supportedrequirements, sharedpath, store, cachevfs,
+                 intents=None):
         """Create a new local repository instance.
 
         Most callers should use ``hg.repository()``, ``localrepo.instance()``,
@@ -612,6 +650,17 @@
            ``set`` of bytestrings representing repository requirements that we
            know how to open. May be a supetset of ``requirements``.
 
+        sharedpath
+           ``bytes`` Defining path to storage base directory. Points to a
+           ``.hg/`` directory somewhere.
+
+        store
+           ``store.basicstore`` (or derived) instance providing access to
+           versioned storage.
+
+        cachevfs
+           ``vfs.vfs`` used for cache files.
+
         intents
            ``set`` of system strings indicating what this repo will be used
            for.
@@ -627,12 +676,11 @@
         self.path = hgvfs.base
         self.requirements = requirements
         self.supported = supportedrequirements
+        self.sharedpath = sharedpath
+        self.store = store
+        self.cachevfs = cachevfs
 
         self.filtername = None
-        # svfs: usually rooted at .hg/store, used to access repository history
-        # If this is a shared repository, this vfs may point to another
-        # repository's .hg/store directory.
-        self.svfs = None
 
         if (self.ui.configbool('devel', 'all-warnings') or
             self.ui.configbool('devel', 'check-locks')):
@@ -644,32 +692,9 @@
 
         color.setup(self.ui)
 
-        cachepath = self.vfs.join('cache')
-        self.sharedpath = self.path
-        try:
-            sharedpath = self.vfs.read("sharedpath").rstrip('\n')
-            if 'relshared' in self.requirements:
-                sharedpath = self.vfs.join(sharedpath)
-            vfs = vfsmod.vfs(sharedpath, realpath=True)
-            cachepath = vfs.join('cache')
-            s = vfs.base
-            if not vfs.exists():
-                raise error.RepoError(
-                    _('.hg/sharedpath points to nonexistent directory %s') % s)
-            self.sharedpath = s
-        except IOError as inst:
-            if inst.errno != errno.ENOENT:
-                raise
-
-        self.store = store.store(
-            self.requirements, self.sharedpath,
-            lambda base: vfsmod.vfs(base, cacheaudited=True))
         self.spath = self.store.path
         self.svfs = self.store.vfs
         self.sjoin = self.store.join
-        self.vfs.createmode = self.store.createmode
-        self.cachevfs = vfsmod.vfs(cachepath, cacheaudited=True)
-        self.cachevfs.createmode = self.store.createmode
         if (self.ui.configbool('devel', 'all-warnings') or
             self.ui.configbool('devel', 'check-locks')):
             if util.safehasattr(self.svfs, 'vfs'): # this is filtervfs