@@ -18,6 +18,7 @@ const TerminalAdapter = require('yeoman-environment/lib/adapter');
1818const log = require ( 'npmlog' ) ;
1919const rimraf = require ( 'rimraf' ) ;
2020const semver = require ( 'semver' ) ;
21+ const yarn = require ( './yarn' ) ;
2122
2223const {
2324 checkDeclaredVersion,
@@ -31,8 +32,7 @@ log.heading = 'git-upgrade';
3132
3233/**
3334 * Promisify the callback-based shelljs function exec
34- * @param command
35- * @param logOutput
35+ * @param logOutput If true, log the stdout of the command.
3636 * @returns {Promise }
3737 */
3838function exec ( command , logOutput ) {
@@ -62,42 +62,37 @@ stdout: ${stdout}`));
6262 } )
6363}
6464
65- /**
66- + * Returns two objects:
67- + * - Parsed node_modules/react-native/package.json
68- + * - Parsed package.json
69- + */
70- function readPackageFiles ( ) {
65+ function parseJsonFile ( path , useYarn ) {
66+ const installHint = useYarn ?
67+ 'Make sure you ran "yarn" and that you are inside a React Native project.' :
68+ 'Make sure you ran "npm install" and that you are inside a React Native project.' ;
69+ let fileContents ;
70+ try {
71+ fileContents = fs . readFileSync ( path , 'utf8' ) ;
72+ } catch ( err ) {
73+ throw new Error ( 'Cannot find "' + path + '". ' + installHint ) ;
74+ }
75+ try {
76+ return JSON . parse ( fileContents ) ;
77+ } catch ( err ) {
78+ throw new Error ( 'Cannot parse "' + path + '": ' + err . message ) ;
79+ }
80+ }
81+
82+ function readPackageFiles ( useYarn ) {
7183 const reactNativeNodeModulesPakPath = path . resolve (
72- process . cwd ( ) ,
73- 'node_modules' ,
74- 'react-native' ,
75- 'package.json'
84+ process . cwd ( ) , 'node_modules' , 'react-native' , 'package.json'
7685 ) ;
77-
7886 const reactNodeModulesPakPath = path . resolve (
79- process . cwd ( ) ,
80- 'node_modules' ,
81- 'react' ,
82- 'package.json'
87+ process . cwd ( ) , 'node_modules' , 'react' , 'package.json'
8388 ) ;
84-
8589 const pakPath = path . resolve (
86- process . cwd ( ) ,
87- 'package.json'
90+ process . cwd ( ) , 'package.json'
8891 ) ;
89-
90- try {
91- const reactNativeNodeModulesPak = JSON . parse ( fs . readFileSync ( reactNativeNodeModulesPakPath , 'utf8' ) ) ;
92- const reactNodeModulesPak = JSON . parse ( fs . readFileSync ( reactNodeModulesPakPath , 'utf8' ) ) ;
93- const pak = JSON . parse ( fs . readFileSync ( pakPath , 'utf8' ) ) ;
94-
95- return { reactNativeNodeModulesPak, reactNodeModulesPak, pak} ;
96- } catch ( err ) {
97- throw new Error (
98- 'Unable to find one of "' + pakPath + '", "' + rnPakPath + '" or "' + reactPakPath + '". ' +
99- 'Make sure you ran "npm install" and that you are inside a React Native project.'
100- )
92+ return {
93+ reactNativeNodeModulesPak : parseJsonFile ( reactNativeNodeModulesPakPath ) ,
94+ reactNodeModulesPak : parseJsonFile ( reactNodeModulesPakPath ) ,
95+ pak : parseJsonFile ( pakPath )
10196 }
10297}
10398
@@ -191,6 +186,21 @@ async function checkForUpdates() {
191186 }
192187}
193188
189+ /**
190+ * If true, use yarn instead of the npm client to upgrade the project.
191+ */
192+ function shouldUseYarn ( cliArgs , projectDir ) {
193+ if ( cliArgs && cliArgs . npm ) {
194+ return false ;
195+ }
196+ const yarnVersion = yarn . getYarnVersionIfAvailable ( ) ;
197+ if ( yarnVersion && yarn . isProjectUsingYarn ( projectDir ) ) {
198+ log . info ( 'Using yarn ' + yarnVersion ) ;
199+ return true ;
200+ }
201+ return false ;
202+ }
203+
194204/**
195205 * @param requestedVersion The version argument, e.g. 'react-native-git-upgrade 0.38'.
196206 * `undefined` if no argument passed.
@@ -204,8 +214,10 @@ async function run(requestedVersion, cliArgs) {
204214 try {
205215 await checkForUpdates ( ) ;
206216
217+ const useYarn = shouldUseYarn ( cliArgs , path . resolve ( process . cwd ( ) ) ) ;
218+
207219 log . info ( 'Read package.json files' ) ;
208- const { reactNativeNodeModulesPak, reactNodeModulesPak, pak} = readPackageFiles ( ) ;
220+ const { reactNativeNodeModulesPak, reactNodeModulesPak, pak} = readPackageFiles ( useYarn ) ;
209221 const appName = pak . name ;
210222 const currentVersion = reactNativeNodeModulesPak . version ;
211223 const currentReactVersion = reactNodeModulesPak . version ;
@@ -218,7 +230,7 @@ async function run(requestedVersion, cliArgs) {
218230 checkDeclaredVersion ( declaredVersion ) ;
219231
220232 log . info ( 'Check matching versions' ) ;
221- checkMatchingVersions ( currentVersion , declaredVersion ) ;
233+ checkMatchingVersions ( currentVersion , declaredVersion , useYarn ) ;
222234
223235 log . info ( 'Check React peer dependency' ) ;
224236 checkReactPeerDependency ( currentVersion , declaredReactVersion ) ;
@@ -231,6 +243,8 @@ async function run(requestedVersion, cliArgs) {
231243 const viewOutput = await exec ( viewCommand , verbose ) . then ( JSON . parse ) ;
232244 const newVersion = viewOutput . version ;
233245 const newReactVersionRange = viewOutput [ 'peerDependencies.react' ] ;
246+ // Print which versions we're upgrading to
247+ log . info ( 'Upgrading to React Native ' + newVersion + ( newReactVersionRange ? ', React ' + newReactVersionRange : '' ) ) ;
234248
235249 log . info ( 'Check new version' ) ;
236250 checkNewVersionValid ( newVersion , requestedVersion ) ;
@@ -264,9 +278,14 @@ async function run(requestedVersion, cliArgs) {
264278 await exec ( 'git commit -m "Old version" --allow-empty' , verbose ) ;
265279
266280 log . info ( 'Install the new version' ) ;
267- let installCommand = 'npm install --save --color=always' ;
281+ let installCommand ;
282+ if ( useYarn ) {
283+ installCommand = 'yarn add' ;
284+ } else {
285+ installCommand = 'npm install --save --color=always' ;
286+ }
268287 installCommand += ' react-native@' + newVersion ;
269- if ( ! semver . satisfies ( currentReactVersion , newReactVersionRange ) ) {
288+ if ( newReactVersionRange && ! semver . satisfies ( currentReactVersion , newReactVersionRange ) ) {
270289 // Install React as well to avoid unmet peer dependency
271290 installCommand += ' react@' + newReactVersionRange ;
272291 }
@@ -296,8 +315,8 @@ async function run(requestedVersion, cliArgs) {
296315 await exec ( `git apply --3way ${ patchPath } ` , true ) ;
297316 } catch ( err ) {
298317 log . warn (
299- 'The upgrade process succeeded but there might be conflicts to be resolved.\n ' +
300- 'See above for the list of files that had merge conflicts.' ) ;
318+ 'The upgrade process succeeded but there might be conflicts to be resolved. ' +
319+ 'See above for the list of files that have merge conflicts.' ) ;
301320 } finally {
302321 log . info ( 'Upgrade done' ) ;
303322 if ( cliArgs . verbose ) {
0 commit comments