authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-04-20 17:46:26 -07:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-04-20 17:46:26 -07:00
log0099e96f6f35c65569d8370c617640503d48edbb
tree0c9c9fe157cd9dba332e299878cd6005045597f6
parent52d3c1ee59c734fa12302409e2b4531af05b8ae8
signaturebadge-check Signed by SSH key SHA256:4hHJbtBRU58AYXwjL7fkz2fnQHdiye8x1QpTCQ0sHNw

cache ofs_delta objects too


1 files changed, 18 insertions(+), 9 deletions(-)

git.zig+18-9
...@@ -828,7 +828,8 @@ pub const BlameIterator = struct {...@@ -828,7 +828,8 @@ pub const BlameIterator = struct {
828pub const Repository = struct {828pub const Repository = struct {
829 gitdir: nfs.Dir,829 gitdir: nfs.Dir,
830 gpa: std.mem.Allocator,830 gpa: std.mem.Allocator,
831 unpacked_objects: std.StringArrayHashMapUnmanaged(GitObject),831 unpacked_loose_objects: std.StringArrayHashMapUnmanaged(GitObject),
832 unpacked_objects: std.AutoArrayHashMapUnmanaged(u64, GitObject),
832 idx_content: std.StringArrayHashMapUnmanaged([]const u8),833 idx_content: std.StringArrayHashMapUnmanaged([]const u8),
833 pack_content: std.StringArrayHashMapUnmanaged([]const u8),834 pack_content: std.StringArrayHashMapUnmanaged([]const u8),
834 commits: std.StringArrayHashMapUnmanaged(Commit),835 commits: std.StringArrayHashMapUnmanaged(Commit),
...@@ -839,6 +840,7 @@ pub const Repository = struct {...@@ -839,6 +840,7 @@ pub const Repository = struct {
839 return .{840 return .{
840 .gitdir = gitdir,841 .gitdir = gitdir,
841 .gpa = gpa,842 .gpa = gpa,
843 .unpacked_loose_objects = .empty,
842 .unpacked_objects = .empty,844 .unpacked_objects = .empty,
843 .idx_content = .empty,845 .idx_content = .empty,
844 .pack_content = .empty,846 .pack_content = .empty,
...@@ -849,6 +851,8 @@ pub const Repository = struct {...@@ -849,6 +851,8 @@ pub const Repository = struct {
849 }851 }
850852
851 pub fn deinit(r: *Repository) void {853 pub fn deinit(r: *Repository) void {
854 for (r.unpacked_loose_objects.values()) |v| r.gpa.free(v.content);
855 r.unpacked_loose_objects.deinit(r.gpa);
852 for (r.unpacked_objects.values()) |v| r.gpa.free(v.content);856 for (r.unpacked_objects.values()) |v| r.gpa.free(v.content);
853 r.unpacked_objects.deinit(r.gpa);857 r.unpacked_objects.deinit(r.gpa);
854 for (r.idx_content.values()) |v| nfs.munmap(v);858 for (r.idx_content.values()) |v| nfs.munmap(v);
...@@ -865,7 +869,7 @@ pub const Repository = struct {...@@ -865,7 +869,7 @@ pub const Repository = struct {
865 const t = tracer.trace(@src(), " {s}", .{oid});869 const t = tracer.trace(@src(), " {s}", .{oid});
866 defer t.end();870 defer t.end();
867871
868 if (r.unpacked_objects.get(oid)) |obj| {872 if (r.unpacked_loose_objects.get(oid)) |obj| {
869 return obj;873 return obj;
870 }874 }
871 if (oid.len == 40) blk: { //sha1 object875 if (oid.len == 40) blk: { //sha1 object
...@@ -893,7 +897,7 @@ pub const Repository = struct {...@@ -893,7 +897,7 @@ pub const Repository = struct {
893 const content = try list.toOwnedSlice(r.gpa);897 const content = try list.toOwnedSlice(r.gpa);
894 std.debug.assert(content.len == content_len);898 std.debug.assert(content.len == content_len);
895 const obj: GitObject = .{ .type = _type, .content = content };899 const obj: GitObject = .{ .type = _type, .content = content };
896 try r.unpacked_objects.put(r.gpa, oid, obj);900 try r.unpacked_loose_objects.put(r.gpa, oid, obj);
897 return obj;901 return obj;
898 }902 }
899903
...@@ -987,6 +991,9 @@ pub const Repository = struct {...@@ -987,6 +991,9 @@ pub const Repository = struct {
987 const t = tracer.trace(@src(), " {?s} {d} {d} {s}", .{ maybe_oid, pack_index, pack_offset, r.pack_content.keys()[pack_index] });991 const t = tracer.trace(@src(), " {?s} {d} {d} {s}", .{ maybe_oid, pack_index, pack_offset, r.pack_content.keys()[pack_index] });
988 defer t.end();992 defer t.end();
989993
994 const key = std.hash.Wyhash.hash(0, &(std.mem.toBytes(pack_index) ++ std.mem.toBytes(pack_offset)));
995 if (r.unpacked_objects.get(key)) |o| return o;
996
990 const pack_content = r.pack_content.values()[pack_index];997 const pack_content = r.pack_content.values()[pack_index];
991 if (!std.mem.eql(u8, pack_content[0..4], "PACK")) return error.InvalidGitPack;998 if (!std.mem.eql(u8, pack_content[0..4], "PACK")) return error.InvalidGitPack;
992 const pack_version = std.mem.readInt(u32, pack_content[4..][0..4], .big);999 const pack_version = std.mem.readInt(u32, pack_content[4..][0..4], .big);
...@@ -1024,7 +1031,7 @@ pub const Repository = struct {...@@ -1024,7 +1031,7 @@ pub const Repository = struct {
1024 const _type = std.meta.stringToEnum(RefType, @tagName(ty)).?;1031 const _type = std.meta.stringToEnum(RefType, @tagName(ty)).?;
1025 const content = try list.toOwnedSlice(r.gpa);1032 const content = try list.toOwnedSlice(r.gpa);
1026 const obj: GitObject = .{ .type = _type, .content = content };1033 const obj: GitObject = .{ .type = _type, .content = content };
1027 if (maybe_oid) |oid| try r.unpacked_objects.put(r.gpa, oid, obj);1034 try r.unpacked_objects.put(r.gpa, key, obj);
1028 return obj;1035 return obj;
1029 },1036 },
1030 .ofs_delta => {1037 .ofs_delta => {
...@@ -1037,13 +1044,12 @@ pub const Repository = struct {...@@ -1037,13 +1044,12 @@ pub const Repository = struct {
1037 }1044 }
1038 const base_pack_offset = pack_offset - offset;1045 const base_pack_offset = pack_offset - offset;
1039 const base_obj = try r.getPackedObject(arena, null, pack_index, base_pack_offset);1046 const base_obj = try r.getPackedObject(arena, null, pack_index, base_pack_offset);
1040 defer r.gpa.free(base_obj.content);1047 return r.getDeltadObject(maybe_oid, key, &packedobj_fbs, size, base_obj);
1041 return r.getDeltadObject(maybe_oid, &packedobj_fbs, size, base_obj);
1042 },1048 },
1043 .ref_delta => {1049 .ref_delta => {
1044 const base_oid = extras.to_hex(packedobj_fbs.takeSlice(20)[0..20].*);1050 const base_oid = extras.to_hex(packedobj_fbs.takeSlice(20)[0..20].*);
1045 const base_obj = (try r.getObject(arena, &base_oid)).?;1051 const base_obj = (try r.getObject(arena, &base_oid)).?;
1046 return r.getDeltadObject(maybe_oid, &packedobj_fbs, size, base_obj);1052 return r.getDeltadObject(maybe_oid, key, &packedobj_fbs, size, base_obj);
1047 },1053 },
1048 }1054 }
1049 comptime unreachable;1055 comptime unreachable;
...@@ -1055,7 +1061,7 @@ pub const Repository = struct {...@@ -1055,7 +1061,7 @@ pub const Repository = struct {
1055 }1061 }
1056 }1062 }
10571063
1058 fn getDeltadObject(r: *Repository, maybe_oid: ?Id, packedobj_fbs: *nio.FixedBufferStream([]const u8), size: usize, base_obj: GitObject) !GitObject {1064 fn getDeltadObject(r: *Repository, maybe_oid: ?Id, key: u64, packedobj_fbs: *nio.FixedBufferStream([]const u8), size: usize, base_obj: GitObject) !GitObject {
1059 const compressed_content = packedobj_fbs.rest();1065 const compressed_content = packedobj_fbs.rest();
1060 var list: std.ArrayListUnmanaged(u8) = .empty;1066 var list: std.ArrayListUnmanaged(u8) = .empty;
1061 defer list.deinit(r.gpa);1067 defer list.deinit(r.gpa);
...@@ -1122,7 +1128,10 @@ pub const Repository = struct {...@@ -1122,7 +1128,10 @@ pub const Repository = struct {
1122 const _type = base_obj.type;1128 const _type = base_obj.type;
1123 const content = try list2.toOwnedSlice(r.gpa);1129 const content = try list2.toOwnedSlice(r.gpa);
1124 const obj: GitObject = .{ .type = _type, .content = content };1130 const obj: GitObject = .{ .type = _type, .content = content };
1125 if (maybe_oid) |oid| try r.unpacked_objects.put(r.gpa, oid, obj);1131 if (maybe_oid) |oid|
1132 try r.unpacked_loose_objects.put(r.gpa, oid, obj)
1133 else
1134 try r.unpacked_objects.put(r.gpa, key, obj);
1126 return obj;1135 return obj;
1127 }1136 }
11281137