added ability to specify custom locations for libraries. added before + after_library_download, and progress event for lib downloads via library_download
Project: http://git-wip-us.apache.org/repos/asf/cordova-cli/repo Commit: http://git-wip-us.apache.org/repos/asf/cordova-cli/commit/72c07827 Tree: http://git-wip-us.apache.org/repos/asf/cordova-cli/tree/72c07827 Diff: http://git-wip-us.apache.org/repos/asf/cordova-cli/diff/72c07827 Branch: refs/heads/master2 Commit: 72c0782784650421d6c09e0a3ac00d9949706f57 Parents: a42ee2e Author: Fil Maj <[email protected]> Authored: Tue Jun 11 15:51:36 2013 -0700 Committer: Fil Maj <[email protected]> Committed: Thu Jun 13 11:13:20 2013 -0700 ---------------------------------------------------------------------- cordova.js | 1 + platforms.js | 13 ++-- src/config.js | 54 +++++++++++++++ src/create.js | 88 ++++++++++++++++++------- src/hooker.js | 9 +++ src/lazy_load.js | 179 +++++++++++++++++++++++++++++++------------------- src/util.js | 2 +- 7 files changed, 250 insertions(+), 96 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/72c07827/cordova.js ---------------------------------------------------------------------- diff --git a/cordova.js b/cordova.js index 35b8134..94d5aec 100644 --- a/cordova.js +++ b/cordova.js @@ -36,6 +36,7 @@ var emit = function() { module.exports = { help: require('./src/help'), + config: require('./src/config'), create: require('./src/create'), platform: platform, platforms: platform, http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/72c07827/platforms.js ---------------------------------------------------------------------- diff --git a/platforms.js b/platforms.js index d41abd3..7d894b4 100644 --- a/platforms.js +++ b/platforms.js @@ -20,22 +20,25 @@ module.exports = { 'ios' : { parser : require('./src/metadata/ios_parser'), - url : 'https://git-wip-us.apache.org/repos/asf/cordova-ios.git' + url : 'https://git-wip-us.apache.org/repos/asf?p=cordova-ios.git' }, 'android' : { parser : require('./src/metadata/android_parser'), - url : 'https://git-wip-us.apache.org/repos/asf/cordova-ios.git' + url : 'https://git-wip-us.apache.org/repos/asf?p=cordova-ios.git' }, 'wp7' : { parser : require('./src/metadata/wp7_parser'), - url : 'https://git-wip-us.apache.org/repos/asf/cordova-wp7.git' + url : 'https://git-wip-us.apache.org/repos/asf?p=cordova-wp7.git' }, 'wp8' : { parser : require('./src/metadata/wp8_parser'), - url : 'https://git-wip-us.apache.org/repos/asf/cordova-wp8.git' + url : 'https://git-wip-us.apache.org/repos/asf?p=cordova-wp8.git' }, blackberry : { parser : require('./src/metadata/blackberry_parser'), - url : 'https://git-wip-us.apache.org/repos/asf/cordova-blackberry.git' + url : 'https://git-wip-us.apache.org/repos/asf?p=cordova-blackberry.git' + }, + 'www':{ + url : 'https://git-wip-us.apache.org/repos/asf?p=cordova-app-hello-world.git' } }; http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/72c07827/src/config.js ---------------------------------------------------------------------- diff --git a/src/config.js b/src/config.js new file mode 100644 index 0000000..fb0a59b --- /dev/null +++ b/src/config.js @@ -0,0 +1,54 @@ +/** + 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 path = require('path'), + fs = require('fs'), + shell = require('shelljs'), + events = require('./events'), + util = require('./util'); + +module.exports = function config(project_root, opts) { + var json = module.exports.read(project_root); + Object.keys(opts).forEach(function(p) { + json[p] = opts[p]; + }); + return module.exports.write(project_root, json); +}; + +module.exports.read = function get_config(project_root) { + var dotCordova = path.join(project_root, '.cordova'); + + if (!fs.existsSync(dotCordova)) { + shell.mkdir('-p', dotCordova); + } + + var config_json = path.join(dotCordova, 'config.json'); + if (!fs.existsSync(config_json)) { + return module.exports.write(project_root, {}); + } else { + return JSON.parse(fs.readFileSync(config_json, 'utf-8')); + } +}; + +module.exports.write = function set_config(project_root, json) { + var dotCordova = path.join(project_root, '.cordova'); + var config_json = path.join(dotCordova, 'config.json'); + fs.writeFileSync(config_json, JSON.stringify(json), 'utf-8'); + return json; +}; http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/72c07827/src/create.js ---------------------------------------------------------------------- diff --git a/src/create.js b/src/create.js index be9966c..6665694 100644 --- a/src/create.js +++ b/src/create.js @@ -22,6 +22,8 @@ var path = require('path'), help = require('./help'), config_parser = require('./config_parser'), events = require('./events'), + config = require('./config'), + lazy_load = require('./lazy_load'), util = require('./util'); var DEFAULT_NAME = "HelloCordova", @@ -33,18 +35,26 @@ var DEFAULT_NAME = "HelloCordova", * create(dir, name) - as above, but with specified name * create(dir, id, name) - you get the gist **/ -module.exports = function create (dir, id, name) { - if (dir === undefined) { +module.exports = function create (dir, id, name, callback) { + if (arguments.length === 0) { return help(); } - // Massage parameters a bit. - if (id && name === undefined) { - name = id; - id = undefined; + // Massage parameters + var args = Array.prototype.slice.call(arguments, 0); + if (typeof args[args.length-1] == 'function') { + callback = args.pop(); + } + if (args.length === 0) { + dir = process.cwd(); + id = DEFAULT_ID; + name = DEFAULT_NAME; + } else if (args.length == 1) { + id = DEFAULT_ID; + name = DEFAULT_NAME; + } else if (args.length == 2) { + name = DEFAULT_NAME; } - id = id || DEFAULT_ID; - name = name || DEFAULT_NAME; // Make absolute. dir = path.resolve(dir); @@ -53,11 +63,6 @@ module.exports = function create (dir, id, name) { var dotCordova = path.join(dir, '.cordova'); - // Check for existing cordova project - if (fs.existsSync(dotCordova)) { - throw new Error('Cordova project already exists at ' + dir + ', aborting.'); - } - // Create basic project structure. shell.mkdir('-p', dotCordova); shell.mkdir('-p', path.join(dir, 'platforms')); @@ -93,18 +98,55 @@ module.exports = function create (dir, id, name) { shell.mkdir(path.join(hooks, 'before_run')); // Write out .cordova/config.json file with a simple json manifest - fs.writeFileSync(path.join(dotCordova, 'config.json'), JSON.stringify({ + config(dir, { id:id, name:name - })); + }); - // Copy in base template - events.emit('log', 'Copying stock application assets into "' + path.join(dir, 'www') + '"'); - shell.cp('-r', path.join(__dirname, '..', 'templates', 'www'), dir); + // Copy in base www template + var config_json = config.read(dir); + // Check if www assets to use was overridden. + var www_dir = path.join(dir, 'www'); + var finalize = function(www_lib) { + while (!fs.existsSync(path.join(www_lib, 'config.xml'))) { + www_lib = path.join(www_lib, 'www'); + if (!fs.existsSync(www_lib)) { + var err = new Error('downloaded www assets in ' + www_lib + ' does not contain config.xml, or www subdir with config.xml'); + if (callback) return callback(err); + else throw err; + } + } + shell.cp('-rf', path.join(www_lib, '*'), www_dir); + // Write out id and name to config.xml + var configPath = util.projectConfig(dir); + var config = new config_parser(configPath); + config.packageName(id); + config.name(name); + if (callback) callback(); + }; - // Write out id and name to config.xml - var configPath = util.projectConfig(dir); - var config = new config_parser(configPath); - config.packageName(id); - config.name(name); + if (config_json.lib && config_json.lib.www) { + events.emit('log', 'Using custom www assets ('+config_json.lib.www.id+').'); + lazy_load.custom(config_json.lib.www.uri, config_json.lib.www.id, 'www', config_json.lib.www.version, function(err) { + if (err) { + if (callback) callback(err); + else throw err; + } else { + events.emit('log', 'Copying custom www assets into "' + www_dir + '"'); + finalize(path.join(util.libDirectory, 'www', config_json.lib.www.id, config_json.lib.www.version)); + } + }); + } else { + // Nope, so use stock cordova-hello-world-app one. + events.emit('log', 'Using stock cordova hello-world application.'); + lazy_load.cordova('www', function(err) { + if (err) { + if (callback) callback(err); + else throw err; + } else { + events.emit('log', 'Copying stock Cordova www assets into "' + www_dir + '"'); + finalize(path.join(util.libDirectory, 'www', 'cordova', util.cordovaTag)); + } + }); + } }; http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/72c07827/src/hooker.js ---------------------------------------------------------------------- diff --git a/src/hooker.js b/src/hooker.js index a483b8f..247385f 100644 --- a/src/hooker.js +++ b/src/hooker.js @@ -28,6 +28,15 @@ module.exports = function hooker(root) { else this.root = r; } +module.exports.fire = function global_fire(hook, opts, callback) { + if (arguments.length == 2) { + callback = opts; + opts = {}; + } + var handlers = events.listeners(hook); + execute_handlers_serially(handlers, opts, callback); +}; + module.exports.prototype = { fire:function fire(hook, opts, callback) { if (arguments.length == 2) { http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/72c07827/src/lazy_load.js ---------------------------------------------------------------------- diff --git a/src/lazy_load.js b/src/lazy_load.js index 8094965..f7bf15c 100644 --- a/src/lazy_load.js +++ b/src/lazy_load.js @@ -21,88 +21,133 @@ var path = require('path'), shell = require('shelljs'), platforms = require('../platforms'), events = require('./events'), - glob = require('glob'), + hooker = require('./hooker'), https = require('follow-redirects').https, zlib = require('zlib'), tar = require('tar'), + URL = require('url'), util = require('./util'); -/** - * Usage: - **/ -module.exports = function lazy_load(platform, callback) { - if (!(platform in platforms)) { - var err = new Error('platform "' + platform + '" not recognized.'); - if (callback) return callback(err); - else throw err; - } +module.exports = { + cordova:function lazy_load(platform, callback) { + if (!(platform in platforms)) { + var err = new Error('Cordova library "' + platform + '" not recognized.'); + if (callback) return callback(err); + else throw err; + } - if (util.has_platform_lib(platform)) { - events.emit('log', 'Platform library for "' + platform + '" already exists. No need to download. Continuing.'); - return (callback ? callback() : true); - } else { - // TODO: hook in before_library_dl event var url = platforms[platform].url + ';a=snapshot;h=' + util.cordovaTag + ';sf=tgz'; - var filename = path.join(util.libDirectory, 'cordova-' + platform + '-' + util.cordovaTag + '.tar.gz'); - var req_opts = { - hostname: 'git-wip-us.apache.org', - path: '/repos/asf?p=cordova-' + platform + '.git;a=snapshot;h=' + util.cordovaTag + ';sf=tgz' - }; - events.emit('log', 'Requesting ' + req_opts.hostname + req_opts.path + '...'); - var req = https.request(req_opts, function(res) { - var downloadfile = fs.createWriteStream(filename, {'flags': 'a'}); - - res.on('data', function(chunk){ - // TODO: hook in progress event - downloadfile.write(chunk, 'binary'); - events.emit('log', 'Wrote ' + chunk.length + ' bytes...'); - }); + module.exports.custom(url, 'cordova', platform, util.cordovaTag, function(err) { + if (err) { + if (callback) return callback(err); + else throw err; + } else { + if (callback) callback(); + } + }); + }, + custom:function(url, id, platform, version, callback) { + var download_dir = path.join(util.libDirectory, platform, id, version); + shell.mkdir('-p', download_dir); + if (fs.existsSync(download_dir)) { + events.emit('log', 'Platform library for "' + platform + '" already exists. No need to download. Continuing.'); + if (callback) callback(); + return; + } - res.on('end', function(){ - // TODO: hook in end event - downloadfile.end(); - events.emit('log', 'Download complete. Extracting...'); - var tar_path = path.join(util.libDirectory, 'cordova-' + platform + '-' + util.cordovaTag + '.tar'); - var tarfile = fs.createWriteStream(tar_path); - tarfile.on('error', function(err) { - if (callback) callback(err); - else throw err; - }); - tarfile.on('finish', function() { + hooker.fire('before_library_download', { + platform:platform, + url:url, + id:id, + version:version + }, function() { + var uri = URL.parse(url); + if (uri.protocol) { + // assuming its remote + var filename = path.join(download_dir, id+'-'+platform+'-'+version+'.tar.gz'); + if (fs.existsSync(filename)) { shell.rm(filename); - fs.createReadStream(tar_path) - .pipe(tar.Extract({ path: util.libDirectory })) - .on("error", function (err) { + } + var req_opts = { + hostname: uri.hostname, + path: uri.path + }; + events.emit('log', 'Requesting ' + url + '...'); + // TODO: may not be an https request.. + var req = https.request(req_opts, function(res) { + var downloadfile = fs.createWriteStream(filename, {'flags': 'a'}); + + res.on('data', function(chunk){ + downloadfile.write(chunk, 'binary'); + hooker.fire('library_download', { + platform:platform, + url:url, + id:id, + version:version, + chunk:chunk + }); + }); + + res.on('end', function(){ + downloadfile.end(); + var payload_size = fs.statSync(filename).size; + events.emit('log', 'Download complete. Extracting...'); + var tar_path = path.join(download_dir, id+'-'+platform+'-'+version+'.tar'); + var tarfile = fs.createWriteStream(tar_path); + tarfile.on('error', function(err) { if (callback) callback(err); else throw err; - }) - .on("end", function () { - shell.rm(tar_path); - // rename the extracted dir to remove the trailing SHA - glob(path.join(util.libDirectory, 'cordova-' + platform + '-' + util.cordovaTag + '-*'), function(err, entries) { - if (err) { - if (callback) return callback(err); + }); + tarfile.on('finish', function() { + shell.rm(filename); + fs.createReadStream(tar_path) + .pipe(tar.Extract({ path: download_dir })) + .on("error", function (err) { + if (callback) callback(err); else throw err; - } else { - var entry = entries[0]; - var final_dir = path.join(util.libDirectory, 'cordova-' + platform + '-' + util.cordovaTag); - shell.mkdir(final_dir); - shell.mv('-f', path.join(entry, (platform=='blackberry'?'blackberry10':''), '*'), final_dir); + }) + .on("end", function () { + shell.rm(tar_path); + // move contents out of extracted dir + var entries = fs.readdirSync(download_dir); + var entry = path.join(download_dir, entries[0]); + shell.mv('-f', path.join(entry, (platform=='blackberry'?'blackberry10':''), '*'), download_dir); shell.rm('-rf', entry); - if (callback) callback(); - } - }); + hooker.fire('after_library_download', { + platform:platform, + url:url, + id:id, + version:version, + path:download_dir, + size:payload_size + }, function() { + if (callback) callback(); + }); + }); }); + fs.createReadStream(filename) + .pipe(zlib.createUnzip()) + .pipe(tarfile); + }); }); - fs.createReadStream(filename) - .pipe(zlib.createUnzip()) - .pipe(tarfile); - }); - }); - req.on('error', function(err) { - if (callback) return callback(err); - else throw err; + req.on('error', function(err) { + if (callback) return callback(err); + else throw err; + }); + req.end(); + } else { + // local path + shell.cp('-rf', path.join(uri.path, '*'), download_dir); + hooker.fire('after_library_download', { + platform:platform, + url:url, + id:id, + version:version, + path:download_dir + }, function() { + if (callback) callback(); + }); + } }); - req.end(); } }; http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/72c07827/src/util.js ---------------------------------------------------------------------- diff --git a/src/util.js b/src/util.js index d458bc2..c689340 100644 --- a/src/util.js +++ b/src/util.js @@ -37,7 +37,7 @@ module.exports = { globalConfig:global_config_path, libDirectory:lib_path, has_platform_lib:function has_platform_lib(platform) { - return fs.existsSync(path.join(lib_path, 'cordova-' + platform + '-' + TAG, 'bin', 'create')); + return fs.existsSync(path.join(lib_path, platform, 'cordova', TAG, 'bin', 'create')); }, // Runs up the directory chain looking for a .cordova directory. // IF it is found we are in a Cordova project.
