diff --git a/tools/commands-cordova.js b/tools/commands-cordova.js index cdb28a7572..ecf1a31c10 100644 --- a/tools/commands-cordova.js +++ b/tools/commands-cordova.js @@ -25,11 +25,54 @@ var Console = require('./console.js').Console; // XXX hard-coded the use of default tropohouse var tropo = tropohouse.default; +var supportedPlatforms = ['ios', 'android', 'firefoxos']; +var webArchName = "web.cordova"; var cordova = exports; -var supportedPlatforms = ['ios', 'android', 'firefoxos']; -var webArchName = "web.cordova"; + +// --- the public interface --- + +// Builds a Cordova project that targets the list of 'platforms' +// options: +// - appName: the target path of the build +// - host +// - port +cordova.buildPlatforms = function (localPath, platforms, options) { + verboseLog('Running build for platforms:', platforms); + checkRequestedPlatforms(platforms); + buildCordova(localPath, 'build', options); +}; + +cordova.buildPlatformRunners = function (localPath, platforms, options) { + var runners = []; + _.each(platforms, function (platformName) { + runners.push(new CordovaRunner(localPath, platformName, options)); + }); + return runners; +}; + +// packages - list of strings +cordova.filterPackages = function (packages) { +// We hard-code the 'cordova' and 'platform' namespaces + var ret = { + rest: [], + plugins: [] + }; + + _.each(packages, function (p) { + var namespace = p.split(':')[0]; + var name = p.split(':').slice(1).join(':'); + if (namespace === 'cordova') { + ret.plugins.push(name); + } else { + ret.rest.push(p); // leave it the same + } + }); + return ret; +}; + +// --- helpers --- var localCordova = path.join(files.getCurrentToolsDir(), "tools", "cordova-scripts", "cordova.sh"); @@ -130,6 +173,17 @@ var execFileSyncOrThrow = function (file, args, opts) { return childProcess; }; +var getLoadedPackages = _.once(function () { + var uniload = require('./uniload.js'); + return uniload.load({ + packages: [ 'boilerplate-generator', 'logging', 'webapp-hashing' ] + }); +}); + + + +// --- Cordova routines --- + var ensureAndroidBundleCache = {}; var ensureAndroidBundle = function (command) { @@ -159,13 +213,6 @@ var ensureAndroidBundle = function (command) { } }; -var getLoadedPackages = _.once(function () { - var uniload = require('./uniload.js'); - return uniload.load({ - packages: [ 'boilerplate-generator', 'logging', 'webapp-hashing' ] - }); -}); - var generateCordovaBoilerplate = function (clientDir, options) { var clientJsonPath = path.join(clientDir, 'program.json'); var clientJson = JSON.parse(fs.readFileSync(clientJsonPath, 'utf8')); @@ -212,61 +259,6 @@ var generateCordovaBoilerplate = function (clientDir, options) { return boilerplate.toHTML(); }; -var fetchCordovaPluginFromShaUrl = - function (urlWithSha, localPluginsDir, pluginName) { - verboseLog('Fetching a tarball from url:', urlWithSha); - var pluginPath = path.join(localPluginsDir, pluginName); - var pluginTarballPath = pluginPath + '.tgz'; - - var execFileSync = require('./utils.js').execFileSync; - var whichCurl = execFileSync('which', ['curl']); - - var downloadProcess = null; - - if (whichCurl.success) { - verboseLog('Downloading with curl'); - downloadProcess = - execFileSyncOrThrow('curl', ['-L', urlWithSha, '-o', pluginTarballPath]); - } else { - verboseLog('Downloading with wget'); - downloadProcess = - execFileSyncOrThrow('wget', ['-O', pluginTarballPath, urlWithSha]); - } - - if (! downloadProcess.success) - throw new Error("Failed to fetch the tarball from " + urlWithSha + ": " + - downloadProcess.stderr); - - verboseLog('Create a folder for the plugin', pluginPath); - files.mkdir_p(pluginPath); - - verboseLog('Untarring the tarball with plugin'); - var tarProcess = execFileSyncOrThrow('tar', - ['xf', pluginTarballPath, '-C', pluginPath, '--strip-components=1']); - if (! tarProcess.success) - throw new Error("Failed to untar the tarball from " + urlWithSha + ": " + - tarProcess.stderr); - verboseLog('Untarring succeeded, removing the tarball'); - files.rm_recursive(pluginTarballPath); - return pluginPath; -}; - -cordova.checkIsValidPlatform = function (name) { - if (name.match(/ios/i) && process.platform !== 'darwin') - throw new Error(name + ': not available on your system'); - if (! _.contains(supportedPlatforms, name)) - throw new Error(name + ': no such platform'); -}; - -cordova.checkIsValidPlugin = function (name) { - var pluginHash = {}; - pluginHash[name.split('@')[0]] = name.split('@')[1]; - - // check that every plugin is specifying either an exact constraint or a - // tarball url with sha - utils.ensureOnlyExactVersions(pluginHash); -}; - // options // - debug var getBundle = function (bundlePath, webArchs, options) { @@ -289,16 +281,8 @@ var getBundle = function (bundlePath, webArchs, options) { return bundleResult; }; -var localPluginsPathFromCordovaPath = function (cordovaPath) { - return path.join(cordovaPath, 'local-plugins'); -}; - -//////////////////////////////////////////////////////////////////////////////// -// ensureCordova -//////////////////////////////////////////////////////////////////////////////// - // Creates a Cordova project if necessary. -cordova.ensureCordovaProject = function (localPath, appName) { +var ensureCordovaProject = function (localPath, appName) { verboseLog('Ensuring the cordova build project'); var cordovaPath = path.join(localPath, 'cordova-build'); var localPluginsPath = localPluginsPathFromCordovaPath(cordovaPath); @@ -322,9 +306,11 @@ cordova.ensureCordovaProject = function (localPath, appName) { } }; +// --- Cordova platforms --- + // Ensures that the Cordova platforms are synchronized with the app-level // platforms. -cordova.ensureCordovaPlatforms = function (localPath) { +var ensureCordovaPlatforms = function (localPath) { verboseLog('Ensuring that platforms in cordova build project are in sync'); var cordovaPath = path.join(localPath, 'cordova-build'); var platforms = project.getCordovaPlatforms(); @@ -371,6 +357,40 @@ cordova.ensureCordovaPlatforms = function (localPath) { return true; }; +// checks that every requested platform such as 'android' or 'ios' is already +// added to the project +var checkRequestedPlatforms = function (platforms) { + platforms = _.uniq(platforms); + + var requestedPlatforms = []; + // Find the required platforms. + // ie. ["ios", "android", "ios-device"] will produce ["ios", "android"] + _.each(platforms, function (platformName) { + var platform = platformName.split('-')[0]; + if (! _.contains(requestedPlatforms, platform)) { + requestedPlatforms.push(platform); + } + }); + + var cordovaPlatforms = project.getCordovaPlatforms(); + _.each(requestedPlatforms, function (platform) { + if (! _.contains(cordovaPlatforms, platform)) + throw new Error(platform + +": platform is not added to the project.\n" + +"Try 'meteor add-platform " + platform + "' to add it or\n" + +"'meteor help add-platform' for help."); + }); +}; + +var isValidPlatform = function (name) { + if (name.match(/ios/i) && process.platform !== 'darwin') + throw new Error(name + ': not available on your system'); + if (! _.contains(supportedPlatforms, name)) + throw new Error(name + ': no such platform'); +}; + + +// --- Cordova plugins --- var installPlugin = function (cordovaPath, name, version, settings) { verboseLog('Installing a plugin', name, version); @@ -599,7 +619,7 @@ var ensureCordovaPlugins = function (localPath, options) { // Cordova to fix the bug in their system, because it doesn't seem // like there's a way around this. files.rm_recursive(path.join(cordovaPath, 'platforms')); - cordova.ensureCordovaPlatforms(localPath); + ensureCordovaPlatforms(localPath); }; Console.stdout.write("Initializing Cordova plugins...\n"); uninstallAllPlugins(); @@ -622,6 +642,53 @@ var ensureCordovaPlugins = function (localPath, options) { } }; +var fetchCordovaPluginFromShaUrl = + function (urlWithSha, localPluginsDir, pluginName) { + verboseLog('Fetching a tarball from url:', urlWithSha); + var pluginPath = path.join(localPluginsDir, pluginName); + var pluginTarballPath = pluginPath + '.tgz'; + + var execFileSync = require('./utils.js').execFileSync; + var whichCurl = execFileSync('which', ['curl']); + + var downloadProcess = null; + + if (whichCurl.success) { + verboseLog('Downloading with curl'); + downloadProcess = + execFileSyncOrThrow('curl', ['-L', urlWithSha, '-o', pluginTarballPath]); + } else { + verboseLog('Downloading with wget'); + downloadProcess = + execFileSyncOrThrow('wget', ['-O', pluginTarballPath, urlWithSha]); + } + + if (! downloadProcess.success) + throw new Error("Failed to fetch the tarball from " + urlWithSha + ": " + + downloadProcess.stderr); + + verboseLog('Create a folder for the plugin', pluginPath); + files.mkdir_p(pluginPath); + + verboseLog('Untarring the tarball with plugin'); + var tarProcess = execFileSyncOrThrow('tar', + ['xf', pluginTarballPath, '-C', pluginPath, '--strip-components=1']); + if (! tarProcess.success) + throw new Error("Failed to untar the tarball from " + urlWithSha + ": " + + tarProcess.stderr); + verboseLog('Untarring succeeded, removing the tarball'); + files.rm_recursive(pluginTarballPath); + return pluginPath; +}; + +var localPluginsPathFromCordovaPath = function (cordovaPath) { + return path.join(cordovaPath, 'local-plugins'); +}; + + + +// --- Cordova from project --- + // Returns the cordovaDependencies of the Cordova arch from a star json. var getCordovaDependenciesFromStar = function (star) { var cordovaProgram = _.findWhere(star.programs, { arch: webArchName }); @@ -644,8 +711,8 @@ var buildCordova = function (localPath, buildCommand, options) { verboseLog('Bundling the web.cordova program of the app'); var bundle = getBundle(bundlePath, [webArchName], options); - cordova.ensureCordovaProject(localPath, options.appName); - cordova.ensureCordovaPlatforms(localPath); + ensureCordovaProject(localPath, options.appName); + ensureCordovaPlatforms(localPath); ensureCordovaPlugins(localPath, _.extend({}, options, { packagePlugins: getCordovaDependenciesFromStar(bundle.starManifest) })); @@ -718,51 +785,6 @@ var buildCordova = function (localPath, buildCommand, options) { verboseLog('Done building the cordova build project'); }; -// checks that every requested platform such as 'android' or 'ios' is already -// added to the project -var checkRequestedPlatforms = function (platforms) { - platforms = _.uniq(platforms); - - var requestedPlatforms = []; - // Find the required platforms. - // ie. ["ios", "android", "ios-device"] will produce ["ios", "android"] - _.each(platforms, function (platformName) { - var platform = platformName.split('-')[0]; - if (! _.contains(requestedPlatforms, platform)) { - requestedPlatforms.push(platform); - } - }); - - var cordovaPlatforms = project.getCordovaPlatforms(); - _.each(requestedPlatforms, function (platform) { - if (! _.contains(cordovaPlatforms, platform)) - throw new Error(platform + -": platform is not added to the project.\n" + -"Try 'meteor add-platform " + platform + "' to add it or\n" + -"'meteor help add-platform' for help."); - }); -}; - -// Builds a Cordova project that targets the list of 'platforms' -// options: -// - appName: the target path of the build -// - host -// - port -cordova.buildPlatforms = function (localPath, platforms, options) { - verboseLog('Running build for platforms:', platforms); - checkRequestedPlatforms(platforms); - buildCordova(localPath, 'build', options); -}; - - -cordova.buildPlatformRunners = function (localPath, platforms, options) { - var runners = []; - _.each(platforms, function (platformName) { - runners.push(new CordovaRunner(localPath, platformName, options)); - }); - return runners; -}; - // This is a runner, that we pass to Runner (run-all.js) var CordovaRunner = function (localPath, platformName, options) { @@ -961,28 +983,6 @@ var execCordovaOnPlatform = function (localPath, platformName, options) { return 0; }; - - -// packages - list of strings -cordova.filterPackages = function (packages) { -// We hard-code the 'cordova' and 'platform' namespaces - var ret = { - rest: [], - plugins: [] - }; - - _.each(packages, function (p) { - var namespace = p.split(':')[0]; - var name = p.split(':').slice(1).join(':'); - if (namespace === 'cordova') { - ret.plugins.push(name); - } else { - ret.rest.push(p); // leave it the same - } - }); - return ret; -}; - var getTermsForPlatform = function (platform) { var url = 'https://warehouse.meteor.com/cordova/license_cordova_' + platform + '.txt'; var result = httpHelpers.request({ @@ -1039,6 +1039,9 @@ var checkAgreePlatformTerms = function (platform) { return agreed; }; + +// --- Cordova commands --- + // add one or more Cordova platforms main.registerCommand({ name: "add-platform", @@ -1055,7 +1058,7 @@ main.registerCommand({ try { _.each(platforms, function (platform) { - cordova.checkIsValidPlatform(platform); + isValidPlatform(platform); }); } catch (err) { Console.stderr.write(err.message + "\n"); @@ -1081,8 +1084,8 @@ main.registerCommand({ files.mkdir_p(localPath); var appName = path.basename(options.appDir); - cordova.ensureCordovaProject(localPath, appName); - cordova.ensureCordovaPlatforms(localPath); + ensureCordovaProject(localPath, appName); + ensureCordovaPlatforms(localPath); } _.each(platforms, function (platform) { @@ -1114,8 +1117,8 @@ main.registerCommand({ files.mkdir_p(localPath); var appName = path.basename(options.appDir); - cordova.ensureCordovaProject(localPath, appName); - cordova.ensureCordovaPlatforms(localPath); + ensureCordovaProject(localPath, appName); + ensureCordovaPlatforms(localPath); } }); @@ -1152,3 +1155,4 @@ main.registerCommand({ } return 0; }); + diff --git a/tools/package-source.js b/tools/package-source.js index 5242a0eb2f..cffd2404f8 100644 --- a/tools/package-source.js +++ b/tools/package-source.js @@ -1477,6 +1477,9 @@ _.extend(PackageSource.prototype, { self.sourceRoot = appDir; self.serveRoot = path.sep; + // special files those are excluded from app's top-level sources + var controlFiles = ['mobile-config.js']; + _.each(self.allArchs, function (arch) { // Determine used packages var project = require('./project.js').project; @@ -1531,6 +1534,9 @@ _.extend(PackageSource.prototype, { exclude: sourceExclude }); + // don't include watched but not included control files + sources = _.difference(sources, controlFiles); + var otherUnibuildRegExp = (arch === "os" ? /^client\/$/ : /^server\/$/); diff --git a/tools/selftest.js b/tools/selftest.js index 2e2276d12f..da88f77800 100644 --- a/tools/selftest.js +++ b/tools/selftest.js @@ -833,7 +833,7 @@ _.extend(PhantomClient.prototype, { '/bin/bash', ['-c', ("exec " + phantomPath + " --load-images=no /dev/stdin <<'END'\n" + - phantomScript + "END\n")]); + phantomScript + "\nEND\n")]); }, stop: function() { var self = this;