╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ───╮ │src/fork.zig│ ╰────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │274 const base_oid = try mrg.commonAncestor(.xit, repo_opts, state.readOnly(), ctx.io, ctx.allocator, &ctx.target_oid, &source_oid);│ │275 const existing_revision = if (ctx.newest) |latest| │ │276 if (std.mem.eql(u8, latest.record.event.base_oid, &base_oid) and │ │279 - std.mem.eql(u8, latest.record.event.source_oid, &source_oid) and │ │280 - std.mem.eql(u8, latest.record.event.target_ref, ctx.target_ref)) latest else null │ │277 + std.mem.eql(u8, latest.record.event.source_oid, &source_oid)) latest else null │ │278 else │ │279 null; │ │280 │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │300 const revision_event: evt.PatchRev = .{ │ │301 .base_oid = &base_oid, │ │302 .source_oid = &source_oid, │ │306 - .target_ref = ctx.target_ref, │ │303 .message = ctx.title, │ │304 }; │ │305 const identity = try std.fmt.allocPrint(ctx.allocator, "{s} <{s}>", .{ ctx.author.name, ctx.author.email });│ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────╮ │336 .id = revision_hex, │ │337 .squash_oid = &patch_oid, │ │338 .source_oid = &source_oid, │ │343 - .target_ref = ctx.target_ref,│ │339 }; │ │340 events[event_count] = .{ │ │341 .id = ctx.patch_id, │ ╰──────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────╮ │382 .patch = fork_patch, │ │383 .published = published, │ │384 .target_oid = target_oid,│ │390 - .target_ref = target_ref,│ │385 .title = title, │ │386 .author = author, │ │387 .timestamp = timestamp, │ ╰──────────────────────────────────────────╯ ╭ changed ────╮ │src/patch.zig│ ╰─────────────╯ ╭──────────────────────────────────╮ │24 title: []const u8, │ │25 tags: []const u8, │ │26 description: []const u8, │ │27 + target_branch: []const u8,│ │28 author: evt.CommitAuthor, │ │29 timestamp: u64, │ │30 }; │ ╰──────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────╮ │150 patch.title = input.title; │ │151 patch.tags = input.tags; │ │152 patch.description = input.description; │ │153 + if (!std.mem.eql(u8, patch.target_branch, input.target_branch)) patch.revision = null; │ │154 + patch.target_branch = input.target_branch; │ │155 try evt.consume(.fork, .xit, repo_opts, io, allocator, &fork_repo, evt.events_ref, &.{.{│ │156 .id = input.id, │ │157 .timestamp = input.timestamp, │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │185 } │ │186 const selected = patch_record.event.revision orelse return error.PatchNotPushed; │ │187 const revision_id = try evt.parseEventId(&selected.id); │ │185 - const target_ref = rf.Ref.initFromPath(selected.target_ref, null) orelse return error.InvalidPatch;│ │186 - switch (target_ref.kind) { │ │187 - .head => {}, │ │188 - else => return error.InvalidPatch, │ │189 - } │ │188 + const target_ref = rf.Ref{ .kind = .head, .name = patch_record.event.target_branch }; │ │189 │ │190 // open and lock the fork │ │191 const fork_path = try fork.forkPath(arena.allocator(), repo_root_path, &input.id); │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────╮ │438 const revisions = try DB.HashMap(.read_only).init(revisions_cursor); │ │439 var events_ref_buffer: [rf.MAX_REF_CONTENT_SIZE]u8 = undefined; │ │440 const events_ref_path = try evt.events_ref.toPath(&events_ref_buffer);│ │441 + const heads_prefix = "refs/heads/"; │ │442 for (updates) |update| { │ │443 - if (!std.mem.startsWith(u8, update.ref_name, "refs/heads/") or │ │443 + if (!std.mem.startsWith(u8, update.ref_name, heads_prefix) or │ │444 std.mem.eql(u8, update.ref_name, events_ref_path) or │ │445 std.mem.eql(u8, update.old_oid, update.new_oid)) continue; │ │446 if (update.old_oid.len != hash.hexLen(repo_opts.hash) or │ ╰───────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │458 var revision_key_buffer: [rf.MAX_REF_CONTENT_SIZE + 1 + hash.hexLen(repo_opts.hash)]u8 = undefined; │ │459 while (try commits.next(arena.allocator())) |commit| { │ │460 defer commit.deinit(); │ │461 - const key = try std.fmt.bufPrint(&revision_key_buffer, "{s}\x00{s}", .{ update.ref_name, &commit.oid }); │ │461 + const key = try std.fmt.bufPrint(&revision_key_buffer, "{s}\x00{s}", .{ update.ref_name[heads_prefix.len..], &commit.oid });│ │462 const ids_cursor = try revisions.getCursor(hash.hashInt(repo_opts.hash, key)) orelse continue; │ │463 const ids = try DB.CountedHashSet(.read_only).init(ids_cursor); │ │464 var ids_iter = try ids.iterator(); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ────────╮ │src/serve_ssh.zig│ ╰─────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │323 if (std.mem.startsWith(u8, path, fork_prefix)) { │ │324 const route = fork.parseRoute(path[fork_prefix.len..]) orelse return writeError(sess, "invalid fork path"); │ │325 const owner_repo = evt.parseOwnerRepoPath(route.identity) orelse return writeError(sess, "repo path must be <owner>/<repo>"); │ │326 - if (parsed.service == .receive_pack and !xit.ref.validateName(route.target)) return writeError(sess, "invalid target branch");│ │326 │ │327 var admin = try rp.Repo(.xit, evt.admin_repo_opts).open(io, allocator, .{ .path = handler.admin_repo_path }); │ │328 defer admin.deinit(io, allocator); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯