authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-03-27 19:12:16 -07:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-03-27 19:12:46 -07:00
logc13c8f2860e25e1674800059afe19c95897c26c6
tree90a774ab8f8f07acda0ba5fc64d3d23956aeabb9
parent6763a8608ffdf2462f6678145ac8d76cc418ff32
signaturebadge-check Signed by SSH key SHA256:4hHJbtBRU58AYXwjL7fkz2fnQHdiye8x1QpTCQ0sHNw

add getTree to Repository


1 files changed, 51 insertions(+), 0 deletions(-)

git.zig+51
...@@ -950,6 +950,7 @@ pub const Repository = struct {...@@ -950,6 +950,7 @@ pub const Repository = struct {
950 gpa: std.mem.Allocator,950 gpa: std.mem.Allocator,
951 raw_object_contents: std.StringArrayHashMapUnmanaged([]const u8),951 raw_object_contents: std.StringArrayHashMapUnmanaged([]const u8),
952 commits: std.StringArrayHashMapUnmanaged(Commit),952 commits: std.StringArrayHashMapUnmanaged(Commit),
953 trees: std.StringArrayHashMapUnmanaged(Tree),
953954
954 pub fn init(gitdir: nfs.Dir, gpa: std.mem.Allocator) Repository {955 pub fn init(gitdir: nfs.Dir, gpa: std.mem.Allocator) Repository {
955 return .{956 return .{
...@@ -957,6 +958,7 @@ pub const Repository = struct {...@@ -957,6 +958,7 @@ pub const Repository = struct {
957 .gpa = gpa,958 .gpa = gpa,
958 .raw_object_contents = .empty,959 .raw_object_contents = .empty,
959 .commits = .empty,960 .commits = .empty,
961 .trees = .empty,
960 };962 };
961 }963 }
962964
...@@ -964,6 +966,8 @@ pub const Repository = struct {...@@ -964,6 +966,8 @@ pub const Repository = struct {
964 for (r.raw_object_contents.values()) |v| r.gpa.free(v);966 for (r.raw_object_contents.values()) |v| r.gpa.free(v);
965 r.raw_object_contents.deinit(r.gpa);967 r.raw_object_contents.deinit(r.gpa);
966 r.commits.deinit(r.gpa);968 r.commits.deinit(r.gpa);
969 for (r.trees.values()) |v| r.gpa.free(v.children);
970 r.trees.deinit(r.gpa);
967 }971 }
968972
969 fn getObject(r: *Repository, obj: Id) !?[]const u8 {973 fn getObject(r: *Repository, obj: Id) !?[]const u8 {
...@@ -1030,4 +1034,51 @@ pub const Repository = struct {...@@ -1030,4 +1034,51 @@ pub const Repository = struct {
1030 }1034 }
1031 return null;1035 return null;
1032 }1036 }
1037
1038 pub fn getTree(r: *Repository, arena: std.mem.Allocator, id: TreeId) !?struct { TreeId, Tree } {
1039 if (r.trees.getPtr(id.id)) |val| {
1040 return .{ id, val.* };
1041 }
1042 if (try r.getGitObject(id.id, arena)) |obj| {
1043 if (obj.type == .tree) {
1044 var children = std.ArrayList(Tree.Object).init(r.gpa);
1045 errdefer children.deinit();
1046 var i: usize = 0;
1047 while (i < obj.content.len) {
1048 const mode_end = std.mem.indexOfScalar(u8, obj.content[i..], ' ').?;
1049 const mode = obj.content[i..][0..mode_end];
1050 i += mode_end + 1;
1051
1052 const name_end = std.mem.indexOfScalar(u8, obj.content[i..], 0).?;
1053 const name = obj.content[i..][0..name_end :0];
1054 i += name_end + 1;
1055
1056 const oid_raw = obj.content[i..][0..20].*;
1057 const oid_hex = (try arena.alloc(u8, 40))[0..40];
1058 oid_hex.* = extras.to_hex(oid_raw);
1059 i += 20;
1060
1061 var mode_buf: [6]u8 = @splat('0');
1062 @memcpy(mode_buf[6 - mode.len ..], mode);
1063 const mode_real = try parseTreeMode(&mode_buf);
1064
1065 try children.append(.{
1066 .mode = mode_real,
1067 .name = name,
1068 .id = switch (mode_real.type) {
1069 .file => .{ .blob = .{ .id = oid_hex } },
1070 .directory => .{ .tree = .{ .id = oid_hex } },
1071 .submodule => .{ .commit = .{ .id = oid_hex } },
1072 .symlink => .{ .blob = .{ .id = oid_hex } },
1073 .none => unreachable,
1074 },
1075 });
1076 }
1077 const tree: Tree = .{ .children = try children.toOwnedSlice() };
1078 try r.trees.put(r.gpa, id.id, tree);
1079 return .{ id, tree };
1080 }
1081 }
1082 return null;
1083 }
1033};1084};