Lindenii Project Forge
Login

hare-git

Git library for Hare
Commit info
ID
47561d01e99499cd86b5f879210cf3078bafb282
Author
Runxi Yu <me@runxiyu.org>
Author date
Sun, 14 Sep 2025 03:37:51 +0800
Committer
Runxi Yu <me@runxiyu.org>
Committer date
Sun, 14 Sep 2025 03:37:51 +0800
Actions
Minor formatting cleanup
export type blob = struct {
	oid: oid,
	data: []u8,
};

export fn blob_finish(b: blob) void = {
	free(b.data);
};

export type commit = struct {
	oid: oid,
	tree: oid,
	parents: []oid,
	author: person,
	committer: person,
	message: []u8,
	// other raw headers?
};

export fn commit_finish(c: commit) void = {
	free(c.parents);
	person_finish(c.author);
	person_finish(c.committer);
	free(c.message);
};

use bytes;
use crypto::sha256;
use errors;
use strconv;
use strings;

export type tree = struct {
	oid: oid,
	entries: []tree_entry,
};

export fn tree_finish(t: tree) void = {
	for (let entry .. t.entries) {
		tree_entry_finish(entry);
	};
	free(t.entries);
};

export type tree_entry = struct {
	mode: u32,
	name: []u8,
	oid: oid,
};

export fn tree_entry_finish(te: tree_entry) void = {
	free(te.name);
};

export fn parse_tree(id: oid, body: []u8) (tree | errors::invalid | strconv::invalid | strconv::overflow | nomem) = {
	let entries: []tree_entry = [];
	let i = 0z;

	for (i < len(body)) {
		const sp = match (bytes::index(body[i..], ' ')) {
		case let j: size => yield j;
		case void => return errors::invalid;
		};
		const mode_b = body[i .. i+sp];
		i += sp + 1z;

		const nul = match (bytes::index(body[i..], 0u8)) {
		case let j: size => yield j;
		case void => return errors::invalid;
		};
		const name_b = body[i .. i+nul];
		i += nul + 1z;

		if (i + sha256::SZ > len(body)) return errors::invalid;
		let child: oid = [0...];
		child[..] = body[i .. i+sha256::SZ];
		i += sha256::SZ;

		const mode_s = strings::fromutf8_unsafe(mode_b);
		const mode = strconv::stou32(mode_s, strconv::base::OCT)?;

		const name = name_b[..];
		append(entries, tree_entry { mode = mode, name = name, oid = child })!;
	};

	return tree { oid = id, entries = entries };
};
export type object = (blob | tree | commit);

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);
	};
};

export type person = struct {
	name: []u8,
	email: []u8,
	when: i64,
	ofs: i32,
};

export fn person_finish(p: person) void = {
	free(p.name);
	free(p.email);
};