rhg: add support for share-safe
Differential Revision: https://phab.mercurial-scm.org/D9942
--- a/rust/hg-core/src/repo.rs Thu Jan 14 13:04:12 2021 +0100
+++ b/rust/hg-core/src/repo.rs Mon Feb 01 11:41:10 2021 +0100
@@ -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 {
--- a/rust/hg-core/src/requirements.rs Thu Jan 14 13:04:12 2021 +0100
+++ b/rust/hg-core/src/requirements.rs Mon Feb 01 11:41:10 2021 +0100
@@ -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";
--- a/tests/test-rhg.t Thu Jan 14 13:04:12 2021 +0100
+++ b/tests/test-rhg.t Mon Feb 01 11:41:10 2021 +0100
@@ -256,7 +256,7 @@
$ cd repo5
$ rhg files
- [252]
+ a
$ rhg cat -r 0 a
- [252]
+ a