| ... | ... | @@ -828,7 +828,8 @@ pub const BlameIterator = struct { |
| 828 | 828 | pub const Repository = struct { |
| 829 | 829 | gitdir: nfs.Dir, |
| 830 | 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 | 833 | idx_content: std.StringArrayHashMapUnmanaged([]const u8), |
| 833 | 834 | pack_content: std.StringArrayHashMapUnmanaged([]const u8), |
| 834 | 835 | commits: std.StringArrayHashMapUnmanaged(Commit), |
| ... | ... | @@ -839,6 +840,7 @@ pub const Repository = struct { |
| 839 | 840 | return .{ |
| 840 | 841 | .gitdir = gitdir, |
| 841 | 842 | .gpa = gpa, |
| 843 | .unpacked_loose_objects = .empty, |
| 842 | 844 | .unpacked_objects = .empty, |
| 843 | 845 | .idx_content = .empty, |
| 844 | 846 | .pack_content = .empty, |
| ... | ... | @@ -849,6 +851,8 @@ pub const Repository = struct { |
| 849 | 851 | } |
| 850 | 852 | |
| 851 | 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 | 856 | for (r.unpacked_objects.values()) |v| r.gpa.free(v.content); |
| 853 | 857 | r.unpacked_objects.deinit(r.gpa); |
| 854 | 858 | for (r.idx_content.values()) |v| nfs.munmap(v); |
| ... | ... | @@ -865,7 +869,7 @@ pub const Repository = struct { |
| 865 | 869 | const t = tracer.trace(@src(), " {s}", .{oid}); |
| 866 | 870 | defer t.end(); |
| 867 | 871 | |
| 868 | | if (r.unpacked_objects.get(oid)) |obj| { |
| 872 | if (r.unpacked_loose_objects.get(oid)) |obj| { |
| 869 | 873 | return obj; |
| 870 | 874 | } |
| 871 | 875 | if (oid.len == 40) blk: { //sha1 object |
| ... | ... | @@ -893,7 +897,7 @@ pub const Repository = struct { |
| 893 | 897 | const content = try list.toOwnedSlice(r.gpa); |
| 894 | 898 | std.debug.assert(content.len == content_len); |
| 895 | 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 | 901 | return obj; |
| 898 | 902 | } |
| 899 | 903 | |
| ... | ... | @@ -987,6 +991,9 @@ pub const Repository = struct { |
| 987 | 991 | const t = tracer.trace(@src(), " {?s} {d} {d} {s}", .{ maybe_oid, pack_index, pack_offset, r.pack_content.keys()[pack_index] }); |
| 988 | 992 | defer t.end(); |
| 989 | 993 | |
| 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 | 997 | const pack_content = r.pack_content.values()[pack_index]; |
| 991 | 998 | if (!std.mem.eql(u8, pack_content[0..4], "PACK")) return error.InvalidGitPack; |
| 992 | 999 | const pack_version = std.mem.readInt(u32, pack_content[4..][0..4], .big); |
| ... | ... | @@ -1024,7 +1031,7 @@ pub const Repository = struct { |
| 1024 | 1031 | const _type = std.meta.stringToEnum(RefType, @tagName(ty)).?; |
| 1025 | 1032 | const content = try list.toOwnedSlice(r.gpa); |
| 1026 | 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 | 1035 | return obj; |
| 1029 | 1036 | }, |
| 1030 | 1037 | .ofs_delta => { |
| ... | ... | @@ -1037,13 +1044,12 @@ pub const Repository = struct { |
| 1037 | 1044 | } |
| 1038 | 1045 | const base_pack_offset = pack_offset - offset; |
| 1039 | 1046 | const base_obj = try r.getPackedObject(arena, null, pack_index, base_pack_offset); |
| 1040 | | defer r.gpa.free(base_obj.content); |
| 1041 | | return r.getDeltadObject(maybe_oid, &packedobj_fbs, size, base_obj); |
| 1047 | return r.getDeltadObject(maybe_oid, key, &packedobj_fbs, size, base_obj); |
| 1042 | 1048 | }, |
| 1043 | 1049 | .ref_delta => { |
| 1044 | 1050 | const base_oid = extras.to_hex(packedobj_fbs.takeSlice(20)[0..20].*); |
| 1045 | 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 | 1055 | comptime unreachable; |
| ... | ... | @@ -1055,7 +1061,7 @@ pub const Repository = struct { |
| 1055 | 1061 | } |
| 1056 | 1062 | } |
| 1057 | 1063 | |
| 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 | 1065 | const compressed_content = packedobj_fbs.rest(); |
| 1060 | 1066 | var list: std.ArrayListUnmanaged(u8) = .empty; |
| 1061 | 1067 | defer list.deinit(r.gpa); |
| ... | ... | @@ -1122,7 +1128,10 @@ pub const Repository = struct { |
| 1122 | 1128 | const _type = base_obj.type; |
| 1123 | 1129 | const content = try list2.toOwnedSlice(r.gpa); |
| 1124 | 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 | 1135 | return obj; |
| 1127 | 1136 | } |
| 1128 | 1137 | |