| ... | ... | @@ -950,7 +950,7 @@ pub const Repository = struct { |
| 950 | 950 | r.tags.deinit(r.gpa); |
| 951 | 951 | } |
| 952 | 952 | |
| 953 | | pub fn getObject(r: *Repository, arena: std.mem.Allocator, oid: Id) !?GitObject { |
| 953 | pub fn getObject(r: *Repository, arena: std.mem.Allocator, oid: Id) anyerror!?GitObject { |
| 954 | 954 | const t = tracer.trace(@src(), " {s}", .{oid}); |
| 955 | 955 | defer t.end(); |
| 956 | 956 | |
| ... | ... | @@ -1042,10 +1042,10 @@ pub const Repository = struct { |
| 1042 | 1042 | // parse .pack |
| 1043 | 1043 | // std.log.debug("pack_index={d} pack_offset={d}", .{ pack_index, pack_offset }); |
| 1044 | 1044 | |
| 1045 | | return try r.getPackedObject(oid, pack_index, pack_offset); |
| 1045 | return try r.getPackedObject(arena, oid, pack_index, pack_offset); |
| 1046 | 1046 | } |
| 1047 | 1047 | |
| 1048 | | fn getPackedObject(r: *Repository, maybe_oid: ?Id, pack_index: usize, pack_offset: usize) !GitObject { |
| 1048 | fn getPackedObject(r: *Repository, arena: std.mem.Allocator, maybe_oid: ?Id, pack_index: usize, pack_offset: usize) !GitObject { |
| 1049 | 1049 | const t = tracer.trace(@src(), " {?s} {d} {d}", .{ maybe_oid, pack_index, pack_offset }); |
| 1050 | 1050 | defer t.end(); |
| 1051 | 1051 | |
| ... | ... | @@ -1096,7 +1096,7 @@ pub const Repository = struct { |
| 1096 | 1096 | offset += 1; |
| 1097 | 1097 | } |
| 1098 | 1098 | const base_pack_offset = pack_offset - offset; |
| 1099 | | const base_obj = try r.getPackedObject(null, pack_index, base_pack_offset); |
| 1099 | const base_obj = try r.getPackedObject(arena, null, pack_index, base_pack_offset); |
| 1100 | 1100 | // std.log.debug("base: type={s} content=[{d}]", .{ @tagName(base_obj.type), base_obj.content.len }); |
| 1101 | 1101 | |
| 1102 | 1102 | const compressed_content = packedobj_fbs.rest()[0..size]; |
| ... | ... | @@ -1106,7 +1106,6 @@ pub const Repository = struct { |
| 1106 | 1106 | defer list.deinit(r.gpa); |
| 1107 | 1107 | try list.ensureUnusedCapacity(r.gpa, size); |
| 1108 | 1108 | try std.compress.flate.inflate.decompress(.zlib, bufr.anyReadable(), list.writer(r.gpa)); |
| 1109 | | |
| 1110 | 1109 | // std.log.debug("transformation data={d}", .{list.items}); |
| 1111 | 1110 | |
| 1112 | 1111 | var unpackedobj_fbs = nio.FixedBufferStream([]const u8).init(list.items); |
| ... | ... | @@ -1167,8 +1166,75 @@ pub const Repository = struct { |
| 1167 | 1166 | return obj; |
| 1168 | 1167 | }, |
| 1169 | 1168 | .ref_delta => { |
| 1170 | | std.log.debug("type={s} size={d}", .{ @tagName(ty), size }); |
| 1171 | | unreachable; |
| 1169 | // std.log.debug("type={s} size={d}", .{ @tagName(ty), size }); |
| 1170 | const base_oid = extras.to_hex(packedobj_fbs.takeSlice(20)[0..20].*); |
| 1171 | const base_obj = (try r.getObject(arena, &base_oid)).?; |
| 1172 | |
| 1173 | const compressed_content = packedobj_fbs.rest()[0..size]; |
| 1174 | var bufr = nio.FixedBufferStream([]const u8).init(compressed_content); |
| 1175 | |
| 1176 | var list: std.ArrayListUnmanaged(u8) = .empty; |
| 1177 | defer list.deinit(r.gpa); |
| 1178 | try list.ensureUnusedCapacity(r.gpa, size); |
| 1179 | try std.compress.flate.inflate.decompress(.zlib, bufr.anyReadable(), list.writer(r.gpa)); |
| 1180 | // std.log.debug("transformation data={d}", .{list.items}); |
| 1181 | |
| 1182 | var unpackedobj_fbs = nio.FixedBufferStream([]const u8).init(list.items); |
| 1183 | |
| 1184 | var list2: std.ArrayListUnmanaged(u8) = .empty; |
| 1185 | errdefer list2.deinit(r.gpa); |
| 1186 | |
| 1187 | var base_size: usize = 0; |
| 1188 | while (true) { |
| 1189 | const c2: usize = unpackedobj_fbs.takeByte(); |
| 1190 | base_size = (base_size << 7) | (c2 & 0x7f); |
| 1191 | if (c2 & 0x80 == 0) break; |
| 1192 | base_size += 1; |
| 1193 | } |
| 1194 | // std.log.debug("base_size={d}", .{base_size}); |
| 1195 | |
| 1196 | var obj_size: usize = 0; |
| 1197 | while (true) { |
| 1198 | const c2: usize = unpackedobj_fbs.takeByte(); |
| 1199 | obj_size = (obj_size << 7) | (c2 & 0x7f); |
| 1200 | if (c2 & 0x80 == 0) break; |
| 1201 | obj_size += 1; |
| 1202 | } |
| 1203 | // std.log.debug("obj_size={d}", .{obj_size}); |
| 1204 | |
| 1205 | while (unpackedobj_fbs.pos < unpackedobj_fbs.buffer.len) { |
| 1206 | const c2 = unpackedobj_fbs.takeByte(); |
| 1207 | if (c2 & 0x80 > 0) { |
| 1208 | // copy range from base |
| 1209 | var b: extras.RingBuffer(u8, 7) = .{}; |
| 1210 | for (0..7) |i| { |
| 1211 | const mask = @as(u8, 1) << @intCast(i); |
| 1212 | b.append(if (c2 & mask > 0) unpackedobj_fbs.takeByte() else 0); |
| 1213 | } |
| 1214 | const start: u32 = @bitCast(b.items[0..4].*); |
| 1215 | const nbytes: u24 = @bitCast(b.items[4..7].*); |
| 1216 | // std.log.debug("- copy from base: start={d} nbytes={d}", .{ start, nbytes }); |
| 1217 | const bytes = base_obj.content[start..][0..nbytes]; |
| 1218 | // std.log.debug("{s}\n", .{bytes}); |
| 1219 | try list2.appendSlice(r.gpa, bytes); |
| 1220 | } else { |
| 1221 | // append new data |
| 1222 | const nbytes = c2 & 0x7f; |
| 1223 | // std.log.debug("- append new bytes={d}", .{nbytes}); |
| 1224 | if (nbytes == 0) continue; |
| 1225 | const bytes = unpackedobj_fbs.takeSlice(nbytes); |
| 1226 | // std.log.debug("{s}\n", .{bytes}); |
| 1227 | try list2.appendSlice(r.gpa, bytes); |
| 1228 | } |
| 1229 | } |
| 1230 | |
| 1231 | // std.log.debug("- done", .{}); |
| 1232 | // std.log.debug("{s}\n", .{list2.items}); |
| 1233 | const _type = base_obj.type; |
| 1234 | const content = try list2.toOwnedSlice(r.gpa); |
| 1235 | const obj: GitObject = .{ .type = _type, .content = content }; |
| 1236 | if (maybe_oid) |oid| try r.unpacked_objects.put(r.gpa, oid, obj); |
| 1237 | return obj; |
| 1172 | 1238 | }, |
| 1173 | 1239 | } |
| 1174 | 1240 | comptime unreachable; |