mirror of
https://seed.radicle.dev/rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5.git
synced 2026-11-01 09:40:28 +08:00
Extract tree and history route loading
The `loadProjectRoute` function has become too big too understand. To address this, we extract and separate the loading for the `tree` and `history` views. This also gives us the opportunity to simplify some of the code and parallelize more HTTP requests. Signed-off-by: Thomas Scholtes <geigerzaehler@axiom.fm>
This commit is contained in:
+188
-142
@@ -19,22 +19,8 @@ import { seedPath } from "@app/views/seeds/router";
|
||||
export const COMMITS_PER_PAGE = 30;
|
||||
|
||||
export type ProjectRoute =
|
||||
| {
|
||||
resource: "project.tree";
|
||||
seed: BaseUrl;
|
||||
project: string;
|
||||
path?: string;
|
||||
peer?: string;
|
||||
revision?: string;
|
||||
route?: string;
|
||||
}
|
||||
| {
|
||||
resource: "project.history";
|
||||
seed: BaseUrl;
|
||||
project: string;
|
||||
peer?: string;
|
||||
revision?: string;
|
||||
}
|
||||
| ProjectTreeRoute
|
||||
| ProjectHistoryRoute
|
||||
| {
|
||||
resource: "project.commit";
|
||||
seed: BaseUrl;
|
||||
@@ -69,6 +55,24 @@ export type ProjectRoute =
|
||||
search?: string;
|
||||
};
|
||||
|
||||
interface ProjectTreeRoute {
|
||||
resource: "project.tree";
|
||||
seed: BaseUrl;
|
||||
project: string;
|
||||
path?: string;
|
||||
peer?: string;
|
||||
revision?: string;
|
||||
route?: string;
|
||||
}
|
||||
|
||||
interface ProjectHistoryRoute {
|
||||
resource: "project.history";
|
||||
seed: BaseUrl;
|
||||
project: string;
|
||||
peer?: string;
|
||||
revision?: string;
|
||||
}
|
||||
|
||||
export interface ProjectLoadedRoute {
|
||||
resource: "projects";
|
||||
params: ProjectLoadedParams;
|
||||
@@ -80,7 +84,6 @@ export interface ProjectLoadedParams {
|
||||
project: Project;
|
||||
view: ProjectLoadedView;
|
||||
}
|
||||
|
||||
export type LoadedSourceBrowsingView =
|
||||
| {
|
||||
resource: "tree";
|
||||
@@ -132,7 +135,7 @@ function isOid(input: string): boolean {
|
||||
return /^[a-fA-F0-9]{40}$/.test(input);
|
||||
}
|
||||
|
||||
export function parseRevisionToOid(
|
||||
function parseRevisionToOid(
|
||||
revision: string | undefined,
|
||||
defaultBranch: string,
|
||||
branches: Record<string, string>,
|
||||
@@ -158,130 +161,10 @@ export async function loadProjectRoute(
|
||||
): Promise<ProjectLoadedRoute | LoadError> {
|
||||
const api = new HttpdClient(route.seed);
|
||||
try {
|
||||
if (
|
||||
route.resource === "project.tree" ||
|
||||
route.resource === "project.history"
|
||||
) {
|
||||
const projectPromise = api.project.getById(route.project);
|
||||
const peersPromise = api.project.getAllRemotes(route.project);
|
||||
const branchesPromise = (async () => {
|
||||
if (route.peer) {
|
||||
return (await api.project.getRemoteByPeer(route.project, route.peer))
|
||||
.heads;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
})();
|
||||
|
||||
const [project, peers, branches] = await Promise.all([
|
||||
projectPromise,
|
||||
peersPromise,
|
||||
branchesPromise,
|
||||
]);
|
||||
|
||||
if (route.resource === "project.tree" && route.route) {
|
||||
const { revision, path } = detectRevision(
|
||||
route.route,
|
||||
branches || { [project.defaultBranch]: project.head },
|
||||
);
|
||||
route.revision = revision;
|
||||
route.path = path;
|
||||
}
|
||||
|
||||
const commit = parseRevisionToOid(
|
||||
route.revision,
|
||||
project.defaultBranch,
|
||||
branches || { [project.defaultBranch]: project.head },
|
||||
);
|
||||
const tree = await api.project.getTree(route.project, commit);
|
||||
const viewParams = {
|
||||
loadedBranches: branches,
|
||||
loadedPeers: peers,
|
||||
loadedTree: tree,
|
||||
};
|
||||
if (route.resource === "project.tree") {
|
||||
let blobResult: BlobResult;
|
||||
|
||||
const path = route.path || "/";
|
||||
try {
|
||||
let blob: Blob;
|
||||
if (path === "/") {
|
||||
blob = await api.project.getReadme(project.id, commit);
|
||||
} else {
|
||||
blob = await api.project.getBlob(project.id, commit, path);
|
||||
}
|
||||
blobResult = {
|
||||
ok: true,
|
||||
blob,
|
||||
highlighted: blob.content
|
||||
? await Syntax.highlight(
|
||||
blob.content,
|
||||
blob.path.split(".").pop() ?? "",
|
||||
)
|
||||
: undefined,
|
||||
};
|
||||
} catch {
|
||||
if (path === "/") {
|
||||
blobResult = {
|
||||
ok: false,
|
||||
error: {
|
||||
message: "The README could not be loaded",
|
||||
path,
|
||||
},
|
||||
};
|
||||
} else {
|
||||
blobResult = {
|
||||
ok: false,
|
||||
error: {
|
||||
message: "Not able to load file",
|
||||
path,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
resource: "projects",
|
||||
params: {
|
||||
id: route.project,
|
||||
baseUrl: route.seed,
|
||||
project,
|
||||
view: {
|
||||
resource: "tree",
|
||||
peer: route.peer,
|
||||
revision: route.revision,
|
||||
params: viewParams,
|
||||
path,
|
||||
blobResult,
|
||||
},
|
||||
},
|
||||
};
|
||||
} else if (route.resource === "project.history") {
|
||||
const commitsResponse = await api.project.getAllCommits(project.id, {
|
||||
parent: commit,
|
||||
page: 0,
|
||||
perPage: COMMITS_PER_PAGE,
|
||||
});
|
||||
|
||||
return {
|
||||
resource: "projects",
|
||||
params: {
|
||||
id: route.project,
|
||||
baseUrl: route.seed,
|
||||
project,
|
||||
view: {
|
||||
resource: "history",
|
||||
peer: route.peer,
|
||||
revision: route.revision,
|
||||
params: viewParams,
|
||||
commitHeaders: commitsResponse.commits.map(c => c.commit),
|
||||
totalCommitCount: commitsResponse.stats.commits,
|
||||
},
|
||||
},
|
||||
};
|
||||
} else {
|
||||
return unreachable(route);
|
||||
}
|
||||
if (route.resource === "project.tree") {
|
||||
return loadTreeView(route);
|
||||
} else if (route.resource === "project.history") {
|
||||
return loadHistoryView(route);
|
||||
} else if (route.resource === "project.commit") {
|
||||
const projectPromise = api.project.getById(route.project);
|
||||
const peersPromise = api.project.getAllRemotes(route.project);
|
||||
@@ -439,6 +322,169 @@ export async function loadProjectRoute(
|
||||
}
|
||||
}
|
||||
|
||||
async function loadTreeView(
|
||||
route: ProjectTreeRoute,
|
||||
): Promise<ProjectLoadedRoute> {
|
||||
const api = new HttpdClient(route.seed);
|
||||
|
||||
const [project, peers, branches] = await Promise.all([
|
||||
api.project.getById(route.project),
|
||||
api.project.getAllRemotes(route.project),
|
||||
getPeerBranches(api, route.project, route.peer),
|
||||
]);
|
||||
|
||||
if (route.route) {
|
||||
const { revision, path } = detectRevision(
|
||||
route.route,
|
||||
branches || { [project.defaultBranch]: project.head },
|
||||
);
|
||||
route.revision = revision;
|
||||
route.path = path;
|
||||
}
|
||||
|
||||
const commit = parseRevisionToOid(
|
||||
route.revision,
|
||||
project.defaultBranch,
|
||||
branches || { [project.defaultBranch]: project.head },
|
||||
);
|
||||
|
||||
const path = route.path || "/";
|
||||
|
||||
const [tree, blobResult] = await Promise.all([
|
||||
api.project.getTree(route.project, commit),
|
||||
loadBlob(api, project.id, commit, path),
|
||||
]);
|
||||
return {
|
||||
resource: "projects",
|
||||
params: {
|
||||
id: route.project,
|
||||
baseUrl: route.seed,
|
||||
project,
|
||||
view: {
|
||||
resource: "tree",
|
||||
peer: route.peer,
|
||||
revision: route.revision,
|
||||
params: {
|
||||
loadedBranches: branches,
|
||||
loadedPeers: peers,
|
||||
loadedTree: tree,
|
||||
},
|
||||
path,
|
||||
blobResult,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async function loadBlob(
|
||||
api: HttpdClient,
|
||||
project: string,
|
||||
commit: string,
|
||||
path: string,
|
||||
): Promise<BlobResult> {
|
||||
try {
|
||||
let blob: Blob;
|
||||
if (path === "" || path === "/") {
|
||||
blob = await api.project.getReadme(project, commit);
|
||||
} else {
|
||||
blob = await api.project.getBlob(project, commit, path);
|
||||
}
|
||||
return {
|
||||
ok: true,
|
||||
blob,
|
||||
highlighted: blob.content
|
||||
? await Syntax.highlight(blob.content, blob.path.split(".").pop() ?? "")
|
||||
: undefined,
|
||||
};
|
||||
} catch {
|
||||
if (path === "/") {
|
||||
return {
|
||||
ok: false,
|
||||
error: {
|
||||
message: "The README could not be loaded",
|
||||
path,
|
||||
},
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
ok: false,
|
||||
error: {
|
||||
message: "Not able to load file",
|
||||
path,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
async function loadHistoryView(
|
||||
route: ProjectHistoryRoute,
|
||||
): Promise<ProjectLoadedRoute> {
|
||||
const api = new HttpdClient(route.seed);
|
||||
|
||||
const [project, peers, branches] = await Promise.all([
|
||||
api.project.getById(route.project),
|
||||
api.project.getAllRemotes(route.project),
|
||||
getPeerBranches(api, route.project, route.peer),
|
||||
]);
|
||||
|
||||
let commitId;
|
||||
if (route.revision && isOid(route.revision)) {
|
||||
commitId = route.revision;
|
||||
} else if (branches) {
|
||||
commitId = branches[route.revision || project.defaultBranch];
|
||||
} else if (!route.revision) {
|
||||
commitId = project.head;
|
||||
}
|
||||
|
||||
if (!commitId) {
|
||||
throw new Error(
|
||||
`Revision ${route.revision} not found for project ${project.id}`,
|
||||
);
|
||||
}
|
||||
|
||||
const [tree, commitsResponse] = await Promise.all([
|
||||
api.project.getTree(route.project, commitId),
|
||||
await api.project.getAllCommits(project.id, {
|
||||
parent: commitId,
|
||||
page: 0,
|
||||
perPage: COMMITS_PER_PAGE,
|
||||
}),
|
||||
]);
|
||||
|
||||
return {
|
||||
resource: "projects",
|
||||
params: {
|
||||
id: route.project,
|
||||
baseUrl: route.seed,
|
||||
project,
|
||||
view: {
|
||||
resource: "history",
|
||||
peer: route.peer,
|
||||
revision: route.revision,
|
||||
params: {
|
||||
loadedBranches: branches,
|
||||
loadedPeers: peers,
|
||||
loadedTree: tree,
|
||||
},
|
||||
commitHeaders: commitsResponse.commits.map(c => c.commit),
|
||||
totalCommitCount: commitsResponse.stats.commits,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async function getPeerBranches(
|
||||
api: HttpdClient,
|
||||
project: string,
|
||||
peer?: string,
|
||||
) {
|
||||
if (peer) {
|
||||
return (await api.project.getRemoteByPeer(project, peer)).heads;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// Detects branch names and commit IDs at the start of `input` and extract it.
|
||||
function detectRevision(
|
||||
input: string,
|
||||
|
||||
Reference in New Issue
Block a user