nl_tokens: Install platforms looking at config . xml and package . json ( if there is one ) .
pl_tokens: function installPlatformsFromConfigXML ( platforms , opts ) { events . emit ( 'verbose' , 'Checking config.xml and package.json for saved platforms that haven\'t been added to the project' ) ; var projectHome = cordova_util . cdProjectRoot ( ) ; var configPath = cordova_util . projectConfig ( projectHome ) ; var cfg = new ConfigParser ( configPath ) ; var engines = cfg . getEngines ( ) ; var pkgJsonPath = path . join ( projectHome , 'package.json' ) ; var pkgJson ; var pkgJsonPlatforms ; var comboArray = [ ] ; var configPlatforms = [ ] ; var modifiedPkgJson = false ; var mergedPlatformSpecs = { } ; var key ; var installAllPlatforms = ! platforms || platforms . length === 0 ; var file ; var indent ; // Check if path exists and require pkgJsonPath. if ( fs . existsSync ( pkgJsonPath ) ) { pkgJson = require ( pkgJsonPath ) ; file = fs . readFileSync ( pkgJsonPath , 'utf8' ) ; indent = detectIndent ( file ) . indent || '  ' ; } if ( pkgJson !== undefined && pkgJson . cordova !== undefined && pkgJson . cordova . platforms !== undefined ) { pkgJsonPlatforms = pkgJson . cordova . platforms ; } if ( cfg !== undefined ) { if ( pkgJsonPlatforms !== undefined ) { // Combining arrays and checking duplicates. comboArray = pkgJsonPlatforms . slice ( ) ; } engines = cfg . getEngines ( projectHome ) ; // TODO: CB-12592: Eventually refactor out to pacakge manager module. // If package.json doesn't exist, auto-create one. if ( engines . length > 0 && pkgJson === undefined ) { pkgJson = { } ; if ( cfg . packageName ( ) ) { pkgJson . <mask> = cfg . packageName ( ) . toLowerCase ( ) ; } if ( cfg . version ( ) ) { pkgJson . version = cfg . version ( ) ; } if ( cfg . name ( ) ) { pkgJson . displayName = cfg . name ( ) ; } fs . writeFileSync ( pkgJsonPath , JSON . stringify ( pkgJson , null , indent ) , 'utf8' ) ; } configPlatforms = engines . map ( function ( Engine ) { var configPlatName = Engine . name ; // Add specs from config into mergedPlatformSpecs. if ( mergedPlatformSpecs [ configPlatName ] === undefined && Engine . spec ) { mergedPlatformSpecs [ configPlatName ] = Engine . spec ; } return configPlatName ; } ) ; configPlatforms . forEach ( function ( item ) { if ( comboArray . indexOf ( item ) < 0 ) { comboArray . push ( item ) ; } } ) ; // ComboArray should have all platforms from config.xml & package.json. // Remove duplicates in comboArray & sort. var uniq = comboArray . reduce ( function ( a , b ) { if ( a . indexOf ( b ) < 0 ) a . push ( b ) ; return a ; } , [ ] ) ; comboArray = uniq ; // No platforms to restore from either config.xml or package.json. if ( comboArray . length <= 0 ) { return Promise . resolve ( 'No platforms found in config.xml or package.json. Nothing to restore' ) ; } // If no package.json, don't continue. if ( pkgJson !== undefined ) { // If config.xml & pkgJson exist and the cordova key is undefined, create a cordova key. if ( pkgJson . cordova === undefined ) { pkgJson . cordova = { } ; } // If there is no platforms array, create an empty one. if ( pkgJson . cordova . platforms === undefined ) { pkgJson . cordova . platforms = [ ] ; } // If comboArray has the same platforms as pkg.json, no modification to pkg.json. if ( comboArray . toString ( ) === pkgJson . cordova . platforms . toString ( ) ) { events . emit ( 'verbose' , 'Config.xml and package.json platforms are the same. No pkg.json modification.' ) ; } else { // Modify pkg.json to include the elements. // From the comboArray array so that the arrays are identical. events . emit ( 'verbose' , 'Config.xml and package.json platforms are different. Updating package.json with most current list of platforms.' ) ; modifiedPkgJson = true ; } events . emit ( 'verbose' , 'Package.json and config.xml platforms are different. Updating config.xml with most current list of platforms.' ) ; comboArray . forEach ( function ( item ) { var prefixItem = ( 'cordova-' + item ) ; // Modify package.json if any of these cases are true: if ( ( pkgJson . dependencies === undefined && Object . keys ( mergedPlatformSpecs ) . length ) || ( pkgJson . dependencies && mergedPlatformSpecs && pkgJson . dependencies [ item ] === undefined && mergedPlatformSpecs [ item ] ) || ( pkgJson . dependencies && mergedPlatformSpecs && pkgJson . dependencies [ prefixItem ] === undefined && mergedPlatformSpecs [ prefixItem ] ) ) { modifiedPkgJson = true ; } // Get the cordova- prefixed spec from package.json and add it to mergedPluginSpecs. if ( pkgJson . dependencies && pkgJson . dependencies [ prefixItem ] ) { if ( mergedPlatformSpecs [ prefixItem ] !== pkgJson . dependencies [ prefixItem ] ) { modifiedPkgJson = true ; } mergedPlatformSpecs [ item ] = pkgJson . dependencies [ prefixItem ] ; } // Get the spec from package.json and add it to mergedPluginSpecs. if ( pkgJson . dependencies && pkgJson . dependencies [ item ] && pkgJson . dependencies [ prefixItem ] === undefined ) { if ( mergedPlatformSpecs [ item ] !== pkgJson . dependencies [ item ] ) { modifiedPkgJson = true ; } mergedPlatformSpecs [ item ] = pkgJson . dependencies [ item ] ; } } ) ; } // Write and update pkg.json if it has been modified. if ( modifiedPkgJson === true ) { pkgJson . cordova . platforms = comboArray ; if ( pkgJson . dependencies === undefined ) { pkgJson . dependencies = { } ; } // Check if key is part of cordova alias list. // Add prefix if it is. for ( key in mergedPlatformSpecs ) { var prefixKey = key ; if ( key in platformsList ) { prefixKey = 'cordova-' + key ; } pkgJson . dependencies [ prefixKey ] = mergedPlatformSpecs [ key ] ; } fs . writeFileSync ( pkgJsonPath , JSON . stringify ( pkgJson , null , indent ) , 'utf8' ) ; } if ( ! comboArray || ! comboArray . length ) { return Promise . resolve ( 'No platforms found in config.xml and/or package.json that haven\'t been added to the project' ) ; } } // Run `platform add` for all the platforms separately // so that failure on one does not affect the other. // CB-9278 : Run `platform add` serially, one platform after another // Otherwise, we get a bug where the following line: https://github.com/apache/cordova-lib/blob/0b0dee5e403c2c6d4e7262b963babb9f532e7d27/cordova-lib/src/util/npm-helper.js#L39 // gets executed simultaneously by each platform and leads to an exception being thrown return promiseutil . Q_chainmap_graceful ( comboArray , function ( target ) { var cwd = process . cwd ( ) ; var platformsFolderPath = path . join ( cwd , 'platforms' ) ; var platformsInstalled = path . join ( platformsFolderPath , target ) ; if ( target ) { var platformName = target ; // Add the spec to the target if ( mergedPlatformSpecs [ target ] ) { target = target + '@' + mergedPlatformSpecs [ target ] ; } // If the platform is already installed, no need to re-install it. if ( ! fs . existsSync ( platformsInstalled ) && ( installAllPlatforms || platforms . indexOf ( platformName ) > - 1 ) ) { events . emit ( 'log' , 'Discovered platform "' + target + '" in config.xml or package.json. Adding it to the project' ) ; return cordovaPlatform ( 'add' , target , opts ) ; } } return Promise . resolve ( ) ; } , function ( err ) { events . emit ( 'warn' , err ) ; } ) ; }