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
use bstr::BStr;

/// The error returned by [`status()`][crate::status()].
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
    #[error("Could not convert path to UTF8")]
    IllformedUtf8,
    #[error("The clock was off when reading file related metadata after updating a file on disk")]
    Time(#[from] std::time::SystemTimeError),
    #[error("IO error while writing blob or reading file metadata or changing filetype")]
    Io(#[from] std::io::Error),
    #[error("Failed to obtain blob from object database")]
    Find(#[source] Box<dyn std::error::Error + Send + Sync + 'static>),
}

#[derive(Clone, Default)]
/// Options that control how the index status with a worktree is computed.
pub struct Options {
    /// Capabilities of the file system which affect the status computation.
    pub fs: gix_fs::Capabilities,
    /// If set, don't use more than this amount of threads.
    /// Otherwise, usually use as many threads as there are logical cores.
    /// A value of 0 is interpreted as no-limit
    pub thread_limit: Option<usize>,
    /// Options that control how stat comparisons are made when checking if a file is fresh.
    pub stat: gix_index::entry::stat::Options,
}

/// How an index entry needs to be changed to obtain the destination worktree state, i.e. `entry.apply(this_change) == worktree-entry`.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub enum Change<T = ()> {
    /// This corresponding file does not exist in the worktree anymore.
    Removed,
    /// The type of file changed compared to the worktree, i.e. a symlink s now a file.
    Type,
    /// This worktree file was modified in some form, like a permission change or content change or both,
    /// as compared to this entry.
    Modification {
        /// Indicates that one of the stat changes was an executable bit change
        /// which is a significant change itself.
        executable_bit_changed: bool,
        /// The output of the [`CompareBlobs`][crate::status::content::CompareBlobs] run on this entry.
        /// If there is no content change and only the executable bit
        /// changed than this is `None`.
        content_change: Option<T>,
    },
    /// An index entry that correspond to an untracked worktree file marked with `git add --intent-to-add`.
    ///
    /// This means it's not available in the object database yet or the index was created from,
    /// even though now an entry exists that represents the worktree file.
    IntentToAdd,
}

/// Observe changes by comparing an index entry to the worktree or another index.
pub trait VisitEntry<'index> {
    /// Data generated by comparing an entry with a file.
    type ContentChange;
    /// Observe the `change` of `entry` at the repository-relative `rela_path`, indicating whether
    /// or not it has a `conflict`.
    /// If `change` is `None`, there is no change.
    fn visit_entry(
        &mut self,
        entry: &'index gix_index::Entry,
        rela_path: &'index BStr,
        change: Option<Change<Self::ContentChange>>,
        conflict: bool,
    );
}