@datatruck/cli 0.34.3 → 0.34.5
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/lib/actions/BackupAction.js +125 -39
- package/lib/actions/ConfigAction.js +1 -1
- package/lib/actions/CopyAction.js +110 -74
- package/lib/actions/InitAction.js +1 -1
- package/lib/actions/PruneAction.js +3 -2
- package/lib/actions/RestoreAction.d.ts +0 -2
- package/lib/actions/RestoreAction.js +131 -62
- package/lib/cli.js +1 -1
- package/lib/commands/StartServerCommand.js +2 -1
- package/lib/repositories/DatatruckRepository.d.ts +1 -1
- package/lib/repositories/DatatruckRepository.js +31 -18
- package/lib/repositories/GitRepository.js +11 -3
- package/lib/repositories/RepositoryAbstract.d.ts +2 -1
- package/lib/repositories/RepositoryAbstract.js +3 -1
- package/lib/repositories/ResticRepository.js +1 -1
- package/lib/tasks/GitTask.js +2 -1
- package/lib/tasks/MssqlTask.js +2 -2
- package/lib/tasks/MysqlDumpTask.js +1 -1
- package/lib/tasks/SqlDumpTaskAbstract.js +2 -2
- package/lib/utils/async-process.js +3 -2
- package/lib/utils/cli.js +10 -10
- package/lib/utils/data-format.js +3 -3
- package/lib/utils/datatruck/client.d.ts +7 -3
- package/lib/utils/datatruck/client.js +9 -2
- package/lib/utils/datatruck/command.js +1 -1
- package/lib/utils/datatruck/config.js +4 -4
- package/lib/utils/datatruck/report-list.js +2 -1
- package/lib/utils/datatruck/repository.d.ts +3 -3
- package/lib/utils/datatruck/repository.js +4 -4
- package/lib/utils/datatruck/task.js +1 -1
- package/lib/utils/{datatruck/error.d.ts → error.d.ts} +1 -1
- package/lib/utils/{datatruck/error.js → error.js} +2 -2
- package/lib/utils/fs.d.ts +2 -1
- package/lib/utils/fs.js +22 -3
- package/lib/utils/git.d.ts +5 -0
- package/lib/utils/git.js +10 -0
- package/lib/utils/list.d.ts +3 -1
- package/lib/utils/list.js +2 -3
- package/lib/utils/mysql.js +1 -1
- package/lib/utils/object.d.ts +1 -1
- package/lib/utils/object.js +1 -1
- package/lib/utils/progress.d.ts +8 -1
- package/lib/utils/progress.js +38 -5
- package/lib/utils/reportSteps.js +3 -2
- package/lib/utils/string.js +1 -1
- package/lib/utils/temp.d.ts +13 -10
- package/lib/utils/temp.js +47 -40
- package/package.json +1 -1
|
@@ -1,4 +1,49 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
|
|
3
|
+
if (value !== null && value !== void 0) {
|
|
4
|
+
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
|
|
5
|
+
var dispose;
|
|
6
|
+
if (async) {
|
|
7
|
+
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
|
|
8
|
+
dispose = value[Symbol.asyncDispose];
|
|
9
|
+
}
|
|
10
|
+
if (dispose === void 0) {
|
|
11
|
+
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
|
|
12
|
+
dispose = value[Symbol.dispose];
|
|
13
|
+
}
|
|
14
|
+
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
|
|
15
|
+
env.stack.push({ value: value, dispose: dispose, async: async });
|
|
16
|
+
}
|
|
17
|
+
else if (async) {
|
|
18
|
+
env.stack.push({ async: true });
|
|
19
|
+
}
|
|
20
|
+
return value;
|
|
21
|
+
};
|
|
22
|
+
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
|
|
23
|
+
return function (env) {
|
|
24
|
+
function fail(e) {
|
|
25
|
+
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
|
|
26
|
+
env.hasError = true;
|
|
27
|
+
}
|
|
28
|
+
function next() {
|
|
29
|
+
while (env.stack.length) {
|
|
30
|
+
var rec = env.stack.pop();
|
|
31
|
+
try {
|
|
32
|
+
var result = rec.dispose && rec.dispose.call(rec.value);
|
|
33
|
+
if (rec.async) return Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
|
|
34
|
+
}
|
|
35
|
+
catch (e) {
|
|
36
|
+
fail(e);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (env.hasError) throw env.error;
|
|
40
|
+
}
|
|
41
|
+
return next();
|
|
42
|
+
};
|
|
43
|
+
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
44
|
+
var e = new Error(message);
|
|
45
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
46
|
+
});
|
|
2
47
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
48
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
49
|
};
|
|
@@ -10,6 +55,7 @@ const config_1 = require("../utils/datatruck/config");
|
|
|
10
55
|
const repository_1 = require("../utils/datatruck/repository");
|
|
11
56
|
const task_1 = require("../utils/datatruck/task");
|
|
12
57
|
const date_1 = require("../utils/date");
|
|
58
|
+
const error_1 = require("../utils/error");
|
|
13
59
|
const fs_1 = require("../utils/fs");
|
|
14
60
|
const list_1 = require("../utils/list");
|
|
15
61
|
const progress_1 = require("../utils/progress");
|
|
@@ -70,27 +116,25 @@ class RestoreAction {
|
|
|
70
116
|
const repoConfig = (0, config_1.findRepositoryOrFail)(this.config, snapshot.repositoryName);
|
|
71
117
|
const repo = await (0, repository_1.createAndInitRepo)(repoConfig, this.options.verbose);
|
|
72
118
|
let snapshotPath = pkg.restorePath ?? pkg.path;
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const taskResult = await task.prepareRestore({
|
|
76
|
-
options: this.options,
|
|
77
|
-
package: pkg,
|
|
78
|
-
snapshot,
|
|
79
|
-
});
|
|
80
|
-
snapshotPath = taskResult?.snapshotPath;
|
|
81
|
-
}
|
|
82
|
-
await (0, fs_1.initEmptyDir)(snapshotPath);
|
|
83
|
-
if (this.config.minFreeDiskSpace)
|
|
84
|
-
await (0, fs_1.ensureFreeDiskSpace)([snapshotPath], this.config.minFreeDiskSpace);
|
|
85
|
-
await repo.restore({
|
|
119
|
+
if (task) {
|
|
120
|
+
const taskResult = await task.prepareRestore({
|
|
86
121
|
options: this.options,
|
|
87
|
-
snapshot: data.snapshot,
|
|
88
122
|
package: pkg,
|
|
89
|
-
|
|
90
|
-
packageConfig: pkg.repositoryConfigs?.find((config) => config.type === repoConfig.type &&
|
|
91
|
-
(!config.names || config.names.includes(repoConfig.name)))?.config,
|
|
92
|
-
onProgress: data.onProgress,
|
|
123
|
+
snapshot,
|
|
93
124
|
});
|
|
125
|
+
snapshotPath = taskResult?.snapshotPath;
|
|
126
|
+
}
|
|
127
|
+
await (0, fs_1.initEmptyDir)(snapshotPath);
|
|
128
|
+
if (this.config.minFreeDiskSpace)
|
|
129
|
+
await (0, fs_1.ensureFreeDiskSpace)([snapshotPath], this.config.minFreeDiskSpace);
|
|
130
|
+
await repo.restore({
|
|
131
|
+
options: this.options,
|
|
132
|
+
snapshot: data.snapshot,
|
|
133
|
+
package: pkg,
|
|
134
|
+
snapshotPath: snapshotPath,
|
|
135
|
+
packageConfig: pkg.repositoryConfigs?.find((config) => config.type === repoConfig.type &&
|
|
136
|
+
(!config.names || config.names.includes(repoConfig.name)))?.config,
|
|
137
|
+
onProgress: data.onProgress,
|
|
94
138
|
});
|
|
95
139
|
return { snapshotPath };
|
|
96
140
|
}
|
|
@@ -138,6 +182,7 @@ class RestoreAction {
|
|
|
138
182
|
}
|
|
139
183
|
async exec() {
|
|
140
184
|
const { options } = this;
|
|
185
|
+
const gc = new temp_1.GargabeCollector();
|
|
141
186
|
const pm = new progress_1.ProgressManager({
|
|
142
187
|
verbose: options.verbose,
|
|
143
188
|
tty: options.tty,
|
|
@@ -146,6 +191,7 @@ class RestoreAction {
|
|
|
146
191
|
const l = new list_1.Listr3({
|
|
147
192
|
streams: options.streams,
|
|
148
193
|
progressManager: pm,
|
|
194
|
+
gargabeCollector: gc,
|
|
149
195
|
});
|
|
150
196
|
return l
|
|
151
197
|
.add(l.$task({
|
|
@@ -165,10 +211,10 @@ class RestoreAction {
|
|
|
165
211
|
if (minFreeDiskSpace)
|
|
166
212
|
await (0, temp_1.ensureFreeDiskTempSpace)(minFreeDiskSpace);
|
|
167
213
|
if (!options.snapshotId)
|
|
168
|
-
throw new
|
|
214
|
+
throw new error_1.AppError("Snapshot id is required");
|
|
169
215
|
const snapshots = this.groupSnapshots(await this.findSnapshots());
|
|
170
216
|
if (!snapshots.length)
|
|
171
|
-
throw new
|
|
217
|
+
throw new error_1.AppError("None snapshot found");
|
|
172
218
|
data.id = options.snapshotId;
|
|
173
219
|
data.packages = snapshots.length;
|
|
174
220
|
return snapshots.map((snapshot) => l.$task({
|
|
@@ -183,48 +229,71 @@ class RestoreAction {
|
|
|
183
229
|
},
|
|
184
230
|
exitOnError: false,
|
|
185
231
|
run: async (listTask) => {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
232
|
+
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
233
|
+
try {
|
|
234
|
+
let pkg = (0, config_1.resolvePackage)((0, config_1.findPackageOrFail)(this.config, snapshot.packageName), {
|
|
235
|
+
snapshotId: options.snapshotId,
|
|
236
|
+
snapshotDate: snapshot.date,
|
|
237
|
+
action: "restore",
|
|
238
|
+
});
|
|
239
|
+
if (this.options.initial)
|
|
240
|
+
pkg = { ...pkg, restorePath: pkg.path };
|
|
241
|
+
const task = pkg.task ? (0, task_1.createTask)(pkg.task) : undefined;
|
|
242
|
+
const progress = __addDisposableResource(env_1, pm.create(listTask), false);
|
|
243
|
+
const restoreGc = gc.create();
|
|
244
|
+
const restore = await restoreGc.disposeIfFail(() => this.restore({
|
|
245
|
+
pkg,
|
|
246
|
+
task,
|
|
247
|
+
snapshot: snapshot,
|
|
248
|
+
onProgress: progress.update,
|
|
249
|
+
}));
|
|
250
|
+
if (!task)
|
|
251
|
+
return await restoreGc.dispose();
|
|
252
|
+
return l.$tasks({
|
|
253
|
+
key: "task",
|
|
254
|
+
keyIndex: pkg.name,
|
|
255
|
+
data: { taskName: pkg.task.name, packageName: pkg.name },
|
|
256
|
+
title: {
|
|
257
|
+
initial: `Execute task: ${pkg.name} (${pkg.task.name})`,
|
|
258
|
+
started: `Executing task: ${pkg.name} (${pkg.task.name})`,
|
|
259
|
+
completed: `Task executed: ${pkg.name} (${pkg.task.name})`,
|
|
260
|
+
failed: `Task execute failed: ${pkg.name} (${pkg.task.name})`,
|
|
261
|
+
},
|
|
262
|
+
exitOnError: false,
|
|
263
|
+
run: async (listTask) => {
|
|
264
|
+
const env_2 = { stack: [], error: void 0, hasError: false };
|
|
265
|
+
try {
|
|
266
|
+
const _ = __addDisposableResource(env_2, restoreGc.disposeOnFinish(), true);
|
|
267
|
+
const { snapshotPath } = restore;
|
|
268
|
+
(0, assert_1.ok)(snapshotPath);
|
|
269
|
+
const progress = __addDisposableResource(env_2, pm.create(listTask), false);
|
|
270
|
+
await task.restore({
|
|
271
|
+
package: pkg,
|
|
272
|
+
options,
|
|
273
|
+
snapshot,
|
|
274
|
+
snapshotPath,
|
|
275
|
+
onProgress: progress.update,
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
catch (e_2) {
|
|
279
|
+
env_2.error = e_2;
|
|
280
|
+
env_2.hasError = true;
|
|
281
|
+
}
|
|
282
|
+
finally {
|
|
283
|
+
const result_1 = __disposeResources(env_2);
|
|
284
|
+
if (result_1)
|
|
285
|
+
await result_1;
|
|
286
|
+
}
|
|
287
|
+
},
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
catch (e_1) {
|
|
291
|
+
env_1.error = e_1;
|
|
292
|
+
env_1.hasError = true;
|
|
293
|
+
}
|
|
294
|
+
finally {
|
|
295
|
+
__disposeResources(env_1);
|
|
296
|
+
}
|
|
228
297
|
},
|
|
229
298
|
}));
|
|
230
299
|
},
|
package/lib/cli.js
CHANGED
|
@@ -8,7 +8,7 @@ const ConfigAction_1 = require("./actions/ConfigAction");
|
|
|
8
8
|
const globalData_1 = __importDefault(require("./globalData"));
|
|
9
9
|
const cli_1 = require("./utils/cli");
|
|
10
10
|
const command_1 = require("./utils/datatruck/command");
|
|
11
|
-
const error_1 = require("./utils/
|
|
11
|
+
const error_1 = require("./utils/error");
|
|
12
12
|
const exit_1 = require("./utils/exit");
|
|
13
13
|
const fs_1 = require("./utils/fs");
|
|
14
14
|
const string_1 = require("./utils/string");
|
|
@@ -4,6 +4,7 @@ exports.StartServerCommand = void 0;
|
|
|
4
4
|
const ConfigAction_1 = require("../actions/ConfigAction");
|
|
5
5
|
const cron_server_1 = require("../utils/datatruck/cron-server");
|
|
6
6
|
const repository_server_1 = require("../utils/datatruck/repository-server");
|
|
7
|
+
const error_1 = require("../utils/error");
|
|
7
8
|
const CommandAbstract_1 = require("./CommandAbstract");
|
|
8
9
|
class StartServerCommand extends CommandAbstract_1.CommandAbstract {
|
|
9
10
|
optionsConfig() {
|
|
@@ -31,7 +32,7 @@ class StartServerCommand extends CommandAbstract_1.CommandAbstract {
|
|
|
31
32
|
const cronOptions = config.server?.cron || {};
|
|
32
33
|
if (cronOptions.enabled ?? true) {
|
|
33
34
|
if (typeof this.configPath !== "string")
|
|
34
|
-
throw new
|
|
35
|
+
throw new error_1.AppError(`Config path is required by cron server`);
|
|
35
36
|
const server = (0, cron_server_1.createCronServer)(cronOptions, {
|
|
36
37
|
verbose,
|
|
37
38
|
log,
|
|
@@ -4,8 +4,8 @@ exports.DatatruckRepository = exports.datatruckRepositoryName = void 0;
|
|
|
4
4
|
const cli_1 = require("../utils/cli");
|
|
5
5
|
const crypto_1 = require("../utils/crypto");
|
|
6
6
|
const client_1 = require("../utils/datatruck/client");
|
|
7
|
-
const error_1 = require("../utils/datatruck/error");
|
|
8
7
|
const paths_1 = require("../utils/datatruck/paths");
|
|
8
|
+
const error_1 = require("../utils/error");
|
|
9
9
|
const fs_1 = require("../utils/fs");
|
|
10
10
|
const math_1 = require("../utils/math");
|
|
11
11
|
const string_1 = require("../utils/string");
|
|
@@ -45,15 +45,15 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
45
45
|
return this.config.backend;
|
|
46
46
|
}
|
|
47
47
|
fetchDiskStats(config) {
|
|
48
|
-
const fs = (0, client_1.createFs)(config.backend);
|
|
48
|
+
const fs = (0, client_1.createFs)(config.backend, this.verbose);
|
|
49
49
|
return fs.fetchDiskStats(".");
|
|
50
50
|
}
|
|
51
51
|
async init(data) {
|
|
52
|
-
const fs = (0, client_1.createFs)(this.config.backend);
|
|
52
|
+
const fs = (0, client_1.createFs)(this.config.backend, this.verbose);
|
|
53
53
|
await fs.mkdir(".");
|
|
54
54
|
}
|
|
55
55
|
async prune(data) {
|
|
56
|
-
const fs = (0, client_1.createFs)(this.config.backend);
|
|
56
|
+
const fs = (0, client_1.createFs)(this.config.backend, this.verbose);
|
|
57
57
|
const snapshotName = DatatruckRepository.buildSnapshotName(data.snapshot, {
|
|
58
58
|
name: data.snapshot.packageName,
|
|
59
59
|
});
|
|
@@ -63,9 +63,9 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
63
63
|
await fs.rmAll(snapshotName);
|
|
64
64
|
}
|
|
65
65
|
async fetchSnapshots(data) {
|
|
66
|
-
const fs = (0, client_1.createFs)(this.config.backend);
|
|
66
|
+
const fs = (0, client_1.createFs)(this.config.backend, this.verbose);
|
|
67
67
|
if (!(await fs.existsDir(".")))
|
|
68
|
-
throw new
|
|
68
|
+
throw new error_1.AppError(`Repository (${this.repository.name}) out path does not exist: ${fs.resolvePath(".")}`);
|
|
69
69
|
const snapshots = [];
|
|
70
70
|
const snapshotNames = await fs.readdir(".");
|
|
71
71
|
const packagePatterns = (0, string_1.makePathPatterns)(data.options.packageNames);
|
|
@@ -105,7 +105,7 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
105
105
|
return snapshots;
|
|
106
106
|
}
|
|
107
107
|
async backup(data) {
|
|
108
|
-
const fs = (0, client_1.createFs)(this.config.backend);
|
|
108
|
+
const fs = (0, client_1.createFs)(this.config.backend, this.verbose);
|
|
109
109
|
const snapshotName = DatatruckRepository.buildSnapshotName(data.snapshot, data.package);
|
|
110
110
|
const outPath = fs.isLocal()
|
|
111
111
|
? fs.resolvePath(snapshotName)
|
|
@@ -147,7 +147,8 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
147
147
|
scanner.total++;
|
|
148
148
|
stream.writeLine(defaultsPackIndex, ".");
|
|
149
149
|
await scanner.start(async (entry) => {
|
|
150
|
-
let packIndex =
|
|
150
|
+
let packIndex = packs.findIndex((pack) => pack !== defaultsPack &&
|
|
151
|
+
(0, string_1.match)(entry.path, pack.include, pack.exclude));
|
|
151
152
|
if (packIndex === -1)
|
|
152
153
|
packIndex = defaultsPackIndex;
|
|
153
154
|
const pack = packs[packIndex];
|
|
@@ -176,11 +177,11 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
176
177
|
.join("-") + (pack.compress ? `.tar.gz` : `.tar`);
|
|
177
178
|
const includeList = stream.path(packIndex);
|
|
178
179
|
if (includeList) {
|
|
179
|
-
tarStats[packBasename] = {
|
|
180
|
+
const stats = (tarStats[packBasename] = {
|
|
180
181
|
files: stream.lines(packIndex),
|
|
181
182
|
size: 0,
|
|
182
183
|
checksum: "",
|
|
183
|
-
};
|
|
184
|
+
});
|
|
184
185
|
const tarPath = (0, path_1.join)(outPath, packBasename);
|
|
185
186
|
await (0, tar_1.createTar)({
|
|
186
187
|
compress: pack.compress,
|
|
@@ -191,8 +192,8 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
191
192
|
onEntry: async (data) => scanner.progress(pack.compress ? "Compressing" : "Packing", data.path),
|
|
192
193
|
});
|
|
193
194
|
scanner.progress("Fetching tar stats", (0, path_1.basename)(tarPath), false);
|
|
194
|
-
|
|
195
|
-
|
|
195
|
+
stats.checksum = await (0, crypto_1.calcFileHash)(tarPath, "sha1");
|
|
196
|
+
stats.size = (await (0, promises_1.stat)(tarPath)).size;
|
|
196
197
|
if (!fs.isLocal()) {
|
|
197
198
|
scanner.progress("Uploading tar", (0, path_1.basename)(tarPath), false);
|
|
198
199
|
await fs.upload(tarPath, `${snapshotName}/${packBasename}`);
|
|
@@ -203,7 +204,7 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
203
204
|
}
|
|
204
205
|
scanner.end();
|
|
205
206
|
// Meta
|
|
206
|
-
const size = Object.values(tarStats).reduce((total,
|
|
207
|
+
const size = Object.values(tarStats).reduce((total, stat) => total + stat.size, 0);
|
|
207
208
|
const metaPath = `${snapshotName}/meta.json`;
|
|
208
209
|
const nodePkg = (0, fs_1.parsePackageFile)();
|
|
209
210
|
const meta = {
|
|
@@ -224,8 +225,8 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
224
225
|
};
|
|
225
226
|
}
|
|
226
227
|
async copy(data) {
|
|
227
|
-
const sourceFs = (0, client_1.createFs)(this.config.backend);
|
|
228
|
-
const targetFs = (0, client_1.createFs)(data.mirrorRepositoryConfig.backend);
|
|
228
|
+
const sourceFs = (0, client_1.createFs)(this.config.backend, this.verbose);
|
|
229
|
+
const targetFs = (0, client_1.createFs)(data.mirrorRepositoryConfig.backend, this.verbose);
|
|
229
230
|
const snapshotName = DatatruckRepository.buildSnapshotName(data.snapshot, data.package);
|
|
230
231
|
if (data.options.verbose)
|
|
231
232
|
(0, cli_1.logExec)(`Copying backup files to ${data.mirrorRepositoryConfig.backend}`);
|
|
@@ -261,6 +262,7 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
261
262
|
relative: {
|
|
262
263
|
description: "Downloading",
|
|
263
264
|
format: "size",
|
|
265
|
+
payload: entry,
|
|
264
266
|
...progress,
|
|
265
267
|
},
|
|
266
268
|
}),
|
|
@@ -277,6 +279,7 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
277
279
|
relative: {
|
|
278
280
|
description: "Downloading",
|
|
279
281
|
format: "size",
|
|
282
|
+
payload: entry,
|
|
280
283
|
...progress,
|
|
281
284
|
},
|
|
282
285
|
}),
|
|
@@ -293,7 +296,7 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
293
296
|
return { bytes };
|
|
294
297
|
}
|
|
295
298
|
async restore(data) {
|
|
296
|
-
const fs = (0, client_1.createFs)(this.config.backend);
|
|
299
|
+
const fs = (0, client_1.createFs)(this.config.backend, this.verbose);
|
|
297
300
|
const relRestorePath = data.snapshotPath;
|
|
298
301
|
(0, assert_1.ok)(relRestorePath);
|
|
299
302
|
const restorePath = (0, path_1.resolve)(relRestorePath);
|
|
@@ -322,10 +325,20 @@ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
322
325
|
if (!fs.isLocal()) {
|
|
323
326
|
const tempDir = await (0, temp_1.mkTmpDir)(exports.datatruckRepositoryName, "repo", "restore", "remote-fs", entry);
|
|
324
327
|
tempEntry = `${tempDir}/${entry}`;
|
|
325
|
-
await fs.download(sourceEntry, tempEntry
|
|
328
|
+
await fs.download(sourceEntry, tempEntry, {
|
|
329
|
+
onProgress: (stats) => {
|
|
330
|
+
progress.updateRelative("Downloading", entry, {
|
|
331
|
+
...stats,
|
|
332
|
+
format: "size",
|
|
333
|
+
});
|
|
334
|
+
},
|
|
335
|
+
});
|
|
326
336
|
}
|
|
337
|
+
const stats = tarStats[entry];
|
|
338
|
+
if (data.options.verbose)
|
|
339
|
+
(0, cli_1.logExec)(`Stats of '${entry}' is not available`);
|
|
327
340
|
await (0, tar_1.extractTar)({
|
|
328
|
-
total:
|
|
341
|
+
total: stats?.files,
|
|
329
342
|
input: tempEntry ?? fs.resolvePath(sourceEntry),
|
|
330
343
|
output: restorePath,
|
|
331
344
|
decompress: entry.endsWith(".tar.gz"),
|
|
@@ -68,7 +68,11 @@ class GitRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
68
68
|
branchName,
|
|
69
69
|
orphan: true,
|
|
70
70
|
});
|
|
71
|
-
await git.
|
|
71
|
+
await git.commit("Initial commit", {
|
|
72
|
+
allowEmpty: true,
|
|
73
|
+
userName: "datatruck",
|
|
74
|
+
userEmail: "datatruck@localhost",
|
|
75
|
+
});
|
|
72
76
|
await git.push({ branchName });
|
|
73
77
|
}
|
|
74
78
|
}
|
|
@@ -184,8 +188,12 @@ class GitRepository extends RepositoryAbstract_1.RepositoryAbstract {
|
|
|
184
188
|
if (data.options.verbose)
|
|
185
189
|
console.info(`Copied ${files} files`);
|
|
186
190
|
await git.exec(["add", "--verbose", "."]);
|
|
187
|
-
if (await git.haveChanges())
|
|
188
|
-
await git.
|
|
191
|
+
if (await git.haveChanges()) {
|
|
192
|
+
await git.commit(data.snapshot.id, {
|
|
193
|
+
userName: "datatruck",
|
|
194
|
+
userEmail: "datatruck@localhost",
|
|
195
|
+
});
|
|
196
|
+
}
|
|
189
197
|
const nodePkg = (0, fs_1.parsePackageFile)();
|
|
190
198
|
const size = (await (0, fs_1.fastFolderSizeAsync)(tmpPath)) -
|
|
191
199
|
(await (0, fs_1.fastFolderSizeAsync)((0, path_1.join)(tmpPath, ".git")));
|
|
@@ -75,8 +75,9 @@ export type SnapshotTagObject = {
|
|
|
75
75
|
};
|
|
76
76
|
export declare abstract class RepositoryAbstract<TConfig> {
|
|
77
77
|
readonly repository: RepositoryConfig;
|
|
78
|
+
readonly verbose: boolean;
|
|
78
79
|
readonly config: TConfig;
|
|
79
|
-
constructor(repository: RepositoryConfig);
|
|
80
|
+
constructor(repository: RepositoryConfig, verbose: boolean);
|
|
80
81
|
abstract getSource(): string;
|
|
81
82
|
abstract fetchDiskStats(config: TConfig): Promise<DiskStats | undefined>;
|
|
82
83
|
ensureFreeDiskSpace(config: TConfig, minFreeDiskSpace: number | string): Promise<void>;
|
|
@@ -15,9 +15,11 @@ var SnapshotTagEnum;
|
|
|
15
15
|
})(SnapshotTagEnum || (exports.SnapshotTagEnum = SnapshotTagEnum = {}));
|
|
16
16
|
class RepositoryAbstract {
|
|
17
17
|
repository;
|
|
18
|
+
verbose;
|
|
18
19
|
config;
|
|
19
|
-
constructor(repository) {
|
|
20
|
+
constructor(repository, verbose) {
|
|
20
21
|
this.repository = repository;
|
|
22
|
+
this.verbose = verbose;
|
|
21
23
|
this.config = repository.config;
|
|
22
24
|
}
|
|
23
25
|
async ensureFreeDiskSpace(config, minFreeDiskSpace) {
|
|
@@ -5,8 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.ResticRepository = exports.resticRepositoryName = void 0;
|
|
7
7
|
const cli_1 = require("../utils/cli");
|
|
8
|
-
const error_1 = require("../utils/datatruck/error");
|
|
9
8
|
const paths_1 = require("../utils/datatruck/paths");
|
|
9
|
+
const error_1 = require("../utils/error");
|
|
10
10
|
const fs_1 = require("../utils/fs");
|
|
11
11
|
const math_1 = require("../utils/math");
|
|
12
12
|
const restic_1 = require("../utils/restic");
|
package/lib/tasks/GitTask.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.GitTask = exports.gitTaskName = void 0;
|
|
4
4
|
const async_process_1 = require("../utils/async-process");
|
|
5
5
|
const cli_1 = require("../utils/cli");
|
|
6
|
+
const error_1 = require("../utils/error");
|
|
6
7
|
const fs_1 = require("../utils/fs");
|
|
7
8
|
const math_1 = require("../utils/math");
|
|
8
9
|
const stream_1 = require("../utils/stream");
|
|
@@ -21,7 +22,7 @@ class GitTask extends TaskAbstract_1.TaskAbstract {
|
|
|
21
22
|
}
|
|
22
23
|
async backup(data) {
|
|
23
24
|
if (!data.package.path)
|
|
24
|
-
throw new
|
|
25
|
+
throw new error_1.AppError(`'package.path' is required`);
|
|
25
26
|
const snapshotPath = await (0, temp_1.mkTmpDir)(exports.gitTaskName, "task", "backup", "snapshot");
|
|
26
27
|
this.verbose = data.options.verbose;
|
|
27
28
|
const config = this.config;
|
package/lib/tasks/MssqlTask.js
CHANGED
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.MssqlTask = exports.mssqlTaskName = void 0;
|
|
4
4
|
const async_process_1 = require("../utils/async-process");
|
|
5
5
|
const config_1 = require("../utils/datatruck/config");
|
|
6
|
-
const error_1 = require("../utils/
|
|
6
|
+
const error_1 = require("../utils/error");
|
|
7
7
|
const fs_1 = require("../utils/fs");
|
|
8
8
|
const temp_1 = require("../utils/temp");
|
|
9
9
|
const TaskAbstract_1 = require("./TaskAbstract");
|
|
@@ -51,7 +51,7 @@ class MssqlTask extends TaskAbstract_1.TaskAbstract {
|
|
|
51
51
|
async backup(data) {
|
|
52
52
|
this.verbose = data.options.verbose;
|
|
53
53
|
if (data.package.path)
|
|
54
|
-
throw new
|
|
54
|
+
throw new error_1.AppError(`'package.path' is required: ${data.package.path}`);
|
|
55
55
|
const snapshotPath = await (0, temp_1.mkTmpDir)(exports.mssqlTaskName, "task", "backup", "snapshot");
|
|
56
56
|
const databaseNames = (await this.fetchDatabaseNames()).filter((databaseName) => (!this.config.includeDatabases ||
|
|
57
57
|
(0, micromatch_1.isMatch)(databaseName, this.config.includeDatabases)) &&
|
|
@@ -4,7 +4,7 @@ exports.MysqlDumpTask = exports.mysqlDumpTaskName = void 0;
|
|
|
4
4
|
const async_1 = require("../utils/async");
|
|
5
5
|
const cli_1 = require("../utils/cli");
|
|
6
6
|
const config_1 = require("../utils/datatruck/config");
|
|
7
|
-
const error_1 = require("../utils/
|
|
7
|
+
const error_1 = require("../utils/error");
|
|
8
8
|
const fs_1 = require("../utils/fs");
|
|
9
9
|
const math_1 = require("../utils/math");
|
|
10
10
|
const mysql_1 = require("../utils/mysql");
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.SqlDumpTaskAbstract = void 0;
|
|
4
4
|
const cli_1 = require("../utils/cli");
|
|
5
5
|
const config_1 = require("../utils/datatruck/config");
|
|
6
|
-
const error_1 = require("../utils/
|
|
6
|
+
const error_1 = require("../utils/error");
|
|
7
7
|
const fs_1 = require("../utils/fs");
|
|
8
8
|
const math_1 = require("../utils/math");
|
|
9
9
|
const temp_1 = require("../utils/temp");
|
|
@@ -42,7 +42,7 @@ function parseSqlFile(fileName) {
|
|
|
42
42
|
return { fileName, database: lastName };
|
|
43
43
|
}
|
|
44
44
|
else {
|
|
45
|
-
throw new
|
|
45
|
+
throw new error_1.AppError(`Invalid SQL file type: ${type}`);
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
class SqlDumpTaskAbstract extends TaskAbstract_1.TaskAbstract {
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.AsyncProcess = void 0;
|
|
4
4
|
const cli_1 = require("./cli");
|
|
5
|
+
const error_1 = require("./error");
|
|
5
6
|
const math_1 = require("./math");
|
|
6
7
|
const process_1 = require("./process");
|
|
7
8
|
const stream_1 = require("./stream");
|
|
@@ -22,7 +23,7 @@ function ensureDir(cwd) {
|
|
|
22
23
|
}
|
|
23
24
|
catch (error) { }
|
|
24
25
|
if (!isDir)
|
|
25
|
-
throw new
|
|
26
|
+
throw new error_1.AppError(`Current working directory does not exist: ${cwd}`);
|
|
26
27
|
}
|
|
27
28
|
}
|
|
28
29
|
class StdIn {
|
|
@@ -215,7 +216,7 @@ class AsyncProcess {
|
|
|
215
216
|
else if (result === false) {
|
|
216
217
|
return exitCode;
|
|
217
218
|
}
|
|
218
|
-
return new
|
|
219
|
+
return new error_1.AppError(message, {
|
|
219
220
|
cause: {
|
|
220
221
|
command: this.command,
|
|
221
222
|
argv: this.argv,
|
package/lib/utils/cli.js
CHANGED
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.confirm = exports.stringifyOptions = exports.parseOptions = exports.renderObject = exports.renderListTaskItem = exports.renderError = exports.renderResult = exports.logExec = exports.renderProgressBar = exports.showCursorCommand = void 0;
|
|
7
|
+
const error_1 = require("./error");
|
|
7
8
|
const chalk_1 = __importDefault(require("chalk"));
|
|
8
9
|
const chalk_2 = require("chalk");
|
|
9
10
|
const readline_1 = require("readline");
|
|
@@ -59,20 +60,19 @@ function renderResult(error, color = true) {
|
|
|
59
60
|
}
|
|
60
61
|
exports.renderResult = renderResult;
|
|
61
62
|
function renderError(error, verbose) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
message = error;
|
|
63
|
+
if (!error) {
|
|
64
|
+
return "";
|
|
65
65
|
}
|
|
66
|
-
else if (error) {
|
|
67
|
-
message
|
|
66
|
+
else if (error instanceof error_1.AppError) {
|
|
67
|
+
return chalk_1.default.red(verbose ? error.stack ?? error.message : error.message);
|
|
68
68
|
}
|
|
69
|
-
else {
|
|
70
|
-
return
|
|
69
|
+
else if (error instanceof Error) {
|
|
70
|
+
return chalk_1.default.red(error.stack ?? error.message);
|
|
71
71
|
}
|
|
72
|
-
|
|
73
|
-
message =
|
|
72
|
+
else {
|
|
73
|
+
const message = error.split(/\r?\n/).shift() ?? "";
|
|
74
|
+
return chalk_1.default.red(message.trim());
|
|
74
75
|
}
|
|
75
|
-
return chalk_1.default.red(message.trim());
|
|
76
76
|
}
|
|
77
77
|
exports.renderError = renderError;
|
|
78
78
|
function renderListTaskItem(item, color, config) {
|