@datatruck/cli 0.5.0 → 0.7.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.
Files changed (56) hide show
  1. package/Action/BackupAction.d.ts +1 -0
  2. package/Action/BackupAction.js +4 -1
  3. package/Action/RestoreAction.d.ts +1 -0
  4. package/CHANGELOG.md +40 -0
  5. package/Command/BackupCommand.d.ts +1 -0
  6. package/Command/BackupCommand.js +8 -2
  7. package/Command/BackupSessionsCommand.js +1 -1
  8. package/Command/ConfigCommand.d.ts +1 -0
  9. package/Command/ConfigCommand.js +7 -1
  10. package/Command/InitCommand.js +1 -1
  11. package/Command/PruneCommand.js +2 -2
  12. package/Command/RestoreCommand.d.ts +1 -0
  13. package/Command/RestoreCommand.js +8 -2
  14. package/Command/RestoreSessionsCommand.js +1 -1
  15. package/Command/SnapshotsCommand.js +1 -1
  16. package/Repository/GitRepository.js +2 -3
  17. package/Repository/LocalRepository.d.ts +4 -0
  18. package/Repository/LocalRepository.js +38 -37
  19. package/Repository/RepositoryAbstract.d.ts +4 -4
  20. package/Repository/ResticRepository.js +30 -9
  21. package/SessionDriver/ConsoleSessionDriver.d.ts +6 -2
  22. package/SessionDriver/ConsoleSessionDriver.js +31 -40
  23. package/SessionDriver/SessionDriverAbstract.d.ts +1 -1
  24. package/SessionDriver/SessionDriverAbstract.js +1 -1
  25. package/SessionManager/BackupSessionManager.d.ts +1 -1
  26. package/SessionManager/BackupSessionManager.js +2 -2
  27. package/Task/GitTask.d.ts +4 -0
  28. package/Task/GitTask.js +28 -29
  29. package/Task/MariadbTask.js +27 -15
  30. package/Task/MssqlTask.js +1 -2
  31. package/Task/MysqlDumpTask.d.ts +1 -1
  32. package/Task/MysqlDumpTask.js +4 -2
  33. package/Task/PostgresqlDumpTask.d.ts +1 -1
  34. package/Task/PostgresqlDumpTask.js +2 -4
  35. package/Task/SqlDumpTaskAbstract.d.ts +1 -2
  36. package/Task/SqlDumpTaskAbstract.js +60 -17
  37. package/Task/TaskAbstract.d.ts +4 -4
  38. package/config.schema.json +8 -0
  39. package/package.json +2 -2
  40. package/util/GitUtil.js +2 -2
  41. package/util/ResticUtil.d.ts +1 -1
  42. package/util/ResticUtil.js +3 -4
  43. package/util/cli-util.d.ts +1 -0
  44. package/util/cli-util.js +13 -1
  45. package/util/datatruck/config-util.d.ts +1 -0
  46. package/util/datatruck/config-util.js +3 -0
  47. package/util/date-util.d.ts +4 -0
  48. package/util/date-util.js +17 -1
  49. package/util/fs-util.d.ts +33 -0
  50. package/util/fs-util.js +73 -4
  51. package/util/process-util.d.ts +2 -2
  52. package/util/process-util.js +6 -6
  53. package/util/string-util.d.ts +1 -0
  54. package/util/string-util.js +21 -1
  55. package/util/zip-util.d.ts +2 -2
  56. package/util/zip-util.js +9 -9
@@ -10,6 +10,7 @@ export declare type BackupActionOptionsType = {
10
10
  repositoryNames?: string[];
11
11
  repositoryTypes?: string[];
12
12
  packageNames?: string[];
13
+ packageTaskNames?: string[];
13
14
  tags?: string[];
14
15
  dryRun?: boolean;
15
16
  verbose?: boolean;
@@ -21,6 +21,7 @@ class BackupAction {
21
21
  await session.initDrivers();
22
22
  let packages = (0, config_util_1.filterPackages)(this.config, {
23
23
  packageNames: this.options.packageNames,
24
+ packageTaskNames: this.options.packageTaskNames,
24
25
  repositoryNames: this.options.repositoryNames,
25
26
  repositoryTypes: this.options.repositoryTypes,
26
27
  sourceAction: "backup",
@@ -193,7 +194,9 @@ class BackupAction {
193
194
  error: error?.message,
194
195
  });
195
196
  }
196
- await session.endDrivers();
197
+ await session.endDrivers({
198
+ snapshotId: snapshot.id.slice(0, 8),
199
+ });
197
200
  return {
198
201
  total: total,
199
202
  errors: errors,
@@ -10,6 +10,7 @@ export declare type RestoreActionOptionsType = {
10
10
  snapshotId: string;
11
11
  tags?: string[];
12
12
  packageNames?: string[];
13
+ packageTaskNames?: string[];
13
14
  repositoryNames?: string[];
14
15
  repositoryTypes?: string[];
15
16
  verbose?: boolean;
package/CHANGELOG.md CHANGED
@@ -1,5 +1,45 @@
1
1
  # @datatruck/cli
2
2
 
3
+ ## 0.7.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`3b8d6da`](https://github.com/swordev/datatruck/commit/3b8d6da01495799aceb848a63b35b8c46a7d1b0e) Thanks [@juanrgm](https://github.com/juanrgm)! - Add `--package-task` cli option
8
+
9
+ * [`69b34a0`](https://github.com/swordev/datatruck/commit/69b34a02b9cade48df2b071a92a8f79d5cfec23e) Thanks [@juanrgm](https://github.com/juanrgm)! - Allow restore multiple backups over the same database
10
+
11
+ - [`69caf26`](https://github.com/swordev/datatruck/commit/69caf26881272331bd4c8d7d345b3b85d33e33ac) Thanks [@juanrgm](https://github.com/juanrgm)! - Add cli short option to `--tag`
12
+
13
+ * [`377f0de`](https://github.com/swordev/datatruck/commit/377f0de345c9c8f45c772ac47e4ded81e91725d7) Thanks [@juanrgm](https://github.com/juanrgm)! - Rename cli short option to `-rt`
14
+
15
+ ### Patch Changes
16
+
17
+ - [`c03200a`](https://github.com/swordev/datatruck/commit/c03200a6347d1e9f9fdad86dcb22df30bbefcab4) Thanks [@juanrgm](https://github.com/juanrgm)! - Fix `sql-dump` tasks
18
+
19
+ * [`f56a4bc`](https://github.com/swordev/datatruck/commit/f56a4bcb429a674c13f32de73985cd67eb1acc23) Thanks [@juanrgm](https://github.com/juanrgm)! - Show full error message
20
+
21
+ - [`4324422`](https://github.com/swordev/datatruck/commit/4324422550474619811a8d455af55bc6e3b08aeb) Thanks [@juanrgm](https://github.com/juanrgm)! - Use connection port in `mysql-dump` task
22
+
23
+ ## 0.6.1
24
+
25
+ ### Patch Changes
26
+
27
+ - [`0ba6229`](https://github.com/swordev/datatruck/commit/0ba6229348c109a59783e72242ab7c0e61f25e36) Thanks [@juanrgm](https://github.com/juanrgm)! - Fix progress bar in restic repository
28
+
29
+ ## 0.6.0
30
+
31
+ ### Minor Changes
32
+
33
+ - [`0c6877d`](https://github.com/swordev/datatruck/commit/0c6877d189761e75dd434b0a8d72b71621d024de) Thanks [@juanrgm](https://github.com/juanrgm)! - Show more progress stats
34
+
35
+ * [`751e1f6`](https://github.com/swordev/datatruck/commit/751e1f6d6b33d3fa96eb40d998fdd140ce0e3875) Thanks [@juanrgm](https://github.com/juanrgm)! - Add `fileCopyConcurrency` option
36
+
37
+ - [`05487e6`](https://github.com/swordev/datatruck/commit/05487e6a33f875a3afb7ff0815b16da6f2a41301) Thanks [@juanrgm](https://github.com/juanrgm)! - Parse InnoDB error in `MariadbTask` to avoid infinite wait
38
+
39
+ ### Patch Changes
40
+
41
+ - [`b62a6f8`](https://github.com/swordev/datatruck/commit/b62a6f8a82409339afd65d4f96476eb57bbfb5a2) Thanks [@juanrgm](https://github.com/juanrgm)! - Resolve target/restore path in local repository
42
+
3
43
  ## 0.5.0
4
44
 
5
45
  ### Minor Changes
@@ -3,6 +3,7 @@ import { If } from "../util/ts-util";
3
3
  import { CommandAbstract } from "./CommandAbstract";
4
4
  export declare type BackupCommandOptionsType<TResolved = false> = {
5
5
  package?: If<TResolved, string[]>;
6
+ packageTask?: If<TResolved, string[]>;
6
7
  repository?: If<TResolved, string[]>;
7
8
  repositoryType?: If<TResolved, RepositoryConfigType["type"][]>;
8
9
  tag?: If<TResolved, string[]>;
@@ -21,6 +21,11 @@ class BackupCommand extends CommandAbstract_1.CommandAbstract {
21
21
  option: "-p,--package <values>",
22
22
  parser: string_util_1.parseStringList,
23
23
  },
24
+ packageTask: {
25
+ description: "Package task names",
26
+ option: "-pt,--package-task <values>",
27
+ parser: string_util_1.parseStringList,
28
+ },
24
29
  repository: {
25
30
  description: "Repository names",
26
31
  option: "-r,--repository <values>",
@@ -28,12 +33,12 @@ class BackupCommand extends CommandAbstract_1.CommandAbstract {
28
33
  },
29
34
  repositoryType: {
30
35
  description: "Repository types",
31
- option: "-t,--repository-type <values>",
36
+ option: "-rt,--repository-type <values>",
32
37
  parser: (v) => (0, string_util_1.parseStringList)(v),
33
38
  },
34
39
  tag: {
35
40
  description: "Tags",
36
- option: "--tag <values>",
41
+ option: "-t,--tag <values>",
37
42
  parser: string_util_1.parseStringList,
38
43
  },
39
44
  date: {
@@ -47,6 +52,7 @@ class BackupCommand extends CommandAbstract_1.CommandAbstract {
47
52
  const config = await ConfigAction_1.ConfigAction.fromGlobalOptions(this.globalOptions);
48
53
  const backup = new BackupAction_1.BackupAction(config, {
49
54
  packageNames: this.options.package,
55
+ packageTaskNames: this.options.packageTask,
50
56
  repositoryNames: this.options.repository,
51
57
  repositoryTypes: this.options.repositoryType,
52
58
  tags: this.options.tag,
@@ -24,7 +24,7 @@ class BackupSessionsCommand extends CommandAbstract_1.CommandAbstract {
24
24
  },
25
25
  tag: {
26
26
  description: "Tags",
27
- option: "--tag <values>",
27
+ option: "-t,--tag <values>",
28
28
  parser: string_util_1.parseStringList,
29
29
  },
30
30
  limit: {
@@ -3,6 +3,7 @@ import { If } from "../util/ts-util";
3
3
  import { CommandAbstract } from "./CommandAbstract";
4
4
  export declare type ConfigCommandOptionsType<TResolved = false> = {
5
5
  package?: If<TResolved, string[]>;
6
+ packageTask?: If<TResolved, string[]>;
6
7
  repository?: If<TResolved, string[]>;
7
8
  repositoryType?: If<TResolved, RepositoryConfigType["type"][]>;
8
9
  };
@@ -14,6 +14,11 @@ class ConfigCommand extends CommandAbstract_1.CommandAbstract {
14
14
  option: "-p,--package <values>",
15
15
  parser: string_util_1.parseStringList,
16
16
  },
17
+ packageTask: {
18
+ description: "Package task names",
19
+ option: "-pt,--package-task <values>",
20
+ parser: string_util_1.parseStringList,
21
+ },
17
22
  repository: {
18
23
  description: "Repository names",
19
24
  option: "-r,--repository <values>",
@@ -21,7 +26,7 @@ class ConfigCommand extends CommandAbstract_1.CommandAbstract {
21
26
  },
22
27
  repositoryType: {
23
28
  description: "Repository types",
24
- option: "-t,--repository-type <values>",
29
+ option: "-rt,--repository-type <values>",
25
30
  parser: (v) => (0, string_util_1.parseStringList)(v),
26
31
  },
27
32
  });
@@ -30,6 +35,7 @@ class ConfigCommand extends CommandAbstract_1.CommandAbstract {
30
35
  const config = await ConfigAction_1.ConfigAction.fromGlobalOptions(this.globalOptions);
31
36
  const packages = (0, config_util_1.filterPackages)(config, {
32
37
  packageNames: this.options.package,
38
+ packageTaskNames: this.options.packageTask,
33
39
  repositoryNames: this.options.repository,
34
40
  repositoryTypes: this.options.repositoryType,
35
41
  });
@@ -18,7 +18,7 @@ class InitCommand extends CommandAbstract_1.CommandAbstract {
18
18
  },
19
19
  repositoryType: {
20
20
  description: "Repository types",
21
- option: "-t,--repository-type <values>",
21
+ option: "-rt,--repository-type <values>",
22
22
  parser: (v) => (0, string_util_1.parseStringList)(v),
23
23
  },
24
24
  });
@@ -81,12 +81,12 @@ class PruneCommand extends CommandAbstract_1.CommandAbstract {
81
81
  },
82
82
  repositoryType: {
83
83
  description: "Repository types",
84
- option: "-t,--repositoryType <values>",
84
+ option: "-rt,--repository-type <values>",
85
85
  parser: (v) => (0, string_util_1.parseStringList)(v),
86
86
  },
87
87
  tag: {
88
88
  description: "Tags",
89
- option: "--tag <values>",
89
+ option: "-t,--tag <values>",
90
90
  parser: string_util_1.parseStringList,
91
91
  },
92
92
  showAll: {
@@ -4,6 +4,7 @@ import { CommandAbstract } from "./CommandAbstract";
4
4
  export declare type RestoreCommandOptionsType<TResolved = false> = {
5
5
  id: string;
6
6
  package?: If<TResolved, string[]>;
7
+ packageTask?: If<TResolved, string[]>;
7
8
  repository?: If<TResolved, string[]>;
8
9
  repositoryType?: If<TResolved, RepositoryConfigType["type"][]>;
9
10
  tag?: If<TResolved, string[]>;
@@ -21,6 +21,11 @@ class RestoreCommand extends CommandAbstract_1.CommandAbstract {
21
21
  option: "-p,--package <values>",
22
22
  parser: string_util_1.parseStringList,
23
23
  },
24
+ packageTask: {
25
+ description: "Package task names",
26
+ option: "-pt,--package-task <values>",
27
+ parser: string_util_1.parseStringList,
28
+ },
24
29
  repository: {
25
30
  description: "Repository names",
26
31
  option: "-r,--repository <values>",
@@ -28,12 +33,12 @@ class RestoreCommand extends CommandAbstract_1.CommandAbstract {
28
33
  },
29
34
  repositoryType: {
30
35
  description: "Repository types",
31
- option: "-t,--repository-type <values>",
36
+ option: "-rt,--repository-type <values>",
32
37
  parser: (v) => (0, string_util_1.parseStringList)(v),
33
38
  },
34
39
  tag: {
35
40
  description: "Tags",
36
- option: "--tag <values>",
41
+ option: "-t,--tag <values>",
37
42
  parser: string_util_1.parseStringList,
38
43
  },
39
44
  });
@@ -44,6 +49,7 @@ class RestoreCommand extends CommandAbstract_1.CommandAbstract {
44
49
  const restore = new RestoreAction_1.RestoreAction(config, {
45
50
  snapshotId: this.options.id,
46
51
  packageNames: this.options.package,
52
+ packageTaskNames: this.options.packageTask,
47
53
  repositoryNames: this.options.repository,
48
54
  repositoryTypes: this.options.repositoryType,
49
55
  tags: this.options.tag,
@@ -24,7 +24,7 @@ class RestoreSessionsCommand extends CommandAbstract_1.CommandAbstract {
24
24
  },
25
25
  tag: {
26
26
  description: "Tags",
27
- option: "--tag <values>",
27
+ option: "-t,--tag <values>",
28
28
  parser: string_util_1.parseStringList,
29
29
  },
30
30
  limit: {
@@ -76,7 +76,7 @@ class SnapshotsCommand extends CommandAbstract_1.CommandAbstract {
76
76
  },
77
77
  tag: {
78
78
  description: "Tags",
79
- option: "--tag <values>",
79
+ option: "-t,--tag <values>",
80
80
  parser: string_util_1.parseStringList,
81
81
  },
82
82
  });
@@ -13,7 +13,6 @@ const string_util_1 = require("../util/string-util");
13
13
  const RepositoryAbstract_1 = require("./RepositoryAbstract");
14
14
  const assert_1 = require("assert");
15
15
  const fast_glob_1 = __importDefault(require("fast-glob"));
16
- const fs_extra_1 = require("fs-extra");
17
16
  const promises_1 = require("fs/promises");
18
17
  const micromatch_1 = require("micromatch");
19
18
  const path_1 = require("path");
@@ -62,7 +61,7 @@ class GitRepository extends RepositoryAbstract_1.RepositoryAbstract {
62
61
  log: data.options.verbose,
63
62
  });
64
63
  if (await git.canBeInit(this.config.repo)) {
65
- await (0, fs_extra_1.mkdir)(git.options.dir);
64
+ await (0, promises_1.mkdir)(git.options.dir);
66
65
  await git.exec(["init", "--bare", this.config.repo]);
67
66
  }
68
67
  const branchName = this.config.branch ?? "master";
@@ -182,7 +181,7 @@ class GitRepository extends RepositoryAbstract_1.RepositoryAbstract {
182
181
  const target = (0, path_1.join)(tmpPath, entry);
183
182
  const dir = (0, path_1.dirname)(target);
184
183
  if (!createdPaths.includes(dir)) {
185
- await (0, fs_extra_1.mkdir)(dir, {
184
+ await (0, promises_1.mkdir)(dir, {
186
185
  recursive: true,
187
186
  });
188
187
  createdPaths.push(dir);
@@ -10,6 +10,10 @@ export declare type MetaDataType = {
10
10
  export declare type LocalRepositoryConfigType = {
11
11
  outPath: string;
12
12
  compress?: boolean;
13
+ /**
14
+ * @default 1
15
+ */
16
+ fileCopyConcurrency?: number;
13
17
  };
14
18
  declare type CompressObjectType = {
15
19
  packs?: {
@@ -16,11 +16,9 @@ const RepositoryAbstract_1 = require("./RepositoryAbstract");
16
16
  const assert_1 = require("assert");
17
17
  const fast_glob_1 = __importDefault(require("fast-glob"));
18
18
  const fs_1 = require("fs");
19
- const fs_extra_1 = require("fs-extra");
20
19
  const promises_1 = require("fs/promises");
21
20
  const micromatch_1 = require("micromatch");
22
21
  const path_1 = require("path");
23
- const path_2 = require("path");
24
22
  const readline_1 = require("readline");
25
23
  exports.localRepositoryName = "local";
26
24
  exports.localRepositoryDefinition = {
@@ -62,6 +60,10 @@ exports.localPackageRepositoryDefinition = {
62
60
  },
63
61
  ],
64
62
  },
63
+ fileCopyConcurrency: {
64
+ type: "integer",
65
+ minimum: 1,
66
+ },
65
67
  },
66
68
  };
67
69
  class LocalRepository extends RepositoryAbstract_1.RepositoryAbstract {
@@ -111,11 +113,11 @@ class LocalRepository extends RepositoryAbstract_1.RepositoryAbstract {
111
113
  if (data.options.verbose)
112
114
  (0, cli_util_1.logExec)(`Deleting ${snapshotPath}`);
113
115
  if (await (0, fs_util_1.checkDir)(snapshotPath))
114
- await (0, fs_extra_1.rm)(snapshotPath, {
116
+ await (0, promises_1.rm)(snapshotPath, {
115
117
  recursive: true,
116
118
  });
117
119
  if (await (0, fs_util_1.checkFile)(metaPath))
118
- await (0, fs_extra_1.rm)(metaPath);
120
+ await (0, promises_1.rm)(metaPath);
119
121
  }
120
122
  async onSnapshots(data) {
121
123
  if (!(await (0, fs_util_1.checkDir)(this.config.outPath)))
@@ -173,8 +175,7 @@ class LocalRepository extends RepositoryAbstract_1.RepositoryAbstract {
173
175
  snapshotDate: data.snapshot.date,
174
176
  packageName: data.package.name,
175
177
  });
176
- const outPath = (0, path_1.join)(this.config.outPath, snapshotName);
177
- const createdPaths = [];
178
+ const outPath = (0, path_1.resolve)((0, path_1.join)(this.config.outPath, snapshotName));
178
179
  const pkg = data.package;
179
180
  await (0, promises_1.mkdir)(outPath, {
180
181
  recursive: true,
@@ -260,35 +261,26 @@ class LocalRepository extends RepositoryAbstract_1.RepositoryAbstract {
260
261
  }
261
262
  if (data.options.verbose)
262
263
  (0, cli_util_1.logExec)(`Copying files to ${outPath}`);
263
- const reader = (0, readline_1.createInterface)({
264
- input: (0, fs_1.createReadStream)(pathLists.path),
265
- });
266
- for await (const entry of reader) {
267
- const source = (0, path_1.join)(sourcePath, entry);
268
- const target = (0, path_1.join)(outPath, entry);
269
- if (entry.endsWith("/")) {
270
- await (0, promises_1.mkdir)(target, {
271
- recursive: true,
272
- });
273
- }
274
- else {
264
+ await (0, fs_util_1.cpy)({
265
+ input: {
266
+ type: "pathList",
267
+ path: pathLists.path,
268
+ basePath: sourcePath,
269
+ },
270
+ targetPath: outPath,
271
+ concurrency: this.config.fileCopyConcurrency,
272
+ async onPath({ isDir, entryPath }) {
273
+ if (isDir)
274
+ return;
275
275
  currentFiles++;
276
276
  await data.onProgress({
277
277
  total: pathLists.total.all,
278
278
  current: currentFiles,
279
279
  percent: (0, math_util_1.progressPercent)(pathLists.total.all, currentFiles),
280
- step: entry,
280
+ step: entryPath,
281
281
  });
282
- const dir = (0, path_2.dirname)(target);
283
- if (!createdPaths.includes(dir)) {
284
- await (0, promises_1.mkdir)(dir, {
285
- recursive: true,
286
- });
287
- createdPaths.push(dir);
288
- }
289
- await (0, promises_1.copyFile)(source, target);
290
- }
291
- }
282
+ },
283
+ });
292
284
  const metaPath = `${outPath}.json`;
293
285
  const nodePkg = (0, fs_util_1.parsePackageFile)();
294
286
  const meta = {
@@ -303,8 +295,9 @@ class LocalRepository extends RepositoryAbstract_1.RepositoryAbstract {
303
295
  await (0, promises_1.writeFile)(metaPath, LocalRepository.stringifyMetaData(meta));
304
296
  }
305
297
  async onRestore(data) {
306
- const restorePath = data.targetPath ?? data.package.restorePath;
307
- (0, assert_1.ok)(restorePath);
298
+ const relRestorePath = data.targetPath ?? data.package.restorePath;
299
+ (0, assert_1.ok)(relRestorePath);
300
+ const restorePath = (0, path_1.resolve)(relRestorePath);
308
301
  const [snapshot] = await this.onSnapshots({
309
302
  options: {
310
303
  ids: [data.options.snapshotId],
@@ -325,19 +318,27 @@ class LocalRepository extends RepositoryAbstract_1.RepositoryAbstract {
325
318
  }, true);
326
319
  if (data.options.verbose)
327
320
  (0, cli_util_1.logExec)(`Copying files to ${restorePath}`);
328
- await (0, fs_extra_1.copy)(sourcePath, restorePath, {
329
- filter: async (path) => {
330
- const [firstFolder] = (0, path_1.relative)(sourcePath, path).split(path_1.sep);
331
- const isZipFile = firstFolder.startsWith(".") && firstFolder.endsWith(".dd.zip");
321
+ await (0, fs_util_1.cpy)({
322
+ input: {
323
+ type: "glob",
324
+ sourcePath,
325
+ },
326
+ targetPath: restorePath,
327
+ concurrency: this.config.fileCopyConcurrency,
328
+ onPath: async ({ entryPath, entrySourcePath }) => {
329
+ const isRootFile = (0, path_1.basename)(entryPath) === entryPath;
330
+ const isZipFile = isRootFile &&
331
+ entryPath.startsWith(".") &&
332
+ entryPath.endsWith(".dd.zip");
332
333
  await data.onProgress({
333
334
  total: totalFiles,
334
335
  current: Math.max(currentFiles, 0),
335
336
  percent: (0, math_util_1.progressPercent)(totalFiles, Math.max(currentFiles, 0)),
336
- step: (0, path_1.relative)(sourcePath, path),
337
+ step: entryPath,
337
338
  });
338
339
  if (isZipFile) {
339
340
  await (0, zip_util_1.unzip)({
340
- input: path,
341
+ input: entrySourcePath,
341
342
  output: restorePath,
342
343
  verbose: data.options.verbose,
343
344
  onStream: async (stream) => await data.onProgress({
@@ -14,10 +14,10 @@ export declare type SnapshotResultType = SnapshotType & {
14
14
  tags: string[];
15
15
  };
16
16
  export declare type ProgressDataType = {
17
- total: number;
18
- current: number;
19
- percent: number;
20
- step: string;
17
+ total?: number;
18
+ current?: number;
19
+ percent?: number;
20
+ step?: string;
21
21
  stepPercent?: number | null;
22
22
  };
23
23
  export declare type InitDataType = {
@@ -190,6 +190,9 @@ class ResticRepository extends RepositoryAbstract_1.RepositoryAbstract {
190
190
  });
191
191
  if (data.options.verbose)
192
192
  (0, cli_util_1.logExec)(`Writing paths lists`);
193
+ await data.onProgress({
194
+ step: "Writing excluded paths list...",
195
+ });
193
196
  gitignorePath = await (0, fs_util_1.writeGitIgnoreList)({
194
197
  paths: stream,
195
198
  });
@@ -197,12 +200,21 @@ class ResticRepository extends RepositoryAbstract_1.RepositoryAbstract {
197
200
  if (data.options.tags?.some((tag) => tag.startsWith(ResticRepository.refPrefix)))
198
201
  throw new AppError_1.AppError(`Tag prefix is not allowed`);
199
202
  const packageTag = ResticRepository.buildSnapshotTag(RepositoryAbstract_1.SnapshotTagEnum.PACKAGE, data.package.name);
203
+ await data.onProgress({
204
+ step: "Fetching last snapshot...",
205
+ });
200
206
  const [lastSnapshot] = await restic.snapshots({
201
207
  json: true,
202
208
  tags: [packageTag],
203
209
  latest: 1,
204
210
  });
205
211
  const nodePkg = (0, fs_util_1.parsePackageFile)();
212
+ let lastProgress;
213
+ let totalFilesChanges = 0;
214
+ const totalFilesChangesLimit = 10;
215
+ await data.onProgress({
216
+ step: "Executing backup action...",
217
+ });
206
218
  await restic.backup({
207
219
  cwd: sourcePath,
208
220
  paths: ["."],
@@ -223,22 +235,31 @@ class ResticRepository extends RepositoryAbstract_1.RepositoryAbstract {
223
235
  ],
224
236
  onStream: async (streamData) => {
225
237
  if (streamData.message_type === "status") {
226
- await data.onProgress({
227
- total: Number((streamData.total_bytes / 1024 / 1024).toFixed(2)),
228
- current: streamData.bytes_done
229
- ? Number((streamData.bytes_done / 1024 / 1024).toFixed(2))
238
+ let showProgressBar = false;
239
+ if (totalFilesChanges > totalFilesChangesLimit) {
240
+ showProgressBar = true;
241
+ }
242
+ else if (lastProgress?.total !== streamData.total_files) {
243
+ totalFilesChanges = 0;
244
+ }
245
+ else {
246
+ totalFilesChanges++;
247
+ }
248
+ await data.onProgress((lastProgress = {
249
+ total: Math.max(lastProgress?.total || 0, streamData.total_files),
250
+ current: Math.max(lastProgress?.current || 0, streamData.files_done ?? 0),
251
+ percent: showProgressBar
252
+ ? Number((streamData.percent_done * 100).toFixed(2))
230
253
  : 0,
231
- percent: Number((streamData.percent_done * 100).toFixed(2)),
232
254
  step: streamData.current_files?.join(", ") ?? "-",
233
- });
255
+ }));
234
256
  }
235
257
  },
236
258
  });
237
259
  await data.onProgress({
238
- current: 100,
260
+ total: lastProgress?.total || 0,
261
+ current: lastProgress?.total || 0,
239
262
  percent: 100,
240
- step: "",
241
- total: 100,
242
263
  });
243
264
  }
244
265
  async onRestore(data) {
@@ -26,10 +26,14 @@ export declare class ConsoleSessionDriver extends SessionDriverAbstract {
26
26
  protected rendering?: boolean;
27
27
  protected lastColumns?: number;
28
28
  protected startTime: number;
29
+ protected chron: {
30
+ start: () => number;
31
+ elapsed: (formatted?: boolean | undefined) => string | number;
32
+ };
29
33
  onInit(): Promise<void>;
30
- onEnd(): Promise<void>;
34
+ onEnd(data?: Record<string, any>): Promise<void>;
31
35
  onRead(): Promise<ReadResultType[]>;
32
- protected printMessage(message: MessageType): void;
36
+ protected printMessage(message: MessageType, endMessage: boolean): void;
33
37
  protected renderSpinner(text: string): string;
34
38
  protected renderMessage(message: MessageType): string;
35
39
  onWrite(data: WriteDataType): Promise<void>;