mirror of
https://github.com/awfixers-stuff/src.git
synced 2026-03-23 11:05:59 +00:00
79 lines
2.2 KiB
Rust
79 lines
2.2 KiB
Rust
use std::io::{stdout, Write};
|
|
|
|
use clap::Parser;
|
|
use src::{bstr::BString, objs::tree::EntryMode, traverse::tree::Recorder, ObjectId};
|
|
|
|
fn main() {
|
|
let args = Args::parse_from(src::env::args_os());
|
|
match run(args) {
|
|
Ok(()) => {}
|
|
Err(e) => eprintln!("error: {e}"),
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, clap::Parser)]
|
|
#[clap(name = "ls-tree", about = "git ls-tree example", version = option_env!("src_VERSION"))]
|
|
#[clap(arg_required_else_help = true)]
|
|
struct Args {
|
|
/// Recurse into subtrees
|
|
#[clap(short = 'r')]
|
|
recursive: bool,
|
|
/// Only show trees
|
|
#[clap(short = 'd')]
|
|
tree_only: bool,
|
|
/// Show trees when recursing
|
|
#[clap(short = 't')]
|
|
tree_recursing: bool,
|
|
/// A revspec pointing to a tree-ish object, e.g. 'HEAD', 'HEAD:src/'
|
|
#[clap(name = "tree-ish")]
|
|
treeish: String,
|
|
}
|
|
|
|
fn run(args: Args) -> anyhow::Result<()> {
|
|
let repo = src::discover(".")?;
|
|
let tree = repo.rev_parse_single(&*args.treeish)?.object()?.peel_to_tree()?;
|
|
let entries = if args.recursive {
|
|
let mut recorder = Recorder::default();
|
|
tree.traverse().breadthfirst(&mut recorder)?;
|
|
recorder
|
|
.records
|
|
.into_iter()
|
|
.filter(|entry| args.tree_recursing || args.tree_only || entry.mode.is_no_tree())
|
|
.filter(|entry| !args.tree_only || (entry.mode.is_tree()))
|
|
.map(|entry| Entry::new(entry.mode, entry.oid, entry.filepath))
|
|
.collect::<Vec<_>>()
|
|
} else {
|
|
tree.iter()
|
|
.filter_map(|res| res.ok().map(|entry| entry.inner)) // dropping errors silently
|
|
.filter(|entry| !args.tree_only || (entry.mode.is_tree()))
|
|
.map(|entry| Entry::new(entry.mode, entry.oid.to_owned(), entry.filename.to_owned()))
|
|
.collect::<Vec<_>>()
|
|
};
|
|
|
|
let mut out = stdout().lock();
|
|
for entry in entries {
|
|
writeln!(
|
|
out,
|
|
"{:>6o} {:4} {} {}",
|
|
entry.mode,
|
|
entry.mode.as_str(),
|
|
entry.hash,
|
|
entry.path
|
|
)?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
struct Entry {
|
|
mode: EntryMode,
|
|
hash: ObjectId,
|
|
path: BString,
|
|
}
|
|
|
|
impl Entry {
|
|
fn new(mode: EntryMode, hash: ObjectId, path: BString) -> Self {
|
|
Self { mode, hash, path }
|
|
}
|
|
}
|