From: Patrick Schönberger Date: Mon, 20 May 2024 17:47:00 +0000 (+0200) Subject: git.zig X-Git-Url: https://gitweb.ps.run/ziggit/commitdiff_plain/cf98fcd670a86203b54e89eff81c4854639baec0?ds=inline git.zig --- diff --git a/git.zig b/git.zig new file mode 100644 index 0000000..3baa985 --- /dev/null +++ b/git.zig @@ -0,0 +1,147 @@ +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}); +// }