--- /dev/null
+const std = @import("std");
+
+const Alloc = std.mem.Allocator;
+
+const Id = u160;
+const Commit = struct {
+ author: std.BoundedArray(u8, 64),
+ message: std.BoundedArray(u8, 1024),
+ parent: Id,
+ tree: Id,
+};
+const Blob = struct {
+ data: std.BoundedArray(u8, 1024),
+};
+const Object = struct {
+ alloc: Alloc,
+
+ // pub fn getCommit(self: *Object) Commit {}
+ // pub fn getBlob(self: *Object) Blob {}
+};
+const PackFile = struct {
+ alloc: Alloc,
+
+ pub fn init(alloc: Alloc) PackFile {
+ return .{
+ .alloc = alloc,
+ };
+ }
+ pub fn deinit(self: *PackFile) void {
+ _ = self;
+ }
+ pub fn parse(self: *PackFile, idxReader: std.io.AnyReader, pckReader: anytype) !void {
+ _ = self;
+ var buffer: [16]u8 = undefined;
+ _ = try idxReader.read(&buffer);
+ std.debug.print("{s}\n", .{&buffer});
+ _ = try pckReader.read(&buffer);
+ std.debug.print("{s}\n", .{&buffer});
+ }
+
+ // pub fn init(alloc: Alloc, path: []const u8) PackFile {}
+ // pub fn deinit(self: *PackFile) void {}
+ // pub fn getObject(self: *PackFile, id: Id) Object {}
+};
+const Repo = struct {
+ alloc: Alloc,
+ packfile: PackFile,
+
+ head: Id,
+
+ pub fn open(alloc: Alloc, path: []const u8) !Repo {
+ const dir = try std.fs.cwd().openDir(path, .{});
+
+ // read file HEAD
+ const head = try dir.readFileAlloc(alloc, "HEAD", 1024);
+ defer alloc.free(head);
+
+ // read file pointed at by HEAD
+ const headPath = head[5 .. head.len - 1];
+ var idBuffer: [40]u8 = undefined;
+ const idStr = try dir.readFile(headPath, &idBuffer);
+
+ // parse id from file
+ const id = try std.fmt.parseUnsigned(u160, idStr, 16);
+
+ // open any packfiles
+ var packfile = PackFile.init(alloc);
+ if (dir.openDir("objects/pack", .{ .iterate = true })) |packDir| {
+ var packIt = packDir.iterate();
+ while (try packIt.next()) |f| {
+ if (std.mem.endsWith(u8, f.name, ".idx")) {
+ const idxFilename = f.name;
+ var pckFilenameBuffer: [64]u8 = undefined;
+ const pckFilename = try std.fmt.bufPrint(&pckFilenameBuffer, "{s}.pack", .{idxFilename[0 .. idxFilename.len - 4]});
+
+ const idxFile = try packDir.openFile(idxFilename, .{});
+ const pckFile = try packDir.openFile(pckFilename, .{});
+ defer idxFile.close();
+ defer pckFile.close();
+
+ const idxReader = idxFile.reader().any();
+ const pckReader = pckFile.reader().any();
+
+ try packfile.parse(idxReader, pckReader);
+ }
+ }
+ } else |err| {
+ std.debug.print("{}\n", .{err});
+ }
+
+ return .{
+ .alloc = alloc,
+ .packfile = packfile,
+ .head = id,
+ };
+ }
+ pub fn close(self: *Repo) void {
+ self.packfile.deinit();
+ }
+ // pub fn getObject(self: *Repo, id: Id) Object {}
+};
+
+test "print HEAD" {
+ var repo = try Repo.open(std.testing.allocator, "../microwindows/.git");
+ defer repo.close();
+
+ std.debug.print("HEAD: {}\n", .{repo.head});
+}
+
+// test "list commits" {
+// var repo = Repo.open(std.testing.allocator, "../microwindows/.git");
+// defer repo.close();
+
+// const head = repo.getObject(repo.head);
+// defer head.deinit();
+
+// var c = head.getCommit();
+// for (0..3) |_| {
+// std.debug.print("{}\n", .{c});
+// c = c.parent;
+// }
+// }
+
+// test "tree" {
+// var repo = Repo.open(std.testing.allocator, "../microwindows/.git");
+// defer repo.close();
+
+// const head = repo.getObject(repo.head);
+// defer head.deinit();
+
+// const commit = head.getCommit();
+
+// std.debug.print("{}\n", .{commit.tree});
+// }
+
+// test "blob" {
+// var repo = Repo.open(std.testing.allocator, "../microwindows/.git");
+// defer repo.close();
+
+// const head = repo.getObject(repo.head);
+// defer head.deinit();
+
+// const commit = head.getCommit();
+// const blob = repo.getBlob(commit.files[0].id);
+
+// std.debug.print("{}\n", .{blob});
+// }