Provide world Git identity, reflog fallback, object inspection, and which (T73)
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
//! Read Git object types, sizes, contents, and tree entries without changing repository state.
|
||||
use crate::{Result, repo::error};
|
||||
use std::io::Write;
|
||||
|
||||
pub(crate) fn cat_file(
|
||||
repo: &gix::Repository,
|
||||
revision: &str,
|
||||
kind: bool,
|
||||
size: bool,
|
||||
exists: bool,
|
||||
) -> Result<()> {
|
||||
let object = repo
|
||||
.rev_parse_single(revision)
|
||||
.map_err(|e| error("cat-file", e))?
|
||||
.object()
|
||||
.map_err(|e| error("cat-file", e))?;
|
||||
if exists {
|
||||
return Ok(());
|
||||
}
|
||||
if kind {
|
||||
println!("{}", object.kind);
|
||||
} else if size {
|
||||
println!("{}", object.data.len());
|
||||
} else if object.kind == gix::objs::Kind::Tree {
|
||||
ls_tree(repo, revision, false, false, None)?;
|
||||
} else {
|
||||
std::io::stdout()
|
||||
.write_all(&object.data)
|
||||
.map_err(|e| error("cat-file", e))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn ls_tree(
|
||||
repo: &gix::Repository,
|
||||
revision: &str,
|
||||
recursive: bool,
|
||||
names: bool,
|
||||
path: Option<&str>,
|
||||
) -> Result<()> {
|
||||
let id = crate::local::tree(repo, revision)?;
|
||||
fn walk(
|
||||
repo: &gix::Repository,
|
||||
id: gix::ObjectId,
|
||||
prefix: &str,
|
||||
recursive: bool,
|
||||
names: bool,
|
||||
filter: Option<&str>,
|
||||
) -> Result<()> {
|
||||
let tree = repo.find_tree(id).map_err(|e| error("ls-tree", e))?;
|
||||
for entry in tree.iter() {
|
||||
let entry = entry.map_err(|e| error("ls-tree", e))?;
|
||||
let filename = format!("{prefix}{}", entry.filename());
|
||||
let directory = entry.mode().is_tree();
|
||||
let descend = directory
|
||||
&& (recursive
|
||||
|| filter.is_some_and(|path| path.starts_with(&format!("{filename}/"))));
|
||||
if descend {
|
||||
walk(
|
||||
repo,
|
||||
entry.oid().to_owned(),
|
||||
&format!("{filename}/"),
|
||||
recursive,
|
||||
names,
|
||||
filter,
|
||||
)?;
|
||||
} else if filter.is_none_or(|path| {
|
||||
filename == path
|
||||
|| filename.starts_with(&format!("{}/", path.trim_end_matches('/')))
|
||||
}) {
|
||||
if names {
|
||||
println!("{filename}");
|
||||
} else {
|
||||
let kind = if directory {
|
||||
"tree"
|
||||
} else if entry.mode().is_commit() {
|
||||
"commit"
|
||||
} else {
|
||||
"blob"
|
||||
};
|
||||
println!(
|
||||
"{:06o} {kind} {}\t{filename}",
|
||||
entry.mode().kind() as u32,
|
||||
entry.oid()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
walk(repo, id, "", recursive, names, path)
|
||||
}
|
||||
Reference in New Issue
Block a user