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