gitoxide_core/index/
information.rs1pub struct Options {
2 pub index: super::Options,
3 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 id: String,
17 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;