Files
radicle-explorer/httpd-client/lib/project/commit.ts
T
Sebastian Martinez bd6ba784b3 Improve binary detection
libgit2 optimizes around not loading the content, when there's no
content callbacks configured.

So we aren't able to get a clear answer from radicle-surf if a file in a
diff is a binary or not.

A simple way without doing additional API requests is to check if the
file type is a executable and if there are no hunks (since we don't get
any deltas in binaries), this is a strong
indicator for a binary.

Signed-off-by: Sebastian Martinez <me@sebastinez.dev>
2023-09-26 09:04:01 +02:00

161 lines
3.5 KiB
TypeScript

import type { z } from "zod";
export type {
Commits,
HunkLine,
Hunks,
Commit,
Diff,
CommitHeader,
DiffFile,
DiffContent,
};
import { array, literal, number, object, optional, string, union } from "zod";
export { commitHeaderSchema, diffSchema, commitSchema, commitsSchema };
const gitPersonSchema = object({
name: string(),
email: string(),
});
type CommitHeader = z.infer<typeof commitHeaderSchema>;
const commitHeaderSchema = object({
id: string(),
author: gitPersonSchema,
summary: string(),
description: string(),
parents: array(string()),
committer: gitPersonSchema.merge(object({ time: number() })),
});
type AdditionHunkLine = z.infer<typeof additionHunkLineSchema>;
const additionHunkLineSchema = object({
line: string(),
lineNo: number(),
type: literal("addition"),
});
type DeletionHunkLine = z.infer<typeof deletionHunkLineSchema>;
const deletionHunkLineSchema = object({
line: string(),
lineNo: number(),
type: literal("deletion"),
});
type DiffFile = z.infer<typeof diffFileSchema>;
const diffFileSchema = object({
oid: string(),
mode: union([
literal("blob"),
literal("blobExecutable"),
literal("tree"),
literal("link"),
literal("commit"),
]),
});
type ContextHunkLine = z.infer<typeof contextHunkLineSchema>;
const contextHunkLineSchema = object({
line: string(),
lineNoNew: number(),
lineNoOld: number(),
type: literal("context"),
});
type HunkLine = AdditionHunkLine | DeletionHunkLine | ContextHunkLine;
const hunkLineSchema = union([
additionHunkLineSchema,
deletionHunkLineSchema,
contextHunkLineSchema,
]);
type Hunks = z.infer<typeof changesetHunkSchema>;
const changesetHunkSchema = object({
header: string(),
lines: array(hunkLineSchema),
});
type DiffContent = z.infer<typeof diffContentSchema>;
const diffContentSchema = object({
type: union([literal("plain"), literal("binary"), literal("empty")]),
hunks: array(changesetHunkSchema),
eof: union([
literal("noneMissing"),
literal("oldMissing"),
literal("newMissing"),
literal("bothMissing"),
]),
});
const diffChangesetSchema = object({
path: string(),
diff: diffContentSchema,
});
const diffAddedChangesetSchema = diffChangesetSchema.merge(
object({ new: diffFileSchema }),
);
const diffDeletedChangesetSchema = diffChangesetSchema.merge(
object({ old: diffFileSchema }),
);
const diffModifiedChangesetSchema = diffChangesetSchema.merge(
object({ new: diffFileSchema, old: diffFileSchema }),
);
const diffCopiedChangesetSchema = object({
newPath: string(),
oldPath: string(),
});
const diffMovedChangesetSchema = diffCopiedChangesetSchema.merge(
object({
old: optional(diffFileSchema),
new: optional(diffFileSchema),
diff: optional(diffContentSchema),
}),
);
type Diff = z.infer<typeof diffSchema>;
const diffSchema = object({
added: array(diffAddedChangesetSchema),
deleted: array(diffDeletedChangesetSchema),
modified: array(diffModifiedChangesetSchema),
moved: array(diffMovedChangesetSchema),
copied: array(diffCopiedChangesetSchema),
stats: object({
filesChanged: number(),
insertions: number(),
deletions: number(),
}),
});
type Commit = z.infer<typeof commitSchema>;
const commitSchema = object({
commit: commitHeaderSchema,
diff: diffSchema,
branches: array(string()),
});
type Commits = z.infer<typeof commitsSchema>;
const commitsSchema = object({
commits: array(commitSchema),
stats: object({
commits: number(),
branches: number(),
contributors: number(),
}),
});