react-native-platform-override 1.9.21 → 1.9.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib-commonjs/Api.d.ts +57 -57
- package/lib-commonjs/Api.js +187 -187
- package/lib-commonjs/BatchingQueue.d.ts +15 -15
- package/lib-commonjs/BatchingQueue.js +57 -57
- package/lib-commonjs/Cli.d.ts +7 -7
- package/lib-commonjs/Cli.js +323 -323
- package/lib-commonjs/CrossProcessLock.d.ts +44 -44
- package/lib-commonjs/CrossProcessLock.js +147 -147
- package/lib-commonjs/DiffStrategy.d.ts +24 -24
- package/lib-commonjs/DiffStrategy.js +34 -34
- package/lib-commonjs/FileRepository.d.ts +62 -62
- package/lib-commonjs/FileRepository.js +21 -21
- package/lib-commonjs/FileSearch.d.ts +21 -21
- package/lib-commonjs/FileSearch.js +77 -77
- package/lib-commonjs/FileSystemRepository.d.ts +20 -20
- package/lib-commonjs/FileSystemRepository.js +62 -62
- package/lib-commonjs/GitReactFileRepository.d.ts +56 -56
- package/lib-commonjs/GitReactFileRepository.js +202 -202
- package/lib-commonjs/Hash.d.ts +33 -33
- package/lib-commonjs/Hash.js +81 -81
- package/lib-commonjs/Manifest.d.ts +80 -80
- package/lib-commonjs/Manifest.js +157 -157
- package/lib-commonjs/Override.d.ts +182 -182
- package/lib-commonjs/Override.js +248 -248
- package/lib-commonjs/OverrideFactory.d.ts +33 -33
- package/lib-commonjs/OverrideFactory.js +85 -85
- package/lib-commonjs/OverridePrompt.d.ts +30 -30
- package/lib-commonjs/OverridePrompt.js +130 -130
- package/lib-commonjs/PackageUtils.d.ts +15 -15
- package/lib-commonjs/PackageUtils.js +40 -40
- package/lib-commonjs/PathUtils.d.ts +14 -14
- package/lib-commonjs/PathUtils.js +31 -31
- package/lib-commonjs/Serialized.d.ts +158 -158
- package/lib-commonjs/Serialized.js +145 -145
- package/lib-commonjs/UpgradeStrategy.d.ts +39 -39
- package/lib-commonjs/UpgradeStrategy.js +102 -102
- package/lib-commonjs/ValidationStrategy.d.ts +57 -57
- package/lib-commonjs/ValidationStrategy.js +124 -124
- package/lib-commonjs/refFromVersion.d.ts +10 -10
- package/lib-commonjs/refFromVersion.js +98 -98
- package/lib-commonjs/refFromVersion.js.map +1 -1
- package/lib-commonjs/scripts/generateManifest.d.ts +7 -7
- package/lib-commonjs/scripts/generateManifest.js +196 -196
- package/lib-commonjs/scripts/hashFile.d.ts +7 -7
- package/lib-commonjs/scripts/hashFile.js +17 -17
- package/lib-commonjs/scripts/testLocks.d.ts +1 -1
- package/lib-commonjs/scripts/testLocks.js +29 -29
- package/package.json +10 -10
package/lib-commonjs/Cli.js
CHANGED
|
@@ -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
|