| ... | ... | @@ -1014,7 +1014,7 @@ pub const Repository = struct { |
| 1014 | 1014 | const object_id = &extras.to_hex(name_bytes[i * 20 ..][0..20].*); |
| 1015 | 1015 | const pack_offset = std.mem.readInt(u32, offset_bytes[i * 4 ..][0..4], .big); |
| 1016 | 1016 | if (std.mem.eql(u8, object_id, oid)) { |
| 1017 | | std.log.debug("found {s} in {s} at offset {d}", .{ obj, idx_path, pack_offset }); |
| 1017 | std.log.debug("found {s} in {s} at offset {d}", .{ oid, idx_path, pack_offset }); |
| 1018 | 1018 | const pack_index = r.pack_content.getIndex(idx_path) orelse clk: { |
| 1019 | 1019 | var pack_path: [128]u8 = @splat(0); |
| 1020 | 1020 | @memcpy(pack_path[0..13], "objects/pack/"); |
| ... | ... | @@ -1037,7 +1037,7 @@ pub const Repository = struct { |
| 1037 | 1037 | } else return null; |
| 1038 | 1038 | |
| 1039 | 1039 | // parse .pack |
| 1040 | | std.log.warn("pack_index={d} pack_offset={d}", .{ pack_index, pack_offset }); |
| 1040 | std.log.debug("pack_index={d} pack_offset={d}", .{ pack_index, pack_offset }); |
| 1041 | 1041 | |
| 1042 | 1042 | return try r.getPackedObject(oid, pack_index, pack_offset); |
| 1043 | 1043 | } |
| ... | ... | @@ -1049,11 +1049,8 @@ pub const Repository = struct { |
| 1049 | 1049 | switch (pack_version) { |
| 1050 | 1050 | 2 => { |
| 1051 | 1051 | const packedobj_content = pack_content[pack_offset..]; |
| 1052 | | // var packedobj_fbs = std.ArrayListUnmanaged(u8).initBuffer(packedobj_content); |
| 1053 | 1052 | var packedobj_fbs = nio.FixedBufferStream([]const u8).init(packedobj_content); |
| 1054 | | |
| 1055 | 1053 | const PackedObjType = enum(u3) { none, commit, tree, blob, tag, reserved, ofs_delta, ref_delta }; |
| 1056 | | |
| 1057 | 1054 | var c: usize = packedobj_fbs.takeByte(); |
| 1058 | 1055 | const ty: PackedObjType = @enumFromInt((c >> 4) & 7); |
| 1059 | 1056 | var size: usize = c & 15; |
| ... | ... | @@ -1063,8 +1060,6 @@ pub const Repository = struct { |
| 1063 | 1060 | size += (c & 0x7f) << shift; |
| 1064 | 1061 | shift += 7; |
| 1065 | 1062 | } |
| 1066 | | std.log.warn("type={s} size={d}", .{ @tagName(ty), size }); |
| 1067 | | |
| 1068 | 1063 | switch (ty) { |
| 1069 | 1064 | .none => { |
| 1070 | 1065 | unreachable; |
| ... | ... | @@ -1087,7 +1082,83 @@ pub const Repository = struct { |
| 1087 | 1082 | }, |
| 1088 | 1083 | .ofs_delta => { |
| 1089 | 1084 | std.log.debug("type={s} size={d}", .{ @tagName(ty), size }); |
| 1090 | | unreachable; |
| 1085 | var offset: usize = 0; |
| 1086 | while (true) { |
| 1087 | const c2: usize = packedobj_fbs.takeByte(); |
| 1088 | offset = (offset << 7) | (c2 & 0x7f); |
| 1089 | if (c2 & 0x80 == 0) break; |
| 1090 | offset += 1; |
| 1091 | } |
| 1092 | const base_pack_offset = pack_offset - offset; |
| 1093 | const base_obj = try r.getPackedObject(null, pack_index, base_pack_offset); |
| 1094 | std.log.debug("base: type={s} content=[{d}]", .{ @tagName(base_obj.type), base_obj.content.len }); |
| 1095 | |
| 1096 | const compressed_content = packedobj_fbs.rest()[0..size]; |
| 1097 | var bufr = nio.FixedBufferStream([]const u8).init(compressed_content); |
| 1098 | |
| 1099 | var list: std.ArrayListUnmanaged(u8) = .empty; |
| 1100 | defer list.deinit(r.gpa); |
| 1101 | try list.ensureUnusedCapacity(r.gpa, size); |
| 1102 | try std.compress.flate.inflate.decompress(.zlib, bufr.anyReadable(), list.writer(r.gpa)); |
| 1103 | |
| 1104 | std.log.debug("transformation data={d}", .{list.items}); |
| 1105 | |
| 1106 | var unpackedobj_fbs = nio.FixedBufferStream([]const u8).init(list.items); |
| 1107 | |
| 1108 | var list2: std.ArrayListUnmanaged(u8) = .empty; |
| 1109 | errdefer list2.deinit(r.gpa); |
| 1110 | |
| 1111 | var base_size: usize = 0; |
| 1112 | while (true) { |
| 1113 | const c2: usize = unpackedobj_fbs.takeByte(); |
| 1114 | base_size = (base_size << 7) | (c2 & 0x7f); |
| 1115 | if (c2 & 0x80 == 0) break; |
| 1116 | base_size += 1; |
| 1117 | } |
| 1118 | std.log.debug("base_size={d}", .{base_size}); |
| 1119 | |
| 1120 | var obj_size: usize = 0; |
| 1121 | while (true) { |
| 1122 | const c2: usize = unpackedobj_fbs.takeByte(); |
| 1123 | obj_size = (obj_size << 7) | (c2 & 0x7f); |
| 1124 | if (c2 & 0x80 == 0) break; |
| 1125 | obj_size += 1; |
| 1126 | } |
| 1127 | std.log.debug("obj_size={d}", .{obj_size}); |
| 1128 | |
| 1129 | while (unpackedobj_fbs.pos < unpackedobj_fbs.buffer.len) { |
| 1130 | const c2 = unpackedobj_fbs.takeByte(); |
| 1131 | if (c2 & 0x80 > 0) { |
| 1132 | // copy range from base |
| 1133 | var b: extras.RingBuffer(u8, 7) = .{}; |
| 1134 | for (0..7) |i| { |
| 1135 | const mask = @as(u8, 1) << @intCast(i); |
| 1136 | b.append(if (c2 & mask > 0) unpackedobj_fbs.takeByte() else 0); |
| 1137 | } |
| 1138 | const start: u32 = @bitCast(b.items[0..4].*); |
| 1139 | const nbytes: u24 = @bitCast(b.items[4..7].*); |
| 1140 | std.log.debug("- copy from base: start={d} nbytes={d}", .{ start, nbytes }); |
| 1141 | const bytes = base_obj.content[start..][0..nbytes]; |
| 1142 | // std.log.debug("{s}\n", .{bytes}); |
| 1143 | try list2.appendSlice(r.gpa, bytes); |
| 1144 | } else { |
| 1145 | // append new data |
| 1146 | const nbytes = c2 & 0x7f; |
| 1147 | std.log.debug("- append new bytes={d}", .{nbytes}); |
| 1148 | if (nbytes == 0) continue; |
| 1149 | const bytes = unpackedobj_fbs.takeSlice(nbytes); |
| 1150 | // std.log.debug("{s}\n", .{bytes}); |
| 1151 | try list2.appendSlice(r.gpa, bytes); |
| 1152 | } |
| 1153 | } |
| 1154 | |
| 1155 | std.log.debug("- done", .{}); |
| 1156 | // std.log.debug("{s}\n", .{list2.items}); |
| 1157 | const _type = base_obj.type; |
| 1158 | const content = try list2.toOwnedSlice(r.gpa); |
| 1159 | const obj: GitObject = .{ .type = _type, .content = content }; |
| 1160 | if (maybe_oid) |oid| try r.unpacked_objects.put(r.gpa, oid, obj); |
| 1161 | return obj; |
| 1091 | 1162 | }, |
| 1092 | 1163 | .ref_delta => { |
| 1093 | 1164 | std.log.debug("type={s} size={d}", .{ @tagName(ty), size }); |