react-native-platform-override 1.9.21 → 1.9.22

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 (48) hide show
  1. package/lib-commonjs/Api.d.ts +57 -57
  2. package/lib-commonjs/Api.js +187 -187
  3. package/lib-commonjs/BatchingQueue.d.ts +15 -15
  4. package/lib-commonjs/BatchingQueue.js +57 -57
  5. package/lib-commonjs/Cli.d.ts +7 -7
  6. package/lib-commonjs/Cli.js +323 -323
  7. package/lib-commonjs/CrossProcessLock.d.ts +44 -44
  8. package/lib-commonjs/CrossProcessLock.js +147 -147
  9. package/lib-commonjs/DiffStrategy.d.ts +24 -24
  10. package/lib-commonjs/DiffStrategy.js +34 -34
  11. package/lib-commonjs/FileRepository.d.ts +62 -62
  12. package/lib-commonjs/FileRepository.js +21 -21
  13. package/lib-commonjs/FileSearch.d.ts +21 -21
  14. package/lib-commonjs/FileSearch.js +77 -77
  15. package/lib-commonjs/FileSystemRepository.d.ts +20 -20
  16. package/lib-commonjs/FileSystemRepository.js +62 -62
  17. package/lib-commonjs/GitReactFileRepository.d.ts +56 -56
  18. package/lib-commonjs/GitReactFileRepository.js +202 -202
  19. package/lib-commonjs/Hash.d.ts +33 -33
  20. package/lib-commonjs/Hash.js +81 -81
  21. package/lib-commonjs/Manifest.d.ts +80 -80
  22. package/lib-commonjs/Manifest.js +157 -157
  23. package/lib-commonjs/Override.d.ts +182 -182
  24. package/lib-commonjs/Override.js +248 -248
  25. package/lib-commonjs/OverrideFactory.d.ts +33 -33
  26. package/lib-commonjs/OverrideFactory.js +85 -85
  27. package/lib-commonjs/OverridePrompt.d.ts +30 -30
  28. package/lib-commonjs/OverridePrompt.js +130 -130
  29. package/lib-commonjs/PackageUtils.d.ts +15 -15
  30. package/lib-commonjs/PackageUtils.js +40 -40
  31. package/lib-commonjs/PathUtils.d.ts +14 -14
  32. package/lib-commonjs/PathUtils.js +31 -31
  33. package/lib-commonjs/Serialized.d.ts +158 -158
  34. package/lib-commonjs/Serialized.js +145 -145
  35. package/lib-commonjs/UpgradeStrategy.d.ts +39 -39
  36. package/lib-commonjs/UpgradeStrategy.js +102 -102
  37. package/lib-commonjs/ValidationStrategy.d.ts +57 -57
  38. package/lib-commonjs/ValidationStrategy.js +124 -124
  39. package/lib-commonjs/refFromVersion.d.ts +10 -10
  40. package/lib-commonjs/refFromVersion.js +98 -98
  41. package/lib-commonjs/refFromVersion.js.map +1 -1
  42. package/lib-commonjs/scripts/generateManifest.d.ts +7 -7
  43. package/lib-commonjs/scripts/generateManifest.js +196 -196
  44. package/lib-commonjs/scripts/hashFile.d.ts +7 -7
  45. package/lib-commonjs/scripts/hashFile.js +17 -17
  46. package/lib-commonjs/scripts/testLocks.d.ts +1 -1
  47. package/lib-commonjs/scripts/testLocks.js +29 -29
  48. package/package.json +10 -10
@@ -1,324 +1,324 @@
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
- }
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
+ }
324
324
  //# sourceMappingURL=Cli.js.map