react-native-platform-override 0.4.6 → 0.80.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/bin.js +1 -2
  2. package/lib-commonjs/Api.d.ts +57 -56
  3. package/lib-commonjs/Api.js +187 -167
  4. package/lib-commonjs/Api.js.map +1 -1
  5. package/lib-commonjs/BatchingQueue.d.ts +15 -15
  6. package/lib-commonjs/BatchingQueue.js +57 -57
  7. package/lib-commonjs/BatchingQueue.js.map +1 -1
  8. package/lib-commonjs/Cli.d.ts +7 -7
  9. package/lib-commonjs/Cli.js +323 -291
  10. package/lib-commonjs/Cli.js.map +1 -1
  11. package/lib-commonjs/CrossProcessLock.d.ts +44 -44
  12. package/lib-commonjs/CrossProcessLock.js +147 -144
  13. package/lib-commonjs/CrossProcessLock.js.map +1 -1
  14. package/lib-commonjs/DiffStrategy.d.ts +24 -24
  15. package/lib-commonjs/DiffStrategy.js +34 -34
  16. package/lib-commonjs/DiffStrategy.js.map +1 -1
  17. package/lib-commonjs/FileRepository.d.ts +63 -62
  18. package/lib-commonjs/FileRepository.js +21 -21
  19. package/lib-commonjs/FileRepository.js.map +1 -1
  20. package/lib-commonjs/FileSearch.d.ts +21 -21
  21. package/lib-commonjs/FileSearch.js +77 -91
  22. package/lib-commonjs/FileSearch.js.map +1 -1
  23. package/lib-commonjs/FileSystemRepository.d.ts +21 -20
  24. package/lib-commonjs/FileSystemRepository.js +62 -59
  25. package/lib-commonjs/FileSystemRepository.js.map +1 -1
  26. package/lib-commonjs/GitReactFileRepository.d.ts +57 -58
  27. package/lib-commonjs/GitReactFileRepository.js +202 -208
  28. package/lib-commonjs/GitReactFileRepository.js.map +1 -1
  29. package/lib-commonjs/Hash.d.ts +34 -33
  30. package/lib-commonjs/Hash.js +81 -81
  31. package/lib-commonjs/Hash.js.map +1 -1
  32. package/lib-commonjs/Manifest.d.ts +80 -80
  33. package/lib-commonjs/Manifest.js +157 -154
  34. package/lib-commonjs/Manifest.js.map +1 -1
  35. package/lib-commonjs/Override.d.ts +182 -182
  36. package/lib-commonjs/Override.js +248 -245
  37. package/lib-commonjs/Override.js.map +1 -1
  38. package/lib-commonjs/OverrideFactory.d.ts +33 -33
  39. package/lib-commonjs/OverrideFactory.js +85 -70
  40. package/lib-commonjs/OverrideFactory.js.map +1 -1
  41. package/lib-commonjs/OverridePrompt.d.ts +30 -30
  42. package/lib-commonjs/OverridePrompt.js +130 -104
  43. package/lib-commonjs/OverridePrompt.js.map +1 -1
  44. package/lib-commonjs/PackageUtils.d.ts +15 -15
  45. package/lib-commonjs/PackageUtils.js +40 -38
  46. package/lib-commonjs/PackageUtils.js.map +1 -1
  47. package/lib-commonjs/PathUtils.d.ts +14 -14
  48. package/lib-commonjs/PathUtils.js +31 -28
  49. package/lib-commonjs/PathUtils.js.map +1 -1
  50. package/lib-commonjs/Serialized.d.ts +158 -158
  51. package/lib-commonjs/Serialized.js +145 -119
  52. package/lib-commonjs/Serialized.js.map +1 -1
  53. package/lib-commonjs/UpgradeStrategy.d.ts +39 -39
  54. package/lib-commonjs/UpgradeStrategy.js +102 -99
  55. package/lib-commonjs/UpgradeStrategy.js.map +1 -1
  56. package/lib-commonjs/ValidationStrategy.d.ts +57 -57
  57. package/lib-commonjs/ValidationStrategy.js +124 -124
  58. package/lib-commonjs/ValidationStrategy.js.map +1 -1
  59. package/lib-commonjs/refFromVersion.d.ts +10 -0
  60. package/lib-commonjs/refFromVersion.js +99 -0
  61. package/lib-commonjs/refFromVersion.js.map +1 -0
  62. package/lib-commonjs/scripts/generateManifest.d.ts +7 -7
  63. package/lib-commonjs/scripts/generateManifest.js +196 -170
  64. package/lib-commonjs/scripts/generateManifest.js.map +1 -1
  65. package/lib-commonjs/scripts/hashFile.d.ts +7 -7
  66. package/lib-commonjs/scripts/hashFile.js +17 -14
  67. package/lib-commonjs/scripts/hashFile.js.map +1 -1
  68. package/lib-commonjs/scripts/testLocks.d.ts +1 -1
  69. package/lib-commonjs/scripts/testLocks.js +29 -26
  70. package/lib-commonjs/scripts/testLocks.js.map +1 -1
  71. package/package.json +53 -43
  72. package/CHANGELOG.json +0 -524
  73. package/CHANGELOG.md +0 -230
@@ -1,292 +1,324 @@
1
- "use strict";
2
- /**
3
- * Copyright (c) Microsoft Corporation.
4
- * Licensed under the MIT License.
5
- *
6
- * @format
7
- */
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- const Api = require("./Api");
10
- const chalk = require("chalk");
11
- const ora = require("ora");
12
- const path = require("path");
13
- const yargs = require("yargs");
14
- const FileSearch_1 = require("./FileSearch");
15
- const OverridePrompt_1 = require("./OverridePrompt");
16
- const CrossProcessLock_1 = require("./CrossProcessLock");
17
- const GitReactFileRepository_1 = require("./GitReactFileRepository");
18
- const PackageUtils_1 = require("./PackageUtils");
19
- void doMain(async () => {
20
- const npmPackage = await PackageUtils_1.getNpmPackage();
21
- return new Promise((resolve, _reject) => {
22
- yargs
23
- .command('validate', 'Verify that overrides are recorded and up-to-date', cmdYargs => cmdYargs.options({
24
- manifest: {
25
- type: 'string',
26
- describe: 'Optional path to the override manifest to validate',
27
- },
28
- version: {
29
- type: 'string',
30
- describe: 'Optional React Native version to check against',
31
- },
32
- }),
33
- // eslint-disable-next-line @typescript-eslint/no-misused-promises
34
- cmdArgv => validateManifests({
35
- manifestPath: cmdArgv.manifest,
36
- reactNativeVersion: cmdArgv.version,
37
- }))
38
- .command('add <override>', 'Add an override to the manifest', cmdYargs => cmdYargs.options({
39
- override: { type: 'string', describe: 'The override to add' },
40
- }),
41
- // eslint-disable-next-line @typescript-eslint/no-misused-promises
42
- cmdArgv => addOverride(cmdArgv.override))
43
- .command('remove <override>', 'Remove an override from the manifest', cmdYargs => cmdYargs.options({
44
- override: { type: 'string', describe: 'The override to remove' },
45
- }),
46
- // eslint-disable-next-line @typescript-eslint/no-misused-promises
47
- cmdArgv => removeOverride(cmdArgv.override))
48
- .command('diff <override>', 'Compares an override to the base file of its current version', cmdYargs => cmdYargs.options({
49
- override: { type: 'string', describe: 'The override to add' },
50
- }),
51
- // eslint-disable-next-line @typescript-eslint/no-misused-promises
52
- cmdArgv => diffOverride(cmdArgv.override))
53
- .command('upgrade', 'Attempts to automatically merge new changes into out-of-date overrides', cmdYargs => cmdYargs.options({
54
- manifest: {
55
- type: 'string',
56
- describe: 'Optional path to the override manifests to validate',
57
- },
58
- conflicts: {
59
- type: 'boolean',
60
- default: true,
61
- describe: 'Whether to allow merge conflicts to be written',
62
- },
63
- version: {
64
- type: 'string',
65
- describe: 'Optional React Native version to check against',
66
- },
67
- }),
68
- // eslint-disable-next-line @typescript-eslint/no-misused-promises
69
- cmdArgv => upgrade({
70
- manifestPath: cmdArgv.manifest,
71
- reactNativeVersion: cmdArgv.version,
72
- allowConflicts: cmdArgv.conflicts,
73
- }))
74
- .epilogue(npmPackage.description)
75
- .option('color', { hidden: true })
76
- .option('githubToken', {
77
- description: 'Optional PAT to use for GitHub API calls',
78
- type: 'string',
79
- })
80
- .middleware(argv => {
81
- if (argv.githubToken) {
82
- GitReactFileRepository_1.default.setGithubToken(argv.githubToken);
83
- }
84
- })
85
- .demandCommand()
86
- .recommendCommands()
87
- .strict()
88
- .showHelpOnFail(false)
89
- .wrap(yargs.terminalWidth())
90
- .version(false)
91
- .scriptName(npmPackage.name)
92
- .onFinishCommand(resolve).argv;
93
- });
94
- });
95
- /**
96
- * Check that the given manifest correctly describe overrides and that all
97
- * overrides are up to date
98
- */
99
- async function validateManifests(opts) {
100
- const manifests = opts.manifestPath
101
- ? [opts.manifestPath]
102
- : await enumerateManifests();
103
- const spinner = ora();
104
- await spinnerGuard(spinner, async () => {
105
- // Perform validation sequentially because validation has internal
106
- // concurrency
107
- const errors = [];
108
- for (const manifest of manifests) {
109
- spinner.text = `Validating ${manifest}`;
110
- spinner.start();
111
- const manifestErrors = await Api.validateManifest(manifest, opts);
112
- if (manifestErrors.length !== 0) {
113
- errors.push(
114
- // Add the manifest path to the override name to disambiguate between different packages
115
- ...manifestErrors.map(e => (Object.assign(Object.assign({}, e), { overrideName: path.join(path.dirname(manifest), e.overrideName) }))));
116
- }
117
- }
118
- if (errors.length === 0) {
119
- spinner.text = 'Validation succeeded';
120
- spinner.succeed();
121
- }
122
- else {
123
- spinner.text = 'Validation failed';
124
- spinner.fail();
125
- await printValidationErrors(errors);
126
- process.exitCode = 1;
127
- }
128
- });
129
- }
130
- /**
131
- * Add an override to the manifest
132
- */
133
- async function addOverride(overridePath) {
134
- const manifestPath = await FileSearch_1.findManifest(path.dirname(overridePath));
135
- const manifestDir = path.dirname(manifestPath);
136
- const overrideName = path.relative(manifestDir, path.resolve(overridePath));
137
- if (await Api.hasOverride(overrideName, manifestPath)) {
138
- console.warn(chalk.yellow('Warning: override already exists in manifest and will be overwritten'));
139
- }
140
- const overrideDetails = await OverridePrompt_1.promptForOverrideDetails();
141
- const spinner = ora('Adding override').start();
142
- await spinnerGuard(spinner, async () => {
143
- const override = await OverridePrompt_1.overrideFromDetails(overridePath, overrideDetails, await Api.getOverrideFactory(manifestPath));
144
- await Api.removeOverride(overrideName, manifestPath);
145
- await Api.addOverride(override, manifestPath);
146
- spinner.succeed();
147
- });
148
- }
149
- /**
150
- * Remove an override from the manifest
151
- */
152
- async function removeOverride(overridePath) {
153
- const manifestPath = await FileSearch_1.findManifest(path.dirname(overridePath));
154
- const manifestDir = path.dirname(manifestPath);
155
- const overrideName = path.relative(manifestDir, path.resolve(overridePath));
156
- if (await Api.removeOverride(overrideName, manifestPath)) {
157
- console.log(chalk.greenBright('Override successfully removed'));
158
- }
159
- else {
160
- console.error(chalk.red('Could not remove override. Is it part of the manifest?'));
161
- process.exit(1);
162
- }
163
- }
164
- /**
165
- * Diffs an override against its base file
166
- */
167
- async function diffOverride(overridePath) {
168
- const manifestPath = await FileSearch_1.findManifest(path.dirname(overridePath));
169
- const manifestDir = path.dirname(manifestPath);
170
- const overrideName = path.relative(manifestDir, path.resolve(overridePath));
171
- const diff = await Api.diffOverride(overrideName, manifestPath);
172
- const colorizedDiff = diff
173
- .split('\n')
174
- .map(line => line.startsWith('+')
175
- ? chalk.green(line)
176
- : line.startsWith('-')
177
- ? chalk.red(line)
178
- : line)
179
- .join('\n');
180
- console.log(colorizedDiff);
181
- }
182
- /**
183
- * Attempts to automatically merge changes from the current version into
184
- * out-of-date overrides.
185
- */
186
- async function upgrade(opts) {
187
- const manifests = opts.manifestPath
188
- ? [opts.manifestPath]
189
- : await enumerateManifests();
190
- for (const manifest of manifests) {
191
- await upgradeManifest(manifest, opts);
192
- }
193
- }
194
- async function upgradeManifest(manifestPath, opts) {
195
- const spinner = ora(`Merging overrides in ${manifestPath}`).start();
196
- await spinnerGuard(spinner, async () => {
197
- const upgradeResults = await Api.upgradeOverrides(manifestPath, Object.assign(Object.assign({}, opts), { progressListener: (currentOverride, totalOverrides) => (spinner.text = `Merging overrides in ${manifestPath} (${currentOverride}/${totalOverrides})`) }));
198
- spinner.succeed();
199
- printUpgradeStats(upgradeResults, opts.allowConflicts);
200
- });
201
- }
202
- /**
203
- * Print statistics about an attempt to upgrade out-of-date-overrides.
204
- */
205
- function printUpgradeStats(results, allowConflicts) {
206
- const numTotal = results.length;
207
- const numConflicts = results.filter(res => res.hasConflicts).length;
208
- const numAutoPatched = numTotal - numConflicts;
209
- if (numTotal === 0) {
210
- console.log(chalk.greenBright('No out-of-date overrides detected'));
211
- }
212
- else {
213
- console.log(chalk.greenBright(`${numAutoPatched}/${numTotal} out-of-date overrides automatically merged`));
214
- }
215
- if (allowConflicts && numConflicts > 0) {
216
- console.log(chalk.yellowBright(`${numConflicts} overrides require manual resolution`));
217
- }
218
- }
219
- /**
220
- * Prints validation errors in a user-readable form to stderr
221
- */
222
- async function printValidationErrors(errors) {
223
- if (errors.length === 0) {
224
- return;
225
- }
226
- const npmPackage = await PackageUtils_1.getNpmPackage();
227
- // Add an initial line of separation
228
- console.error();
229
- printErrorType('missingFromManifest', errors, `Found override files that aren't listed in the manifest. Overrides can be added to the manifest by using 'npx ${npmPackage.name} add <override>':`);
230
- printErrorType('overrideNotFound', errors, `Found overrides in the manifest that don't exist on disk. Remove existing overrides using 'npx ${npmPackage.name} remove <override>':`);
231
- printErrorType('baseNotFound', errors, `Found overrides whose base files do not exist. Remove existing overrides using 'npx ${npmPackage.name} remove <override>':`);
232
- printErrorType('outOfDate', errors, `Found overrides whose original files have changed. Upgrade overrides using 'npx ${npmPackage.name} upgrade':`);
233
- printErrorType('overrideDifferentFromBase', errors, 'The following overrides should be an exact copy of their base files. Ensure overrides are up to date or revert changes:');
234
- printErrorType('overrideSameAsBase', errors, 'The following overrides are identical to their base files. Please remove them or set their type to "copy":');
235
- printErrorType('expectedFile', errors, 'The following overrides should operate on files, but list directories:');
236
- printErrorType('expectedDirectory', errors, 'The following overrides should operate on directories, but listed files:');
237
- }
238
- /**
239
- * Print validation errors of a speccific type
240
- */
241
- function printErrorType(type, errors, message) {
242
- const filteredErrors = errors.filter(err => err.type === type);
243
- filteredErrors.sort((a, b) => a.overrideName.localeCompare(b.overrideName, 'en'));
244
- if (filteredErrors.length > 0) {
245
- console.error(chalk.red(message));
246
- filteredErrors.forEach(err => {
247
- console.error(` - ${err.overrideName}`);
248
- });
249
- console.error();
250
- }
251
- }
252
- /**
253
- * Wraps the function in a try/catch, failing the spinner if an exception is
254
- * thrown to allow unmangled output
255
- */
256
- async function spinnerGuard(spinner, fn) {
257
- try {
258
- return await fn();
259
- }
260
- catch (ex) {
261
- if (spinner.isSpinning) {
262
- spinner.fail();
263
- }
264
- throw ex;
265
- }
266
- }
267
- /**
268
- * Wrap the main function around a barrier to ensure only one copy of the
269
- * override tool is running at once. This is needed to avoid multiple tools
270
- * accessing the same local Git repo at the same time.
271
- */
272
- async function doMain(fn) {
273
- const lock = new CrossProcessLock_1.default(`${(await PackageUtils_1.getNpmPackage()).name}-cli-lock`);
274
- if (!(await lock.tryLock())) {
275
- const spinner = ora('Waiting for other instances of the override CLI to finish').start();
276
- await lock.lock();
277
- spinner.stop();
278
- }
279
- await fn();
280
- await lock.unlock();
281
- }
282
- /**
283
- * Check that a manifest exists, and return all that are found
284
- */
285
- async function enumerateManifests() {
286
- const manifests = await FileSearch_1.findAllManifests();
287
- if (manifests.length === 0) {
288
- throw new Error('No override manifests were found relative to the current directory');
289
- }
290
- return manifests;
291
- }
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) Microsoft Corporation.
4
+ * Licensed under the MIT License.
5
+ *
6
+ * @format
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
21
+ }) : function(o, v) {
22
+ o["default"] = v;
23
+ });
24
+ var __importStar = (this && this.__importStar) || function (mod) {
25
+ if (mod && mod.__esModule) return mod;
26
+ var result = {};
27
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
28
+ __setModuleDefault(result, mod);
29
+ return result;
30
+ };
31
+ var __importDefault = (this && this.__importDefault) || function (mod) {
32
+ return (mod && mod.__esModule) ? mod : { "default": mod };
33
+ };
34
+ Object.defineProperty(exports, "__esModule", { value: true });
35
+ const Api = __importStar(require("./Api"));
36
+ const chalk_1 = __importDefault(require("chalk"));
37
+ const ora_1 = __importDefault(require("ora"));
38
+ const path_1 = __importDefault(require("path"));
39
+ const yargs_1 = __importDefault(require("yargs"));
40
+ const FileSearch_1 = require("./FileSearch");
41
+ const OverridePrompt_1 = require("./OverridePrompt");
42
+ const CrossProcessLock_1 = __importDefault(require("./CrossProcessLock"));
43
+ const GitReactFileRepository_1 = __importDefault(require("./GitReactFileRepository"));
44
+ const PackageUtils_1 = require("./PackageUtils");
45
+ void doMain(async () => {
46
+ const npmPackage = await (0, PackageUtils_1.getNpmPackage)();
47
+ return new Promise((resolve, _reject) => {
48
+ yargs_1.default
49
+ .command('validate', 'Verify that overrides are recorded and up-to-date', cmdYargs => cmdYargs.options({
50
+ manifest: {
51
+ type: 'string',
52
+ describe: 'Optional path to the override manifest to validate',
53
+ },
54
+ version: {
55
+ type: 'string',
56
+ describe: 'Optional React Native version to check against',
57
+ },
58
+ }),
59
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
60
+ cmdArgv => validateManifests({
61
+ manifestPath: cmdArgv.manifest,
62
+ reactNativeVersion: cmdArgv.version,
63
+ }))
64
+ .command('add <override>', 'Add an override to the manifest', cmdYargs => cmdYargs.options({
65
+ override: { type: 'string', describe: 'The override to add' },
66
+ }),
67
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
68
+ cmdArgv => addOverride(cmdArgv.override))
69
+ .command('remove <override>', 'Remove an override from the manifest', cmdYargs => cmdYargs.options({
70
+ override: { type: 'string', describe: 'The override to remove' },
71
+ }),
72
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
73
+ cmdArgv => removeOverride(cmdArgv.override))
74
+ .command('diff <override>', 'Compares an override to the base file of its current version', cmdYargs => cmdYargs.options({
75
+ override: { type: 'string', describe: 'The override to add' },
76
+ }),
77
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
78
+ cmdArgv => diffOverride(cmdArgv.override))
79
+ .command('upgrade', 'Attempts to automatically merge new changes into out-of-date overrides', cmdYargs => cmdYargs.options({
80
+ manifest: {
81
+ type: 'string',
82
+ describe: 'Optional path to the override manifests to validate',
83
+ },
84
+ conflicts: {
85
+ type: 'boolean',
86
+ default: true,
87
+ describe: 'Whether to allow merge conflicts to be written',
88
+ },
89
+ version: {
90
+ type: 'string',
91
+ describe: 'Optional React Native version to check against',
92
+ },
93
+ }),
94
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
95
+ cmdArgv => upgrade({
96
+ manifestPath: cmdArgv.manifest,
97
+ reactNativeVersion: cmdArgv.version,
98
+ allowConflicts: cmdArgv.conflicts,
99
+ }))
100
+ .epilogue(npmPackage.description)
101
+ .option('color', { hidden: true })
102
+ .option('githubToken', {
103
+ description: 'Optional PAT to use for GitHub API calls',
104
+ type: 'string',
105
+ })
106
+ .middleware(argv => {
107
+ if (argv.githubToken) {
108
+ GitReactFileRepository_1.default.setGithubToken(argv.githubToken);
109
+ }
110
+ })
111
+ .demandCommand()
112
+ .recommendCommands()
113
+ .strict()
114
+ .showHelpOnFail(false)
115
+ .wrap(yargs_1.default.terminalWidth())
116
+ .version(false)
117
+ .scriptName(npmPackage.name)
118
+ .onFinishCommand(resolve).argv;
119
+ });
120
+ });
121
+ /**
122
+ * Check that the given manifest correctly describe overrides and that all
123
+ * overrides are up to date
124
+ */
125
+ async function validateManifests(opts) {
126
+ const manifests = opts.manifestPath
127
+ ? [opts.manifestPath]
128
+ : await enumerateManifests();
129
+ const spinner = (0, ora_1.default)();
130
+ await spinnerGuard(spinner, async () => {
131
+ // Perform validation sequentially because validation has internal
132
+ // concurrency
133
+ const errors = [];
134
+ for (const manifest of manifests) {
135
+ spinner.text = `Validating ${manifest}`;
136
+ spinner.start();
137
+ const manifestErrors = await Api.validateManifest(manifest, opts);
138
+ if (manifestErrors.length !== 0) {
139
+ errors.push(
140
+ // Add the manifest path to the override name to disambiguate between different packages
141
+ ...manifestErrors.map(e => ({
142
+ ...e,
143
+ overrideName: path_1.default.join(path_1.default.dirname(manifest), e.overrideName),
144
+ })));
145
+ }
146
+ }
147
+ if (errors.length === 0) {
148
+ spinner.text = 'Validation succeeded';
149
+ spinner.succeed();
150
+ }
151
+ else {
152
+ spinner.text = 'Validation failed';
153
+ spinner.fail();
154
+ await printValidationErrors(errors);
155
+ process.exitCode = 1;
156
+ }
157
+ });
158
+ }
159
+ /**
160
+ * Add an override to the manifest
161
+ */
162
+ async function addOverride(overridePath) {
163
+ const manifestPath = await (0, FileSearch_1.findManifest)(path_1.default.dirname(overridePath));
164
+ const manifestDir = path_1.default.dirname(manifestPath);
165
+ const overrideName = path_1.default.relative(manifestDir, path_1.default.resolve(overridePath));
166
+ if (await Api.hasOverride(overrideName, manifestPath)) {
167
+ console.warn(chalk_1.default.yellow('Warning: override already exists in manifest and will be overwritten'));
168
+ }
169
+ const overrideDetails = await (0, OverridePrompt_1.promptForOverrideDetails)();
170
+ const spinner = (0, ora_1.default)('Adding override').start();
171
+ await spinnerGuard(spinner, async () => {
172
+ const override = await (0, OverridePrompt_1.overrideFromDetails)(overridePath, overrideDetails, await Api.getOverrideFactory(manifestPath));
173
+ await Api.removeOverride(overrideName, manifestPath);
174
+ await Api.addOverride(override, manifestPath);
175
+ spinner.succeed();
176
+ });
177
+ }
178
+ /**
179
+ * Remove an override from the manifest
180
+ */
181
+ async function removeOverride(overridePath) {
182
+ const manifestPath = await (0, FileSearch_1.findManifest)(path_1.default.dirname(overridePath));
183
+ const manifestDir = path_1.default.dirname(manifestPath);
184
+ const overrideName = path_1.default.relative(manifestDir, path_1.default.resolve(overridePath));
185
+ if (await Api.removeOverride(overrideName, manifestPath)) {
186
+ console.log(chalk_1.default.greenBright('Override successfully removed'));
187
+ }
188
+ else {
189
+ console.error(chalk_1.default.red('Could not remove override. Is it part of the manifest?'));
190
+ process.exit(1);
191
+ }
192
+ }
193
+ /**
194
+ * Diffs an override against its base file
195
+ */
196
+ async function diffOverride(overridePath) {
197
+ const manifestPath = await (0, FileSearch_1.findManifest)(path_1.default.dirname(overridePath));
198
+ const manifestDir = path_1.default.dirname(manifestPath);
199
+ const overrideName = path_1.default.relative(manifestDir, path_1.default.resolve(overridePath));
200
+ const diff = await Api.diffOverride(overrideName, manifestPath);
201
+ const colorizedDiff = diff
202
+ .split('\n')
203
+ .map(line => line.startsWith('+')
204
+ ? chalk_1.default.green(line)
205
+ : line.startsWith('-')
206
+ ? chalk_1.default.red(line)
207
+ : line)
208
+ .join('\n');
209
+ console.log(colorizedDiff);
210
+ }
211
+ /**
212
+ * Attempts to automatically merge changes from the current version into
213
+ * out-of-date overrides.
214
+ */
215
+ async function upgrade(opts) {
216
+ const manifests = opts.manifestPath
217
+ ? [opts.manifestPath]
218
+ : await enumerateManifests();
219
+ for (const manifest of manifests) {
220
+ await upgradeManifest(manifest, opts);
221
+ }
222
+ }
223
+ async function upgradeManifest(manifestPath, opts) {
224
+ const spinner = (0, ora_1.default)(`Merging overrides in ${manifestPath}`).start();
225
+ await spinnerGuard(spinner, async () => {
226
+ const upgradeResults = await Api.upgradeOverrides(manifestPath, {
227
+ ...opts,
228
+ progressListener: (currentOverride, totalOverrides) => (spinner.text = `Merging overrides in ${manifestPath} (${currentOverride}/${totalOverrides})`),
229
+ });
230
+ spinner.succeed();
231
+ printUpgradeStats(upgradeResults, opts.allowConflicts);
232
+ });
233
+ }
234
+ /**
235
+ * Print statistics about an attempt to upgrade out-of-date-overrides.
236
+ */
237
+ function printUpgradeStats(results, allowConflicts) {
238
+ const numTotal = results.length;
239
+ const numConflicts = results.filter(res => res.hasConflicts).length;
240
+ const numAutoPatched = numTotal - numConflicts;
241
+ if (numTotal === 0) {
242
+ console.log(chalk_1.default.greenBright('No out-of-date overrides detected'));
243
+ }
244
+ else {
245
+ console.log(chalk_1.default.greenBright(`${numAutoPatched}/${numTotal} out-of-date overrides automatically merged`));
246
+ }
247
+ if (allowConflicts && numConflicts > 0) {
248
+ console.log(chalk_1.default.yellowBright(`${numConflicts} overrides require manual resolution`));
249
+ }
250
+ }
251
+ /**
252
+ * Prints validation errors in a user-readable form to stderr
253
+ */
254
+ async function printValidationErrors(errors) {
255
+ if (errors.length === 0) {
256
+ return;
257
+ }
258
+ const npmPackage = await (0, PackageUtils_1.getNpmPackage)();
259
+ // Add an initial line of separation
260
+ console.error();
261
+ printErrorType('missingFromManifest', errors, `Found override files that aren't listed in the manifest. Overrides can be added to the manifest by using 'npx ${npmPackage.name} add <override>':`);
262
+ printErrorType('overrideNotFound', errors, `Found overrides in the manifest that don't exist on disk. Remove existing overrides using 'npx ${npmPackage.name} remove <override>':`);
263
+ printErrorType('baseNotFound', errors, `Found overrides whose base files do not exist. Remove existing overrides using 'npx ${npmPackage.name} remove <override>':`);
264
+ printErrorType('outOfDate', errors, `Found overrides whose original files have changed. Upgrade overrides using 'npx ${npmPackage.name} upgrade':`);
265
+ printErrorType('overrideDifferentFromBase', errors, 'The following overrides should be an exact copy of their base files. Ensure overrides are up to date or revert changes:');
266
+ printErrorType('overrideSameAsBase', errors, 'The following overrides are identical to their base files. Please remove them or set their type to "copy":');
267
+ printErrorType('expectedFile', errors, 'The following overrides should operate on files, but list directories:');
268
+ printErrorType('expectedDirectory', errors, 'The following overrides should operate on directories, but listed files:');
269
+ }
270
+ /**
271
+ * Print validation errors of a specific type
272
+ */
273
+ function printErrorType(type, errors, message) {
274
+ const filteredErrors = errors.filter(err => err.type === type);
275
+ filteredErrors.sort((a, b) => a.overrideName.localeCompare(b.overrideName, 'en'));
276
+ if (filteredErrors.length > 0) {
277
+ console.error(chalk_1.default.red(message));
278
+ filteredErrors.forEach(err => {
279
+ console.error(` - ${err.overrideName}`);
280
+ });
281
+ console.error();
282
+ }
283
+ }
284
+ /**
285
+ * Wraps the function in a try/catch, failing the spinner if an exception is
286
+ * thrown to allow unmangled output
287
+ */
288
+ async function spinnerGuard(spinner, fn) {
289
+ try {
290
+ return await fn();
291
+ }
292
+ catch (ex) {
293
+ if (spinner.isSpinning) {
294
+ spinner.fail();
295
+ }
296
+ throw ex;
297
+ }
298
+ }
299
+ /**
300
+ * Wrap the main function around a barrier to ensure only one copy of the
301
+ * override tool is running at once. This is needed to avoid multiple tools
302
+ * accessing the same local Git repo at the same time.
303
+ */
304
+ async function doMain(fn) {
305
+ const lock = new CrossProcessLock_1.default(`${(await (0, PackageUtils_1.getNpmPackage)()).name}-cli-lock`);
306
+ if (!(await lock.tryLock())) {
307
+ const spinner = (0, ora_1.default)('Waiting for other instances of the override CLI to finish').start();
308
+ await lock.lock();
309
+ spinner.stop();
310
+ }
311
+ await fn();
312
+ await lock.unlock();
313
+ }
314
+ /**
315
+ * Check that a manifest exists, and return all that are found
316
+ */
317
+ async function enumerateManifests() {
318
+ const manifests = await (0, FileSearch_1.findAllManifests)();
319
+ if (manifests.length === 0) {
320
+ throw new Error('No override manifests were found relative to the current directory');
321
+ }
322
+ return manifests;
323
+ }
292
324
  //# sourceMappingURL=Cli.js.map