Skip to content

Commit becef72

Browse files
authored
[0.83] Fix rncore tarball extraction for EdenFS compatibility (#55795)
1 parent c8ab750 commit becef72

1 file changed

Lines changed: 62 additions & 8 deletions

File tree

packages/react-native/scripts/replace-rncore-version.js

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
const {spawnSync} = require('child_process');
1414
const fs = require('fs');
15+
const os = require('os');
16+
const path = require('path');
1517
const yargs = require('yargs');
1618

1719
const LAST_BUILD_FILENAME = 'React-Core-prebuilt/.last_build_configuration';
@@ -62,14 +64,66 @@ function replaceRNCoreConfiguration(
6264
const tarballURLPath = `${podsRoot}/ReactNativeCore-artifacts/reactnative-core-${version.toLowerCase()}-${configuration.toLowerCase()}.tar.gz`;
6365

6466
const finalLocation = 'React-Core-prebuilt';
65-
console.log('Preparing the final location', finalLocation);
66-
fs.rmSync(finalLocation, {force: true, recursive: true});
67-
fs.mkdirSync(finalLocation, {recursive: true});
68-
69-
console.log('Extracting the tarball', tarballURLPath);
70-
spawnSync('tar', ['-xf', tarballURLPath, '-C', finalLocation], {
71-
stdio: 'inherit',
72-
});
67+
68+
// Extract to a temporary directory on a regular filesystem first, then move
69+
// into the final location. This avoids issues with partial tar extraction on
70+
// certain filesystems (e.g. EdenFS) where extracting directly can silently
71+
// produce incomplete results.
72+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'rncore-'));
73+
const tmpExtractDir = path.join(tmpDir, 'React-Core-prebuilt');
74+
fs.mkdirSync(tmpExtractDir, {recursive: true});
75+
76+
try {
77+
console.log('Extracting the tarball to temp dir', tarballURLPath);
78+
const result = spawnSync(
79+
'tar',
80+
['-xf', tarballURLPath, '-C', tmpExtractDir],
81+
{
82+
stdio: 'inherit',
83+
},
84+
);
85+
86+
if (result.status !== 0) {
87+
throw new Error(`tar extraction failed with exit code ${result.status}`);
88+
}
89+
90+
// Verify extraction produced the expected xcframework structure
91+
const xcfwPath = path.join(tmpExtractDir, 'React.xcframework');
92+
const modulemapPath = path.join(xcfwPath, 'Modules', 'module.modulemap');
93+
if (!fs.existsSync(modulemapPath)) {
94+
throw new Error(
95+
`Extraction verification failed: ${modulemapPath} not found`,
96+
);
97+
}
98+
99+
// Move from temp to final location
100+
console.log('Preparing the final location', finalLocation);
101+
fs.rmSync(finalLocation, {force: true, recursive: true});
102+
103+
// Use mv for an atomic-ish replacement. If the final location is on the
104+
// same filesystem as tmpDir this is a rename; otherwise it falls back to
105+
// copy + delete via spawnSync.
106+
const mvResult = spawnSync('mv', [tmpExtractDir, finalLocation], {
107+
stdio: 'inherit',
108+
});
109+
110+
if (mvResult.status !== 0) {
111+
// Fallback: copy recursively then remove temp
112+
console.log('mv failed, falling back to cp -R');
113+
fs.mkdirSync(finalLocation, {recursive: true});
114+
const cpResult = spawnSync(
115+
'cp',
116+
['-R', tmpExtractDir + '/.', finalLocation],
117+
{stdio: 'inherit'},
118+
);
119+
if (cpResult.status !== 0) {
120+
throw new Error(`cp fallback failed with exit code ${cpResult.status}`);
121+
}
122+
}
123+
} finally {
124+
// Clean up temp directory
125+
fs.rmSync(tmpDir, {force: true, recursive: true});
126+
}
73127
}
74128

75129
function updateLastBuildConfiguration(configuration /*: string */) {

0 commit comments

Comments
 (0)