Patchwork D9942: rhg: add support for share-safe

login
register
mail settings
Submitter phabricator
Date Feb. 1, 2021, 6:41 p.m.
Message ID <differential-rev-PHID-DREV-vtojl3jqq2t74xwvmdb4-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/48252/
State Superseded
Headers show

Comments

phabricator - Feb. 1, 2021, 6:41 p.m.
SimonSapin created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REPOSITORY
  rHG Mercurial

BRANCH
  default

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

AFFECTED FILES
  rust/hg-core/src/repo.rs
  rust/hg-core/src/requirements.rs
  tests/test-rhg.t

CHANGE DETAILS




To: SimonSapin, #hg-reviewers
Cc: mercurial-patches, mercurial-devel

Patch

diff --git a/tests/test-rhg.t b/tests/test-rhg.t
--- a/tests/test-rhg.t
+++ b/tests/test-rhg.t
@@ -256,7 +256,7 @@ 
 
   $ cd repo5
   $ rhg files
-  [252]
+  a
   $ rhg cat -r 0 a
-  [252]
+  a
 
diff --git a/rust/hg-core/src/requirements.rs b/rust/hg-core/src/requirements.rs
--- a/rust/hg-core/src/requirements.rs
+++ b/rust/hg-core/src/requirements.rs
@@ -22,6 +22,10 @@ 
         .collect()
 }
 
+pub(crate) fn load(hg_vfs: Vfs) -> Result<HashSet<String>, HgError> {
+    parse(&hg_vfs.read("requires")?)
+}
+
 pub(crate) fn load_if_exists(hg_vfs: Vfs) -> Result<HashSet<String>, HgError> {
     if let Some(bytes) = hg_vfs.read("requires").io_not_found_as_none()? {
         parse(&bytes)
@@ -58,6 +62,7 @@ 
     "generaldelta",
     "revlogv1",
     SHARED_REQUIREMENT,
+    SHARESAFE_REQUIREMENT,
     SPARSEREVLOG_REQUIREMENT,
     RELATIVE_SHARED_REQUIREMENT,
     "store",
@@ -130,4 +135,4 @@ 
 /// store and working copy requirements i.e. both `.hg/requires` and
 /// `.hg/store/requires` are present.
 #[allow(unused)]
-pub(crate) const SHARESAFE_REQUIREMENT: &str = "exp-sharesafe";
+pub(crate) const SHARESAFE_REQUIREMENT: &str = "share-safe";
diff --git a/rust/hg-core/src/repo.rs b/rust/hg-core/src/repo.rs
--- a/rust/hg-core/src/repo.rs
+++ b/rust/hg-core/src/repo.rs
@@ -47,15 +47,34 @@ 
     /// To be called after checking that `.hg` is a sub-directory
     fn new_at_path(working_directory: PathBuf) -> Result<Self, HgError> {
         let dot_hg = working_directory.join(".hg");
+
         let hg_vfs = Vfs { base: &dot_hg };
-        let reqs = requirements::load_if_exists(hg_vfs)?;
+        let mut reqs = requirements::load_if_exists(hg_vfs)?;
         let relative =
             reqs.contains(requirements::RELATIVE_SHARED_REQUIREMENT);
         let shared =
             reqs.contains(requirements::SHARED_REQUIREMENT) || relative;
+
+        // From `mercurial/localrepo.py`:
+        //
+        // if .hg/requires contains the sharesafe requirement, it means
+        // there exists a `.hg/store/requires` too and we should read it
+        // NOTE: presence of SHARESAFE_REQUIREMENT imply that store requirement
+        // is present. We never write SHARESAFE_REQUIREMENT for a repo if store
+        // is not present, refer checkrequirementscompat() for that
+        //
+        // However, if SHARESAFE_REQUIREMENT is not present, it means that the
+        // repository was shared the old way. We check the share source
+        // .hg/requires for SHARESAFE_REQUIREMENT to detect whether the
+        // current repository needs to be reshared
+        let share_safe = reqs.contains(requirements::SHARESAFE_REQUIREMENT);
+
         let store_path;
         if !shared {
             store_path = dot_hg.join("store");
+            if share_safe {
+                reqs.extend(requirements::load(Vfs { base: &store_path })?);
+            }
         } else {
             let bytes = hg_vfs.read("sharedpath")?;
             let mut shared_path = get_path_from_bytes(&bytes).to_owned();
@@ -70,6 +89,17 @@ 
             }
 
             store_path = shared_path.join("store");
+
+            let source_is_share_safe =
+                requirements::load(Vfs { base: &shared_path })?
+                    .contains(requirements::SHARESAFE_REQUIREMENT);
+
+            // TODO: support for `share.safe-mismatch.*` config
+            if share_safe && !source_is_share_safe {
+                return Err(HgError::unsupported("share-safe downgrade"));
+            } else if source_is_share_safe && !share_safe {
+                return Err(HgError::unsupported("share-safe upgrade"));
+            }
         }
 
         let repo = Self {