diff options
-rwxr-xr-x | scripts/prune-storage.ts | 37 | ||||
-rw-r--r-- | server/models/redundancy/video-redundancy.ts | 32 |
2 files changed, 60 insertions, 9 deletions
diff --git a/scripts/prune-storage.ts b/scripts/prune-storage.ts index b00f20934..4088fa700 100755 --- a/scripts/prune-storage.ts +++ b/scripts/prune-storage.ts | |||
@@ -4,6 +4,7 @@ import { CONFIG } from '../server/initializers/constants' | |||
4 | import { VideoModel } from '../server/models/video/video' | 4 | import { VideoModel } from '../server/models/video/video' |
5 | import { initDatabaseModels } from '../server/initializers' | 5 | import { initDatabaseModels } from '../server/initializers' |
6 | import { remove, readdir } from 'fs-extra' | 6 | import { remove, readdir } from 'fs-extra' |
7 | import { VideoRedundancyModel } from '../server/models/redundancy/video-redundancy' | ||
7 | 8 | ||
8 | run() | 9 | run() |
9 | .then(() => process.exit(0)) | 10 | .then(() => process.exit(0)) |
@@ -15,16 +16,23 @@ run() | |||
15 | async function run () { | 16 | async function run () { |
16 | await initDatabaseModels(true) | 17 | await initDatabaseModels(true) |
17 | 18 | ||
18 | const storageToPrune = [ | 19 | const storageOnlyOwnedToPrune = [ |
19 | CONFIG.STORAGE.VIDEOS_DIR, | 20 | CONFIG.STORAGE.VIDEOS_DIR, |
20 | CONFIG.STORAGE.PREVIEWS_DIR, | ||
21 | CONFIG.STORAGE.THUMBNAILS_DIR, | ||
22 | CONFIG.STORAGE.TORRENTS_DIR | 21 | CONFIG.STORAGE.TORRENTS_DIR |
23 | ] | 22 | ] |
24 | 23 | ||
24 | const storageForAllToPrune = [ | ||
25 | CONFIG.STORAGE.PREVIEWS_DIR, | ||
26 | CONFIG.STORAGE.THUMBNAILS_DIR | ||
27 | ] | ||
28 | |||
25 | let toDelete: string[] = [] | 29 | let toDelete: string[] = [] |
26 | for (const directory of storageToPrune) { | 30 | for (const directory of storageOnlyOwnedToPrune) { |
27 | toDelete = toDelete.concat(await pruneDirectory(directory)) | 31 | toDelete = toDelete.concat(await pruneDirectory(directory, true)) |
32 | } | ||
33 | |||
34 | for (const directory of storageForAllToPrune) { | ||
35 | toDelete = toDelete.concat(await pruneDirectory(directory, false)) | ||
28 | } | 36 | } |
29 | 37 | ||
30 | if (toDelete.length === 0) { | 38 | if (toDelete.length === 0) { |
@@ -48,17 +56,27 @@ async function run () { | |||
48 | } | 56 | } |
49 | } | 57 | } |
50 | 58 | ||
51 | async function pruneDirectory (directory: string) { | 59 | async function pruneDirectory (directory: string, onlyOwned = false) { |
52 | const files = await readdir(directory) | 60 | const files = await readdir(directory) |
53 | 61 | ||
54 | const toDelete: string[] = [] | 62 | const toDelete: string[] = [] |
55 | for (const file of files) { | 63 | for (const file of files) { |
56 | const uuid = getUUIDFromFilename(file) | 64 | const uuid = getUUIDFromFilename(file) |
57 | let video: VideoModel | 65 | let video: VideoModel |
66 | let localRedundancy: boolean | ||
58 | 67 | ||
59 | if (uuid) video = await VideoModel.loadByUUIDWithFile(uuid) | 68 | if (uuid) { |
69 | video = await VideoModel.loadByUUIDWithFile(uuid) | ||
70 | localRedundancy = await VideoRedundancyModel.isLocalByVideoUUIDExists(uuid) | ||
71 | } | ||
60 | 72 | ||
61 | if (!uuid || !video) toDelete.push(join(directory, file)) | 73 | if ( |
74 | !uuid || | ||
75 | !video || | ||
76 | (onlyOwned === true && (video.isOwned() === false && localRedundancy === false)) | ||
77 | ) { | ||
78 | toDelete.push(join(directory, file)) | ||
79 | } | ||
62 | } | 80 | } |
63 | 81 | ||
64 | return toDelete | 82 | return toDelete |
@@ -80,7 +98,8 @@ async function askConfirmation () { | |||
80 | properties: { | 98 | properties: { |
81 | confirm: { | 99 | confirm: { |
82 | type: 'string', | 100 | type: 'string', |
83 | description: 'Are you sure you want to delete these files? Please check carefully', | 101 | description: 'These following unused files can be deleted, but please check your backups first (bugs happen).' + |
102 | ' Can we delete these files?', | ||
84 | default: 'n', | 103 | default: 'n', |
85 | required: true | 104 | required: true |
86 | } | 105 | } |
diff --git a/server/models/redundancy/video-redundancy.ts b/server/models/redundancy/video-redundancy.ts index e67164802..791ba3137 100644 --- a/server/models/redundancy/video-redundancy.ts +++ b/server/models/redundancy/video-redundancy.ts | |||
@@ -146,6 +146,38 @@ export class VideoRedundancyModel extends Model<VideoRedundancyModel> { | |||
146 | return VideoRedundancyModel.findOne(query) | 146 | return VideoRedundancyModel.findOne(query) |
147 | } | 147 | } |
148 | 148 | ||
149 | static async isLocalByVideoUUIDExists (uuid: string) { | ||
150 | const actor = await getServerActor() | ||
151 | |||
152 | const query = { | ||
153 | raw: true, | ||
154 | attributes: [ 'id' ], | ||
155 | where: { | ||
156 | actorId: actor.id | ||
157 | }, | ||
158 | include: [ | ||
159 | { | ||
160 | attributes: [ ], | ||
161 | model: VideoFileModel, | ||
162 | required: true, | ||
163 | include: [ | ||
164 | { | ||
165 | attributes: [ ], | ||
166 | model: VideoModel, | ||
167 | required: true, | ||
168 | where: { | ||
169 | uuid | ||
170 | } | ||
171 | } | ||
172 | ] | ||
173 | } | ||
174 | ] | ||
175 | } | ||
176 | |||
177 | return VideoRedundancyModel.findOne(query) | ||
178 | .then(r => !!r) | ||
179 | } | ||
180 | |||
149 | static async getVideoSample (p: Bluebird<VideoModel[]>) { | 181 | static async getVideoSample (p: Bluebird<VideoModel[]>) { |
150 | const rows = await p | 182 | const rows = await p |
151 | const ids = rows.map(r => r.id) | 183 | const ids = rows.map(r => r.id) |