╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ──╮ │src/web.zig│ ╰───────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1335 base: []const u8, │ │1336 host: Host, │ │1337 ) !void { │ │1327 - const parts = commentBaseParts(base) orelse return respondRemoveNotFound(request); │ │1338 + const parts = commentBaseParts(host, base) orelse return respondRemoveNotFound(request); │ │1339 if (parts.comment_id != null) return handleCommentEdit(io, request, allocator, base, host, parts);│ │1340 return handleThreadEdit(io, request, allocator, base, host, parts); │ │1341 } │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────╮ │1428 }; │ │1429 │ │1430 // split a remove url into the repo and event it names │ │1420 -fn removeParts(base: []const u8) ?RemoveParts { │ │1431 +fn removeParts(host: Host, base: []const u8) ?RemoveParts { │ │1432 if (attachmentRequest(base)) |attachment| { │ │1433 const parent = attachParentParts(attachment.repo_base) orelse return null;│ │1434 return .{ │ ╰────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────╮ │1437 .id = attachment.id, │ │1438 }; │ │1439 } │ │1429 - if (commentBaseParts(base)) |thread| return .{ │ │1440 + if (commentBaseParts(host, base)) |thread| return .{ │ │1441 .repo_base = thread.repo_base, │ │1442 .kind = if (thread.comment_id != null) .comment else thread.thread_kind,│ │1443 .id = thread.comment_id orelse thread.thread_id, │ ╰──────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────╮ │1453 base: []const u8, │ │1454 host: Host, │ │1455 ) !void { │ │1445 - const parts = removeParts(base) orelse return respondRemoveNotFound(request); │ │1456 + const parts = removeParts(host, base) orelse return respondRemoveNotFound(request);│ │1457 │ │1458 var author_arena = std.heap.ArenaAllocator.init(allocator); │ │1459 defer author_arena.deinit(); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────╮ │1548 } │ │1549 │ │1550 // set the status of the issue the url names (base is │ │1540 -// "/repo/<owner>/<name>/issue:<id>", identity elided in local mode) by│ │1551 +// "/<owner>:<name>/issue:<id>", identity elided in local mode) by │ │1552 // re-emitting its event, then redirect back to it │ │1553 fn handleThreadStatus( │ │1554 io: std.Io, │ ╰─────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────╮ │1559 open: bool, │ │1560 ) !void { │ │1561 const not_found = "thread not found"; │ │1551 - const parts = commentBaseParts(base) orelse { │ │1562 + const parts = commentBaseParts(host, base) orelse { │ │1563 try request.respond(not_found, .{ │ │1564 .status = .not_found, │ │1565 .extra_headers = &.{.{ .name = "content-type", .value = "text/plain" }},│ ╰──────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────╮ │1742 base: []const u8, │ │1743 host: Host, │ │1744 ) !void { │ │1734 - const parts = commentBaseParts(base) orelse { │ │1745 + const parts = commentBaseParts(host, base) orelse { │ │1746 try request.respond("thread not found", .{ │ │1747 .status = .not_found, │ │1748 .extra_headers = &.{.{ .name = "content-type", .value = "text/plain" }},│ ╰──────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1780 }); │ │1781 return; │ │1782 } │ │1772 - const route = ui.RoutablePage.fromUrl(base) orelse ui.RoutablePage.fromUrlLocal(base) orelse {│ │1783 + const route = routeFromUrl(host, base) orelse { │ │1784 try request.respond("thread not found", .{ │ │1785 .status = .not_found, │ │1786 .extra_headers = &.{.{ .name = "content-type", .value = "text/plain" }}, │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1837 // the posted path drops the action's own segment, so the route it parses is │ │1838 // the undo page the action applies to, never the confirmation page itself │ │1839 fn handleUndo(io: std.Io, request: *std.http.Server.Request, allocator: std.mem.Allocator, base: []const u8, host: Host, action: enum { undo, clear }) !void {│ │1829 - const route = (switch (host) { │ │1830 - .local => ui.RoutablePage.fromUrlLocal(base), │ │1831 - .server => ui.RoutablePage.fromUrl(base), │ │1832 - }) orelse return respondRepoNotFound(request); │ │1840 + const route = routeFromUrl(host, base) orelse return respondRepoNotFound(request); │ │1841 if (route != .repo_undo) return respondRepoNotFound(request); │ │1842 const target = route.repo_undo; │ │1843 var arena = std.heap.ArenaAllocator.init(allocator); │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1844 defer arena.deinit(); │ │1837 - const repo_base = if (target.name.len == 0) "" else try std.fmt.allocPrint(arena.allocator(), "/repo/{s}", .{target.name.slice()});│ │1845 + const repo_base = if (target.name.len == 0) "" else try std.fmt.allocPrint(arena.allocator(), "/{s}", .{target.name.slice()}); │ │1846 _ = (try authorizeWrite(io, allocator, &arena, request, host, repo_base, .owner)) orelse return; │ │1847 const resolved = (try requestRepoSource(io, allocator, host, repo_base)) orelse return respondRepoNotFound(request); │ │1848 defer resolved.deinit(allocator); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯