@datatruck/cli 0.17.2 → 0.19.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 +4 -2
- package/Action/BackupSessionsAction.js +2 -0
- package/Action/CleanCacheAction.js +1 -0
- package/Action/ConfigAction.js +1 -0
- package/Action/InitAction.js +2 -0
- package/Action/PruneAction.js +2 -0
- package/Action/RestoreAction.js +4 -2
- package/Action/RestoreSessionsAction.js +2 -0
- package/Action/SnapshotsAction.js +2 -0
- package/Command/CommandAbstract.js +2 -0
- package/Entity/BackupSessionEntity.js +5 -2
- package/Entity/BackupSessionRepositoryEntity.js +5 -2
- package/Entity/BackupSessionTaskEntity.js +4 -2
- package/Entity/CrudEntityAbstract.js +3 -0
- package/Entity/RestoreSessionEntity.js +4 -2
- package/Entity/RestoreSessionRepositoryEntity.js +5 -2
- package/Entity/RestoreSessionTaskEntity.js +4 -2
- package/Entity/StateEntityAbstract.js +5 -0
- package/Factory/CommandFactory.js +1 -1
- package/JsonSchema/DefinitionEnum.js +1 -1
- package/Repository/DatatruckRepository.d.ts +8 -14
- package/Repository/DatatruckRepository.js +115 -298
- package/Repository/GitRepository.js +1 -1
- package/Repository/RepositoryAbstract.js +4 -2
- package/Repository/ResticRepository.js +2 -1
- package/SessionDriver/ConsoleSessionDriver.js +9 -5
- package/SessionDriver/SessionDriverAbstract.js +3 -2
- package/SessionDriver/SqliteSessionDriver.js +2 -4
- package/SessionManager/BackupSessionManager.js +3 -6
- package/SessionManager/RestoreSessionManager.js +3 -6
- package/SessionManager/SessionManagerAbstract.js +4 -0
- package/Task/GitTask.js +1 -0
- package/Task/MariadbTask.d.ts +11 -0
- package/Task/MariadbTask.js +234 -51
- package/Task/MssqlTask.js +2 -1
- package/Task/ScriptTask.js +1 -0
- package/Task/SqlDumpTaskAbstract.js +1 -0
- package/Task/TaskAbstract.js +2 -1
- package/config.schema.json +67 -37
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/package.json +10 -9
- package/utils/DataFormat.js +1 -0
- package/utils/Git.js +1 -0
- package/utils/ObjectVault.js +3 -5
- package/utils/Restic.js +1 -0
- package/utils/datatruck/config.d.ts +1 -1
- package/utils/fs.d.ts +17 -2
- package/utils/fs.js +58 -7
- package/utils/process.d.ts +55 -3
- package/utils/process.js +159 -19
- package/utils/tar.d.ts +32 -0
- package/utils/tar.js +92 -0
- package/utils/zip.d.ts +0 -97
- package/utils/zip.js +0 -238
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.DatatruckRepository = exports.datatruckPackageRepositoryDefinition = exports.datatruckRepositoryDefinition = exports.datatruckRepositoryName = void 0;
|
|
7
4
|
const AppError_1 = require("../Error/AppError");
|
|
@@ -9,18 +6,13 @@ const DefinitionEnum_1 = require("../JsonSchema/DefinitionEnum");
|
|
|
9
6
|
const cli_1 = require("../utils/cli");
|
|
10
7
|
const paths_1 = require("../utils/datatruck/paths");
|
|
11
8
|
const fs_1 = require("../utils/fs");
|
|
12
|
-
const math_1 = require("../utils/math");
|
|
13
9
|
const string_1 = require("../utils/string");
|
|
14
|
-
const
|
|
10
|
+
const tar_1 = require("../utils/tar");
|
|
15
11
|
const RepositoryAbstract_1 = require("./RepositoryAbstract");
|
|
16
12
|
const assert_1 = require("assert");
|
|
17
|
-
const fast_glob_1 = __importDefault(require("fast-glob"));
|
|
18
|
-
const fs_2 = require("fs");
|
|
19
13
|
const promises_1 = require("fs/promises");
|
|
20
14
|
const micromatch_1 = require("micromatch");
|
|
21
15
|
const path_1 = require("path");
|
|
22
|
-
const perf_hooks_1 = require("perf_hooks");
|
|
23
|
-
const readline_1 = require("readline");
|
|
24
16
|
exports.datatruckRepositoryName = "datatruck";
|
|
25
17
|
exports.datatruckRepositoryDefinition = {
|
|
26
18
|
type: "object",
|
|
@@ -36,39 +28,26 @@ exports.datatruckPackageRepositoryDefinition = {
|
|
|
36
28
|
additionalProperties: false,
|
|
37
29
|
properties: {
|
|
38
30
|
compress: {
|
|
39
|
-
|
|
40
|
-
{
|
|
41
|
-
type: "boolean",
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
type: "object",
|
|
45
|
-
additionalProperties: false,
|
|
46
|
-
properties: {
|
|
47
|
-
packs: {
|
|
48
|
-
type: "array",
|
|
49
|
-
items: {
|
|
50
|
-
type: "object",
|
|
51
|
-
additionalProperties: false,
|
|
52
|
-
required: ["include"],
|
|
53
|
-
properties: {
|
|
54
|
-
name: { type: "string" },
|
|
55
|
-
include: (0, DefinitionEnum_1.makeRef)(DefinitionEnum_1.DefinitionEnum.stringListUtil),
|
|
56
|
-
exclude: (0, DefinitionEnum_1.makeRef)(DefinitionEnum_1.DefinitionEnum.stringListUtil),
|
|
57
|
-
onePackByResult: { type: "boolean" },
|
|
58
|
-
},
|
|
59
|
-
},
|
|
60
|
-
},
|
|
61
|
-
},
|
|
62
|
-
},
|
|
63
|
-
],
|
|
31
|
+
type: "boolean",
|
|
64
32
|
},
|
|
65
|
-
|
|
66
|
-
type: "
|
|
67
|
-
|
|
33
|
+
packs: {
|
|
34
|
+
type: "array",
|
|
35
|
+
items: {
|
|
36
|
+
type: "object",
|
|
37
|
+
additionalProperties: false,
|
|
38
|
+
required: ["include"],
|
|
39
|
+
properties: {
|
|
40
|
+
name: { type: "string" },
|
|
41
|
+
include: (0, DefinitionEnum_1.makeRef)(DefinitionEnum_1.DefinitionEnum.stringListUtil),
|
|
42
|
+
exclude: (0, DefinitionEnum_1.makeRef)(DefinitionEnum_1.DefinitionEnum.stringListUtil),
|
|
43
|
+
onePackByResult: { type: "boolean" },
|
|
44
|
+
},
|
|
45
|
+
},
|
|
68
46
|
},
|
|
69
47
|
},
|
|
70
48
|
};
|
|
71
49
|
class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
50
|
+
static zipBasenameTpl = `.*.dd.tar.gz`;
|
|
72
51
|
static buildSnapshotName(data) {
|
|
73
52
|
const date = data.snapshotDate.replace(/:/g, "-");
|
|
74
53
|
const pkgName = encodeURIComponent(data.packageName).replace(/%40/g, "@");
|
|
@@ -110,66 +89,6 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
110
89
|
async onInit(data) {
|
|
111
90
|
await (0, fs_1.mkdirIfNotExists)(this.config.outPath);
|
|
112
91
|
}
|
|
113
|
-
async createFileScanner(options) {
|
|
114
|
-
const object = {
|
|
115
|
-
total: 0,
|
|
116
|
-
current: 0,
|
|
117
|
-
progress: async (description, data) => {
|
|
118
|
-
await options.onProgress({
|
|
119
|
-
relative: {
|
|
120
|
-
description,
|
|
121
|
-
payload: data.path,
|
|
122
|
-
percent: data.percent,
|
|
123
|
-
},
|
|
124
|
-
absolute: {
|
|
125
|
-
total: object.total,
|
|
126
|
-
current: object.current + data.current,
|
|
127
|
-
percent: (0, math_1.progressPercent)(object.total, object.current + data.current),
|
|
128
|
-
},
|
|
129
|
-
});
|
|
130
|
-
if (data.type === "end") {
|
|
131
|
-
object.current += data.current;
|
|
132
|
-
}
|
|
133
|
-
},
|
|
134
|
-
updateProgress: async (end) => {
|
|
135
|
-
const currentTime = perf_hooks_1.performance.now();
|
|
136
|
-
const diff = currentTime - lastTime;
|
|
137
|
-
if (end || diff > 1000) {
|
|
138
|
-
await options.onProgress({
|
|
139
|
-
relative: {
|
|
140
|
-
description: end ? "Scanned files" : "Scanning files",
|
|
141
|
-
payload: object.total.toString(),
|
|
142
|
-
},
|
|
143
|
-
});
|
|
144
|
-
lastTime = currentTime;
|
|
145
|
-
}
|
|
146
|
-
},
|
|
147
|
-
start: async (cb) => {
|
|
148
|
-
for await (const entry of (0, fs_1.pathIterator)(stream)) {
|
|
149
|
-
if (!options.disableCounting)
|
|
150
|
-
object.total++;
|
|
151
|
-
await object.updateProgress();
|
|
152
|
-
if (cb)
|
|
153
|
-
await cb(entry);
|
|
154
|
-
}
|
|
155
|
-
if (!options.disableEndProgress)
|
|
156
|
-
await object.updateProgress(true);
|
|
157
|
-
},
|
|
158
|
-
};
|
|
159
|
-
await options.onProgress({
|
|
160
|
-
relative: {
|
|
161
|
-
description: "Scanning files",
|
|
162
|
-
},
|
|
163
|
-
});
|
|
164
|
-
const stream = fast_glob_1.default.stream(options.glob.include, {
|
|
165
|
-
dot: true,
|
|
166
|
-
markDirectories: true,
|
|
167
|
-
stats: true,
|
|
168
|
-
...options.glob,
|
|
169
|
-
});
|
|
170
|
-
let lastTime = perf_hooks_1.performance.now();
|
|
171
|
-
return object;
|
|
172
|
-
}
|
|
173
92
|
async onPrune(data) {
|
|
174
93
|
const snapshotName = DatatruckRepository.buildSnapshotName({
|
|
175
94
|
snapshotId: data.snapshot.id,
|
|
@@ -225,22 +144,6 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
225
144
|
}
|
|
226
145
|
return snapshots;
|
|
227
146
|
}
|
|
228
|
-
normalizeCompressConfig(packageConfig) {
|
|
229
|
-
let compress = packageConfig?.compress ?? this.config.compress;
|
|
230
|
-
if (compress === true || (compress && !Array.isArray(compress.packs))) {
|
|
231
|
-
return {
|
|
232
|
-
packs: [
|
|
233
|
-
{
|
|
234
|
-
include: ["**"],
|
|
235
|
-
},
|
|
236
|
-
],
|
|
237
|
-
};
|
|
238
|
-
}
|
|
239
|
-
else if (!compress) {
|
|
240
|
-
return undefined;
|
|
241
|
-
}
|
|
242
|
-
return compress;
|
|
243
|
-
}
|
|
244
147
|
async onBackup(data) {
|
|
245
148
|
const snapshotName = DatatruckRepository.buildSnapshotName({
|
|
246
149
|
snapshotId: data.snapshot.id,
|
|
@@ -249,134 +152,74 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
249
152
|
});
|
|
250
153
|
const outPath = (0, path_1.resolve)((0, path_1.join)(this.config.outPath, snapshotName));
|
|
251
154
|
const pkg = data.package;
|
|
252
|
-
await (0, promises_1.mkdir)(outPath, {
|
|
253
|
-
recursive: true,
|
|
254
|
-
});
|
|
255
155
|
const sourcePath = data.targetPath ?? pkg.path;
|
|
256
156
|
(0, assert_1.ok)(sourcePath);
|
|
257
|
-
|
|
258
|
-
const
|
|
259
|
-
|
|
260
|
-
verbose: data.options.verbose,
|
|
261
|
-
});
|
|
262
|
-
const exclude = pkg.exclude
|
|
263
|
-
? await (0, paths_1.parsePaths)(pkg.exclude, {
|
|
264
|
-
cwd: sourcePath,
|
|
265
|
-
verbose: data.options.verbose,
|
|
266
|
-
})
|
|
267
|
-
: undefined;
|
|
268
|
-
const packs = compress?.packs || [];
|
|
269
|
-
const tmpDir = await this.mkTmpDir("path-lists");
|
|
270
|
-
const unpackedStream = (0, fs_2.createWriteStream)((0, path_1.join)(tmpDir, "unpacked.txt"));
|
|
271
|
-
const singlePackStream = (0, fs_2.createWriteStream)((0, path_1.join)(tmpDir, "single-pack.txt"));
|
|
272
|
-
const packStreams = Array.from({ length: packs.length }).map((v, i) => (0, fs_2.createWriteStream)((0, path_1.join)(tmpDir, `pack-${i}.txt`)));
|
|
273
|
-
const streams = [unpackedStream, singlePackStream, ...packStreams];
|
|
274
|
-
if (data.options.verbose)
|
|
275
|
-
(0, cli_1.logExec)(`Writing file lists in ${tmpDir}`);
|
|
276
|
-
const scanner = await this.createFileScanner({
|
|
157
|
+
await (0, promises_1.mkdir)(outPath, { recursive: true });
|
|
158
|
+
const scanner = await (0, fs_1.createFileScanner)({
|
|
159
|
+
onProgress: data.onProgress,
|
|
277
160
|
glob: {
|
|
278
|
-
include,
|
|
279
161
|
cwd: sourcePath,
|
|
280
|
-
ignore: exclude,
|
|
281
162
|
onlyFiles: false,
|
|
163
|
+
include: await (0, paths_1.parsePaths)(pkg.include ?? ["**"], {
|
|
164
|
+
cwd: sourcePath,
|
|
165
|
+
verbose: data.options.verbose,
|
|
166
|
+
}),
|
|
167
|
+
ignore: pkg.exclude
|
|
168
|
+
? await (0, paths_1.parsePaths)(pkg.exclude, {
|
|
169
|
+
cwd: sourcePath,
|
|
170
|
+
verbose: data.options.verbose,
|
|
171
|
+
})
|
|
172
|
+
: undefined,
|
|
282
173
|
},
|
|
283
|
-
onProgress: data.onProgress,
|
|
284
|
-
disableCounting: true,
|
|
285
174
|
});
|
|
286
|
-
|
|
287
|
-
...
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
? await (0, fs_1.isEmptyDir)((0, path_1.join)(sourcePath, entry.path))
|
|
310
|
-
: true
|
|
311
|
-
: true;
|
|
312
|
-
if (include) {
|
|
313
|
-
let value = entry.path;
|
|
314
|
-
if (isUnpackedStream) {
|
|
315
|
-
value += `:${entry.stats.uid}:${entry.stats.gid}:${entry.stats.mode}`;
|
|
316
|
-
}
|
|
317
|
-
else if (isSinglePackStream) {
|
|
318
|
-
value += `:${successPackIndex}`;
|
|
319
|
-
}
|
|
320
|
-
if (!entry.stats.isDirectory())
|
|
321
|
-
scanner.total++;
|
|
322
|
-
stream.write(`${value}\n`);
|
|
323
|
-
}
|
|
175
|
+
const configPacks = (data.packageConfig?.packs ?? []).map((p) => ({
|
|
176
|
+
...p,
|
|
177
|
+
compress: p.compress ?? data.packageConfig?.compress ?? this.config.compress,
|
|
178
|
+
includeResult: [],
|
|
179
|
+
}));
|
|
180
|
+
const defaultsPack = {
|
|
181
|
+
name: "defaults",
|
|
182
|
+
compress: data.packageConfig?.compress ?? this.config.compress,
|
|
183
|
+
include: [],
|
|
184
|
+
includeResult: [],
|
|
185
|
+
};
|
|
186
|
+
const packs = [...configPacks, defaultsPack];
|
|
187
|
+
await scanner.start(async (entry) => {
|
|
188
|
+
if (entry.dirent.isDirectory() &&
|
|
189
|
+
!(await (0, fs_1.isEmptyDir)((0, path_1.join)(sourcePath, entry.path))))
|
|
190
|
+
return false;
|
|
191
|
+
const pack = configPacks.find((pack) => (0, string_1.checkPath)(entry.path, pack.include, pack.exclude)) || defaultsPack;
|
|
192
|
+
if (pack.onePackByResult) {
|
|
193
|
+
const subname = (0, path_1.basename)(entry.path);
|
|
194
|
+
packs.push({
|
|
195
|
+
...pack,
|
|
196
|
+
name: pack.name ? `${pack.name}-${subname}` : subname,
|
|
197
|
+
includeResult: [entry.path],
|
|
324
198
|
});
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
const unpackedPath = (0, path_1.join)(outPath, "unpacked");
|
|
331
|
-
await (0, promises_1.mkdir)(unpackedPath);
|
|
332
|
-
await (0, promises_1.copyFile)(unpackedStream.path, (0, path_1.join)(outPath, "permissions.txt"));
|
|
333
|
-
// Non pack
|
|
334
|
-
if (data.options.verbose)
|
|
335
|
-
(0, cli_1.logExec)(`Copying files from ${unpackedStream.path.toString()} to ${unpackedPath}`);
|
|
336
|
-
await (0, fs_1.cpy)({
|
|
337
|
-
input: {
|
|
338
|
-
type: "pathList",
|
|
339
|
-
path: unpackedStream.path.toString(),
|
|
340
|
-
basePath: sourcePath,
|
|
341
|
-
},
|
|
342
|
-
targetPath: unpackedPath,
|
|
343
|
-
skipNotFoundError: true,
|
|
344
|
-
concurrency: this.config.fileCopyConcurrency,
|
|
345
|
-
onProgress: async (progress) => await scanner.progress(progress.type === "end" ? "Files copied" : "Copying file", progress),
|
|
346
|
-
});
|
|
347
|
-
// Single pack
|
|
348
|
-
const singleReader = (0, readline_1.createInterface)({
|
|
349
|
-
input: (0, fs_2.createReadStream)(singlePackStream.path),
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
pack.includeResult.push(entry.path);
|
|
202
|
+
}
|
|
203
|
+
return true;
|
|
350
204
|
});
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
const
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
}
|
|
368
|
-
// Packs
|
|
369
|
-
for (const [packIndex, packStream] of packStreams.entries()) {
|
|
370
|
-
const pack = packs[packIndex];
|
|
371
|
-
const target = (0, path_1.join)(outPath, `pack-${packIndex}${pack.name ? `-${pack.name}` : ""}.zip`);
|
|
372
|
-
await (0, zip_1.zip)({
|
|
373
|
-
path: sourcePath,
|
|
374
|
-
output: target,
|
|
375
|
-
includeList: packStream.path.toString(),
|
|
376
|
-
verbose: data.options.verbose,
|
|
377
|
-
onProgress: async (progress) => await scanner.progress("Compressing file", progress),
|
|
378
|
-
});
|
|
205
|
+
let packIndex = 0;
|
|
206
|
+
for (const pack of packs) {
|
|
207
|
+
const packBasename = [`pack`, (packIndex++).toString(), pack.name]
|
|
208
|
+
.filter((v) => typeof v === "string")
|
|
209
|
+
.map((v) => encodeURIComponent(v.toString().replace(/[\\/]/g, "-")))
|
|
210
|
+
.join("-");
|
|
211
|
+
const ext = pack.compress ? `.tar.gz` : `.tar`;
|
|
212
|
+
if (pack.includeResult.length)
|
|
213
|
+
await (0, tar_1.createTar)({
|
|
214
|
+
compress: pack.compress,
|
|
215
|
+
verbose: data.options.verbose,
|
|
216
|
+
include: pack.includeResult,
|
|
217
|
+
path: sourcePath,
|
|
218
|
+
output: (0, path_1.join)(outPath, packBasename) + ext,
|
|
219
|
+
onEntry: async (data) => await scanner.progress(pack.compress ? "Compressing" : "Packing", data.path),
|
|
220
|
+
});
|
|
379
221
|
}
|
|
222
|
+
await scanner.end();
|
|
380
223
|
// Meta
|
|
381
224
|
const metaPath = `${outPath}/meta.json`;
|
|
382
225
|
const nodePkg = (0, fs_1.parsePackageFile)();
|
|
@@ -403,23 +246,28 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
403
246
|
const targetPath = (0, path_1.resolve)((0, path_1.join)(data.mirrorRepositoryConfig.outPath, snapshotName));
|
|
404
247
|
if (data.options.verbose)
|
|
405
248
|
(0, cli_1.logExec)(`Copying backup files to ${targetPath}`);
|
|
406
|
-
await (0, promises_1.mkdir)(targetPath);
|
|
407
|
-
|
|
249
|
+
await (0, promises_1.mkdir)(targetPath, { recursive: true });
|
|
250
|
+
await (0, fs_1.ensureEmptyDir)(targetPath);
|
|
251
|
+
const scanner = await (0, fs_1.createFileScanner)({
|
|
252
|
+
onProgress: data.onProgress,
|
|
408
253
|
glob: {
|
|
409
254
|
include: ["**/*"],
|
|
410
255
|
cwd: sourcePath,
|
|
411
256
|
},
|
|
412
|
-
onProgress: data.onProgress,
|
|
413
257
|
});
|
|
414
|
-
|
|
415
|
-
await (
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
sourcePath,
|
|
419
|
-
},
|
|
420
|
-
targetPath,
|
|
421
|
-
onProgress: async (progress) => await scanner.progress(progress.type === "end" ? "Files copied" : "Copying file", progress),
|
|
258
|
+
const entryPaths = [];
|
|
259
|
+
await scanner.start(async (entry) => {
|
|
260
|
+
entryPaths.push(entry.path);
|
|
261
|
+
return true;
|
|
422
262
|
});
|
|
263
|
+
for (const entryPath of entryPaths) {
|
|
264
|
+
const sourceFile = (0, path_1.join)(sourcePath, entryPath);
|
|
265
|
+
const targetFile = (0, path_1.join)(targetPath, entryPath);
|
|
266
|
+
await scanner.progress("Copying", entryPath);
|
|
267
|
+
await (0, promises_1.mkdir)((0, path_1.dirname)(targetFile), { recursive: true });
|
|
268
|
+
await (0, promises_1.cp)(sourceFile, targetFile);
|
|
269
|
+
}
|
|
270
|
+
await scanner.end();
|
|
423
271
|
}
|
|
424
272
|
async onRestore(data) {
|
|
425
273
|
const relRestorePath = data.targetPath ?? data.package.restorePath;
|
|
@@ -438,72 +286,41 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
438
286
|
packageName: data.package.name,
|
|
439
287
|
});
|
|
440
288
|
const sourcePath = (0, path_1.join)(this.config.outPath, snapshotName);
|
|
441
|
-
const scanner = await
|
|
289
|
+
const scanner = await (0, fs_1.createFileScanner)({
|
|
290
|
+
onProgress: data.onProgress,
|
|
442
291
|
glob: {
|
|
443
|
-
include: ["unpacked/**/*"],
|
|
444
292
|
cwd: sourcePath,
|
|
293
|
+
include: ["**/*"],
|
|
445
294
|
},
|
|
446
|
-
onProgress: data.onProgress,
|
|
447
|
-
disableEndProgress: true,
|
|
448
295
|
});
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
const
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
await (0, zip_1.listZip)({
|
|
459
|
-
path,
|
|
296
|
+
const tarFiles = [];
|
|
297
|
+
await scanner.start(async (entry) => {
|
|
298
|
+
const path = (0, path_1.join)(sourcePath, entry.name);
|
|
299
|
+
const isTar = entry.name.endsWith(".tar");
|
|
300
|
+
const isTarGz = entry.name.endsWith(".tar.gz");
|
|
301
|
+
if (isTar || isTarGz) {
|
|
302
|
+
tarFiles.push(path);
|
|
303
|
+
await (0, tar_1.listTar)({
|
|
304
|
+
input: path,
|
|
460
305
|
verbose: data.options.verbose,
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
if (!isDir)
|
|
464
|
-
scanner.total++;
|
|
465
|
-
await scanner.updateProgress();
|
|
306
|
+
onEntry: () => {
|
|
307
|
+
scanner.total++;
|
|
466
308
|
},
|
|
467
309
|
});
|
|
468
310
|
}
|
|
469
|
-
|
|
470
|
-
await scanner.updateProgress(true);
|
|
471
|
-
if (data.options.verbose)
|
|
472
|
-
(0, cli_1.logExec)(`Copying files to ${restorePath}`);
|
|
473
|
-
await (0, fs_1.cpy)({
|
|
474
|
-
input: {
|
|
475
|
-
type: "glob",
|
|
476
|
-
sourcePath: (0, path_1.join)(sourcePath, "unpacked"),
|
|
477
|
-
},
|
|
478
|
-
targetPath: restorePath,
|
|
479
|
-
concurrency: this.config.fileCopyConcurrency,
|
|
480
|
-
onProgress: async (progress) => await scanner.progress(progress.type === "end" ? "Files copied" : "Copying file", progress),
|
|
311
|
+
return false;
|
|
481
312
|
});
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
await (0, fs_1.applyPermissions)(restorePath, path);
|
|
492
|
-
await scanner.progress("Permissions applied", {
|
|
493
|
-
current: 1,
|
|
494
|
-
type: "end",
|
|
495
|
-
});
|
|
496
|
-
}
|
|
497
|
-
else if (dirent.name.endsWith(".zip")) {
|
|
498
|
-
await (0, zip_1.unzip)({
|
|
499
|
-
input: path,
|
|
500
|
-
output: restorePath,
|
|
501
|
-
verbose: data.options.verbose,
|
|
502
|
-
onProgress: async (progress) => await scanner.progress("Extracting file", progress),
|
|
503
|
-
});
|
|
504
|
-
}
|
|
313
|
+
if (data.options.verbose)
|
|
314
|
+
(0, cli_1.logExec)(`Unpacking files to ${restorePath}`);
|
|
315
|
+
for (const tarFile of tarFiles) {
|
|
316
|
+
await (0, tar_1.extractTar)({
|
|
317
|
+
input: tarFile,
|
|
318
|
+
output: restorePath,
|
|
319
|
+
verbose: data.options.verbose,
|
|
320
|
+
onEntry: async (data) => await scanner.progress(tarFile.endsWith(".tar.gz") ? "Extracting" : "Unpacking", data.path),
|
|
321
|
+
});
|
|
505
322
|
}
|
|
323
|
+
await scanner.end();
|
|
506
324
|
}
|
|
507
325
|
}
|
|
508
326
|
exports.DatatruckRepository = DatatruckRepository;
|
|
509
|
-
DatatruckRepository.zipBasenameTpl = `.*.dd.zip`;
|
|
@@ -32,6 +32,7 @@ exports.gitPackageRepositoryDefinition = {
|
|
|
32
32
|
properties: {},
|
|
33
33
|
};
|
|
34
34
|
class GitRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
35
|
+
static refPrefix = "dt";
|
|
35
36
|
onGetSource() {
|
|
36
37
|
return this.config.repo;
|
|
37
38
|
}
|
|
@@ -244,4 +245,3 @@ class GitRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
244
245
|
}
|
|
245
246
|
}
|
|
246
247
|
exports.GitRepository = GitRepository;
|
|
247
|
-
GitRepository.refPrefix = "dt";
|
|
@@ -12,11 +12,13 @@ var SnapshotTagEnum;
|
|
|
12
12
|
SnapshotTagEnum["TAGS"] = "tags";
|
|
13
13
|
SnapshotTagEnum["VERSION"] = "version";
|
|
14
14
|
SnapshotTagEnum["SIZE"] = "size";
|
|
15
|
-
})(SnapshotTagEnum
|
|
15
|
+
})(SnapshotTagEnum || (exports.SnapshotTagEnum = SnapshotTagEnum = {}));
|
|
16
16
|
class RepositoryAbstract {
|
|
17
|
+
repository;
|
|
18
|
+
config;
|
|
19
|
+
tmpDirs = [];
|
|
17
20
|
constructor(repository) {
|
|
18
21
|
this.repository = repository;
|
|
19
|
-
this.tmpDirs = [];
|
|
20
22
|
this.config = repository.config;
|
|
21
23
|
}
|
|
22
24
|
async mkTmpDir(prefix, id) {
|
|
@@ -81,6 +81,8 @@ exports.resticPackageRepositoryDefinition = {
|
|
|
81
81
|
properties: {},
|
|
82
82
|
};
|
|
83
83
|
class ResticRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
84
|
+
static refPrefix = "dt-";
|
|
85
|
+
env;
|
|
84
86
|
async buildEnv() {
|
|
85
87
|
if (this.env)
|
|
86
88
|
return this.env;
|
|
@@ -386,4 +388,3 @@ class ResticRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
386
388
|
}
|
|
387
389
|
}
|
|
388
390
|
exports.ResticRepository = ResticRepository;
|
|
389
|
-
ResticRepository.refPrefix = "dt-";
|
|
@@ -14,11 +14,15 @@ const sep = (0, chalk_1.grey)(`|`);
|
|
|
14
14
|
const renderBadge = (badge) => `${badge.color(badge.name)}${(0, chalk_1.grey)(`:`)} ${(0, chalk_1.white)(badge.value)}`;
|
|
15
15
|
const renderBadges = (badges) => badges.map(renderBadge).join(` ${sep} `);
|
|
16
16
|
class ConsoleSessionDriver extends SessionDriverAbstract_1.SessionDriverAbstract {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
lastMessage;
|
|
18
|
+
lastMessageText;
|
|
19
|
+
prints = 0;
|
|
20
|
+
renderInterval;
|
|
21
|
+
rendering;
|
|
22
|
+
lastColumns;
|
|
23
|
+
startTime;
|
|
24
|
+
chron = (0, date_1.createChron)();
|
|
25
|
+
tty;
|
|
22
26
|
async onInit() {
|
|
23
27
|
this.tty = this.options.verbose
|
|
24
28
|
? false
|
|
@@ -7,7 +7,7 @@ var ActionEnum;
|
|
|
7
7
|
ActionEnum[ActionEnum["Start"] = 1] = "Start";
|
|
8
8
|
ActionEnum[ActionEnum["Progress"] = 2] = "Progress";
|
|
9
9
|
ActionEnum[ActionEnum["End"] = 3] = "End";
|
|
10
|
-
})(ActionEnum
|
|
10
|
+
})(ActionEnum || (exports.ActionEnum = ActionEnum = {}));
|
|
11
11
|
var EntityEnum;
|
|
12
12
|
(function (EntityEnum) {
|
|
13
13
|
EntityEnum[EntityEnum["BackupSession"] = 0] = "BackupSession";
|
|
@@ -16,8 +16,9 @@ var EntityEnum;
|
|
|
16
16
|
EntityEnum[EntityEnum["RestoreSession"] = 3] = "RestoreSession";
|
|
17
17
|
EntityEnum[EntityEnum["RestoreSessionTask"] = 4] = "RestoreSessionTask";
|
|
18
18
|
EntityEnum[EntityEnum["RestoreSessionRepository"] = 5] = "RestoreSessionRepository";
|
|
19
|
-
})(EntityEnum
|
|
19
|
+
})(EntityEnum || (exports.EntityEnum = EntityEnum = {}));
|
|
20
20
|
class SessionDriverAbstract {
|
|
21
|
+
options;
|
|
21
22
|
constructor(options) {
|
|
22
23
|
this.options = options;
|
|
23
24
|
}
|
|
@@ -20,10 +20,8 @@ const path_2 = require("path");
|
|
|
20
20
|
const sqlite_1 = require("sqlite");
|
|
21
21
|
const sqlite3_1 = __importDefault(require("sqlite3"));
|
|
22
22
|
class SqliteSessionDriver extends SessionDriverAbstract_1.SessionDriverAbstract {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
this.idMap = {};
|
|
26
|
-
}
|
|
23
|
+
idMap = {};
|
|
24
|
+
db;
|
|
27
25
|
async onInit() {
|
|
28
26
|
this.db = await (0, sqlite_1.open)({
|
|
29
27
|
filename: process.env["DATATRUCK_SQLITE_DB"] ??
|
|
@@ -8,12 +8,9 @@ const SessionDriverAbstract_1 = require("../SessionDriver/SessionDriverAbstract"
|
|
|
8
8
|
const ObjectVault_1 = require("../utils/ObjectVault");
|
|
9
9
|
const SessionManagerAbstract_1 = __importDefault(require("./SessionManagerAbstract"));
|
|
10
10
|
class BackupSessionManager extends SessionManagerAbstract_1.default {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
this.taskVault = new ObjectVault_1.ObjectVault();
|
|
15
|
-
this.repositoryVault = new ObjectVault_1.ObjectVault();
|
|
16
|
-
}
|
|
11
|
+
sessionVault = new ObjectVault_1.ObjectVault();
|
|
12
|
+
taskVault = new ObjectVault_1.ObjectVault();
|
|
13
|
+
repositoryVault = new ObjectVault_1.ObjectVault();
|
|
17
14
|
findId(data) {
|
|
18
15
|
return this.sessionVault.getId([data.packageName]);
|
|
19
16
|
}
|
|
@@ -8,12 +8,9 @@ const SessionDriverAbstract_1 = require("../SessionDriver/SessionDriverAbstract"
|
|
|
8
8
|
const ObjectVault_1 = require("../utils/ObjectVault");
|
|
9
9
|
const SessionManagerAbstract_1 = __importDefault(require("./SessionManagerAbstract"));
|
|
10
10
|
class RestoreSessionManager extends SessionManagerAbstract_1.default {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
this.repositoryVault = new ObjectVault_1.ObjectVault();
|
|
15
|
-
this.taskVault = new ObjectVault_1.ObjectVault();
|
|
16
|
-
}
|
|
11
|
+
sessionVault = new ObjectVault_1.ObjectVault();
|
|
12
|
+
repositoryVault = new ObjectVault_1.ObjectVault();
|
|
13
|
+
taskVault = new ObjectVault_1.ObjectVault();
|
|
17
14
|
findId(data) {
|
|
18
15
|
return this.sessionVault.getId([data.packageName]);
|
|
19
16
|
}
|