| ... | @@ -1098,143 +1098,14 @@ pub const Repository = struct { | ... | @@ -1098,143 +1098,14 @@ pub const Repository = struct { |
| 1098 | const base_pack_offset = pack_offset - offset; | 1098 | const base_pack_offset = pack_offset - offset; |
| 1099 | const base_obj = try r.getPackedObject(arena, null, pack_index, base_pack_offset); | 1099 | const base_obj = try r.getPackedObject(arena, null, pack_index, base_pack_offset); |
| 1100 | // std.log.debug("base: type={s} content=[{d}]", .{ @tagName(base_obj.type), base_obj.content.len }); | 1100 | // std.log.debug("base: type={s} content=[{d}]", .{ @tagName(base_obj.type), base_obj.content.len }); |
| 1101 | | 1101 | return r.getDeltadObject(maybe_oid, &packedobj_fbs, size, base_obj); |
| 1102 | const compressed_content = packedobj_fbs.rest()[0..size]; | | |
| 1103 | var bufr = nio.FixedBufferStream([]const u8).init(compressed_content); | | |
| 1104 | | | |
| 1105 | var list: std.ArrayListUnmanaged(u8) = .empty; | | |
| 1106 | defer list.deinit(r.gpa); | | |
| 1107 | try list.ensureUnusedCapacity(r.gpa, size); | | |
| 1108 | try std.compress.flate.inflate.decompress(.zlib, bufr.anyReadable(), list.writer(r.gpa)); | | |
| 1109 | // std.log.debug("transformation data={d}", .{list.items}); | | |
| 1110 | | | |
| 1111 | var unpackedobj_fbs = nio.FixedBufferStream([]const u8).init(list.items); | | |
| 1112 | | | |
| 1113 | var list2: std.ArrayListUnmanaged(u8) = .empty; | | |
| 1114 | errdefer list2.deinit(r.gpa); | | |
| 1115 | | | |
| 1116 | var base_size: usize = 0; | | |
| 1117 | while (true) { | | |
| 1118 | const c2: usize = unpackedobj_fbs.takeByte(); | | |
| 1119 | base_size = (base_size << 7) | (c2 & 0x7f); | | |
| 1120 | if (c2 & 0x80 == 0) break; | | |
| 1121 | base_size += 1; | | |
| 1122 | } | | |
| 1123 | // std.log.debug("base_size={d}", .{base_size}); | | |
| 1124 | | | |
| 1125 | var obj_size: usize = 0; | | |
| 1126 | while (true) { | | |
| 1127 | const c2: usize = unpackedobj_fbs.takeByte(); | | |
| 1128 | obj_size = (obj_size << 7) | (c2 & 0x7f); | | |
| 1129 | if (c2 & 0x80 == 0) break; | | |
| 1130 | obj_size += 1; | | |
| 1131 | } | | |
| 1132 | // std.log.debug("obj_size={d}", .{obj_size}); | | |
| 1133 | | | |
| 1134 | while (unpackedobj_fbs.pos < unpackedobj_fbs.buffer.len) { | | |
| 1135 | const c2 = unpackedobj_fbs.takeByte(); | | |
| 1136 | if (c2 & 0x80 > 0) { | | |
| 1137 | // copy range from base | | |
| 1138 | var b: extras.RingBuffer(u8, 7) = .{}; | | |
| 1139 | for (0..7) |i| { | | |
| 1140 | const mask = @as(u8, 1) << @intCast(i); | | |
| 1141 | b.append(if (c2 & mask > 0) unpackedobj_fbs.takeByte() else 0); | | |
| 1142 | } | | |
| 1143 | const start: u32 = @bitCast(b.items[0..4].*); | | |
| 1144 | const nbytes: u24 = @bitCast(b.items[4..7].*); | | |
| 1145 | // std.log.debug("- copy from base: start={d} nbytes={d}", .{ start, nbytes }); | | |
| 1146 | const bytes = base_obj.content[start..][0..nbytes]; | | |
| 1147 | // std.log.debug("{s}\n", .{bytes}); | | |
| 1148 | try list2.appendSlice(r.gpa, bytes); | | |
| 1149 | } else { | | |
| 1150 | // append new data | | |
| 1151 | const nbytes = c2 & 0x7f; | | |
| 1152 | // std.log.debug("- append new bytes={d}", .{nbytes}); | | |
| 1153 | if (nbytes == 0) continue; | | |
| 1154 | const bytes = unpackedobj_fbs.takeSlice(nbytes); | | |
| 1155 | // std.log.debug("{s}\n", .{bytes}); | | |
| 1156 | try list2.appendSlice(r.gpa, bytes); | | |
| 1157 | } | | |
| 1158 | } | | |
| 1159 | | | |
| 1160 | // std.log.debug("- done", .{}); | | |
| 1161 | // std.log.debug("{s}\n", .{list2.items}); | | |
| 1162 | const _type = base_obj.type; | | |
| 1163 | const content = try list2.toOwnedSlice(r.gpa); | | |
| 1164 | const obj: GitObject = .{ .type = _type, .content = content }; | | |
| 1165 | if (maybe_oid) |oid| try r.unpacked_objects.put(r.gpa, oid, obj); | | |
| 1166 | return obj; | | |
| 1167 | }, | 1102 | }, |
| 1168 | .ref_delta => { | 1103 | .ref_delta => { |
| 1169 | // std.log.debug("type={s} size={d}", .{ @tagName(ty), size }); | 1104 | // std.log.debug("type={s} size={d}", .{ @tagName(ty), size }); |
| 1170 | const base_oid = extras.to_hex(packedobj_fbs.takeSlice(20)[0..20].*); | 1105 | const base_oid = extras.to_hex(packedobj_fbs.takeSlice(20)[0..20].*); |
| 1171 | const base_obj = (try r.getObject(arena, &base_oid)).?; | 1106 | const base_obj = (try r.getObject(arena, &base_oid)).?; |
| 1172 | | 1107 | // std.log.debug("base: type={s} content=[{d}]", .{ @tagName(base_obj.type), base_obj.content.len }); |
| 1173 | const compressed_content = packedobj_fbs.rest()[0..size]; | 1108 | return r.getDeltadObject(maybe_oid, &packedobj_fbs, size, base_obj); |
| 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; | | |
| 1238 | }, | 1109 | }, |
| 1239 | } | 1110 | } |
| 1240 | comptime unreachable; | 1111 | comptime unreachable; |
| ... | @@ -1246,6 +1117,74 @@ pub const Repository = struct { | ... | @@ -1246,6 +1117,74 @@ pub const Repository = struct { |
| 1246 | } | 1117 | } |
| 1247 | } | 1118 | } |
| 1248 | | 1119 | |
| | 1120 | fn getDeltadObject(r: *Repository, maybe_oid: ?Id, packedobj_fbs: *nio.FixedBufferStream([]const u8), size: usize, base_obj: GitObject) !GitObject { |
| | 1121 | const compressed_content = packedobj_fbs.rest()[0..size]; |
| | 1122 | var bufr = nio.FixedBufferStream([]const u8).init(compressed_content); |
| | 1123 | |
| | 1124 | var list: std.ArrayListUnmanaged(u8) = .empty; |
| | 1125 | defer list.deinit(r.gpa); |
| | 1126 | try list.ensureUnusedCapacity(r.gpa, size); |
| | 1127 | try std.compress.flate.inflate.decompress(.zlib, bufr.anyReadable(), list.writer(r.gpa)); |
| | 1128 | // std.log.debug("transformation data={d}", .{list.items}); |
| | 1129 | |
| | 1130 | var unpackedobj_fbs = nio.FixedBufferStream([]const u8).init(list.items); |
| | 1131 | |
| | 1132 | var list2: std.ArrayListUnmanaged(u8) = .empty; |
| | 1133 | errdefer list2.deinit(r.gpa); |
| | 1134 | |
| | 1135 | var base_size: usize = 0; |
| | 1136 | while (true) { |
| | 1137 | const c2: usize = unpackedobj_fbs.takeByte(); |
| | 1138 | base_size = (base_size << 7) | (c2 & 0x7f); |
| | 1139 | if (c2 & 0x80 == 0) break; |
| | 1140 | base_size += 1; |
| | 1141 | } |
| | 1142 | // std.log.debug("base_size={d}", .{base_size}); |
| | 1143 | |
| | 1144 | var obj_size: usize = 0; |
| | 1145 | while (true) { |
| | 1146 | const c2: usize = unpackedobj_fbs.takeByte(); |
| | 1147 | obj_size = (obj_size << 7) | (c2 & 0x7f); |
| | 1148 | if (c2 & 0x80 == 0) break; |
| | 1149 | obj_size += 1; |
| | 1150 | } |
| | 1151 | // std.log.debug("obj_size={d}", .{obj_size}); |
| | 1152 | |
| | 1153 | while (unpackedobj_fbs.pos < unpackedobj_fbs.buffer.len) { |
| | 1154 | const c2 = unpackedobj_fbs.takeByte(); |
| | 1155 | if (c2 & 0x80 > 0) { |
| | 1156 | // copy range from base |
| | 1157 | var b: extras.RingBuffer(u8, 7) = .{}; |
| | 1158 | for (0..7) |i| { |
| | 1159 | const mask = @as(u8, 1) << @intCast(i); |
| | 1160 | b.append(if (c2 & mask > 0) unpackedobj_fbs.takeByte() else 0); |
| | 1161 | } |
| | 1162 | const start: u32 = @bitCast(b.items[0..4].*); |
| | 1163 | const nbytes: u24 = @bitCast(b.items[4..7].*); |
| | 1164 | // std.log.debug("- copy from base: start={d} nbytes={d}", .{ start, nbytes }); |
| | 1165 | const bytes = base_obj.content[start..][0..nbytes]; |
| | 1166 | // std.log.debug("{s}\n", .{bytes}); |
| | 1167 | try list2.appendSlice(r.gpa, bytes); |
| | 1168 | } else { |
| | 1169 | // append new data |
| | 1170 | const nbytes = c2 & 0x7f; |
| | 1171 | // std.log.debug("- append new bytes={d}", .{nbytes}); |
| | 1172 | if (nbytes == 0) continue; |
| | 1173 | const bytes = unpackedobj_fbs.takeSlice(nbytes); |
| | 1174 | // std.log.debug("{s}\n", .{bytes}); |
| | 1175 | try list2.appendSlice(r.gpa, bytes); |
| | 1176 | } |
| | 1177 | } |
| | 1178 | |
| | 1179 | // std.log.debug("- done", .{}); |
| | 1180 | // std.log.debug("{s}\n", .{list2.items}); |
| | 1181 | const _type = base_obj.type; |
| | 1182 | const content = try list2.toOwnedSlice(r.gpa); |
| | 1183 | const obj: GitObject = .{ .type = _type, .content = content }; |
| | 1184 | if (maybe_oid) |oid| try r.unpacked_objects.put(r.gpa, oid, obj); |
| | 1185 | return obj; |
| | 1186 | } |
| | 1187 | |
| 1249 | const GitObject = struct { | 1188 | const GitObject = struct { |
| 1250 | type: RefType, | 1189 | type: RefType, |
| 1251 | content: []const u8, | 1190 | content: []const u8, |