From ab2e0f870d14f0f82bd56346c3f054689a73a83a Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Sat, 20 Jan 2018 18:24:25 +0000 Subject: [PATCH] Fix the script replacing local deps (#3876) --- tasks/cra.js | 113 +++++++++++++++++++++----------------- tasks/replace-own-deps.js | 30 ---------- 2 files changed, 64 insertions(+), 79 deletions(-) delete mode 100755 tasks/replace-own-deps.js diff --git a/tasks/cra.js b/tasks/cra.js index ec15d702ac5..c181a23561c 100644 --- a/tasks/cra.js +++ b/tasks/cra.js @@ -14,6 +14,8 @@ const cp = require('child_process'); const cleanup = () => { console.log('Cleaning up.'); + // Reset changes made to package.json files. + cp.execSync(`git checkout -- packages/*/package.json`); // Uncomment when snapshot testing is enabled by default: // rm ./template/src/__snapshots__/App.test.js.snap }; @@ -25,7 +27,8 @@ const handleExit = () => { }; const handleError = e => { - console.error('ERROR! An error was encountered while executing\n', e); + console.error('ERROR! An error was encountered while executing'); + console.error(e); cleanup(); console.log('Exiting with error.'); process.exit(1); @@ -34,69 +37,81 @@ const handleError = e => { process.on('SIGINT', handleExit); process.on('uncaughtException', handleError); -// ****************************************************************************** -// Pack react- scripts so we can verify they work. -// ****************************************************************************** +console.log(); +console.log('-------------------------------------------------------'); +console.log('Assuming you have already run `yarn` to update the deps.'); +console.log('If not, remember to do this before testing!'); +console.log('-------------------------------------------------------'); +console.log(); -const rootDir = path.join(__dirname, '..'); -const reactScriptsDir = path.join(rootDir, 'packages', 'react-scripts'); -const packageJsonPath = path.join(reactScriptsDir, 'package.json'); -const packageJsonOrigPath = path.join(reactScriptsDir, 'package.json.orig'); - -// Install all our packages -const lernaPath = path.join(rootDir, 'node_modules', '.bin', 'lerna'); -cp.execSync(`${lernaPath} bootstrap`, { - cwd: rootDir, - stdio: 'inherit', -}); +// Temporarily overwrite package.json of all packages in monorepo +// to point to each other using absolute file:/ URLs. -// Save package.json because we're going to touch it -fs.writeFileSync(packageJsonOrigPath, fs.readFileSync(packageJsonPath)); +const gitStatus = cp.execSync(`git status --porcelain`).toString(); -// Replace own dependencies (those in the`packages` dir) with the local paths -// of those packages -const replaceOwnDepsPath = path.join(__dirname, 'replace-own-deps.js'); -cp.execSync(`node ${replaceOwnDepsPath}`, { stdio: 'inherit' }); +if (gitStatus.trim() !== '') { + console.log('Please commit your changes before running this script!'); + console.log('Exiting because `git status` is not empty:'); + console.log(); + console.log(gitStatus); + console.log(); + process.exit(1); +} + +const rootDir = path.join(__dirname, '..'); +const packagesDir = path.join(rootDir, 'packages'); +const packagePathsByName = {}; +fs.readdirSync(packagesDir).forEach(name => { + const packageDir = path.join(packagesDir, name); + const packageJson = path.join(packageDir, 'package.json'); + if (fs.existsSync(packageJson)) { + packagePathsByName[name] = packageDir; + } +}); +Object.keys(packagePathsByName).forEach(name => { + const packageJson = path.join(packagePathsByName[name], 'package.json'); + const json = JSON.parse(fs.readFileSync(packageJson, 'utf8')); + Object.keys(packagePathsByName).forEach(otherName => { + if (json.dependencies && json.dependencies[otherName]) { + json.dependencies[otherName] = 'file:' + packagePathsByName[otherName]; + } + if (json.devDependencies && json.devDependencies[otherName]) { + json.devDependencies[otherName] = 'file:' + packagePathsByName[otherName]; + } + if (json.peerDependencies && json.peerDependencies[otherName]) { + json.peerDependencies[otherName] = + 'file:' + packagePathsByName[otherName]; + } + if (json.optionalDependencies && json.optionalDependencies[otherName]) { + json.optionalDependencies[otherName] = + 'file:' + packagePathsByName[otherName]; + } + }); + + fs.writeFileSync(packageJson, JSON.stringify(json, null, 2), 'utf8'); + console.log( + 'Replaced local dependencies in packages/' + name + '/package.json' + ); +}); +console.log('Replaced all local dependencies for testing.'); +console.log('Do not edit any package.json while this task is running.'); -// Finally, pack react-scripts +// Finally, pack react-scripts. // Don't redirect stdio as we want to capture the output that will be returned // from execSync(). In this case it will be the .tgz filename. const scriptsFileName = cp - .execSync(`npm pack`, { cwd: reactScriptsDir }) + .execSync(`npm pack`, { cwd: path.join(packagesDir, 'react-scripts') }) .toString() .trim(); -const scriptsPath = path.join( - rootDir, - 'packages', - 'react-scripts', - scriptsFileName -); - -// Restore package.json -fs.unlinkSync(packageJsonPath); -fs.writeFileSync(packageJsonPath, fs.readFileSync(packageJsonOrigPath)); -fs.unlinkSync(packageJsonOrigPath); +const scriptsPath = path.join(packagesDir, 'react-scripts', scriptsFileName); -// ****************************************************************************** // Now that we have packed them, call the global CLI. -// ****************************************************************************** - -// If Yarn is installed, clean its cache because it may have cached react-scripts -try { - cp.execSync('yarn cache clean'); -} catch (e) { - // We can safely ignore this as the user doesn't have yarn installed -} +cp.execSync('yarn cache clean'); const args = process.argv.slice(2); // Now run the CRA command -const craScriptPath = path.join( - rootDir, - 'packages', - 'create-react-app', - 'index.js' -); +const craScriptPath = path.join(packagesDir, 'create-react-app', 'index.js'); cp.execSync( `node ${craScriptPath} --scripts-version="${scriptsPath}" ${args.join(' ')}`, { diff --git a/tasks/replace-own-deps.js b/tasks/replace-own-deps.js deleted file mode 100755 index 15d53d9dc86..00000000000 --- a/tasks/replace-own-deps.js +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env node -/** - * Copyright (c) 2015-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ -'use strict'; - -// Replaces internal dependencies in package.json with local package paths. - -const fs = require('fs'); -const path = require('path'); - -const packagesDir = path.join(__dirname, '../packages'); -const pkgFilename = path.join(packagesDir, 'react-scripts/package.json'); -const data = require(pkgFilename); - -fs.readdirSync(packagesDir).forEach(name => { - if (data.dependencies[name]) { - data.dependencies[name] = 'file:' + path.join(packagesDir, name); - } -}); - -fs.writeFile(pkgFilename, JSON.stringify(data, null, 2), 'utf8', err => { - if (err) { - throw err; - } - console.log('Replaced local dependencies.'); -});