╭ changed ──╮ │src/try.zig│ ╰───────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │679 │ │680 try evt.consume(.local, .repo, .xit, .{}, io, allocator, &template_repo, evt.events_ref, &ours); │ │681 │ │682 - // consume can't root a new branch, so theirs commits by hand │ │683 - var json: std.Io.Writer.Allocating = .init(allocator); │ │684 - defer json.deinit(); │ │685 - for (theirs, 0..) |event, i| { │ │686 - json.clearRetainingCapacity(); │ │687 - try std.json.Stringify.value(event, .{}, &json.writer); │ │688 - const author = try std.fmt.allocPrint(allocator, "{s} <{s}>", .{ event.author.name, event.author.email });│ │689 - defer allocator.free(author); │ │690 - _ = try template_repo.commitAtRef(io, allocator, .{ │ │691 - .author = author, │ │692 - .message = json.written(), │ │693 - .timestamp = event.timestamp, │ │694 - // root the branch at the shared seed tip │ │695 - .parent_oids = if (i == 0) &.{seed_tip} else null, │ │696 - }, null, other_ref); │ │697 - } │ │682 + try commitEventsAtRef(io, allocator, &template_repo, other_ref, &theirs, seed_tip); │ │683 │ │684 { │ │685 var to_events = try template_repo.switchDir(io, allocator, .{ .target = .{ .ref = evt.events_ref } }); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1323 theirs[2].event.patch = theirs_values[2]; │ │1324 │ │1325 try evt.consume(.server, .repo, .xit, .{}, io, allocator, target_repo, evt.events_ref, &ours); │ │1341 - var json: std.Io.Writer.Allocating = .init(allocator); │ │1342 - defer json.deinit(); │ │1343 - for (theirs, 0..) |event, i| { │ │1344 - json.clearRetainingCapacity(); │ │1345 - try std.json.Stringify.value(event, .{}, &json.writer); │ │1346 - const author = try std.fmt.allocPrint(allocator, "{s} <{s}>", .{ event.author.name, event.author.email }); │ │1347 - defer allocator.free(author); │ │1348 - _ = try target_repo.commitAtRef(io, allocator, .{ │ │1349 - .author = author, │ │1350 - .message = json.written(), │ │1351 - .timestamp = event.timestamp, │ │1352 - .parent_oids = if (i == 0) &.{seed_tip} else null, │ │1353 - }, null, other_ref); │ │1354 - } │ │1326 + try commitEventsAtRef(io, allocator, target_repo, other_ref, &theirs, seed_tip); │ │1327 { │ │1328 var merge = try target_repo.mergeAtRef(io, allocator, .{ .kind = .full, .action = .{ .new = .{ .source = &.{.{ .ref = other_ref }} } } }, evt.events_ref, null);│ │1329 defer merge.deinit(); │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1340 }, null, patch_author); │ │1341 } │ │1342 │ │1343 +// commit `events` onto `ref`, rooted at `parent`, as one undoable step. │ │1344 +// consume always roots a new branch at nothing, so the divergent fixtures │ │1345 +// write their side branch here instead, recording the action consume would │ │1346 +fn commitEventsAtRef( │ │1347 + io: std.Io, │ │1348 + allocator: std.mem.Allocator, │ │1349 + repo: *rp.Repo(.xit, .{}), │ │1350 + ref: xit.ref.Ref, │ │1351 + events: []const evt.EventWithId, │ │1352 + parent: [hash.hexLen(.sha1)]u8, │ │1353 +) !void { │ │1354 + const Repo = rp.Repo(.xit, .{}); │ │1355 + const DB = Repo.DB; │ │1356 + const Ctx = struct { │ │1357 + core: *Repo.Core, │ │1358 + io: std.Io, │ │1359 + allocator: std.mem.Allocator, │ │1360 + ref: xit.ref.Ref, │ │1361 + events: []const evt.EventWithId, │ │1362 + parent: [hash.hexLen(.sha1)]u8, │ │1363 + │ │1364 + pub fn run(ctx: @This(), cursor: *DB.Cursor(.read_write)) !void { │ │1365 + var moment = try DB.HashMap(.read_write).init(cursor.*); │ │1366 + const state = Repo.State(.read_write){ .core = ctx.core, .extra = .{ .moment = &moment } }; │ │1367 + try evt.commitEvents(.xit, .{}, state, ctx.io, ctx.allocator, ctx.ref, ctx.events, .{ctx.parent}); │ │1368 + try xit.undo.write(.{}, state, std.Io.Timestamp.now(ctx.io, .real).toSeconds(), .{ .custom = .{ .action = evt.undo_action } });│ │1369 + } │ │1370 + }; │ │1371 + │ │1372 + try repo.core.db_file.lock(io, .exclusive); │ │1373 + defer repo.core.db_file.unlock(io); │ │1374 + │ │1375 + const history = try DB.ArrayList(.read_write).init(repo.core.db.rootCursor()); │ │1376 + try history.appendContext(.{ .slot = try history.getSlot(-1) }, Ctx{ │ │1377 + .core = &repo.core, │ │1378 + .io = io, │ │1379 + .allocator = allocator, │ │1380 + .ref = ref, │ │1381 + .events = events, │ │1382 + .parent = parent, │ │1383 + }); │ │1384 +} │ │1385 + │ │1386 // recursively copy the contents of src_dir into dest_dir │ │1387 fn copyDir(io: std.Io, src_dir: std.Io.Dir, dest_dir: std.Io.Dir) !void { │ │1388 var iter = src_dir.iterate(); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯