╭ changed ───────────────╮ │src/test/event/patch.zig│ ╰────────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │12 const repo_opts: rp.RepoOpts(.xit) = .{ .is_test = true }; │ │13 const Repo = rp.Repo(.xit, repo_opts); │ │14 const author = evt.CommitAuthor{ .name = "alice", .email = "alice@example.test" }; │ │15 + │ │16 +test "patch commit counts require a short first-parent path" { │ │17 + const io = std.testing.io; │ │18 + const allocator = std.testing.allocator; │ │19 + var temp = std.testing.tmpDir(.{}); │ │20 + defer temp.cleanup(); │ │21 + const path = try temp.dir.realPathFileAlloc(io, ".", allocator); │ │22 + defer allocator.free(path); │ │23 + var repo = try Repo.init(io, allocator, .{ .path = path }); │ │24 + defer repo.deinit(io, allocator); │ │25 + const branch = rf.Ref{ .kind = .head, .name = "patch" }; │ │26 + │ │27 + // a second-parent base must not produce a misleading depth difference │ │28 + const root = try repo.commitAtRef(io, allocator, .{ .message = "root" }, null, branch); │ │29 + const base = try repo.commitAtRef(io, allocator, .{ .message = "base" }, null, branch); │ │30 + const source = try repo.commitAtRef(io, allocator, .{ .message = "source", .parent_oids = &.{root} }, null, branch); │ │31 + var tip = try repo.commitAtRef(io, allocator, .{ .message = "merge", .parent_oids = &.{ source, base } }, null, branch); │ │32 + var moment = try repo.core.latestMoment(); │ │33 + const state = Repo.State(.read_only){ .core = &repo.core, .extra = .{ .moment = &moment } }; │ │34 + try std.testing.expectEqual(null, try evt.PatchRev.commitCount(.xit, repo_opts, state, io, allocator, &base, &tip)); │ │35 + try std.testing.expectEqual(@as(?u64, 2), try evt.PatchRev.commitCount(.xit, repo_opts, state, io, allocator, &root, &tip)); │ │36 + try std.testing.expectEqual(null, try evt.PatchRev.commitCount(.xit, repo_opts, state, io, allocator, &tip, &root)); │ │37 + try std.testing.expectEqual(null, try evt.PatchRev.commitCount(.xit, repo_opts, state, io, allocator, &base, &source)); │ │38 + │ │39 + // long ranges omit the count instead of walking unbounded history │ │40 + for (2..256) |_| { │ │41 + tip = try repo.commitAtRef(io, allocator, .{ .message = "next" }, null, branch); │ │42 + } │ │43 + moment = try repo.core.latestMoment(); │ │44 + try std.testing.expectEqual(@as(?u64, 256), try evt.PatchRev.commitCount(.xit, repo_opts, state, io, allocator, &root, &tip));│ │45 + tip = try repo.commitAtRef(io, allocator, .{ .message = "next" }, null, branch); │ │46 + moment = try repo.core.latestMoment(); │ │47 + try std.testing.expectEqual(null, try evt.PatchRev.commitCount(.xit, repo_opts, state, io, allocator, &root, &tip)); │ │48 +} │ │49 │ │50 test "branch patch lifecycle" { │ │51 try testBranchPatch(.git, .sha1); │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │92 const first = (try evt.Patch.readFromRepo(kind, opts, io, allocator, &arena, &repo, &id)) orelse return error.NotFound; │ │93 const first_revision = first.event.revision orelse return error.NotFound; │ │94 try std.testing.expectEqualStrings(&base, first_revision.source_oid); │ │95 + try std.testing.expectEqual(@as(?u64, if (kind == .xit) 0 else null), first_revision.commit_count); │ │96 try std.testing.expectEqualStrings(&base, &(try repo.readRef(io, .{ .kind = .head, .name = "master" }) orelse return error.NotFound));│ │97 │ │98 // an unchanged refresh does not add events │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │115 const updated = (try evt.Patch.readFromRepo(kind, opts, io, allocator, &arena, &repo, &id)) orelse return error.NotFound;│ │116 const revision = updated.event.revision orelse return error.NotFound; │ │117 try std.testing.expectEqualStrings(&next, revision.source_oid); │ │118 + try std.testing.expectEqual(@as(?u64, if (kind == .xit) 1 else null), revision.commit_count); │ │119 try std.testing.expect(!std.mem.eql(u8, &first_revision.id, &revision.id)); │ │120 try std.testing.expectEqualStrings(patch.title, updated.event.title); │ │121 │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯