@datatruck/cli 0.14.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Action/BackupAction.js +3 -15
- package/Action/RestoreAction.js +2 -10
- package/Command/BackupCommand.js +2 -1
- package/Command/BackupSessionsCommand.js +1 -0
- package/Command/RestoreCommand.js +1 -1
- package/Command/RestoreSessionsCommand.js +1 -0
- package/Entity/StateEntityAbstract.d.ts +2 -1
- package/Repository/DatatruckRepository.d.ts +1 -0
- package/Repository/DatatruckRepository.js +116 -96
- package/Repository/RepositoryAbstract.d.ts +10 -5
- package/Repository/ResticRepository.js +34 -17
- package/SessionDriver/ConsoleSessionDriver.d.ts +2 -3
- package/SessionDriver/ConsoleSessionDriver.js +11 -10
- package/SessionManager/BackupSessionManager.d.ts +10 -11
- package/SessionManager/BackupSessionManager.js +24 -5
- package/SessionManager/RestoreSessionManager.d.ts +12 -11
- package/SessionManager/RestoreSessionManager.js +24 -5
- package/SessionManager/SessionManagerAbstract.d.ts +14 -0
- package/SessionManager/SessionManagerAbstract.js +21 -0
- package/Task/GitTask.js +22 -14
- package/Task/MariadbTask.js +9 -4
- package/Task/SqlDumpTaskAbstract.js +30 -10
- package/Task/TaskAbstract.d.ts +10 -5
- package/cli.js +1 -1
- package/migrations/001-initial.sql +12 -6
- package/package.json +1 -1
- package/util/fs-util.d.ts +10 -1
- package/util/fs-util.js +9 -0
- package/util/zip-util.d.ts +23 -5
- package/util/zip-util.js +70 -19
package/Action/BackupAction.js
CHANGED
|
@@ -77,11 +77,7 @@ class BackupAction {
|
|
|
77
77
|
onProgress: async (data) => {
|
|
78
78
|
await session.progressTask({
|
|
79
79
|
id: taskId,
|
|
80
|
-
|
|
81
|
-
progressPercent: data.percent,
|
|
82
|
-
progressStep: data.step,
|
|
83
|
-
progressStepPercent: data.stepPercent,
|
|
84
|
-
progressTotal: data.total,
|
|
80
|
+
...data,
|
|
85
81
|
});
|
|
86
82
|
},
|
|
87
83
|
});
|
|
@@ -123,11 +119,7 @@ class BackupAction {
|
|
|
123
119
|
onProgress: async (data) => {
|
|
124
120
|
await session.progressRepository({
|
|
125
121
|
id: repositoryId,
|
|
126
|
-
|
|
127
|
-
progressPercent: data.percent,
|
|
128
|
-
progressStep: data.step,
|
|
129
|
-
progressStepPercent: data.stepPercent,
|
|
130
|
-
progressTotal: data.total,
|
|
122
|
+
...data,
|
|
131
123
|
});
|
|
132
124
|
},
|
|
133
125
|
});
|
|
@@ -167,11 +159,7 @@ class BackupAction {
|
|
|
167
159
|
onProgress: async (data) => {
|
|
168
160
|
await session.progressRepository({
|
|
169
161
|
id: repositoryId,
|
|
170
|
-
|
|
171
|
-
progressPercent: data.percent,
|
|
172
|
-
progressStep: data.step,
|
|
173
|
-
progressStepPercent: data.stepPercent,
|
|
174
|
-
progressTotal: data.total,
|
|
162
|
+
...data,
|
|
175
163
|
});
|
|
176
164
|
},
|
|
177
165
|
});
|
package/Action/RestoreAction.js
CHANGED
|
@@ -114,11 +114,7 @@ class RestoreAction {
|
|
|
114
114
|
onProgress: async (data) => {
|
|
115
115
|
await session.progressTask({
|
|
116
116
|
id: taskId,
|
|
117
|
-
|
|
118
|
-
progressPercent: data.percent,
|
|
119
|
-
progressStep: data.step,
|
|
120
|
-
progressStepPercent: data.stepPercent,
|
|
121
|
-
progressTotal: data.total,
|
|
117
|
+
...data,
|
|
122
118
|
});
|
|
123
119
|
},
|
|
124
120
|
});
|
|
@@ -163,11 +159,7 @@ class RestoreAction {
|
|
|
163
159
|
onProgress: async (data) => {
|
|
164
160
|
await session.progressRepository({
|
|
165
161
|
id: repositoryId,
|
|
166
|
-
|
|
167
|
-
progressPercent: data.percent,
|
|
168
|
-
progressStep: data.step,
|
|
169
|
-
progressStepPercent: data.stepPercent,
|
|
170
|
-
progressTotal: data.total,
|
|
162
|
+
...data,
|
|
171
163
|
});
|
|
172
164
|
},
|
|
173
165
|
});
|
package/Command/BackupCommand.js
CHANGED
|
@@ -68,9 +68,10 @@ class BackupCommand extends CommandAbstract_1.CommandAbstract {
|
|
|
68
68
|
new ConsoleSessionDriver_1.ConsoleSessionDriver({
|
|
69
69
|
verbose: verbose > 0,
|
|
70
70
|
progress: this.globalOptions.progress,
|
|
71
|
-
progressInterval: this.globalOptions.progressInterval,
|
|
72
71
|
}),
|
|
73
72
|
],
|
|
73
|
+
verbose: verbose > 1,
|
|
74
|
+
progressInterval: this.globalOptions.progressInterval,
|
|
74
75
|
});
|
|
75
76
|
const result = await backup.exec(sessionManager);
|
|
76
77
|
if (result.errors) {
|
|
@@ -50,6 +50,7 @@ class BackupSessionsCommand extends CommandAbstract_1.CommandAbstract {
|
|
|
50
50
|
verbose: verbose > 1,
|
|
51
51
|
}),
|
|
52
52
|
verbose: verbose > 1,
|
|
53
|
+
progressInterval: this.globalOptions.progressInterval,
|
|
53
54
|
});
|
|
54
55
|
const items = await action.exec(manager);
|
|
55
56
|
const dataFormat = new DataFormat_1.DataFormat({
|
|
@@ -68,10 +68,10 @@ class RestoreCommand extends CommandAbstract_1.CommandAbstract {
|
|
|
68
68
|
new ConsoleSessionDriver_1.ConsoleSessionDriver({
|
|
69
69
|
verbose: verbose > 0,
|
|
70
70
|
progress: this.globalOptions.progress,
|
|
71
|
-
progressInterval: this.globalOptions.progressInterval,
|
|
72
71
|
}),
|
|
73
72
|
],
|
|
74
73
|
verbose: verbose > 1,
|
|
74
|
+
progressInterval: this.globalOptions.progressInterval,
|
|
75
75
|
});
|
|
76
76
|
const result = await restore.exec(sessionManager);
|
|
77
77
|
return result ? 0 : 1;
|
|
@@ -49,6 +49,7 @@ class RestoreSessionsCommand extends CommandAbstract_1.CommandAbstract {
|
|
|
49
49
|
driver: new SqliteSessionDriver_1.SqliteSessionDriver({
|
|
50
50
|
verbose: verbose > 1,
|
|
51
51
|
}),
|
|
52
|
+
progressInterval: this.globalOptions.progressInterval,
|
|
52
53
|
});
|
|
53
54
|
const items = await action.exec(manager);
|
|
54
55
|
const dataFormat = new DataFormat_1.DataFormat({
|
|
@@ -7,6 +7,7 @@ export declare abstract class StateEntityAbstract extends CrudEntityAbstract {
|
|
|
7
7
|
progressTotal?: number | null;
|
|
8
8
|
progressCurrent?: number | null;
|
|
9
9
|
progressPercent?: number | null;
|
|
10
|
-
|
|
10
|
+
progressStepDescription?: string | null;
|
|
11
|
+
progressStepItem?: string | null;
|
|
11
12
|
progressStepPercent?: number | null;
|
|
12
13
|
}
|
|
@@ -49,6 +49,7 @@ export declare class DatatruckRepository extends RepositoryAbstract<DatatruckRep
|
|
|
49
49
|
static stringifyMetaData(data: MetaDataType): string;
|
|
50
50
|
onGetSource(): string;
|
|
51
51
|
onInit(data: InitDataType): Promise<void>;
|
|
52
|
+
private createFileScanner;
|
|
52
53
|
onPrune(data: PruneDataType): Promise<void>;
|
|
53
54
|
onSnapshots(data: SnapshotsDataType): Promise<SnapshotResultType[]>;
|
|
54
55
|
private normalizeCompressConfig;
|
|
@@ -19,6 +19,7 @@ const fs_1 = require("fs");
|
|
|
19
19
|
const promises_1 = require("fs/promises");
|
|
20
20
|
const micromatch_1 = require("micromatch");
|
|
21
21
|
const path_1 = require("path");
|
|
22
|
+
const perf_hooks_1 = require("perf_hooks");
|
|
22
23
|
const readline_1 = require("readline");
|
|
23
24
|
exports.datatruckRepositoryName = "datatruck";
|
|
24
25
|
exports.datatruckRepositoryDefinition = {
|
|
@@ -103,6 +104,67 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
103
104
|
async onInit(data) {
|
|
104
105
|
await (0, fs_util_1.mkdirIfNotExists)(this.config.outPath);
|
|
105
106
|
}
|
|
107
|
+
async createFileScanner(options) {
|
|
108
|
+
const object = {
|
|
109
|
+
total: 0,
|
|
110
|
+
current: 0,
|
|
111
|
+
progress: async (description, data) => {
|
|
112
|
+
await options.onProgress({
|
|
113
|
+
step: {
|
|
114
|
+
description,
|
|
115
|
+
item: data.path,
|
|
116
|
+
percent: data.percent,
|
|
117
|
+
},
|
|
118
|
+
stats: {
|
|
119
|
+
total: object.total,
|
|
120
|
+
current: object.current + data.current,
|
|
121
|
+
percent: (0, math_util_1.progressPercent)(object.total, object.current + data.current),
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
if (data.type === "end") {
|
|
125
|
+
object.current += data.current;
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
start: async (cb) => {
|
|
129
|
+
for await (const entry of (0, fs_util_1.pathIterator)(stream)) {
|
|
130
|
+
if (!options.disableCounting)
|
|
131
|
+
object.total++;
|
|
132
|
+
const currentTime = perf_hooks_1.performance.now();
|
|
133
|
+
const diff = currentTime - lastTime;
|
|
134
|
+
if (diff > 1000) {
|
|
135
|
+
await options.onProgress({
|
|
136
|
+
step: {
|
|
137
|
+
description: "Scanning files",
|
|
138
|
+
item: object.total.toString(),
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
lastTime = currentTime;
|
|
142
|
+
}
|
|
143
|
+
if (cb)
|
|
144
|
+
await cb(entry);
|
|
145
|
+
}
|
|
146
|
+
await options.onProgress({
|
|
147
|
+
step: {
|
|
148
|
+
description: "Scanned files",
|
|
149
|
+
item: object.total.toString(),
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
await options.onProgress({
|
|
155
|
+
step: {
|
|
156
|
+
description: "Scanning files",
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
const stream = fast_glob_1.default.stream(options.glob.include, {
|
|
160
|
+
dot: true,
|
|
161
|
+
markDirectories: true,
|
|
162
|
+
stats: true,
|
|
163
|
+
...options.glob,
|
|
164
|
+
});
|
|
165
|
+
let lastTime = perf_hooks_1.performance.now();
|
|
166
|
+
return object;
|
|
167
|
+
}
|
|
106
168
|
async onPrune(data) {
|
|
107
169
|
const snapshotName = DatatruckRepository.buildSnapshotName({
|
|
108
170
|
snapshotId: data.snapshot.id,
|
|
@@ -199,30 +261,28 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
199
261
|
verbose: data.options.verbose,
|
|
200
262
|
})
|
|
201
263
|
: undefined;
|
|
202
|
-
const stream = fast_glob_1.default.stream(include, {
|
|
203
|
-
cwd: sourcePath,
|
|
204
|
-
ignore: exclude,
|
|
205
|
-
dot: true,
|
|
206
|
-
onlyFiles: false,
|
|
207
|
-
markDirectories: true,
|
|
208
|
-
stats: true,
|
|
209
|
-
});
|
|
210
264
|
const packs = compress?.packs || [];
|
|
211
265
|
const tmpDir = await (0, fs_util_1.mkTmpDir)("path-lists");
|
|
212
266
|
const nonPackStream = (0, fs_1.createWriteStream)((0, path_1.join)(tmpDir, "nonpack.txt"));
|
|
213
267
|
const singlePackStream = (0, fs_1.createWriteStream)((0, path_1.join)(tmpDir, "single-pack.txt"));
|
|
214
268
|
const packStreams = Array.from({ length: packs.length }).map((v, i) => (0, fs_1.createWriteStream)((0, path_1.join)(tmpDir, `pack-${i}.txt`)));
|
|
215
|
-
let totalFiles = 0;
|
|
216
269
|
const streams = [nonPackStream, singlePackStream, ...packStreams];
|
|
217
270
|
if (data.options.verbose)
|
|
218
271
|
(0, cli_util_1.logExec)(`Writing file lists in ${tmpDir}`);
|
|
219
|
-
await
|
|
220
|
-
|
|
272
|
+
const scanner = await this.createFileScanner({
|
|
273
|
+
glob: {
|
|
274
|
+
include,
|
|
275
|
+
cwd: sourcePath,
|
|
276
|
+
ignore: exclude,
|
|
277
|
+
onlyFiles: false,
|
|
278
|
+
},
|
|
279
|
+
onProgress: data.onProgress,
|
|
280
|
+
disableCounting: true,
|
|
221
281
|
});
|
|
222
282
|
await Promise.all([
|
|
223
283
|
...streams.map((p) => (0, fs_util_1.waitForClose)(p)),
|
|
224
284
|
(async () => {
|
|
225
|
-
|
|
285
|
+
await scanner.start(async (entry) => {
|
|
226
286
|
const pathSubject = entry.stats.isDirectory()
|
|
227
287
|
? entry.path.slice(0, -1)
|
|
228
288
|
: entry.path;
|
|
@@ -254,23 +314,22 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
254
314
|
value += `:${successPackIndex}`;
|
|
255
315
|
}
|
|
256
316
|
if (!entry.stats.isDirectory())
|
|
257
|
-
|
|
317
|
+
scanner.total++;
|
|
258
318
|
stream.write(`${value}\n`);
|
|
259
319
|
}
|
|
260
|
-
}
|
|
320
|
+
});
|
|
261
321
|
for (const stream of streams) {
|
|
262
322
|
stream.end();
|
|
263
323
|
}
|
|
264
324
|
})(),
|
|
265
325
|
]);
|
|
266
|
-
let currentFiles = 0;
|
|
267
326
|
const dttFolder = `.dtt-${data.snapshot.id.slice(0, 8)}`;
|
|
268
327
|
const dttPath = (0, path_1.join)(outPath, dttFolder);
|
|
269
328
|
await (0, promises_1.mkdir)(dttPath);
|
|
329
|
+
await (0, promises_1.copyFile)(nonPackStream.path, (0, path_1.join)(dttPath, "permissions.txt"));
|
|
270
330
|
// Non pack
|
|
271
331
|
if (data.options.verbose)
|
|
272
|
-
(0, cli_util_1.logExec)(`Copying files to ${outPath}`);
|
|
273
|
-
await (0, promises_1.copyFile)(nonPackStream.path, (0, path_1.join)(dttPath, "permissions.txt"));
|
|
332
|
+
(0, cli_util_1.logExec)(`Copying files from ${nonPackStream.path.toString()} to ${outPath}`);
|
|
274
333
|
await (0, fs_util_1.cpy)({
|
|
275
334
|
input: {
|
|
276
335
|
type: "pathList",
|
|
@@ -280,17 +339,7 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
280
339
|
targetPath: outPath,
|
|
281
340
|
skipNotFoundError: true,
|
|
282
341
|
concurrency: this.config.fileCopyConcurrency,
|
|
283
|
-
async
|
|
284
|
-
if (isDir)
|
|
285
|
-
return;
|
|
286
|
-
currentFiles++;
|
|
287
|
-
await data.onProgress({
|
|
288
|
-
total: totalFiles,
|
|
289
|
-
current: currentFiles,
|
|
290
|
-
percent: (0, math_util_1.progressPercent)(totalFiles, currentFiles),
|
|
291
|
-
step: entryPath,
|
|
292
|
-
});
|
|
293
|
-
},
|
|
342
|
+
onProgress: async (progress) => await scanner.progress(progress.type === "end" ? "Files copied" : "Copying file", progress),
|
|
294
343
|
});
|
|
295
344
|
// Single pack
|
|
296
345
|
const singleReader = (0, readline_1.createInterface)({
|
|
@@ -305,44 +354,29 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
305
354
|
`-${encodeURIComponent(packPath.replace(/[\\/]/g, "-"))}` +
|
|
306
355
|
`.zip`).slice(0, 255);
|
|
307
356
|
const target = (0, path_1.join)(dttPath, outBasename);
|
|
308
|
-
|
|
357
|
+
await (0, zip_util_1.zip)({
|
|
309
358
|
path: pkg.path,
|
|
310
359
|
output: target,
|
|
311
360
|
filter: [{ patterns: [packPath] }],
|
|
312
361
|
verbose: data.options.verbose,
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
total: totalFiles,
|
|
317
|
-
current: currentFiles + stream.data.files,
|
|
318
|
-
percent: (0, math_util_1.progressPercent)(totalFiles, currentFiles + stream.data.files),
|
|
319
|
-
step: stream.data.path,
|
|
320
|
-
stepPercent: stream.data.progress,
|
|
321
|
-
});
|
|
322
|
-
},
|
|
362
|
+
onProgress: async (progress) => await scanner.progress(progress.type === "start"
|
|
363
|
+
? "Starting compressing"
|
|
364
|
+
: "Compressing file", progress),
|
|
323
365
|
});
|
|
324
|
-
currentFiles += stats.files;
|
|
325
366
|
}
|
|
326
367
|
// Packs
|
|
327
368
|
for (const [packIndex, packStream] of packStreams.entries()) {
|
|
328
369
|
const pack = packs[packIndex];
|
|
329
370
|
const target = (0, path_1.join)(dttPath, `pack-${packIndex}${pack.name ? `-${pack.name}` : ""}.zip`);
|
|
330
|
-
|
|
371
|
+
await (0, zip_util_1.zip)({
|
|
331
372
|
path: sourcePath,
|
|
332
373
|
output: target,
|
|
333
374
|
includeList: packStream.path.toString(),
|
|
334
375
|
verbose: data.options.verbose,
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
total: totalFiles,
|
|
339
|
-
current: currentFiles + stream.data.files,
|
|
340
|
-
percent: (0, math_util_1.progressPercent)(totalFiles, currentFiles + stream.data.files),
|
|
341
|
-
step: stream.data.path,
|
|
342
|
-
});
|
|
343
|
-
},
|
|
376
|
+
onProgress: async (progress) => await scanner.progress(progress.type === "start"
|
|
377
|
+
? "Starting compressing"
|
|
378
|
+
: "Compressing file", progress),
|
|
344
379
|
});
|
|
345
|
-
currentFiles += stats.files;
|
|
346
380
|
}
|
|
347
381
|
// Meta
|
|
348
382
|
const metaPath = `${outPath}.json`;
|
|
@@ -374,12 +408,21 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
374
408
|
if (data.options.verbose)
|
|
375
409
|
(0, cli_util_1.logExec)(`Copying backup files to ${targetPath}`);
|
|
376
410
|
await (0, promises_1.mkdir)(targetPath);
|
|
411
|
+
const scanner = await this.createFileScanner({
|
|
412
|
+
glob: {
|
|
413
|
+
include: ["**/*"],
|
|
414
|
+
cwd: sourcePath,
|
|
415
|
+
},
|
|
416
|
+
onProgress: data.onProgress,
|
|
417
|
+
});
|
|
418
|
+
await scanner.start();
|
|
377
419
|
await (0, fs_util_1.cpy)({
|
|
378
420
|
input: {
|
|
379
421
|
type: "glob",
|
|
380
422
|
sourcePath,
|
|
381
423
|
},
|
|
382
424
|
targetPath,
|
|
425
|
+
onProgress: async (progress) => await scanner.progress(progress.type === "end" ? "Files copied" : "Copying file", progress),
|
|
383
426
|
});
|
|
384
427
|
await (0, promises_1.copyFile)(sourceMetaPath, targetMetaPath);
|
|
385
428
|
}
|
|
@@ -400,43 +443,38 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
400
443
|
packageName: data.package.name,
|
|
401
444
|
});
|
|
402
445
|
const sourcePath = (0, path_1.join)(this.config.outPath, snapshotName);
|
|
403
|
-
let totalFiles = 0;
|
|
404
|
-
let currentFiles = 0;
|
|
405
|
-
await data.onProgress({
|
|
406
|
-
step: "Counting files...",
|
|
407
|
-
});
|
|
408
446
|
const dttFolder = `.dtt-${data.snapshot.id.slice(0, 8)}`;
|
|
409
447
|
const dttPath = (0, path_1.join)(sourcePath, dttFolder);
|
|
448
|
+
const scanner = await this.createFileScanner({
|
|
449
|
+
glob: {
|
|
450
|
+
include: ["**/*"],
|
|
451
|
+
cwd: sourcePath,
|
|
452
|
+
ignore: [dttFolder],
|
|
453
|
+
},
|
|
454
|
+
onProgress: data.onProgress,
|
|
455
|
+
});
|
|
456
|
+
await scanner.start();
|
|
410
457
|
const dttPathExists = await (0, fs_util_1.checkDir)(dttPath);
|
|
411
458
|
if (dttPathExists) {
|
|
412
459
|
const it = await (0, promises_1.opendir)(dttPath);
|
|
413
460
|
for await (const dirent of it) {
|
|
414
461
|
const path = (0, path_1.join)(dttPath, dirent.name);
|
|
415
462
|
if (dirent.name === "permissions.txt") {
|
|
416
|
-
|
|
463
|
+
scanner.total++;
|
|
417
464
|
}
|
|
418
465
|
else if (dirent.name.endsWith(".zip")) {
|
|
419
466
|
await (0, zip_util_1.listZip)({
|
|
420
467
|
path,
|
|
421
468
|
verbose: data.options.verbose,
|
|
422
|
-
onStream: (item) => {
|
|
469
|
+
onStream: async (item) => {
|
|
423
470
|
const isDir = item.Folder === "+";
|
|
424
471
|
if (!isDir)
|
|
425
|
-
|
|
472
|
+
scanner.total++;
|
|
426
473
|
},
|
|
427
474
|
});
|
|
428
475
|
}
|
|
429
476
|
}
|
|
430
477
|
}
|
|
431
|
-
const allFiles = fast_glob_1.default.stream(["**"], {
|
|
432
|
-
cwd: sourcePath,
|
|
433
|
-
ignore: [dttFolder],
|
|
434
|
-
dot: true,
|
|
435
|
-
onlyFiles: true,
|
|
436
|
-
});
|
|
437
|
-
for await (const _file of allFiles) {
|
|
438
|
-
totalFiles++;
|
|
439
|
-
}
|
|
440
478
|
if (data.options.verbose)
|
|
441
479
|
(0, cli_util_1.logExec)(`Copying files to ${restorePath}`);
|
|
442
480
|
await (0, fs_util_1.cpy)({
|
|
@@ -447,17 +485,7 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
447
485
|
},
|
|
448
486
|
targetPath: restorePath,
|
|
449
487
|
concurrency: this.config.fileCopyConcurrency,
|
|
450
|
-
|
|
451
|
-
if (!isDir) {
|
|
452
|
-
currentFiles++;
|
|
453
|
-
await data.onProgress({
|
|
454
|
-
total: totalFiles,
|
|
455
|
-
current: Math.max(currentFiles, 0),
|
|
456
|
-
percent: (0, math_util_1.progressPercent)(totalFiles, Math.max(currentFiles, 0)),
|
|
457
|
-
step: entryPath,
|
|
458
|
-
});
|
|
459
|
-
}
|
|
460
|
-
},
|
|
488
|
+
onProgress: async (progress) => await scanner.progress(progress.type === "end" ? "Files copied" : "Copying file", progress),
|
|
461
489
|
});
|
|
462
490
|
if (dttPathExists) {
|
|
463
491
|
const it = await (0, promises_1.opendir)(dttPath);
|
|
@@ -466,31 +494,23 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
466
494
|
if (dirent.name === "permissions.txt") {
|
|
467
495
|
if (data.options.verbose)
|
|
468
496
|
(0, cli_util_1.logExec)(`Applying permissions (${path})`);
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
total: totalFiles,
|
|
472
|
-
current: currentFiles,
|
|
473
|
-
percent: (0, math_util_1.progressPercent)(totalFiles, currentFiles),
|
|
474
|
-
step: "Applying permissions",
|
|
497
|
+
await scanner.progress("Applying permissions", {
|
|
498
|
+
current: 0,
|
|
475
499
|
});
|
|
476
500
|
await (0, fs_util_1.applyPermissions)(restorePath, path);
|
|
501
|
+
await scanner.progress("Permissions applied", {
|
|
502
|
+
current: 1,
|
|
503
|
+
type: "end",
|
|
504
|
+
});
|
|
477
505
|
}
|
|
478
506
|
else if (dirent.name.endsWith(".zip")) {
|
|
479
507
|
await (0, zip_util_1.unzip)({
|
|
480
508
|
input: path,
|
|
481
509
|
output: restorePath,
|
|
482
510
|
verbose: data.options.verbose,
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
current: currentFiles + stream.data.files,
|
|
487
|
-
percent: (0, math_util_1.progressPercent)(totalFiles, currentFiles + stream.data.files),
|
|
488
|
-
step: stream.type === "progress"
|
|
489
|
-
? `Extracting ${stream.data.path}`
|
|
490
|
-
: "",
|
|
491
|
-
stepPercent: stream.data.progress,
|
|
492
|
-
});
|
|
493
|
-
},
|
|
511
|
+
onProgress: async (progress) => await scanner.progress(progress.type === "start"
|
|
512
|
+
? "Starting extracting"
|
|
513
|
+
: "Extracting file", progress),
|
|
494
514
|
});
|
|
495
515
|
}
|
|
496
516
|
}
|
|
@@ -16,11 +16,16 @@ export declare type SnapshotResultType = SnapshotType & {
|
|
|
16
16
|
size: number;
|
|
17
17
|
};
|
|
18
18
|
export declare type ProgressDataType = {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
stats?: {
|
|
20
|
+
total?: number;
|
|
21
|
+
current?: number;
|
|
22
|
+
percent?: number;
|
|
23
|
+
};
|
|
24
|
+
step?: {
|
|
25
|
+
description?: string;
|
|
26
|
+
item?: string;
|
|
27
|
+
percent?: number | null;
|
|
28
|
+
};
|
|
24
29
|
};
|
|
25
30
|
export declare type InitDataType = {
|
|
26
31
|
options: InitActionOptionsType;
|
|
@@ -195,7 +195,9 @@ class ResticRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
195
195
|
verbose: data.options.verbose,
|
|
196
196
|
});
|
|
197
197
|
await data.onProgress({
|
|
198
|
-
step:
|
|
198
|
+
step: {
|
|
199
|
+
description: "Writing excluded paths list",
|
|
200
|
+
},
|
|
199
201
|
});
|
|
200
202
|
const tmpDir = await (0, fs_util_1.mkTmpDir)("restic-exclude");
|
|
201
203
|
const ignoredContents = (0, fs_util_1.fastglobToGitIgnore)(exclude, sourcePath).join("\n");
|
|
@@ -223,7 +225,9 @@ class ResticRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
223
225
|
if (data.options.verbose)
|
|
224
226
|
(0, cli_util_1.logExec)(`Writing paths lists`);
|
|
225
227
|
await data.onProgress({
|
|
226
|
-
step:
|
|
228
|
+
step: {
|
|
229
|
+
description: "Writing excluded paths list",
|
|
230
|
+
},
|
|
227
231
|
});
|
|
228
232
|
gitignorePath = await (0, fs_util_1.writeGitIgnoreList)({
|
|
229
233
|
paths: stream,
|
|
@@ -233,7 +237,9 @@ class ResticRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
233
237
|
throw new AppError_1.AppError(`Tag prefix is not allowed`);
|
|
234
238
|
const packageTag = ResticRepository.buildSnapshotTag(RepositoryAbstract_1.SnapshotTagEnum.PACKAGE, data.package.name);
|
|
235
239
|
await data.onProgress({
|
|
236
|
-
step:
|
|
240
|
+
step: {
|
|
241
|
+
description: "Fetching last snapshot",
|
|
242
|
+
},
|
|
237
243
|
});
|
|
238
244
|
const [lastSnapshot] = await restic.snapshots({
|
|
239
245
|
json: true,
|
|
@@ -245,7 +251,9 @@ class ResticRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
245
251
|
let totalFilesChanges = 0;
|
|
246
252
|
const totalFilesChangesLimit = 10;
|
|
247
253
|
await data.onProgress({
|
|
248
|
-
step:
|
|
254
|
+
step: {
|
|
255
|
+
description: "Executing backup action",
|
|
256
|
+
},
|
|
249
257
|
});
|
|
250
258
|
let resticSnapshotId;
|
|
251
259
|
let resticTotalBytes;
|
|
@@ -278,19 +286,24 @@ class ResticRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
278
286
|
if (totalFilesChanges > totalFilesChangesLimit) {
|
|
279
287
|
showProgressBar = true;
|
|
280
288
|
}
|
|
281
|
-
else if (lastProgress?.total !== streamData.total_files) {
|
|
289
|
+
else if (lastProgress?.stats?.total !== streamData.total_files) {
|
|
282
290
|
totalFilesChanges = 0;
|
|
283
291
|
}
|
|
284
292
|
else {
|
|
285
293
|
totalFilesChanges++;
|
|
286
294
|
}
|
|
287
295
|
await data.onProgress((lastProgress = {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
296
|
+
step: {
|
|
297
|
+
description: "Copying file",
|
|
298
|
+
item: streamData.current_files?.join(", ") ?? "-",
|
|
299
|
+
},
|
|
300
|
+
stats: {
|
|
301
|
+
total: Math.max(lastProgress?.stats?.total || 0, streamData.total_files || 0),
|
|
302
|
+
current: Math.max(lastProgress?.stats?.current || 0, streamData.files_done ?? 0),
|
|
303
|
+
percent: showProgressBar
|
|
304
|
+
? Number((streamData.percent_done * 100).toFixed(2))
|
|
305
|
+
: 0,
|
|
306
|
+
},
|
|
294
307
|
}));
|
|
295
308
|
}
|
|
296
309
|
else if (streamData.message_type === "summary") {
|
|
@@ -306,9 +319,11 @@ class ResticRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
306
319
|
const sizeTag = ResticRepository.buildSnapshotTag(RepositoryAbstract_1.SnapshotTagEnum.SIZE, resticTotalBytes.toString());
|
|
307
320
|
await restic.exec(["tag", "--add", sizeTag, resticSnapshotId]);
|
|
308
321
|
await data.onProgress({
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
322
|
+
stats: {
|
|
323
|
+
total: lastProgress?.stats?.total || 0,
|
|
324
|
+
current: lastProgress?.stats?.total || 0,
|
|
325
|
+
percent: 100,
|
|
326
|
+
},
|
|
312
327
|
});
|
|
313
328
|
}
|
|
314
329
|
async onCopyBackup(data) {
|
|
@@ -357,9 +372,11 @@ class ResticRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
357
372
|
if (streamData.message_type === "restore-status") {
|
|
358
373
|
const current = Math.min(streamData.total_bytes, snapshot.size);
|
|
359
374
|
await data.onProgress({
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
375
|
+
stats: {
|
|
376
|
+
total: snapshot.size,
|
|
377
|
+
current,
|
|
378
|
+
percent: (0, math_util_1.progressPercent)(snapshot.size, current),
|
|
379
|
+
},
|
|
363
380
|
});
|
|
364
381
|
}
|
|
365
382
|
},
|
|
@@ -15,17 +15,16 @@ declare type MessageType = {
|
|
|
15
15
|
progressCurrent?: number | null;
|
|
16
16
|
progressTotal?: number | null;
|
|
17
17
|
progressPercent?: number | null;
|
|
18
|
-
|
|
18
|
+
progressStepDescription?: string | null;
|
|
19
|
+
progressStepItem?: string | null;
|
|
19
20
|
progressStepPercent?: number | null;
|
|
20
21
|
};
|
|
21
22
|
declare type ConsoleSessionDriverOptions = SessionDriverOptions & {
|
|
22
23
|
progress?: "auto" | "tty" | "plain";
|
|
23
|
-
progressInterval?: number;
|
|
24
24
|
};
|
|
25
25
|
export declare class ConsoleSessionDriver extends SessionDriverAbstract<ConsoleSessionDriverOptions> {
|
|
26
26
|
protected lastMessage: MessageType | undefined;
|
|
27
27
|
protected lastMessageText: string | undefined;
|
|
28
|
-
protected lastProgressDate: number | undefined;
|
|
29
28
|
protected prints: number;
|
|
30
29
|
protected renderInterval: NodeJS.Timeout;
|
|
31
30
|
protected rendering?: boolean;
|