]> gitweb.ps.run Git - ziggit/blobdiff - git.zig
Implement Object parsing
[ziggit] / git.zig
diff --git a/git.zig b/git.zig
index d228b50eff37afce72b3ed185e73a4dd3676da32..0d42c2afe50e6cc448b412a30caa4559ebdde242 100644 (file)
--- a/git.zig
+++ b/git.zig
@@ -8,11 +8,18 @@ const MaxFileSize = 1024 * 1024;
 
 const Id = u160;
 const Commit = struct {
+    tree: Id,
+    parent: Id,
     author: []u8,
+    committer: []u8,
     message: []u8,
-    parent: Id,
-    tree: Id,
 };
+const TreeEntry = struct {
+    permissions: []u8,
+    name: []u8,
+    id: Id,
+};
+const Tree = std.ArrayList(TreeEntry);
 const Blob = struct {
     data: []u8,
 };
@@ -26,6 +33,55 @@ const Object = struct {
             .data = data,
         };
     }
+    pub fn parse(self: Object, alloc: Alloc) !union(enum) { c: Commit, t: Tree, b: Blob } {
+        switch (self.kind) {
+            1 => {
+                const authorOffset = std.mem.indexOf(u8, self.data, "author ") orelse return error.InvalidCommitFormat;
+                const authorNewline = std.mem.indexOfScalarPos(u8, self.data, authorOffset, '\n') orelse return error.InvalidCommitFormat;
+                const committerOffset = std.mem.indexOf(u8, self.data, "committer ") orelse return error.InvalidCommitFormat;
+                const committerNewline = std.mem.indexOfScalarPos(u8, self.data, committerOffset, '\n') orelse return error.InvalidCommitFormat;
+
+                return .{
+                    .c = Commit{
+                        .tree = try std.fmt.parseUnsigned(Id, self.data[5..45], 16),
+                        .parent = try std.fmt.parseUnsigned(Id, self.data[53..93], 16),
+                        .author = self.data[authorOffset..authorNewline],
+                        .committer = self.data[committerOffset..committerNewline],
+                        .message = self.data[committerNewline + 1 .. self.data.len],
+                    },
+                };
+            },
+            2 => {
+                var t = Tree.init(alloc);
+
+                var offset: usize = 0;
+
+                while (offset < self.data.len - 1) {
+                    const spaceOffset = std.mem.indexOfScalarPos(u8, self.data, offset, ' ') orelse return error.InvalidTreeFormat;
+                    const zeroOffset = std.mem.indexOfScalarPos(u8, self.data, spaceOffset, 0) orelse return error.InvalidTreeFormat;
+
+                    try t.append(.{
+                        .permissions = self.data[offset..spaceOffset],
+                        .name = self.data[spaceOffset + 1 .. zeroOffset],
+                        .id = std.mem.readVarInt(Id, self.data[zeroOffset + 1 .. zeroOffset + 21], .big),
+                    });
+
+                    offset = zeroOffset + 21;
+                }
+
+                return .{ .t = t };
+            },
+            3 => {
+                return .{
+                    .b = Blob{ .data = self.data },
+                };
+            },
+            4 => {
+                return error.TagNotImplemented;
+            },
+            else => return error.UnknownGitObjectType,
+        }
+    }
     // pub fn getCommit(self: *Object) Commit {}
     // pub fn getBlob(self: *Object) Blob {}
 };