Lindenii Project Forge
Warning: Due to various recent migrations, viewing non-HEAD refs may be broken.
/cmd/show-object/main.ha (raw)
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)!;
};
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) {
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);
};
};