zerobyte/packages/core/src/restic/commands/check.ts

90 lines
2.1 KiB
TypeScript

import { Data, Effect } from "effect";
import { logger, safeExec } from "../../node";
import { addCommonArgs } from "../helpers/add-common-args";
import { buildEnv } from "../helpers/build-env";
import { buildRepoUrl } from "../helpers/build-repo-url";
import { cleanupTemporaryKeys } from "../helpers/cleanup-temporary-keys";
import type { RepositoryConfig } from "../schemas";
import type { ResticDeps } from "../types";
import { isResticError } from "../error";
import { toMessage } from "../../utils";
class ResticCheckCommandError extends Data.TaggedError("ResticCheckCommandError")<{
cause: unknown;
message: string;
}> {}
export const check = (
config: RepositoryConfig,
options: {
readData?: boolean;
signal?: AbortSignal;
organizationId: string;
},
deps: ResticDeps,
) => {
return Effect.tryPromise({
try: async () => {
const repoUrl = buildRepoUrl(config);
const env = await buildEnv(config, options.organizationId, deps);
const args: string[] = ["--repo", repoUrl, "check"];
if (options.readData) {
args.push("--read-data");
}
addCommonArgs(args, env, config);
const res = await safeExec({
command: "restic",
args,
env,
signal: options.signal,
});
await cleanupTemporaryKeys(env, deps);
if (options.signal?.aborted) {
logger.warn("Restic check was aborted by signal.");
return {
success: false,
hasErrors: true,
output: "",
error: "Operation aborted",
};
}
const { stdout, stderr } = res;
if (res.exitCode !== 0) {
logger.error(`Restic check failed: ${stderr}`);
return {
success: false,
hasErrors: true,
output: stdout,
error: stderr,
};
}
const hasErrors = stdout.includes("Fatal");
logger.info(`Restic check completed for repository: ${repoUrl}`);
return {
success: !hasErrors,
hasErrors,
output: stdout,
error: hasErrors ? "Repository contains errors" : null,
};
},
catch: (error) => {
if (isResticError(error)) {
return error;
}
return new ResticCheckCommandError({
cause: error,
message: toMessage(error),
});
},
});
};