Skip to content

Commit

Permalink
Print basic index information, including the tree extension (#293)
Browse files Browse the repository at this point in the history
The latter is the one we have to maintain/create when creating
and index from a tree.
  • Loading branch information
Byron committed Jan 24, 2022
1 parent 239e7b2 commit 9277cf8
Show file tree
Hide file tree
Showing 8 changed files with 185 additions and 106 deletions.
2 changes: 1 addition & 1 deletion git-index/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ path = "tests/index-single-threaded.rs"
required-features = ["internal-testing-to-avoid-being-run-by-cargo-test-all"]

[features]
serde1 = ["serde"]
serde1 = ["serde", "smallvec/serde", "git-hash/serde1"]

internal-testing-git-features-parallel = ["git-features/parallel"]
internal-testing-to-avoid-being-run-by-cargo-test-all = []
Expand Down
6 changes: 3 additions & 3 deletions git-index/src/extension/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ pub struct Iter<'a> {
/// It allows to more quickly build trees by avoiding as it can quickly re-use portions of the index and its associated tree ids
/// if there was no change to them. Portions of this tree are invalidated as the index is changed.
pub struct Tree {
name: SmallVec<[u8; 23]>,
pub name: SmallVec<[u8; 23]>,
/// Only set if there are any entries in the index we are associated with.
id: Option<tree::NodeId>,
children: Vec<Tree>,
pub id: Option<tree::NodeId>,
pub children: Vec<Tree>,
}

pub struct Link {
Expand Down
4 changes: 2 additions & 2 deletions git-index/src/extension/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ pub const SIGNATURE: Signature = *b"TREE";

pub struct NodeId {
/// The id of the directory tree of the associated tree object.
id: git_hash::ObjectId,
pub id: git_hash::ObjectId,
/// The amount of non-tree entries contained within, and definitely not zero.
entry_count: u32,
pub entry_count: u32,
}

/// A recursive data structure
Expand Down
19 changes: 17 additions & 2 deletions git-index/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ use filetime::FileTime;

pub mod file;

pub(crate) mod extension;
pub mod extension;

pub mod entry;

mod access {
use crate::{Entry, State, Version};
use crate::{extension, Entry, State, Version};

impl State {
pub fn version(&self) -> Version {
Expand All @@ -22,6 +22,21 @@ mod access {
pub fn entries(&self) -> &[Entry] {
&self.entries
}
pub fn tree(&self) -> Option<&extension::Tree> {
self.tree.as_ref()
}
pub fn link(&self) -> Option<&extension::Link> {
self.link.as_ref()
}
pub fn resolve_undo(&self) -> Option<&extension::resolve_undo::Paths> {
self.resolve_undo.as_ref()
}
pub fn untracked(&self) -> Option<&extension::UntrackedCache> {
self.untracked.as_ref()
}
pub fn fs_monitor(&self) -> Option<&extension::FsMonitor> {
self.fs_monitor.as_ref()
}
}
}

Expand Down
5 changes: 0 additions & 5 deletions gitoxide-core/src/index/entries.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
use git_repository as git;
use git_repository::bstr::ByteSlice;

pub struct Options {
pub object_hash: git::hash::Kind,
pub format: crate::OutputFormat,
}

#[cfg(feature = "serde1")]
pub(crate) fn to_json(
mut out: &mut impl std::io::Write,
Expand Down
152 changes: 152 additions & 0 deletions gitoxide-core/src/index/information.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
use git_repository as git;
use std::convert::TryFrom;

mod ext {
#[cfg_attr(feature = "serde1", derive(serde::Serialize))]
pub(crate) struct Tree {
name: String,
/// Only set if there are any entries in the index we are associated with.
id: Option<tree::NodeId>,
children: Vec<Tree>,
}

mod tree {
use git_repository as git;
use git_repository::bstr::ByteSlice;

impl<'a> From<&'a git::index::extension::Tree> for super::Tree {
fn from(t: &'a git_repository::index::extension::Tree) -> Self {
super::Tree {
name: t.name.as_bstr().to_string(),
id: t.id.as_ref().map(|id| NodeId {
entry_count: id.entry_count,
id: id.id.to_hex().to_string(),
}),
children: t.children.iter().map(|t| t.into()).collect(),
}
}
}

#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
pub struct NodeId {
/// The id of the directory tree of the associated tree object.
id: String,
/// The amount of non-tree entries contained within, and definitely not zero.
entry_count: u32,
}
}
}

#[cfg_attr(feature = "serde1", derive(serde::Serialize))]
pub(crate) struct EntryKind {
dir: usize,
file: usize,
executable: usize,
symlink: usize,
submodule: usize,
other: usize,
}

#[cfg_attr(feature = "serde1", derive(serde::Serialize))]
pub(crate) struct EntryFlag {
intent_to_add: usize,
skip_worktree: usize,
}

#[cfg_attr(feature = "serde1", derive(serde::Serialize))]
pub(crate) struct Entries {
stage_0: usize,
stage_1: usize,
stage_2: usize,
kind: EntryKind,
flags: EntryFlag,
}

#[cfg_attr(feature = "serde1", derive(serde::Serialize))]
pub(crate) struct Extensions {
count: usize,
tree: Option<ext::Tree>,
}

#[cfg_attr(feature = "serde1", derive(serde::Serialize))]
pub(crate) struct Collection {
version: u8,
checksum: String,
entries: Entries,
extensions: Extensions,
}

impl TryFrom<git::index::File> for Collection {
type Error = anyhow::Error;

fn try_from(f: git::index::File) -> Result<Self, Self::Error> {
Ok(Collection {
version: f.version() as u8,
checksum: f.checksum.to_hex().to_string(),
extensions: {
let mut count = 0;
let tree = f.tree().map(|tree| {
count += 1;
tree.into()
});
if let Some(_) = f.link() {
count += 1
};
if let Some(_) = f.resolve_undo() {
count += 1
};
if let Some(_) = f.untracked() {
count += 1
};
if let Some(_) = f.fs_monitor() {
count += 1
};
Extensions { count, tree }
},
entries: {
let (mut stage_0, mut stage_1, mut stage_2) = (0, 0, 0);
let (mut dir, mut file, mut executable, mut symlink, mut submodule, mut other) = (0, 0, 0, 0, 0, 0);
let (mut intent_to_add, mut skip_worktree) = (0, 0);
for entry in f.entries() {
match entry.flags.stage() {
0 => stage_0 += 1,
1 => stage_1 += 1,
2 => stage_2 += 1,
invalid => anyhow::bail!("Invalid stage {} encountered", invalid),
}
match entry.mode {
git::index::entry::Mode::DIR => dir += 1,
git::index::entry::Mode::FILE => file += 1,
git::index::entry::Mode::FILE_EXECUTABLE => executable += 1,
git::index::entry::Mode::SYMLINK => symlink += 1,
git::index::entry::Mode::COMMIT => submodule += 1,
_ => other += 1,
}
if entry.flags.contains(git::index::entry::Flags::INTENT_TO_ADD) {
intent_to_add += 1;
}
if entry.flags.contains(git::index::entry::Flags::SKIP_WORKTREE) {
skip_worktree += 1;
}
}
Entries {
stage_0,
stage_1,
stage_2,
kind: EntryKind {
dir,
file,
executable,
symlink,
submodule,
other,
},
flags: EntryFlag {
intent_to_add,
skip_worktree,
},
}
},
})
}
}
99 changes: 8 additions & 91 deletions gitoxide-core/src/index/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,102 +3,19 @@ use std::path::Path;

use git_repository as git;

pub mod entries;

mod information {
use git_repository as git;
use std::convert::TryFrom;

#[cfg_attr(feature = "serde1", derive(serde::Serialize))]
pub(crate) struct EntryKind {
dir: usize,
file: usize,
executable: usize,
symlink: usize,
submodule: usize,
other: usize,
}

#[cfg_attr(feature = "serde1", derive(serde::Serialize))]
pub(crate) struct EntryFlag {
intent_to_add: usize,
skip_worktree: usize,
}

#[cfg_attr(feature = "serde1", derive(serde::Serialize))]
pub(crate) struct Entries {
stage_0: usize,
stage_1: usize,
stage_2: usize,
kind: EntryKind,
flags: EntryFlag,
}

#[cfg_attr(feature = "serde1", derive(serde::Serialize))]
pub(crate) struct Collection {
version: u8,
entries: Entries,
}
pub struct Options {
pub object_hash: git::hash::Kind,
pub format: crate::OutputFormat,
}

impl TryFrom<git::index::File> for Collection {
type Error = anyhow::Error;
mod entries;

fn try_from(f: git::index::File) -> Result<Self, Self::Error> {
Ok(Collection {
version: f.version() as u8,
entries: {
let (mut stage_0, mut stage_1, mut stage_2) = (0, 0, 0);
let (mut dir, mut file, mut executable, mut symlink, mut submodule, mut other) = (0, 0, 0, 0, 0, 0);
let (mut intent_to_add, mut skip_worktree) = (0, 0);
for entry in f.entries() {
match entry.flags.stage() {
0 => stage_0 += 1,
1 => stage_1 += 1,
2 => stage_2 += 1,
invalid => anyhow::bail!("Invalid stage {} encountered", invalid),
}
match entry.mode {
git::index::entry::Mode::DIR => dir += 1,
git::index::entry::Mode::FILE => file += 1,
git::index::entry::Mode::FILE_EXECUTABLE => executable += 1,
git::index::entry::Mode::SYMLINK => symlink += 1,
git::index::entry::Mode::COMMIT => submodule += 1,
_ => other += 1,
}
if entry.flags.contains(git::index::entry::Flags::INTENT_TO_ADD) {
intent_to_add += 1;
}
if entry.flags.contains(git::index::entry::Flags::SKIP_WORKTREE) {
skip_worktree += 1;
}
}
Entries {
stage_0,
stage_1,
stage_2,
kind: EntryKind {
dir,
file,
executable,
symlink,
submodule,
other,
},
flags: EntryFlag {
intent_to_add,
skip_worktree,
},
}
},
})
}
}
}
mod information;

pub fn information(
index_path: impl AsRef<Path>,
out: impl std::io::Write,
entries::Options { object_hash, format }: entries::Options,
Options { object_hash, format }: Options,
) -> anyhow::Result<()> {
use crate::OutputFormat::*;
let info = information::Collection::try_from(parse_file(index_path, object_hash)?)?;
Expand All @@ -115,7 +32,7 @@ pub fn information(
pub fn entries(
index_path: impl AsRef<Path>,
mut out: impl std::io::Write,
entries::Options { object_hash, format }: entries::Options,
Options { object_hash, format }: Options,
) -> anyhow::Result<()> {
use crate::OutputFormat::*;
let file = parse_file(index_path, object_hash)?;
Expand Down
4 changes: 2 additions & 2 deletions src/plumbing/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ pub fn main() -> Result<()> {
progress_keep_open,
None,
move |_progress, out, _err| {
core::index::information(index_path, out, core::index::entries::Options { object_hash, format })
core::index::information(index_path, out, core::index::Options { object_hash, format })
},
),
index::Subcommands::Entries => prepare_and_run(
Expand All @@ -95,7 +95,7 @@ pub fn main() -> Result<()> {
progress_keep_open,
None,
move |_progress, out, _err| {
core::index::entries(index_path, out, core::index::entries::Options { object_hash, format })
core::index::entries(index_path, out, core::index::Options { object_hash, format })
},
),
},
Expand Down

0 comments on commit 9277cf8

Please sign in to comment.