gix_fs/
lib.rs

1//! A crate with file-system specific utilities.
2#![deny(rust_2018_idioms, missing_docs)]
3#![forbid(unsafe_code)]
4
5use std::path::PathBuf;
6
7/// Common knowledge about the worktree that is needed across most interactions with the work tree
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
10pub struct Capabilities {
11    /// If `true`, the filesystem will consider the precomposed umlaut `ä` similar to its decomposed form `"a\u{308}"` and consider them the same.
12    /// If `false`, the filesystem will only see bytes which means that the above example could live side-by-side.
13    ///
14    /// Even though a filesystem that treats both forms the same will still reproduce the exact same byte sequence during traversal for instance,
15    /// this might also mean that we see paths in their decomposed form (this happens when creating directory `ä` in MacOS Finder for example).
16    ///
17    /// If Git would store such decomposed paths in the repository, which only sees bytes, on linux this might mean the path will look strange
18    /// at best, which is why it prefers to store precomposed unicode on systems where it matters, like MacOS and Windows.
19    ///
20    /// For best compatibility, and with this value being `true`, we will turn decomposed paths and input like command-line arguments into their
21    /// precomposed forms, so no decomposed byte sequences should end up in storage.
22    pub precompose_unicode: bool,
23    /// If true, the filesystem ignores the case of input, which makes `A` the same file as `a`.
24    /// This is also called case-folding.
25    pub ignore_case: bool,
26    /// If true, we assume the executable bit is honored as part of the files mode. If false, we assume the file system
27    /// ignores the executable bit, hence it will be reported as 'off' even though we just tried to set it to be on.
28    pub executable_bit: bool,
29    /// If true, the file system supports symbolic links and we should try to create them. Otherwise symbolic links will be checked
30    /// out as files which contain the link as text.
31    pub symlink: bool,
32}
33mod capabilities;
34
35mod snapshot;
36pub use snapshot::{FileSnapshot, SharedFileSnapshot, SharedFileSnapshotMut};
37
38///
39pub mod symlink;
40
41///
42pub mod read_dir;
43pub use read_dir::function::read_dir;
44
45///
46pub mod dir;
47
48/// Like [`std::env::current_dir()`], but it will `precompose_unicode` if that value is true, if the current directory
49/// is valid unicode and if there are decomposed unicode codepoints.
50///
51/// Thus, it will turn `"a\u{308}"` into `ä` if `true`.
52/// Keeping it `false` will not alter the output.
53///
54/// Note that `precompose_unicode` most be set using the `core.precomposeUnicode` git configuration.
55pub fn current_dir(precompose_unicode: bool) -> std::io::Result<PathBuf> {
56    let cwd = std::env::current_dir()?;
57    Ok(if precompose_unicode {
58        gix_utils::str::precompose_path(cwd.into()).into_owned()
59    } else {
60        cwd
61    })
62}
63
64/// A stack of path components with the delegation of side-effects as the currently set path changes, component by component.
65#[derive(Clone)]
66pub struct Stack {
67    /// The prefix/root for all paths we handle.
68    root: PathBuf,
69    /// the most recent known cached that we know is valid.
70    current: PathBuf,
71    /// The relative portion of `valid` that was added previously.
72    current_relative: PathBuf,
73    /// The amount of path components of 'current' beyond the roots components.
74    valid_components: usize,
75    /// If set, we assume the `current` element is a directory to affect calls to `(push|pop)_directory()`.
76    current_is_directory: bool,
77}
78
79#[cfg(unix)]
80/// Returns whether a a file has the executable permission set.
81pub fn is_executable(metadata: &std::fs::Metadata) -> bool {
82    use std::os::unix::fs::MetadataExt;
83    (metadata.mode() & 0o100) != 0
84}
85
86/// Classifiers for IO-errors.
87pub mod io_err {
88    use std::io::ErrorKind;
89
90    /// Return `true` if `err` indicates that the entry doesn't exist on disk. `raw` is used as well
91    /// for additional checks while the variants are outside the MSRV.
92    pub fn is_not_found(err: ErrorKind, raw_err: Option<i32>) -> bool {
93        // TODO: use variant once MSRV is 1.83
94        err == ErrorKind::NotFound || raw_err == Some(20)
95    }
96}
97
98#[cfg(not(unix))]
99/// Returns whether a a file has the executable permission set.
100pub fn is_executable(_metadata: &std::fs::Metadata) -> bool {
101    false
102}
103
104///
105pub mod stack;