Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

31 linesCodeBlameRaw
1import { redirect } from "react-router";
2
3import type { RepoPath, Viewer } from "@g1t/contracts";
4
5import { renamedBranchPath } from "./repo-lifecycle";
6import { repos } from "./services.server";
7
8/**
9 * A renamed branch keeps its old name as a redirect. Call this where a
10 * tree or blob page is about to 404 on `ref`: if the branch was renamed
11 * away from it, it throws a 301 to the same page on the new name.
12 * Otherwise it returns, and the caller 404s as before. Only the not-found
13 * path pays for the lookup.
14 */
15export async function redirectIfBranchRenamed(request: Request, path: RepoPath, viewer: Viewer, ref: string): Promise<void> {
16 let to: string | null = null;
17 try {
18 const repo = await repos.get(path, viewer);
19 if (!repo.ok) return;
20 // `HEAD` is the default branch, as git means it (Go's go-source links use it).
21 const now = ref === "HEAD" ? repo.value.defaultBranch : await repos.resolveBranch(repo.value.id, ref);
22 if (!now || now === ref) return;
23 const url = new URL(request.url);
24 to = renamedBranchPath(url.pathname, url.search, now);
25 } catch {
26 // A lookup that fails leaves the page a 404, never a 500.
27 return;
28 }
29 // A rename is for good; what HEAD names can change.
30 if (to) throw redirect(to, ref === "HEAD" ? 302 : 301);
31}