diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:42 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:42 +0000 |
commit | 837b550238aa671a591ccf282dddeab29cadb206 (patch) | |
tree | 914b6b8862bace72bd3245ca184d374b08d8a672 /vendor/gix-discover/src/upwards | |
parent | Adding debian version 1.70.0+dfsg2-1. (diff) | |
download | rustc-837b550238aa671a591ccf282dddeab29cadb206.tar.xz rustc-837b550238aa671a591ccf282dddeab29cadb206.zip |
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/gix-discover/src/upwards')
-rw-r--r-- | vendor/gix-discover/src/upwards/mod.rs | 41 | ||||
-rw-r--r-- | vendor/gix-discover/src/upwards/types.rs | 15 |
2 files changed, 41 insertions, 15 deletions
diff --git a/vendor/gix-discover/src/upwards/mod.rs b/vendor/gix-discover/src/upwards/mod.rs index 8b041f443..87e6a18b4 100644 --- a/vendor/gix-discover/src/upwards/mod.rs +++ b/vendor/gix-discover/src/upwards/mod.rs @@ -4,6 +4,7 @@ pub use types::{Error, Options}; mod util; pub(crate) mod function { + use std::ffi::OsStr; use std::{borrow::Cow, path::Path}; use gix_sec::Trust; @@ -12,6 +13,7 @@ pub(crate) mod function { #[cfg(unix)] use crate::upwards::util::device_id; use crate::{ + is::git_with_metadata as is_git_with_metadata, is_git, upwards::util::{find_ceiling_height, shorten_path_with_cwd}, DOT_GIT_DIR, @@ -31,6 +33,7 @@ pub(crate) mod function { match_ceiling_dir_or_error, cross_fs, current_dir, + dot_git_only, }: Options<'_>, ) -> Result<(crate::repository::Path, Trust), Error> { // Normalize the path so that `Path::parent()` _actually_ gives @@ -80,6 +83,7 @@ pub(crate) mod function { let mut cursor = dir.clone().into_owned(); let mut current_height = 0; + let mut cursor_metadata = Some(dir_metadata); 'outer: loop { if max_height.map_or(false, |x| current_height > x) { return Err(Error::NoGitRepositoryWithinCeiling { @@ -91,13 +95,15 @@ pub(crate) mod function { #[cfg(unix)] if current_height != 0 && !cross_fs { - let metadata = if cursor.as_os_str().is_empty() { - Path::new(".") - } else { - cursor.as_ref() - } - .metadata() - .map_err(|_| Error::InaccessibleDirectory { path: cursor.clone() })?; + let metadata = cursor_metadata.take().map(Ok).unwrap_or_else(|| { + if cursor.as_os_str().is_empty() { + Path::new(".") + } else { + cursor.as_ref() + } + .metadata() + .map_err(|_| Error::InaccessibleDirectory { path: cursor.clone() }) + })?; if device_id(&metadata) != initial_device { return Err(Error::NoGitRepositoryWithinFs { @@ -105,13 +111,21 @@ pub(crate) mod function { limit: cursor.clone(), }); } + cursor_metadata = Some(metadata); } - for append_dot_git in &[false, true] { - if *append_dot_git { + let mut cursor_metadata_backup = None; + let started_as_dot_git = cursor.file_name() == Some(OsStr::new(DOT_GIT_DIR)); + let dir_manipulation = if dot_git_only { &[true] as &[_] } else { &[true, false] }; + for append_dot_git in dir_manipulation { + if *append_dot_git && !started_as_dot_git { cursor.push(DOT_GIT_DIR); + cursor_metadata_backup = cursor_metadata.take(); } - if let Ok(kind) = is_git(&cursor) { + if let Ok(kind) = match cursor_metadata.take() { + Some(metadata) => is_git_with_metadata(&cursor, metadata), + None => is_git(&cursor), + } { match filter_by_trust(&cursor)? { Some(trust) => { // TODO: test this more, it definitely doesn't always find the shortest path to a directory @@ -138,8 +152,13 @@ pub(crate) mod function { } } } - if *append_dot_git { + + // Usually `.git` (started_as_dot_git == true) will be a git dir, but if not we can quickly skip over it. + if *append_dot_git || started_as_dot_git { cursor.pop(); + if let Some(metadata) = cursor_metadata_backup.take() { + cursor_metadata = Some(metadata); + } } } if cursor.parent().map_or(false, |p| p.as_os_str().is_empty()) { diff --git a/vendor/gix-discover/src/upwards/types.rs b/vendor/gix-discover/src/upwards/types.rs index 52ce9db9c..d8fb19d49 100644 --- a/vendor/gix-discover/src/upwards/types.rs +++ b/vendor/gix-discover/src/upwards/types.rs @@ -10,15 +10,15 @@ pub enum Error { InvalidInput { directory: PathBuf }, #[error("Failed to access a directory, or path is not a directory: '{}'", .path.display())] InaccessibleDirectory { path: PathBuf }, - #[error("Could find a git repository in '{}' or in any of its parents", .path.display())] + #[error("Could not find a git repository in '{}' or in any of its parents", .path.display())] NoGitRepository { path: PathBuf }, - #[error("Could find a git repository in '{}' or in any of its parents within ceiling height of {}", .path.display(), .ceiling_height)] + #[error("Could not find a git repository in '{}' or in any of its parents within ceiling height of {}", .path.display(), .ceiling_height)] NoGitRepositoryWithinCeiling { path: PathBuf, ceiling_height: usize }, - #[error("Could find a git repository in '{}' or in any of its parents within device limits below '{}'", .path.display(), .limit.display())] + #[error("Could not find a git repository in '{}' or in any of its parents within device limits below '{}'", .path.display(), .limit.display())] NoGitRepositoryWithinFs { path: PathBuf, limit: PathBuf }, #[error("None of the passed ceiling directories prefixed the git-dir candidate, making them ineffective.")] NoMatchingCeilingDir, - #[error("Could find a trusted git repository in '{}' or in any of its parents, candidate at '{}' discarded", .path.display(), .candidate.display())] + #[error("Could not find a trusted git repository in '{}' or in any of its parents, candidate at '{}' discarded", .path.display(), .candidate.display())] NoTrustedGitRepository { path: PathBuf, candidate: PathBuf, @@ -53,6 +53,12 @@ pub struct Options<'a> { // TODO: test on Linux // TODO: Handle WASI once https://github.com/rust-lang/rust/issues/71213 is resolved pub cross_fs: bool, + /// If true, limit discovery to `.git` directories. + /// + /// This will fail to find typical bare repositories, but would find them if they happen to be named `.git`. + /// Use this option if repos with worktrees are the only kind of repositories you are interested in for + /// optimal discovery performance. + pub dot_git_only: bool, /// If set, the _current working directory_ (absolute path) to use when resolving relative paths. Note that /// that this is merely an optimization for those who discover a lot of repositories in the same process. /// @@ -67,6 +73,7 @@ impl Default for Options<'_> { ceiling_dirs: vec![], match_ceiling_dir_or_error: true, cross_fs: false, + dot_git_only: false, current_dir: None, } } |