@datatruck/cli 0.18.0 → 0.20.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 +5 -3
- 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 -13
- package/Repository/DatatruckRepository.js +122 -231
- 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 +3 -2
- package/Task/MariadbTask.js +6 -4
- package/Task/MssqlTask.js +2 -1
- package/Task/ScriptTask.js +1 -0
- package/Task/SqlDumpTaskAbstract.js +2 -1
- package/Task/TaskAbstract.js +2 -1
- package/config.schema.json +23 -37
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/package.json +8 -8
- package/utils/DataFormat.js +1 -0
- package/utils/Git.js +2 -1
- package/utils/ObjectVault.js +3 -5
- package/utils/Restic.js +1 -0
- package/utils/datatruck/paths.js +5 -1
- package/utils/fs.d.ts +23 -24
- package/utils/fs.js +108 -96
- package/utils/process.d.ts +1 -1
- package/utils/process.js +17 -8
- package/utils/string.d.ts +0 -2
- package/utils/string.js +1 -9
- package/utils/tar.d.ts +35 -0
- package/utils/tar.js +127 -0
- package/utils/zip.d.ts +0 -97
- package/utils/zip.js +0 -238
|
@@ -7,14 +7,12 @@ const cli_1 = require("../utils/cli");
|
|
|
7
7
|
const paths_1 = require("../utils/datatruck/paths");
|
|
8
8
|
const fs_1 = require("../utils/fs");
|
|
9
9
|
const string_1 = require("../utils/string");
|
|
10
|
-
const
|
|
10
|
+
const tar_1 = require("../utils/tar");
|
|
11
11
|
const RepositoryAbstract_1 = require("./RepositoryAbstract");
|
|
12
12
|
const assert_1 = require("assert");
|
|
13
|
-
const fs_2 = require("fs");
|
|
14
13
|
const promises_1 = require("fs/promises");
|
|
15
14
|
const micromatch_1 = require("micromatch");
|
|
16
15
|
const path_1 = require("path");
|
|
17
|
-
const readline_1 = require("readline");
|
|
18
16
|
exports.datatruckRepositoryName = "datatruck";
|
|
19
17
|
exports.datatruckRepositoryDefinition = {
|
|
20
18
|
type: "object",
|
|
@@ -30,39 +28,26 @@ exports.datatruckPackageRepositoryDefinition = {
|
|
|
30
28
|
additionalProperties: false,
|
|
31
29
|
properties: {
|
|
32
30
|
compress: {
|
|
33
|
-
|
|
34
|
-
{
|
|
35
|
-
type: "boolean",
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
type: "object",
|
|
39
|
-
additionalProperties: false,
|
|
40
|
-
properties: {
|
|
41
|
-
packs: {
|
|
42
|
-
type: "array",
|
|
43
|
-
items: {
|
|
44
|
-
type: "object",
|
|
45
|
-
additionalProperties: false,
|
|
46
|
-
required: ["include"],
|
|
47
|
-
properties: {
|
|
48
|
-
name: { type: "string" },
|
|
49
|
-
include: (0, DefinitionEnum_1.makeRef)(DefinitionEnum_1.DefinitionEnum.stringListUtil),
|
|
50
|
-
exclude: (0, DefinitionEnum_1.makeRef)(DefinitionEnum_1.DefinitionEnum.stringListUtil),
|
|
51
|
-
onePackByResult: { type: "boolean" },
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
},
|
|
55
|
-
},
|
|
56
|
-
},
|
|
57
|
-
],
|
|
31
|
+
type: "boolean",
|
|
58
32
|
},
|
|
59
|
-
|
|
60
|
-
type: "
|
|
61
|
-
|
|
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
|
+
},
|
|
62
46
|
},
|
|
63
47
|
},
|
|
64
48
|
};
|
|
65
49
|
class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
50
|
+
static zipBasenameTpl = `.*.dd.tar.gz`;
|
|
66
51
|
static buildSnapshotName(data) {
|
|
67
52
|
const date = data.snapshotDate.replace(/:/g, "-");
|
|
68
53
|
const pkgName = encodeURIComponent(data.packageName).replace(/%40/g, "@");
|
|
@@ -113,13 +98,13 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
113
98
|
const snapshotPath = (0, path_1.join)(this.config.outPath, snapshotName);
|
|
114
99
|
if (data.options.verbose)
|
|
115
100
|
(0, cli_1.logExec)(`Deleting ${snapshotPath}`);
|
|
116
|
-
if (await (0, fs_1.
|
|
101
|
+
if (await (0, fs_1.existsDir)(snapshotPath))
|
|
117
102
|
await (0, promises_1.rm)(snapshotPath, {
|
|
118
103
|
recursive: true,
|
|
119
104
|
});
|
|
120
105
|
}
|
|
121
106
|
async onSnapshots(data) {
|
|
122
|
-
if (!(await (0, fs_1.
|
|
107
|
+
if (!(await (0, fs_1.existsDir)(this.config.outPath)))
|
|
123
108
|
throw new Error(`Repository (${this.repository.name}) out path does not exist: ${this.config.outPath}`);
|
|
124
109
|
const snapshotNames = await (0, fs_1.readDir)(this.config.outPath);
|
|
125
110
|
const snapshots = [];
|
|
@@ -159,22 +144,6 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
159
144
|
}
|
|
160
145
|
return snapshots;
|
|
161
146
|
}
|
|
162
|
-
normalizeCompressConfig(packageConfig) {
|
|
163
|
-
let compress = packageConfig?.compress ?? this.config.compress;
|
|
164
|
-
if (compress === true || (compress && !Array.isArray(compress.packs))) {
|
|
165
|
-
return {
|
|
166
|
-
packs: [
|
|
167
|
-
{
|
|
168
|
-
include: ["**"],
|
|
169
|
-
},
|
|
170
|
-
],
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
else if (!compress) {
|
|
174
|
-
return undefined;
|
|
175
|
-
}
|
|
176
|
-
return compress;
|
|
177
|
-
}
|
|
178
147
|
async onBackup(data) {
|
|
179
148
|
const snapshotName = DatatruckRepository.buildSnapshotName({
|
|
180
149
|
snapshotId: data.snapshot.id,
|
|
@@ -183,134 +152,81 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
183
152
|
});
|
|
184
153
|
const outPath = (0, path_1.resolve)((0, path_1.join)(this.config.outPath, snapshotName));
|
|
185
154
|
const pkg = data.package;
|
|
186
|
-
await (0, promises_1.mkdir)(outPath, {
|
|
187
|
-
recursive: true,
|
|
188
|
-
});
|
|
189
155
|
const sourcePath = data.targetPath ?? pkg.path;
|
|
190
156
|
(0, assert_1.ok)(sourcePath);
|
|
191
|
-
|
|
192
|
-
const include = await (0, paths_1.parsePaths)(pkg.include ?? ["**"], {
|
|
193
|
-
cwd: sourcePath,
|
|
194
|
-
verbose: data.options.verbose,
|
|
195
|
-
});
|
|
196
|
-
const exclude = pkg.exclude
|
|
197
|
-
? await (0, paths_1.parsePaths)(pkg.exclude, {
|
|
198
|
-
cwd: sourcePath,
|
|
199
|
-
verbose: data.options.verbose,
|
|
200
|
-
})
|
|
201
|
-
: undefined;
|
|
202
|
-
const packs = compress?.packs || [];
|
|
203
|
-
const tmpDir = await this.mkTmpDir("path-lists");
|
|
204
|
-
const unpackedStream = (0, fs_2.createWriteStream)((0, path_1.join)(tmpDir, "unpacked.txt"));
|
|
205
|
-
const singlePackStream = (0, fs_2.createWriteStream)((0, path_1.join)(tmpDir, "single-pack.txt"));
|
|
206
|
-
const packStreams = Array.from({ length: packs.length }).map((v, i) => (0, fs_2.createWriteStream)((0, path_1.join)(tmpDir, `pack-${i}.txt`)));
|
|
207
|
-
const streams = [unpackedStream, singlePackStream, ...packStreams];
|
|
208
|
-
if (data.options.verbose)
|
|
209
|
-
(0, cli_1.logExec)(`Writing file lists in ${tmpDir}`);
|
|
157
|
+
await (0, promises_1.mkdir)(outPath, { recursive: true });
|
|
210
158
|
const scanner = await (0, fs_1.createFileScanner)({
|
|
159
|
+
onProgress: data.onProgress,
|
|
211
160
|
glob: {
|
|
212
|
-
include,
|
|
213
161
|
cwd: sourcePath,
|
|
214
|
-
ignore: exclude,
|
|
215
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,
|
|
216
173
|
},
|
|
217
|
-
onProgress: data.onProgress,
|
|
218
|
-
disableCounting: true,
|
|
219
|
-
});
|
|
220
|
-
await Promise.all([
|
|
221
|
-
...streams.map((p) => (0, fs_1.waitForClose)(p)),
|
|
222
|
-
(async () => {
|
|
223
|
-
await scanner.start(async (entry) => {
|
|
224
|
-
const pathSubject = entry.stats.isDirectory()
|
|
225
|
-
? entry.path.slice(0, -1)
|
|
226
|
-
: entry.path;
|
|
227
|
-
let stream = unpackedStream;
|
|
228
|
-
let successPackIndex;
|
|
229
|
-
for (const [packIndex, pack] of packs.entries()) {
|
|
230
|
-
if ((0, string_1.checkPath)(pathSubject, pack.include, pack.exclude)) {
|
|
231
|
-
stream = pack.onePackByResult
|
|
232
|
-
? singlePackStream
|
|
233
|
-
: packStreams[packIndex];
|
|
234
|
-
successPackIndex = packIndex;
|
|
235
|
-
break;
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
const isUnpackedStream = stream === unpackedStream;
|
|
239
|
-
const isPackStream = stream !== unpackedStream;
|
|
240
|
-
const isSinglePackStream = stream === singlePackStream;
|
|
241
|
-
const include = isPackStream
|
|
242
|
-
? entry.stats.isDirectory()
|
|
243
|
-
? await (0, fs_1.isEmptyDir)((0, path_1.join)(sourcePath, entry.path))
|
|
244
|
-
: true
|
|
245
|
-
: true;
|
|
246
|
-
if (include) {
|
|
247
|
-
let value = entry.path;
|
|
248
|
-
if (isUnpackedStream) {
|
|
249
|
-
value += `:${entry.stats.uid}:${entry.stats.gid}:${entry.stats.mode}`;
|
|
250
|
-
}
|
|
251
|
-
else if (isSinglePackStream) {
|
|
252
|
-
value += `:${successPackIndex}`;
|
|
253
|
-
}
|
|
254
|
-
if (!entry.stats.isDirectory())
|
|
255
|
-
scanner.total++;
|
|
256
|
-
stream.write(`${value}\n`);
|
|
257
|
-
}
|
|
258
|
-
});
|
|
259
|
-
for (const stream of streams) {
|
|
260
|
-
stream.end();
|
|
261
|
-
}
|
|
262
|
-
})(),
|
|
263
|
-
]);
|
|
264
|
-
const unpackedPath = (0, path_1.join)(outPath, "unpacked");
|
|
265
|
-
await (0, promises_1.mkdir)(unpackedPath);
|
|
266
|
-
await (0, promises_1.copyFile)(unpackedStream.path, (0, path_1.join)(outPath, "permissions.txt"));
|
|
267
|
-
// Non pack
|
|
268
|
-
if (data.options.verbose)
|
|
269
|
-
(0, cli_1.logExec)(`Copying files from ${unpackedStream.path.toString()} to ${unpackedPath}`);
|
|
270
|
-
await (0, fs_1.cpy)({
|
|
271
|
-
input: {
|
|
272
|
-
type: "pathList",
|
|
273
|
-
path: unpackedStream.path.toString(),
|
|
274
|
-
basePath: sourcePath,
|
|
275
|
-
},
|
|
276
|
-
targetPath: unpackedPath,
|
|
277
|
-
skipNotFoundError: true,
|
|
278
|
-
concurrency: this.config.fileCopyConcurrency,
|
|
279
|
-
onProgress: async (progress) => await scanner.progress(progress.type === "end" ? "Files copied" : "Copying file", progress),
|
|
280
174
|
});
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
175
|
+
const configPacks = (data.packageConfig?.packs ?? []).map((p) => ({
|
|
176
|
+
...p,
|
|
177
|
+
compress: p.compress ?? data.packageConfig?.compress ?? this.config.compress,
|
|
178
|
+
}));
|
|
179
|
+
const defaultsPack = {
|
|
180
|
+
name: "defaults",
|
|
181
|
+
compress: data.packageConfig?.compress ?? this.config.compress,
|
|
182
|
+
include: [],
|
|
183
|
+
};
|
|
184
|
+
const packs = [...configPacks, defaultsPack];
|
|
185
|
+
const defaultsPackIndex = packs.findIndex((p) => p === defaultsPack);
|
|
186
|
+
const stream = (0, fs_1.createWriteStreamPool)({
|
|
187
|
+
path: await this.mkTmpDir("files"),
|
|
188
|
+
onStreamPath: (key) => `files-${key}.txt`,
|
|
284
189
|
});
|
|
285
|
-
|
|
286
|
-
|
|
190
|
+
await scanner.start(async (entry) => {
|
|
191
|
+
if (entry.dirent.isDirectory() &&
|
|
192
|
+
!(await (0, fs_1.isEmptyDir)((0, path_1.join)(sourcePath, entry.path))))
|
|
193
|
+
return false;
|
|
194
|
+
let packIndex = configPacks.findIndex((pack) => (0, string_1.checkPath)(entry.path, pack.include, pack.exclude));
|
|
195
|
+
if (packIndex === -1)
|
|
196
|
+
packIndex = defaultsPackIndex;
|
|
287
197
|
const pack = packs[packIndex];
|
|
288
|
-
if (
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
198
|
+
if (pack.onePackByResult) {
|
|
199
|
+
const subname = (0, path_1.basename)(entry.path);
|
|
200
|
+
packs.push({
|
|
201
|
+
...pack,
|
|
202
|
+
name: pack.name ? `${pack.name}-${subname}` : subname,
|
|
203
|
+
});
|
|
204
|
+
packIndex = packs.length - 1;
|
|
205
|
+
}
|
|
206
|
+
stream.writeLine(packIndex, entry.path);
|
|
207
|
+
return true;
|
|
208
|
+
});
|
|
209
|
+
await stream.end();
|
|
210
|
+
let packIndex = 0;
|
|
211
|
+
for (const pack of packs) {
|
|
212
|
+
const packBasename = [`pack`, packIndex.toString(), pack.name]
|
|
213
|
+
.filter((v) => typeof v === "string")
|
|
214
|
+
.map((v) => encodeURIComponent(v.toString().replace(/[\\/]/g, "-")))
|
|
215
|
+
.join("-");
|
|
216
|
+
const ext = pack.compress ? `.tar.gz` : `.tar`;
|
|
217
|
+
const includeList = stream.path(packIndex);
|
|
218
|
+
if (includeList)
|
|
219
|
+
await (0, tar_1.createTar)({
|
|
220
|
+
compress: pack.compress,
|
|
221
|
+
verbose: data.options.verbose,
|
|
222
|
+
includeList,
|
|
223
|
+
path: sourcePath,
|
|
224
|
+
output: (0, path_1.join)(outPath, packBasename) + ext,
|
|
225
|
+
onEntry: async (data) => await scanner.progress(pack.compress ? "Compressing" : "Packing", data.path),
|
|
226
|
+
});
|
|
227
|
+
packIndex++;
|
|
313
228
|
}
|
|
229
|
+
await scanner.end();
|
|
314
230
|
// Meta
|
|
315
231
|
const metaPath = `${outPath}/meta.json`;
|
|
316
232
|
const nodePkg = (0, fs_1.parsePackageFile)();
|
|
@@ -337,23 +253,28 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
337
253
|
const targetPath = (0, path_1.resolve)((0, path_1.join)(data.mirrorRepositoryConfig.outPath, snapshotName));
|
|
338
254
|
if (data.options.verbose)
|
|
339
255
|
(0, cli_1.logExec)(`Copying backup files to ${targetPath}`);
|
|
340
|
-
await (0, promises_1.mkdir)(targetPath);
|
|
256
|
+
await (0, promises_1.mkdir)(targetPath, { recursive: true });
|
|
257
|
+
await (0, fs_1.ensureEmptyDir)(targetPath);
|
|
341
258
|
const scanner = await (0, fs_1.createFileScanner)({
|
|
259
|
+
onProgress: data.onProgress,
|
|
342
260
|
glob: {
|
|
343
261
|
include: ["**/*"],
|
|
344
262
|
cwd: sourcePath,
|
|
345
263
|
},
|
|
346
|
-
onProgress: data.onProgress,
|
|
347
264
|
});
|
|
348
|
-
|
|
349
|
-
await (
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
sourcePath,
|
|
353
|
-
},
|
|
354
|
-
targetPath,
|
|
355
|
-
onProgress: async (progress) => await scanner.progress(progress.type === "end" ? "Files copied" : "Copying file", progress),
|
|
265
|
+
const entryPaths = [];
|
|
266
|
+
await scanner.start(async (entry) => {
|
|
267
|
+
entryPaths.push(entry.path);
|
|
268
|
+
return true;
|
|
356
269
|
});
|
|
270
|
+
for (const entryPath of entryPaths) {
|
|
271
|
+
const sourceFile = (0, path_1.join)(sourcePath, entryPath);
|
|
272
|
+
const targetFile = (0, path_1.join)(targetPath, entryPath);
|
|
273
|
+
await scanner.progress("Copying", entryPath);
|
|
274
|
+
await (0, promises_1.mkdir)((0, path_1.dirname)(targetFile), { recursive: true });
|
|
275
|
+
await (0, promises_1.cp)(sourceFile, targetFile);
|
|
276
|
+
}
|
|
277
|
+
await scanner.end();
|
|
357
278
|
}
|
|
358
279
|
async onRestore(data) {
|
|
359
280
|
const relRestorePath = data.targetPath ?? data.package.restorePath;
|
|
@@ -373,71 +294,41 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
373
294
|
});
|
|
374
295
|
const sourcePath = (0, path_1.join)(this.config.outPath, snapshotName);
|
|
375
296
|
const scanner = await (0, fs_1.createFileScanner)({
|
|
297
|
+
onProgress: data.onProgress,
|
|
376
298
|
glob: {
|
|
377
|
-
include: ["unpacked/**/*"],
|
|
378
299
|
cwd: sourcePath,
|
|
300
|
+
include: ["**/*"],
|
|
379
301
|
},
|
|
380
|
-
onProgress: data.onProgress,
|
|
381
|
-
disableEndProgress: true,
|
|
382
302
|
});
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
const
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
await (0, zip_1.listZip)({
|
|
393
|
-
path,
|
|
303
|
+
const tarFiles = [];
|
|
304
|
+
await scanner.start(async (entry) => {
|
|
305
|
+
const path = (0, path_1.join)(sourcePath, entry.name);
|
|
306
|
+
const isTar = entry.name.endsWith(".tar");
|
|
307
|
+
const isTarGz = entry.name.endsWith(".tar.gz");
|
|
308
|
+
if (isTar || isTarGz) {
|
|
309
|
+
tarFiles.push(path);
|
|
310
|
+
await (0, tar_1.listTar)({
|
|
311
|
+
input: path,
|
|
394
312
|
verbose: data.options.verbose,
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
if (!isDir)
|
|
398
|
-
scanner.total++;
|
|
399
|
-
await scanner.updateProgress();
|
|
313
|
+
onEntry: () => {
|
|
314
|
+
scanner.total++;
|
|
400
315
|
},
|
|
401
316
|
});
|
|
402
317
|
}
|
|
403
|
-
|
|
404
|
-
await scanner.updateProgress(true);
|
|
405
|
-
if (data.options.verbose)
|
|
406
|
-
(0, cli_1.logExec)(`Copying files to ${restorePath}`);
|
|
407
|
-
await (0, fs_1.cpy)({
|
|
408
|
-
input: {
|
|
409
|
-
type: "glob",
|
|
410
|
-
sourcePath: (0, path_1.join)(sourcePath, "unpacked"),
|
|
411
|
-
},
|
|
412
|
-
targetPath: restorePath,
|
|
413
|
-
concurrency: this.config.fileCopyConcurrency,
|
|
414
|
-
onProgress: async (progress) => await scanner.progress(progress.type === "end" ? "Files copied" : "Copying file", progress),
|
|
318
|
+
return false;
|
|
415
319
|
});
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
await scanner.progress("Permissions applied", {
|
|
427
|
-
current: 1,
|
|
428
|
-
type: "end",
|
|
429
|
-
});
|
|
430
|
-
}
|
|
431
|
-
else if (dirent.name.endsWith(".zip")) {
|
|
432
|
-
await (0, zip_1.unzip)({
|
|
433
|
-
input: path,
|
|
434
|
-
output: restorePath,
|
|
435
|
-
verbose: data.options.verbose,
|
|
436
|
-
onProgress: async (progress) => await scanner.progress("Extracting file", progress),
|
|
437
|
-
});
|
|
438
|
-
}
|
|
320
|
+
if (data.options.verbose)
|
|
321
|
+
(0, cli_1.logExec)(`Unpacking files to ${restorePath}`);
|
|
322
|
+
for (const tarFile of tarFiles) {
|
|
323
|
+
await (0, tar_1.extractTar)({
|
|
324
|
+
input: tarFile,
|
|
325
|
+
output: restorePath,
|
|
326
|
+
uncompress: tarFile.endsWith(".tar.gz"),
|
|
327
|
+
verbose: data.options.verbose,
|
|
328
|
+
onEntry: async (data) => await scanner.progress(tarFile.endsWith(".tar.gz") ? "Extracting" : "Unpacking", data.path),
|
|
329
|
+
});
|
|
439
330
|
}
|
|
331
|
+
await scanner.end();
|
|
440
332
|
}
|
|
441
333
|
}
|
|
442
334
|
exports.DatatruckRepository = DatatruckRepository;
|
|
443
|
-
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
|
}
|
package/Task/GitTask.js
CHANGED
|
@@ -55,6 +55,7 @@ exports.gitTaskDefinition = {
|
|
|
55
55
|
},
|
|
56
56
|
};
|
|
57
57
|
class GitTask extends TaskAbstract_1.TaskAbstract {
|
|
58
|
+
verbose;
|
|
58
59
|
get command() {
|
|
59
60
|
return this.config.command ?? "git";
|
|
60
61
|
}
|
|
@@ -230,14 +231,14 @@ class GitTask extends TaskAbstract_1.TaskAbstract {
|
|
|
230
231
|
await incrementProgress();
|
|
231
232
|
// Config
|
|
232
233
|
const configPath = (0, path_1.join)(targetPath, "repo.config");
|
|
233
|
-
if (await (0, fs_1.
|
|
234
|
+
if (await (0, fs_1.existsFile)(configPath)) {
|
|
234
235
|
await (0, promises_1.copyFile)(configPath, (0, path_1.join)(restorePath, ".git", "config"));
|
|
235
236
|
await incrementProgress();
|
|
236
237
|
}
|
|
237
238
|
// ls-files
|
|
238
239
|
for (const name of ["untracked", "modified", "ignored"]) {
|
|
239
240
|
const sourcePath = (0, path_1.join)(targetPath, `repo.${name}`);
|
|
240
|
-
if (await (0, fs_1.
|
|
241
|
+
if (await (0, fs_1.existsDir)(sourcePath)) {
|
|
241
242
|
if (data.options.verbose)
|
|
242
243
|
(0, cli_1.logExec)(`Copying ${name} files to ${restorePath}`);
|
|
243
244
|
await (0, fs_1.cpy)({
|
package/Task/MariadbTask.js
CHANGED
|
@@ -6,7 +6,7 @@ const cli_1 = require("../utils/cli");
|
|
|
6
6
|
const fs_1 = require("../utils/fs");
|
|
7
7
|
const math_1 = require("../utils/math");
|
|
8
8
|
const process_1 = require("../utils/process");
|
|
9
|
-
const
|
|
9
|
+
const tar_1 = require("../utils/tar");
|
|
10
10
|
const TaskAbstract_1 = require("./TaskAbstract");
|
|
11
11
|
const assert_1 = require("assert");
|
|
12
12
|
const fs_2 = require("fs");
|
|
@@ -101,6 +101,7 @@ function parseLine(line) {
|
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
103
|
class MariadbTask extends TaskAbstract_1.TaskAbstract {
|
|
104
|
+
verbose;
|
|
104
105
|
get command() {
|
|
105
106
|
return this.config.command ?? "mariabackup";
|
|
106
107
|
}
|
|
@@ -255,17 +256,18 @@ class MariadbTask extends TaskAbstract_1.TaskAbstract {
|
|
|
255
256
|
await data.onProgress({
|
|
256
257
|
absolute,
|
|
257
258
|
});
|
|
258
|
-
await (0,
|
|
259
|
+
await (0, tar_1.extractTar)({
|
|
259
260
|
input: (0, path_1.join)(restorePath, zipFile),
|
|
261
|
+
uncompress: true,
|
|
260
262
|
output: restorePath,
|
|
261
263
|
verbose: this.verbose,
|
|
262
|
-
async
|
|
264
|
+
async onEntry(item) {
|
|
263
265
|
await data.onProgress({
|
|
264
266
|
absolute,
|
|
265
267
|
relative: {
|
|
266
268
|
payload: item.path,
|
|
267
269
|
format: "amount",
|
|
268
|
-
percent: item.percent,
|
|
270
|
+
percent: item.progress.percent,
|
|
269
271
|
},
|
|
270
272
|
});
|
|
271
273
|
},
|