@datatruck/cli 0.13.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 +2 -0
- package/Repository/DatatruckRepository.js +239 -108
- 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 +23 -14
- package/Task/MariadbTask.js +9 -4
- package/Task/SqlDumpTaskAbstract.js +31 -10
- package/Task/TaskAbstract.d.ts +10 -5
- package/cli.js +1 -1
- package/config.schema.json +4 -0
- package/migrations/001-initial.sql +12 -6
- package/package.json +1 -1
- package/util/fs-util.d.ts +27 -21
- package/util/fs-util.js +89 -101
- package/util/math-util.js +2 -0
- package/util/process-util.d.ts +1 -0
- package/util/process-util.js +20 -4
- package/util/string-util.d.ts +1 -0
- package/util/string-util.js +8 -1
- package/util/zip-util.d.ts +64 -19
- package/util/zip-util.js +156 -59
|
@@ -14,7 +14,8 @@ CREATE TABLE "backup_session" (
|
|
|
14
14
|
"progressCurrent" INTEGER,
|
|
15
15
|
"progressTotal" INTEGER,
|
|
16
16
|
"progressPercent" INTEGER,
|
|
17
|
-
"
|
|
17
|
+
"progressStepDescription" TEXT,
|
|
18
|
+
"progressStepItem" TEXT,
|
|
18
19
|
"progressStepPercent" INTEGER,
|
|
19
20
|
|
|
20
21
|
"snapshotId" TEXT NOT NULL,
|
|
@@ -35,7 +36,8 @@ CREATE TABLE "backup_session_task" (
|
|
|
35
36
|
"progressCurrent" INTEGER,
|
|
36
37
|
"progressTotal" INTEGER,
|
|
37
38
|
"progressPercent" INTEGER,
|
|
38
|
-
"
|
|
39
|
+
"progressStepDescription" TEXT,
|
|
40
|
+
"progressStepItem" TEXT,
|
|
39
41
|
"progressStepPercent" INTEGER,
|
|
40
42
|
|
|
41
43
|
"sessionId" INTEGER NOT NULL,
|
|
@@ -54,7 +56,8 @@ CREATE TABLE "backup_session_repository" (
|
|
|
54
56
|
"progressCurrent" INTEGER,
|
|
55
57
|
"progressTotal" INTEGER,
|
|
56
58
|
"progressPercent" INTEGER,
|
|
57
|
-
"
|
|
59
|
+
"progressStepDescription" TEXT,
|
|
60
|
+
"progressStepItem" TEXT,
|
|
58
61
|
"progressStepPercent" INTEGER,
|
|
59
62
|
|
|
60
63
|
"sessionId" INTEGER NOT NULL,
|
|
@@ -74,7 +77,8 @@ CREATE TABLE "restore_session" (
|
|
|
74
77
|
"progressCurrent" INTEGER,
|
|
75
78
|
"progressTotal" INTEGER,
|
|
76
79
|
"progressPercent" INTEGER,
|
|
77
|
-
"
|
|
80
|
+
"progressStepDescription" TEXT,
|
|
81
|
+
"progressStepItem" TEXT,
|
|
78
82
|
"progressStepPercent" INTEGER,
|
|
79
83
|
|
|
80
84
|
"snapshotId" TEXT NOT NULL,
|
|
@@ -94,7 +98,8 @@ CREATE TABLE "restore_session_task" (
|
|
|
94
98
|
"progressCurrent" INTEGER,
|
|
95
99
|
"progressTotal" INTEGER,
|
|
96
100
|
"progressPercent" INTEGER,
|
|
97
|
-
"
|
|
101
|
+
"progressStepDescription" TEXT,
|
|
102
|
+
"progressStepItem" TEXT,
|
|
98
103
|
"progressStepPercent" INTEGER,
|
|
99
104
|
|
|
100
105
|
"sessionId" INTEGER NOT NULL,
|
|
@@ -113,7 +118,8 @@ CREATE TABLE "restore_session_repository" (
|
|
|
113
118
|
"progressCurrent" INTEGER,
|
|
114
119
|
"progressTotal" INTEGER,
|
|
115
120
|
"progressPercent" INTEGER,
|
|
116
|
-
"
|
|
121
|
+
"progressStepDescription" TEXT,
|
|
122
|
+
"progressStepItem" TEXT,
|
|
117
123
|
"progressStepPercent" INTEGER,
|
|
118
124
|
|
|
119
125
|
"sessionId" INTEGER NOT NULL,
|
package/package.json
CHANGED
package/util/fs-util.d.ts
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
/// <reference types="node" />
|
|
3
3
|
/// <reference types="node" />
|
|
4
|
-
|
|
4
|
+
/// <reference types="node" />
|
|
5
|
+
import { Dirent, Stats } from "fs";
|
|
6
|
+
import { WriteStream } from "fs";
|
|
5
7
|
import { Interface } from "readline";
|
|
6
8
|
export declare const isWSLSystem: boolean;
|
|
9
|
+
export declare function isEmptyDir(path: string): Promise<boolean>;
|
|
10
|
+
declare type EntryObject = {
|
|
11
|
+
name: string;
|
|
12
|
+
path: string;
|
|
13
|
+
dirent: Dirent;
|
|
14
|
+
stats: Stats;
|
|
15
|
+
};
|
|
16
|
+
export declare function applyPermissions(baseDir: string, permissionsPath: string): Promise<void>;
|
|
17
|
+
export declare function pathIterator(stream: AsyncIterable<string | Buffer>): AsyncIterable<EntryObject>;
|
|
7
18
|
export declare function isLocalDir(path: string): boolean;
|
|
8
19
|
export declare function isDirEmpty(path: string): Promise<boolean>;
|
|
9
20
|
export declare function mkdirIfNotExists(path: string): Promise<string>;
|
|
@@ -28,7 +39,7 @@ export declare function mkTmpDir(prefix: string, id?: string): Promise<string>;
|
|
|
28
39
|
export declare function readPartialFile(path: string, positions: [number, number?]): Promise<string>;
|
|
29
40
|
export declare function checkFile(path: string): Promise<boolean>;
|
|
30
41
|
export declare function checkDir(path: string): Promise<boolean>;
|
|
31
|
-
export declare function readDir(path: string): Promise<string[]>;
|
|
42
|
+
export declare function readDir(path: string, optional?: boolean): Promise<string[]>;
|
|
32
43
|
export declare function forEachFile(dirPath: string, cb: (path: string, dir: boolean) => void, includeDir?: boolean): Promise<void>;
|
|
33
44
|
/**
|
|
34
45
|
* @experimental
|
|
@@ -37,26 +48,10 @@ export declare function fastglobToGitIgnore(patterns: string[], baseDir: string)
|
|
|
37
48
|
export declare function writeGitIgnoreList(options: {
|
|
38
49
|
paths: NodeJS.ReadableStream | string[];
|
|
39
50
|
}): Promise<string>;
|
|
40
|
-
export declare function
|
|
41
|
-
paths: NodeJS.ReadableStream | string[];
|
|
42
|
-
packs?: {
|
|
43
|
-
include: string[];
|
|
44
|
-
exclude?: string[];
|
|
45
|
-
multiple?: boolean;
|
|
46
|
-
}[];
|
|
47
|
-
}): Promise<{
|
|
48
|
-
path: string;
|
|
49
|
-
includedPackPaths: string[];
|
|
50
|
-
excludedPackPaths: string[];
|
|
51
|
-
total: {
|
|
52
|
-
all: number;
|
|
53
|
-
path: number;
|
|
54
|
-
packsPaths: number[];
|
|
55
|
-
multipleStats: Record<string, number>;
|
|
56
|
-
};
|
|
57
|
-
}>;
|
|
51
|
+
export declare function waitForClose(stream: WriteStream): Promise<WriteStream>;
|
|
58
52
|
export declare function copyFileWithStreams(source: string, target: string): Promise<unknown>;
|
|
59
53
|
export declare function updateFileStats(path: string, fileInfo: Stats): Promise<void>;
|
|
54
|
+
export declare function isNotFoundError(error: unknown): boolean;
|
|
60
55
|
export declare function cpy(options: {
|
|
61
56
|
input: {
|
|
62
57
|
type: "glob";
|
|
@@ -77,6 +72,12 @@ export declare function cpy(options: {
|
|
|
77
72
|
* @default 1
|
|
78
73
|
*/
|
|
79
74
|
concurrency?: number;
|
|
75
|
+
skipNotFoundError?: boolean;
|
|
76
|
+
onProgress?: (data: {
|
|
77
|
+
current: number;
|
|
78
|
+
path?: string;
|
|
79
|
+
type?: "start" | "end";
|
|
80
|
+
}) => Promise<boolean | void>;
|
|
80
81
|
onPath?: (data: {
|
|
81
82
|
isDir: boolean;
|
|
82
83
|
entryPath: string;
|
|
@@ -88,4 +89,9 @@ export declare function cpy(options: {
|
|
|
88
89
|
dirs: number;
|
|
89
90
|
};
|
|
90
91
|
}) => Promise<boolean | void>;
|
|
91
|
-
}): Promise<
|
|
92
|
+
}): Promise<{
|
|
93
|
+
paths: number;
|
|
94
|
+
files: number;
|
|
95
|
+
dirs: number;
|
|
96
|
+
}>;
|
|
97
|
+
export {};
|
package/util/fs-util.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.cpy = exports.updateFileStats = exports.copyFileWithStreams = exports.
|
|
6
|
+
exports.cpy = exports.isNotFoundError = exports.updateFileStats = exports.copyFileWithStreams = exports.waitForClose = exports.writeGitIgnoreList = exports.fastglobToGitIgnore = exports.forEachFile = exports.readDir = exports.checkDir = exports.checkFile = exports.readPartialFile = exports.mkTmpDir = exports.fastFolderSizeAsync = exports.tmpDir = exports.sessionTmpDir = exports.parentTmpDir = exports.existsFile = exports.findFile = exports.parsePackageFile = exports.parseFile = exports.parseFileExtensions = exports.readdirIfExists = exports.writeJSONFile = exports.existsDir = exports.ensureEmptyDir = exports.mkdirIfNotExists = exports.isDirEmpty = exports.isLocalDir = exports.pathIterator = exports.applyPermissions = exports.isEmptyDir = exports.isWSLSystem = void 0;
|
|
7
7
|
const globalData_1 = __importDefault(require("../globalData"));
|
|
8
8
|
const path_util_1 = require("./path-util");
|
|
9
9
|
const async_1 = require("async");
|
|
@@ -13,13 +13,49 @@ const fast_glob_1 = __importDefault(require("fast-glob"));
|
|
|
13
13
|
const fs_1 = require("fs");
|
|
14
14
|
const fs_2 = require("fs");
|
|
15
15
|
const promises_1 = require("fs/promises");
|
|
16
|
-
const micromatch_1 = require("micromatch");
|
|
17
16
|
const os_1 = require("os");
|
|
18
17
|
const path_1 = require("path");
|
|
19
18
|
const path_2 = require("path");
|
|
20
19
|
const readline_1 = require("readline");
|
|
21
20
|
const util_1 = require("util");
|
|
22
21
|
exports.isWSLSystem = (0, os_1.release)().includes("microsoft-standard-WSL");
|
|
22
|
+
async function isEmptyDir(path) {
|
|
23
|
+
const iterator = await (0, promises_1.opendir)(path);
|
|
24
|
+
let done = false;
|
|
25
|
+
try {
|
|
26
|
+
const next = await iterator[Symbol.asyncIterator]().next();
|
|
27
|
+
done = !!next.done;
|
|
28
|
+
return done;
|
|
29
|
+
}
|
|
30
|
+
finally {
|
|
31
|
+
if (!done) {
|
|
32
|
+
await iterator.close();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.isEmptyDir = isEmptyDir;
|
|
37
|
+
async function applyPermissions(baseDir, permissionsPath) {
|
|
38
|
+
const singleReader = (0, readline_1.createInterface)({
|
|
39
|
+
input: (0, fs_1.createReadStream)(permissionsPath),
|
|
40
|
+
});
|
|
41
|
+
for await (const line of singleReader) {
|
|
42
|
+
const [rpath, rawUid, rawGui, rawMode] = line.split(":");
|
|
43
|
+
const path = (0, path_1.join)(baseDir, rpath);
|
|
44
|
+
if (!path.startsWith(baseDir)) {
|
|
45
|
+
throw new Error(`Entry path is out of the base dir: (${path}, ${baseDir})`);
|
|
46
|
+
}
|
|
47
|
+
const uid = Number(rawUid);
|
|
48
|
+
const guid = Number(rawGui);
|
|
49
|
+
await (0, promises_1.chown)(path, uid, guid);
|
|
50
|
+
const mode = Number(rawMode);
|
|
51
|
+
await (0, promises_1.chmod)(path, mode);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.applyPermissions = applyPermissions;
|
|
55
|
+
function pathIterator(stream) {
|
|
56
|
+
return stream;
|
|
57
|
+
}
|
|
58
|
+
exports.pathIterator = pathIterator;
|
|
23
59
|
function isLocalDir(path) {
|
|
24
60
|
return /^[\/\.]|([A-Z]:)/i.test(path);
|
|
25
61
|
}
|
|
@@ -59,9 +95,7 @@ async function writeJSONFile(path, json) {
|
|
|
59
95
|
}
|
|
60
96
|
exports.writeJSONFile = writeJSONFile;
|
|
61
97
|
async function readdirIfExists(path) {
|
|
62
|
-
|
|
63
|
-
return [];
|
|
64
|
-
return await readDir(path);
|
|
98
|
+
return await readDir(path, true);
|
|
65
99
|
}
|
|
66
100
|
exports.readdirIfExists = readdirIfExists;
|
|
67
101
|
exports.parseFileExtensions = ["json", "js", "ts", "yaml", "yml"];
|
|
@@ -187,13 +221,15 @@ async function checkDir(path) {
|
|
|
187
221
|
}
|
|
188
222
|
}
|
|
189
223
|
exports.checkDir = checkDir;
|
|
190
|
-
async function readDir(path) {
|
|
224
|
+
async function readDir(path, optional) {
|
|
191
225
|
try {
|
|
192
226
|
return await (0, promises_1.readdir)(path);
|
|
193
227
|
}
|
|
194
228
|
catch (anyError) {
|
|
195
229
|
const nodeError = anyError;
|
|
196
230
|
if (nodeError.code === "ENOENT") {
|
|
231
|
+
if (optional)
|
|
232
|
+
return [];
|
|
197
233
|
const error = new Error(nodeError.message);
|
|
198
234
|
error.code = nodeError.code;
|
|
199
235
|
error.errno = nodeError.errno;
|
|
@@ -262,93 +298,14 @@ async function writeGitIgnoreList(options) {
|
|
|
262
298
|
return path;
|
|
263
299
|
}
|
|
264
300
|
exports.writeGitIgnoreList = writeGitIgnoreList;
|
|
265
|
-
async function
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
const multipleStats = {};
|
|
272
|
-
const total = new Array((options.packs?.length || 0) + 1).fill(0);
|
|
273
|
-
await Promise.all([
|
|
274
|
-
...new Array((options.packs?.length || 0) + 1).fill(null).map((_, index) => new Promise((resolve, reject) => {
|
|
275
|
-
const path = (0, path_1.join)(tempDir, `${index}-included.txt`);
|
|
276
|
-
const stream = (0, fs_2.createWriteStream)(path);
|
|
277
|
-
includedPaths.push(path);
|
|
278
|
-
included.push(stream);
|
|
279
|
-
stream.on("close", resolve);
|
|
280
|
-
stream.on("error", reject);
|
|
281
|
-
})),
|
|
282
|
-
...new Array(options.packs?.length || 0).fill(null).map((_, index) => new Promise((resolve, reject) => {
|
|
283
|
-
const path = (0, path_1.join)(tempDir, `${index}-excluded.txt`);
|
|
284
|
-
const stream = (0, fs_2.createWriteStream)(path);
|
|
285
|
-
excludedPaths.push(path);
|
|
286
|
-
excluded.push(stream);
|
|
287
|
-
stream.on("close", resolve);
|
|
288
|
-
stream.on("error", reject);
|
|
289
|
-
})),
|
|
290
|
-
new Promise(async (resolve) => {
|
|
291
|
-
const packDirectories = [];
|
|
292
|
-
for await (const value of options.paths) {
|
|
293
|
-
const entry = value.toString();
|
|
294
|
-
const isDir = entry.endsWith("/");
|
|
295
|
-
const matchEntry = isDir ? entry.slice(0, -1) : entry;
|
|
296
|
-
let packIndex = 1;
|
|
297
|
-
let matches = false;
|
|
298
|
-
for (const pack of options.packs || []) {
|
|
299
|
-
if ((0, micromatch_1.isMatch)(matchEntry, pack.include) &&
|
|
300
|
-
(!pack.exclude || !(0, micromatch_1.isMatch)(matchEntry, pack.exclude))) {
|
|
301
|
-
if (isDir)
|
|
302
|
-
packDirectories.push([packIndex - 1, entry]);
|
|
303
|
-
included[packIndex].write(`${entry}\n`);
|
|
304
|
-
if (!isDir)
|
|
305
|
-
total[packIndex]++;
|
|
306
|
-
matches = true;
|
|
307
|
-
break;
|
|
308
|
-
}
|
|
309
|
-
packIndex++;
|
|
310
|
-
}
|
|
311
|
-
if (!matches) {
|
|
312
|
-
const packDir = packDirectories.find(([, p]) => entry.startsWith(p));
|
|
313
|
-
if (packDir) {
|
|
314
|
-
const [i, v] = packDir;
|
|
315
|
-
const multipleExclude = options.packs?.[i].exclude;
|
|
316
|
-
if (multipleExclude && (0, micromatch_1.isMatch)(matchEntry, multipleExclude)) {
|
|
317
|
-
included[0].write(`${entry}\n`);
|
|
318
|
-
excluded[i].write(`${entry}\n`);
|
|
319
|
-
}
|
|
320
|
-
else {
|
|
321
|
-
if (!multipleStats[v])
|
|
322
|
-
multipleStats[v] = 0;
|
|
323
|
-
multipleStats[v]++;
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
else {
|
|
327
|
-
included[0].write(`${entry}\n`);
|
|
328
|
-
}
|
|
329
|
-
if (!isDir)
|
|
330
|
-
total[0]++;
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
for (const stream of [...included, ...excluded]) {
|
|
334
|
-
stream.end();
|
|
335
|
-
}
|
|
336
|
-
resolve();
|
|
337
|
-
}),
|
|
338
|
-
]);
|
|
339
|
-
return {
|
|
340
|
-
path: includedPaths[0],
|
|
341
|
-
includedPackPaths: includedPaths.slice(1),
|
|
342
|
-
excludedPackPaths: excludedPaths,
|
|
343
|
-
total: {
|
|
344
|
-
all: total.reduce((p, v) => p + v, 0),
|
|
345
|
-
path: total[0],
|
|
346
|
-
packsPaths: total.slice(1),
|
|
347
|
-
multipleStats,
|
|
348
|
-
},
|
|
349
|
-
};
|
|
301
|
+
async function waitForClose(stream) {
|
|
302
|
+
return new Promise(async (resolve, reject) => {
|
|
303
|
+
stream.on("close", resolve);
|
|
304
|
+
stream.on("error", reject);
|
|
305
|
+
return stream;
|
|
306
|
+
});
|
|
350
307
|
}
|
|
351
|
-
exports.
|
|
308
|
+
exports.waitForClose = waitForClose;
|
|
352
309
|
async function copyFileWithStreams(source, target) {
|
|
353
310
|
const r = (0, fs_1.createReadStream)(source);
|
|
354
311
|
const w = (0, fs_2.createWriteStream)(target);
|
|
@@ -373,6 +330,10 @@ async function updateFileStats(path, fileInfo) {
|
|
|
373
330
|
await (0, promises_1.chown)(path, fileInfo.uid, fileInfo.gid);
|
|
374
331
|
}
|
|
375
332
|
exports.updateFileStats = updateFileStats;
|
|
333
|
+
function isNotFoundError(error) {
|
|
334
|
+
return error.code === "ENOENT";
|
|
335
|
+
}
|
|
336
|
+
exports.isNotFoundError = isNotFoundError;
|
|
376
337
|
async function cpy(options) {
|
|
377
338
|
const stats = { paths: 0, files: 0, dirs: 0 };
|
|
378
339
|
const dirs = new Set();
|
|
@@ -387,6 +348,7 @@ async function cpy(options) {
|
|
|
387
348
|
}
|
|
388
349
|
};
|
|
389
350
|
const task = async (rawEntryPath, basePath) => {
|
|
351
|
+
[rawEntryPath] = rawEntryPath.split(":");
|
|
390
352
|
const isDir = rawEntryPath.endsWith("/");
|
|
391
353
|
const entryPath = (0, path_1.normalize)(rawEntryPath);
|
|
392
354
|
const entrySourcePath = (0, path_1.resolve)((0, path_1.join)(basePath, rawEntryPath));
|
|
@@ -407,20 +369,41 @@ async function cpy(options) {
|
|
|
407
369
|
else {
|
|
408
370
|
const dir = (0, path_1.dirname)(entryTargetPath);
|
|
409
371
|
await makeRecursiveDir(dir);
|
|
372
|
+
await options.onProgress?.({
|
|
373
|
+
current: stats.files,
|
|
374
|
+
path: entryPath,
|
|
375
|
+
});
|
|
410
376
|
stats.files++;
|
|
411
377
|
// https://github.com/nodejs/node/issues/44261
|
|
412
378
|
if (exports.isWSLSystem) {
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
379
|
+
let fileInfo;
|
|
380
|
+
try {
|
|
381
|
+
fileInfo = await (0, promises_1.stat)(entrySourcePath);
|
|
382
|
+
}
|
|
383
|
+
catch (error) {
|
|
384
|
+
const skipError = options.skipNotFoundError && isNotFoundError(error);
|
|
385
|
+
if (!skipError)
|
|
386
|
+
throw error;
|
|
387
|
+
}
|
|
388
|
+
if (fileInfo) {
|
|
389
|
+
const isWritable = (fileInfo.mode & 0o200) === 0o200;
|
|
390
|
+
if (!isWritable) {
|
|
391
|
+
await copyFileWithStreams(entrySourcePath, entryTargetPath);
|
|
392
|
+
await updateFileStats(entryTargetPath, fileInfo);
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
419
395
|
}
|
|
420
396
|
}
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
397
|
+
try {
|
|
398
|
+
await (0, promises_1.cp)(entrySourcePath, entryTargetPath, {
|
|
399
|
+
preserveTimestamps: true,
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
catch (error) {
|
|
403
|
+
const skipError = options.skipNotFoundError && isNotFoundError(error);
|
|
404
|
+
if (!skipError)
|
|
405
|
+
throw error;
|
|
406
|
+
}
|
|
424
407
|
}
|
|
425
408
|
};
|
|
426
409
|
const { input } = options;
|
|
@@ -450,5 +433,10 @@ async function cpy(options) {
|
|
|
450
433
|
},
|
|
451
434
|
});
|
|
452
435
|
}
|
|
436
|
+
await options.onProgress?.({
|
|
437
|
+
current: stats.files,
|
|
438
|
+
type: "end",
|
|
439
|
+
});
|
|
440
|
+
return stats;
|
|
453
441
|
}
|
|
454
442
|
exports.cpy = cpy;
|
package/util/math-util.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.progressPercent = void 0;
|
|
4
4
|
function progressPercent(total, current) {
|
|
5
|
+
if (total === 0 && current === 0)
|
|
6
|
+
return 0;
|
|
5
7
|
return Number(((current / total) * 100).toFixed(2));
|
|
6
8
|
}
|
|
7
9
|
exports.progressPercent = progressPercent;
|
package/util/process-util.d.ts
CHANGED
package/util/process-util.js
CHANGED
|
@@ -11,6 +11,7 @@ const chalk_1 = __importDefault(require("chalk"));
|
|
|
11
11
|
const child_process_1 = require("child_process");
|
|
12
12
|
const fs_1 = require("fs");
|
|
13
13
|
const promises_1 = require("fs/promises");
|
|
14
|
+
const readline_1 = require("readline");
|
|
14
15
|
function logExecStdout(input) {
|
|
15
16
|
let text = input.colorize ? chalk_1.default.grey(input.data) : input.data;
|
|
16
17
|
if (input.lineSalt)
|
|
@@ -70,7 +71,11 @@ async function exec(command, argv = [], options = null, settings = {}) {
|
|
|
70
71
|
stderr: "",
|
|
71
72
|
exitCode: 0,
|
|
72
73
|
};
|
|
73
|
-
let finishListeners =
|
|
74
|
+
let finishListeners = 1;
|
|
75
|
+
if (pipe?.stream instanceof fs_1.WriteStream)
|
|
76
|
+
finishListeners++;
|
|
77
|
+
if (settings.stdout?.parseLines)
|
|
78
|
+
finishListeners++;
|
|
74
79
|
let streamError;
|
|
75
80
|
const tryFinish = () => {
|
|
76
81
|
if (!--finishListeners)
|
|
@@ -129,10 +134,11 @@ async function exec(command, argv = [], options = null, settings = {}) {
|
|
|
129
134
|
if (log.stdout || settings.stdout) {
|
|
130
135
|
if (!p.stdout)
|
|
131
136
|
throw new Error(`stdout is not defined`);
|
|
132
|
-
|
|
137
|
+
const parseLines = settings.stdout?.parseLines;
|
|
138
|
+
const onData = (data) => {
|
|
133
139
|
if (log.stdout)
|
|
134
140
|
logExecStdout({
|
|
135
|
-
data: data.toString(),
|
|
141
|
+
data: parseLines ? `${data}\n` : data.toString(),
|
|
136
142
|
stderr: log.allToStderr,
|
|
137
143
|
colorize: log.colorize,
|
|
138
144
|
});
|
|
@@ -140,7 +146,17 @@ async function exec(command, argv = [], options = null, settings = {}) {
|
|
|
140
146
|
spawnData.stdout += data.toString();
|
|
141
147
|
if (settings.stdout?.onData)
|
|
142
148
|
settings.stdout.onData(data.toString());
|
|
143
|
-
}
|
|
149
|
+
};
|
|
150
|
+
if (parseLines) {
|
|
151
|
+
const rl = (0, readline_1.createInterface)({
|
|
152
|
+
input: p.stdout,
|
|
153
|
+
});
|
|
154
|
+
rl.on("line", onData);
|
|
155
|
+
rl.on("close", tryFinish);
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
p.stdout.on("data", onData);
|
|
159
|
+
}
|
|
144
160
|
}
|
|
145
161
|
if (log.stderr || settings.stderr) {
|
|
146
162
|
if (!p.stderr)
|
package/util/string-util.d.ts
CHANGED
|
@@ -15,5 +15,6 @@ export declare type UriType = {
|
|
|
15
15
|
export declare function formatUri(input: UriType, hidePassword?: boolean): string;
|
|
16
16
|
export declare function formatSeconds(seconds: number): string;
|
|
17
17
|
export declare function makePathPatterns(values: string[] | undefined): string[] | undefined;
|
|
18
|
+
export declare function checkPath(path: string, include: string[], exclude?: string[]): boolean;
|
|
18
19
|
export declare function checkMatch(subject: string | undefined, patterns: string[]): boolean;
|
|
19
20
|
export declare function formatDateTime(datetime: string): string;
|
package/util/string-util.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.formatDateTime = exports.checkMatch = exports.makePathPatterns = exports.formatSeconds = exports.formatUri = exports.parseStringList = exports.render = exports.snakeCase = exports.lcfirst = exports.ucfirst = exports.serialize = void 0;
|
|
3
|
+
exports.formatDateTime = exports.checkMatch = exports.checkPath = exports.makePathPatterns = exports.formatSeconds = exports.formatUri = exports.parseStringList = exports.render = exports.snakeCase = exports.lcfirst = exports.ucfirst = exports.serialize = void 0;
|
|
4
4
|
const AppError_1 = require("../Error/AppError");
|
|
5
5
|
const micromatch_1 = require("micromatch");
|
|
6
6
|
function serialize(message, data) {
|
|
@@ -99,6 +99,13 @@ function makePathPatterns(values) {
|
|
|
99
99
|
});
|
|
100
100
|
}
|
|
101
101
|
exports.makePathPatterns = makePathPatterns;
|
|
102
|
+
function checkPath(path, include, exclude) {
|
|
103
|
+
return ((0, micromatch_1.isMatch)(path, include, {
|
|
104
|
+
dot: true,
|
|
105
|
+
}) &&
|
|
106
|
+
(!exclude || !(0, micromatch_1.isMatch)(path, exclude, { dot: true })));
|
|
107
|
+
}
|
|
108
|
+
exports.checkPath = checkPath;
|
|
102
109
|
function checkMatch(subject, patterns) {
|
|
103
110
|
if (!subject?.length)
|
|
104
111
|
subject = "<empty>";
|
package/util/zip-util.d.ts
CHANGED
|
@@ -3,20 +3,6 @@ export interface ZipDataFilterType {
|
|
|
3
3
|
exclude?: boolean;
|
|
4
4
|
patterns: string[];
|
|
5
5
|
}
|
|
6
|
-
export declare type ZipStreamDataType = {
|
|
7
|
-
type: "progress";
|
|
8
|
-
data: {
|
|
9
|
-
progress: number;
|
|
10
|
-
files: number;
|
|
11
|
-
path: string;
|
|
12
|
-
};
|
|
13
|
-
} | {
|
|
14
|
-
type: "summary";
|
|
15
|
-
data: {
|
|
16
|
-
folders: number;
|
|
17
|
-
files: number;
|
|
18
|
-
};
|
|
19
|
-
};
|
|
20
6
|
export interface ZipDataType {
|
|
21
7
|
command?: string;
|
|
22
8
|
path: string;
|
|
@@ -26,7 +12,14 @@ export interface ZipDataType {
|
|
|
26
12
|
includeList?: string;
|
|
27
13
|
excludeList?: string;
|
|
28
14
|
verbose?: boolean;
|
|
29
|
-
|
|
15
|
+
onProgress?: (data: {
|
|
16
|
+
percent: number;
|
|
17
|
+
total: number;
|
|
18
|
+
current: number;
|
|
19
|
+
path?: string;
|
|
20
|
+
type?: "start" | "end";
|
|
21
|
+
}) => void | Promise<void>;
|
|
22
|
+
onStream?: (data: ZipStream) => void | Promise<void>;
|
|
30
23
|
}
|
|
31
24
|
export interface UnzipDataType {
|
|
32
25
|
command?: string;
|
|
@@ -34,19 +27,71 @@ export interface UnzipDataType {
|
|
|
34
27
|
files?: (ZipDataFilterType | string)[];
|
|
35
28
|
output: string;
|
|
36
29
|
verbose?: boolean;
|
|
37
|
-
|
|
30
|
+
onProgress?: (data: {
|
|
31
|
+
percent: number;
|
|
32
|
+
current: number;
|
|
33
|
+
path?: string;
|
|
34
|
+
type?: "start" | "end";
|
|
35
|
+
}) => void | Promise<void>;
|
|
36
|
+
onStream?: (data: UnzipStream) => void | Promise<void>;
|
|
38
37
|
}
|
|
39
|
-
export declare
|
|
38
|
+
export declare function buildArguments(filters: (ZipDataFilterType | string)[]): string[];
|
|
39
|
+
export declare function checkSSEOption(command?: string): Promise<boolean>;
|
|
40
|
+
declare type ListZipStream = {
|
|
41
|
+
Path?: string;
|
|
42
|
+
Folder?: string;
|
|
43
|
+
Size?: string;
|
|
44
|
+
"Packed Size"?: string;
|
|
45
|
+
Modified?: string;
|
|
46
|
+
Created?: string;
|
|
47
|
+
Accessed?: string;
|
|
48
|
+
Attributes?: string;
|
|
49
|
+
Encrypted?: string;
|
|
50
|
+
Comment?: string;
|
|
51
|
+
CRC?: string;
|
|
52
|
+
Method?: string;
|
|
53
|
+
Characteristics?: string;
|
|
54
|
+
"Host OS"?: string;
|
|
55
|
+
Version?: string;
|
|
56
|
+
Volume?: string;
|
|
57
|
+
Offset?: string;
|
|
58
|
+
};
|
|
59
|
+
export declare function listZip(data: {
|
|
60
|
+
command?: string;
|
|
61
|
+
path: string;
|
|
62
|
+
onStream: (item: ListZipStream) => Promise<void>;
|
|
63
|
+
verbose?: boolean;
|
|
64
|
+
}): Promise<void>;
|
|
65
|
+
export declare type ZipStream = {
|
|
40
66
|
type: "progress";
|
|
41
67
|
data: {
|
|
42
68
|
progress: number;
|
|
43
69
|
files: number;
|
|
44
70
|
path: string;
|
|
45
71
|
};
|
|
72
|
+
} | {
|
|
73
|
+
type: "summary";
|
|
74
|
+
data: {
|
|
75
|
+
folders: number;
|
|
76
|
+
files: number;
|
|
77
|
+
};
|
|
46
78
|
};
|
|
47
|
-
export declare function buildArguments(filters: (ZipDataFilterType | string)[]): string[];
|
|
48
79
|
export declare function zip(data: ZipDataType): Promise<{
|
|
49
80
|
folders: number;
|
|
50
81
|
files: number;
|
|
51
82
|
}>;
|
|
52
|
-
export declare
|
|
83
|
+
export declare type UnzipStream = {
|
|
84
|
+
type: "progress";
|
|
85
|
+
data: {
|
|
86
|
+
percent: number;
|
|
87
|
+
files: number;
|
|
88
|
+
path: string;
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
export declare function unzip(data: UnzipDataType): Promise<{
|
|
92
|
+
files: number;
|
|
93
|
+
stdout: string;
|
|
94
|
+
stderr: string;
|
|
95
|
+
exitCode: number;
|
|
96
|
+
}>;
|
|
97
|
+
export {};
|