╭ changed ────╮ │src/patch.zig│ ╰─────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭──────────╮ │← previous│ ╰──────────╯ ╭───────────────────────────────────────────────────────────────────────────────────╮ │494 }; │ │495 } │ │496 │ │478 -// check every open patch, reporting progress as each one finishes │ │497 +// check the open patches a push could have invalidated, reporting progress as│ │498 +// each one finishes. `updates` limits them to the branches it moved │ │499 pub fn refreshOpenMergeability( │ │500 comptime repo_opts: rp.RepoOpts(.xit), │ │501 io: std.Io, │ ╰───────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │502 allocator: std.mem.Allocator, │ │503 target_repo: *rp.Repo(.xit, repo_opts), │ │504 + updates: ?[]const xit.net_server_receive_pack.AppliedRefUpdate, │ │505 progress_ctx_maybe: ?repo_opts.ProgressCtx, │ │506 ) void { │ │486 - refreshOpenMergeChecks(repo_opts, io, allocator, target_repo, progress_ctx_maybe) catch |err| { │ │507 + refreshOpenMergeChecks(repo_opts, io, allocator, target_repo, updates, progress_ctx_maybe) catch |err| {│ │508 std.log.warn("failed to refresh mergeability: {s}", .{@errorName(err)}); │ │509 }; │ │510 } │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────╮ │514 io: std.Io, │ │515 allocator: std.mem.Allocator, │ │516 target_repo: *rp.Repo(.xit, repo_opts), │ │517 + updates: ?[]const xit.net_server_receive_pack.AppliedRefUpdate, │ │518 progress_ctx_maybe: ?repo_opts.ProgressCtx, │ │519 ) !void { │ │520 // collect open patch ids before any refresh changes the database│ ╰──────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────╮ │521 const DB = evt.EventDB(repo_opts.hash); │ │522 + var arena = std.heap.ArenaAllocator.init(allocator); │ │523 + defer arena.deinit(); │ │524 var ids: std.ArrayList([evt.event_id_size]u8) = .empty;│ │525 defer ids.deinit(allocator); │ │526 collect: { │ ╰────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │533 const open_cursor = try statuses.getCursor("open") orelse break :collect; │ │534 const open = try DB.SortedSet(.read_only).init(open_cursor); │ │535 var iter = try open.iteratorFromIndex(0); │ │512 - while (try iter.next()) |cursor| try ids.append(allocator, try evt.readOrderKeyId(DB, cursor)); │ │536 + while (try iter.next()) |cursor| { │ │537 + const id = try evt.readOrderKeyId(DB, cursor); │ │538 + │ │539 + // a saved check only goes stale when the patch's revision or its │ │540 + // target tip moves, so a push can skip the branches it left alone │ │541 + if (updates) |changed| { │ │542 + const record = (try evt.Patch.readById(DB, repo_opts.hash, moment, &arena, &id)) orelse continue; │ │543 + const source_moved = if (record.event.source_branch) |branch| branchUpdated(changed, branch) else false;│ │544 + if (!source_moved and !branchUpdated(changed, record.event.target_branch)) continue; │ │545 + } │ │546 + try ids.append(allocator, id); │ │547 + } │ │548 } │ │549 │ │550 // start progress reporting after the patch count is known │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │516 - if (repo_opts.ProgressCtx != void) { │ │517 - if (progress_ctx_maybe) |progress_ctx| progress_ctx.run(io, .{ .start = .{ .kind = .writing_patch, .estimated_total_items = ids.items.len } }) catch {};│ │518 - } │ │551 + reportProgress(repo_opts, io, progress_ctx_maybe, .{ .text = "Checking mergeability" }); │ │552 + reportProgress(repo_opts, io, progress_ctx_maybe, .{ .start = .{ .kind = .writing_patch, .estimated_total_items = ids.items.len } }); │ │553 │ │554 // refresh each collected patch independently │ │555 for (ids.items) |id| { │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │556 refreshMergeability(repo_opts, io, allocator, target_repo, id); │ │523 - if (repo_opts.ProgressCtx != void) { │ │524 - if (progress_ctx_maybe) |progress_ctx| progress_ctx.run(io, .{ .complete_one = .writing_patch }) catch {};│ │525 - } │ │557 + reportProgress(repo_opts, io, progress_ctx_maybe, .{ .complete_one = .writing_patch }); │ │558 } │ │559 │ │560 // finish progress reporting after all patches have been visited │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │529 - if (repo_opts.ProgressCtx != void) { │ │530 - if (progress_ctx_maybe) |progress_ctx| progress_ctx.run(io, .{ .end = .writing_patch }) catch {};│ │531 - } │ │561 + reportProgress(repo_opts, io, progress_ctx_maybe, .{ .end = .writing_patch }); │ │562 } │ │563 │ │564 fn refreshMergeCheck( │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────╮ │1154 } │ │1155 │ │1156 // refresh other patches affected by the updated target branch. │ │1127 - refreshOpenMergeability(repo_opts, io, allocator, target_repo, null); │ │1157 + 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| { │ ╰─────────────────────────────────────────────────────────────────────────────────────╯