╭ changed ────╮ │src/event.zig│ ╰─────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │559 }, &tree, ref); │ │560 // later events parent on the ref's new tip │ │561 parent_oids = null; │ │562 - } │ │563 -} │ │564 - │ │565 -pub const PushProgress = struct { │ │566 - response: *xit.net_server_receive_pack.Response, │ │567 - writer: *std.Io.Writer, │ │568 - count: usize = 0, │ │569 - total: usize = 0, │ │570 - │ │571 - pub fn run(self: *PushProgress, _: std.Io, event: rp.ProgressEvent) !void { │ │572 - switch (event) { │ │573 - .start => |start| { │ │574 - if (start.kind != .writing_patch) return; │ │575 - self.total = start.estimated_total_items; │ │576 - self.count = 0; │ │577 - }, │ │578 - .complete_one => |kind| { │ │579 - if (kind != .writing_patch) return; │ │580 - self.count += 1; │ │581 - }, │ │582 - .end => |kind| { │ │583 - if (kind != .writing_patch) return; │ │584 - }, │ │585 - else => return, │ │586 - } │ │587 - var buffer: [128]u8 = undefined; │ │588 - const percent = if (self.total == 0) 100 else @as(u128, self.count) * 100 / self.total; │ │589 - const text = try std.fmt.bufPrint(&buffer, "Processing commits: {d}% ({d}/{d}){s}", .{ percent, self.count, self.total, if (event == .end) "\n" else "\r" });│ │590 - try self.response.progress(self.writer, text); │ │591 - } │ │592 -}; │ │593 - │ │594 -// prepare all reachable commits, including history received before patch │ │595 -// generation was enabled. this shares the receive-pack transaction. │ │596 -pub fn writeReceivedPatches( │ │597 - comptime repo_opts: rp.RepoOpts(.xit), │ │598 - state: rp.Repo(.xit, repo_opts).State(.read_write), │ │599 - io: std.Io, │ │600 - allocator: std.mem.Allocator, │ │601 - response: *xit.net_server_receive_pack.Response, │ │602 - writer: *std.Io.Writer, │ │603 -) !void { │ │604 - try response.progress(writer, "Processing commits...\n"); │ │605 - var config = try xit.config.Config(.xit, repo_opts).init(state.readOnly(), io, allocator); │ │606 - defer config.deinit(); │ │607 - try config.add(state, io, .{ .name = "merge.algorithm", .value = "patch" }); │ │608 - │ │609 - var iter = try obj.ObjectIterator(.xit, repo_opts).init(state.readOnly(), io, allocator, .{ .kind = .commit }); │ │610 - defer iter.deinit(); │ │611 - var refs = try rf.AllRefIterator(.xit, repo_opts).init(state.readOnly(), allocator); │ │612 - defer refs.deinit(); │ │613 - while (try refs.next()) |ref| { │ │614 - if (try rf.readRecur(.xit, repo_opts, state.readOnly(), io, .{ .ref = ref })) |oid| { │ │615 - try iter.include(&oid); │ │616 - } │ │562 } │ │618 - var progress = PushProgress{ .response = response, .writer = writer }; │ │619 - try xit.patch.writePatches(repo_opts, state, io, allocator, &iter, &progress); │ │620 -} │ │621 - │ │622 -// serve a receive-pack and consume any events it pushed to the events branch, │ │623 -// all in one transaction: the push and the views derived from it commit │ │624 -// atomically, and a failed consume cancels the push │ │625 -pub fn receivePackAndConsume( │ │626 - comptime repo_opts: rp.RepoOpts(.xit), │ │627 - io: std.Io, │ │628 - allocator: std.mem.Allocator, │ │629 - repo: *rp.Repo(.xit, repo_opts), │ │630 - reader: *std.Io.Reader, │ │631 - writer: *std.Io.Writer, │ │632 - options: xit.net_server_receive_pack.Options, │ │633 - repo_root_path: []const u8, │ │634 - error_writer: *std.Io.Writer, │ │635 -) !void { │ │636 - const DB = rp.Repo(.xit, repo_opts).DB; │ │637 - const State = rp.Repo(.xit, repo_opts).State; │ │638 - │ │639 - var response = xit.net_server_receive_pack.Response.init(allocator); │ │640 - defer response.deinit(); │ │641 - │ │642 - const Ctx = struct { │ │643 - core: *rp.Repo(.xit, repo_opts).Core, │ │644 - io: std.Io, │ │645 - allocator: std.mem.Allocator, │ │646 - reader: *std.Io.Reader, │ │647 - writer: *std.Io.Writer, │ │648 - options: xit.net_server_receive_pack.Options, │ │649 - response: *xit.net_server_receive_pack.Response, │ │650 - repo_root_path: []const u8, │ │651 - error_writer: *std.Io.Writer, │ │652 - │ │653 - pub fn run(ctx: @This(), cursor: *DB.Cursor(.read_write)) !void { │ │654 - var moment = try DB.HashMap(.read_write).init(cursor.*); │ │655 - const state = State(.read_write){ .core = ctx.core, .extra = .{ .moment = &moment } }; │ │656 - var updates = xit.net_server_receive_pack.AppliedRefUpdates.init(ctx.allocator); │ │657 - defer updates.deinit(); │ │658 - var receive_options = ctx.options; │ │659 - receive_options.applied_ref_updates = &updates; │ │660 - receive_options.deferred_response = ctx.response; │ │661 - try xit.net_server_receive_pack.run(.xit, repo_opts, state, ctx.io, ctx.allocator, ctx.reader, ctx.writer, receive_options); │ │662 - try writeReceivedPatches(repo_opts, state, ctx.io, ctx.allocator, ctx.response, ctx.writer); │ │663 - │ │664 - // a repo without an events branch has no events to consume. a │ │665 - // no-op consume must not cancel here, since the push shares the │ │666 - // transaction and must commit regardless. │ │667 - if (null != try rf.readRecur(.xit, repo_opts, state.readOnly(), ctx.io, .{ .ref = events_ref })) { │ │668 - _ = try consumeInTransaction(.repo, .xit, repo_opts, state, &ctx.core.db, &moment, ctx.io, ctx.allocator, events_ref); │ │669 - try pch.detectMerged(repo_opts, state, &ctx.core.db, &moment, ctx.io, ctx.allocator, ctx.repo_root_path, updates.items.items, ctx.error_writer); │ │670 - } │ │671 - try xit.undo.writeMessage(repo_opts, state, .push); │ │672 - } │ │673 - }; │ │674 - │ │675 - try repo.core.db_file.lock(io, .exclusive); │ │676 - defer repo.core.db_file.unlock(io); │ │677 - │ │678 - const history = try DB.ArrayList(.read_write).init(repo.core.db.rootCursor()); │ │679 - history.appendContext( │ │680 - .{ .slot = try history.getSlot(-1) }, │ │681 - Ctx{ │ │682 - .core = &repo.core, │ │683 - .io = io, │ │684 - .allocator = allocator, │ │685 - .reader = reader, │ │686 - .writer = writer, │ │687 - .options = options, │ │688 - .response = &response, │ │689 - .repo_root_path = repo_root_path, │ │690 - .error_writer = error_writer, │ │691 - }, │ │692 - ) catch |err| { │ │693 - response.finish(writer, @errorName(err)) catch {}; │ │694 - if (err == error.CancelTransaction) return; │ │695 - return err; │ │696 - }; │ │697 - │ │698 - try response.finish(writer, null); │ │563 } │ │564 │ │565 // a standalone event db holding events consumed from a local repo's events │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯