rust/hg-core/src/repo.rs
changeset 46486 d7685105e504
parent 46485 f031fe1c6ede
child 46503 d8730ff51d5a
--- a/rust/hg-core/src/repo.rs	Thu Feb 04 14:29:47 2021 +0100
+++ b/rust/hg-core/src/repo.rs	Thu Feb 04 15:04:53 2021 +0100
@@ -1,4 +1,4 @@
-use crate::config::Config;
+use crate::config::{Config, ConfigError, ConfigParseError};
 use crate::errors::{HgError, IoResultExt};
 use crate::requirements;
 use crate::utils::files::get_path_from_bytes;
@@ -12,17 +12,29 @@
     dot_hg: PathBuf,
     store: PathBuf,
     requirements: HashSet<String>,
+    config: Config,
 }
 
 #[derive(Debug, derive_more::From)]
-pub enum RepoFindError {
-    NotFoundInCurrentDirectoryOrAncestors {
+pub enum RepoError {
+    NotFound {
         current_directory: PathBuf,
     },
     #[from]
+    ConfigParseError(ConfigParseError),
+    #[from]
     Other(HgError),
 }
 
+impl From<ConfigError> for RepoError {
+    fn from(error: ConfigError) -> Self {
+        match error {
+            ConfigError::Parse(error) => error.into(),
+            ConfigError::Other(error) => error.into(),
+        }
+    }
+}
+
 /// Filesystem access abstraction for the contents of a given "base" diretory
 #[derive(Clone, Copy)]
 pub(crate) struct Vfs<'a> {
@@ -32,7 +44,7 @@
 impl Repo {
     /// Search the current directory and its ancestores for a repository:
     /// a working directory that contains a `.hg` sub-directory.
-    pub fn find(config: &Config) -> Result<Self, RepoFindError> {
+    pub fn find(config: &Config) -> Result<Self, RepoError> {
         let current_directory = crate::utils::current_dir()?;
         // ancestors() is inclusive: it first yields `current_directory` as-is.
         for ancestor in current_directory.ancestors() {
@@ -40,18 +52,20 @@
                 return Ok(Self::new_at_path(ancestor.to_owned(), config)?);
             }
         }
-        Err(RepoFindError::NotFoundInCurrentDirectoryOrAncestors {
-            current_directory,
-        })
+        Err(RepoError::NotFound { current_directory })
     }
 
     /// To be called after checking that `.hg` is a sub-directory
     fn new_at_path(
         working_directory: PathBuf,
         config: &Config,
-    ) -> Result<Self, HgError> {
+    ) -> Result<Self, RepoError> {
         let dot_hg = working_directory.join(".hg");
 
+        let mut repo_config_files = Vec::new();
+        repo_config_files.push(dot_hg.join("hgrc"));
+        repo_config_files.push(dot_hg.join("hgrc-not-shared"));
+
         let hg_vfs = Vfs { base: &dot_hg };
         let mut reqs = requirements::load_if_exists(hg_vfs)?;
         let relative =
@@ -89,7 +103,8 @@
                 return Err(HgError::corrupted(format!(
                     ".hg/sharedpath points to nonexistent directory {}",
                     shared_path.display()
-                )));
+                ))
+                .into());
             }
 
             store_path = shared_path.join("store");
@@ -99,12 +114,15 @@
                     .contains(requirements::SHARESAFE_REQUIREMENT);
 
             if share_safe && !source_is_share_safe {
-                return Err(match config.get(b"safe-mismatch", b"source-not-safe") {
+                return Err(match config
+                    .get(b"safe-mismatch", b"source-not-safe")
+                {
                     Some(b"abort") | None => HgError::abort(
-                        "share source does not support share-safe requirement"
+                        "share source does not support share-safe requirement",
                     ),
-                    _ => HgError::unsupported("share-safe downgrade")
-                });
+                    _ => HgError::unsupported("share-safe downgrade"),
+                }
+                .into());
             } else if source_is_share_safe && !share_safe {
                 return Err(
                     match config.get(b"safe-mismatch", b"source-safe") {
@@ -113,16 +131,24 @@
                             functionality while the current share does not",
                         ),
                         _ => HgError::unsupported("share-safe upgrade"),
-                    },
+                    }
+                    .into(),
                 );
             }
+
+            if share_safe {
+                repo_config_files.insert(0, shared_path.join("hgrc"))
+            }
         }
 
+        let repo_config = config.combine_with_repo(&repo_config_files)?;
+
         let repo = Self {
             requirements: reqs,
             working_directory,
             store: store_path,
             dot_hg,
+            config: repo_config,
         };
 
         requirements::check(&repo)?;
@@ -138,6 +164,10 @@
         &self.requirements
     }
 
+    pub fn config(&self) -> &Config {
+        &self.config
+    }
+
     /// For accessing repository files (in `.hg`), except for the store
     /// (`.hg/store`).
     pub(crate) fn hg_vfs(&self) -> Vfs<'_> {