authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-06-27 19:31:01 -07:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-06-27 19:31:01 -07:00
logba166a3a7d614ee1bfd2475460410146666aebb9
treef6d5c5a5d81af0031a16939065ac8c6ae351dfec
parentfc9a0e648f726225767dbf69ed931b3b321a8dcc
signaturebadge-check Signed by SSH key SHA256:4hHJbtBRU58AYXwjL7fkz2fnQHdiye8x1QpTCQ0sHNw

make Tree own its memory


1 files changed, 25 insertions(+), 15 deletions(-)

git.zig+25-15
......@@ -724,7 +724,7 @@ pub const Repository = struct {
724724 idx_content: std.StringArrayHashMapUnmanaged([]const u8),
725725 pack_content: std.StringArrayHashMapUnmanaged([]const u8),
726726 commits: std.StringArrayHashMapUnmanaged(Commit),
727 trees: std.StringArrayHashMapUnmanaged(Tree),
727 trees: std.StringArrayHashMapUnmanaged(*Tree),
728728 tags: std.StringArrayHashMapUnmanaged(*Tag),
729729 mailmap: std.hash_map.StringHashMapUnmanaged([]const u8),
730730 mailmap_names: std.hash_map.StringHashMapUnmanaged([]const u8),
......@@ -759,7 +759,7 @@ pub const Repository = struct {
759759 r.pack_content.deinit(r.gpa);
760760 for (r.commits.values()) |v| r.gpa.free(v.parents);
761761 r.commits.deinit(r.gpa);
762 for (r.trees.values()) |*v| r.gpa.free(v.children);
762 for (r.trees.values()) |v| v.destroy(r);
763763 r.trees.deinit(r.gpa);
764764 for (r.tags.values()) |v| v.destroy(r);
765765 r.tags.deinit(r.gpa);
......@@ -1125,16 +1125,18 @@ pub const Repository = struct {
11251125 return (try r.getCommit(.{ .id = id }, cache_behavior)).?.@"1";
11261126 }
11271127
1128 pub fn getTree(r: *Repository, id: TreeId, cache_behavior: CacheBehavior) !?struct { TreeId, Tree } {
1128 pub fn getTree(r: *Repository, id: TreeId, cache_behavior: CacheBehavior) !?struct { TreeId, *Tree } {
11291129 const t = tracer.trace(@src(), " {s}", .{id.id});
11301130 defer t.end();
11311131
1132 if (cache_behavior == .cache) if (r.trees.getPtr(id.id)) |val| {
1133 return .{ id, val.* };
1132 if (cache_behavior == .cache) if (r.trees.get(id.id)) |val| {
1133 return .{ id, val };
11341134 };
11351135 if (try r.getObject(id.id, cache_behavior)) |obj| {
11361136 if (obj.type == .tree) {
11371137 errdefer if (cache_behavior == .no_cache) r.gpa.free(obj.content);
1138 const raw = try r.gpa.dupe(u8, obj.content);
1139 errdefer r.gpa.free(raw);
11381140 var children: std.ArrayList(Tree.Object) = .empty;
11391141 errdefer children.deinit(r.gpa);
11401142 try children.ensureUnusedCapacity(r.gpa, 33);
......@@ -1173,7 +1175,9 @@ pub const Repository = struct {
11731175 .symlink => .{ .blob = .{ .id = &item.id_bytes } },
11741176 .none => unreachable,
11751177 };
1176 const tree: Tree = .{ .raw = obj.content, .children = children_slice };
1178 const tree = try r.gpa.create(Tree);
1179 errdefer r.gpa.destroy(tree);
1180 tree.* = .{ .raw = obj.content, .children = children_slice };
11771181 if (cache_behavior == .cache) try r.trees.put(r.gpa, id.id, tree);
11781182 return .{ id, tree };
11791183 }
......@@ -1182,7 +1186,7 @@ pub const Repository = struct {
11821186 return null;
11831187 }
11841188
1185 pub fn getTreeA(r: *Repository, id: Id, cache_behavior: CacheBehavior) !Tree {
1189 pub fn getTreeA(r: *Repository, id: Id, cache_behavior: CacheBehavior) !*Tree {
11861190 return (try r.getTree(.{ .id = id }, cache_behavior)).?.@"1";
11871191 }
11881192
......@@ -1190,8 +1194,8 @@ pub const Repository = struct {
11901194 const t = tracer.trace(@src(), " {s}", .{id.id});
11911195 defer t.end();
11921196
1193 if (cache_behavior == .cache) if (r.tags.getPtr(id.id)) |val| {
1194 return .{ id, val.* };
1197 if (cache_behavior == .cache) if (r.tags.get(id.id)) |val| {
1198 return .{ id, val };
11951199 };
11961200 if (try r.getObject(id.id, cache_behavior)) |obj| {
11971201 if (obj.type == .tag) {
......@@ -1719,7 +1723,13 @@ pub const Tree = struct {
17191723 raw: []const u8,
17201724 children: []const Object,
17211725
1722 pub fn get(self: Tree, name: string) ?Object {
1726 pub fn destroy(t: *Tree, r: *Repository) void {
1727 r.gpa.free(t.children);
1728 r.gpa.free(t.raw);
1729 r.gpa.destroy(t);
1730 }
1731
1732 pub fn get(self: *Tree, name: string) ?Object {
17231733 // modified std.sort.binarySearch
17241734 const i = blk: {
17251735 var low: usize = 0;
......@@ -1749,13 +1759,13 @@ pub const Tree = struct {
17491759 return self.children[i];
17501760 }
17511761
1752 pub fn getBlob(self: Tree, name: string, hint: Object.Type) ?Object {
1762 pub fn getBlob(self: *Tree, name: string, hint: Object.Type) ?Object {
17531763 const o = self.get(name, hint) orelse return null;
17541764 if (o.id != .blob) return null;
17551765 return o;
17561766 }
17571767
1758 pub fn find(self: Tree, name: string) ?Object {
1768 pub fn find(self: *Tree, name: string) ?Object {
17591769 for (self.children, 0..) |item, i| {
17601770 if (std.ascii.eqlIgnoreCase(item.name, name)) {
17611771 return self.children[i];
......@@ -1764,7 +1774,7 @@ pub const Tree = struct {
17641774 return null;
17651775 }
17661776
1767 pub fn findBlob(self: Tree, name: string) ?Object {
1777 pub fn findBlob(self: *Tree, name: string) ?Object {
17681778 const o = self.find(name) orelse return null;
17691779 if (o.id != .blob) return null;
17701780 return o;
......@@ -1929,7 +1939,7 @@ pub const Tree = struct {
19291939 };
19301940 };
19311941
1932 pub fn walk(self: Tree, r: *Repository) !Walker {
1942 pub fn walk(self: *Tree, r: *Repository) !Walker {
19331943 var stack: std.ArrayListUnmanaged(Walker.StackItem) = .empty;
19341944
19351945 try stack.append(r.gpa, .{
......@@ -1955,7 +1965,7 @@ pub const Tree = struct {
19551965 };
19561966
19571967 const StackItem = struct {
1958 tree: Tree,
1968 tree: *Tree,
19591969 idx: usize,
19601970 dirname_len: usize,
19611971 };