@datatruck/cli 0.12.0 → 0.13.1

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 (35) hide show
  1. package/Action/SnapshotsAction.js +3 -1
  2. package/Command/BackupCommand.js +2 -0
  3. package/Command/CommandAbstract.d.ts +2 -0
  4. package/Command/RestoreCommand.js +2 -0
  5. package/Command/SnapshotsCommand.js +6 -0
  6. package/Config/PackageRepositoryConfig.d.ts +3 -3
  7. package/Config/PackageRepositoryConfig.js +2 -2
  8. package/Config/RepositoryConfig.d.ts +3 -3
  9. package/Config/RepositoryConfig.js +2 -2
  10. package/Factory/RepositoryFactory.js +3 -3
  11. package/JsonSchema/DefinitionEnum.d.ts +2 -2
  12. package/JsonSchema/DefinitionEnum.js +2 -2
  13. package/JsonSchema/JsonSchema.js +3 -3
  14. package/Repository/{LocalRepository.d.ts → DatatruckRepository.d.ts} +10 -9
  15. package/Repository/{LocalRepository.js → DatatruckRepository.js} +17 -14
  16. package/Repository/GitRepository.js +3 -0
  17. package/Repository/RepositoryAbstract.d.ts +4 -1
  18. package/Repository/RepositoryAbstract.js +1 -0
  19. package/Repository/ResticRepository.js +25 -1
  20. package/SessionDriver/ConsoleSessionDriver.d.ts +8 -2
  21. package/SessionDriver/ConsoleSessionDriver.js +18 -10
  22. package/SessionDriver/SessionDriverAbstract.d.ts +6 -7
  23. package/Task/GitTask.js +1 -0
  24. package/Task/SqlDumpTaskAbstract.js +1 -0
  25. package/cli.js +2 -0
  26. package/config.schema.json +7 -6
  27. package/package.json +3 -1
  28. package/util/ResticUtil.d.ts +9 -2
  29. package/util/ResticUtil.js +47 -20
  30. package/util/datatruck/config-util.d.ts +6 -6
  31. package/util/fs-util.d.ts +3 -0
  32. package/util/fs-util.js +37 -10
  33. package/util/process-util.js +3 -1
  34. package/util/zip-util.d.ts +1 -0
  35. package/util/zip-util.js +13 -6
@@ -24,7 +24,9 @@ class SnapshotsAction {
24
24
  continue;
25
25
  const repoInstance = (0, RepositoryFactory_1.RepositoryFactory)(repo);
26
26
  const configPackageNames = this.config.packages.map((pkg) => pkg.name);
27
- const packageNames = this.options.packageNames?.filter((name) => configPackageNames.includes(name)) || configPackageNames;
27
+ const packageNames = this.options.packageConfig
28
+ ? this.options.packageNames?.filter((name) => configPackageNames.includes(name)) || configPackageNames
29
+ : this.options.packageNames;
28
30
  const snapshots = await repoInstance.onSnapshots({
29
31
  options: {
30
32
  ...this.options,
@@ -67,6 +67,8 @@ class BackupCommand extends CommandAbstract_1.CommandAbstract {
67
67
  altDrivers: [
68
68
  new ConsoleSessionDriver_1.ConsoleSessionDriver({
69
69
  verbose: verbose > 0,
70
+ progress: this.globalOptions.progress,
71
+ progressInterval: this.globalOptions.progressInterval,
70
72
  }),
71
73
  ],
72
74
  });
@@ -6,6 +6,8 @@ export declare type GlobalOptionsType<TResolved = false> = {
6
6
  config: string | ConfigType;
7
7
  outputFormat?: FormatType;
8
8
  verbose?: number;
9
+ progress?: "auto" | "plain" | "tty";
10
+ progressInterval?: number;
9
11
  };
10
12
  export declare type CommandConstructorType<TUnresolvedOptions, TOptions extends SimilarObject<TUnresolvedOptions>> = {
11
13
  new (globalOptions: GlobalOptionsType<true>, options: TOptions): CommandAbstract<TUnresolvedOptions, TOptions>;
@@ -67,6 +67,8 @@ class RestoreCommand extends CommandAbstract_1.CommandAbstract {
67
67
  altDrivers: [
68
68
  new ConsoleSessionDriver_1.ConsoleSessionDriver({
69
69
  verbose: verbose > 0,
70
+ progress: this.globalOptions.progress,
71
+ progressInterval: this.globalOptions.progressInterval,
70
72
  }),
71
73
  ],
72
74
  verbose: verbose > 1,
@@ -1,4 +1,7 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.SnapshotsCommand = void 0;
4
7
  const ConfigAction_1 = require("../Action/ConfigAction");
@@ -6,6 +9,7 @@ const SnapshotsAction_1 = require("../Action/SnapshotsAction");
6
9
  const DataFormat_1 = require("../util/DataFormat");
7
10
  const string_util_1 = require("../util/string-util");
8
11
  const CommandAbstract_1 = require("./CommandAbstract");
12
+ const pretty_bytes_1 = __importDefault(require("pretty-bytes"));
9
13
  class SnapshotsCommand extends CommandAbstract_1.CommandAbstract {
10
14
  onOptions() {
11
15
  const groupByValues = ["packageName", "repositoryName", "repositoryType"];
@@ -120,6 +124,7 @@ class SnapshotsCommand extends CommandAbstract_1.CommandAbstract {
120
124
  "Date",
121
125
  "Package",
122
126
  "Task",
127
+ "Size",
123
128
  "Repository",
124
129
  "Repository type",
125
130
  ],
@@ -128,6 +133,7 @@ class SnapshotsCommand extends CommandAbstract_1.CommandAbstract {
128
133
  item.date.replace("T", " ").replace("Z", ""),
129
134
  item.packageName,
130
135
  item.packageTaskName || "",
136
+ (0, pretty_bytes_1.default)(item.size),
131
137
  item.repositoryName,
132
138
  item.repositoryType,
133
139
  ],
@@ -1,5 +1,5 @@
1
+ import { DatatruckPackageRepositoryConfigType, datatruckRepositoryName } from "../Repository/DatatruckRepository";
1
2
  import { GitPackageRepositoryConfigType, gitRepositoryName } from "../Repository/GitRepository";
2
- import { LocalPackageRepositoryConfigType, localRepositoryName } from "../Repository/LocalRepository";
3
3
  import { ResticPackageRepositoryConfigType, resticRepositoryName } from "../Repository/ResticRepository";
4
4
  import type { JSONSchema7 } from "json-schema";
5
5
  export declare const packageRepositoryConfigDefinition: JSONSchema7;
@@ -9,8 +9,8 @@ export declare type PackageRepositoryConfigType = {
9
9
  type: typeof resticRepositoryName;
10
10
  config: ResticPackageRepositoryConfigType;
11
11
  } | {
12
- type: typeof localRepositoryName;
13
- config: LocalPackageRepositoryConfigType;
12
+ type: typeof datatruckRepositoryName;
13
+ config: DatatruckPackageRepositoryConfigType;
14
14
  } | {
15
15
  type: typeof gitRepositoryName;
16
16
  config: GitPackageRepositoryConfigType;
@@ -2,12 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.packageRepositoryConfigDefinition = void 0;
4
4
  const DefinitionEnum_1 = require("../JsonSchema/DefinitionEnum");
5
+ const DatatruckRepository_1 = require("../Repository/DatatruckRepository");
5
6
  const GitRepository_1 = require("../Repository/GitRepository");
6
- const LocalRepository_1 = require("../Repository/LocalRepository");
7
7
  const ResticRepository_1 = require("../Repository/ResticRepository");
8
8
  const types = {
9
9
  [ResticRepository_1.resticRepositoryName]: DefinitionEnum_1.DefinitionEnum.resticPackageRepository,
10
- [LocalRepository_1.localRepositoryName]: DefinitionEnum_1.DefinitionEnum.localPackageRepository,
10
+ [DatatruckRepository_1.datatruckRepositoryName]: DefinitionEnum_1.DefinitionEnum.datatruckPackageRepository,
11
11
  [GitRepository_1.gitRepositoryName]: DefinitionEnum_1.DefinitionEnum.gitPackageRepository,
12
12
  };
13
13
  exports.packageRepositoryConfigDefinition = {
@@ -1,5 +1,5 @@
1
+ import { DatatruckRepositoryConfigType, datatruckRepositoryName } from "../Repository/DatatruckRepository";
1
2
  import { GitRepositoryConfigType, gitRepositoryName } from "../Repository/GitRepository";
2
- import { LocalRepositoryConfigType, localRepositoryName } from "../Repository/LocalRepository";
3
3
  import { ResticRepositoryConfigType, resticRepositoryName } from "../Repository/ResticRepository";
4
4
  import type { JSONSchema7 } from "json-schema";
5
5
  export declare const repositoryConfigDefinition: JSONSchema7;
@@ -15,8 +15,8 @@ export declare type RepositoryConfigType = {
15
15
  type: typeof resticRepositoryName;
16
16
  config: ResticRepositoryConfigType;
17
17
  } | {
18
- type: typeof localRepositoryName;
19
- config: LocalRepositoryConfigType;
18
+ type: typeof datatruckRepositoryName;
19
+ config: DatatruckRepositoryConfigType;
20
20
  } | {
21
21
  type: typeof gitRepositoryName;
22
22
  config: GitRepositoryConfigType;
@@ -2,12 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.repositoryConfigDefinition = void 0;
4
4
  const DefinitionEnum_1 = require("../JsonSchema/DefinitionEnum");
5
+ const DatatruckRepository_1 = require("../Repository/DatatruckRepository");
5
6
  const GitRepository_1 = require("../Repository/GitRepository");
6
- const LocalRepository_1 = require("../Repository/LocalRepository");
7
7
  const ResticRepository_1 = require("../Repository/ResticRepository");
8
8
  const types = {
9
9
  [ResticRepository_1.resticRepositoryName]: DefinitionEnum_1.DefinitionEnum.resticRepository,
10
- [LocalRepository_1.localRepositoryName]: DefinitionEnum_1.DefinitionEnum.localRepository,
10
+ [DatatruckRepository_1.datatruckRepositoryName]: DefinitionEnum_1.DefinitionEnum.datatruckRepository,
11
11
  [GitRepository_1.gitRepositoryName]: DefinitionEnum_1.DefinitionEnum.gitRepository,
12
12
  };
13
13
  exports.repositoryConfigDefinition = {
@@ -2,8 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RepositoryFactory = void 0;
4
4
  const AppError_1 = require("../Error/AppError");
5
+ const DatatruckRepository_1 = require("../Repository/DatatruckRepository");
5
6
  const GitRepository_1 = require("../Repository/GitRepository");
6
- const LocalRepository_1 = require("../Repository/LocalRepository");
7
7
  const ResticRepository_1 = require("../Repository/ResticRepository");
8
8
  function RepositoryFactory(repository) {
9
9
  const type = repository.type;
@@ -13,8 +13,8 @@ function RepositoryFactory(repository) {
13
13
  else if (type === ResticRepository_1.resticRepositoryName) {
14
14
  return new ResticRepository_1.ResticRepository(repository);
15
15
  }
16
- else if (type === LocalRepository_1.localRepositoryName) {
17
- return new LocalRepository_1.LocalRepository(repository);
16
+ else if (type === DatatruckRepository_1.datatruckRepositoryName) {
17
+ return new DatatruckRepository_1.DatatruckRepository(repository);
18
18
  }
19
19
  else {
20
20
  throw new AppError_1.AppError(`Invalid repository type: ${type}`);
@@ -6,8 +6,8 @@ export declare enum DefinitionEnum {
6
6
  task = "task",
7
7
  resticRepository = "restic-repository",
8
8
  resticPackageRepository = "restic-package-repository",
9
- localRepository = "local-repository",
10
- localPackageRepository = "local-package-repository",
9
+ datatruckRepository = "datatruck-repository",
10
+ datatruckPackageRepository = "datatruck-package-repository",
11
11
  gitRepository = "git-repository",
12
12
  gitPackageRepository = "git-package-repository",
13
13
  gitTask = "git-task",
@@ -10,8 +10,8 @@ var DefinitionEnum;
10
10
  DefinitionEnum["task"] = "task";
11
11
  DefinitionEnum["resticRepository"] = "restic-repository";
12
12
  DefinitionEnum["resticPackageRepository"] = "restic-package-repository";
13
- DefinitionEnum["localRepository"] = "local-repository";
14
- DefinitionEnum["localPackageRepository"] = "local-package-repository";
13
+ DefinitionEnum["datatruckRepository"] = "datatruck-repository";
14
+ DefinitionEnum["datatruckPackageRepository"] = "datatruck-package-repository";
15
15
  DefinitionEnum["gitRepository"] = "git-repository";
16
16
  DefinitionEnum["gitPackageRepository"] = "git-package-repository";
17
17
  DefinitionEnum["gitTask"] = "git-task";
@@ -7,8 +7,8 @@ const PackageRepositoryConfig_1 = require("../Config/PackageRepositoryConfig");
7
7
  const PrunePolicyConfig_1 = require("../Config/PrunePolicyConfig");
8
8
  const RepositoryConfig_1 = require("../Config/RepositoryConfig");
9
9
  const TaskConfig_1 = require("../Config/TaskConfig");
10
+ const DatatruckRepository_1 = require("../Repository/DatatruckRepository");
10
11
  const GitRepository_1 = require("../Repository/GitRepository");
11
- const LocalRepository_1 = require("../Repository/LocalRepository");
12
12
  const ResticRepository_1 = require("../Repository/ResticRepository");
13
13
  const GitTask_1 = require("../Task/GitTask");
14
14
  const MariadbTask_1 = require("../Task/MariadbTask");
@@ -31,8 +31,8 @@ exports.definitions = {
31
31
  [DefinitionEnum_1.DefinitionEnum.task]: TaskConfig_1.taskConfigDefinition,
32
32
  [DefinitionEnum_1.DefinitionEnum.gitRepository]: GitRepository_1.gitRepositoryDefinition,
33
33
  [DefinitionEnum_1.DefinitionEnum.gitPackageRepository]: GitRepository_1.gitPackageRepositoryDefinition,
34
- [DefinitionEnum_1.DefinitionEnum.localRepository]: LocalRepository_1.localRepositoryDefinition,
35
- [DefinitionEnum_1.DefinitionEnum.localPackageRepository]: LocalRepository_1.localPackageRepositoryDefinition,
34
+ [DefinitionEnum_1.DefinitionEnum.datatruckRepository]: DatatruckRepository_1.datatruckRepositoryDefinition,
35
+ [DefinitionEnum_1.DefinitionEnum.datatruckPackageRepository]: DatatruckRepository_1.datatruckPackageRepositoryDefinition,
36
36
  [DefinitionEnum_1.DefinitionEnum.resticRepository]: ResticRepository_1.resticRepositoryDefinition,
37
37
  [DefinitionEnum_1.DefinitionEnum.resticPackageRepository]: ResticRepository_1.resticPackageRepositoryDefinition,
38
38
  [DefinitionEnum_1.DefinitionEnum.gitTask]: GitTask_1.gitTaskDefinition,
@@ -7,8 +7,9 @@ export declare type MetaDataType = {
7
7
  task: string | undefined;
8
8
  tags: string[];
9
9
  version: string;
10
+ size: number;
10
11
  };
11
- export declare type LocalRepositoryConfigType = {
12
+ export declare type DatatruckRepositoryConfigType = {
12
13
  outPath: string;
13
14
  compress?: boolean;
14
15
  /**
@@ -23,13 +24,13 @@ declare type CompressObjectType = {
23
24
  onePackByResult?: boolean;
24
25
  }[];
25
26
  };
26
- export declare type LocalPackageRepositoryConfigType = {
27
+ export declare type DatatruckPackageRepositoryConfigType = {
27
28
  compress?: CompressObjectType | boolean;
28
29
  };
29
- export declare const localRepositoryName = "local";
30
- export declare const localRepositoryDefinition: JSONSchema7;
31
- export declare const localPackageRepositoryDefinition: JSONSchema7;
32
- export declare class LocalRepository extends RepositoryAbstract<LocalRepositoryConfigType> {
30
+ export declare const datatruckRepositoryName = "datatruck";
31
+ export declare const datatruckRepositoryDefinition: JSONSchema7;
32
+ export declare const datatruckPackageRepositoryDefinition: JSONSchema7;
33
+ export declare class DatatruckRepository extends RepositoryAbstract<DatatruckRepositoryConfigType> {
33
34
  static zipBasenameTpl: string;
34
35
  static buildSnapshotName(data: {
35
36
  snapshotId: string;
@@ -50,8 +51,8 @@ export declare class LocalRepository extends RepositoryAbstract<LocalRepositoryC
50
51
  onPrune(data: PruneDataType): Promise<void>;
51
52
  onSnapshots(data: SnapshotsDataType): Promise<SnapshotResultType[]>;
52
53
  private normalizeCompressConfig;
53
- onBackup(data: BackupDataType<LocalPackageRepositoryConfigType>): Promise<void>;
54
- onCopyBackup(data: CopyBackupType<LocalRepositoryConfigType>): Promise<void>;
55
- onRestore(data: RestoreDataType<LocalPackageRepositoryConfigType>): Promise<void>;
54
+ onBackup(data: BackupDataType<DatatruckPackageRepositoryConfigType>): Promise<void>;
55
+ onCopyBackup(data: CopyBackupType<DatatruckRepositoryConfigType>): Promise<void>;
56
+ onRestore(data: RestoreDataType<DatatruckPackageRepositoryConfigType>): Promise<void>;
56
57
  }
57
58
  export {};
@@ -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.LocalRepository = exports.localPackageRepositoryDefinition = exports.localRepositoryDefinition = exports.localRepositoryName = void 0;
6
+ exports.DatatruckRepository = exports.datatruckPackageRepositoryDefinition = exports.datatruckRepositoryDefinition = exports.datatruckRepositoryName = void 0;
7
7
  const AppError_1 = require("../Error/AppError");
8
8
  const DefinitionEnum_1 = require("../JsonSchema/DefinitionEnum");
9
9
  const cli_util_1 = require("../util/cli-util");
@@ -20,8 +20,8 @@ const promises_1 = require("fs/promises");
20
20
  const micromatch_1 = require("micromatch");
21
21
  const path_1 = require("path");
22
22
  const readline_1 = require("readline");
23
- exports.localRepositoryName = "local";
24
- exports.localRepositoryDefinition = {
23
+ exports.datatruckRepositoryName = "datatruck";
24
+ exports.datatruckRepositoryDefinition = {
25
25
  type: "object",
26
26
  required: ["outPath"],
27
27
  additionalProperties: false,
@@ -30,7 +30,7 @@ exports.localRepositoryDefinition = {
30
30
  compress: { type: "boolean" },
31
31
  },
32
32
  };
33
- exports.localPackageRepositoryDefinition = {
33
+ exports.datatruckPackageRepositoryDefinition = {
34
34
  type: "object",
35
35
  additionalProperties: false,
36
36
  properties: {
@@ -66,7 +66,7 @@ exports.localPackageRepositoryDefinition = {
66
66
  },
67
67
  },
68
68
  };
69
- class LocalRepository extends RepositoryAbstract_1.RepositoryAbstract {
69
+ class DatatruckRepository extends RepositoryAbstract_1.RepositoryAbstract {
70
70
  static buildSnapshotName(data) {
71
71
  const date = data.snapshotDate.replace(/:/g, "-");
72
72
  const pkgName = encodeURIComponent(data.packageName).replace(/%40/g, "@");
@@ -103,7 +103,7 @@ class LocalRepository extends RepositoryAbstract_1.RepositoryAbstract {
103
103
  await (0, fs_util_1.mkdirIfNotExists)(this.config.outPath);
104
104
  }
105
105
  async onPrune(data) {
106
- const snapshotName = LocalRepository.buildSnapshotName({
106
+ const snapshotName = DatatruckRepository.buildSnapshotName({
107
107
  snapshotId: data.snapshot.id,
108
108
  snapshotDate: data.snapshot.date,
109
109
  packageName: data.snapshot.packageName,
@@ -127,7 +127,7 @@ class LocalRepository extends RepositoryAbstract_1.RepositoryAbstract {
127
127
  const packagePatterns = (0, string_util_1.makePathPatterns)(data.options.packageNames);
128
128
  const taskPatterns = (0, string_util_1.makePathPatterns)(data.options.packageTaskNames);
129
129
  for (const snapshotName of snapshotNames) {
130
- const snapshotNameData = LocalRepository.parseSnapshotName(snapshotName);
130
+ const snapshotNameData = DatatruckRepository.parseSnapshotName(snapshotName);
131
131
  if (!snapshotNameData)
132
132
  continue;
133
133
  if (packagePatterns &&
@@ -137,7 +137,7 @@ class LocalRepository extends RepositoryAbstract_1.RepositoryAbstract {
137
137
  !data.options.ids.some((id) => snapshotNameData.snapshotShortId.startsWith(id.slice(0, 8))))
138
138
  continue;
139
139
  const metaPath = (0, path_1.join)(this.config.outPath, snapshotName);
140
- const meta = await LocalRepository.parseMetaData(metaPath);
140
+ const meta = await DatatruckRepository.parseMetaData(metaPath);
141
141
  if (taskPatterns && !(0, string_util_1.checkMatch)(meta.task, taskPatterns))
142
142
  continue;
143
143
  if (data.options.ids &&
@@ -153,6 +153,7 @@ class LocalRepository extends RepositoryAbstract_1.RepositoryAbstract {
153
153
  packageName: meta.package,
154
154
  packageTaskName: meta.task,
155
155
  tags: meta.tags,
156
+ size: meta.size || 0,
156
157
  });
157
158
  }
158
159
  return snapshots;
@@ -174,7 +175,7 @@ class LocalRepository extends RepositoryAbstract_1.RepositoryAbstract {
174
175
  return compress;
175
176
  }
176
177
  async onBackup(data) {
177
- const snapshotName = LocalRepository.buildSnapshotName({
178
+ const snapshotName = DatatruckRepository.buildSnapshotName({
178
179
  snapshotId: data.snapshot.id,
179
180
  snapshotDate: data.snapshot.date,
180
181
  packageName: data.package.name,
@@ -272,6 +273,7 @@ class LocalRepository extends RepositoryAbstract_1.RepositoryAbstract {
272
273
  basePath: sourcePath,
273
274
  },
274
275
  targetPath: outPath,
276
+ skipNotFoundError: true,
275
277
  concurrency: this.config.fileCopyConcurrency,
276
278
  async onPath({ isDir, entryPath }) {
277
279
  if (isDir)
@@ -294,13 +296,14 @@ class LocalRepository extends RepositoryAbstract_1.RepositoryAbstract {
294
296
  package: data.package.name,
295
297
  task: data.package.task?.name,
296
298
  version: nodePkg.version,
299
+ size: await (0, fs_util_1.fastFolderSizeAsync)(outPath),
297
300
  };
298
301
  if (data.options.verbose)
299
302
  (0, cli_util_1.logExec)(`Writing metadata into ${metaPath}`);
300
- await (0, promises_1.writeFile)(metaPath, LocalRepository.stringifyMetaData(meta));
303
+ await (0, promises_1.writeFile)(metaPath, DatatruckRepository.stringifyMetaData(meta));
301
304
  }
302
305
  async onCopyBackup(data) {
303
- const snapshotName = LocalRepository.buildSnapshotName({
306
+ const snapshotName = DatatruckRepository.buildSnapshotName({
304
307
  snapshotId: data.snapshot.id,
305
308
  snapshotDate: data.snapshot.date,
306
309
  packageName: data.package.name,
@@ -332,7 +335,7 @@ class LocalRepository extends RepositoryAbstract_1.RepositoryAbstract {
332
335
  });
333
336
  if (!snapshot)
334
337
  throw new AppError_1.AppError("Snapshot not found");
335
- const snapshotName = LocalRepository.buildSnapshotName({
338
+ const snapshotName = DatatruckRepository.buildSnapshotName({
336
339
  snapshotId: data.snapshot.id,
337
340
  snapshotDate: data.snapshot.date,
338
341
  packageName: data.package.name,
@@ -384,5 +387,5 @@ class LocalRepository extends RepositoryAbstract_1.RepositoryAbstract {
384
387
  });
385
388
  }
386
389
  }
387
- exports.LocalRepository = LocalRepository;
388
- LocalRepository.zipBasenameTpl = `.*.dd.zip`;
390
+ exports.DatatruckRepository = DatatruckRepository;
391
+ DatatruckRepository.zipBasenameTpl = `.*.dd.zip`;
@@ -136,6 +136,7 @@ class GitRepository extends RepositoryAbstract_1.RepositoryAbstract {
136
136
  packageName: parsedTag.package,
137
137
  packageTaskName: parsedTag.task,
138
138
  tags: parsedTag.tags,
139
+ size: Number(parsedTag.size) || 0,
139
140
  });
140
141
  return result;
141
142
  }, [])
@@ -207,6 +208,8 @@ class GitRepository extends RepositoryAbstract_1.RepositoryAbstract {
207
208
  package: data.package.name,
208
209
  task: data.package.task?.name,
209
210
  version: nodePkg.version,
211
+ size: ((await (0, fs_util_1.fastFolderSizeAsync)(tmpPath)) -
212
+ (await (0, fs_util_1.fastFolderSizeAsync)((0, path_1.join)(tmpPath, ".git")))).toString(),
210
213
  });
211
214
  await git.addTag(meta.name, meta.message);
212
215
  await git.push({ branchName });
@@ -13,6 +13,7 @@ export declare type SnapshotResultType = SnapshotType & {
13
13
  packageName: string;
14
14
  packageTaskName: string | undefined;
15
15
  tags: string[];
16
+ size: number;
16
17
  };
17
18
  export declare type ProgressDataType = {
18
19
  total?: number;
@@ -63,7 +64,8 @@ export declare enum SnapshotTagEnum {
63
64
  PACKAGE = "package",
64
65
  TASK = "task",
65
66
  TAGS = "tags",
66
- VERSION = "version"
67
+ VERSION = "version",
68
+ SIZE = "size"
67
69
  }
68
70
  export declare type SnapshotTagObjectType = {
69
71
  [SnapshotTagEnum.ID]: string;
@@ -73,6 +75,7 @@ export declare type SnapshotTagObjectType = {
73
75
  [SnapshotTagEnum.TASK]: string | undefined;
74
76
  [SnapshotTagEnum.TAGS]: string[];
75
77
  [SnapshotTagEnum.VERSION]: string;
78
+ [SnapshotTagEnum.SIZE]: string;
76
79
  };
77
80
  export declare abstract class RepositoryAbstract<TConfig> {
78
81
  readonly repository: RepositoryConfigType;
@@ -10,6 +10,7 @@ var SnapshotTagEnum;
10
10
  SnapshotTagEnum["TASK"] = "task";
11
11
  SnapshotTagEnum["TAGS"] = "tags";
12
12
  SnapshotTagEnum["VERSION"] = "version";
13
+ SnapshotTagEnum["SIZE"] = "size";
13
14
  })(SnapshotTagEnum = exports.SnapshotTagEnum || (exports.SnapshotTagEnum = {}));
14
15
  class RepositoryAbstract {
15
16
  constructor(repository) {
@@ -9,6 +9,7 @@ const ResticUtil_1 = require("../util/ResticUtil");
9
9
  const cli_util_1 = require("../util/cli-util");
10
10
  const paths_util_1 = require("../util/datatruck/paths-util");
11
11
  const fs_util_1 = require("../util/fs-util");
12
+ const math_util_1 = require("../util/math-util");
12
13
  const string_util_1 = require("../util/string-util");
13
14
  const RepositoryAbstract_1 = require("./RepositoryAbstract");
14
15
  const assert_1 = require("assert");
@@ -164,6 +165,7 @@ class ResticRepository extends RepositoryAbstract_1.RepositoryAbstract {
164
165
  date: tag.date,
165
166
  id: tag.id,
166
167
  tags: itemTags,
168
+ size: Number(tag.size) || 0,
167
169
  });
168
170
  return items;
169
171
  }, []);
@@ -245,6 +247,8 @@ class ResticRepository extends RepositoryAbstract_1.RepositoryAbstract {
245
247
  await data.onProgress({
246
248
  step: "Executing backup action...",
247
249
  });
250
+ let resticSnapshotId;
251
+ let resticTotalBytes;
248
252
  await restic.backup({
249
253
  cwd: sourcePath,
250
254
  paths: ["."],
@@ -281,7 +285,7 @@ class ResticRepository extends RepositoryAbstract_1.RepositoryAbstract {
281
285
  totalFilesChanges++;
282
286
  }
283
287
  await data.onProgress((lastProgress = {
284
- total: Math.max(lastProgress?.total || 0, streamData.total_files),
288
+ total: Math.max(lastProgress?.total || 0, streamData.total_files || 0),
285
289
  current: Math.max(lastProgress?.current || 0, streamData.files_done ?? 0),
286
290
  percent: showProgressBar
287
291
  ? Number((streamData.percent_done * 100).toFixed(2))
@@ -289,8 +293,18 @@ class ResticRepository extends RepositoryAbstract_1.RepositoryAbstract {
289
293
  step: streamData.current_files?.join(", ") ?? "-",
290
294
  }));
291
295
  }
296
+ else if (streamData.message_type === "summary") {
297
+ resticSnapshotId = streamData.snapshot_id;
298
+ resticTotalBytes = streamData.total_bytes_processed;
299
+ }
292
300
  },
293
301
  });
302
+ if (typeof resticSnapshotId !== "string")
303
+ throw new AppError_1.AppError(`Restic snapshot id is is not defined`);
304
+ if (typeof resticTotalBytes !== "number")
305
+ throw new AppError_1.AppError(`Restic snapshot total bytes is not defined`);
306
+ const sizeTag = ResticRepository.buildSnapshotTag(RepositoryAbstract_1.SnapshotTagEnum.SIZE, resticTotalBytes.toString());
307
+ await restic.exec(["tag", "--add", sizeTag, resticSnapshotId]);
294
308
  await data.onProgress({
295
309
  total: lastProgress?.total || 0,
296
310
  current: lastProgress?.total || 0,
@@ -339,6 +353,16 @@ class ResticRepository extends RepositoryAbstract_1.RepositoryAbstract {
339
353
  await restic.restore({
340
354
  id: snapshot.originalId,
341
355
  target: restorePath,
356
+ onStream: async (streamData) => {
357
+ if (streamData.message_type === "restore-status") {
358
+ const current = Math.min(streamData.total_bytes, snapshot.size);
359
+ await data.onProgress({
360
+ total: snapshot.size,
361
+ current,
362
+ percent: (0, math_util_1.progressPercent)(snapshot.size, current),
363
+ });
364
+ }
365
+ },
342
366
  });
343
367
  }
344
368
  }
@@ -1,5 +1,5 @@
1
1
  /// <reference types="node" />
2
- import { WriteDataType, ReadResultType, SessionDriverAbstract } from "./SessionDriverAbstract";
2
+ import { WriteDataType, ReadResultType, SessionDriverAbstract, SessionDriverOptions } from "./SessionDriverAbstract";
3
3
  declare type BadgeType = {
4
4
  name: string;
5
5
  value: string;
@@ -18,9 +18,14 @@ declare type MessageType = {
18
18
  progressStep?: string | null;
19
19
  progressStepPercent?: number | null;
20
20
  };
21
- export declare class ConsoleSessionDriver extends SessionDriverAbstract {
21
+ declare type ConsoleSessionDriverOptions = SessionDriverOptions & {
22
+ progress?: "auto" | "tty" | "plain";
23
+ progressInterval?: number;
24
+ };
25
+ export declare class ConsoleSessionDriver extends SessionDriverAbstract<ConsoleSessionDriverOptions> {
22
26
  protected lastMessage: MessageType | undefined;
23
27
  protected lastMessageText: string | undefined;
28
+ protected lastProgressDate: number | undefined;
24
29
  protected prints: number;
25
30
  protected renderInterval: NodeJS.Timeout;
26
31
  protected rendering?: boolean;
@@ -30,6 +35,7 @@ export declare class ConsoleSessionDriver extends SessionDriverAbstract {
30
35
  start: () => number;
31
36
  elapsed: (formatted?: boolean | undefined) => string | number;
32
37
  };
38
+ protected tty: boolean;
33
39
  onInit(): Promise<void>;
34
40
  onEnd(data?: Record<string, any>): Promise<void>;
35
41
  onRead(): Promise<ReadResultType[]>;
@@ -16,6 +16,11 @@ class ConsoleSessionDriver extends SessionDriverAbstract_1.SessionDriverAbstract
16
16
  this.chron = (0, date_util_1.createChron)();
17
17
  }
18
18
  async onInit() {
19
+ this.tty = this.options.verbose
20
+ ? false
21
+ : this.options.progress === "auto"
22
+ ? process.stdout.isTTY
23
+ : this.options.progress === "tty";
19
24
  this.chron.start();
20
25
  this.renderInterval = setInterval(() => {
21
26
  if (this.lastMessage)
@@ -24,7 +29,7 @@ class ConsoleSessionDriver extends SessionDriverAbstract_1.SessionDriverAbstract
24
29
  }
25
30
  async onEnd(data) {
26
31
  clearInterval(this.renderInterval);
27
- if (!this.options.verbose)
32
+ if (this.tty)
28
33
  process.stdout.write(cli_util_1.showCursorCommand);
29
34
  (0, cli_util_1.logVars)({
30
35
  ...data,
@@ -36,10 +41,10 @@ class ConsoleSessionDriver extends SessionDriverAbstract_1.SessionDriverAbstract
36
41
  }
37
42
  printMessage(message, endMessage) {
38
43
  const text = this.renderMessage(message);
39
- if (this.options.verbose && this.lastMessageText === text) {
44
+ if (!this.tty && this.lastMessageText === text) {
40
45
  return;
41
46
  }
42
- if (this.options.verbose) {
47
+ if (!this.tty) {
43
48
  process.stdout.write(`${this.renderSpinner(text)}\n`);
44
49
  }
45
50
  else {
@@ -58,7 +63,7 @@ class ConsoleSessionDriver extends SessionDriverAbstract_1.SessionDriverAbstract
58
63
  this.lastMessageText = text;
59
64
  }
60
65
  renderSpinner(text) {
61
- return text.replace("{spinner}", (0, chalk_1.grey)(this.options.verbose ? "?" : (0, cli_util_1.renderSpinner)(this.prints)));
66
+ return text.replace("{spinner}", (0, chalk_1.grey)(this.tty ? (0, cli_util_1.renderSpinner)(this.prints) : "?"));
62
67
  }
63
68
  renderMessage(message) {
64
69
  const badges = renderBadges([
@@ -66,7 +71,6 @@ class ConsoleSessionDriver extends SessionDriverAbstract_1.SessionDriverAbstract
66
71
  ...(message.errorBadge ? [message.errorBadge] : []),
67
72
  ]);
68
73
  const padding = " ".repeat(message.level ?? 0);
69
- const haveProgressBar = typeof message.progressPercent === "number";
70
74
  const sessionId = message.sessionId.toString().padStart(2, "0");
71
75
  const parts = [
72
76
  `${padding}${message.textPrefix} [${(0, chalk_1.grey)(sessionId)}] ${message.text}`,
@@ -89,6 +93,13 @@ class ConsoleSessionDriver extends SessionDriverAbstract_1.SessionDriverAbstract
89
93
  async onWrite(data) {
90
94
  if (data.action === SessionDriverAbstract_1.ActionEnum.Init)
91
95
  return;
96
+ if (data.action === SessionDriverAbstract_1.ActionEnum.Progress && this.options.progressInterval) {
97
+ const skip = this.lastProgressDate &&
98
+ Date.now() - this.lastProgressDate < this.options.progressInterval;
99
+ if (skip)
100
+ return;
101
+ this.lastProgressDate = Date.now();
102
+ }
92
103
  const message = {
93
104
  sessionId: "sessionId" in data.data ? data.data.sessionId : data.data.id,
94
105
  badges: [],
@@ -113,9 +124,7 @@ class ConsoleSessionDriver extends SessionDriverAbstract_1.SessionDriverAbstract
113
124
  if (data.data.error)
114
125
  message.errorBadge = {
115
126
  name: "error",
116
- value: this.options.verbose
117
- ? data.data.error
118
- : data.data.error.split("\n")[0],
127
+ value: this.tty ? data.data.error.split("\n")[0] : data.data.error,
119
128
  color: chalk_1.red,
120
129
  };
121
130
  }
@@ -159,8 +168,7 @@ class ConsoleSessionDriver extends SessionDriverAbstract_1.SessionDriverAbstract
159
168
  if (isHeader && data.action === SessionDriverAbstract_1.ActionEnum.End) {
160
169
  return;
161
170
  }
162
- const endMessage = !this.options.verbose &&
163
- (!hasProgress || data.action === SessionDriverAbstract_1.ActionEnum.End || isHeader);
171
+ const endMessage = this.tty && (!hasProgress || data.action === SessionDriverAbstract_1.ActionEnum.End || isHeader);
164
172
  this.printMessage(message, endMessage);
165
173
  if (endMessage)
166
174
  process.stdout.write("\n");
@@ -64,13 +64,12 @@ export declare type ReadResultType = {
64
64
  repositoryType: string;
65
65
  error: string | null;
66
66
  };
67
- export declare abstract class SessionDriverAbstract {
68
- readonly options: {
69
- verbose?: boolean;
70
- };
71
- constructor(options: {
72
- verbose?: boolean;
73
- });
67
+ export declare type SessionDriverOptions = {
68
+ verbose?: boolean;
69
+ };
70
+ export declare abstract class SessionDriverAbstract<TOptions extends SessionDriverOptions = SessionDriverOptions> {
71
+ readonly options: TOptions;
72
+ constructor(options: TOptions);
74
73
  onInit(): Promise<void>;
75
74
  abstract onWrite(data: WriteDataType): Promise<void>;
76
75
  onEnd(data?: Record<string, any>): Promise<void>;
package/Task/GitTask.js CHANGED
@@ -169,6 +169,7 @@ class GitTask extends TaskAbstract_1.TaskAbstract {
169
169
  basePath: path,
170
170
  },
171
171
  targetPath: outPath,
172
+ skipNotFoundError: true,
172
173
  concurrency: this.config.fileCopyConcurrency,
173
174
  onPath: async ({ entryPath }) => {
174
175
  currentFiles++;
@@ -15,6 +15,7 @@ const path_1 = require("path");
15
15
  exports.sqlDumpTaskDefinition = {
16
16
  type: "object",
17
17
  required: ["password", "hostname", "username", "database"],
18
+ additionalProperties: false,
18
19
  properties: {
19
20
  password: {
20
21
  anyOf: [
package/cli.js CHANGED
@@ -80,6 +80,8 @@ program.description(description);
80
80
  program.usage("dtt");
81
81
  program.option("-v,--verbose", "Verbose", (_, previous) => previous + 1, 0);
82
82
  program.option("-c,--config <path>", "Config path", process.env["DATATRUCK_CONFIG"] ?? (cwd.endsWith(path_1.sep) ? cwd : `${cwd}${path_1.sep}`));
83
+ program.option("--progress <value>", "Progress type (auto, plain, tty)", "auto");
84
+ program.option("--progress-interval <ms>", "Progress interval");
83
85
  program.option("-o,--output-format <format>", "Output format (json, pjson, yaml, table, custom=$, tpl=name)", "table");
84
86
  makeCommand(CommandFactory_1.CommandEnum.config).alias("c");
85
87
  makeCommand(CommandFactory_1.CommandEnum.init).alias("i");
@@ -81,7 +81,7 @@
81
81
  "type": "object",
82
82
  "properties": {
83
83
  "type": {
84
- "const": "local"
84
+ "const": "datatruck"
85
85
  }
86
86
  }
87
87
  },
@@ -89,7 +89,7 @@
89
89
  "type": "object",
90
90
  "properties": {
91
91
  "config": {
92
- "$ref": "#/definitions/local-repository"
92
+ "$ref": "#/definitions/datatruck-repository"
93
93
  }
94
94
  }
95
95
  },
@@ -248,7 +248,7 @@
248
248
  "type": "object",
249
249
  "properties": {
250
250
  "type": {
251
- "const": "local"
251
+ "const": "datatruck"
252
252
  }
253
253
  }
254
254
  },
@@ -256,7 +256,7 @@
256
256
  "type": "object",
257
257
  "properties": {
258
258
  "config": {
259
- "$ref": "#/definitions/local-package-repository"
259
+ "$ref": "#/definitions/datatruck-package-repository"
260
260
  }
261
261
  }
262
262
  },
@@ -438,7 +438,7 @@
438
438
  "additionalProperties": false,
439
439
  "properties": {}
440
440
  },
441
- "local-repository": {
441
+ "datatruck-repository": {
442
442
  "type": "object",
443
443
  "required": [
444
444
  "outPath"
@@ -453,7 +453,7 @@
453
453
  }
454
454
  }
455
455
  },
456
- "local-package-repository": {
456
+ "datatruck-package-repository": {
457
457
  "type": "object",
458
458
  "additionalProperties": false,
459
459
  "properties": {
@@ -683,6 +683,7 @@
683
683
  "username",
684
684
  "database"
685
685
  ],
686
+ "additionalProperties": false,
686
687
  "properties": {
687
688
  "password": {
688
689
  "anyOf": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datatruck/cli",
3
- "version": "0.12.0",
3
+ "version": "0.13.1",
4
4
  "dependencies": {
5
5
  "ajv": "^8.11.0",
6
6
  "async": "^3.2.4",
@@ -8,8 +8,10 @@
8
8
  "cli-table3": "^0.6.2",
9
9
  "commander": "^9.4.0",
10
10
  "dayjs": "^1.11.5",
11
+ "fast-folder-size": "^1.7.1",
11
12
  "fast-glob": "^3.2.11",
12
13
  "micromatch": "^4.0.5",
14
+ "pretty-bytes": "^5.6.0",
13
15
  "sqlite": "^4.1.2",
14
16
  "sqlite3": "^5.0.11"
15
17
  },
@@ -10,13 +10,16 @@ export declare type RepositoryType = {
10
10
  } & Omit<UriType, "password">;
11
11
  export declare type BackupStreamType = {
12
12
  message_type: "status";
13
- seconds_elapsed: number;
13
+ seconds_elapsed?: number;
14
14
  percent_done: number;
15
- total_files: number;
15
+ total_files?: number;
16
16
  files_done?: number;
17
17
  total_bytes: number;
18
18
  bytes_done?: number;
19
19
  current_files?: string[];
20
+ } | {
21
+ message_type: "restore-status";
22
+ total_bytes: number;
20
23
  } | {
21
24
  message_type: "summary";
22
25
  files_new: number;
@@ -95,6 +98,10 @@ export declare class ResticUtil {
95
98
  restore(options: {
96
99
  id: string;
97
100
  target: string;
101
+ /**
102
+ * @default 30_000
103
+ */
104
+ progressInterval?: number | false;
98
105
  onStream?: (data: BackupStreamType) => Promise<void>;
99
106
  }): Promise<ExecResultType>;
100
107
  }
@@ -29,7 +29,7 @@ class ResticUtil {
29
29
  async exec(args, settings, options) {
30
30
  return await (0, process_util_1.exec)("restic", args, {
31
31
  stdio: ["ignore", "pipe", "pipe"],
32
- env: { ...this.options.env },
32
+ env: { ...process.env, ...this.options.env },
33
33
  cwd: options?.cwd,
34
34
  }, {
35
35
  stderr: { toExitCode: true },
@@ -40,7 +40,11 @@ class ResticUtil {
40
40
  stderr: true,
41
41
  colorize: true,
42
42
  allToStderr: true,
43
- envNames: ["RESTIC_REPOSITORY", "RESTIC_PASSWORD_FILE"],
43
+ envNames: [
44
+ "RESTIC_REPOSITORY",
45
+ "RESTIC_PASSWORD_FILE",
46
+ "RESTIC_PASSWORD",
47
+ ],
44
48
  }
45
49
  : {},
46
50
  ...(settings ?? {}),
@@ -96,11 +100,12 @@ class ResticUtil {
96
100
  return JSON.parse(result.stdout);
97
101
  }
98
102
  async checkBackupSetPathSupport() {
99
- const result = await this.exec(["backup", "--set-path"], {
100
- onExitCodeError: () => false,
101
- stderr: { save: true },
103
+ /*const result = await this.exec(["backup", "--set-path"], {
104
+ onExitCodeError: () => false,
105
+ stderr: { save: true },
102
106
  });
103
- return result.stderr.includes("flag needs an argument");
107
+ return result.stderr.includes("flag needs an argument");*/
108
+ return false;
104
109
  }
105
110
  async backup(options) {
106
111
  const exec = async () => await this.exec([
@@ -174,20 +179,42 @@ class ResticUtil {
174
179
  });
175
180
  }
176
181
  async restore(options) {
177
- return await this.exec(["restore", "--json", options.id, "--target", options.target], {
178
- stderr: {
179
- toExitCode: true,
180
- },
181
- stdout: {
182
- ...(options.onStream && {
183
- onData: async (data) => {
184
- if (data.startsWith("{") && data.endsWith("}")) {
185
- await options.onStream?.(JSON.parse(data));
186
- }
187
- },
188
- }),
189
- },
190
- });
182
+ let progressTimeout;
183
+ const progressInterval = options.progressInterval ?? 30000;
184
+ async function progressRutine() {
185
+ try {
186
+ const total_bytes = await (0, fs_util_1.fastFolderSizeAsync)(options.target);
187
+ options.onStream?.({
188
+ message_type: "restore-status",
189
+ total_bytes,
190
+ });
191
+ }
192
+ finally {
193
+ if (typeof progressInterval === "number")
194
+ progressTimeout = setTimeout(progressRutine, progressInterval);
195
+ }
196
+ }
197
+ if (typeof progressInterval === "number")
198
+ progressRutine();
199
+ try {
200
+ return await this.exec(["restore", "--json", options.id, "--target", options.target], {
201
+ stderr: {
202
+ toExitCode: true,
203
+ },
204
+ stdout: {
205
+ ...(options.onStream && {
206
+ onData: async (data) => {
207
+ if (data.startsWith("{") && data.endsWith("}")) {
208
+ await options.onStream?.(JSON.parse(data));
209
+ }
210
+ },
211
+ }),
212
+ },
213
+ });
214
+ }
215
+ finally {
216
+ clearTimeout(progressTimeout);
217
+ }
191
218
  }
192
219
  }
193
220
  exports.ResticUtil = ResticUtil;
@@ -31,17 +31,17 @@ export declare const pkgPathParams: {
31
31
  [name in "temp" | Exclude<keyof ResolvePackagePathParamsType, "path">]: string;
32
32
  };
33
33
  export declare const pkgIncludeParams: {
34
- snapshotDate: string;
35
34
  packageName: string;
36
35
  temp: string;
37
36
  snapshotId: string;
37
+ snapshotDate: string;
38
38
  action: string;
39
39
  };
40
40
  export declare const pkgExcludeParams: {
41
- snapshotDate: string;
42
41
  packageName: string;
43
42
  temp: string;
44
43
  snapshotId: string;
44
+ snapshotDate: string;
45
45
  action: string;
46
46
  };
47
47
  export declare const pkgRestorePathParams: {
@@ -52,32 +52,32 @@ export declare const dbNameParams: {
52
52
  };
53
53
  export declare const params: {
54
54
  pkgPath: {
55
- snapshotDate: string;
56
55
  packageName: string;
57
56
  temp: string;
58
57
  snapshotId: string;
58
+ snapshotDate: string;
59
59
  action: string;
60
60
  };
61
61
  pkgRestorePath: {
62
- snapshotDate: string;
63
62
  packageName: string;
64
63
  path: string;
65
64
  temp: string;
66
65
  snapshotId: string;
66
+ snapshotDate: string;
67
67
  action: string;
68
68
  };
69
69
  pkgInclude: {
70
- snapshotDate: string;
71
70
  packageName: string;
72
71
  temp: string;
73
72
  snapshotId: string;
73
+ snapshotDate: string;
74
74
  action: string;
75
75
  };
76
76
  pkgExclude: {
77
- snapshotDate: string;
78
77
  packageName: string;
79
78
  temp: string;
80
79
  snapshotId: string;
80
+ snapshotDate: string;
81
81
  action: string;
82
82
  };
83
83
  dbName: {
package/util/fs-util.d.ts CHANGED
@@ -23,6 +23,7 @@ export declare function existsFile(path: string): Promise<boolean>;
23
23
  export declare function parentTmpDir(): string;
24
24
  export declare function sessionTmpDir(): string;
25
25
  export declare function tmpDir(prefix: string, id?: string): string;
26
+ export declare function fastFolderSizeAsync(path: string): Promise<number>;
26
27
  export declare function mkTmpDir(prefix: string, id?: string): Promise<string>;
27
28
  export declare function readPartialFile(path: string, positions: [number, number?]): Promise<string>;
28
29
  export declare function checkFile(path: string): Promise<boolean>;
@@ -56,6 +57,7 @@ export declare function writePathLists(options: {
56
57
  }>;
57
58
  export declare function copyFileWithStreams(source: string, target: string): Promise<unknown>;
58
59
  export declare function updateFileStats(path: string, fileInfo: Stats): Promise<void>;
60
+ export declare function isNotFoundError(error: unknown): boolean;
59
61
  export declare function cpy(options: {
60
62
  input: {
61
63
  type: "glob";
@@ -76,6 +78,7 @@ export declare function cpy(options: {
76
78
  * @default 1
77
79
  */
78
80
  concurrency?: number;
81
+ skipNotFoundError?: boolean;
79
82
  onPath?: (data: {
80
83
  isDir: boolean;
81
84
  entryPath: string;
package/util/fs-util.js CHANGED
@@ -3,11 +3,12 @@ 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.writePathLists = exports.writeGitIgnoreList = exports.fastglobToGitIgnore = exports.forEachFile = exports.readDir = exports.checkDir = exports.checkFile = exports.readPartialFile = exports.mkTmpDir = 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.isWSLSystem = void 0;
6
+ exports.cpy = exports.isNotFoundError = exports.updateFileStats = exports.copyFileWithStreams = exports.writePathLists = 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.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");
10
10
  const crypto_1 = require("crypto");
11
+ const fast_folder_size_1 = __importDefault(require("fast-folder-size"));
11
12
  const fast_glob_1 = __importDefault(require("fast-glob"));
12
13
  const fs_1 = require("fs");
13
14
  const fs_2 = require("fs");
@@ -17,6 +18,7 @@ const os_1 = require("os");
17
18
  const path_1 = require("path");
18
19
  const path_2 = require("path");
19
20
  const readline_1 = require("readline");
21
+ const util_1 = require("util");
20
22
  exports.isWSLSystem = (0, os_1.release)().includes("microsoft-standard-WSL");
21
23
  function isLocalDir(path) {
22
24
  return /^[\/\.]|([A-Z]:)/i.test(path);
@@ -130,6 +132,10 @@ function tmpDir(prefix, id) {
130
132
  return (0, path_1.join)(sessionTmpDir(), `${prefix}-${id}`);
131
133
  }
132
134
  exports.tmpDir = tmpDir;
135
+ async function fastFolderSizeAsync(path) {
136
+ return (await (0, util_1.promisify)(fast_folder_size_1.default)(path)) || 0;
137
+ }
138
+ exports.fastFolderSizeAsync = fastFolderSizeAsync;
133
139
  async function mkTmpDir(prefix, id) {
134
140
  const path = tmpDir(prefix, id);
135
141
  await (0, promises_1.mkdir)(path, { recursive: true });
@@ -367,6 +373,10 @@ async function updateFileStats(path, fileInfo) {
367
373
  await (0, promises_1.chown)(path, fileInfo.uid, fileInfo.gid);
368
374
  }
369
375
  exports.updateFileStats = updateFileStats;
376
+ function isNotFoundError(error) {
377
+ return error.code === "ENOENT";
378
+ }
379
+ exports.isNotFoundError = isNotFoundError;
370
380
  async function cpy(options) {
371
381
  const stats = { paths: 0, files: 0, dirs: 0 };
372
382
  const dirs = new Set();
@@ -404,17 +414,34 @@ async function cpy(options) {
404
414
  stats.files++;
405
415
  // https://github.com/nodejs/node/issues/44261
406
416
  if (exports.isWSLSystem) {
407
- const fileInfo = await (0, promises_1.stat)(entrySourcePath);
408
- const isWritable = (fileInfo.mode & 0o200) === 0o200;
409
- if (!isWritable) {
410
- await copyFileWithStreams(entrySourcePath, entryTargetPath);
411
- await updateFileStats(entryTargetPath, fileInfo);
412
- return;
417
+ let fileInfo;
418
+ try {
419
+ fileInfo = await (0, promises_1.stat)(entrySourcePath);
420
+ }
421
+ catch (error) {
422
+ const skipError = options.skipNotFoundError && isNotFoundError(error);
423
+ if (!skipError)
424
+ throw error;
425
+ }
426
+ if (fileInfo) {
427
+ const isWritable = (fileInfo.mode & 0o200) === 0o200;
428
+ if (!isWritable) {
429
+ await copyFileWithStreams(entrySourcePath, entryTargetPath);
430
+ await updateFileStats(entryTargetPath, fileInfo);
431
+ return;
432
+ }
413
433
  }
414
434
  }
415
- await (0, promises_1.cp)(entrySourcePath, entryTargetPath, {
416
- preserveTimestamps: true,
417
- });
435
+ try {
436
+ await (0, promises_1.cp)(entrySourcePath, entryTargetPath, {
437
+ preserveTimestamps: true,
438
+ });
439
+ }
440
+ catch (error) {
441
+ const skipError = options.skipNotFoundError && isNotFoundError(error);
442
+ if (!skipError)
443
+ throw error;
444
+ }
418
445
  }
419
446
  };
420
447
  const { input } = options;
@@ -34,7 +34,9 @@ async function exec(command, argv = [], options = null, settings = {}) {
34
34
  return new Promise(async (resolve, reject) => {
35
35
  if (log.exec) {
36
36
  const logEnv = log.envNames?.reduce((env, key) => {
37
- env[key] = options?.env?.[key] ?? "";
37
+ const value = options?.env?.[key];
38
+ if (typeof value !== "undefined")
39
+ env[key] = value;
38
40
  return env;
39
41
  }, {});
40
42
  (0, cli_util_1.logExec)(command, pipe
@@ -45,6 +45,7 @@ export declare type UnzipStreamDataType = {
45
45
  };
46
46
  };
47
47
  export declare function buildArguments(filters: (ZipDataFilterType | string)[]): string[];
48
+ export declare function checkSSEOption(command?: string): Promise<boolean>;
48
49
  export declare function zip(data: ZipDataType): Promise<{
49
50
  folders: number;
50
51
  files: number;
package/util/zip-util.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.unzip = exports.zip = exports.buildArguments = void 0;
3
+ exports.unzip = exports.zip = exports.checkSSEOption = exports.buildArguments = void 0;
4
4
  const process_util_1 = require("./process-util");
5
5
  const path_1 = require("path");
6
6
  function buildArguments(filters) {
@@ -60,6 +60,14 @@ function parseZipStream(chunk, buffer, cb) {
60
60
  }
61
61
  }
62
62
  }
63
+ let checkSSEOptionResult;
64
+ async function checkSSEOption(command = "7z") {
65
+ const result = await (0, process_util_1.exec)(command);
66
+ if (typeof checkSSEOptionResult === "boolean")
67
+ return checkSSEOptionResult;
68
+ return (checkSSEOptionResult = result.stdout.includes(" -sse"));
69
+ }
70
+ exports.checkSSEOption = checkSSEOption;
63
71
  async function zip(data) {
64
72
  let result = {
65
73
  folders: 0,
@@ -68,7 +76,9 @@ async function zip(data) {
68
76
  let buffer = {};
69
77
  await (0, process_util_1.exec)(data.command ?? "7z", [
70
78
  "a",
71
- "-mmt1",
79
+ // https://sourceforge.net/p/sevenzip/bugs/2099/,
80
+ // https://github.com/mcmilk/7-Zip/commit/87ba6f01ba3c5b2ce3186bddfe3d7d880639193c#diff-779d6b1bfa6196b288478f78ca96c4d4c6d7ac6cf8be15a28a20dabc9137ca36L515
81
+ ...((await checkSSEOption(data.command)) ? [] : ["-mmt1"]),
72
82
  "-bsp1",
73
83
  ...(data.deleteOnZip ? ["-sdel"] : []),
74
84
  (0, path_1.normalize)(data.output),
@@ -79,9 +89,7 @@ async function zip(data) {
79
89
  cwd: data.path,
80
90
  }, {
81
91
  log: data.verbose ?? false,
82
- stderr: {
83
- toExitCode: true,
84
- },
92
+ onExitCodeError: (data, error) => (data.exitCode > 2 ? error : false),
85
93
  stdout: {
86
94
  onData: (chunk) => {
87
95
  parseZipStream(chunk, buffer, (stream) => {
@@ -113,7 +121,6 @@ function parseUnzipStream(chunk, cb) {
113
121
  async function unzip(data) {
114
122
  return await (0, process_util_1.exec)(data.command ?? "7z", [
115
123
  "x",
116
- "-mmt1",
117
124
  "-bsp1",
118
125
  (0, path_1.normalize)(data.input),
119
126
  ...buildArguments(data.files ?? []),