╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ───────────────╮ │src/test/event/patch.zig│ ╰────────────────────────╯ ╭──────────────────────────────────────────────────────────────╮ │ 7 const rf = xit.ref; │ │ 8 const fork = @import("../../fork.zig"); │ │ 9 const pch = @import("../../patch.zig"); │ │10 +const push = @import("../../push.zig"); │ │11 │ │12 const repo_opts: rp.RepoOpts(.xit) = .{ .is_test = true };│ │13 const Repo = rp.Repo(.xit, repo_opts); │ ╰──────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │62 │ │63 // an unchanged refresh does not add events │ │64 const event_tip = (try repo.readRef(io, evt.events_ref)) orelse return error.NotFound; │ │64 - try pch.refreshBranches(.local, kind, opts, io, allocator, &repo, null); │ │65 + try pch.refreshBranches(.local, kind, opts, io, allocator, &repo, null, null); │ │66 try std.testing.expectEqualStrings(&event_tip, &(try repo.readRef(io, evt.events_ref) orelse return error.NotFound));│ │67 │ │68 // retargeting to the source leaves the patch and revision unchanged │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │76 │ │77 // a source update replaces the revision, not the patch metadata │ │78 const next = try repo.commitAtRef(io, allocator, .{ .message = "next feature" }, null, .{ .kind = .head, .name = "feature" });│ │78 - try pch.refreshBranches(.local, kind, opts, io, allocator, &repo, null); │ │79 + try pch.refreshBranches(.local, kind, opts, io, allocator, &repo, null, null); │ │80 const updated = (try evt.Patch.readFromRepo(kind, opts, io, allocator, &arena, &repo, &id)) orelse return error.NotFound; │ │81 const revision = updated.event.revision orelse return error.NotFound; │ │82 try std.testing.expectEqualStrings(&next, revision.source_oid); │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │124 │ │125 // removing the patch leaves its branch intact │ │126 try evt.remove(.local, .repo, kind, opts, io, allocator, &repo, &id, .patch, author); │ │126 - try pch.refreshBranches(.local, kind, opts, io, allocator, &repo, null); │ │127 + try pch.refreshBranches(.local, kind, opts, io, allocator, &repo, null, null); │ │128 const removed = (try evt.Patch.readFromRepo(kind, opts, io, allocator, &arena, &repo, &id)) orelse return error.NotFound; │ │129 try std.testing.expect(removed.removed); │ │130 try std.testing.expectEqualStrings(&next, &(try repo.readRef(io, .{ .kind = .head, .name = "feature" }) orelse return error.NotFound));│ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────╮ │145 fn testBranchMerge(selection: pch.MergeRevision) !void { │ │146 const io = std.testing.io; │ │147 const allocator = std.testing.allocator; │ │148 + const opts: rp.RepoOpts(.xit) = .{ .is_test = true, .ProgressCtx = *push.PushProgress };│ │149 var temp = std.testing.tmpDir(.{}); │ │150 defer temp.cleanup(); │ │151 const path = try temp.dir.realPathFileAlloc(io, ".", allocator); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────╮ │152 defer allocator.free(path); │ │151 - var repo = try Repo.init(io, allocator, .{ .path = path }); │ │153 + var repo = try rp.Repo(.xit, opts).init(io, allocator, .{ .path = path });│ │154 defer repo.deinit(io, allocator); │ │155 { │ │156 const file = try repo.core.work_dir.createFile(io, "base.txt", .{}); │ ╰───────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │163 _ = try repo.commitAtRef(io, allocator, .{ .message = "remove file" }, null, .{ .kind = .head, .name = "feature" });│ │164 const id = [_]u8{9} ** evt.event_id_size; │ │165 const id_hex = std.fmt.bytesToHex(id, .lower); │ │164 - try pch.writeBranchPatch(.server, .xit, repo_opts, io, allocator, &repo, id_hex, .{ │ │166 + try pch.writeBranchPatch(.server, .xit, opts, io, allocator, &repo, id_hex, .{ │ │167 .title = "merge branch", │ │168 .description = "", │ │169 .tags = "", │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │170 .source_branch = "feature", │ │171 .target_branch = "master", │ │172 }, null, author); │ │173 + │ │174 + // updating a branch and checking its mergeability counts as one patch │ │175 + _ = try repo.commitAtRef(io, allocator, .{ .message = "revise feature" }, null, .{ .kind = .head, .name = "feature" }); │ │176 + var response = xit.net_server_receive_pack.Response.init(allocator); │ │177 + defer response.deinit(); │ │178 + response.sideband = true; │ │179 + var output = std.Io.Writer.Allocating.init(allocator); │ │180 + defer output.deinit(); │ │181 + var progress = push.PushProgress{ .response = &response, .writer = &output.writer, .label = "Updating patches" }; │ │182 + try pch.refreshBranches(.server, .xit, opts, io, allocator, &repo, null, &progress); │ │183 + try std.testing.expect(std.mem.indexOf(u8, output.written(), "Updating patches: 100% (1/1)\n") != null); │ │184 + │ │185 var arena = std.heap.ArenaAllocator.init(allocator); │ │186 defer arena.deinit(); │ │173 - const before = (try evt.Patch.readFromRepo(.xit, repo_opts, io, allocator, &arena, &repo, &id)) orelse return error.NotFound;│ │187 + const before = (try evt.Patch.readFromRepo(.xit, opts, io, allocator, &arena, &repo, &id)) orelse return error.NotFound; │ │188 const revision = before.event.revision orelse return error.NotFound; │ │189 │ │190 // both merge styles use the stored revision, without fork data │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │177 - try pch.merge(repo_opts, io, allocator, path, &repo, .{ .id = id_hex, .revision = selection, .author = author, .timestamp = 100 });│ │178 - const merged = (try evt.Patch.readFromRepo(.xit, repo_opts, io, allocator, &arena, &repo, &id)) orelse return error.NotFound; │ │191 + try pch.merge(opts, io, allocator, path, &repo, .{ .id = id_hex, .revision = selection, .author = author, .timestamp = 100 }); │ │192 + const merged = (try evt.Patch.readFromRepo(.xit, opts, io, allocator, &arena, &repo, &id)) orelse return error.NotFound; │ │193 const oid = switch (merged.event.status) { │ │194 .merged => |value| value, │ │195 else => return error.NotMerged, │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │199 // the source survives, and merged patches no longer follow it │ │200 _ = try repo.commitAtRef(io, allocator, .{ .message = "later" }, null, .{ .kind = .head, .name = "feature" }); │ │201 const tip = (try repo.readRef(io, evt.events_ref)) orelse return error.NotFound; │ │188 - try pch.refreshBranches(.server, .xit, repo_opts, io, allocator, &repo, null); │ │202 + const progress_len = output.written().len; │ │203 + try pch.refreshBranches(.server, .xit, opts, io, allocator, &repo, null, &progress); │ │204 + try std.testing.expectEqual(progress_len, output.written().len); │ │205 try std.testing.expectEqualStrings(&tip, &(try repo.readRef(io, evt.events_ref) orelse return error.NotFound));│ │206 } │ │207 │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯