You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by cs...@apache.org on 2015/12/03 23:59:34 UTC
cordova-lib git commit: CB-9964 Added --template to Cordova Create
Repository: cordova-lib
Updated Branches:
refs/heads/master 7af5c5367 -> ac57bebf3
CB-9964 Added --template to Cordova Create
Project: http://git-wip-us.apache.org/repos/asf/cordova-lib/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-lib/commit/ac57bebf
Tree: http://git-wip-us.apache.org/repos/asf/cordova-lib/tree/ac57bebf
Diff: http://git-wip-us.apache.org/repos/asf/cordova-lib/diff/ac57bebf
Branch: refs/heads/master
Commit: ac57bebf3b567f825fe6e586b34ddaa748a27185
Parents: 7af5c53
Author: dubeejw <jw...@us.ibm.com>
Authored: Thu Nov 5 16:05:06 2015 -0500
Committer: Carlos Santana <cs...@gmail.com>
Committed: Thu Dec 3 17:57:22 2015 -0500
----------------------------------------------------------------------
cordova-lib/spec-cordova/create.spec.js | 113 +++++++++++++++-----
cordova-lib/src/cordova/create.js | 127 +++++++++++++++++++----
cordova-lib/src/cordova/remote_load.js | 147 +++++++++++++++++++++++++++
3 files changed, 341 insertions(+), 46 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/ac57bebf/cordova-lib/spec-cordova/create.spec.js
----------------------------------------------------------------------
diff --git a/cordova-lib/spec-cordova/create.spec.js b/cordova-lib/spec-cordova/create.spec.js
index 0cbddc8..1f4be51 100644
--- a/cordova-lib/spec-cordova/create.spec.js
+++ b/cordova-lib/spec-cordova/create.spec.js
@@ -30,6 +30,7 @@ var tmpDir = helpers.tmpDir('create_test');
var appName = 'TestBase';
var appId = 'org.testing';
var project = path.join(tmpDir, appName);
+
var configNormal = {
lib: {
www: {
@@ -48,6 +49,28 @@ var configSymlink = {
}
};
+var configGit = {
+ lib: {
+ www: {
+ url: 'https://github.com/apache/cordova-app-hello-world',
+ template: true,
+ version: 'not_versioned',
+ id: appName
+ }
+ }
+};
+
+var configNPM = {
+ lib: {
+ www: {
+ template: true,
+ url: 'cordova-app-hello-world',
+ version: '',
+ id: appName
+ }
+ }
+};
+
describe('cordova create checks for valid-identifier', function(done) {
it('should reject reserved words from start of id', function(done) {
@@ -69,11 +92,14 @@ describe('cordova create checks for valid-identifier', function(done) {
describe('create end-to-end', function() {
+ //this.timeout(240000);
beforeEach(function() {
shell.rm('-rf', project);
shell.mkdir('-p', tmpDir);
});
+
+
afterEach(function() {
process.chdir(path.join(__dirname, '..')); // Needed to rm the dir on Windows.
shell.rm('-rf', tmpDir);
@@ -92,7 +118,7 @@ describe('create end-to-end', function() {
expect(path.join(project, 'www', 'index.html')).toExist();
// Check that www/config.xml was updated.
- var configXml = new ConfigParser(path.join(project, 'www', 'config.xml'));
+ var configXml = new ConfigParser(path.join(project, 'config.xml'));
expect(configXml.packageName()).toEqual(appId);
// TODO (kamrik): check somehow that we got the right config.xml from the fixture and not some place else.
@@ -105,37 +131,70 @@ describe('create end-to-end', function() {
it('should successfully run with regular config', function(done) {
// Call cordova create with no args, should return help.
Q()
- .then(function() {
- // Create a real project
- return cordova.raw.create(project, appId, appName, configNormal);
- })
- .then(checkProject)
- .fail(function(err) {
- console.log(err && err.stack);
- expect(err).toBeUndefined();
- })
- .fin(done);
+ .then(function() {
+ // Create a real project
+ return cordova.raw.create(project, appId, appName, configNormal);
+ })
+ .then(checkProject)
+ .fail(function(err) {
+ console.log(err && err.stack);
+ expect(err).toBeUndefined();
+ })
+ .fin(done);
});
it('should successfully run with symlinked www', function(done) {
// Call cordova create with no args, should return help.
cordova.raw.create(project, appId, appName, configSymlink)
- .then(checkProject)
- .then(function() {
- // Check that www is really a symlink
- expect(fs.lstatSync(path.join(project, 'www')).isSymbolicLink()).toBe(true);
- })
- .fail(function(err) {
- if(process.platform.slice(0, 3) == 'win') {
- // Allow symlink error if not in admin mode
- expect(err.message).toBe('Symlinks on Windows require Administrator privileges');
- } else {
- if (err) {
- console.log(err.stack);
+ .then(checkProject)
+ .then(function() {
+ // Check that www is really a symlink
+ expect(fs.lstatSync(path.join(project, 'www')).isSymbolicLink()).toBe(true);
+ })
+ .fail(function(err) {
+ if(process.platform.slice(0, 3) == 'win') {
+ // Allow symlink error if not in admin mode
+ expect(err.message).toBe('Symlinks on Windows require Administrator privileges');
+ } else {
+ if (err) {
+ console.log(err.stack);
+ }
+ expect(err).toBeUndefined();
}
+ })
+ .fin(done);
+ });
+
+ it('should successfully run with Git URL', function(done) {
+ // Call cordova create with no args, should return help.
+ Q()
+ .then(function() {
+ // Create a real project
+ return cordova.raw.create(project, appId, appName, configGit);
+ })
+ .then(checkProject)
+ .fail(function(err) {
+ console.log(err && err.stack);
expect(err).toBeUndefined();
- }
- })
- .fin(done);
+ })
+ .fin(done);
+ }, 60000);
+
+ it('should successfully run with NPM package', function(done) {
+ // Call cordova create with no args, should return help.
+ Q()
+ .then(function() {
+ // Create a real project
+ return cordova.raw.create(project, appId, appName, configNPM);
+ })
+ .then(checkProject)
+ .fail(function(err) {
+ console.log(err && err.stack);
+ expect(err).toBeUndefined();
+ })
+ .fin(done);
});
-});
+
+
+
+});
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/ac57bebf/cordova-lib/src/cordova/create.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/cordova/create.js b/cordova-lib/src/cordova/create.js
index 1f5e010..b848a16 100644
--- a/cordova-lib/src/cordova/create.js
+++ b/cordova-lib/src/cordova/create.js
@@ -22,7 +22,7 @@ var path = require('path'),
shell = require('shelljs'),
events = require('cordova-common').events,
config = require('./config'),
- lazy_load = require('./lazy_load'),
+ remoteLoad = require('./remote_load'),
Q = require('q'),
CordovaError = require('cordova-common').CordovaError,
ConfigParser = require('cordova-common').ConfigParser,
@@ -40,7 +40,7 @@ var path = require('path'),
module.exports = create;
function create(dir, optionalId, optionalName, cfg) {
var argumentCount = arguments.length;
-
+
return Q.fcall(function() {
// Lets check prerequisites first
@@ -165,24 +165,67 @@ function create(dir, optionalId, optionalName, cfg) {
config.setAutoPersist(origAutoPersist);
})
.then(function() {
+ var gitURL;
+ var branch;
+ var parseArr;
+ var packageName;
+ var packageVersion;
+ var isGit;
+ var isNPM;
+
if (!!cfg.lib.www.link) {
events.emit('verbose', 'Symlinking assets."');
return cfg.lib.www.url;
} else {
events.emit('verbose', 'Copying assets."');
- return lazy_load.custom({ 'www': cfg.lib.www }, 'www')
- .fail(function (error) {
- var message = 'Failed to fetch custom www assets from ' + cfg.lib.www +
- '\nProbably this is either a connection problem, or assets URL is incorrect.' +
- '\nCheck your connection and assets URL.' +
- '\n' + error;
- return Q.reject(message);
- });
+
+ isGit = cfg.lib.www.template && cordova_util.isUrl(cfg.lib.www.url);
+ isNPM = cfg.lib.www.template && (cfg.lib.www.url.indexOf('@') > -1 || !fs.existsSync(path.resolve(cfg.lib.www.url)));
+
+ if (isGit) {
+ parseArr = cfg.lib.www.url.split('#');
+ gitURL = parseArr[0];
+ branch = parseArr[1];
+
+ events.emit('log', 'Retrieving ' + cfg.lib.www.url + ' from GitHub...');
+
+ return remoteLoad.gitClone(gitURL, branch).fail(
+ function(err) {
+ events.emit('verbose', err);
+ return Q.reject('Failed to retrieve '+ cfg.lib.www.url + ' from Git.');
+ }
+ );
+ } else if (isNPM) {
+ events.emit('log', 'Retrieving ' + cfg.lib.www.url + ' from NPM...');
+
+ // Determine package name, and version
+ if (cfg.lib.www.url.indexOf('@') !== -1) {
+ parseArr = cfg.lib.www.url.split('@');
+ packageName = parseArr[0];
+ packageVersion = parseArr[1];
+ } else {
+ packageName = cfg.lib.www.url;
+ packageVersion = '';
+ }
+
+ return remoteLoad.npmFetch(packageName, packageVersion).fail(
+ function(err) {
+ events.emit('verbose', err);
+ return Q.reject('Failed to retrieve '+ cfg.lib.www.url + ' from NPM.');
+ }
+ );
+ } else {
+ cfg.lib.www.url = path.resolve(cfg.lib.www.url);
+
+ return Q(cfg.lib.www.url);
+ }
}
})
.then(function(import_from_path) {
+
if (!fs.existsSync(import_from_path)) {
- throw new CordovaError('Could not find directory: ' + import_from_path);
+ throw new CordovaError('Could not find directory: ' +
+ import_from_path);
}
var paths = {
@@ -191,21 +234,27 @@ function create(dir, optionalId, optionalName, cfg) {
};
// Keep going into child "www" folder if exists in stock app package.
+ // why?
while (fs.existsSync(path.join(paths.www, 'www'))) {
paths.root = paths.www;
paths.www = path.join(paths.root, 'www');
}
+ // find config.xml
if (fs.existsSync(path.join(paths.root, 'config.xml'))) {
paths.configXml = path.join(paths.root, 'config.xml');
paths.configXmlLinkable = true;
} else {
try {
- paths.configXml = path.join(require('cordova-app-hello-world').dirname, 'config.xml');
+ paths.configXml =
+ path.join(require('cordova-app-hello-world').dirname,
+ 'config.xml');
} catch (e) {
// Falling back on npm@2 path hierarchy
// TODO: Remove fallback after cordova-app-hello-world release
- paths.configXml = path.join(__dirname, '..', '..', 'node_modules', 'cordova-app-hello-world', 'config.xml');
+ paths.configXml =
+ path.join(__dirname, '..', '..', 'node_modules',
+ 'cordova-app-hello-world', 'config.xml');
}
}
if (fs.existsSync(path.join(paths.root, 'merges'))) {
@@ -218,11 +267,15 @@ function create(dir, optionalId, optionalName, cfg) {
paths.hooksLinkable = true;
} else {
try {
- paths.hooks = path.join(require('cordova-app-hello-world').dirname, 'hooks');
+ paths.hooks =
+ path.join(require('cordova-app-hello-world').dirname,
+ 'hooks');
} catch (e) {
// Falling back on npm@2 path hierarchy
// TODO: Remove fallback after cordova-app-hello-world release
- paths.hooks = path.join(__dirname, '..', '..', 'node_modules', 'cordova-app-hello-world', 'hooks');
+ paths.hooks =
+ path.join(__dirname, '..', '..', 'node_modules',
+ 'cordova-app-hello-world', 'hooks');
}
}
@@ -231,6 +284,7 @@ function create(dir, optionalId, optionalName, cfg) {
fs.mkdirSync(dir);
}
+
var tryToLink = !!cfg.lib.www.link;
function copyOrLink(src, dst, linkable) {
if (src) {
@@ -242,10 +296,43 @@ function create(dir, optionalId, optionalName, cfg) {
}
}
}
+
+ /*
+ Copies template files, and directories into a Cordova project directory.
+ Files, and directories not copied include: www, mergers,platforms,
+ plugins, hooks, and config.xml. A template directory, and platform
+ directory must be passed.
+
+ templateDir - Template directory
+ projectDir - Project directory
+ */
+ function copyTemplateFiles(templateDir, projectDir) {
+ var templateFiles; // Current file
+
+ templateFiles = fs.readdirSync(templateDir);
+
+ // Remove directories, and files that are automatically copied
+ templateFiles = templateFiles.filter(
+ function (value) {
+ return !(value === 'www' || value === 'mergers' ||
+ value === 'config.xml' || value === 'hooks');
+ }
+ );
+
+ // Copy each template file
+ for (var i = 0; i < templateFiles.length; i++)
+ shell.cp('-R', path.resolve(templateDir, templateFiles[i]), projectDir);
+ }
+
try {
copyOrLink(paths.www, path.join(dir, 'www'), true);
copyOrLink(paths.merges, path.join(dir, 'merges'), true);
- copyOrLink(paths.hooks, path.join(dir, 'hooks'), paths.hooksLinkable);
+ copyOrLink(paths.hooks, path.join(dir, 'hooks'),
+ paths.hooksLinkable);
+
+ if (cfg.lib.www.template)
+ copyTemplateFiles(import_from_path, dir);
+
if (paths.configXml) {
if (tryToLink && paths.configXmlLinkable) {
fs.symlinkSync(paths.configXml, path.join(dir, 'config.xml'));
@@ -262,10 +349,12 @@ function create(dir, optionalId, optionalName, cfg) {
}
throw e;
}
-
// Create basic project structure.
- shell.mkdir(path.join(dir, 'platforms'));
- shell.mkdir(path.join(dir, 'plugins'));
+ if (!fs.existsSync(path.join(dir, 'platforms')))
+ shell.mkdir(path.join(dir, 'platforms'));
+
+ if (!fs.existsSync(path.join(dir, 'plugins')))
+ shell.mkdir(path.join(dir, 'plugins'));
// Write out id and name to config.xml
var configPath = cordova_util.projectConfig(dir);
http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/ac57bebf/cordova-lib/src/cordova/remote_load.js
----------------------------------------------------------------------
diff --git a/cordova-lib/src/cordova/remote_load.js b/cordova-lib/src/cordova/remote_load.js
new file mode 100644
index 0000000..ac56786
--- /dev/null
+++ b/cordova-lib/src/cordova/remote_load.js
@@ -0,0 +1,147 @@
+/**
+ 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');
+var shell = require('shelljs');
+var Q = require('q');
+var npm = require('npm');
+var npmHelper = require('../util/npm-helper');
+var unpack = require('../util/unpack');
+var util = require('./util');
+var git = require('../gitclone');
+
+/*
+Fetches the latests version of a package from NPM. A promise is returned that
+resolves to the directory the NPM package is located in. Package options must be
+passed containing a packageName, name, and version.
+
+options - Package options
+ */
+function npmFetch(packageName, packageVersion) {
+ var versionCallback; // Resultant callback
+ var downloadDir; // Download directory
+ var npmPackage; // NPM package information
+
+ // Get the latest matching version from NPM if a version range is specified
+ versionCallback = util.getLatestMatchingNpmVersion(packageName, packageVersion).then(
+ function (latestVersion) {
+ downloadDir = path.join(util.libDirectory, packageName, 'cordova', latestVersion);
+ npmPackage = packageName + '@' + latestVersion;
+
+ return exports.npmCacheAdd(npmPackage);
+ },
+ function (err) {
+ return Q.reject(err);
+ }
+ );
+
+ return versionCallback;
+}
+
+/*
+Invokes "npm cache add," and then returns a promise that resolves to a
+directory containing the downloaded, or cached package. NPM package information
+must be passed in the form of package@version.
+
+npmPackage - NPM package details
+ */
+function npmCacheAdd(npmPackage) {
+ var loadCallback; // Resultant callback
+ var cacheAddCallback; // Callback for cache
+ var cacheDir; // Cache directory
+ var npmConfig; // NPM Configuration
+ var packageDir; // Downloaded package directory
+ var packageTGZ; // Downloaded TGZ directory
+
+ cacheDir = path.join(util.libDirectory, 'npm_cache');
+
+ npmConfig = {
+ 'cache-min': 3600 * 24,
+ 'cache': cacheDir
+ };
+
+ // Load with NPM configuration
+ loadCallback = npmHelper.loadWithSettingsThenRestore(npmConfig,
+ function () {
+
+ // Invoke NPM Cache Add
+ cacheAddCallback = Q.ninvoke(npm.commands, 'cache', ['add', npmPackage]).then(
+ function (info) {
+ packageDir = path.resolve(npm.cache, info.name, info.version, 'package');
+ packageTGZ = path.resolve(npm.cache, info.name, info.version, 'package.tgz');
+
+ return unpack.unpackTgz(packageTGZ, packageDir);
+ },
+ function (err) {
+ return Q.reject(err);
+ }
+ );
+
+ return cacheAddCallback;
+ },
+ function (err) {
+ return Q.reject(err);
+ }
+ );
+
+ return loadCallback;
+}
+
+/*
+Performs a Git clone an a Git URL, and branch. If the clone was successful,
+the path to the cloned directory will be returned. Otherwise, a error is
+returned. A gitURL, must be passed, and a branch to checkout at is optionally
+passed.
+
+gitURL - URL to Git repository
+branch - Branch to checkout at
+ */
+function gitClone(gitURL, branch) {
+ var cloneCallback; // Resultant callback
+ var tmpSubDir; // Temporary sub-directory
+ var tmpDir; // Temporary directory
+ var checkoutBranch; // Branch to checkout
+
+ checkoutBranch = branch || 'master';
+ tmpSubDir = 'tmp_cordova_git_' + process.pid + '_' + (new Date()).valueOf();
+ tmpDir = path.join(util.libDirectory, 'tmp', tmpSubDir);
+
+ shell.rm('-rf', tmpDir);
+ shell.mkdir('-p', tmpDir);
+
+ cloneCallback = git.clone(gitURL, checkoutBranch, tmpDir);
+
+ // Callback for Git clone
+ cloneCallback.then(
+ function() {
+ return tmpDir;
+ },
+ function (err) {
+ shell.rm('-rf', tmpDir);
+
+ return Q.reject(err);
+ }
+ );
+
+ return cloneCallback;
+}
+
+exports.gitClone = gitClone;
+exports.npmFetch = npmFetch;
+exports.npmCacheAdd = npmCacheAdd;
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org