╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ────╮ │src/patch.zig│ ╰─────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1125 // retain the submitted revision and snapshot the merge result │ │1126 if (!try importMergedRevision(repo_opts, state, &ctx.core.db, &moment, ctx.io, ctx.allocator, ctx.fork_repo, &ctx.patch_id, .{ .revision = ctx.revision, .before_oid = &before_oid, .after_oid = &after_oid }, ctx.expected_patch, ctx.author, ctx.timestamp)) return error.PatchOutOfDate;│ │1127 │ │1128 + // the merge moved the target branch, so its indexes follow, │ │1129 + // the commit index deriving from the old tip's version │ │1130 + _ = try find.refreshInTransaction(repo_opts, state, &moment, ctx.io, ctx.allocator, null); │ │1131 + _ = try srch_cmmt.refreshInTransaction(repo_opts, state, &moment, ctx.io, ctx.allocator, &.{.{ .old_oid = &before_oid, .new_oid = &after_oid }}, null); │ │1132 + │ │1133 // record the merge as one undoable action. │ │1134 try xit.undo.write(repo_opts, state, std.Io.Timestamp.now(ctx.io, .real).toSeconds(), .{ .custom = .{ .action_kind = merge_undo_action } }); │ │1135 } │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────╮ │1160 │ │1161 // refresh other patches affected by the updated target branch. │ │1162 refreshOpenMergeability(repo_opts, io, allocator, target_repo, null, null); │ │1158 - │ │1159 - // the merge moved the target branch, so its indexes follow │ │1160 - find.refresh(repo_opts, io, allocator, target_repo) catch |err| { │ │1161 - std.log.warn("failed to refresh file index: {s}", .{@errorName(err)}); │ │1162 - }; │ │1163 - srch_cmmt.refresh(repo_opts, io, allocator, target_repo, null) catch |err| {│ │1164 - std.log.warn("failed to refresh commit index: {s}", .{@errorName(err)});│ │1165 - }; │ │1163 } │ │1164 │ │1165 // merge a published patch and remove its fork │ ╰──────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ───╮ │src/push.zig│ ╰────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │173 │ │174 // the indexes the pushed refs invalidate belong to the push too │ │175 _ = try find.refreshInTransaction(repo_opts, state, &moment, ctx.io, ctx.allocator, ctx.sideband); │ │176 - _ = try srch_cmmt.refreshInTransaction(repo_opts, state, &moment, ctx.io, ctx.allocator, ctx.updates.items.items, ctx.sideband); │ │176 + var moves: std.ArrayList(srch_cmmt.Move) = .empty; │ │177 + defer moves.deinit(ctx.allocator); │ │178 + for (ctx.updates.items.items) |update| try moves.append(ctx.allocator, .{ .old_oid = update.old_oid, .new_oid = update.new_oid });│ │179 + _ = try srch_cmmt.refreshInTransaction(repo_opts, state, &moment, ctx.io, ctx.allocator, moves.items, ctx.sideband); │ │180 │ │181 try writeUndo(repo_opts, state, ctx.io, ctx.allocator, ctx.author, ctx.updates.items.items); │ │182 } │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │354 try evt.commitEvents(.xit, repo_opts, state, ctx.io, ctx.allocator, evt.events_ref, events[0..event_count], null); │ │355 if (!try evt.consumeInTransaction(.fork, .xit, repo_opts, state, &ctx.core.db, &moment, ctx.io, ctx.allocator, evt.events_ref)) return error.CancelTransaction;│ │356 } │ │357 + // the patch branch's file index lands with the push │ │358 + _ = try find.refreshInTransaction(repo_opts, state, &moment, ctx.io, ctx.allocator, ctx.sideband); │ │359 + │ │360 // a fork push tracks no ref updates, so it records no ranges │ │361 try writeUndo(repo_opts, state, ctx.io, ctx.allocator, ctx.author, &.{}); │ │362 } │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │392 return err; │ │393 }; │ │394 │ │389 - find.refresh(repo_opts, io, allocator, fork_repo) catch |err| { │ │390 - serve_common.logError(io, error_writer, "failed to refresh file index: {s}\n", .{@errorName(err)});│ │391 - }; │ │395 if (!published) return response.finish(writer, null); │ │396 │ │397 sideband.run(io, .{ .text = "Updating patches" }) catch {}; │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ────────────╮ │src/search_commit.zig│ ╰─────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────╮ │ 7 const rf = xit.ref; │ │ 8 const obj = xit.object; │ │ 9 const mrg = xit.merge; │ │10 -const serve_common = @import("serve_common.zig"); │ │10 const progress = @import("./progress.zig"); │ │11 │ │12 // the repo moment key holding one commit-message index per ref tip. it sits│ ╰────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────╮ │13 // outside the haxy moment because pushes change it and events never do. each │ │14 // entry is keyed by its commit oid's hash: its value is the index as of that │ │16 -// commit, and its key slot holds the raw commit oid. │ │15 +// commit, and its key slot holds the raw commit oid followed by its timestamp.│ │16 pub const index_key = "haxy/commit-oid->word->time+oid"; │ │17 │ │19 -// a commit a version covers. │ │20 -pub fn Commit(comptime hash_kind: hash.HashKind) type { │ │21 - return struct { │ │22 - oid: [hash.hexLen(hash_kind)]u8, │ │23 - timestamp: u64, │ │24 - }; │ │25 -} │ │18 +// a ref move: the old tip's version, when it has one, is the base the new │ │19 +// tip's derives from │ │20 +pub const Move = struct { │ │21 + old_oid: []const u8, │ │22 + new_oid: []const u8, │ │23 +}; │ │24 │ │25 // `commit_oid`'s index, or null when it has none. a version is correct for its│ │26 // commit by construction, so there is nothing to check for staleness. │ ╰───────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────╮ │72 io: std.Io, │ │73 allocator: std.mem.Allocator, │ │74 repo: *rp.Repo(.xit, repo_opts), │ │77 - updates: ?[]const xit.net_server_receive_pack.AppliedRefUpdate,│ │75 ) !void { │ │76 const Repo = rp.Repo(.xit, repo_opts); │ │77 const DB = Repo.DB; │ ╰───────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────╮ │79 core: *Repo.Core, │ │80 io: std.Io, │ │81 allocator: std.mem.Allocator, │ │85 - updates: ?[]const xit.net_server_receive_pack.AppliedRefUpdate, │ │82 │ │83 pub fn run(ctx: @This(), cursor: *DB.Cursor(.read_write)) !void {│ │84 var moment = try DB.HashMap(.read_write).init(cursor.*); │ ╰─────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │85 const state = Repo.State(.read_write){ .core = ctx.core, .extra = .{ .moment = &moment } }; │ │90 - if (!try refreshInTransaction(repo_opts, state, &moment, ctx.io, ctx.allocator, ctx.updates, null)) return error.CancelTransaction; │ │86 + if (!try refreshInTransaction(repo_opts, state, &moment, ctx.io, ctx.allocator, &.{}, null)) return error.CancelTransaction; │ │87 │ │88 // record the user action for undo │ │89 try xit.undo.write(repo_opts, state, std.Io.Timestamp.now(ctx.io, .real).toSeconds(), .{ .custom = .{ .action_kind = undo_action } });│ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯