[Updated] D8633: share: introduce config option to store requires in .hg/store

pulkit (Pulkit Goyal) phabricator at mercurial-scm.org
Mon Jun 22 09:37:34 UTC 2020


Herald added a reviewer: durin42.
pulkit edited the summary of this revision.
pulkit updated this revision to Diff 21677.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D8633?vs=21636&id=21677

BRANCH
  default

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D8633/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D8633

AFFECTED FILES
  mercurial/configitems.py
  mercurial/localrepo.py
  mercurial/store.py
  tests/test-journal-share.t
  tests/test-narrow-share.t
  tests/test-remotefilelog-share.t
  tests/test-share-bookmarks.t
  tests/test-share-safe.t
  tests/test-share.t

CHANGE DETAILS

diff --git a/tests/test-share.t b/tests/test-share.t
--- a/tests/test-share.t
+++ b/tests/test-share.t
@@ -1,3 +1,10 @@
+#testcases safe normal
+
+#if safe
+  $ echo "[format]"         >> $HGRCPATH
+  $ echo "exp-share-safe = True" >> $HGRCPATH
+#endif
+
   $ echo "[extensions]"      >> $HGRCPATH
   $ echo "share = "          >> $HGRCPATH
 
diff --git a/tests/test-share-safe.t b/tests/test-share-safe.t
new file mode 100644
--- /dev/null
+++ b/tests/test-share-safe.t
@@ -0,0 +1,69 @@
+setup
+
+  $ cat >> $HGRCPATH <<EOF
+  > [extensions]
+  > share =
+  > [format]
+  > exp-share-safe = True
+  > EOF
+
+prepare source repo
+
+  $ hg init source
+  $ cd source
+  $ cat .hg/requires
+  exp-sharesafe
+  $ cat .hg/store/requires
+  dotencode
+  fncache
+  generaldelta
+  revlogv1
+  sparserevlog
+  store
+  $ hg debugrequirements
+  dotencode
+  exp-sharesafe
+  fncache
+  generaldelta
+  revlogv1
+  sparserevlog
+  store
+
+  $ echo a > a
+  $ hg ci -Aqm "added a"
+  $ echo b > b
+  $ hg ci -Aqm "added b"
+  $ cd ..
+
+Create a shared repo and check the requirements are shared and read correctly
+  $ hg share source shared1
+  updating working directory
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ cd shared1
+  $ cat .hg/requires
+  exp-sharesafe
+  shared
+
+  $ hg debugrequirements -R ../source
+  dotencode
+  exp-sharesafe
+  fncache
+  generaldelta
+  revlogv1
+  sparserevlog
+  store
+
+  $ hg debugrequirements
+  dotencode
+  exp-sharesafe
+  fncache
+  generaldelta
+  revlogv1
+  shared
+  sparserevlog
+  store
+
+  $ echo c > c
+  $ hg ci -Aqm "added c"
+
+  $ hg unshare
diff --git a/tests/test-share-bookmarks.t b/tests/test-share-bookmarks.t
--- a/tests/test-share-bookmarks.t
+++ b/tests/test-share-bookmarks.t
@@ -1,4 +1,10 @@
 #testcases vfs svfs
+#testcases safe normal
+
+#if safe
+  $ echo "[format]"         >> $HGRCPATH
+  $ echo "exp-share-safe = True" >> $HGRCPATH
+#endif
 
   $ echo "[extensions]"      >> $HGRCPATH
   $ echo "share = "          >> $HGRCPATH
diff --git a/tests/test-remotefilelog-share.t b/tests/test-remotefilelog-share.t
--- a/tests/test-remotefilelog-share.t
+++ b/tests/test-remotefilelog-share.t
@@ -1,5 +1,12 @@
 #require no-windows
 
+#testcases safe normal
+
+#if safe
+  $ echo "[format]"         >> $HGRCPATH
+  $ echo "exp-share-safe = True" >> $HGRCPATH
+#endif
+
   $ . "$TESTDIR/remotefilelog-library.sh"
 
   $ cat >> $HGRCPATH <<EOF
diff --git a/tests/test-narrow-share.t b/tests/test-narrow-share.t
--- a/tests/test-narrow-share.t
+++ b/tests/test-narrow-share.t
@@ -1,4 +1,10 @@
 #testcases flat tree
+#testcases safe normal
+
+#if safe
+  $ echo "[format]"         >> $HGRCPATH
+  $ echo "exp-share-safe = True" >> $HGRCPATH
+#endif
 
   $ . "$TESTDIR/narrow-library.sh"
 
diff --git a/tests/test-journal-share.t b/tests/test-journal-share.t
--- a/tests/test-journal-share.t
+++ b/tests/test-journal-share.t
@@ -1,3 +1,10 @@
+#testcases safe normal
+
+#if safe
+  $ echo "[format]"         >> $HGRCPATH
+  $ echo "exp-share-safe = True" >> $HGRCPATH
+#endif
+
 Journal extension test: tests the share extension support
 
   $ cat >> testmocks.py << EOF
diff --git a/mercurial/store.py b/mercurial/store.py
--- a/mercurial/store.py
+++ b/mercurial/store.py
@@ -375,7 +375,7 @@
 
 _data = (
     b'bookmarks narrowspec data meta 00manifest.d 00manifest.i'
-    b' 00changelog.d 00changelog.i phaseroots obsstore'
+    b' 00changelog.d 00changelog.i phaseroots obsstore requires'
 )
 
 
@@ -447,7 +447,7 @@
             yield x
 
     def copylist(self):
-        return [b'requires'] + _data.split()
+        return _data.split()
 
     def write(self, tr):
         pass
@@ -687,7 +687,7 @@
     def copylist(self):
         d = (
             b'bookmarks narrowspec data meta dh fncache phaseroots obsstore'
-            b' 00manifest.d 00manifest.i 00changelog.d 00changelog.i'
+            b' 00manifest.d 00manifest.i 00changelog.d 00changelog.i requires'
         )
         return [b'requires', b'00changelog.i'] + [
             b'store/' + f for f in d.split()
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -449,6 +449,11 @@
 # The repository use persistent nodemap for the changelog and the manifest.
 NODEMAP_REQUIREMENT = b'persistent-nodemap'
 
+# A repository with share implemented safely. The repository has different
+# store and working copy requirements i.e. both `.hg/requires` and
+# `.hg/store/requires` are present.
+SHARESAFE_REQUIREMENT = b'exp-sharesafe'
+
 # Functions receiving (ui, features) that extensions can register to impact
 # the ability to load repositories with custom requirements. Only
 # functions defined in loaded extensions are called.
@@ -529,6 +534,26 @@
             raise
         requirements = set()
 
+    # if .hg/requires contains the exp-sharesafe requirement, it means
+    # there exists a `.hg/store/requires` too and we should read it
+    # TODO: make this code more stricter by checking whether store exists
+    # and other checks
+    if SHARESAFE_REQUIREMENT in requirements:
+        if hgvfs.exists(b'sharedpath'):
+            # This is a shared repo
+            sharedpath = hgvfs.read(b'sharedpath').rstrip(b'\n')
+            if b'relshared' in requirements:
+                sharedpath = hgvfs.join(sharedpath)
+            storevfs = vfsmod.vfs(vfsmod.vfs(sharedpath).join(b'store'))
+        else:
+            storevfs = vfsmod.vfs(hgvfs.join(b'store'), cacheaudited=True)
+        try:
+            store_requirements = set(storevfs.read(b'requires').splitlines())
+            requirements |= store_requirements
+        except IOError as e:
+            if e.errno != errno.ENOENT:
+                raise
+
     # The .hg/hgrc file may load extensions or contain config options
     # that influence repository construction. Attempt to load it and
     # process any new extensions that it may have pulled in.
@@ -1034,6 +1059,7 @@
         SPARSEREVLOG_REQUIREMENT,
         NODEMAP_REQUIREMENT,
         bookmarks.BOOKMARKS_IN_STORE_REQUIREMENT,
+        SHARESAFE_REQUIREMENT,
     }
     _basesupported = supportedformats | {
         b'store',
@@ -1303,7 +1329,12 @@
         self._writerequirements()
 
     def _writerequirements(self):
-        scmutil.writerequires(self.vfs, self.requirements)
+        if SHARESAFE_REQUIREMENT in self.requirements:
+            with self.lock():
+                scmutil.writerequires(self.svfs, self.requirements)
+            scmutil.writerequires(self.vfs, set([SHARESAFE_REQUIREMENT]))
+        else:
+            scmutil.writerequires(self.vfs, self.requirements)
 
     # Don't cache auditor/nofsauditor, or you'll end up with reference cycle:
     # self -> auditor -> self._checknested -> self
@@ -3638,6 +3669,11 @@
     if ui.configbool(b'format', b'use-persistent-nodemap'):
         requirements.add(NODEMAP_REQUIREMENT)
 
+    # if share-safe is enabled, let's create the new repository with the new
+    # requirement
+    if ui.configbool(b'format', b'exp-share-safe'):
+        requirements.add(SHARESAFE_REQUIREMENT)
+
     return requirements
 
 
@@ -3761,7 +3797,20 @@
             b'layout',
         )
 
-    scmutil.writerequires(hgvfs, requirements)
+    if SHARESAFE_REQUIREMENT in requirements and b'store' in requirements:
+        if b'sharedrepo' in createopts:
+            req = set([b'shared', SHARESAFE_REQUIREMENT])
+            if b'relshared' in requirements:
+                req.add(b'relshared')
+            scmutil.writerequires(hgvfs, req)
+        else:
+            scmutil.writerequires(hgvfs, set([SHARESAFE_REQUIREMENT]))
+            storevfs = vfsmod.vfs(hgvfs.join(b'store'), cacheaudited=True)
+            scmutil.writerequires(
+                storevfs, requirements - set([SHARESAFE_REQUIREMENT])
+            )
+    else:
+        scmutil.writerequires(hgvfs, requirements)
 
     # Write out file telling readers where to find the shared store.
     if b'sharedrepo' in createopts:
diff --git a/mercurial/configitems.py b/mercurial/configitems.py
--- a/mercurial/configitems.py
+++ b/mercurial/configitems.py
@@ -781,6 +781,9 @@
     b'format', b'exp-use-side-data', default=False, experimental=True,
 )
 coreconfigitem(
+    b'format', b'exp-share-safe', default=False, experimental=True,
+)
+coreconfigitem(
     b'format', b'internal-phase', default=False, experimental=True,
 )
 coreconfigitem(



To: pulkit, #hg-reviewers, durin42
Cc: mercurial-patches
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mercurial-scm.org/pipermail/mercurial-patches/attachments/20200622/050026f6/attachment-0002.html>


More information about the Mercurial-patches mailing list