From 52360a91355a0a326ac9f3974a564a062f3d3cce Mon Sep 17 00:00:00 2001 From: Slava Kim Date: Tue, 23 Sep 2014 11:36:45 -0700 Subject: [PATCH 01/29] Do not include android and ios platforms in the default examples --- examples/leaderboard/.meteor/cordova-platforms | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 examples/leaderboard/.meteor/cordova-platforms diff --git a/examples/leaderboard/.meteor/cordova-platforms b/examples/leaderboard/.meteor/cordova-platforms deleted file mode 100644 index c966e1ea2f..0000000000 --- a/examples/leaderboard/.meteor/cordova-platforms +++ /dev/null @@ -1,2 +0,0 @@ -android -ios \ No newline at end of file From 9055e8e0f2602d54d18ea9fa3a5c1a252f408942 Mon Sep 17 00:00:00 2001 From: Slava Kim Date: Tue, 23 Sep 2014 11:57:10 -0700 Subject: [PATCH 02/29] Don't produce a JSON file containing "undefined". #2621 And correctly read the old settings before overriding them (should fix the settings invalidation problem). --- tools/commands-cordova.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tools/commands-cordova.js b/tools/commands-cordova.js index de581109a8..52f60bd658 100644 --- a/tools/commands-cordova.js +++ b/tools/commands-cordova.js @@ -454,23 +454,23 @@ var ensureCordovaPlugins = function (localPath, options) { var cordovaPath = path.join(localPath, 'cordova-build'); var settingsFile = path.join(cordovaPath, 'cordova-settings.json'); - var newSettings; - if (options.settings) { - newSettings = - JSON.parse(fs.readFileSync(options.settings, "utf8")).cordova; - fs.writeFileSync(settingsFile, JSON.stringify(newSettings, null, 2), - 'utf8'); - } - var oldSettings; try { - oldSettings = JSON.parse(fs.readFileSync(settingsFile, 'utf8')); + oldSettings = JSON.parse(fs.readFileSync(settingsFile, 'utf8')) || {}; } catch(err) { if (err.code !== 'ENOENT') throw err; oldSettings = {}; } + var newSettings; + if (options.settings) { + newSettings = + JSON.parse(fs.readFileSync(options.settings, "utf8")).cordova || {}; + fs.writeFileSync(settingsFile, JSON.stringify(newSettings, null, 2), + 'utf8'); + } + // XXX compare the latest used sha's with the currently required sha's for // plugins fetched from a github/tarball url. From 1f1ed7472493f9c2d326fe115a93eb0790e8b5ec Mon Sep 17 00:00:00 2001 From: Slava Kim Date: Tue, 23 Sep 2014 12:29:50 -0700 Subject: [PATCH 03/29] Print a nice error message in case of building iOS app from /tmp --- tools/commands-cordova.js | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/tools/commands-cordova.js b/tools/commands-cordova.js index 52f60bd658..ed18bf6dd5 100644 --- a/tools/commands-cordova.js +++ b/tools/commands-cordova.js @@ -619,8 +619,26 @@ var buildCordova = function (localPath, buildCommand, options) { verboseLog('Running the build command:', buildCommand); // Give the buffer more space as the output of the build is really huge - execFileSyncOrThrow(localCordova, [buildCommand], - { cwd: cordovaPath, maxBuffer: 2000*1024 }); + try { + execFileSyncOrThrow(localCordova, [buildCommand], + { cwd: cordovaPath, maxBuffer: 2000*1024 }); + } catch (err) { + // "ld: 100000 duplicate symbols for architecture i386" is a common error + // message that occurs when you run an iOS project compilation from /tmp or + // whenever there is a symbolic link cycle reachable for ld to multiple + // object files. + if (err.message.match(/ld: \d+ duplicate symbols/g)) { + // XXX a better message + var message = "Can't build an iOS project from the /tmp directory."; + + if (verboseness) + message = err.message + '\n' + message; + + throw new Error(message); + } else { + throw err; + } + } verboseLog('Done building the cordova build project'); }; From b76f81697666c9a8e6aed3b69a69c13542951d98 Mon Sep 17 00:00:00 2001 From: Slava Kim Date: Tue, 23 Sep 2014 13:51:46 -0700 Subject: [PATCH 04/29] Do not install the Cordova iOS platform on non-OSX OSes --- tools/commands-cordova.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/commands-cordova.js b/tools/commands-cordova.js index ed18bf6dd5..2825f3b781 100644 --- a/tools/commands-cordova.js +++ b/tools/commands-cordova.js @@ -319,8 +319,13 @@ cordova.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(); - var platformsList = execFileSyncOrThrow(localCordova, ['platform', 'list'], - { cwd: cordovaPath }); + var platformsList = execFileSyncOrThrow( + localCordova, ['platform', 'list'], { cwd: cordovaPath }); + + // skip iOS platform if not on darwin + if (process.platform !== 'darwin') { + platforms = _.difference(platforms, ['ios']); + } verboseLog('The output of `cordova platforms list`:', platformsList.stdout); From 77649caa0aece4e7f3fa0e2f05f2e16b86f058e2 Mon Sep 17 00:00:00 2001 From: Slava Kim Date: Tue, 23 Sep 2014 14:35:34 -0700 Subject: [PATCH 05/29] A mild hack to give a better error message on incorrect json settings passed on a cordova build --- tools/commands-cordova.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tools/commands-cordova.js b/tools/commands-cordova.js index 2825f3b781..48c0288068 100644 --- a/tools/commands-cordova.js +++ b/tools/commands-cordova.js @@ -470,8 +470,16 @@ var ensureCordovaPlugins = function (localPath, options) { var newSettings; if (options.settings) { - newSettings = - JSON.parse(fs.readFileSync(options.settings, "utf8")).cordova || {}; + var settingsText = fs.readFileSync(options.settings, "utf8"); + var parsedSettings = {}; + try { + parsedSettings = JSON.parse(settingsText); + } catch (err) { + throw new Error( + 'Passed --settings are not a valid JSON: ' + settingsText); + } + + newSettings = parsedSettings.cordova || {}; fs.writeFileSync(settingsFile, JSON.stringify(newSettings, null, 2), 'utf8'); } From 6663015cbd7ec339eab04ee2058a6fd2c4f5b186 Mon Sep 17 00:00:00 2001 From: Slava Kim Date: Tue, 23 Sep 2014 15:32:03 -0700 Subject: [PATCH 06/29] Remove the ip-like url prefix for android logs --- tools/commands-cordova.js | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/commands-cordova.js b/tools/commands-cordova.js index 48c0288068..58d70f538f 100644 --- a/tools/commands-cordova.js +++ b/tools/commands-cordova.js @@ -781,6 +781,7 @@ var execCordovaOnPlatform = function (localPath, platformName, options) { line = line.replace(/^.\/CordovaLog\(\s*\d+\s*\):\s+/, ''); // remove a part of file url we don't like line = line.replace(/^file:\/\/\/android_asset\/www\//, ''); + line = line.replace(/^http:\/\/\d+\.\d+\.\d+\.\d+:\d+\//, ''); // filename.js?hashsha1: Line 123 : message goes here var parsedLine = line.match(/^([^?]+)(\?[a-zA-Z0-9]+)?: Line (\d+) : (.*)$/); From 573f8462e53134db8e2744fef040e5e96592b382 Mon Sep 17 00:00:00 2001 From: Slava Kim Date: Tue, 23 Sep 2014 15:46:58 -0700 Subject: [PATCH 07/29] Improve Android logs filtering --- tools/commands-cordova.js | 14 ++++++++++++-- tools/utils.js | 3 ++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/tools/commands-cordova.js b/tools/commands-cordova.js index 58d70f538f..714efc4c73 100644 --- a/tools/commands-cordova.js +++ b/tools/commands-cordova.js @@ -782,11 +782,21 @@ var execCordovaOnPlatform = function (localPath, platformName, options) { // remove a part of file url we don't like line = line.replace(/^file:\/\/\/android_asset\/www\//, ''); line = line.replace(/^http:\/\/\d+\.\d+\.\d+\.\d+:\d+\//, ''); + + // ignore annoying lines that we see all the time but don't bring any value + if (line.match(/^--------- beginning of /) || + line.match(/^Changing log level to/) || + line.match(/^Found start page location: /)) { + return null; + } + // filename.js?hashsha1: Line 123 : message goes here - var parsedLine = line.match(/^([^?]+)(\?[a-zA-Z0-9]+)?: Line (\d+) : (.*)$/); + var parsedLine = + line.match(/^([^?]*)(\?[a-zA-Z0-9]+)?: Line (\d+) : (.*)$/); if (! parsedLine) - return Log.format(Log.objFromText(line), { color: true }); + return Log.format( + Log.objFromText(line), { metaColor: 'green', color: true }); var output = { time: new Date, diff --git a/tools/utils.js b/tools/utils.js index 851f28da12..7251b85307 100644 --- a/tools/utils.js +++ b/tools/utils.js @@ -461,7 +461,8 @@ exports.execFileAsync = function (file, args, opts) { var logOutput = fiberHelpers.bindEnvironment(function (line) { if (opts.verbose) { line = mapper(line); - console.log(line); + if (line) + console.log(line); } }); From c1255aebd7426cb1bfb311beb6c1cdea6bb1188e Mon Sep 17 00:00:00 2001 From: Slava Kim Date: Tue, 23 Sep 2014 15:48:03 -0700 Subject: [PATCH 08/29] Use cloudfronted urls for android-bundle --- tools/commands-cordova.js | 2 +- tools/cordova-scripts/ensure_android_bundle.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/commands-cordova.js b/tools/commands-cordova.js index 714efc4c73..eef0118370 100644 --- a/tools/commands-cordova.js +++ b/tools/commands-cordova.js @@ -891,7 +891,7 @@ cordova.filterPackages = function (packages) { }; var getTermsForPlatform = function (platform) { - var url = 'http://s3.amazonaws.com/android-bundle/license_cordova_' + platform + '.txt'; + var url = 'https://warehouse.meteor.com/cordova/license_cordova_' + platform + '.txt'; var result = httpHelpers.request({ url: url }); diff --git a/tools/cordova-scripts/ensure_android_bundle.sh b/tools/cordova-scripts/ensure_android_bundle.sh index c2db0330a6..59f7c7daac 100755 --- a/tools/cordova-scripts/ensure_android_bundle.sh +++ b/tools/cordova-scripts/ensure_android_bundle.sh @@ -95,7 +95,7 @@ install_android_bundle () { rm -rf "$BUNDLE_TMPDIR" mkdir "$BUNDLE_TMPDIR" - ANDROID_BUNDLE_URL_ROOT="http://s3.amazonaws.com/android-bundle/" + ANDROID_BUNDLE_URL_ROOT="https://warehouse.meteor.com/cordova/" if [ -f "$DEST_DIR/$TARBALL" ] ; then echo "Skipping download and installing kit from $DEST_DIR/$TARBALL" >&2 From a2a1eef3bc66fbe33d1bd9e5e97e0f668705cacc Mon Sep 17 00:00:00 2001 From: Slava Kim Date: Tue, 23 Sep 2014 17:04:16 -0700 Subject: [PATCH 09/29] Lock the cordova-tarball-plugins.json --- tools/commands-cordova.js | 44 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/tools/commands-cordova.js b/tools/commands-cordova.js index eef0118370..8b087bd911 100644 --- a/tools/commands-cordova.js +++ b/tools/commands-cordova.js @@ -394,6 +394,12 @@ var installPlugin = function (cordovaPath, name, version, settings) { { cwd: cordovaPath }); if (! execRes.success) throw new Error("Failed to install plugin " + name + ": " + execRes.stderr); + + if (utils.isUrlWithSha(version)) { + var lock = getTarballPluginsLock(cordovaPath); + lock[name] = version; + writeTarballPluginsLock(cordovaPath, lock); + } }; var uninstallPlugin = function (cordovaPath, name) { @@ -409,6 +415,39 @@ var uninstallPlugin = function (cordovaPath, name) { } }; +var getTarballPluginsLock = function (cordovaPath) { + verboseLog('Will check for cordova-tarball-plugins.json' + + ' for tarball-url-based plugins previously installed.'); + + var tarballPluginsLockPath = + path.join(cordovaPath, 'cordova-tarball-plugins.json'); + + var tarballPluginsLock; + try { + var text = fs.readFileSync(tarballPluginsLockPath, 'utf8'); + tarballPluginsLock = JSON.parse(text); + + verboseLog('The tarball plugins lock:', tarballPluginsLock); + } catch (err) { + if (err.code !== 'ENOENT') + throw err; + + verboseLog('The tarball plugins file was not found.'); + tarballPluginsLock = {}; + } + + return tarballPluginsLock; +}; + +var writeTarballPluginsLock = function (cordovaPath, lock) { + verboseLog('Will write cordova-tarball-plugins.json'); + + var tarballPluginsLockPath = + path.join(cordovaPath, 'cordova-tarball-plugins.json'); + + fs.writeFileSync(tarballPluginsLock, JSON.stringify(lock), 'utf8'); +}; + // Returns the list of installed plugins as a hash from plugin name to version. var getInstalledPlugins = function (cordovaPath) { verboseLog('Getting installed plugins for project'); @@ -431,6 +470,11 @@ var getInstalledPlugins = function (cordovaPath) { }); } + // override the values of the plugins installed from tarballs + _.each(getTarballPluginsLock(cordovaPath), function (url, name) { + installedPlugins[name] = url; + }); + return installedPlugins; }; From 74c090e92a7ba44da34c76c798867159f090bcec Mon Sep 17 00:00:00 2001 From: Slava Kim Date: Tue, 23 Sep 2014 17:21:08 -0700 Subject: [PATCH 10/29] Fix the typo --- tools/commands-cordova.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/commands-cordova.js b/tools/commands-cordova.js index 8b087bd911..abed0e8129 100644 --- a/tools/commands-cordova.js +++ b/tools/commands-cordova.js @@ -439,13 +439,17 @@ var getTarballPluginsLock = function (cordovaPath) { return tarballPluginsLock; }; -var writeTarballPluginsLock = function (cordovaPath, lock) { +var writeTarballPluginsLock = function (cordovaPath, tarballPluginsLock) { verboseLog('Will write cordova-tarball-plugins.json'); var tarballPluginsLockPath = path.join(cordovaPath, 'cordova-tarball-plugins.json'); - fs.writeFileSync(tarballPluginsLock, JSON.stringify(lock), 'utf8'); + fs.writeFileSync( + tarballPluginsLockPath, + JSON.stringify(tarballPluginsLock), + 'utf8' + ); }; // Returns the list of installed plugins as a hash from plugin name to version. From 75a1c4c718687156e42f03c0864462d5f9933bf8 Mon Sep 17 00:00:00 2001 From: Slava Kim Date: Tue, 23 Sep 2014 17:36:56 -0700 Subject: [PATCH 11/29] Refactor build/bundle. Error when -p is not supplied. --- tools/commands.js | 105 ++++++++-------------------------------------- 1 file changed, 18 insertions(+), 87 deletions(-) diff --git a/tools/commands.js b/tools/commands.js index 605393097c..9586a92622 100644 --- a/tools/commands.js +++ b/tools/commands.js @@ -577,7 +577,19 @@ var buildCommands = { }; main.registerCommand(_.extend({ name: 'build' }, buildCommands), + function (options) { + return buildCommand(options); +}); + +// Deprecated -- identical functionality to 'build' +main.registerCommand(_.extend({ name: 'bundle', hidden: true }, buildCommands), function (options) { + Console.stdout.write("WARNING: 'bundle' has been deprecated. " + + "Use 'build' instead.\n"); + return buildCommand(options); +}); + +var buildCommand = function (options) { cordova.setVerboseness(options.verbose); // XXX output, to stderr, the name of the file written to (for human // comfort, especially since we might change the name) @@ -619,8 +631,11 @@ main.registerCommand(_.extend({ name: 'build' }, buildCommands), // warn about it. var cordovaBuildHost = parsedHostPort.host || DEFAULT_BUILD_HOST; if (cordovaBuildHost === DEFAULT_BUILD_HOST) { - process.stdout.write("WARNING: Building your app with host: localhost.\n" + - "Pass a -p argument to specify a host URL.\n"); + // XXX better error message? + process.stdout.write( + "Supply the server hostname and port argument in the -p option\n" + + "for the mobile apps builds.\n"); + return 1; } var cordovaSettings = {}; @@ -697,91 +712,7 @@ main.registerCommand(_.extend({ name: 'build' }, buildCommands), }); files.rm_recursive(buildDir); -}); - -// Deprecated -- identical functionality to 'build' -main.registerCommand(_.extend({ name: 'bundle', hidden: true }, buildCommands), - function (options) { - cordova.setVerboseness(options.verbose); - Console.stdout.write("WARNING: 'bundle' has been deprecated. " + - "Use 'build' instead.\n"); - // XXX if they pass a file that doesn't end in .tar.gz or .tgz, add - // the former for them - - // XXX output, to stderr, the name of the file written to (for human - // comfort, especially since we might change the name) - - // XXX name the root directory in the bundle based on the basename - // of the file, not a constant 'bundle' (a bit obnoxious for - // machines, but worth it for humans) - - // Error handling for options.architecture. We must pass in only one of three - // architectures. See archinfo.js for more information on what the - // architectures are, what they mean, et cetera. - var VALID_ARCHITECTURES = - ["os.osx.x86_64", "os.linux.x86_64", "os.linux.x86_32"]; - if (options.architecture && - _.indexOf(VALID_ARCHITECTURES, options.architecture) === -1) { - Console.stderr.write("Invalid architecture: " + options.architecture + "\n"); - Console.stderr.write( - "Please use one of the following: " + VALID_ARCHITECTURES + "\n"); - return 1; - } - var bundleArch = options.architecture || archinfo.host(); - - var buildDir = path.join(options.appDir, '.meteor', 'local', 'build_tar'); - var outputPath = path.resolve(options.args[0]); // get absolute path - var bundlePath = options['directory'] ? - outputPath : path.join(buildDir, 'bundle'); - - var loader; - var messages = buildmessage.capture(function () { - loader = project.getPackageLoader(); - }); - if (messages.hasMessages()) { - Console.stderr.write("Errors prevented bundling your app:\n"); - Console.stderr.write(messages.formatMessages()); - return 1; - } - - var statsMessages = buildmessage.capture(function () { - stats.recordPackages("sdk.bundle"); - }); - if (statsMessages.hasMessages()) { - Console.stdout.write("Error recording package list:\n" + - statsMessages.formatMessages()); - // ... but continue; - } - - var bundler = require(path.join(__dirname, 'bundler.js')); - var bundleResult = bundler.bundle({ - outputPath: bundlePath, - buildOptions: { - minify: ! options.debug, - // XXX is this a good idea, or should linux be the default since - // that's where most people are deploying - // default? i guess the problem with using DEPLOY_ARCH as default - // is then 'meteor bundle' with no args fails if you have any local - // packages with binary npm dependencies - serverArch: bundleArch - } - }); - if (bundleResult.errors) { - Console.stderr.write("Errors prevented bundling:\n"); - Console.stderr.write(bundleResult.errors.formatMessages()); - return 1; - } - - if (!options['directory']) { - try { - files.createTarball(path.join(buildDir, 'bundle'), outputPath); - } catch (err) { - console.log(JSON.stringify(err)); - Console.stderr.write("Couldn't create tarball\n"); - } - } - files.rm_recursive(buildDir); -}); +}; /////////////////////////////////////////////////////////////////////////////// // mongo From 182b80734cfe1c08d13580fdef2e6d3e2827f508 Mon Sep 17 00:00:00 2001 From: Slava Kim Date: Wed, 24 Sep 2014 11:56:52 -0700 Subject: [PATCH 12/29] Always print a warning when running on a remote device the new warning message gives user the exact ip address they can use --- tools/commands.js | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/tools/commands.js b/tools/commands.js index 9586a92622..d7fce0e778 100644 --- a/tools/commands.js +++ b/tools/commands.js @@ -2,6 +2,7 @@ var main = require('./main.js'); var path = require('path'); var _ = require('underscore'); var fs = require('fs'); +var ip = require('ip'); var files = require('./files.js'); var deploy = require('./deploy.js'); var buildmessage = require('./buildmessage.js'); @@ -223,15 +224,20 @@ main.registerCommand({ options.httpProxyPort = options['http-proxy-port']; - // If we are targeting the remote devices + // If we are targeting the remote devices, warn about ports and same network if (_.intersection(options.args, ['ios-device', 'android-device']).length) { cordova.verboseLog('A run on a device requested'); - // ... and if you didn't specify your ip address as host, print a warning - if (parsedMobileHostPort.host === DEFAULT_BUILD_HOST) - Console.stderr.write( - "WARN: You are testing your app on a remote device but your host option\n" + - "WARN: is set to 'localhost'. Perhaps you want to change it to your local\n" + - "WARN: network's IP address with the -p or --mobile-port option?\n"); + Console.stderr.write([ +"WARNING: You are testing your app on a remote device.", +" For the mobile app to be able to connect to the local server, make", +" sure your device is on the same network, and that the network", +" configuration allows clients to talk to each other", +" (no client isolation).", +"", +" You can pass the host and the port in -p or --mobile-port argument.", +" For example: --mobile-port " + + ip.address() + ":" + parsedMobileHostPort.port + "\n\n" +].join("\n")); } // Always bundle for the browser by default. From 6f06298dbb408b57759e589f416c1264f45b9778 Mon Sep 17 00:00:00 2001 From: Slava Kim Date: Wed, 24 Sep 2014 12:02:34 -0700 Subject: [PATCH 13/29] Put 'ip' into dev_bundle --- meteor | 2 +- scripts/dev-bundle-package.json | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/meteor b/meteor index c4edf115f4..04cf25173b 100755 --- a/meteor +++ b/meteor @@ -1,6 +1,6 @@ #!/bin/bash -BUNDLE_VERSION=0.3.55 +BUNDLE_VERSION=0.3.56 # OS Check. Put here because here is where we download the precompiled # bundles that are arch specific. diff --git a/scripts/dev-bundle-package.json b/scripts/dev-bundle-package.json index 390d0b1961..4b8a4b5955 100644 --- a/scripts/dev-bundle-package.json +++ b/scripts/dev-bundle-package.json @@ -7,6 +7,7 @@ "chalk": "0.5.1", "underscore": "1.5.2", "source-map-support": "0.2.5", - "semver": "2.2.1" + "semver": "2.2.1", + "ip": "0.3.2" } } From d02c7c9759d371ebdfa9f5f356f01fb5f7eea77a Mon Sep 17 00:00:00 2001 From: Slava Kim Date: Wed, 24 Sep 2014 12:05:18 -0700 Subject: [PATCH 14/29] Add a license for ip npm module --- LICENSE.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/LICENSE.txt b/LICENSE.txt index 4c09e63af0..06169cc68d 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1058,6 +1058,13 @@ This product includes software developed at The Apache Software Foundation (http://www.apache.org/). +---------- +ip: https://github.com/indutny/node-ip +---------- + +Copyright Fedor Indutny, 2012 + + ====================== Eclipse Public License From 6faacb7fa34c75b53a7cf101cd2dcc2daa8bfd9b Mon Sep 17 00:00:00 2001 From: Slava Kim Date: Wed, 24 Sep 2014 14:58:47 -0700 Subject: [PATCH 15/29] Cut off scary logs of iOS emulator Here is what we are cutting off with this commit: Multi-tasking -> Device: YES, App: YES Unlimited access to network resources Started backup to iCloud! Please be careful. Your application might rejected by Apple if For more information please read "iOS Data You could find it at the following address ... [CDVTimer][file] 1.550019ms [CDVTimer][statusbar] 91.206014ms [CDVTimer][TotalPluginStartup] 93.596995ms Resetting plugins due to page load. Finished load of: ... No new versions saved to disk. Starting the server on port 29821 Setting document root: n Support/iPhone 9-FEA4-4A74-8EDE-2D443B905679/leaderboard.app/www/application HTTPServer: Started HTTP server on port 29821 Started httpd on port 29821 addresses: { "en0/ipv4" = "192.168.2.223"; "en0/ipv6" = "fe80::1610:9fff:fee5:105"; "lo0/ipv4" = "127.0.0.1"; "lo0/ipv6" = "fe80::1"; "vboxnet0/ipv4" = "192.168.50.1"; } Resetting plugins due to page load. Finished load of: http://192.168.2.223:29821/ These logs are somewhat useful (not all of them) but only in case of something going wrong. So they are staying here for the verbose mode. --- tools/commands-cordova.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tools/commands-cordova.js b/tools/commands-cordova.js index abed0e8129..947460703a 100644 --- a/tools/commands-cordova.js +++ b/tools/commands-cordova.js @@ -860,11 +860,24 @@ var execCordovaOnPlatform = function (localPath, platformName, options) { }); }; + // In case of verboseness don't skip any logs. Otherwise skip all the scary + // stuff that gets printed before the app load. + var appLogsStarted = false || verboseness; var iosMapper = function (line) { if (line.match(/^[0-9]+-[0-9]+-[0-9].*/)) { // if the line starts with the date, we remove the prefix line = line.replace(/^\S+\s\S+\s\S+\s/, ''); } + + var finishedRegexp = + /Finished load of: http:\/\/[0-9]+.[0-9]+.[0-9]+.[0-9]+:[0-9]+/g; + + if (finishedRegexp.test(line)) + appLogsStarted = true; + + if (! appLogsStarted) + return null; + return Log.format(Log.objFromText(line, { program: 'ios' }), { metaColor: 'cyan', color: true From 9fc5b15b2adaccd2e5d1708057af5395792e5088 Mon Sep 17 00:00:00 2001 From: Slava Kim Date: Wed, 24 Sep 2014 15:42:53 -0700 Subject: [PATCH 16/29] Suppress debug logs from meteor hcp components --- packages/autoupdate/autoupdate_cordova.js | 15 ++++++++------- tools/client/meteor_cordova_loader.js | 15 ++++++++------- tools/commands-cordova.js | 15 +++++++++++++++ 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/packages/autoupdate/autoupdate_cordova.js b/packages/autoupdate/autoupdate_cordova.js index d29dee3546..a649236ed1 100644 --- a/packages/autoupdate/autoupdate_cordova.js +++ b/packages/autoupdate/autoupdate_cordova.js @@ -1,3 +1,4 @@ +var DEBUG_TAG = 'METEOR CORDOVA DEBUG '; var autoupdateVersionCordova = __meteor_runtime_config__.autoupdateVersionCordova || "unknown"; // The collection of acceptable client versions. @@ -35,8 +36,8 @@ var writeFile = function (directoryPath, fileName, content, cb) { }; var restartServer = function (location) { - console.log('restartserver with location ' + location); - var fail = function (err) { console.log('something failed: ' + err.message) }; + console.log(DEBUG_TAG + 'restartserver with location ' + location); + var fail = function (err) { console.log(DEBUG_TAG + 'something failed: ' + err.message) }; var httpd = cordova && cordova.plugins && cordova.plugins.CorHttpd; if (! httpd) { @@ -86,7 +87,7 @@ var onNewVersion = function () { HTTP.get(urlPrefix + '/manifest.json', function (err, res) { if (err || ! res.data) { - console.log('failed to download the manifest ' + (err && err.message) + ' ' + (res && res.content)); + console.log(DEBUG_TAG + 'failed to download the manifest ' + (err && err.message) + ' ' + (res && res.content)); return; } @@ -110,7 +111,7 @@ var onNewVersion = function () { function (err) { if (err) { - console.log("Failed to write manifest.json"); + console.log(DEBUG_TAG + "Failed to write manifest.json"); // XXX do something smarter? return; } @@ -120,7 +121,7 @@ var onNewVersion = function () { writeFile(localPathPrefix, 'version', version, function (err) { if (err) { - console.log("Failed to write version"); + console.log(DEBUG_TAG + "Failed to write version"); return; } @@ -155,8 +156,8 @@ var onNewVersion = function () { if (tries++ < 5) { tryDownload(); } else { - console.log('fail source: ', error.source); - console.log('fail target: ', error.target); + console.log(DEBUG_TAG + 'fail source: ', error.source); + console.log(DEBUG_TAG + 'fail target: ', error.target); } }); }; diff --git a/tools/client/meteor_cordova_loader.js b/tools/client/meteor_cordova_loader.js index 39052fcace..f90278135e 100644 --- a/tools/client/meteor_cordova_loader.js +++ b/tools/client/meteor_cordova_loader.js @@ -7,6 +7,7 @@ */ (function () { + var DEBUG_TAG = 'METEOR CORDOVA DEBUG '; var readFile = function (url, cb) { window.resolveLocalFileSystemURL(url, function (fileEntry) { @@ -54,9 +55,9 @@ var retry = function () { loadTries++; if (loadTries > 10) { - console.log('Giving up on starting the server.'); + console.log(DEBUG_TAG + 'Giving up on starting the server.'); } else { - console.log('Retrying to to start the server.'); + console.log(DEBUG_TAG + 'Retrying to to start the server.'); loadFromLocation(location); } }; @@ -66,7 +67,7 @@ // if server is already running, stop it and retry httpd.stopServer(retry, retry); } else { - console.log('Starting the server on port ' + port); + console.log(DEBUG_TAG + 'Starting the server on port ' + port); httpd.startServer({ 'www_root' : location, 'port' : port, @@ -91,10 +92,10 @@ // no error is passed, then we simply do not have any new versions. var fallback = function (err) { if (err) { - console.log('Couldn\'t load from the manifest, ' + + console.log(DEBUG_TAG + 'Couldn\'t load from the manifest, ' + 'falling back to the bundled assets.'); } else { - console.log('No new versions saved to disk.'); + console.log(DEBUG_TAG + 'No new versions saved to disk.'); } loadFromLocation('application'); @@ -162,10 +163,10 @@ // around on disk removeDirectory(localPathPrefix + name + '/', function (err) { if (err) { - console.log('Failed to remove an old cache folder ' + console.log(DEBUG_TAG + 'Failed to remove an old cache folder ' + name + ':' + err.message); } else { - console.log('Successfully removed an old cache folder ' + name); + console.log(DEBUG_TAG + 'Successfully removed an old cache folder ' + name); } }); }); diff --git a/tools/commands-cordova.js b/tools/commands-cordova.js index 947460703a..0b54e96c8d 100644 --- a/tools/commands-cordova.js +++ b/tools/commands-cordova.js @@ -838,6 +838,10 @@ var execCordovaOnPlatform = function (localPath, platformName, options) { return null; } + // Skip the debug output produced by Meteor Core components. + if (/^METEOR CORDOVA DEBUG /.test(line) && ! verboseness) + return null; + // filename.js?hashsha1: Line 123 : message goes here var parsedLine = line.match(/^([^?]*)(\?[a-zA-Z0-9]+)?: Line (\d+) : (.*)$/); @@ -878,6 +882,17 @@ var execCordovaOnPlatform = function (localPath, platformName, options) { if (! appLogsStarted) return null; + // Skip the success messages from File Transfer. There are a lot of them on + // Hot-Code Push, but we are interested only in failures. + if (/File Transfer Finished with response code 200/.test(line) + && ! verboseness) { + return null; + } + + // Skip the debug output produced by Meteor Core components. + if (/^METEOR CORDOVA DEBUG /.test(line) && ! verboseness) + return null; + return Log.format(Log.objFromText(line, { program: 'ios' }), { metaColor: 'cyan', color: true From 233d07c017b4e198d2062075fc32e19babe05ec3 Mon Sep 17 00:00:00 2001 From: Slava Kim Date: Wed, 24 Sep 2014 15:46:09 -0700 Subject: [PATCH 17/29] Refactor and skip HTTPD Debug logs --- tools/commands-cordova.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tools/commands-cordova.js b/tools/commands-cordova.js index 0b54e96c8d..e605cf214c 100644 --- a/tools/commands-cordova.js +++ b/tools/commands-cordova.js @@ -824,6 +824,11 @@ var execCordovaOnPlatform = function (localPath, platformName, options) { var Log = getLoadedPackages().logging.Log; + var isDebugOutput = function (line) { + // Skip the debug output produced by Meteor Core components. + return /^METEOR CORDOVA DEBUG /.test(line) || /^HTTPD DEBUG /.test(line); + }; + var androidMapper = function (line) { // remove the annoying prefix line = line.replace(/^.\/CordovaLog\(\s*\d+\s*\):\s+/, ''); @@ -838,8 +843,7 @@ var execCordovaOnPlatform = function (localPath, platformName, options) { return null; } - // Skip the debug output produced by Meteor Core components. - if (/^METEOR CORDOVA DEBUG /.test(line) && ! verboseness) + if (isDebugOutput(line) && ! verboseness) return null; // filename.js?hashsha1: Line 123 : message goes here @@ -889,8 +893,7 @@ var execCordovaOnPlatform = function (localPath, platformName, options) { return null; } - // Skip the debug output produced by Meteor Core components. - if (/^METEOR CORDOVA DEBUG /.test(line) && ! verboseness) + if (isDebugOutput(line) && ! verboseness) return null; return Log.format(Log.objFromText(line, { program: 'ios' }), { From 5beb6ef982772948aa526116665dcf90f77d50d0 Mon Sep 17 00:00:00 2001 From: Slava Kim Date: Wed, 24 Sep 2014 23:37:20 -0700 Subject: [PATCH 18/29] Correctly reinstall tarball-based Cordova plugins if they change between builds Ideally we would also restart the running process and restart the emulator with a new app. Unfortunately it is not as easy right now. --- tools/commands-cordova.js | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/tools/commands-cordova.js b/tools/commands-cordova.js index e605cf214c..22dd1232df 100644 --- a/tools/commands-cordova.js +++ b/tools/commands-cordova.js @@ -402,11 +402,18 @@ var installPlugin = function (cordovaPath, name, version, settings) { } }; -var uninstallPlugin = function (cordovaPath, name) { +var uninstallPlugin = function (cordovaPath, name, isFromTarballUrl) { verboseLog('Uninstalling a plugin', name); try { execFileSyncOrThrow(localCordova, ['plugin', 'rm', name], { cwd: cordovaPath }); + + if (isFromTarballUrl) { + // also remove from tarball-url-based plugins lock + var lock = getTarballPluginsLock(cordovaPath); + delete lock[name]; + writeTarballPluginsLock(cordovaPath, lock); + } } catch (err) { // Catch when an uninstall fails, because it might just be a dependency // issue. For example, plugin A depends on plugin B and we try to remove @@ -532,9 +539,6 @@ var ensureCordovaPlugins = function (localPath, options) { 'utf8'); } - // XXX compare the latest used sha's with the currently required sha's for - // plugins fetched from a github/tarball url. - var installedPlugins = getInstalledPlugins(cordovaPath); // Due to the dependency structure of Cordova plugins, it is impossible to @@ -556,8 +560,7 @@ var ensureCordovaPlugins = function (localPath, options) { // XXX there is a hack here that never updates a package if you are // trying to install it from a URL, because we can't determine if // it's the right version or not - if (! _.has(installedPlugins, name) || - (installedPlugins[name] !== version && ! utils.isUrlWithSha(version))) { + if (! _.has(installedPlugins, name) || installedPlugins[name] !== version) { // The version of the plugin has changed, or we do not contain a plugin. shouldReinstallPlugins = true; } @@ -578,8 +581,8 @@ var ensureCordovaPlugins = function (localPath, options) { var uninstallAllPlugins = function () { installedPlugins = getInstalledPlugins(cordovaPath); while (_.size(installedPlugins)) { - _.each(_.keys(installedPlugins), function (name) { - uninstallPlugin(cordovaPath, name); + _.each(installedPlugins, function (version, name) { + uninstallPlugin(cordovaPath, name, utils.isUrlWithSha(version)); }); installedPlugins = getInstalledPlugins(cordovaPath); } From 448ea0ea7fecff98916a95ae8fd33b55eead3f25 Mon Sep 17 00:00:00 2001 From: Slava Kim Date: Wed, 24 Sep 2014 23:38:18 -0700 Subject: [PATCH 19/29] Fix the HCP on a route (like /something) problem on iOS addresses #2632 partially (only iOS) --- packages/meteor-platform/package.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/meteor-platform/package.js b/packages/meteor-platform/package.js index d1594b6d9c..df944b8927 100644 --- a/packages/meteor-platform/package.js +++ b/packages/meteor-platform/package.js @@ -68,5 +68,5 @@ Package.on_use(function(api) { Cordova.depends({ 'org.apache.cordova.device': '0.2.11', - 'com.rjfun.cordova.httpd': 'https://github.com/meteor/cordova-httpd/tarball/0f1c8bc17e567c57a68427b0fe5e692ab6568d7f' + 'com.rjfun.cordova.httpd': 'https://github.com/meteor/cordova-httpd/tarball/f68bcb43be30878823718bcd01bd6d97561eb337' }); From d68aa09c11bc3d846e3754244d8af761736b210e Mon Sep 17 00:00:00 2001 From: Slava Kim Date: Thu, 25 Sep 2014 21:01:40 -0700 Subject: [PATCH 20/29] WIP --- packages/autoupdate/autoupdate_cordova.js | 23 ++------------- packages/meteor-platform/package.js | 2 +- tools/client/meteor_cordova_loader.js | 36 ++++++----------------- 3 files changed, 13 insertions(+), 48 deletions(-) diff --git a/packages/autoupdate/autoupdate_cordova.js b/packages/autoupdate/autoupdate_cordova.js index a649236ed1..9ae7359fc6 100644 --- a/packages/autoupdate/autoupdate_cordova.js +++ b/packages/autoupdate/autoupdate_cordova.js @@ -38,23 +38,16 @@ var writeFile = function (directoryPath, fileName, content, cb) { var restartServer = function (location) { console.log(DEBUG_TAG + 'restartserver with location ' + location); var fail = function (err) { console.log(DEBUG_TAG + 'something failed: ' + err.message) }; - var httpd = cordova && cordova.plugins && cordova.plugins.CorHttpd; + var httpd = cordova && cordova.plugins && cordova.plugins.CordovaUpdate; if (! httpd) { fail(new Error('no httpd')); return; } - var startServer = function (cordovajsRoot, prevUrl) { - var port; - if (prevUrl) { - var parts = prevUrl.split(':'); - if (parts.length) - port = parseInt(parts[parts.length - 1], 10); - } + var startServer = function (cordovajsRoot) { httpd.startServer({ 'www_root' : location, - 'port' : port, 'cordovajs_root': cordovajsRoot }, function (url) { Package.reload.Reload._reload(); @@ -62,17 +55,7 @@ var restartServer = function (location) { }; httpd.getCordovajsRoot(function (cordovajsRoot) { - httpd.getURL(function (url) { - if (url.length > 0) { - // already have a server running, stop it - httpd.stopServer(function () { - startServer(cordovajsRoot, url); - }, fail); - } else { - // just start a server - startServer(cordovajsRoot); - } - }, fail); + startServer(cordovajsRoot); }, fail); }; diff --git a/packages/meteor-platform/package.js b/packages/meteor-platform/package.js index df944b8927..c9c6014317 100644 --- a/packages/meteor-platform/package.js +++ b/packages/meteor-platform/package.js @@ -68,5 +68,5 @@ Package.on_use(function(api) { Cordova.depends({ 'org.apache.cordova.device': '0.2.11', - 'com.rjfun.cordova.httpd': 'https://github.com/meteor/cordova-httpd/tarball/f68bcb43be30878823718bcd01bd6d97561eb337' + 'com.meteor.cordova-update': 'https://github.com/meteor/com.meteor.cordova-update/tarball/9eddfcc144e8eb523c2b8d317f8837346435b1a6' }); diff --git a/tools/client/meteor_cordova_loader.js b/tools/client/meteor_cordova_loader.js index f90278135e..0fae5e05bf 100644 --- a/tools/client/meteor_cordova_loader.js +++ b/tools/client/meteor_cordova_loader.js @@ -42,15 +42,10 @@ return p.slice(1); }; - var randomInt = function (min, max) { - return Math.floor(Math.random() * (max - min + 1)) + min; - }; - var loadTries = 0; var loadFromLocation = function (location) { var cordovaRoot = decodeURI(window.location.href).replace(/\/index.html$/, '/').replace(/^file:\/\/?/, ''); - var httpd = cordova && cordova.plugins && cordova.plugins.CorHttpd; - var port = randomInt(10000, 50000); + var httpd = cordova && cordova.plugins && cordova.plugins.CordovaUpdate; var retry = function () { loadTries++; @@ -62,27 +57,14 @@ } }; - httpd.getURL(function(url){ - if (url.length > 0) { - // if server is already running, stop it and retry - httpd.stopServer(retry, retry); - } else { - console.log(DEBUG_TAG + 'Starting the server on port ' + port); - httpd.startServer({ - 'www_root' : location, - 'port' : port, - 'cordovajs_root': cordovaRoot - }, function (url) { - // go to the new proxy url - window.location = url; - }, function (error) { - // failed to start a server, is port already in use? - retry(); - }); - } - - }, function () { - // failed to call to server: retry + httpd.startServing({ + 'www_root' : location, + 'cordovajs_root': cordovaRoot + }, function (url) { + // go to the new proxy url + window.location = url; + }, function (error) { + // failed to start a server, is port already in use? retry(); }); }; From b392d7b7e025e21b43627bb7718b674cca6cddb3 Mon Sep 17 00:00:00 2001 From: Justin SB Date: Thu, 25 Sep 2014 21:34:17 -0700 Subject: [PATCH 21/29] startServing -> startServer --- tools/client/meteor_cordova_loader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/client/meteor_cordova_loader.js b/tools/client/meteor_cordova_loader.js index 0fae5e05bf..f9c73c8a46 100644 --- a/tools/client/meteor_cordova_loader.js +++ b/tools/client/meteor_cordova_loader.js @@ -57,7 +57,7 @@ } }; - httpd.startServing({ + httpd.startServer({ 'www_root' : location, 'cordovajs_root': cordovaRoot }, function (url) { From 57e5cae447a77ffa74cb908aa09e3b9d670cef92 Mon Sep 17 00:00:00 2001 From: Slava Kim Date: Thu, 25 Sep 2014 22:44:09 -0700 Subject: [PATCH 22/29] Use the version of CordovaUpdate that seems to work on iOS --- packages/meteor-platform/package.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/meteor-platform/package.js b/packages/meteor-platform/package.js index c9c6014317..ed732e68cb 100644 --- a/packages/meteor-platform/package.js +++ b/packages/meteor-platform/package.js @@ -68,5 +68,5 @@ Package.on_use(function(api) { Cordova.depends({ 'org.apache.cordova.device': '0.2.11', - 'com.meteor.cordova-update': 'https://github.com/meteor/com.meteor.cordova-update/tarball/9eddfcc144e8eb523c2b8d317f8837346435b1a6' + 'com.meteor.cordova-update': 'https://github.com/meteor/com.meteor.cordova-update/tarball/587af6eb67f8f3994309e17a90e8694b93ad47fe' }); From 2ada859d5e2236c7b618ac4eace9715a0a4758d5 Mon Sep 17 00:00:00 2001 From: Justin SB Date: Fri, 26 Sep 2014 08:23:45 -0700 Subject: [PATCH 23/29] More logging in meteor_cordova_loader --- tools/client/meteor_cordova_loader.js | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/tools/client/meteor_cordova_loader.js b/tools/client/meteor_cordova_loader.js index f9c73c8a46..4c54901a67 100644 --- a/tools/client/meteor_cordova_loader.js +++ b/tools/client/meteor_cordova_loader.js @@ -8,6 +8,9 @@ (function () { var DEBUG_TAG = 'METEOR CORDOVA DEBUG '; + var log = function (msg) { + console.log(DEBUG_TAG + msg); + }; var readFile = function (url, cb) { window.resolveLocalFileSystemURL(url, function (fileEntry) { @@ -21,12 +24,12 @@ reader.readAsText(file); }; var fail = function (evt) { - cb(new Error("Failed to load entry"), null); + cb(new Error("Failed to load entry: " + url), null); }; fileEntry.file(success, fail); }, // error callback - function (err) { cb(new Error("Failed to load entry"), null); } + function (err) { cb(new Error("Failed to resolve entry: " + url), null); } ); }; @@ -50,9 +53,11 @@ var retry = function () { loadTries++; if (loadTries > 10) { - console.log(DEBUG_TAG + 'Giving up on starting the server.'); + // XXX: If this means the app fails, we should probably do exponential backoff + // or at least show a message + log('Failed to start the server (too many retries)'); } else { - console.log(DEBUG_TAG + 'Retrying to to start the server.'); + log('Starting the server (retry #' + loadTries + ')'); loadFromLocation(location); } }; @@ -65,6 +70,7 @@ window.location = url; }, function (error) { // failed to start a server, is port already in use? + log("Failed to start the server: " + error); retry(); }); }; @@ -74,10 +80,9 @@ // no error is passed, then we simply do not have any new versions. var fallback = function (err) { if (err) { - console.log(DEBUG_TAG + 'Couldn\'t load from the manifest, ' + - 'falling back to the bundled assets.'); + log("Couldn't load from the manifest, falling back to the bundled assets."); } else { - console.log(DEBUG_TAG + 'No new versions saved to disk.'); + log('No new versions saved to disk.'); } loadFromLocation('application'); @@ -124,6 +129,7 @@ readFile(localPathPrefix + 'version', function (err, version) { if (err) { + log("Error reading version file " + err); fallback(); return; } @@ -145,10 +151,10 @@ // around on disk removeDirectory(localPathPrefix + name + '/', function (err) { if (err) { - console.log(DEBUG_TAG + 'Failed to remove an old cache folder ' - + name + ':' + err.message); + log('Failed to remove an old cache folder ' + + name + ':' + err.message); } else { - console.log(DEBUG_TAG + 'Successfully removed an old cache folder ' + name); + log('Successfully removed an old cache folder ' + name); } }); }); From 4de9718c9a07b233113f87a8cb07fcb390b47704 Mon Sep 17 00:00:00 2001 From: Justin SB Date: Fri, 26 Sep 2014 08:33:22 -0700 Subject: [PATCH 24/29] More logging in autoupdate_cordova.js --- packages/autoupdate/autoupdate_cordova.js | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/packages/autoupdate/autoupdate_cordova.js b/packages/autoupdate/autoupdate_cordova.js index 9ae7359fc6..9ee9135146 100644 --- a/packages/autoupdate/autoupdate_cordova.js +++ b/packages/autoupdate/autoupdate_cordova.js @@ -1,4 +1,8 @@ var DEBUG_TAG = 'METEOR CORDOVA DEBUG '; +var log = function (msg) { + console.log(DEBUG_TAG + msg); +}; + var autoupdateVersionCordova = __meteor_runtime_config__.autoupdateVersionCordova || "unknown"; // The collection of acceptable client versions. @@ -36,8 +40,8 @@ var writeFile = function (directoryPath, fileName, content, cb) { }; var restartServer = function (location) { - console.log(DEBUG_TAG + 'restartserver with location ' + location); - var fail = function (err) { console.log(DEBUG_TAG + 'something failed: ' + err.message) }; + log('restartServer with location ' + location); + var fail = function (err) { log("Unexpected error in restartServer: " + err.message) }; var httpd = cordova && cordova.plugins && cordova.plugins.CordovaUpdate; if (! httpd) { @@ -70,7 +74,7 @@ var onNewVersion = function () { HTTP.get(urlPrefix + '/manifest.json', function (err, res) { if (err || ! res.data) { - console.log(DEBUG_TAG + 'failed to download the manifest ' + (err && err.message) + ' ' + (res && res.content)); + log('Failed to download the manifest ' + (err && err.message) + ' ' + (res && res.content)); return; } @@ -94,7 +98,7 @@ var onNewVersion = function () { function (err) { if (err) { - console.log(DEBUG_TAG + "Failed to write manifest.json"); + log("Failed to write manifest.json: " + err); // XXX do something smarter? return; } @@ -104,7 +108,7 @@ var onNewVersion = function () { writeFile(localPathPrefix, 'version', version, function (err) { if (err) { - console.log(DEBUG_TAG + "Failed to write version"); + log("Failed to write version: " + err); return; } @@ -137,10 +141,10 @@ var onNewVersion = function () { }, function (err) { // It failed, try again if we have tried less than 5 times. if (tries++ < 5) { + log("Download error, will retry (#" + tries + "): " + uri); tryDownload(); } else { - console.log(DEBUG_TAG + 'fail source: ', error.source); - console.log(DEBUG_TAG + 'fail target: ', error.target); + log('Download failed: ' + err + ", source=" + err.source + ", target=" + err.target); } }); }; @@ -158,8 +162,8 @@ var failures = 0; Autoupdate._retrySubscription = function () { Meteor.subscribe("meteor_autoupdate_clientVersions", { - onError: function (error) { - Meteor._debug("autoupdate subscription failed:", error); + onError: function (err) { + Meteor._debug("autoupdate subscription failed:", err); failures++; retry.retryLater(failures, function () { // Just retry making the subscription, don't reload the whole From 977aef2488b400dc2ad004ed534b64df8fc5135c Mon Sep 17 00:00:00 2001 From: Justin SB Date: Fri, 26 Sep 2014 08:33:37 -0700 Subject: [PATCH 25/29] Pass the err to fallback, which expects it --- tools/client/meteor_cordova_loader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/client/meteor_cordova_loader.js b/tools/client/meteor_cordova_loader.js index 4c54901a67..a8ba8f322c 100644 --- a/tools/client/meteor_cordova_loader.js +++ b/tools/client/meteor_cordova_loader.js @@ -130,7 +130,7 @@ function (err, version) { if (err) { log("Error reading version file " + err); - fallback(); + fallback(err); return; } From c7b6a6c4b732a1a2f353b8fc36f2726cfe63d382 Mon Sep 17 00:00:00 2001 From: Justin SB Date: Fri, 26 Sep 2014 08:35:28 -0700 Subject: [PATCH 26/29] Include js filename in cordova log messages --- packages/autoupdate/autoupdate_cordova.js | 2 +- tools/client/meteor_cordova_loader.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/autoupdate/autoupdate_cordova.js b/packages/autoupdate/autoupdate_cordova.js index 9ee9135146..31bc4b2fc6 100644 --- a/packages/autoupdate/autoupdate_cordova.js +++ b/packages/autoupdate/autoupdate_cordova.js @@ -1,4 +1,4 @@ -var DEBUG_TAG = 'METEOR CORDOVA DEBUG '; +var DEBUG_TAG = 'METEOR CORDOVA DEBUG (autoupdate_cordova.js) '; var log = function (msg) { console.log(DEBUG_TAG + msg); }; diff --git a/tools/client/meteor_cordova_loader.js b/tools/client/meteor_cordova_loader.js index a8ba8f322c..487b8cbe69 100644 --- a/tools/client/meteor_cordova_loader.js +++ b/tools/client/meteor_cordova_loader.js @@ -7,7 +7,7 @@ */ (function () { - var DEBUG_TAG = 'METEOR CORDOVA DEBUG '; + var DEBUG_TAG = 'METEOR CORDOVA DEBUG (meteor_cordova_loader.js) '; var log = function (msg) { console.log(DEBUG_TAG + msg); }; From 2f34fd5201a89cac689b60512f5df13966173e4b Mon Sep 17 00:00:00 2001 From: Justin SB Date: Fri, 26 Sep 2014 08:49:37 -0700 Subject: [PATCH 27/29] Log the url we redirect to --- tools/client/meteor_cordova_loader.js | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/client/meteor_cordova_loader.js b/tools/client/meteor_cordova_loader.js index 487b8cbe69..e3f15f65c4 100644 --- a/tools/client/meteor_cordova_loader.js +++ b/tools/client/meteor_cordova_loader.js @@ -67,6 +67,7 @@ 'cordovajs_root': cordovaRoot }, function (url) { // go to the new proxy url + log("Loading from url: " + url); window.location = url; }, function (error) { // failed to start a server, is port already in use? From 9600d92ca7ebecdf05577d692c1e4fe6effc2fb5 Mon Sep 17 00:00:00 2001 From: Slava Kim Date: Fri, 26 Sep 2014 17:21:48 -0700 Subject: [PATCH 28/29] Limit the number of concurrent downloads Doesn't actually help! --- packages/autoupdate/autoupdate_cordova.js | 46 +++++++++++++++-------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/packages/autoupdate/autoupdate_cordova.js b/packages/autoupdate/autoupdate_cordova.js index 9ae7359fc6..3af120e6b0 100644 --- a/packages/autoupdate/autoupdate_cordova.js +++ b/packages/autoupdate/autoupdate_cordova.js @@ -1,4 +1,12 @@ var DEBUG_TAG = 'METEOR CORDOVA DEBUG '; + +// This constant was picked by testing on iOS 7.1 +// We limit the number of concurrent downloads because iOS gets angry on the +// application when a certain limit is exceeded and starts timing-out the +// connections in 1-2 minutes which makes the whole HCP really slow. +var MAX_NUM_CONCURRENT_DOWNLOADS = 15; +var MAX_RETRY_COUNT = 5; + var autoupdateVersionCordova = __meteor_runtime_config__.autoupdateVersionCordova || "unknown"; // The collection of acceptable client versions. @@ -81,14 +89,19 @@ var onNewVersion = function () { manifest.push({ url: '/index.html?' + Random.id() }); - var downloads = 0; - _.each(manifest, function (item) { - if (item.url) downloads++; - }); - var versionPrefix = localPathPrefix + version; - var afterAllFilesDownloaded = _.after(downloads, function () { + var queue = []; + _.each(manifest, function (item) { + if (! item.url) return; + + var url = item.url; + url = url.replace(/\?.+$/, ''); + + queue.push(url); + }); + + var afterAllFilesDownloaded = _.after(queue.length, function () { writeFile(versionPrefix, 'manifest.json', JSON.stringify(program, undefined, 2), function (err) { @@ -118,12 +131,8 @@ var onNewVersion = function () { }); }); - _.each(manifest, function (item) { - if (! item.url) return; - - var url = item.url; - url = url.replace(/\?.+$/, ''); - + var dowloadUrl = function (url) { + console.log(DEBUG_TAG + "start dowloading " + url); // Add a cache buster to ensure that we don't cache an old asset. var uri = encodeURI(urlPrefix + url + '?' + Random.id()); @@ -132,20 +141,27 @@ var onNewVersion = function () { var tryDownload = function () { ft.download(uri, versionPrefix + url, function (entry) { if (entry) { + console.log(DEBUG_TAG + "done dowloading " + url); + // start downloading next queued url + if (queue.length) + dowloadUrl(queue.shift()); afterAllFilesDownloaded(); } }, function (err) { // It failed, try again if we have tried less than 5 times. - if (tries++ < 5) { + if (tries++ < MAX_RETRY_COUNT) { tryDownload(); } else { - console.log(DEBUG_TAG + 'fail source: ', error.source); - console.log(DEBUG_TAG + 'fail target: ', error.target); + console.log(DEBUG_TAG + "failed dowloading " + url); } }); }; tryDownload(); + }; + + _.times(Math.min(MAX_NUM_CONCURRENT_DOWNLOADS, queue.length), function () { + dowloadUrl(queue.shift()); }); }); }; From d4ae3172d3c37d8c90d3e3a8678cc3a962674791 Mon Sep 17 00:00:00 2001 From: Slava Kim Date: Mon, 29 Sep 2014 12:24:02 -0700 Subject: [PATCH 29/29] Add a defer for files download on iOS surprising helps us to fight the iOS rate-limiting back! --- packages/autoupdate/autoupdate_cordova.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/autoupdate/autoupdate_cordova.js b/packages/autoupdate/autoupdate_cordova.js index 3af120e6b0..ec243d71e0 100644 --- a/packages/autoupdate/autoupdate_cordova.js +++ b/packages/autoupdate/autoupdate_cordova.js @@ -4,7 +4,7 @@ var DEBUG_TAG = 'METEOR CORDOVA DEBUG '; // We limit the number of concurrent downloads because iOS gets angry on the // application when a certain limit is exceeded and starts timing-out the // connections in 1-2 minutes which makes the whole HCP really slow. -var MAX_NUM_CONCURRENT_DOWNLOADS = 15; +var MAX_NUM_CONCURRENT_DOWNLOADS = 30; var MAX_RETRY_COUNT = 5; var autoupdateVersionCordova = __meteor_runtime_config__.autoupdateVersionCordova || "unknown"; @@ -161,7 +161,10 @@ var onNewVersion = function () { }; _.times(Math.min(MAX_NUM_CONCURRENT_DOWNLOADS, queue.length), function () { - dowloadUrl(queue.shift()); + var nextUrl = queue.shift(); + // XXX defer the next download so iOS doesn't rate limit us on concurrent + // downloads + Meteor.setTimeout(dowloadUrl.bind(null, nextUrl), 50); }); }); };