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            #[derive(serde::Serialize, serde::Deserialize)]
38            pub struct NodeId {}
39        }
40    }
41
42    #[derive(serde::Serialize)]
43    pub(crate) struct EntryKind {
44        dir: usize,
45        file: usize,
46        executable: usize,
47        symlink: usize,
48        submodule: usize,
49        other: usize,
50    }
51
52    #[derive(serde::Serialize)]
53    pub(crate) struct EntryFlag {
54        intent_to_add: usize,
55        skip_worktree: usize,
56    }
57
58    #[derive(serde::Serialize)]
59    pub struct Entries {
60        stage_0_merged: usize,
61        stage_1_base: usize,
62        stage_2_ours: usize,
63        stage_3_theirs: usize,
64        kind: EntryKind,
65        flags: EntryFlag,
66    }
67
68    #[derive(serde::Serialize)]
69    pub struct Extensions {
70        names: Vec<&'static str>,
71        tree: Option<ext::Tree>,
72    }
73
74    #[derive(serde::Serialize)]
75    pub struct Collection {
76        version: u8,
77        checksum: String,
78        entries: Entries,
79        extensions: Extensions,
80    }
81
82    impl Collection {
83        pub fn try_from_file(f: gix::index::File, extension_details: bool) -> anyhow::Result<Self> {
84            Ok(Collection {
85                version: f.version() as u8,
86                checksum: f.checksum().expect("just read from disk").to_hex().to_string(),
87                extensions: {
88                    let mut names = Vec::new();
89                    let tree = f.tree().and_then(|tree| {
90                        names.push("tree (TREE)");
91                        extension_details.then(|| tree.into())
92                    });
93                    if f.link().is_some() {
94                        names.push("link");
95                    }
96                    if f.resolve_undo().is_some() {
97                        names.push("resolve-undo (REUC)");
98                    }
99                    if f.untracked().is_some() {
100                        names.push("untracked (UNTR)");
101                    }
102                    if f.fs_monitor().is_some() {
103                        names.push("fs-monitor (FSMN)");
104                    }
105                    if f.had_offset_table() {
106                        names.push("offset-table (IEOT)");
107                    }
108                    if f.had_end_of_index_marker() {
109                        names.push("end-of-index (EOIE)");
110                    }
111                    Extensions { names, tree }
112                },
113                entries: {
114                    let (mut stage_0_merged, mut stage_1_base, mut stage_2_ours, mut stage_3_theirs) = (0, 0, 0, 0);
115                    let (mut dir, mut file, mut executable, mut symlink, mut submodule, mut other) = (0, 0, 0, 0, 0, 0);
116                    let (mut intent_to_add, mut skip_worktree) = (0, 0);
117                    for entry in f.entries() {
118                        match entry.flags.stage() {
119                            Stage::Unconflicted => stage_0_merged += 1,
120                            Stage::Base => stage_1_base += 1,
121                            Stage::Ours => stage_2_ours += 1,
122                            Stage::Theirs => stage_3_theirs += 1,
123                        }
124                        match entry.mode {
125                            gix::index::entry::Mode::DIR => dir += 1,
126                            gix::index::entry::Mode::FILE => file += 1,
127                            gix::index::entry::Mode::FILE_EXECUTABLE => executable += 1,
128                            gix::index::entry::Mode::SYMLINK => symlink += 1,
129                            gix::index::entry::Mode::COMMIT => submodule += 1,
130                            _ => other += 1,
131                        }
132                        if entry.flags.contains(gix::index::entry::Flags::INTENT_TO_ADD) {
133                            intent_to_add += 1;
134                        }
135                        if entry.flags.contains(gix::index::entry::Flags::SKIP_WORKTREE) {
136                            skip_worktree += 1;
137                        }
138                    }
139                    Entries {
140                        stage_0_merged,
141                        stage_1_base,
142                        stage_2_ours,
143                        stage_3_theirs,
144                        kind: EntryKind {
145                            dir,
146                            file,
147                            executable,
148                            symlink,
149                            submodule,
150                            other,
151                        },
152                        flags: EntryFlag {
153                            intent_to_add,
154                            skip_worktree,
155                        },
156                    }
157                },
158            })
159        }
160    }
161}
162#[cfg(feature = "serde")]
163pub(crate) use serde_only::Collection;