Lindenii Project Forge
Warning: Due to various recent migrations, viewing non-HEAD refs may be broken.
/git/object.ha (raw)
use bytes;
use crypto::sha256;
use errors;
use fmt;
use fs;
use hash;
use io;
use strconv;
use strings;
// Any Git object. [[tag]] will be supported in the future.
export type object = (blob | tree | commit);
// TODO: These should be enums instead of u8 constants.
// The tag for a commit object.
export def OBJ_COMMIT: u8 = 1u8;
// The tag for a tree object.
export def OBJ_TREE: u8 = 2u8;
// The tag for a blob object.
export def OBJ_BLOB: u8 = 3u8;
// The tag for a tag object.
export def OBJ_TAG: u8 = 4u8;
// The tag for an offset delta object in packfiles.
export def OBJ_OFS_DELTA: u8 = 6u8;
// The tag for a reference delta object in packfiles.
export def OBJ_REF_DELTA: u8 = 7u8;
// Frees resources associated with any Git object.
export fn object_finish(o: object) void = {
match (o) {
case let b: blob =>
blob_finish(b);
case let t: tree =>
tree_finish(t);
case let c: commit =>
commit_finish(c);
case =>
abort("Unknown object type being freed...");
};
};
// Formats a Git object ID as a hexadecimal string.
export fn verify_oid(buf: []u8, want: oid) bool = {
let st = sha256::sha256();
hash::write(&st, buf);
let got: oid = [0...];
hash::sum(&st, got);
hash::close(&st);
if (bytes::equal(got[..], want[..])) {
return true;
} else {
return false;
};
};
// Verifies that the given body matches the given object ID.
export fn verify_typed(ty: str, body: []u8, want: oid) bool = {
let st = sha256::sha256();
defer hash::close(&st);
if (ty == "blob") {
hash::write(&st, strings::toutf8("blob"));
} else if (ty == "tree") {
hash::write(&st, strings::toutf8("tree"));
} else if (ty == "commit") {
hash::write(&st, strings::toutf8("commit"));
} else {
return false;
};
hash::write(&st, strings::toutf8(" "));
let szs = strconv::ztos(len(body));
hash::write(&st, strings::toutf8(szs));
hash::write(&st, strings::toutf8("\x00"));
hash::write(&st, body);
let got: oid = [0...];
hash::sum(&st, got);
if (bytes::equal(got[..], want[..])) {
return true;
} else {
return false;
};
};
// Reads a Git object from the repository by its ID.
export fn read_object(
r: repo,
id: oid,
) (object | fs::error | io::error | errors::invalid | strconv::invalid | strconv::overflow | nomem) = {
match (read_loose(r, id)) {
case let o: object =>
return o;
case let fe: fs::error =>
if (fe is errors::noentry) {
void;
} else {
return fe;
};
case let e: (io::error | errors::invalid | strconv::invalid | strconv::overflow | nomem) =>
return e;
};
match (read_packed(r, id)) {
case let o: object =>
return o;
case let fe: fs::error =>
if (fe is errors::noentry) {
return errors::invalid;
} else {
return fe;
};
case let e: (io::error | errors::invalid | strconv::invalid | strconv::overflow | nomem) =>
return e;
};
};