╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ────────────╮ │src/search_commit.zig│ ╰─────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │381 allocator: std.mem.Allocator, │ │358 - aa: std.mem.Allocator, │ │359 - base_tip: ?*const [hash.hexLen(repo_opts.hash)]u8, │ │382 + version: rp.Repo(.xit, repo_opts).DB.SortedMap(.read_write), │ │383 tip: *const [hash.hexLen(repo_opts.hash)]u8, │ │384 progress_ctx_maybe: ?repo_opts.ProgressCtx, │ │362 -) !struct { removed: []const Commit(repo_opts.hash), added: []const Commit(repo_opts.hash) } { │ │363 - var removed: std.ArrayList(Commit(repo_opts.hash)) = .empty; │ │364 - var added: std.ArrayList(Commit(repo_opts.hash)) = .empty; │ │365 - │ │366 - if (base_tip) |base| { │ │367 - const Ancestry = mrg.Ancestry(.xit, repo_opts); │ │368 - var ancestry = try Ancestry.init(state, io, allocator, base, tip); │ │369 - defer ancestry.deinit(); │ │370 - │ │371 - progress.report(repo_opts, io, progress_ctx_maybe, .{ .start = .{ .kind = .walking_commit, .estimated_total_items = 0 } });│ │372 - try ancestry.finish(progress_ctx_maybe); │ │373 - progress.report(repo_opts, io, progress_ctx_maybe, .{ .end = .walking_commit }); │ │385 +) !void { │ │386 + const DB = rp.Repo(.xit, repo_opts).DB; │ │387 │ │375 - // the walk stops at the shared history, so it trusts timestamps: a │ │376 - // commit dated later than a descendant can be passed from the base │ │377 - // side before the tip turns out to reach it too, and its postings are │ │378 - // then dropped. settling that would mean walking the whole history. │ │379 - // a wrong addition only re-puts postings, so a fast-forward removes │ │380 - // nothing, which the base tip picking up the tip's flag proves. │ │381 - const base_node = ancestry.nodes.get(ancestry.tips[0]) orelse unreachable; │ │382 - const fast_forward = base_node.flags & Ancestry.two != 0; │ │388 + var message: std.ArrayList(u8) = .empty; │ │389 + defer message.deinit(allocator); │ │390 │ │384 - var iter = ancestry.nodes.iterator(); │ │385 - while (iter.next()) |entry| { │ │386 - // tag objects are peeled through, not walked │ │387 - if (entry.value_ptr.tag_target != null) continue; │ │388 - const commit = Commit(repo_opts.hash){ .oid = entry.key_ptr.*, .timestamp = entry.value_ptr.timestamp }; │ │389 - switch (entry.value_ptr.flags & Ancestry.both) { │ │390 - Ancestry.one => if (!fast_forward) try removed.append(aa, commit), │ │391 - Ancestry.two => try added.append(aa, commit), │ │392 - else => {}, │ │393 - } │ │394 - } │ │395 - } else { │ │396 - // a whole history has no count until it is walked, so the walk reports │ │397 - // the commits it has reached so far │ │398 - progress.report(repo_opts, io, progress_ctx_maybe, .{ .start = .{ .kind = .walking_commit, .estimated_total_items = 0 } });│ │399 - var iter = try obj.ObjectIterator(.xit, repo_opts).init(state, io, allocator, .{ .kind = .commit }); │ │400 - defer iter.deinit(); │ │401 - try iter.include(tip); │ │402 - while (try iter.next(allocator)) |object| { │ │403 - defer object.deinit(); │ │404 - try added.append(aa, .{ .oid = object.oid, .timestamp = object.content.commit.metadata.timestamp }); │ │405 - progress.report(repo_opts, io, progress_ctx_maybe, .{ .complete_one = .walking_commit }); │ │406 - } │ │407 - progress.report(repo_opts, io, progress_ctx_maybe, .{ .end = .walking_commit }); │ │391 + // a whole history has no count until it is walked, so it reports the │ │392 + // commits indexed so far │ │393 + progress.report(repo_opts, io, progress_ctx_maybe, .{ .text = "Indexing commits" }); │ │394 + progress.report(repo_opts, io, progress_ctx_maybe, .{ .start = .{ .kind = .writing_patch, .estimated_total_items = 0 } }); │ │395 + var iter = try obj.ObjectIterator(.xit, repo_opts).init(state, io, allocator, .{ .kind = .commit }); │ │396 + defer iter.deinit(); │ │397 + try iter.include(tip); │ │398 + while (try iter.next(allocator)) |object| { │ │399 + defer object.deinit(); │ │400 + if (progress.cancelled(repo_opts, progress_ctx_maybe)) return error.ClientGone; │ │401 + const key = try readPosting(repo_opts, allocator, &message, object); │ │402 + try srch.add(DB, version, allocator, &key, message.items); │ │403 + progress.report(repo_opts, io, progress_ctx_maybe, .{ .complete_one = .writing_patch }); │ │404 } │ │405 + progress.report(repo_opts, io, progress_ctx_maybe, .{ .end = .writing_patch }); │ │406 +} │ │407 │ │410 - return .{ .removed = removed.items, .added = added.items }; │ │408 +// replace `message` with the indexed prefix of `object`'s message and return │ │409 +// the doc key it indexes under │ │410 +fn readPosting( │ │411 + comptime repo_opts: rp.RepoOpts(.xit), │ │412 + allocator: std.mem.Allocator, │ │413 + message: *std.ArrayList(u8), │ │414 + object: *obj.Object(.xit, repo_opts), │ │415 +) ![docKeyLen(repo_opts.hash)]u8 { │ │416 + message.clearRetainingCapacity(); │ │417 + object.readMessage(allocator, message, .limited(srch.max_indexed_bytes)) catch |err| switch (err) { │ │418 + // only the indexed prefix matters │ │419 + error.StreamTooLong => {}, │ │420 + else => |e| return e, │ │421 + }; │ │422 + return docKey(repo_opts.hash, object.content.commit.metadata.timestamp, &object.oid); │ │423 } │ │424 │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ──╮ │src/try.zig│ ╰───────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────╮ │816 try template_repo.addConfig(io, allocator, .{ .name = "core.bare", .value = "true" });│ │817 // fixtures commit directly, so index the ref tips by hand │ │818 try find.refresh(.{}, io, allocator, &template_repo); │ │819 - try srch_cmmt.refresh(.{}, io, allocator, &template_repo, null); │ │819 + try srch_cmmt.refresh(.{}, io, allocator, &template_repo); │ │820 // clear history only after indexing has written its transactions. │ │821 { │ │822 const moment = try evt.currentMoment(.{}, &template_repo); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ────────────╮ │src/ui/Repo/Files.zig│ ╰─────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │144 if (comptime repo_kind == .xit) index: { │ │145 if (resolved.ref_or_oid != .branch) break :index; │ │146 const branch = std.Uri.percentDecodeInPlace(try aa.dupe(u8, resolved.value)); │ │147 - const tree_oid = try fnd.rootTreeOid(repo_opts, state, io, gpa, &resolved.oid); │ │148 - const files = (try fnd.lookup(repo_opts, moment, branch, &tree_oid)) orelse break :index; │ │147 + const files = (try fnd.lookup(repo_opts, moment, branch, &resolved.oid)) orelse break :index;│ │148 find_available = true; │ │149 const value = term orelse break :index; │ │150 // a result's name is its full path, so the listing has no directory and │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────╯