gitoxide_core/index/
information.rs

1pub struct Options {
2    pub index: super::Options,
3    /// If true, show extension in detail.
4    pub extension_details: bool,
5}
6
7#[cfg(feature = "serde")]
8mod serde_only {
9    use gix::index::entry::Stage;
10
11    mod ext {
12        #[derive(serde::Serialize)]
13        pub(crate) struct Tree {
14            name: String,
15            /// The id of the directory tree of the associated tree object.
16            id: String,
17            /// The amount of non-tree entries contained within, and definitely not zero.
18            num_entries: Option<u32>,
19            children: Vec<Tree>,
20        }
21
22        mod tree {
23
24            use gix::bstr::ByteSlice;
25
26            impl<'a> From<&'a gix::index::extension::Tree> for super::Tree {
27                fn from(t: &'a gix::index::extension::Tree) -> Self {
28                    super::Tree {
29                        name: t.name.as_bstr().to_string(),
30                        id: t.id.to_hex().to_string(),
31                        num_entries: t.num_entries,
32                        children: t.children.iter().map(Into::into).collect(),
33                    }
34                }
35            }
36        }
37    }
38
39    #[derive(serde::Serialize)]
40    pub(crate) struct EntryKind {
41        dir: usize,
42        file: usize,
43        executable: usize,
44        symlink: usize,
45        submodule: usize,
46        other: usize,
47    }
48
49    #[derive(serde::Serialize)]
50    pub(crate) struct EntryFlag {
51        intent_to_add: usize,
52        skip_worktree: usize,
53    }
54
55    #[derive(serde::Serialize)]
56    pub struct Entries {
57        stage_0_merged: usize,
58        stage_1_base: usize,
59        stage_2_ours: usize,
60        stage_3_theirs: usize,
61        kind: EntryKind,
62        flags: EntryFlag,
63    }
64
65    #[derive(serde::Serialize)]
66    pub struct Extensions {
67        names: Vec<&'static str>,
68        tree: Option<ext::Tree>,
69    }
70
71    #[derive(serde::Serialize)]
72    pub struct Collection {
73        version: u8,
74        checksum: String,
75        entries: Entries,
76        extensions: Extensions,
77    }
78
79    impl Collection {
80        pub fn try_from_file(f: gix::index::File, extension_details: bool) -> anyhow::Result<Self> {
81            Ok(Collection {
82                version: f.version() as u8,
83                checksum: f.checksum().expect("just read from disk").to_hex().to_string(),
84                extensions: {
85                    let mut names = Vec::new();
86                    let tree = f.tree().and_then(|tree| {
87                        names.push("tree (TREE)");
88                        extension_details.then(|| tree.into())
89                    });
90                    if f.link().is_some() {
91                        names.push("link");
92                    }
93                    if f.resolve_undo().is_some() {
94                        names.push("resolve-undo (REUC)");
95                    }
96                    if f.untracked().is_some() {
97                        names.push("untracked (UNTR)");
98                    }
99                    if f.fs_monitor().is_some() {
100                        names.push("fs-monitor (FSMN)");
101                    }
102                    if f.had_offset_table() {
103                        names.push("offset-table (IEOT)");
104                    }
105                    if f.had_end_of_index_marker() {
106                        names.push("end-of-index (EOIE)");
107                    }
108                    Extensions { names, tree }
109                },
110                entries: {
111                    let (mut stage_0_merged, mut stage_1_base, mut stage_2_ours, mut stage_3_theirs) = (0, 0, 0, 0);
112                    let (mut dir, mut file, mut executable, mut symlink, mut submodule, mut other) = (0, 0, 0, 0, 0, 0);
113                    let (mut intent_to_add, mut skip_worktree) = (0, 0);
114                    for entry in f.entries() {
115                        match entry.flags.stage() {
116                            Stage::Unconflicted => stage_0_merged += 1,
117                            Stage::Base => stage_1_base += 1,
118                            Stage::Ours => stage_2_ours += 1,
119                            Stage::Theirs => stage_3_theirs += 1,
120                        }
121                        match entry.mode {
122                            gix::index::entry::Mode::DIR => dir += 1,
123                            gix::index::entry::Mode::FILE => file += 1,
124                            gix::index::entry::Mode::FILE_EXECUTABLE => executable += 1,
125                            gix::index::entry::Mode::SYMLINK => symlink += 1,
126                            gix::index::entry::Mode::COMMIT => submodule += 1,
127                            _ => other += 1,
128                        }
129                        if entry.flags.contains(gix::index::entry::Flags::INTENT_TO_ADD) {
130                            intent_to_add += 1;
131                        }
132                        if entry.flags.contains(gix::index::entry::Flags::SKIP_WORKTREE) {
133                            skip_worktree += 1;
134                        }
135                    }
136                    Entries {
137                        stage_0_merged,
138                        stage_1_base,
139                        stage_2_ours,
140                        stage_3_theirs,
141                        kind: EntryKind {
142                            dir,
143                            file,
144                            executable,
145                            symlink,
146                            submodule,
147                            other,
148                        },
149                        flags: EntryFlag {
150                            intent_to_add,
151                            skip_worktree,
152                        },
153                    }
154                },
155            })
156        }
157    }
158}
159#[cfg(feature = "serde")]
160pub(crate) use serde_only::Collection;