You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by br...@apache.org on 2013/03/21 23:16:34 UTC
git commit: --prepare with ported JS installation,
cache plugins locally
Updated Branches:
refs/heads/future c770f5250 -> c130382d2
--prepare with ported JS installation, cache plugins locally
NB: --plugins_dir argument and the --prepare command are completely
untested. I'm just committing the skeleton of this change to unblock
others.
Project: http://git-wip-us.apache.org/repos/asf/cordova-plugman/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugman/commit/c130382d
Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugman/tree/c130382d
Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugman/diff/c130382d
Branch: refs/heads/future
Commit: c130382d2f00accb92e3b07c68de3c83d13727e1
Parents: c770f52
Author: Braden Shepherdson <br...@gmail.com>
Authored: Tue Mar 19 14:21:16 2013 -0400
Committer: Braden Shepherdson <br...@gmail.com>
Committed: Thu Mar 21 18:16:07 2013 -0400
----------------------------------------------------------------------
FUTURE.md | 4 +-
plugman.js | 37 +++++++++++-
util/plugin_loader.js | 141 ++++++++++++++++++++++++++++++++++++++++++++
util/plugins.js | 21 +++----
4 files changed, 189 insertions(+), 14 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/c130382d/FUTURE.md
----------------------------------------------------------------------
diff --git a/FUTURE.md b/FUTURE.md
index 6ff6884..41c2c62 100644
--- a/FUTURE.md
+++ b/FUTURE.md
@@ -35,8 +35,8 @@ Care is required here not to remove permissions that are still needed by other p
### `--prepare`
-Takes over part of cordova-cli's `prepare` command. Copies all plugins' Javascript files (more precisely, those specified in `<js-module>` tags rather than `<asset>` tags) into `www/plugins/com.plugin.id/whatever/path/file.js` and constructs the `plugins.json` file.
+Takes over part of cordova-cli's `prepare` command. Copies all plugins' Javascript files (more precisely, those specified in `<js-module>` tags rather than `<asset>` tags) into `www/plugins/com.plugin.id/whatever/path/file.js` and constructs the `cordova_plugins.json` file.
-`cordova.js` in this new model will have code that reads this `plugins.json` file via XHR, loads the JS files for the plugins, and does their clobbers and merges.
+`cordova.js` in this new model will have code that reads this `cordova_plugins.json` file via XHR, loads the JS files for the plugins, and does their clobbers and merges.
This is something of a change from the current cordova-cli method, but necessary because we won't be working with a fresh `cordova.js` file on each run anymore.
http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/c130382d/plugman.js
----------------------------------------------------------------------
diff --git a/plugman.js b/plugman.js
index 9ddcd94..0ecad95 100755
--- a/plugman.js
+++ b/plugman.js
@@ -26,6 +26,8 @@ var fs = require('fs')
, et = require('elementtree')
, nopt = require('nopt')
, plugins = require('./util/plugins')
+ , shell = require('shelljs')
+ , plugin_loader = require('./util/plugin_loader')
, platform_modules = {
'android': require('./platforms/android'),
'ios': require('./platforms/ios'),
@@ -40,10 +42,23 @@ var known_opts = { 'platform' : [ 'ios', 'android', 'bb10' ,'www' ]
, 'list' : Boolean
, 'v' : Boolean
, 'debug' : Boolean
+ , 'prepare' : Boolean
+ , 'plugins': path
+ , 'www': path
};
var cli_opts = nopt(known_opts);
+// Default the plugins_dir to './cordova/plugins'.
+var plugins_dir;
+
+// Without these arguments, the commands will fail and print the usage anyway.
+if (cli_opts.plugins_dir || cli_opts.project) {
+ plugins_dir = typeof cli_opts.plugins_dir == 'string' ?
+ cli_opts.plugins_dir :
+ path.join(cli_opts.project, 'cordova', 'plugins');
+}
+
// only dump stack traces in debug mode, otherwise show error message and exit
if (!cli_opts.debug) {
// provide clean output on exceptions rather than dumping a stack trace
@@ -63,6 +78,9 @@ else if (cli_opts.list) {
}
});
}
+else if (cli_opts.prepare && cli_opts.project && cli_opts.www) {
+ util.handlePrepare(cli_opts.project, plugins_dir, cli_opts.www, cli_opts.platform);
+}
else if (!cli_opts.platform || !cli_opts.project || !cli_opts.plugin) {
printUsage();
}
@@ -79,6 +97,8 @@ function printUsage() {
console.log('Add a plugin:\n\t' + package.name + ' --platform <'+ platforms +'> --project <directory> --plugin <directory|git-url|name>\n');
console.log('Remove a plugin:\n\t' + package.name + ' --remove --platform <'+ platforms +'> --project <directory> --plugin <directory|git-url|name>\n');
console.log('List plugins:\n\t' + package.name + ' --list\n');
+ console.log('Prepare project:\n\t' + package.name + ' --prepare --platform <ios|android|bb10> --project <directory> --www <directory> [--plugins_dir <directory>]');
+ console.log('\n\t--plugins_dir defaults to <project>/cordova/plugins, but can be any directory containing a subdirectory for each plugin');
}
function execAction(action, platform, project_dir, plugin_dir) {
@@ -95,9 +115,24 @@ function execAction(action, platform, project_dir, plugin_dir) {
function handlePlugin(action, platform, project_dir, plugin_dir) {
var plugin_xml_path, async = false;
+ // Ensure the containing directory exists.
+ shell.mkdir('-p', plugins_dir);
+
// clone from git repository
if(plugin_dir.indexOf('https://') == 0 || plugin_dir.indexOf('git://') == 0) {
- plugin_dir = plugins.clonePluginGitRepo(plugin_dir);
+ plugin_dir = plugins.clonePluginGitRepo(plugin_dir, plugins_dir);
+ } else { // Copy from the local filesystem.
+ var lastSlash = plugin_dir.lastIndexOf(path.sep);
+ var dest = plugin_dir;
+ if (lastSlash >= 0) {
+ dest = dest.substring(lastSlash+1);
+ }
+ dest = path.join(plugins_dir, dest);
+
+ shell.rm('-rf', dest);
+ shell.cp('-R', plugin_dir, plugins_dir); // Yes, not dest.
+
+ plugin_dir = dest;
}
plugin_xml_path = path.join(plugin_dir, 'plugin.xml');
http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/c130382d/util/plugin_loader.js
----------------------------------------------------------------------
diff --git a/util/plugin_loader.js b/util/plugin_loader.js
new file mode 100644
index 0000000..6d55694
--- /dev/null
+++ b/util/plugin_loader.js
@@ -0,0 +1,141 @@
+/**
+ 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'),
+ ls = fs.readdirSync,
+ util = require('util'),
+ exec = require('child_process').exec,
+ et = require('elementtree');
+
+
+// Called on --prepare.
+// Sets up each plugin's Javascript code to be loaded properly.
+// Expects a path to the project (platforms/android in CLI, . in plugman-only),
+// a path to where the plugins are downloaded, the www dir, and the platform ('android', 'ios', etc.).
+exports.handlePrepare = function(projectRoot, plugins_dir, wwwDir, platform) {
+ // Process:
+ // - List all plugins in plugins_dir
+ // - Load and parse their plugin.xml files.
+ // - Skip those without support for this platform. (No <platform> tags means JS-only!)
+ // - Build a list of all their js-modules, including platform-specific js-modules.
+ // - For each js-module (general first, then platform) build up an object storing the path and any clobbers, merges and runs for it.
+ // - Write this object into www/plugins.json.
+ // - Cordova.js contains code to load them at runtime from that file.
+
+ var plugins = ls(plugins_dir);
+
+ // This array holds all the metadata for each module and ends up in cordova_plugins.json
+ var moduleObjects = [];
+
+
+ plugins && plugins.forEach(function(plugin) {
+ var pluginDir = path.join(plugins_dir, plugin);
+ var xml = new et.ElementTree(et.XML(fs.readFileSync(path.join(pluginDir, 'plugin.xml'), 'utf-8')));
+
+ var plugin_id = xml.getroot().attrib.id;
+
+ // Copy all the <asset>s into the platform's www/
+ var assets = xml.findall('./asset');
+ assets && assets.forEach(function(asset) {
+ var target = asset.attrib.target;
+ var lastSlash = target.lastIndexOf('/');
+ var dirname = lastSlash < 0 ? '' : target.substring(0, lastSlash);
+ var basename = lastSlash < 0 ? target : target.substring(lastSlash + 1);
+
+ var targetDir = path.join(wwwDir, dirname);
+ shell.mkdir('-p', targetDir);
+
+ var srcFile = path.join(pluginDir, asset.attrib.src);
+ var targetFile = path.join(targetDir, basename);
+
+ var cpOptions = fs.statSync(srcFile).isDirectory() ? '-Rf' : '-f';
+ shell.cp(cpOptions, [srcFile], targetFile);
+ });
+
+ // And then add the plugins dir to the platform's www.
+ var platformPluginsDir = path.join(wwwDir, 'plugins');
+ shell.mkdir('-p', platformPluginsDir);
+
+ var generalModules = xml.findall('./js-module');
+ var platformTag = xml.find(util.format('./platform[@name="%s"]', platform));
+
+ generalModules = generalModules || [];
+ var platformModules = platformTag ? platformTag.findall('./js-module') : [];
+ var allModules = generalModules.concat(platformModules);
+
+ allModules.forEach(function(module) {
+ // Copy the plugin's files into the www directory.
+ var dirname = module.attrib.src;
+ var lastSlash = dirname.lastIndexOf('/');
+ if (lastSlash >= 0) {
+ dirname = dirname.substring(0, lastSlash);
+ } else {
+ dirname = ''; // Just the file, no subdir.
+ }
+
+ var dir = path.join(platformPluginsDir, plugin_id, dirname);
+ shell.mkdir('-p', dir);
+
+ // Read in the file, prepend the cordova.define, and write it back out.
+ var moduleName = plugin_id + '.';
+ if (module.attrib.name) {
+ moduleName += module.attrib.name;
+ } else {
+ var result = module.attrib.src.match(/([^\/]+)\.js/);
+ moduleName += result[1];
+ }
+
+ var scriptContent = fs.readFileSync(path.join(pluginDir, module.attrib.src), 'utf-8');
+ scriptContent = 'cordova.define("' + moduleName + '", function(require, exports, module) {' + scriptContent + '});\n';
+ fs.writeFileSync(path.join(platformPluginsDir, plugin_id, module.attrib.src), scriptContent, 'utf-8');
+
+ // Prepare the object for cordova_plugins.json.
+ var obj = {
+ file: path.join('plugins', plugin_id, module.attrib.src),
+ id: moduleName
+ };
+
+ // Loop over the children of the js-module tag, collecting clobbers, merges and runs.
+ module.getchildren().forEach(function(child) {
+ if (child.tag.toLowerCase() == 'clobbers') {
+ if (!obj.clobbers) {
+ obj.clobbers = [];
+ }
+ obj.clobbers.push(child.attrib.target);
+ } else if (child.tag.toLowerCase() == 'merges') {
+ if (!obj.merges) {
+ obj.merges = [];
+ }
+ obj.merges.push(child.attrib.target);
+ } else if (child.tag.toLowerCase() == 'runs') {
+ obj.runs = true;
+ }
+ });
+
+ // Add it to the list of module objects bound for cordova_plugins.json
+ moduleObjects.push(obj);
+ });
+ });
+
+ // Write out moduleObjects as JSON to cordova_plugins.json
+ fs.writeFileSync(path.join(wwwDir, 'cordova_plugins.json'), JSON.stringify(moduleObjects), 'utf-8');
+};
+
http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/c130382d/util/plugins.js
----------------------------------------------------------------------
diff --git a/util/plugins.js b/util/plugins.js
index 19e97a8..333fd92 100644
--- a/util/plugins.js
+++ b/util/plugins.js
@@ -66,13 +66,20 @@ exports.listAllPlugins = function(success, error) {
});
}
-exports.clonePluginGitRepo = function(plugin_git_url) {
+exports.clonePluginGitRepo = function(plugin_git_url, plugins_dir) {
if(!shell.which('git')) {
throw new Error('git command line is not installed');
}
// use osenv to get a temp directory in a portable way
- plugin_dir = path.join(osenv.tmpdir(), 'plugin');
-
+ var lastSlash = plugin_git_url.lastIndexOf('/');
+ var basename = plugin_git_url.substring(lastSlash+1);
+ var dotGitIndex = basename.lastIndexOf('.git');
+ if (dotGitIndex >= 0) {
+ basename = basename.substring(0, dotGitIndex);
+ }
+
+ var plugin_dir = path.join(plugins_dir, basename);
+
// trash it if it already exists (something went wrong before probably)
if(fs.existsSync(plugin_dir)) {
shell.rm('-rf', plugin_dir);
@@ -82,14 +89,6 @@ exports.clonePluginGitRepo = function(plugin_git_url) {
throw new Error('failed to get the plugin via git URL '+ plugin_git_url);
}
- process.on('exit', function() {
- console.log('cleaning up...');
- // clean up
- if(fs.existsSync(plugin_dir)) {
- shell.rm('-rf', plugin_dir);
- }
- });
-
return plugin_dir;
}