╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ─────────────╮ │src/event/PatchRev.zig│ ╰──────────────────────╯ ╭───────────────────────────────╮ │ 7 │ │ 8 base_oid: []const u8, │ │ 9 source_oid: []const u8, │ │10 +target_ref: []const u8, │ │11 message: []const u8, │ │12 │ │13 pub const Record = struct {│ ╰───────────────────────────────╯ ╭─────────────────────────────────────────╮ │15 removed: bool = false, │ │16 author_email: ?[]const u8 = null,│ │17 created_order: u64 = 0, │ │18 + event_oid: []const u8, │ │19 base_tree_oid: []const u8, │ │20 head_tree_oid: []const u8, │ │21 patch_oid: []const u8, │ ╰─────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────╮ │89 │ │90 try validateOid(hash_kind, record.event.base_oid); │ │91 try validateOid(hash_kind, record.event.source_oid); │ │92 + if (!std.mem.startsWith(u8, record.event.target_ref, "refs/heads/") or │ │93 + !xit.ref.validateName(record.event.target_ref["refs/".len..])) return error.InvalidTarget;│ │94 + try validateOid(hash_kind, record.event_oid); │ │95 try validateOid(hash_kind, record.base_tree_oid); │ │96 try validateOid(hash_kind, record.head_tree_oid); │ │97 try validateOid(hash_kind, record.patch_oid); │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────╮ │ 99 if (existing_maybe) |existing| { │ │100 if (!std.mem.eql(u8, existing.event.base_oid, record.event.base_oid) or │ │101 !std.mem.eql(u8, existing.event.source_oid, record.event.source_oid) or│ │102 + !std.mem.eql(u8, existing.event.target_ref, record.event.target_ref) or│ │103 !std.mem.eql(u8, existing.event.message, record.event.message) or │ │104 !std.mem.eql(u8, existing.base_tree_oid, record.base_tree_oid) or │ │105 !std.mem.eql(u8, existing.head_tree_oid, record.head_tree_oid) or │ ╰────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────╮ │109 } │ │110 record.created_order = existing.created_order;│ │111 record.author_email = existing.author_email; │ │112 + record.event_oid = existing.event_oid; │ │113 } │ │114 │ │115 const cursor = try records.putCursor(record_key); │ ╰───────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │141 return try evt.read(Record, DB, hash_kind, arena, try DB.HashMap(.read_only).init(record_cursor)); │ │142 } │ │143 │ │144 +pub const WithId = struct { │ │145 + id: [evt.event_id_size]u8, │ │146 + record: Record, │ │147 +}; │ │148 + │ │149 +pub fn readNewest( │ │150 + comptime DB: type, │ │151 + comptime hash_kind: hash.HashKind, │ │152 + haxy_moment: DB.HashMap(.read_only), │ │153 + arena: *std.heap.ArenaAllocator, │ │154 +) !?WithId { │ │155 + const ids_cursor = try haxy_moment.getCursor(hash.hashInt(hash_kind, id_set_key)) orelse return null;│ │156 + const ids = try DB.SortedSet(.read_only).init(ids_cursor); │ │157 + var iter = try ids.iteratorFromIndex(0); │ │158 + while (try iter.next()) |cursor| { │ │159 + const id = try evt.readOrderKeyId(DB, cursor); │ │160 + const record = (try readById(DB, hash_kind, haxy_moment, arena, &id)) orelse continue; │ │161 + if (!record.removed) return .{ .id = id, .record = record }; │ │162 + } │ │163 + return null; │ │164 +} │ │165 + │ │166 // derived commits referenced only by patch revision records │ │167 pub fn gcRoots( │ │168 comptime DB: type, │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ───╮ │src/fork.zig│ ╰────────────╯ ╭──────────────────────────────────────────────────────────────────╮ │ 5 const hash = xit.hash; │ │ 6 const obj = xit.object; │ │ 7 const mrg = xit.merge; │ │ 8 +const rf = xit.ref; │ │ 9 │ │ 9 -pub const ref = xit.ref.Ref{ .kind = .head, .name = "patch" };│ │10 +pub const ref = rf.Ref{ .kind = .head, .name = "patch" }; │ │11 +const ref_path = "refs/heads/patch"; │ │12 │ │13 pub const Route = struct { │ │14 identity: []const u8, │ ╰──────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────╮ │38 id: [evt.event_id_size * 2]u8, │ │39 user_id: [evt.event_id_size]u8,│ │40 repo_id: [evt.event_id_size]u8,│ │39 - target: []const u8, │ │41 + title: []const u8, │ │42 + description: []const u8, │ │43 + tags: []const u8, │ │44 author: evt.CommitAuthor, │ │45 timestamp: u64, │ │46 }; │ ╰───────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────╮ │53 admin_repo: *rp.Repo(.xit, evt.admin_repo_opts), │ │54 input: CreateInput, │ │55 ) ![]u8 { │ │56 + if (!evt.Patch.fieldsValid(input.title, input.tags)) return error.InvalidPatch; │ │57 const fork_id = try evt.parseEventId(&input.id); │ │53 - if (!xit.ref.validateName(input.target)) return error.InvalidTarget; │ │54 - const draft_path = try forkPath(allocator, repo_root_path, &input.id); │ │55 - errdefer allocator.free(draft_path); │ │58 + const path = try forkPath(allocator, repo_root_path, &input.id); │ │59 + errdefer allocator.free(path); │ │60 │ │57 - var created_repo = false; │ │58 - errdefer if (created_repo) std.Io.Dir.cwd().deleteTree(io, draft_path) catch {}; │ │59 - │ │61 var arena = std.heap.ArenaAllocator.init(allocator); │ │62 defer arena.deinit(); │ │63 const existing = if (evt.currentMoment(evt.admin_repo_opts, admin_repo)) |moment|│ ╰─────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────╮ │67 else => |other| return other, │ │68 }; │ │69 if (existing) |record| { │ │69 - if (!std.mem.eql(u8, record.event.user_id, &input.user_id) or │ │70 + if (record.removed or │ │71 + !std.mem.eql(u8, record.event.user_id, &input.user_id) or │ │72 !std.mem.eql(u8, record.event.repo_id, &input.repo_id)) return error.InvalidPatchDraft;│ │73 } │ │74 │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯