|
1 | 1 | /**
|
2 | 2 | * Script that runs after node modules have been installed (including Bazel managed
|
3 |
| - * node modules). This script can be used to apply postinstall patches. Similarly |
4 |
| - * to Bazel's "patches" attribute on repository fetch rules. |
| 3 | + * node modules). This script can be used to apply postinstall patches using commands. |
| 4 | + * |
| 5 | + * Most patches should be done using `patch-package` patches. |
5 | 6 | */
|
6 | 7 |
|
7 | 8 | const shelljs = require('shelljs');
|
8 | 9 | const path = require('path');
|
9 |
| -const fs = require('fs'); |
10 |
| -const inquirer = require('inquirer'); |
11 |
| -const chalk = require('chalk'); |
12 |
| - |
13 |
| -/** |
14 |
| - * Version of the post install patch. Needs to be incremented when |
15 |
| - * existing patches or edits have been modified. |
16 |
| - */ |
17 |
| -const PATCH_VERSION = 16; |
18 | 10 |
|
19 | 11 | /** Path to the project directory. */
|
20 | 12 | const projectDir = path.join(__dirname, '../..');
|
21 | 13 |
|
22 |
| -/** |
23 |
| - * Object that maps a given file path to a list of patches that need to be |
24 |
| - * applied. |
25 |
| - */ |
26 |
| -const PATCHES_PER_FILE = {}; |
27 |
| - |
28 |
| -const PATCH_MARKER_FILE_PATH = path.join(projectDir, 'node_modules/_ng-comp-patch-marker.json'); |
29 |
| - |
30 |
| -/** Registry of applied patches. */ |
31 |
| -let registry = null; |
32 |
| - |
33 | 14 | main();
|
34 | 15 |
|
35 | 16 | async function main() {
|
36 | 17 | shelljs.set('-e');
|
37 | 18 | shelljs.cd(projectDir);
|
38 | 19 |
|
39 |
| - registry = await readAndValidatePatchMarker(); |
40 |
| - |
41 | 20 | // Apply all patches synchronously.
|
42 | 21 | try {
|
43 | 22 | applyPatches();
|
44 | 23 | } catch (error) {
|
45 | 24 | console.error(error);
|
46 | 25 | process.exit(1);
|
47 | 26 | }
|
48 |
| - |
49 |
| - // Write the patch marker file so that we don't accidentally re-apply patches |
50 |
| - // in subsequent Yarn installations. |
51 |
| - fs.writeFileSync(PATCH_MARKER_FILE_PATH, JSON.stringify(registry, null, 2)); |
52 | 27 | }
|
53 | 28 |
|
54 | 29 | function applyPatches() {
|
55 |
| - // Switches the devmode output for Angular Bazel to ES2020 target and module. |
56 |
| - applyPatch(path.join(__dirname, './devmode-es2020-bazel.patch')); |
57 |
| - |
58 | 30 | // Similar to the `rxjs` performance improvement below, see:
|
59 | 31 | // https://github.com/angular/angular/pull/46187.
|
60 | 32 | shelljs.rm('-rf', ['node_modules/@angular/common/locales']);
|
@@ -89,125 +61,4 @@ function applyPatches() {
|
89 | 61 | 'node_modules/rxjs/Subscriber.*',
|
90 | 62 | 'node_modules/rxjs/Subscription.*',
|
91 | 63 | ]);
|
92 |
| - |
93 |
| - // Apply all collected patches on a per-file basis. This is necessary because |
94 |
| - // multiple edits might apply to the same file, and we only want to mark a given |
95 |
| - // file as patched once all edits have been made. |
96 |
| - Object.keys(PATCHES_PER_FILE).forEach(filePath => { |
97 |
| - if (isFilePatched(filePath)) { |
98 |
| - console.info('File ' + filePath + ' is already patched. Skipping..'); |
99 |
| - return; |
100 |
| - } |
101 |
| - |
102 |
| - let content = fs.readFileSync(filePath, 'utf8'); |
103 |
| - const patchFunctions = PATCHES_PER_FILE[filePath]; |
104 |
| - |
105 |
| - console.info(`Patching file ${filePath} with ${patchFunctions.length} edits..`); |
106 |
| - patchFunctions.forEach(patchFn => (content = patchFn(content))); |
107 |
| - |
108 |
| - fs.writeFileSync(filePath, content, 'utf8'); |
109 |
| - captureFileAsPatched(filePath); |
110 |
| - }); |
111 |
| -} |
112 |
| - |
113 |
| -/** |
114 |
| - * Applies the given patch if not done already. Throws if the patch |
115 |
| - * does not apply cleanly. |
116 |
| - */ |
117 |
| -function applyPatch(patchFile) { |
118 |
| - if (isFilePatched(patchFile)) { |
119 |
| - console.info('Patch: ' + patchFile + ' has been applied already. Skipping..'); |
120 |
| - return; |
121 |
| - } |
122 |
| - |
123 |
| - shelljs.cat(patchFile).exec('patch -p0'); |
124 |
| - captureFileAsPatched(patchFile); |
125 |
| -} |
126 |
| - |
127 |
| -/** |
128 |
| - * Schedules an edit where the specified file is read and its content replaced based on |
129 |
| - * the given search expression and corresponding replacement. Throws if no changes were made |
130 |
| - * and the patch has not been applied. |
131 |
| - */ |
132 |
| -function searchAndReplace(search, replacement, relativeFilePath) { |
133 |
| - const filePath = path.join(projectDir, relativeFilePath); |
134 |
| - const fileEdits = PATCHES_PER_FILE[filePath] || (PATCHES_PER_FILE[filePath] = []); |
135 |
| - |
136 |
| - fileEdits.push(originalContent => { |
137 |
| - const newFileContent = originalContent.replace(search, replacement); |
138 |
| - if (originalContent === newFileContent) { |
139 |
| - throw Error( |
140 |
| - `Could not perform replacement in: ${filePath}.\n` + `Searched for pattern: ${search}`, |
141 |
| - ); |
142 |
| - } |
143 |
| - return newFileContent; |
144 |
| - }); |
145 |
| -} |
146 |
| - |
147 |
| -/** Gets a project unique id for a given file path. */ |
148 |
| -function getIdForFile(filePath) { |
149 |
| - return path.relative(projectDir, filePath).replace(/\\/g, '/'); |
150 |
| -} |
151 |
| - |
152 |
| -/** Marks the specified file as patched. */ |
153 |
| -function captureFileAsPatched(filePath) { |
154 |
| - registry.patched[getIdForFile(filePath)] = true; |
155 |
| -} |
156 |
| - |
157 |
| -/** Checks whether the given file is patched. */ |
158 |
| -function isFilePatched(filePath) { |
159 |
| - return registry.patched[getIdForFile(filePath)] === true; |
160 |
| -} |
161 |
| - |
162 |
| -/** |
163 |
| - * Reads the patch marker from the node modules if present. Validates that applied |
164 |
| - * patches are up-to-date. If not, an error will be reported with a prompt that |
165 |
| - * allows convenient clean up of node modules in case those need to be cleaned up. |
166 |
| - */ |
167 |
| -async function readAndValidatePatchMarker() { |
168 |
| - if (!shelljs.test('-e', PATCH_MARKER_FILE_PATH)) { |
169 |
| - return {version: PATCH_VERSION, patched: {}}; |
170 |
| - } |
171 |
| - const registry = JSON.parse(shelljs.cat(PATCH_MARKER_FILE_PATH)); |
172 |
| - // If the node modules are up-to-date, return the parsed patch registry. |
173 |
| - if (registry.version === PATCH_VERSION) { |
174 |
| - return registry; |
175 |
| - } |
176 |
| - // Print errors that explain the current situation where patches from another |
177 |
| - // postinstall patch revision are applied in the current node modules. |
178 |
| - if (registry.version < PATCH_VERSION) { |
179 |
| - console.error(chalk.red('Your node modules have been patched by a previous Yarn install.')); |
180 |
| - console.error(chalk.red('The postinstall patches have changed since then, and in order to')); |
181 |
| - console.error(chalk.red('apply the most recent patches, your node modules need to be cleaned')); |
182 |
| - console.error(chalk.red('up from past changes.')); |
183 |
| - } else { |
184 |
| - console.error(chalk.red('Your node modules already have patches applied from a more recent.')); |
185 |
| - console.error(chalk.red('revision of the components repository. In order to be able to apply')); |
186 |
| - console.error(chalk.red('patches for the current revision, your node modules need to be')); |
187 |
| - console.error(chalk.red('cleaned up.')); |
188 |
| - } |
189 |
| - |
190 |
| - let cleanupModules = true; |
191 |
| - |
192 |
| - // Do not prompt if there is no TTY. Inquirer does not skip in non-tty environments. |
193 |
| - // TODO: Remove once inquirer has been updated to v8.x where TTY is respected. |
194 |
| - if (process.stdin.isTTY) { |
195 |
| - cleanupModules = ( |
196 |
| - await inquirer.prompt({ |
197 |
| - name: 'result', |
198 |
| - type: 'confirm', |
199 |
| - message: 'Clean up node modules automatically?', |
200 |
| - default: false, |
201 |
| - }) |
202 |
| - ).result; |
203 |
| - } |
204 |
| - |
205 |
| - if (cleanupModules) { |
206 |
| - // This re-runs Yarn with `--check-files` mode. The postinstall will rerun afterwards, |
207 |
| - // so we can exit with a zero exit-code here. |
208 |
| - shelljs.exec('yarn --check-files --frozen-lockfile', {cwd: projectDir}); |
209 |
| - process.exit(0); |
210 |
| - } else { |
211 |
| - process.exit(1); |
212 |
| - } |
213 | 64 | }
|
0 commit comments