[ https://issues.apache.org/jira/browse/CB-9858?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15270275#comment-15270275 ]
ASF GitHub Bot commented on CB-9858: ------------------------------------ Github user vladimir-kotikov commented on a diff in the pull request: https://github.com/apache/cordova-lib/pull/407#discussion_r62000656 --- Diff: cordova-fetch/index.js --- @@ -0,0 +1,234 @@ +/** + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + 'License'); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ + +var Q = require('q'); +var shell = require('shelljs'); +var superspawn = require('cordova-common').superspawn; +var events = require('cordova-common').events; +var depls = require('dependency-ls'); +var path = require('path'); +var fs = require('fs'); +var CordovaError = require('cordova-common').CordovaError; +var isUrl = require('is-url'); + +/* + * A function that npm installs a module from npm or a git url + * + * @param {String} target the packageID or git url + * @param {String} dest destination of where to install the module + * @param {Object} opts [opts={save:true}] options to pass to fetch module + * + * @return {String||Promise} Returns string of the absolute path to the installed module. + * + */ +module.exports = function(target, dest, opts) { + var fetchArgs = ['install']; + opts = opts || {}; + var tree1; + + //check if npm is installed + isNpmInstalled(); + + if(dest && target) { + //add target to fetchArgs Array + fetchArgs.push(target); + + //append node_modules to dest if it doesn't come included + if (path.basename(dest) !== 'node_modules') { + dest = path.resolve(path.join(dest, 'node_modules')); + } + + //create dest if it doesn't exist + if(!fs.existsSync(dest)) { + shell.mkdir('-p', dest); + } + + } else return Q.reject(new CordovaError('Need to supply a target and destination')); + + //set the directory where npm install will be run + opts.cwd = dest; + + //if user added --save flag, pass it to npm install command + if(opts.save) { + events.emit('verbose', 'saving'); + fetchArgs.push('--save'); + } + + + //Grab json object of installed modules before npm install + return depls(dest) + .then(function(depTree) { + tree1 = depTree; + + //install new module + return superspawn.spawn('npm', fetchArgs, opts); + }) + .then(function(output) { + //Grab object of installed modules after npm install + return depls(dest); + }) + .then(function(depTree2) { + var tree2 = depTree2; + + //getJsonDiff will fail if the module already exists in node_modules. + //Need to use trimID in that case. + //This could happen on a platform update. + var id = getJsonDiff(tree1, tree2) || trimID(target); + + return getPath(id, dest); + }) + .fail(function(err){ + return Q.reject(new CordovaError(err)); + }); +}; + + +/* + * Takes two JSON objects and returns the key of the new property as a string. + * If a module already exists in node_modules, the diff will be blank. + * cordova-fetch will use trimID in that case. + * + * @param {Object} obj1 json object representing installed modules before latest npm install + * @param {Object} obj2 json object representing installed modules after latest npm install + * + * @return {String} String containing the key value of the difference between the two objects + * + */ +function getJsonDiff(obj1, obj2) { + var result = ''; + + //regex to filter out peer dependency warnings from result + var re = /UNMET PEER DEPENDENCY/; + + for (var key in obj2) { + //if it isn't a unmet peer dependency, continue + if (key.search(re) === -1) { + if(obj2[key] != obj1[key]) result = key; + } + } + return result; +} + +/* + * Takes the specified target and returns the moduleID + * If the git repoName is different than moduleID, then the + * output from this function will be incorrect. This is the + * backup way to get ID. getJsonDiff is the preferred way to + * get the moduleID of the installed module. + * + * @param {String} target target that was passed into cordova-fetch. + * can be moduleID, moduleID@version or gitURL + * + * @return {String} ID moduleID without version. + */ +function trimID(target) { + var parts; + + //If GITURL, set target to repo name + if (isUrl(target)) { + var re = /.*\/(.*).git/; + parts = target.match(re); + target = parts[1]; + } + + //strip away everything after '@' + if(target.indexOf('@') != -1) { + parts = target.split('@'); + target = parts[0]; + } + + return target; +} + +/* + * Takes the moduleID and destination and returns an absolute path to the module + * + * @param {String} id the packageID + * @param {String} dest destination of where to fetch the modules + * + * @return {String||Error} Returns the absolute url for the module or throws a error + * + */ + +function getPath(id, dest) { + var finalDest = path.resolve(path.join(dest, id)); + + //Sanity check it exists + if(fs.existsSync(finalDest)){ + return finalDest; + } else return Q.reject(new CordovaError('Failed to get absolute path to installed module')); +} + + +/* + * Checks to see if npm is installed on the users system + * @return {Boolean||Error} Returns true or a cordova error. + */ + +function isNpmInstalled() { + if(!shell.which('npm')) { + return Q.reject(new CordovaError('"npm" command line tool is not installed: make sure it is accessible on your PATH.')); + } + return true; +} + +/* + * A function that deletes the target from node_modules and runs npm uninstall + * + * @param {String} target the packageID + * @param {String} dest destination of where to uninstall the module from + * @param {Object} opts [opts={save:true}] options to pass to npm uninstall + * + * @return {Promise||Error} Returns a promise with the npm uninstall output or an error. + * + */ +module.exports.uninstall = function(target, dest, opts) { + var fetchArgs = ['uninstall']; + opts = opts || {}; + + //check if npm is installed on the system + isNpmInstalled(); --- End diff -- The same issue with not rejecting the promise in case of missing `npm` > Implement Cordova Fetch Proposal > -------------------------------- > > Key: CB-9858 > URL: https://issues.apache.org/jira/browse/CB-9858 > Project: Apache Cordova > Issue Type: Improvement > Components: CordovaLib > Reporter: Steve Gill > Assignee: Steve Gill > Labels: cordova-fetch > Fix For: 6.0.0 > > > https://github.com/cordova/cordova-discuss/pull/33 -- This message was sent by Atlassian JIRA (v6.3.4#6332) --------------------------------------------------------------------- To unsubscribe, e-mail: issues-unsubscr...@cordova.apache.org For additional commands, e-mail: issues-h...@cordova.apache.org