authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-04-13 02:16:24 -07:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-04-13 02:16:24 -07:00
log3c080a86f2a7cc235c0d64245399fcf306cde245
tree3d831d02a84c7b6e60b5761ed3f746f6d4a1b31a
parentc75a9bfb2d1523607ab3f3d676ce747a2f897a59
signaturebadge-check Signed by SSH key SHA256:4hHJbtBRU58AYXwjL7fkz2fnQHdiye8x1QpTCQ0sHNw

implement the oid .idx binary search


1 files changed, 41 insertions(+), 20 deletions(-)

git.zig+41-20
......@@ -986,10 +986,14 @@ pub const Repository = struct {
986986
987987 // read .idx
988988 if (r.idx_content.count() == 0) {
989 const t2 = tracer.trace(@src(), " read objects/pack", .{});
990 defer t2.end();
989991 const packdir = try r.gitdir.openDir("objects/pack", .{});
990992 defer packdir.close();
991993 var iter = packdir.iterate();
992994 while (try iter.next()) |entry| {
995 const t3 = tracer.trace(@src(), " {s}", .{entry.name});
996 defer t3.end();
993997 if (entry.type != .REG) continue;
994998 if (!std.mem.endsWith(u8, entry.name, ".idx")) continue;
995999 // std.log.debug("packdir iterate: {s}", .{entry.name});
......@@ -1005,7 +1009,11 @@ pub const Repository = struct {
10051009 );
10061010 }
10071011 }
1012 const t4 = tracer.trace(@src(), " find pack_index/pack_offset", .{});
1013 errdefer t4.end();
10081014 const pack_index, const pack_offset = blk: for (r.idx_content.keys(), r.idx_content.values()) |idx_path, idx_content| {
1015 const t5 = tracer.trace(@src(), " {s}", .{idx_path});
1016 defer t5.end();
10091017 if (std.mem.startsWith(u8, idx_content, "\xfftOc")) {
10101018 std.debug.assert(std.mem.readInt(u32, idx_content[4..][0..4], .big) == 2);
10111019 const flfo_table_bytes = idx_content[8..][0 .. 256 * 4];
......@@ -1013,31 +1021,42 @@ pub const Repository = struct {
10131021 const name_bytes = idx_content[8..][1024..][0 .. object_count * 20];
10141022 const crc32_bytes = idx_content[8..][1024..][name_bytes.len..][0 .. object_count * 4];
10151023 const offset_bytes = idx_content[8..][1024..][name_bytes.len..][crc32_bytes.len..][0 .. object_count * 4];
1016 for (0..object_count) |i| {
1017 const object_id = &extras.to_hex(name_bytes[i * 20 ..][0..20].*);
1018 const pack_offset = std.mem.readInt(u32, offset_bytes[i * 4 ..][0..4], .big);
1019 if (std.mem.eql(u8, object_id, oid)) {
1020 // std.log.debug("found {s} in {s} at offset {d}", .{ oid, idx_path, pack_offset });
1021 const pack_index = r.pack_content.getIndex(idx_path) orelse clk: {
1022 var pack_path: [128]u8 = @splat(0);
1023 @memcpy(pack_path[0..13], "objects/pack/");
1024 @memcpy(pack_path[13..][0..idx_path.len], idx_path);
1025 @memcpy(pack_path[13..][idx_path.len - 4 ..][0..5], ".pack");
1026 const pack_name_nidx = std.mem.indexOfScalar(u8, &pack_path, 0).?;
1027 const pack_file = try r.gitdir.openFile(pack_path[0..pack_name_nidx :0], .{});
1028 defer pack_file.close();
1029 const pack_content = try pack_file.mmap();
1030 errdefer nfs.munmap(pack_content);
1031 try r.pack_content.put(r.gpa, idx_path, pack_content);
1032 break :clk r.pack_content.count() - 1;
1033 };
1034 break :blk .{ pack_index, pack_offset };
1024 // std.sort.binarySearch;
1025 const i = bll: {
1026 var low: usize = 0;
1027 var high: usize = object_count;
1028 while (low < high) {
1029 const mid = low + (high - low) / 2;
1030 const object_id = &extras.to_hex(name_bytes[mid * 20 ..][0..20].*);
1031 switch (std.mem.order(u8, oid, object_id)) {
1032 .eq => break :bll mid,
1033 .gt => low = mid + 1,
1034 .lt => high = mid,
1035 }
10351036 }
1036 }
1037 continue;
1038 };
1039 const pack_offset = std.mem.readInt(u32, offset_bytes[i * 4 ..][0..4], .big);
1040 // std.log.debug("found {s} in {s} at offset {d}", .{ oid, idx_path, pack_offset });
1041 const pack_index = r.pack_content.getIndex(idx_path) orelse clk: {
1042 var pack_path: [128]u8 = @splat(0);
1043 @memcpy(pack_path[0..13], "objects/pack/");
1044 @memcpy(pack_path[13..][0..idx_path.len], idx_path);
1045 @memcpy(pack_path[13..][idx_path.len - 4 ..][0..5], ".pack");
1046 const pack_name_nidx = std.mem.indexOfScalar(u8, &pack_path, 0).?;
1047 const pack_file = try r.gitdir.openFile(pack_path[0..pack_name_nidx :0], .{});
1048 defer pack_file.close();
1049 const pack_content = try pack_file.mmap();
1050 errdefer nfs.munmap(pack_content);
1051 try r.pack_content.put(r.gpa, idx_path, pack_content);
1052 break :clk r.pack_content.count() - 1;
1053 };
1054 break :blk .{ pack_index, pack_offset };
10371055 } else {
10381056 return error.Version1Idx;
10391057 }
10401058 } else return null;
1059 t4.end();
10411060
10421061 // parse .pack
10431062 // std.log.debug("pack_index={d} pack_offset={d}", .{ pack_index, pack_offset });
......@@ -1066,6 +1085,8 @@ pub const Repository = struct {
10661085 size += (c & 0x7f) << shift;
10671086 shift += 7;
10681087 }
1088 const t2 = tracer.trace(@src(), " 2 {s} {d}", .{ @tagName(ty), size });
1089 defer t2.end();
10691090 switch (ty) {
10701091 .none => {
10711092 unreachable;