╭ changed ────╮ │build.zig.zon│ ╰─────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ 3 .version = "0.0.0", │ │ 4 .dependencies = .{ │ │ 5 .xit = .{ │ │ 6 - .url = "git+https://github.com/xit-vcs/xit#76d5591bafdd25c1a30f60bd224bcd84fc95577d",│ │ 7 - .hash = "xit-0.0.0-Ub3nDGS9UAHche9pY_qj70UbdduOnZegBJO1PupJ0E-H", │ │ 6 + .url = "git+https://github.com/xit-vcs/xit#a03d42c2df8b99e7acd07a3f7f5649f4f030afea",│ │ 7 + .hash = "xit-0.0.0-Ub3nDC_AUAHpFNtNIafDErmwH_O1vlKiE0ybWJC6SQ4B", │ │ 8 }, │ │ 9 }, │ │10 .paths = .{ │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ────╮ │src/event.zig│ ╰─────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────╮ │477 │ │478 // commit each event as a JSON commit message on `ref` through `state`, so a│ │479 // xit repo can write them inside an already-open transaction │ │480 -fn commitEvents( │ │480 +pub fn commitEvents( │ │481 comptime repo_kind: rp.RepoKind, │ │482 comptime repo_opts: rp.RepoOpts(repo_kind), │ │483 state: rp.Repo(repo_kind, repo_opts).State(.read_write), │ ╰─────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │963 const record_maybe: ?PatchRev.Record = if (event_maybe) |event| blk: { │ │964 const trees = try PatchRev.readTrees(repo_kind, repo_opts, read_state, io, allocator, &commit_object.content.commit.tree);│ │965 const existing_maybe = try PatchRev.readById(DB, repo_opts.hash, haxy_moment.readOnly(), &arena, &current_event_id); │ │966 + const event_oid = std.fmt.bytesToHex(repo_event_oid, .lower); │ │967 │ │968 var patch_oid: [hash.hexLen(repo_opts.hash)]u8 = undefined; │ │969 if (existing_maybe) |existing| { │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │992 .event = event, │ │993 .author_email = authorEmail(commit_object.content.commit.metadata.author orelse ""),│ │994 .created_order = event_order, │ │995 + .event_oid = &event_oid, │ │996 .base_tree_oid = &trees.base, │ │997 .head_tree_oid = &trees.head, │ │998 .patch_oid = &patch_oid, │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ─────────╮ │src/event/Fork.zig│ ╰──────────────────╯ ╭──────────────────────────────────────────────────────────────────────────╮ │ 5 │ │ 6 user_id: []const u8, │ │ 7 repo_id: []const u8, │ │ 8 -target: []const u8, │ │ 9 -source_oid: ?[]const u8 = null, │ │ 8 │ │ 9 // what the db stores: the event's data plus the commit-derived fields│ │10 pub const Record = struct { │ ╰──────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────╮ │24 fn validate(record: Record) !void { │ │25 if (record.event.user_id.len != evt.event_id_size) return error.InvalidUserId; │ │26 if (record.event.repo_id.len != evt.event_id_size) return error.InvalidRepoId; │ │29 - if (!xit.ref.validateName(record.event.target)) return error.InvalidTarget; │ │30 - if (record.event.source_oid) |oid| { │ │31 - if (oid.len == 0 or oid.len % 2 != 0) return error.InvalidSourceOid; │ │32 - for (oid) |c| { │ │33 - if (!std.ascii.isDigit(c) and !(c >= 'a' and c <= 'f')) return error.InvalidSourceOid;│ │34 - } │ │35 - } │ │27 } │ │28 │ │29 pub fn consume( │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │57 if (!record.removed) try validate(record); │ │58 │ │59 if (existing_maybe) |existing| { │ │60 + if (!std.mem.eql(u8, existing.event.user_id, record.event.user_id) or │ │61 + !std.mem.eql(u8, existing.event.repo_id, record.event.repo_id)) return error.ForkChanged;│ │62 record.created_order = existing.created_order; │ │63 if (!existing.removed) { │ │64 const order_key = evt.orderKeyDesc(existing.created_order, event_id); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ──────────╮ │src/event/Patch.zig│ ╰───────────────────╯ ╭───────────────────────────────────────────────────────╮ │ 6 title: []const u8, │ │ 7 description: []const u8, │ │ 8 tags: []const u8, // space-separated │ │ 9 -target_ref: []const u8, │ │ 9 target_patch_id: ?[evt.event_id_size * 2]u8 = null,│ │11 -patchrev_id: [evt.event_id_size * 2]u8, │ │10 +patchrev_id: ?[evt.event_id_size * 2]u8 = null, │ │11 │ │12 pub const Record = struct { │ │13 event: Self, │ ╰───────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │63 break :blk value; │ │64 }; │ │65 │ │67 - if (!fieldsValid(record.event.title, record.event.tags) or record.event.target_ref.len == 0) { │ │68 - return error.InvalidPatch; │ │69 - } │ │70 - const patchrev_id = try evt.parseEventId(&record.event.patchrev_id); │ │66 + if (!fieldsValid(record.event.title, record.event.tags)) return error.InvalidPatch; │ │67 + if (record.event.patchrev_id) |*id| _ = try evt.parseEventId(id); │ │68 const target_patch_id = if (record.event.target_patch_id) |*id| try evt.parseEventId(id) else null;│ │69 if (target_patch_id) |*id| { │ │70 if (std.mem.eql(u8, id, event_id)) return error.InvalidPatch; │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ 83 } │ │ 84 } │ │ 85 │ │ 89 - if (event_oid != null) { │ │ 90 - const changed = if (existing_maybe) |existing| !std.mem.eql(u8, &existing.event.patchrev_id, &record.event.patchrev_id) else true; │ │ 91 - if (changed) { │ │ 92 - const patchrev = (try evt.PatchRev.readById(DB, hash_kind, haxy_moment.readOnly(), arena, &patchrev_id)) orelse return error.PatchRevNotFound; │ │ 93 - if (patchrev.removed) return error.PatchRevNotFound; │ │ 94 - if (target_patch_id) |*target_id| { │ │ 95 - const target = (try readById(DB, hash_kind, haxy_moment.readOnly(), arena, target_id)) orelse return error.TargetPatchNotFound; │ │ 96 - if (target.removed) return error.TargetPatchNotFound; │ │ 97 - const target_patchrev_id = try evt.parseEventId(&target.event.patchrev_id); │ │ 98 - const target_patchrev = (try evt.PatchRev.readById(DB, hash_kind, haxy_moment.readOnly(), arena, &target_patchrev_id)) orelse return error.PatchRevNotFound;│ │ 99 - if (target_patchrev.removed) return error.PatchRevNotFound; │ │100 - if (!std.mem.eql(u8, patchrev.event.base_oid, target_patchrev.patch_oid) or │ │101 - !std.mem.eql(u8, patchrev.base_tree_oid, target_patchrev.head_tree_oid)) │ │102 - { │ │103 - return error.InvalidPatchBase; │ │104 - } │ │105 - } │ │106 - } │ │107 - } │ │108 - │ │ 86 try evt.writeOid(Self, DB, hash_kind, field_oid_map, record_key, if (existing_maybe) |existing| existing.event else null, record.event, event_oid); │ │ 87 │ │ 88 const cursor = try records.putCursor(record_key); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯