Skip to content

Commit 955cf76

Browse files
committed
Add script to update Hermes submodule
1 parent 30dcdaa commit 955cf76

2 files changed

Lines changed: 112 additions & 0 deletions

File tree

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
"test-typescript": "dtslint packages/react-native/types",
4141
"test": "jest",
4242
"trigger-react-native-release": "node ./scripts/releases-local/trigger-react-native-release.js",
43+
"update-hermes": "node ./scripts/update-hermes.js",
4344
"update-lock": "npx yarn-deduplicate"
4445
},
4546
"workspaces": [

scripts/update-hermes.js

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/**
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @flow
8+
* @format
9+
* @oncall react_native
10+
*/
11+
12+
const {REPO_ROOT} = require('./consts');
13+
const {parseArgs} = require('@pkgjs/parseargs');
14+
const {execSync} = require('child_process');
15+
const {promises: fs} = require('fs');
16+
const path = require('path');
17+
18+
const config = {
19+
allowPositionals: true,
20+
options: {
21+
help: {type: 'boolean'},
22+
},
23+
};
24+
25+
async function main() {
26+
const {
27+
positionals,
28+
values: {help},
29+
} = parseArgs(config);
30+
let {revision} = positionals;
31+
32+
if (help) {
33+
console.log(`
34+
Usage: node ./scripts/update-hermes.js <revision>
35+
36+
Update the Hermes submodule to the specified Git revision.
37+
38+
If no Hermes revision is provided, updates to the latest commit on
39+
facebook/hermes.
40+
`);
41+
return;
42+
}
43+
44+
if (revision == null) {
45+
console.log(
46+
'No revision provided, updating to latest commit on facebook/hermes.',
47+
);
48+
49+
try {
50+
revision = getLatestHermesRevision();
51+
} catch (e) {
52+
console.error('Could not determine latest Hermes revision. Aborting.');
53+
process.exitCode = 1;
54+
return;
55+
}
56+
}
57+
58+
if (revision === getCurrentHermesRevision()) {
59+
console.log('Hermes submodule is already up to date. Exiting.');
60+
return;
61+
}
62+
63+
console.log(`Updating Hermes submodule to ${revision ?? 'latest'}`);
64+
65+
if ((await fs.stat(path.join(REPO_ROOT, '.git'))).isDirectory()) {
66+
await updateSubmoduleUnderGit(revision);
67+
} else {
68+
await updateSubmoduleUnderHg(revision);
69+
}
70+
}
71+
72+
function getCurrentHermesRevision() /*: string */ {
73+
const stdout = execFromRoot('git -C hermes log -n 1');
74+
75+
return stdout.toString().split('\n')[0].split(' ')[1];
76+
}
77+
78+
function getLatestHermesRevision() /*: string */ {
79+
const stdout = execFromRoot('git -C hermes log -n 1 origin/main');
80+
81+
return stdout.toString().split('\n')[0].split(' ')[1];
82+
}
83+
84+
async function updateSubmoduleUnderGit(revision /*: string */) {
85+
const commands = `
86+
git submodule update --remote hermes;
87+
git -C hermes checkout ${revision};
88+
git add hermes;
89+
git commit -m "Update Hermes to ${revision.slice(0, 8)}" -m "Changelog: [Internal]";
90+
`;
91+
commands.split(';').forEach(command => execFromRoot(command));
92+
}
93+
94+
async function updateSubmoduleUnderHg(revision /*: string */) {
95+
await fs.writeFile(
96+
path.join(REPO_ROOT, 'hermes.submodule.txt'),
97+
`Subproject commit ${revision}\n`,
98+
);
99+
execFromRoot(
100+
`hg commit -m "[RN] Update Hermes to ${revision.slice(0, 8)}" -m "Changelog: [Internal]"`,
101+
);
102+
}
103+
104+
function execFromRoot(command /*: string */, options = {}) {
105+
return execSync(command, {cwd: REPO_ROOT, ...options});
106+
}
107+
108+
if (require.main === module) {
109+
// eslint-disable-next-line no-void
110+
void main();
111+
}

0 commit comments

Comments
 (0)