Something went wrong. Try again.
Monorepo for Tangled tangled.org
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106// the pull page's url grammar, where <aturi> goes in raw and `reroute` in// src/hooks.ts folds its segments back together before routing://// /pulls/<aturi>/latest diff of the newest version// /pulls/<aturi>/1 diff of version 1// /pulls/<aturi>/1/c1..c2 that diff narrowed to a commit range// /pulls/<aturi>/0..1 interdiff between two versions// /pulls/<aturi>/0..1/<change-id> that interdiff narrowed to one change
export interface Revspec { base: string; head: string;}
// parses `<base>..<head>`, where either side may be missingexport const parseRange = (input: string): Revspec | null => { const spec = input.trim(); if (spec === "") return { base: "", head: "" }; // `...` is a symmetric difference in git, and two ranges are not a range if (spec.includes("...") || spec.split("..").length > 2) return null; if (!spec.includes("..")) return { base: "", head: spec };
const [base, head] = spec.split("..", 2).map((part) => part.trim()); if (base === "" && head === "") return null; return { base, head };};
export interface PullDiffView { mode: "diff"; version: number; base: string; head: string;}
export interface PullInterdiffView { mode: "interdiff"; oldVersion: number; version: number; from: Revspec; // oldVersion {base, head} to: Revspec; // version {base, head} // "" means all changes changeId: string;}
export type PullView = PullDiffView | PullInterdiffView;
// a bad version sends you to the newest one, a bad range only drops itselfexport type PullRouteRedirect = { redirect: "latest" | "version" };
export const isRedirect = <T extends object>( result: T | PullRouteRedirect): result is PullRouteRedirect => "redirect" in result;
const index = (raw: string, count: number): number | null => { if (!/^\d+$/.test(raw)) return null; const value = Number(raw); return value < count ? value : null;};
// `/<v1>..<v2>[/<change-id>]`export const parseInterdiffRoute = ( versions: readonly Revspec[], versionParam: string, rangeParam?: string): PullInterdiffView | PullRouteRedirect => { const range = parseRange(versionParam); if (!range) return { redirect: "latest" }; const version1 = index(range.base, versions.length); const version2 = index(range.head, versions.length); if (version1 === null || version2 === null) return { redirect: "latest" }; const changeId = rangeParam === "all" ? "" : (rangeParam ?? ""); return { mode: "interdiff", oldVersion: version1, version: version2, from: versions[version1], to: versions[version2], changeId };};
// `/<version>[/<base>..<head>]`export const parseDiffRoute = ( versions: readonly Revspec[], versionParam: string, rangeParam?: string): PullDiffView | PullRouteRedirect => { const version = versionParam === "latest" ? Math.max(versions.length - 1, 0) : index(versionParam, versions.length); if (version === null) return { redirect: "latest" };
const spec = parseRange(rangeParam ?? ""); if (!spec) return { redirect: "version" };
const isDiffBase = spec.base === "" || spec.base === "base"; const isDiffHead = spec.head === "" || spec.head === "head"; return { mode: "diff", version, base: isDiffBase ? (versions[version]?.base ?? "") : spec.base, head: isDiffHead ? (versions[version]?.head ?? "") : spec.head };};