mirror of
https://github.com/nicotsx/ironmount.git
synced 2025-12-10 12:10:51 +01:00
feat: remove individual snapshot (#26)
This commit is contained in:
@@ -4,6 +4,7 @@ import {
|
||||
createRepositoryBody,
|
||||
createRepositoryDto,
|
||||
deleteRepositoryDto,
|
||||
deleteSnapshotDto,
|
||||
doctorRepositoryDto,
|
||||
getRepositoryDto,
|
||||
getSnapshotDetailsDto,
|
||||
@@ -16,6 +17,7 @@ import {
|
||||
restoreSnapshotBody,
|
||||
restoreSnapshotDto,
|
||||
type DeleteRepositoryDto,
|
||||
type DeleteSnapshotDto,
|
||||
type DoctorRepositoryDto,
|
||||
type GetRepositoryDto,
|
||||
type GetSnapshotDetailsDto,
|
||||
@@ -142,4 +144,11 @@ export const repositoriesController = new Hono()
|
||||
const result = await repositoriesService.doctorRepository(name);
|
||||
|
||||
return c.json<DoctorRepositoryDto>(result, 200);
|
||||
})
|
||||
.delete("/:name/snapshots/:snapshotId", deleteSnapshotDto, async (c) => {
|
||||
const { name, snapshotId } = c.req.param();
|
||||
|
||||
await repositoriesService.deleteSnapshot(name, snapshotId);
|
||||
|
||||
return c.json<DeleteSnapshotDto>({ message: "Snapshot deleted" }, 200);
|
||||
});
|
||||
|
||||
@@ -326,3 +326,28 @@ export const listRcloneRemotesDto = describeRoute({
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Delete a snapshot
|
||||
*/
|
||||
export const deleteSnapshotResponse = type({
|
||||
message: "string",
|
||||
});
|
||||
|
||||
export type DeleteSnapshotDto = typeof deleteSnapshotResponse.infer;
|
||||
|
||||
export const deleteSnapshotDto = describeRoute({
|
||||
description: "Delete a specific snapshot from a repository",
|
||||
tags: ["Repositories"],
|
||||
operationId: "deleteSnapshot",
|
||||
responses: {
|
||||
200: {
|
||||
description: "Snapshot deleted successfully",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: resolver(deleteSnapshotResponse),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -327,6 +327,18 @@ const doctorRepository = async (name: string) => {
|
||||
};
|
||||
};
|
||||
|
||||
const deleteSnapshot = async (name: string, snapshotId: string) => {
|
||||
const repository = await db.query.repositoriesTable.findFirst({
|
||||
where: eq(repositoriesTable.name, name),
|
||||
});
|
||||
|
||||
if (!repository) {
|
||||
throw new NotFoundError("Repository not found");
|
||||
}
|
||||
|
||||
await restic.deleteSnapshot(repository.config, snapshotId);
|
||||
};
|
||||
|
||||
export const repositoriesService = {
|
||||
listRepositories,
|
||||
createRepository,
|
||||
@@ -338,4 +350,5 @@ export const repositoriesService = {
|
||||
getSnapshotDetails,
|
||||
checkHealth,
|
||||
doctorRepository,
|
||||
deleteSnapshot,
|
||||
};
|
||||
|
||||
@@ -441,6 +441,22 @@ const forget = async (config: RepositoryConfig, options: RetentionPolicy, extra:
|
||||
return { success: true };
|
||||
};
|
||||
|
||||
const deleteSnapshot = async (config: RepositoryConfig, snapshotId: string) => {
|
||||
const repoUrl = buildRepoUrl(config);
|
||||
const env = await buildEnv(config);
|
||||
|
||||
const args: string[] = ["--repo", repoUrl, "forget", snapshotId, "--prune"];
|
||||
|
||||
const res = await $`restic ${args}`.env(env).nothrow();
|
||||
|
||||
if (res.exitCode !== 0) {
|
||||
logger.error(`Restic snapshot deletion failed: ${res.stderr}`);
|
||||
throw new Error(`Failed to delete snapshot: ${res.stderr}`);
|
||||
}
|
||||
|
||||
return { success: true };
|
||||
};
|
||||
|
||||
const lsNodeSchema = type({
|
||||
name: "string",
|
||||
type: "string",
|
||||
@@ -601,6 +617,7 @@ export const restic = {
|
||||
restore,
|
||||
snapshots,
|
||||
forget,
|
||||
deleteSnapshot,
|
||||
unlock,
|
||||
ls,
|
||||
check,
|
||||
|
||||
Reference in New Issue
Block a user