| ... | ... | @@ -1270,12 +1270,14 @@ pub const Repository = struct { |
| 1270 | 1270 | defer commit_id_prev = commit_id; |
| 1271 | 1271 | commit = commit_idx.reify(r); |
| 1272 | 1272 | const new_tree_id = try traverseTo(r, arena, commit.tree, dir_path) orelse { |
| 1273 | | for (result.keys(), 0..) |k, i| { |
| 1274 | | if (set.isSet(i)) continue; |
| 1273 | var i: usize = 0; |
| 1274 | while (findFirstUnset(set, i)) |j| : (i += 1) { |
| 1275 | i = j; |
| 1276 | const k = result.keys()[i]; |
| 1275 | 1277 | found += 1; |
| 1276 | 1278 | result.putAssumeCapacity(k, commit_id_prev); |
| 1277 | 1279 | set.set(i); |
| 1278 | | // std.log.debug("found [{d}/{d}] objects after searching {d} commits", .{ found, total, searched }); |
| 1280 | // std.log.debug("found [{d}/{d}] objects after searching {d} commits, found {s}", .{ found, total, searched, k }); |
| 1279 | 1281 | continue; |
| 1280 | 1282 | } |
| 1281 | 1283 | break; |
| ... | ... | @@ -1283,21 +1285,23 @@ pub const Repository = struct { |
| 1283 | 1285 | if (new_tree_id.eql(tree_id)) continue; |
| 1284 | 1286 | tree_id = new_tree_id; |
| 1285 | 1287 | const tree = try r.getTreeA(arena, tree_id.id); |
| 1286 | | for (result.keys(), 0..) |k, i| { |
| 1287 | | if (set.isSet(i)) continue; |
| 1288 | var i: usize = 0; |
| 1289 | while (findFirstUnset(set, i)) |j| : (i += 1) { |
| 1290 | i = j; |
| 1291 | const k = result.keys()[i]; |
| 1288 | 1292 | const new = tree.get(k, base_tree.children[i].mode.type); |
| 1289 | 1293 | if (new == null) { |
| 1290 | 1294 | found += 1; |
| 1291 | 1295 | result.putAssumeCapacity(k, commit_id_prev); |
| 1292 | 1296 | set.set(i); |
| 1293 | | // std.log.debug("found [{d}/{d}] objects after searching {d} commits", .{ found, total, searched }); |
| 1297 | // std.log.debug("found [{d}/{d}] objects after searching {d} commits, at {d} found {s}", .{ found, total, searched, i, k }); |
| 1294 | 1298 | continue; |
| 1295 | 1299 | } |
| 1296 | 1300 | if (!std.mem.eql(u8, new.?.id.erase(), base_tree.children[i].id.erase())) { |
| 1297 | 1301 | found += 1; |
| 1298 | 1302 | result.putAssumeCapacity(k, commit_id_prev); |
| 1299 | 1303 | set.set(i); |
| 1300 | | // std.log.debug("found [{d}/{d}] objects after searching {d} commits", .{ found, total, searched }); |
| 1304 | // std.log.debug("found [{d}/{d}] objects after searching {d} commits, at {d} found {s}", .{ found, total, searched, i, k }); |
| 1301 | 1305 | continue; |
| 1302 | 1306 | } |
| 1303 | 1307 | } |
| ... | ... | @@ -1646,3 +1650,19 @@ pub const Ref = struct { |
| 1646 | 1650 | oid: Id, |
| 1647 | 1651 | label: string, |
| 1648 | 1652 | }; |
| 1653 | |
| 1654 | pub fn findFirstUnset(set: std.bit_set.DynamicBitSetUnmanaged, after: usize) ?usize { |
| 1655 | const MaskInt = std.bit_set.DynamicBitSetUnmanaged.MaskInt; |
| 1656 | if (after >= set.bit_length) return null; |
| 1657 | if (!set.isSet(after)) return after; |
| 1658 | var maski = after / @bitSizeOf(MaskInt); |
| 1659 | while (set.masks[maski] == std.math.maxInt(MaskInt)) maski += 1; |
| 1660 | var mask = set.masks[maski]; |
| 1661 | mask |= (@as(usize, 1) << @intCast((after -| (maski * @bitSizeOf(MaskInt))) % @bitSizeOf(MaskInt))) - 1; |
| 1662 | if (mask == std.math.maxInt(MaskInt)) maski += 1; |
| 1663 | while (set.masks[maski] == std.math.maxInt(MaskInt)) maski += 1; |
| 1664 | if (mask == std.math.maxInt(MaskInt)) mask = set.masks[maski]; |
| 1665 | const candidate = maski * @bitSizeOf(MaskInt) + @ctz(~mask); |
| 1666 | if (candidate >= set.bit_length) return null; |
| 1667 | return candidate; |
| 1668 | } |