Lindenii Project Forge
Git show object for tags
use fmt; use fs; use getopt; use io; use os; use strings; use git; fn usage(cmd: *getopt::command) void = { getopt::printusage(os::stderr, os::args[0], cmd.help)!; }; fn print_blob(b: git::blob) void = { io::write(os::stdout, b.data)!; }; fn print_tree(t: git::tree) void = { for (let i = 0z; i < len(t.entries); i += 1z) { const ent = t.entries[i]; const hex = git::oid_string(ent.oid)!; defer free(hex); const name = strings::fromutf8_unsafe(ent.name); fmt::printfln("{:o} {} {}", ent.mode, hex, name)!; }; }; fn print_ident(label: str, id: git::ident) void = { const name = strings::fromutf8_unsafe(id.name); const email = strings::fromutf8_unsafe(id.email); fmt::printfln("{} {} <{}> {} {}", label, name, email, id.when, id.ofs)!; }; fn print_commit(c: git::commit) void = { const treehex = git::oid_string(c.tree)!; defer free(treehex); fmt::printfln("tree {}", treehex)!; for (let i = 0z; i < len(c.parents); i += 1z) { const phex = git::oid_string(c.parents[i])!; defer free(phex); fmt::printfln("parent {}", phex)!; }; print_ident("author", c.author); print_ident("committer", c.committer); fmt::println("")!; const msg = strings::fromutf8_unsafe(c.message); fmt::println(msg)!; };
fn print_tag(t: git::tag) void = { const tgt = git::oid_string(t.target)!; defer free(tgt); let ty: str = ""; switch (t.target_type) { case git::objtype::OBJ_COMMIT => ty = "commit"; case git::objtype::OBJ_TREE => ty = "tree"; case git::objtype::OBJ_BLOB => ty = "blob"; case git::objtype::OBJ_TAG => ty = "tag"; }; const name = strings::fromutf8_unsafe(t.name); fmt::printfln("object {}", tgt)!; fmt::printfln("type {}", ty)!; fmt::printfln("tag {}", name)!; match (t.tagger) { case let id: git::ident => print_ident("tagger", id); case void => void; }; fmt::println("")!; const msg = strings::fromutf8_unsafe(t.message); fmt::println(msg)!; };
export fn main() void = { let repo_path: (str | void) = void; let cmd = getopt::parse( os::args, "Print a Git object by OID", ('r', "repo", "PATH to repo or .git"), "OID", ); defer getopt::finish(&cmd); for (let opt .. cmd.opts) { switch (opt.0) { case 'r' => repo_path = opt.1; case => abort(); }; };
if (len(cmd.args) != 1) { usage(&cmd); os::exit(2); }; if (repo_path is void) {
if (len(cmd.args) != 1 || repo_path is void) {
usage(&cmd); os::exit(2); }; const rp = repo_path: str; let r = match (git::open(rp)) { case let rr: git::repo => yield rr; case let fe: fs::error => fmt::errorfln("open repo: {}", fs::strerror(fe))!; os::exit(1); }; defer git::close(r); const oidhex = cmd.args[0]; let id = match (git::parse_oid(oidhex)) { case let o: git::oid => yield o; case => fmt::errorfln("invalid oid: {}", oidhex)!; os::exit(1); }; let obj = match (git::read_object(r, id)) { case let o: git::object => yield o; case let fe: fs::error => fmt::errorfln("fs error: {}", fs::strerror(fe))!; os::exit(1); case let ioe: io::error => fmt::errorfln("io error: {}", io::strerror(ioe))!; os::exit(1); case => fmt::errorfln("not a valid object: {}", oidhex)!; os::exit(1); }; match (obj) { case let b: git::blob => print_blob(b); git::blob_finish(b); case let t: git::tree => print_tree(t); git::tree_finish(t); case let c: git::commit => print_commit(c); git::commit_finish(c);
case let g: git::tag => print_tag(g); git::tag_finish(g);
}; };