react-native-binary
Version:
CLI commands to cache and reuse React Native binaries
89 lines (74 loc) • 2.46 kB
JavaScript
const execa = require('execa');
const fs = require('fs-extra');
const path = require('path');
const crypto = require('crypto');
const exec = (...args) => execa(...args).then(({ stdout }) => stdout);
const getPackageVersion = async (pkgDir) =>
(await fs.readJson(path.join(pkgDir, 'package.json'))).version;
const getUncommitedChangesInDir = async (dir) => {
const changes = await exec('git', ['status', '--porcelain', '-u', dir]);
return changes
.split('\n')
.map((line) => line.trim().replace(/^(A|M|D|[?]{2}) /, ''))
.filter(Boolean);
};
const ensureFolderIsHashable = async (dir) => {
const changes = await getUncommitedChangesInDir(dir);
if (changes.length !== 0) {
throw new Error(
`Unable to hash folder "${dir}" due to uncommited changes "${changes.join(
'", "'
)}"`
);
}
};
const getFolderHash = async (dir) => {
await ensureFolderIsHashable(dir);
const lsOutput = await exec('git', ['ls-tree', 'HEAD', dir]);
const hash = lsOutput.split(/\s/)[2];
if (!hash) {
throw new Error(`Unable to hash folder "${dir}"`);
}
return hash;
};
const getNativeDependencyVersions = async (config, platform) => {
const dependencies = Object.values(config.dependencies)
.filter((dependency) => Boolean(dependency.platforms[platform]))
.concat([
{
name: 'react-native-binary',
root: path.dirname(path.dirname(path.dirname(__dirname))),
},
{ name: 'react-native', root: config.reactNativePath },
]);
return Promise.all(
dependencies.map(
async ({ name, root }) => `${name}@${await getPackageVersion(root)}`
)
);
};
const getFolderHashes = (config, platform, additionalFolders) => {
const project = config.project[platform];
const folders = (additionalFolders || []).concat(project.sourceDir);
return Promise.all(folders.map(getFolderHash));
};
const binaryHash = async (_, config, args) => {
const { platform, folders } = args;
if (!(platform in config.platforms)) {
throw new Error(
`Invalid platform "${platform}", expected one of ${Object.keys(
config.platforms
).join(', ')}`
);
}
const snippets = await Promise.all([
getNativeDependencyVersions(config, platform),
getFolderHashes(config, platform, folders),
]);
const hash = crypto
.createHash('sha256')
.update(snippets.flat().join(';'))
.digest('hex');
console.log(hash);
};
module.exports = binaryHash;