1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
use std::path::{Path, PathBuf};
use crate::DOT_GIT_DIR;
pub(crate) fn shorten_path_with_cwd(cursor: PathBuf, cwd: &Path) -> PathBuf {
fn comp_len(c: std::path::Component<'_>) -> usize {
use std::path::Component::*;
match c {
Prefix(p) => p.as_os_str().len(),
CurDir => 1,
ParentDir => 2,
Normal(p) => p.len(),
RootDir => 1,
}
}
debug_assert_eq!(cursor.file_name().and_then(std::ffi::OsStr::to_str), Some(DOT_GIT_DIR));
let parent = cursor.parent().expect(".git appended");
cwd.strip_prefix(parent)
.ok()
.and_then(|path_relative_to_cwd| {
let relative_path_components = path_relative_to_cwd.components().count();
let current_component_len = cursor.components().map(comp_len).sum::<usize>();
(relative_path_components * "..".len() < current_component_len).then(|| {
std::iter::repeat("..")
.take(relative_path_components)
.chain(Some(DOT_GIT_DIR))
.collect()
})
})
.unwrap_or(cursor)
}
/// Find the number of components parenting the `search_dir` before the first directory in `ceiling_dirs`.
/// `search_dir` needs to be normalized, and we normalize every ceiling as well.
pub(crate) fn find_ceiling_height(search_dir: &Path, ceiling_dirs: &[PathBuf], cwd: &Path) -> Option<usize> {
if ceiling_dirs.is_empty() {
return None;
}
let search_realpath;
let search_dir = if search_dir.is_absolute() {
search_dir
} else {
search_realpath = gix_path::realpath_opts(search_dir, cwd, gix_path::realpath::MAX_SYMLINKS).ok()?;
search_realpath.as_path()
};
ceiling_dirs
.iter()
.filter_map(|ceiling_dir| {
#[cfg(windows)]
let ceiling_dir = dunce::simplified(ceiling_dir);
let mut ceiling_dir = gix_path::normalize(ceiling_dir.into(), cwd)?;
if !ceiling_dir.is_absolute() {
ceiling_dir = gix_path::normalize(cwd.join(ceiling_dir.as_ref()).into(), cwd)?;
}
search_dir
.strip_prefix(ceiling_dir.as_ref())
.ok()
.map(|path_relative_to_ceiling| path_relative_to_ceiling.components().count())
.filter(|height| *height > 0)
})
.min()
}
/// Returns the device ID of the directory.
#[cfg(target_os = "linux")]
pub(crate) fn device_id(m: &std::fs::Metadata) -> u64 {
use std::os::linux::fs::MetadataExt;
m.st_dev()
}
/// Returns the device ID of the directory.
#[cfg(all(unix, not(target_os = "linux")))]
pub(crate) fn device_id(m: &std::fs::Metadata) -> u64 {
use std::os::unix::fs::MetadataExt;
m.dev()
}
|