replace-fork: Cleanup after failure if no unstaged changes (#22364)
Brian Vaughn committed
Sep 20, 2021 at 11:10 UTC
57e4d6872fe5786220d23aa4781ff33af65ffeaa
1 file changed
+60
-19
scripts/merge-fork/replace-fork.js
+60
-19
@@ -4,9 +4,10 @@
4
5
// Copies the contents of the new fork into the old fork
6
7
+const chalk = require('chalk');
8
const {promisify} = require('util');
9
const glob = promisify(require('glob'));
9
-const {spawnSync} = require('child_process');
10
+const {execSync, spawnSync} = require('child_process');
11
const fs = require('fs');
12
const minimist = require('minimist');
13
@@ -18,31 +19,71 @@ const argv = minimist(process.argv.slice(2), {
19
});
20
21
async function main() {
22
+ const status = execSync('git status').toString();
23
+ const hadUnstagedChanges = status.includes('Changes not staged for commit');
24
+ if (hadUnstagedChanges) {
25
+ const readline = require('readline');
26
+ const rl = readline.createInterface({
27
+ input: process.stdin,
28
+ output: process.stdout,
29
+ });
30
+
31
+ await new Promise(resolve => {
32
+ rl.question(
33
+ `\n${chalk.yellow.bold(
34
+ 'Unstaged changes were found in repository.'
35
+ )} Do you want to continue? (Y/n) `,
36
+ input => {
37
+ switch (input.trim().toLowerCase()) {
38
+ case '':
39
+ case 'y':
40
+ case 'yes':
41
+ resolve();
42
+ break;
43
+ default:
44
+ console.log('No modifications were made.');
45
+ process.exit(0);
46
+ break;
47
+ }
48
+ }
49
+ );
50
+ });
51
+ }
52
+
53
const oldFilenames = await glob('packages/react-reconciler/**/*.old.js');
54
await Promise.all(oldFilenames.map(unforkFile));
55
56
// Use ESLint to autofix imports
25
- spawnSync('yarn', ['linc', '--fix'], {
57
+ const command = spawnSync('yarn', ['linc', '--fix'], {
58
stdio: ['inherit', 'inherit', 'pipe'],
59
});
28
- // TODO: If eslint crashes, it may not have successfully fixed all
29
- // the imports, which would leave the reconciler files in an inconsistent
30
- // state. So we used to crash and reset the working directory. But that
31
- // solution assumed that the working directory was clean before you run the
32
- // command — if it wasn't, it'll not only reset the synced reconciler files,
33
- // but all the other uncommitted changes.
34
- //
35
- // We need a different strategy to prevent loss of work. For example, we could
36
- // exit early if the working directory is not clean before you run the script.
37
- //
38
- // Until we think of something better, I've commmented out this branch to
39
- // prevent work from accidentally being lost.
40
- // if (spawn.stderr.toString() !== '') {
41
- // spawnSync('git', ['checkout', '.']);
60
+ if (command.status === 1) {
61
+ console.log(
62
+ chalk.bold.red('\nreplace-fork script failed with the following error:')
63
+ );
64
+ console.error(Error(command.stderr));
65
43
- // console.log(Error(spawn.stderr));
44
- // process.exitCode = 1;
45
- // }
66
+ // If eslint crashes, it may not have successfully fixed all the imports,
67
+ // which would leave the reconciler files in an inconsistent stat.
68
+ // It would be nice to clean up the working directory in this case,
69
+ // but it's only safe to do that if we aren't going to override any previous changes.
70
+ if (!hadUnstagedChanges) {
71
+ spawnSync('git', ['checkout', '.']);
72
+ } else {
73
+ console.log(
74
+ `\n${chalk.yellow.bold(
75
+ 'Unstaged changes were present when `replace-fork` was run.'
76
+ )} ` +
77
+ `To cleanup the repository run:\n ${chalk.bold(
78
+ 'git checkout packages/react-reconciler'
79
+ )}`
80
+ );
81
+ }
82
+
83
+ process.exit(1);
84
+ } else {
85
+ process.exit(0);
86
+ }
87
}
88
89
async function unforkFile(oldFilename) {