rust: Fold find_root and check_requirements into Repo::find
Differential Revision: https://phab.mercurial-scm.org/D9906
--- a/rust/hg-core/src/config/config.rs Thu Jan 28 19:13:55 2021 +0100
+++ b/rust/hg-core/src/config/config.rs Thu Jan 28 20:31:42 2021 +0100
@@ -11,7 +11,7 @@
use crate::config::layer::{ConfigError, ConfigLayer, ConfigValue};
use std::path::PathBuf;
-use crate::operations::find_root;
+use crate::repo::Repo;
use crate::utils::files::read_whole_file;
/// Holds the config values for the current repository
@@ -76,10 +76,9 @@
/// Loads the local config. In a future version, this will also load the
/// `$HOME/.hgrc` and more to mirror the Python implementation.
- pub fn load() -> Result<Self, ConfigError> {
- let root = find_root().unwrap();
+ pub fn load_for_repo(repo: &Repo) -> Result<Self, ConfigError> {
Ok(Self::load_from_explicit_sources(vec![
- ConfigSource::AbsPath(root.join(".hg/hgrc")),
+ ConfigSource::AbsPath(repo.hg_vfs().join("hgrc")),
])?)
}
--- a/rust/hg-core/src/operations/find_root.rs Thu Jan 28 19:13:55 2021 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-use std::path::{Path, PathBuf};
-
-/// Error type for `find_root`
-#[derive(Debug)]
-pub enum FindRootError {
- /// Root of the repository has not been found
- /// Contains the current directory used by FindRoot
- RootNotFound(PathBuf),
- /// The current directory does not exists or permissions are insufficient
- /// to get access to it
- GetCurrentDirError(std::io::Error),
-}
-
-/// Find the root of the repository
-/// by searching for a .hg directory in the process’ current directory and its
-/// ancestors
-pub fn find_root() -> Result<PathBuf, FindRootError> {
- let current_dir = std::env::current_dir()
- .map_err(|e| FindRootError::GetCurrentDirError(e))?;
- Ok(find_root_from_path(¤t_dir)?.into())
-}
-
-/// Find the root of the repository
-/// by searching for a .hg directory in the given directory and its ancestors
-pub fn find_root_from_path(start: &Path) -> Result<&Path, FindRootError> {
- if start.join(".hg").exists() {
- return Ok(start);
- }
- for ancestor in start.ancestors() {
- if ancestor.join(".hg").exists() {
- return Ok(ancestor);
- }
- }
- Err(FindRootError::RootNotFound(start.into()))
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use std::fs;
- use tempfile;
-
- #[test]
- fn dot_hg_not_found() {
- let tmp_dir = tempfile::tempdir().unwrap();
- let path = tmp_dir.path();
-
- let err = find_root_from_path(&path).unwrap_err();
-
- // TODO do something better
- assert!(match err {
- FindRootError::RootNotFound(p) => p == path.to_path_buf(),
- _ => false,
- })
- }
-
- #[test]
- fn dot_hg_in_current_path() {
- let tmp_dir = tempfile::tempdir().unwrap();
- let root = tmp_dir.path();
- fs::create_dir_all(root.join(".hg")).unwrap();
-
- let result = find_root_from_path(&root).unwrap();
-
- assert_eq!(result, root)
- }
-
- #[test]
- fn dot_hg_in_parent() {
- let tmp_dir = tempfile::tempdir().unwrap();
- let root = tmp_dir.path();
- fs::create_dir_all(root.join(".hg")).unwrap();
-
- let directory = root.join("some/nested/directory");
- let result = find_root_from_path(&directory).unwrap();
-
- assert_eq!(result, root)
- }
-} /* tests */
--- a/rust/hg-core/src/operations/mod.rs Thu Jan 28 19:13:55 2021 +0100
+++ b/rust/hg-core/src/operations/mod.rs Thu Jan 28 20:31:42 2021 +0100
@@ -5,10 +5,8 @@
mod cat;
mod debugdata;
mod dirstate_status;
-mod find_root;
mod list_tracked_files;
pub use cat::cat;
pub use debugdata::{debug_data, DebugDataKind};
-pub use find_root::{find_root, find_root_from_path, FindRootError};
pub use list_tracked_files::Dirstate;
pub use list_tracked_files::{list_rev_tracked_files, FilesForRev};
--- a/rust/hg-core/src/repo.rs Thu Jan 28 19:13:55 2021 +0100
+++ b/rust/hg-core/src/repo.rs Thu Jan 28 20:31:42 2021 +0100
@@ -1,5 +1,4 @@
use crate::errors::{HgError, IoResultExt};
-use crate::operations::{find_root, FindRootError};
use crate::requirements;
use memmap::{Mmap, MmapOptions};
use std::path::{Path, PathBuf};
@@ -11,6 +10,15 @@
store: PathBuf,
}
+#[derive(Debug, derive_more::From)]
+pub enum RepoFindError {
+ NotFoundInCurrentDirectoryOrAncestors {
+ current_directory: PathBuf,
+ },
+ #[from]
+ Other(HgError),
+}
+
/// Filesystem access abstraction for the contents of a given "base" diretory
#[derive(Clone, Copy)]
pub(crate) struct Vfs<'a> {
@@ -18,24 +26,26 @@
}
impl Repo {
- /// Returns `None` if the given path doesn’t look like a repository
- /// (doesn’t contain a `.hg` sub-directory).
- pub fn for_path(root: impl Into<PathBuf>) -> Self {
- let working_directory = root.into();
- let dot_hg = working_directory.join(".hg");
- Self {
- store: dot_hg.join("store"),
- dot_hg,
- working_directory,
+ /// Search the current directory and its ancestores for a repository:
+ /// a working directory that contains a `.hg` sub-directory.
+ pub fn find() -> Result<Self, RepoFindError> {
+ let current_directory = crate::utils::current_dir()?;
+ // ancestors() is inclusive: it first yields `current_directory` as-is.
+ for ancestor in current_directory.ancestors() {
+ let dot_hg = ancestor.join(".hg");
+ if dot_hg.is_dir() {
+ let repo = Self {
+ store: dot_hg.join("store"),
+ dot_hg,
+ working_directory: ancestor.to_owned(),
+ };
+ requirements::check(&repo)?;
+ return Ok(repo);
+ }
}
- }
-
- pub fn find() -> Result<Self, FindRootError> {
- find_root().map(Self::for_path)
- }
-
- pub fn check_requirements(&self) -> Result<(), HgError> {
- requirements::check(self)
+ Err(RepoFindError::NotFoundInCurrentDirectoryOrAncestors {
+ current_directory,
+ })
}
pub fn working_directory_path(&self) -> &Path {
@@ -65,11 +75,15 @@
}
impl Vfs<'_> {
+ pub(crate) fn join(&self, relative_path: impl AsRef<Path>) -> PathBuf {
+ self.base.join(relative_path)
+ }
+
pub(crate) fn read(
&self,
relative_path: impl AsRef<Path>,
) -> Result<Vec<u8>, HgError> {
- let path = self.base.join(relative_path);
+ let path = self.join(relative_path);
std::fs::read(&path).for_file(&path)
}
--- a/rust/rhg/src/commands/cat.rs Thu Jan 28 19:13:55 2021 +0100
+++ b/rust/rhg/src/commands/cat.rs Thu Jan 28 20:31:42 2021 +0100
@@ -31,7 +31,6 @@
#[timed]
fn run(&self, ui: &Ui) -> Result<(), CommandError> {
let repo = Repo::find()?;
- repo.check_requirements()?;
let cwd = hg::utils::current_dir()?;
let mut files = vec![];
--- a/rust/rhg/src/commands/files.rs Thu Jan 28 19:13:55 2021 +0100
+++ b/rust/rhg/src/commands/files.rs Thu Jan 28 20:31:42 2021 +0100
@@ -48,7 +48,6 @@
impl<'a> Command for FilesCommand<'a> {
fn run(&self, ui: &Ui) -> Result<(), CommandError> {
let repo = Repo::find()?;
- repo.check_requirements()?;
if let Some(rev) = self.rev {
let files =
list_rev_tracked_files(&repo, rev).map_err(|e| (e, rev))?;
--- a/rust/rhg/src/error.rs Thu Jan 28 19:13:55 2021 +0100
+++ b/rust/rhg/src/error.rs Thu Jan 28 20:31:42 2021 +0100
@@ -1,8 +1,10 @@
use crate::ui::utf8_to_local;
use crate::ui::UiError;
-use hg::errors::{HgError, IoErrorContext};
-use hg::operations::FindRootError;
+use format_bytes::format_bytes;
+use hg::errors::HgError;
+use hg::repo::RepoFindError;
use hg::revlog::revlog::RevlogError;
+use hg::utils::files::get_bytes_from_path;
use std::convert::From;
/// The kind of command error
@@ -48,18 +50,18 @@
}
}
-impl From<FindRootError> for CommandError {
- fn from(err: FindRootError) -> Self {
- match err {
- FindRootError::RootNotFound(path) => CommandError::abort(format!(
- "no repository found in '{}' (.hg not found)!",
- path.display()
- )),
- FindRootError::GetCurrentDirError(error) => HgError::IoError {
- error,
- context: IoErrorContext::CurrentDir,
- }
- .into(),
+impl From<RepoFindError> for CommandError {
+ fn from(error: RepoFindError) -> Self {
+ match error {
+ RepoFindError::NotFoundInCurrentDirectoryOrAncestors {
+ current_directory,
+ } => CommandError::Abort {
+ message: format_bytes!(
+ b"no repository found in '{}' (.hg not found)!",
+ get_bytes_from_path(current_directory)
+ ),
+ },
+ RepoFindError::Other(error) => error.into(),
}
}
}
--- a/tests/test-rhg.t Thu Jan 28 19:13:55 2021 +0100
+++ b/tests/test-rhg.t Thu Jan 28 20:31:42 2021 +0100
@@ -153,13 +153,7 @@
[252]
$ rhg debugrequirements
- dotencode
- fncache
- generaldelta
- revlogv1
- sparserevlog
- store
- indoor-pool
+ [252]
$ echo -e '\xFF' >> .hg/requires
$ rhg debugrequirements