╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ fork.zig ─────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │http│ ssh │ │ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
187 // the copied db carries the target's file index, so the patch 188 // branch's entry starts from one of those rather than walking 189 // the tree 190 _ = try find.refreshInTransaction(repo_opts, state, &moment, ctx.io, ctx.allocator, null); 191 192 try xit.undo.write(repo_opts, state, std.Io.Timestamp.now(ctx.io, .real).toSeconds(), .{ .custom = .{ .action_kind = undo_action } }); 193 } 194 }; 195 196 try fork_repo.core.db_file.lock(io, .exclusive); 197 defer fork_repo.core.db_file.unlock(io); 198 199 const history = try DB.ArrayList(.read_write).init(fork_repo.core.db.rootCursor()); 200 try history.appendContext( 201 .{ .slot = try history.getSlot(-1) }, 202 Ctx{ .core = &fork_repo.core, .io = io, .allocator = allocator }, 203 ); 204 } 205 206 // create the patch event 207 try evt.consume(.{ .server = .{ .users_dir = users_dir } }, .fork, .xit, repo_opts, io, allocator, &fork_repo, evt.events_ref, &.{.{ 208 .id = input.id, 209 .timestamp = input.timestamp, 210 .author = input.author, 211 .event = .{ .patch = .{ 212 .title = input.title, 213 .description = input.description, 214 .labels = input.labels, 215 .target_branch = input.target_branch, 216 } }, 217 }}); 218 219 // create the fork event 220 try evt.consume(.{ .server = .{ .users_dir = users_dir } }, .user, .xit, evt.user_repo_opts, io, allocator, &user_repo, evt.events_ref, &.{.{ 221 .id = input.id, 222 .timestamp = input.timestamp, 223 .author = input.author, 224 .event = .{ .fork = .{ 225 .repo_id = &input.repo_id, 226 .repo_user_id = &input.repo_user_id, 227 } }, 228 }}); 229 230 return fork_path; 231 } 232 233 // tombstone first so a missing fork never remains visible 234 pub fn remove( 235 io: std.Io, 236 allocator: std.mem.Allocator, 237 users_dir: []const u8, 238 forker_id: *const [evt.event_id_size]u8, 239 id: *const [evt.event_id_size * 2]u8, 240 author: evt.CommitAuthor, 241 ) !void { 242 const fork_id = try evt.parseEventId(id); 243 var user_repo = (try evt.openUserRepo(io, allocator, users_dir, forker_id)) orelse return error.InvalidPatchDraft; 244 defer user_repo.deinit(io, allocator); 245 var arena = std.heap.ArenaAllocator.init(allocator); 246 defer arena.deinit(); 247 const moment = (try evt.userMoment(&user_repo)) orelse return error.InvalidPatchDraft; 248 const record = (try evt.Fork.readById(evt.UserDB, evt.user_repo_opts.hash, moment, &arena, &fork_id)) orelse return error.InvalidPatchDraft; 249 if (!record.removed) try evt.remove(.{ .server = .{ .users_dir = users_dir } }, .user, .xit, evt.user_repo_opts, io, allocator, &user_repo, &fork_id, .fork, author); 250 251 const path = try forkPath(allocator, users_dir, forker_id, &fork_id); 252 defer allocator.free(path); 253 try std.Io.Dir.cwd().deleteTree(io, path); 254 } 255