]> gitweb.ps.run Git - ziggit/commitdiff
trying to refactor main.zig, decided to redo instead
authorPatrick Schönberger <patrick.schoenberger@posteo.de>
Mon, 20 May 2024 17:47:34 +0000 (19:47 +0200)
committerPatrick Schönberger <patrick.schoenberger@posteo.de>
Mon, 20 May 2024 17:47:34 +0000 (19:47 +0200)
main.zig

index 42a5a4f92d914132548a48e762249701a4817127..cf30d7125722fc8a834f982ef6bf7e83b7c95a1a 100644 (file)
--- a/main.zig
+++ b/main.zig
@@ -151,6 +151,49 @@ fn applyDelta(alloc: std.mem.Allocator, baseData: []const u8, deltaData: []const
     return result;
 }
 
+fn parseObject(alloc: std.mem.Allocator, objectType: u3, objectData: []const u8) !git.Object {
+    if (objectType == 3) {
+        return .{
+            .data = objectData,
+            .blob = .{
+                .data = objectData[0..@min(objectData.len, 1000)],
+            },
+        };
+    } else if (objectType == 2) {
+        var treeEntries = git.Tree.init(alloc);
+
+        var counter: u64 = 0;
+        while (counter < objectData.len) {
+            const modeLen = std.mem.indexOfScalar(u8, objectData[counter..objectData.len], ' ') orelse break;
+            const mode = objectData[counter .. counter + modeLen];
+            counter += modeLen + 1;
+
+            var nameLen: u64 = 0;
+            while (counter + nameLen < objectData.len and objectData[counter + nameLen] != 0) {
+                nameLen += 1;
+            }
+            const name = objectData[counter .. counter + nameLen];
+            counter += nameLen + 1;
+
+            if (counter + 20 <= objectData.len) {
+                const hash: u160 = std.mem.readVarInt(u160, objectData[counter .. counter + 20], .big);
+                counter += 20;
+
+                treeEntries.append(.{
+                    .mode = alloc.dupe(u8, mode),
+                    .name = alloc.dupe(u8, name),
+                    .hash = hash,
+                });
+            }
+        }
+        return .{
+            .tree = treeEntries,
+        };
+    } else {
+        std.debug.print("type: {}\n{s}\n", .{ objectType, objectData });
+    }
+}
+
 const PackFile = struct {
     alloc: std.mem.Allocator,
     version: i32,
@@ -214,7 +257,7 @@ const PackFile = struct {
         return null;
     }
 
-    pub fn getObject(self: @This(), index: u64) !GitObject {
+    pub fn getObject(self: @This(), alloc: std.mem.Allocator, index: u64) !git.Object {
         var objectType: u3 = @truncate(self.packBuffer[index] >> 4);
         const objectSize = getSize(self.packBuffer[index..self.packBuffer.len], true);
 
@@ -233,8 +276,9 @@ const PackFile = struct {
 
             const baseIndex = index - offsetSize.offset;
 
-            const baseObject = try self.getObject(baseIndex);
+            const baseObject = try self.getObject(alloc, baseIndex);
             defer self.alloc.free(baseObject.data);
+
             const deltaData = try decompress(
                 self.alloc,
                 self.packBuffer[index + objectSize.bytelen + offsetSize.bytelen .. self.packBuffer.len],
@@ -273,23 +317,84 @@ const PackFile = struct {
             );
         }
 
-        // const objectStart = objectSize.bytelen;
-        // objectData = self.packBuffer[objectStart .. objectStart + objectSize];
-
-        return .{
-            .type = objectType,
-            .data = objectData,
-        };
+        return try parseObject(alloc, objectType, objectData);
     }
 };
 
-pub fn main() !void {
-    const packPath = "../microwindows/.git/objects/pack/pack-a2e25318e6fc668e1264fdaa11fb7223d5627143.pack";
-    const idxPath = "../microwindows/.git/objects/pack/pack-a2e25318e6fc668e1264fdaa11fb7223d5627143.idx";
+const git = struct {
+    const Blob = struct {
+        data: []u8,
+    };
+    const TreeEntry = struct {
+        mode: []u8,
+        name: []u8,
+        hash: u160,
+    };
+    const Tree = std.ArrayList(TreeEntry);
+    const Commit = struct {
+        author: []u8,
+        message: []u8,
+        parent: u160,
+        Tree: u160,
+    };
+    const Object = struct {
+        usingnamespace union(enum) {
+            blob: Blob,
+            tree: Tree,
+            commit: Commit,
+        };
+        data: []const u8,
+    };
+    const Repo = struct {
+        pub fn init(alloc: std.mem.Allocator, path: []const u8) !@This() {
+            const gitDir = try std.fs.cwd().openDir(path, .{});
+
+            var objects = std.AutoHashMap(u160, Object).init(alloc);
+
+            var iter = gitDir.iterate();
+            while (try iter.next()) |dirEntry| {
+                if (std.mem.endsWith(u8, dirEntry.name, ".idx")) {
+                    var packPathBuffer: [128]u8 = undefined;
+                    const idxPath = try gitDir.realpathAlloc(alloc, dirEntry.name);
+                    const packPath = try std.fmt.bufPrint(
+                        &packPathBuffer,
+                        "{s}.pack",
+                        .{idxPath[0 .. idxPath.len - 4]},
+                    );
+
+                    const packBuffer = try std.fs.cwd().readFileAlloc(alloc, packPath, 1024 * 1024 * 1024 * 1024);
+                    const idxBuffer = try std.fs.cwd().readFileAlloc(alloc, idxPath, 1024 * 1024 * 1024 * 1024);
+                    defer alloc.free(packBuffer);
+                    defer alloc.free(idxBuffer);
+
+                    const pf = try PackFile.init(alloc, packBuffer, idxBuffer);
+                    defer pf.deinit();
+
+                    for (0..pf.objectNames.items.len) |i| {
+                        try objects.put(
+                            pf.objectNames.items[i],
+                            try pf.getObject(alloc, pf.objectOffsets.items[i]),
+                        );
+                    }
+                }
+            }
+            return .{
+                .alloc = alloc,
+                .objects = objects,
+            };
+        }
 
-    const packBytes = 35920363;
-    const idxBytes = 392036;
+        pub fn deinit(self: *@This()) void {
+            self.objects.deinit();
+        }
 
+        alloc: std.mem.Allocator,
+        objects: std.AutoHashMap(u160, Object),
+    };
+};
+
+pub fn main() !void {
+    // allocator
     var allocator = std.heap.GeneralPurposeAllocator(.{}){};
     const alloc = allocator.allocator();
     defer {
@@ -297,94 +402,42 @@ pub fn main() !void {
         std.debug.print("{}\n", .{res});
     }
 
-    const packBuffer = try std.fs.cwd().readFileAlloc(alloc, packPath, packBytes);
-    const idxBuffer = try std.fs.cwd().readFileAlloc(alloc, idxPath, idxBytes);
-    defer alloc.free(packBuffer);
-    defer alloc.free(idxBuffer);
-
-    const print = std.debug.print;
-
-    const pf = try PackFile.init(alloc, packBuffer, idxBuffer);
-    defer pf.deinit();
-
-    print("{} objects\n", .{pf.objectNames.items.len});
+    // open repo
+    var repo = try git.Repo.init(alloc, "../microwindows/.git/");
 
+    // input
     const r = std.io.getStdIn().reader();
     var inputBuffer = std.mem.zeroes([1024]u8);
 
+    // print HEAD
+    // const head = repo.getHead();
+    // const headObject = head.getObject();
+    // std.debug.print("HEAD: {x:0>40}\n", .{headObject.id});
+
+    // main loop
     while (true) {
+        // read line
         const input = r.readUntilDelimiter(&inputBuffer, '\n') catch continue;
 
+        // parse object id
         const id = std.fmt.parseInt(u160, input, 16) catch continue;
 
-        if (pf.findObjectOffset(id)) |offset| {
-            const o = try pf.getObject(offset);
-
-            if (o.type == 3) {
-                std.debug.print("object data: {s}\n\n", .{o.data[0..@min(o.data.len, 1000)]});
-            } else if (o.type == 2) {
-                var counter: u64 = 0;
-                while (counter < o.data.len) {
-                    const modeLen = std.mem.indexOfScalar(u8, o.data[counter..o.data.len], ' ') orelse break;
-                    const mode = o.data[counter .. counter + modeLen];
-                    counter += modeLen + 1;
-
-                    var nameLen: u64 = 0;
-                    while (counter + nameLen < o.data.len and o.data[counter + nameLen] != 0) {
-                        nameLen += 1;
-                    }
-                    const name = o.data[counter .. counter + nameLen];
-                    counter += nameLen + 1;
-
-                    if (counter + 20 <= o.data.len) {
-                        const hash: u160 = std.mem.readVarInt(u160, o.data[counter .. counter + 20], .big);
-                        counter += 20;
-
-                        std.debug.print("{s} {s} {x:0>40}\n", .{ mode, name, hash });
+        // print object
+        if (repo.objects.get(id)) |o| {
+            switch (o) {
+                .Blob => |blob| {
+                    std.debug.print("blob: {s}\n\n", .{blob.data});
+                },
+                .Tree => |tree| {
+                    for (tree.entries) |entry| {
+                        std.debug.print("{s} {s} {x:0>40}\n", .{ entry.mode, entry.name, entry.hash });
                     }
-                }
-                print("\n", .{});
-            } else {
-                std.debug.print("type: {}\n{s}\n", .{ o.type, o.data });
+                    std.debug.print("\n", .{});
+                },
+                .Commit => |commit| {
+                    std.debug.print("commit: {}", .{commit});
+                },
             }
         }
     }
-
-    // for (0..pf.objectNames.items.len) |i| {
-    //     print("object {x:0>40}:\n", .{pf.objectNames.items[i]});
-    //     const o = try pf.getObject(pf.objectOffsets.items[i]);
-    //     defer alloc.free(o.data);
-
-    //     if (o.type == 3) {
-    //         std.debug.print("object data: {s}\n\n", .{o.data[0..@min(o.data.len, 1000)]});
-    //     } else if (o.type == 2) {
-    //         var counter: u64 = 0;
-    //         while (counter < o.data.len) {
-    //             const modeLen = std.mem.indexOfScalar(u8, o.data[counter..o.data.len], ' ') orelse break;
-    //             const mode = o.data[counter .. counter + modeLen];
-    //             counter += modeLen + 1;
-
-    //             var nameLen: u64 = 0;
-    //             while (counter + nameLen < o.data.len and o.data[counter + nameLen] != 0) {
-    //                 nameLen += 1;
-    //             }
-    //             const name = o.data[counter .. counter + nameLen];
-    //             counter += nameLen + 1;
-
-    //             if (counter + 20 <= o.data.len) {
-    //                 const hash: u160 = std.mem.readVarInt(u160, o.data[counter .. counter + 20], .big);
-    //                 counter += 20;
-
-    //                 std.debug.print("{s} {s} {x:0>40}\n", .{ mode, name, hash });
-    //             }
-    //         }
-    //         print("\n", .{});
-    //     } else {
-    //         std.debug.print("type: {}\n", .{o.type});
-    //     }
-
-    //     if (o.type == 4) {
-    //         std.debug.print("type: {}\ndata: {s}\n\n", .{ o.type, o.data });
-    //     }
-    // }
 }