summaryrefslogtreecommitdiffstats
path: root/vendor/gix-discover/src/upwards/mod.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:42 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:42 +0000
commit837b550238aa671a591ccf282dddeab29cadb206 (patch)
tree914b6b8862bace72bd3245ca184d374b08d8a672 /vendor/gix-discover/src/upwards/mod.rs
parentAdding debian version 1.70.0+dfsg2-1. (diff)
downloadrustc-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.rs41
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()) {