| ... | ... | @@ -975,13 +975,15 @@ pub const BlameIterator = struct { |
| 975 | 975 | pub const Repository = struct { |
| 976 | 976 | gitdir: nfs.Dir, |
| 977 | 977 | gpa: std.mem.Allocator, |
| 978 | | raw_object_contents: std.StringArrayHashMapUnmanaged([]const u8), |
| 978 | raw_object_contents: std.StringArrayHashMapUnmanaged(RawObject), |
| 979 | 979 | idx_content: std.StringArrayHashMapUnmanaged([]const u8), |
| 980 | 980 | pack_content: std.StringArrayHashMapUnmanaged([]const u8), |
| 981 | 981 | commits: std.StringArrayHashMapUnmanaged(Commit), |
| 982 | 982 | trees: std.StringArrayHashMapUnmanaged(Tree), |
| 983 | 983 | tags: std.StringArrayHashMapUnmanaged(Tag), |
| 984 | 984 | |
| 985 | const RawObject = struct { RefType, []const u8 }; |
| 986 | |
| 985 | 987 | pub fn init(gitdir: nfs.Dir, gpa: std.mem.Allocator) Repository { |
| 986 | 988 | return .{ |
| 987 | 989 | .gitdir = gitdir, |
| ... | ... | @@ -996,7 +998,7 @@ pub const Repository = struct { |
| 996 | 998 | } |
| 997 | 999 | |
| 998 | 1000 | pub fn deinit(r: *Repository) void { |
| 999 | | for (r.raw_object_contents.values()) |v| r.gpa.free(v); |
| 1001 | for (r.raw_object_contents.values()) |v| r.gpa.free(v[1]); |
| 1000 | 1002 | r.raw_object_contents.deinit(r.gpa); |
| 1001 | 1003 | for (r.idx_content.values()) |v| nfs.munmap(v); |
| 1002 | 1004 | r.idx_content.deinit(r.gpa); |
| ... | ... | @@ -1008,9 +1010,9 @@ pub const Repository = struct { |
| 1008 | 1010 | r.tags.deinit(r.gpa); |
| 1009 | 1011 | } |
| 1010 | 1012 | |
| 1011 | | fn getObject(r: *Repository, obj: Id, arena: std.mem.Allocator) !?[]const u8 { |
| 1012 | | if (r.raw_object_contents.get(obj)) |content| { |
| 1013 | | return content; |
| 1013 | fn getObject(r: *Repository, obj: Id, arena: std.mem.Allocator) !?RawObject { |
| 1014 | if (r.raw_object_contents.get(obj)) |data| { |
| 1015 | return data; |
| 1014 | 1016 | } |
| 1015 | 1017 | if (obj.len == 40) blk: { //sha1 object |
| 1016 | 1018 | var sub_path: [49:0]u8 = "objects/00/00000000000000000000000000000000000000".*; |
| ... | ... | @@ -1026,9 +1028,16 @@ pub const Repository = struct { |
| 1026 | 1028 | errdefer list.deinit(); |
| 1027 | 1029 | try list.ensureUnusedCapacity(512); |
| 1028 | 1030 | try std.compress.flate.inflate.decompress(.zlib, bufr.anyReadable(), list.writer()); |
| 1031 | const data = list.items; |
| 1032 | const header = data[0..std.mem.indexOfScalar(u8, data, 0).?]; |
| 1033 | const _type_s = header[0..std.mem.indexOfScalar(u8, header, ' ').?]; |
| 1034 | const _type = std.meta.stringToEnum(RefType, _type_s).?; |
| 1035 | const content_len = try extras.parseDigits(u64, header[_type_s.len + 1 ..], 10); |
| 1036 | list.replaceRangeAssumeCapacity(0, header.len + 1, ""); |
| 1029 | 1037 | const content = try list.toOwnedSlice(); |
| 1030 | | try r.raw_object_contents.put(r.gpa, obj, content); |
| 1031 | | return content; |
| 1038 | std.debug.assert(content.len == content_len); |
| 1039 | try r.raw_object_contents.put(r.gpa, obj, .{ _type, content }); |
| 1040 | return .{ _type, content }; |
| 1032 | 1041 | } |
| 1033 | 1042 | |
| 1034 | 1043 | // read .idx |
| ... | ... | @@ -1092,7 +1101,7 @@ pub const Repository = struct { |
| 1092 | 1101 | return try r.getPackedObject(obj, pack_index, pack_offset); |
| 1093 | 1102 | } |
| 1094 | 1103 | |
| 1095 | | fn getPackedObject(r: *Repository, maybe_obj: ?Id, pack_index: usize, pack_offset: usize) ![]const u8 { |
| 1104 | fn getPackedObject(r: *Repository, maybe_obj: ?Id, pack_index: usize, pack_offset: usize) !RawObject { |
| 1096 | 1105 | const pack_content = r.pack_content.values()[pack_index]; |
| 1097 | 1106 | if (!std.mem.eql(u8, pack_content[0..4], "PACK")) return error.InvalidGitPack; |
| 1098 | 1107 | const pack_version = std.mem.readInt(u32, pack_content[4..][0..4], .big); |
| ... | ... | @@ -1128,12 +1137,11 @@ pub const Repository = struct { |
| 1128 | 1137 | var list: std.ArrayList(u8) = .init(r.gpa); |
| 1129 | 1138 | errdefer list.deinit(); |
| 1130 | 1139 | try list.ensureUnusedCapacity(512); |
| 1131 | | try list.appendSlice(@tagName(ty)); |
| 1132 | | try list.writer().print(" {d}\x00", .{size}); |
| 1133 | 1140 | try std.compress.flate.inflate.decompress(.zlib, bufr.anyReadable(), list.writer()); |
| 1141 | const _type = std.meta.stringToEnum(RefType, @tagName(ty)).?; |
| 1134 | 1142 | const content = try list.toOwnedSlice(); |
| 1135 | | if (maybe_obj) |obj| try r.raw_object_contents.put(r.gpa, obj, content); |
| 1136 | | return content; |
| 1143 | if (maybe_obj) |obj| try r.raw_object_contents.put(r.gpa, obj, .{ _type, content }); |
| 1144 | return .{ _type, content }; |
| 1137 | 1145 | }, |
| 1138 | 1146 | .ofs_delta => { |
| 1139 | 1147 | std.log.debug("type={s} size={d}", .{ @tagName(ty), size }); |
| ... | ... | @@ -1155,14 +1163,8 @@ pub const Repository = struct { |
| 1155 | 1163 | |
| 1156 | 1164 | pub fn getGitObject(r: *Repository, arena: std.mem.Allocator, obj: Id) !?GitObject { |
| 1157 | 1165 | if (try r.getObject(obj, arena)) |data| { |
| 1158 | | const header = data[0..std.mem.indexOfScalar(u8, data, 0).?]; |
| 1159 | | const _type = header[0..std.mem.indexOfScalar(u8, header, ' ').?]; |
| 1160 | | const content_len = try extras.parseDigits(u64, header[_type.len + 1 ..], 10); |
| 1161 | | std.debug.assert(data[header.len + 1 ..].len == content_len); |
| 1162 | | return .{ |
| 1163 | | .type = std.meta.stringToEnum(RefType, _type).?, |
| 1164 | | .content = try arena.dupe(u8, data[header.len + 1 ..]), |
| 1165 | | }; |
| 1166 | const _type, const content = data; |
| 1167 | return .{ .type = _type, .content = content }; |
| 1166 | 1168 | } |
| 1167 | 1169 | return null; |
| 1168 | 1170 | } |