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/mod.rs | |
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/mod.rs')
-rw-r--r-- | vendor/gix-discover/src/upwards/mod.rs | 41 |
1 files changed, 30 insertions, 11 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()) { |