93 lines
2.8 KiB
Rust
93 lines
2.8 KiB
Rust
//! 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)
|
|
}
|