╭ changed ───╮ │src/find.zig│ ╰────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────╮ │ 7 const tr = xit.tree; │ │ 8 const obj = xit.object; │ │ 9 const fs = xit.fs; │ │10 +const serve_common = @import("serve_common.zig"); │ │11 │ │12 // the repo moment key holding one file map per branch tip. it sits outside the│ │13 // haxy moment because pushes change it and events never do. each entry is │ ╰───────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │128 pub fn run(ctx: @This(), cursor: *DB.Cursor(.read_write)) !void { │ │129 var moment = try DB.HashMap(.read_write).init(cursor.*); │ │130 const state = Repo.State(.read_write){ .core = ctx.core, .extra = .{ .moment = &moment } }; │ │130 - if (!try refreshInTransaction(repo_opts, state, &moment, ctx.io, ctx.allocator)) return error.CancelTransaction; │ │131 + if (!try refreshInTransaction(repo_opts, state, &moment, ctx.io, ctx.allocator, null)) return error.CancelTransaction; │ │132 │ │133 // record the user action for undo │ │134 try xit.undo.write(repo_opts, state, std.Io.Timestamp.now(ctx.io, .real).toSeconds(), .{ .custom = .{ .action_kind = undo_action } });│ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────╮ │157 moment: *rp.Repo(.xit, repo_opts).DB.HashMap(.read_write),│ │158 io: std.Io, │ │159 allocator: std.mem.Allocator, │ │160 + progress_ctx_maybe: ?repo_opts.ProgressCtx, │ │161 ) !bool { │ │162 const Repo = rp.Repo(.xit, repo_opts); │ │163 const DB = Repo.DB; │ ╰───────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │235 { │ │236 const index_hash = hash.hashInt(repo_opts.hash, index_key); │ │237 var new_branch_base = base; │ │238 + serve_common.reportProgress(repo_opts, io, progress_ctx_maybe, .{ .text = "Indexing files" });│ │239 │ │240 var key: std.ArrayList(u8) = .empty; │ │241 defer key.deinit(allocator); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │263 var tree_diff = tr.TreeDiff(.xit, repo_opts).init(allocator); │ │264 defer tree_diff.deinit(); │ │265 try tree_diff.compare(state.readOnly(), io, &entry.tree, &tree, null); │ │266 + serve_common.reportProgress(repo_opts, io, progress_ctx_maybe, .{ .start = .{ .kind = .writing_patch, .estimated_total_items = tree_diff.changes.count() } });│ │267 for (tree_diff.changes.keys(), tree_diff.changes.values()) |path, change| { │ │268 + defer serve_common.reportProgress(repo_opts, io, progress_ctx_maybe, .{ .complete_one = .writing_patch }); │ │269 try fileKey(allocator, &key, path); │ │270 const oid = if (change.new) |*tree_entry| indexedOid(repo_opts.hash, tree_entry) else null; │ │271 if (oid) |bytes| { │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │275 } │ │276 } │ │277 } else { │ │278 + // a whole tree has no count until it is walked, so it reports │ │279 + // the files it has indexed so far │ │280 + serve_common.reportProgress(repo_opts, io, progress_ctx_maybe, .{ .start = .{ .kind = .writing_patch, .estimated_total_items = 0 } });│ │281 var paths = std.heap.ArenaAllocator.init(allocator); │ │282 defer paths.deinit(); │ │275 - try indexTree(repo_opts, state.readOnly(), io, allocator, paths.allocator(), files, &key, "", &tree); │ │283 + try indexTree(repo_opts, state.readOnly(), io, allocator, paths.allocator(), files, &key, "", &tree, progress_ctx_maybe); │ │284 } │ │285 + serve_common.reportProgress(repo_opts, io, progress_ctx_maybe, .{ .end = .writing_patch }); │ │286 │ │287 // the first entry ever written becomes the base for the next │ │288 // new branch, so only one branch walks a whole tree. │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────╮ │306 key: *std.ArrayList(u8), │ │307 prefix: []const u8, │ │308 oid: *const [hash.hexLen(repo_opts.hash)]u8, │ │309 + progress_ctx_maybe: ?repo_opts.ProgressCtx, │ │310 ) !void { │ │311 var object = try obj.Object(.xit, repo_opts).init(state, io, allocator, oid);│ │312 defer object.deinit(); │ ╰──────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │317 for (tree.entries.keys(), tree.entries.values()) |name, *tree_entry| { │ │318 const path = try fs.joinPath(paths, &.{ prefix, name }); │ │319 if (tree_entry.isTree()) { │ │310 - try indexTree(repo_opts, state, io, allocator, paths, files, key, path, &std.fmt.bytesToHex(tree_entry.oid, .lower)); │ │320 + try indexTree(repo_opts, state, io, allocator, paths, files, key, path, &std.fmt.bytesToHex(tree_entry.oid, .lower), progress_ctx_maybe);│ │321 } else if (indexedOid(repo_opts.hash, tree_entry)) |bytes| { │ │322 try fileKey(allocator, key, path); │ │323 try files.put(key.items, .{ .bytes = bytes }); │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │324 + serve_common.reportProgress(repo_opts, io, progress_ctx_maybe, .{ .complete_one = .writing_patch });│ │325 } │ │326 } │ │327 } │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ────╮ │src/patch.zig│ ╰─────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │16 │ │17 // the action a mergeability recheck records │ │18 pub const mergeability_undo_action = "haxy/mergeability"; │ │19 - │ │20 -// progress is optional and best effort: a failed report must not fail a refresh │ │21 -fn reportProgress(comptime repo_opts: rp.RepoOpts(.xit), io: std.Io, progress_ctx_maybe: ?repo_opts.ProgressCtx, event: rp.ProgressEvent) void {│ │22 - if (repo_opts.ProgressCtx != void) { │ │23 - if (progress_ctx_maybe) |progress_ctx| progress_ctx.run(io, event) catch {}; │ │24 - } │ │25 -} │ │19 │ │20 // whether a push moved this branch │ │21 fn branchUpdated(updates: []const xit.net_server_receive_pack.AppliedRefUpdate, branch: []const u8) bool { │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯