Skip to content

Commit 9277cf8

Browse files
committed
Print basic index information, including the tree extension (#293)
The latter is the one we have to maintain/create when creating and index from a tree.
1 parent 239e7b2 commit 9277cf8

File tree

8 files changed

+185
-106
lines changed

8 files changed

+185
-106
lines changed

Diff for: git-index/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ path = "tests/index-single-threaded.rs"
2222
required-features = ["internal-testing-to-avoid-being-run-by-cargo-test-all"]
2323

2424
[features]
25-
serde1 = ["serde"]
25+
serde1 = ["serde", "smallvec/serde", "git-hash/serde1"]
2626

2727
internal-testing-git-features-parallel = ["git-features/parallel"]
2828
internal-testing-to-avoid-being-run-by-cargo-test-all = []

Diff for: git-index/src/extension/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ pub struct Iter<'a> {
1515
/// It allows to more quickly build trees by avoiding as it can quickly re-use portions of the index and its associated tree ids
1616
/// if there was no change to them. Portions of this tree are invalidated as the index is changed.
1717
pub struct Tree {
18-
name: SmallVec<[u8; 23]>,
18+
pub name: SmallVec<[u8; 23]>,
1919
/// Only set if there are any entries in the index we are associated with.
20-
id: Option<tree::NodeId>,
21-
children: Vec<Tree>,
20+
pub id: Option<tree::NodeId>,
21+
pub children: Vec<Tree>,
2222
}
2323

2424
pub struct Link {

Diff for: git-index/src/extension/tree.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ pub const SIGNATURE: Signature = *b"TREE";
99

1010
pub struct NodeId {
1111
/// The id of the directory tree of the associated tree object.
12-
id: git_hash::ObjectId,
12+
pub id: git_hash::ObjectId,
1313
/// The amount of non-tree entries contained within, and definitely not zero.
14-
entry_count: u32,
14+
pub entry_count: u32,
1515
}
1616

1717
/// A recursive data structure

Diff for: git-index/src/lib.rs

+17-2
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ use filetime::FileTime;
77

88
pub mod file;
99

10-
pub(crate) mod extension;
10+
pub mod extension;
1111

1212
pub mod entry;
1313

1414
mod access {
15-
use crate::{Entry, State, Version};
15+
use crate::{extension, Entry, State, Version};
1616

1717
impl State {
1818
pub fn version(&self) -> Version {
@@ -22,6 +22,21 @@ mod access {
2222
pub fn entries(&self) -> &[Entry] {
2323
&self.entries
2424
}
25+
pub fn tree(&self) -> Option<&extension::Tree> {
26+
self.tree.as_ref()
27+
}
28+
pub fn link(&self) -> Option<&extension::Link> {
29+
self.link.as_ref()
30+
}
31+
pub fn resolve_undo(&self) -> Option<&extension::resolve_undo::Paths> {
32+
self.resolve_undo.as_ref()
33+
}
34+
pub fn untracked(&self) -> Option<&extension::UntrackedCache> {
35+
self.untracked.as_ref()
36+
}
37+
pub fn fs_monitor(&self) -> Option<&extension::FsMonitor> {
38+
self.fs_monitor.as_ref()
39+
}
2540
}
2641
}
2742

Diff for: gitoxide-core/src/index/entries.rs

-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
use git_repository as git;
22
use git_repository::bstr::ByteSlice;
33

4-
pub struct Options {
5-
pub object_hash: git::hash::Kind,
6-
pub format: crate::OutputFormat,
7-
}
8-
94
#[cfg(feature = "serde1")]
105
pub(crate) fn to_json(
116
mut out: &mut impl std::io::Write,

Diff for: gitoxide-core/src/index/information.rs

+152
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
use git_repository as git;
2+
use std::convert::TryFrom;
3+
4+
mod ext {
5+
#[cfg_attr(feature = "serde1", derive(serde::Serialize))]
6+
pub(crate) struct Tree {
7+
name: String,
8+
/// Only set if there are any entries in the index we are associated with.
9+
id: Option<tree::NodeId>,
10+
children: Vec<Tree>,
11+
}
12+
13+
mod tree {
14+
use git_repository as git;
15+
use git_repository::bstr::ByteSlice;
16+
17+
impl<'a> From<&'a git::index::extension::Tree> for super::Tree {
18+
fn from(t: &'a git_repository::index::extension::Tree) -> Self {
19+
super::Tree {
20+
name: t.name.as_bstr().to_string(),
21+
id: t.id.as_ref().map(|id| NodeId {
22+
entry_count: id.entry_count,
23+
id: id.id.to_hex().to_string(),
24+
}),
25+
children: t.children.iter().map(|t| t.into()).collect(),
26+
}
27+
}
28+
}
29+
30+
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
31+
pub struct NodeId {
32+
/// The id of the directory tree of the associated tree object.
33+
id: String,
34+
/// The amount of non-tree entries contained within, and definitely not zero.
35+
entry_count: u32,
36+
}
37+
}
38+
}
39+
40+
#[cfg_attr(feature = "serde1", derive(serde::Serialize))]
41+
pub(crate) struct EntryKind {
42+
dir: usize,
43+
file: usize,
44+
executable: usize,
45+
symlink: usize,
46+
submodule: usize,
47+
other: usize,
48+
}
49+
50+
#[cfg_attr(feature = "serde1", derive(serde::Serialize))]
51+
pub(crate) struct EntryFlag {
52+
intent_to_add: usize,
53+
skip_worktree: usize,
54+
}
55+
56+
#[cfg_attr(feature = "serde1", derive(serde::Serialize))]
57+
pub(crate) struct Entries {
58+
stage_0: usize,
59+
stage_1: usize,
60+
stage_2: usize,
61+
kind: EntryKind,
62+
flags: EntryFlag,
63+
}
64+
65+
#[cfg_attr(feature = "serde1", derive(serde::Serialize))]
66+
pub(crate) struct Extensions {
67+
count: usize,
68+
tree: Option<ext::Tree>,
69+
}
70+
71+
#[cfg_attr(feature = "serde1", derive(serde::Serialize))]
72+
pub(crate) struct Collection {
73+
version: u8,
74+
checksum: String,
75+
entries: Entries,
76+
extensions: Extensions,
77+
}
78+
79+
impl TryFrom<git::index::File> for Collection {
80+
type Error = anyhow::Error;
81+
82+
fn try_from(f: git::index::File) -> Result<Self, Self::Error> {
83+
Ok(Collection {
84+
version: f.version() as u8,
85+
checksum: f.checksum.to_hex().to_string(),
86+
extensions: {
87+
let mut count = 0;
88+
let tree = f.tree().map(|tree| {
89+
count += 1;
90+
tree.into()
91+
});
92+
if let Some(_) = f.link() {
93+
count += 1
94+
};
95+
if let Some(_) = f.resolve_undo() {
96+
count += 1
97+
};
98+
if let Some(_) = f.untracked() {
99+
count += 1
100+
};
101+
if let Some(_) = f.fs_monitor() {
102+
count += 1
103+
};
104+
Extensions { count, tree }
105+
},
106+
entries: {
107+
let (mut stage_0, mut stage_1, mut stage_2) = (0, 0, 0);
108+
let (mut dir, mut file, mut executable, mut symlink, mut submodule, mut other) = (0, 0, 0, 0, 0, 0);
109+
let (mut intent_to_add, mut skip_worktree) = (0, 0);
110+
for entry in f.entries() {
111+
match entry.flags.stage() {
112+
0 => stage_0 += 1,
113+
1 => stage_1 += 1,
114+
2 => stage_2 += 1,
115+
invalid => anyhow::bail!("Invalid stage {} encountered", invalid),
116+
}
117+
match entry.mode {
118+
git::index::entry::Mode::DIR => dir += 1,
119+
git::index::entry::Mode::FILE => file += 1,
120+
git::index::entry::Mode::FILE_EXECUTABLE => executable += 1,
121+
git::index::entry::Mode::SYMLINK => symlink += 1,
122+
git::index::entry::Mode::COMMIT => submodule += 1,
123+
_ => other += 1,
124+
}
125+
if entry.flags.contains(git::index::entry::Flags::INTENT_TO_ADD) {
126+
intent_to_add += 1;
127+
}
128+
if entry.flags.contains(git::index::entry::Flags::SKIP_WORKTREE) {
129+
skip_worktree += 1;
130+
}
131+
}
132+
Entries {
133+
stage_0,
134+
stage_1,
135+
stage_2,
136+
kind: EntryKind {
137+
dir,
138+
file,
139+
executable,
140+
symlink,
141+
submodule,
142+
other,
143+
},
144+
flags: EntryFlag {
145+
intent_to_add,
146+
skip_worktree,
147+
},
148+
}
149+
},
150+
})
151+
}
152+
}

Diff for: gitoxide-core/src/index/mod.rs

+8-91
Original file line numberDiff line numberDiff line change
@@ -3,102 +3,19 @@ use std::path::Path;
33

44
use git_repository as git;
55

6-
pub mod entries;
7-
8-
mod information {
9-
use git_repository as git;
10-
use std::convert::TryFrom;
11-
12-
#[cfg_attr(feature = "serde1", derive(serde::Serialize))]
13-
pub(crate) struct EntryKind {
14-
dir: usize,
15-
file: usize,
16-
executable: usize,
17-
symlink: usize,
18-
submodule: usize,
19-
other: usize,
20-
}
21-
22-
#[cfg_attr(feature = "serde1", derive(serde::Serialize))]
23-
pub(crate) struct EntryFlag {
24-
intent_to_add: usize,
25-
skip_worktree: usize,
26-
}
27-
28-
#[cfg_attr(feature = "serde1", derive(serde::Serialize))]
29-
pub(crate) struct Entries {
30-
stage_0: usize,
31-
stage_1: usize,
32-
stage_2: usize,
33-
kind: EntryKind,
34-
flags: EntryFlag,
35-
}
36-
37-
#[cfg_attr(feature = "serde1", derive(serde::Serialize))]
38-
pub(crate) struct Collection {
39-
version: u8,
40-
entries: Entries,
41-
}
6+
pub struct Options {
7+
pub object_hash: git::hash::Kind,
8+
pub format: crate::OutputFormat,
9+
}
4210

43-
impl TryFrom<git::index::File> for Collection {
44-
type Error = anyhow::Error;
11+
mod entries;
4512

46-
fn try_from(f: git::index::File) -> Result<Self, Self::Error> {
47-
Ok(Collection {
48-
version: f.version() as u8,
49-
entries: {
50-
let (mut stage_0, mut stage_1, mut stage_2) = (0, 0, 0);
51-
let (mut dir, mut file, mut executable, mut symlink, mut submodule, mut other) = (0, 0, 0, 0, 0, 0);
52-
let (mut intent_to_add, mut skip_worktree) = (0, 0);
53-
for entry in f.entries() {
54-
match entry.flags.stage() {
55-
0 => stage_0 += 1,
56-
1 => stage_1 += 1,
57-
2 => stage_2 += 1,
58-
invalid => anyhow::bail!("Invalid stage {} encountered", invalid),
59-
}
60-
match entry.mode {
61-
git::index::entry::Mode::DIR => dir += 1,
62-
git::index::entry::Mode::FILE => file += 1,
63-
git::index::entry::Mode::FILE_EXECUTABLE => executable += 1,
64-
git::index::entry::Mode::SYMLINK => symlink += 1,
65-
git::index::entry::Mode::COMMIT => submodule += 1,
66-
_ => other += 1,
67-
}
68-
if entry.flags.contains(git::index::entry::Flags::INTENT_TO_ADD) {
69-
intent_to_add += 1;
70-
}
71-
if entry.flags.contains(git::index::entry::Flags::SKIP_WORKTREE) {
72-
skip_worktree += 1;
73-
}
74-
}
75-
Entries {
76-
stage_0,
77-
stage_1,
78-
stage_2,
79-
kind: EntryKind {
80-
dir,
81-
file,
82-
executable,
83-
symlink,
84-
submodule,
85-
other,
86-
},
87-
flags: EntryFlag {
88-
intent_to_add,
89-
skip_worktree,
90-
},
91-
}
92-
},
93-
})
94-
}
95-
}
96-
}
13+
mod information;
9714

9815
pub fn information(
9916
index_path: impl AsRef<Path>,
10017
out: impl std::io::Write,
101-
entries::Options { object_hash, format }: entries::Options,
18+
Options { object_hash, format }: Options,
10219
) -> anyhow::Result<()> {
10320
use crate::OutputFormat::*;
10421
let info = information::Collection::try_from(parse_file(index_path, object_hash)?)?;
@@ -115,7 +32,7 @@ pub fn information(
11532
pub fn entries(
11633
index_path: impl AsRef<Path>,
11734
mut out: impl std::io::Write,
118-
entries::Options { object_hash, format }: entries::Options,
35+
Options { object_hash, format }: Options,
11936
) -> anyhow::Result<()> {
12037
use crate::OutputFormat::*;
12138
let file = parse_file(index_path, object_hash)?;

Diff for: src/plumbing/main.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ pub fn main() -> Result<()> {
8585
progress_keep_open,
8686
None,
8787
move |_progress, out, _err| {
88-
core::index::information(index_path, out, core::index::entries::Options { object_hash, format })
88+
core::index::information(index_path, out, core::index::Options { object_hash, format })
8989
},
9090
),
9191
index::Subcommands::Entries => prepare_and_run(
@@ -95,7 +95,7 @@ pub fn main() -> Result<()> {
9595
progress_keep_open,
9696
None,
9797
move |_progress, out, _err| {
98-
core::index::entries(index_path, out, core::index::entries::Options { object_hash, format })
98+
core::index::entries(index_path, out, core::index::Options { object_hash, format })
9999
},
100100
),
101101
},

0 commit comments

Comments
 (0)