╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ push.zig ─────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │http│ ssh │ │ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
272 &head_tree_oid, 273 identity, 274 identity, 275 ctx.timestamp, 276 ); 277 tree_entries = .{ 278 .{ .tree = .{ .name = "base", .oid = &base_tree_oid } }, 279 .{ .tree = .{ .name = "head", .oid = &head_tree_oid } }, 280 }; 281 events[event_count] = .{ 282 .id = revision_hex, 283 .timestamp = ctx.timestamp, 284 .author = ctx.author, 285 .tree_entries = &tree_entries, 286 .event = .{ .patchrev = revision_event }, 287 }; 288 event_count += 1; 289 ctx.revision_id_maybe.* = revision_id; 290 291 if (!ctx.published) { 292 var patch = ctx.patch.event; 293 patch.revision = .{ 294 .id = revision_hex, 295 .squash_oid = &patch_oid, 296 .source_oid = &source_oid, 297 }; 298 events[event_count] = .{ 299 .id = ctx.patch_id, 300 .timestamp = ctx.timestamp, 301 .author = ctx.author, 302 .event = .{ .patch = patch }, 303 }; 304 event_count += 1; 305 } 306 } 307 308 // published patches keep only revisions in the fork 309 if (ctx.published and !ctx.patch.removed) { 310 events[event_count] = .{ 311 .id = ctx.patch_id, 312 .timestamp = ctx.timestamp, 313 .author = ctx.author, 314 .event = .{ .patch = null }, 315 }; 316 event_count += 1; 317 } 318 319 // commit and index any new events 320 if (event_count > 0) { 321 try evt.commitEvents(.xit, repo_opts, state, ctx.io, ctx.allocator, evt.events_ref, events[0..event_count], null); 322 if (!try evt.consumeInTransaction(.fork, .xit, repo_opts, state, &ctx.core.db, &moment, ctx.io, ctx.allocator, evt.events_ref)) return error.CancelTransaction; 323 } 324 try xit.undo.writeMessage(repo_opts, state, .push); 325 } 326 }; 327 328 try fork_repo.core.db_file.lock(io, .exclusive); 329 defer fork_repo.core.db_file.unlock(io); 330 331 const history = try DB.ArrayList(.read_write).init(fork_repo.core.db.rootCursor()); 332 history.appendContext(.{ .slot = try history.getSlot(-1) }, Ctx{ 333 .core = &fork_repo.core, 334 .target_core = &target_repo.core, 335 .io = io, 336 .allocator = allocator, 337 .reader = reader, 338 .writer = writer, 339 .response = &response, 340 .patch_id = id.*, 341 .patch = fork_patch, 342 .published = published, 343 .target_oid = target_oid, 344 .title = title, 345 .author = author, 346 .timestamp = timestamp, 347 .newest = newest, 348 .revision_id_maybe = &revision_id_maybe, 349 }) catch |err| { 350 response.finish(writer, @errorName(err)) catch {}; 351 if (err == error.CancelTransaction) return; 352 return err; 353 }; 354 try response.finish(writer, null); 355 } 356 357 // best-effort update the published patch so it has the new revision 358 { 359 const revision_id = revision_id_maybe orelse return; 360 if (!published) return; 361 var update_arena = std.heap.ArenaAllocator.init(allocator); 362 defer update_arena.deinit(); 363 const target_update_moment = evt.currentMoment(repo_opts, target_repo) catch return; 364 const published_patch = (evt.Patch.readById(evt.EventDB(repo_opts.hash), repo_opts.hash, target_update_moment, &update_arena, &patch_id) catch return) orelse return; 365 if (published_patch.removed) return; 366 const fork_update_moment = evt.currentMoment(repo_opts, fork_repo) catch return; 367 const revision = (evt.PatchRev.readById(evt.EventDB(repo_opts.hash), repo_opts.hash, fork_update_moment, &update_arena, &revision_id) catch return) orelse return; 368 if (revision.removed) return; 369 const selected = evt.Patch.Revision.fromRecord(revision_id, revision); 370 if (published_patch.event.revision) |current| { 371 if (evt.fieldEqual(evt.Patch.Revision, current, selected)) return; 372 } 373 var patch = published_patch.event; 374 patch.revision = selected; 375 evt.consume(.repo, .xit, repo_opts, io, allocator, target_repo, evt.events_ref, &.{.{ 376 .id = id.*, 377 .timestamp = timestamp, 378 .author = author, 379 .event = .{ .patch = patch }, 380 }}) catch |update_err| { 381 serve_common.logError(io, error_writer, "failed to update published patch {s}: {s}\n", .{ id, @errorName(update_err) }); 382 }; 383 } 384 } 385