Merge remote-tracking branch 'origin/devel' into blaze-templates

This commit is contained in:
David Greenspan
2014-08-11 14:39:14 -07:00
29 changed files with 846 additions and 585 deletions

View File

@@ -30,19 +30,16 @@ var autoupdateVersionRefreshable =
// The collection of acceptable client versions.
ClientVersions = new Meteor.Collection("meteor_autoupdate_clientVersions");
ClientVersionsRefreshable =
new Meteor.Collection("meteor_autoupdate_clientVersions_refreshable");
Autoupdate = {};
Autoupdate.newClientAvailable = function () {
return !! ClientVersions.findOne(
{ current: true,
_id: {$ne: autoupdateVersion}
}) || !! ClientVersionsRefreshable.findOne(
{ current: true,
_id: {$ne: autoupdateVersionRefreshable}
});
return !! ClientVersions.findOne({
refreshable: false,
version: {$ne: autoupdateVersion} }) ||
!! ClientVersions.findOne({
refreshable: true,
version: {$ne: autoupdateVersionRefreshable} });
};
var knownToSupportCssOnLoad = false;
@@ -79,73 +76,71 @@ Autoupdate._retrySubscription = function () {
},
onReady: function () {
if (Package.reload) {
var handle = ClientVersions.find().observeChanges({
added: function (id, fields) {
var self = this;
if (id !== autoupdateVersion) {
if (handle) {
handle.stop();
Package.reload.Reload._reload();
var checkNewVersionDocument = function (id, fields) {
var self = this;
var isRefreshable = id === 'version-refreshable';
if (isRefreshable &&
fields.version !== autoupdateVersionRefreshable) {
autoupdateVersionRefreshable = fields.version;
// Switch out old css links for the new css links. Inspired by:
// https://github.com/guard/guard-livereload/blob/master/js/livereload.js#L710
var newCss = fields.assets.allCss;
var oldLinks = [];
_.each(document.getElementsByTagName('link'), function (link) {
if (link.className === '__meteor-css__') {
oldLinks.push(link);
}
}
}
});
});
ClientVersionsRefreshable.find().observeChanges({
added: function (id, fields) {
if (id !== autoupdateVersionRefreshable) {
autoupdateVersionRefreshable = id;
var waitUntilCssLoads = function (link, callback) {
var executeCallback = _.once(callback);
link.onload = function () {
knownToSupportCssOnLoad = true;
executeCallback();
};
if (! knownToSupportCssOnLoad) {
var id = Meteor.setInterval(function () {
if (link.sheet) {
executeCallback();
Meteor.clearInterval(id);
}
}, 50);
}
};
// Switch out old css links for the new css links. Inspired by:
// https://github.com/guard/guard-livereload/blob/master/js/livereload.js#L710
var newCss = fields.assets.allCss;
var oldLinks = [];
_.each(document.getElementsByTagName('link'), function (link) {
if (link.className === '__meteor-css__') {
oldLinks.push(link);
}
var attachStylesheetLink = function (newLink) {
var removeOldLinks = _.after(newCss.length, function () {
_.each(oldLinks, function (oldLink) {
oldLink.parentNode.removeChild(oldLink);
});
});
var waitUntilCssLoads = function (link, callback) {
var executeCallback = _.once(callback);
link.onload = function () {
knownToSupportCssOnLoad = true;
executeCallback();
};
if (! knownToSupportCssOnLoad) {
var id = Meteor.setInterval(function () {
if (link.sheet) {
executeCallback();
Meteor.clearInterval(id);
}
}, 50);
}
};
document.getElementsByTagName("head").item(0).appendChild(newLink);
var attachStylesheetLink = function (newLink) {
var removeOldLinks = _.after(newCss.length, function () {
_.each(oldLinks, function (oldLink) {
oldLink.parentNode.removeChild(oldLink);
});
});
document.getElementsByTagName("head").item(0).appendChild(newLink);
waitUntilCssLoads(newLink, function () {
Meteor.setTimeout(removeOldLinks, 200);
});
};
_.each(newCss, function (css) {
var newLink = document.createElement("link");
newLink.setAttribute("rel", "stylesheet");
newLink.setAttribute("type", "text/css");
newLink.setAttribute("class", "__meteor-css__");
newLink.setAttribute("href", css.url);
attachStylesheetLink(newLink);
waitUntilCssLoads(newLink, function () {
Meteor.setTimeout(removeOldLinks, 200);
});
}
};
_.each(newCss, function (css) {
var newLink = document.createElement("link");
newLink.setAttribute("rel", "stylesheet");
newLink.setAttribute("type", "text/css");
newLink.setAttribute("class", "__meteor-css__");
newLink.setAttribute("href", css.url);
attachStylesheetLink(newLink);
});
}
else if (! isRefreshable &&
fields.version !== autoupdateVersionRefreshable && handle) {
handle.stop();
Package.reload.Reload._reload();
}
};
var handle = ClientVersions.find().observeChanges({
added: checkNewVersionDocument,
changed: checkNewVersionDocument
});
}
}

View File

@@ -43,9 +43,6 @@ Autoupdate = {};
// The collection of acceptable client versions.
ClientVersions = new Meteor.Collection("meteor_autoupdate_clientVersions",
{ connection: null });
ClientVersionsRefreshable =
new Meteor.Collection("meteor_autoupdate_clientVersions_refreshable",
{ connection: null });
// The client hash includes __meteor_runtime_config__, so wait until
// all packages have loaded and have had a chance to populate the
@@ -61,9 +58,6 @@ var startupVersion = null;
// updateVersions can only be called after the server has fully loaded.
var updateVersions = function (shouldReloadClientProgram) {
syncQueue.runTask(function () {
var oldVersion = Autoupdate.autoupdateVersion;
var oldVersionRefreshable = Autoupdate.autoupdateVersionRefreshable;
// Step 1: load the current client program on the server and update the
// hash values in __meteor_runtime_config__.
if (shouldReloadClientProgram) {
@@ -90,25 +84,30 @@ var updateVersions = function (shouldReloadClientProgram) {
WebAppInternals.generateBoilerplate();
}
if (Autoupdate.autoupdateVersion !== oldVersion) {
if (oldVersion) {
ClientVersions.remove(oldVersion);
}
if (! ClientVersions.findOne({_id: "version"})) {
ClientVersions.insert({
_id: Autoupdate.autoupdateVersion,
current: true
_id: "version",
refreshable: false,
version: Autoupdate.autoupdateVersion,
});
} else {
ClientVersions.update("version", { $set: {
version: Autoupdate.autoupdateVersion,
}});
}
if (Autoupdate.autoupdateVersionRefreshable !== oldVersionRefreshable) {
if (oldVersionRefreshable) {
ClientVersionsRefreshable.remove(oldVersionRefreshable);
}
ClientVersionsRefreshable.insert({
_id: Autoupdate.autoupdateVersionRefreshable,
if (! ClientVersions.findOne({_id: "version-refreshable"})) {
ClientVersions.insert({
_id: "version-refreshable",
version: Autoupdate.autoupdateVersionRefreshable,
refreshable: true,
assets: WebAppInternals.refreshableAssets
});
} else {
ClientVersions.update("version-refreshable", { $set: {
version: Autoupdate.autoupdateVersionRefreshable,
assets: WebAppInternals.refreshableAssets
}});
}
});
};
@@ -125,7 +124,7 @@ Meteor.startup(function () {
Meteor.publish(
"meteor_autoupdate_clientVersions",
function () {
return [ ClientVersions.find(), ClientVersionsRefreshable.find() ];
return ClientVersions.find();
},
{is_auto: true}
);

View File

@@ -325,8 +325,8 @@ var exception = function (error) {
// XXX this may be the wrong place to do this, but it makes syntax errors in
// files loaded via unipackage.load have context.
if (error instanceof files.FancySyntaxError) {
error.message = "Syntax error: " + error.message + " at " +
error.file + ":" + error.line + ":" + error.column;
error = new Error("Syntax error: " + error.message + " at " +
error.file + ":" + error.line + ":" + error.column);
}
throw error;
}

View File

@@ -1648,8 +1648,6 @@ exports.bundle = function (options) {
var buildOptions = options.buildOptions || {};
var appDir = project.project.rootDir;
if (! release.usingRightReleaseForApp(appDir))
throw new Error("running wrong release for app?");
var serverArch = buildOptions.serverArch || archinfo.host();
var webArchs = buildOptions.webArchs || [ "web.browser" ];
@@ -1668,6 +1666,9 @@ exports.bundle = function (options) {
var messages = buildmessage.capture({
title: "building the application"
}, function () {
if (! release.usingRightReleaseForApp(appDir))
throw new Error("running wrong release for app?");
var packageLoader = project.project.getPackageLoader();
var downloaded = tropohouse.default.downloadMissingPackages(
project.project.dependencies, { serverArch: serverArch });

View File

@@ -105,6 +105,7 @@ _.extend(baseCatalog.BaseCatalog.prototype, {
// the inevitable rather than slowing down normal operations)
_recordOrRefresh: function (recordFinder) {
var self = this;
buildmessage.assertInCapture();
var record = recordFinder();
// If we cannot find it maybe refresh.
if (!record) {
@@ -124,6 +125,7 @@ _.extend(baseCatalog.BaseCatalog.prototype, {
// release track, or null if there is no such release track.
getReleaseTrack: function (name) {
var self = this;
buildmessage.assertInCapture();
self._requireInitialized();
return self._recordOrRefresh(function () {
return _.findWhere(self.releaseTracks, { name: name });
@@ -138,6 +140,7 @@ _.extend(baseCatalog.BaseCatalog.prototype, {
// serious refactoring.
getReleaseVersion: function (track, version, notInitialized) {
var self = this;
buildmessage.assertInCapture();
if (!notInitialized) self._requireInitialized();
return self._recordOrRefresh(function () {
return _.findWhere(self.releaseVersions,
@@ -186,6 +189,7 @@ _.extend(baseCatalog.BaseCatalog.prototype, {
// package, or null if there is no such package.
getPackage: function (name) {
var self = this;
buildmessage.assertInCapture();
self._requireInitialized();
return self._recordOrRefresh(function () {
return _.findWhere(self.packages, { name: name });
@@ -213,6 +217,7 @@ _.extend(baseCatalog.BaseCatalog.prototype, {
getVersion: function (name, version) {
var self = this;
self._requireInitialized();
buildmessage.assertInCapture();
var lookupVersion = function () {
return _.has(self.versions, name) &&
@@ -250,6 +255,7 @@ _.extend(baseCatalog.BaseCatalog.prototype, {
getLatestVersion: function (name) {
var self = this;
self._requireInitialized();
buildmessage.assertInCapture();
var versions = self.getSortedVersions(name);
if (versions.length === 0)
@@ -263,6 +269,7 @@ _.extend(baseCatalog.BaseCatalog.prototype, {
getBuildsForArches: function (name, version, arches) {
var self = this;
self._requireInitialized();
buildmessage.assertInCapture();
var versionInfo = self.getVersion(name, version);
if (! versionInfo)
@@ -298,6 +305,7 @@ _.extend(baseCatalog.BaseCatalog.prototype, {
getBuildWithPreciseBuildArchitectures: function (versionRecord,
buildArchitectures) {
var self = this;
buildmessage.assertInCapture();
self._requireInitialized();
return self._recordOrRefresh(function () {
@@ -310,6 +318,7 @@ _.extend(baseCatalog.BaseCatalog.prototype, {
getAllBuilds: function (name, version) {
var self = this;
self._requireInitialized();
buildmessage.assertInCapture();
var versionRecord = self.getVersion(name, version);
if (!versionRecord)
@@ -324,6 +333,7 @@ _.extend(baseCatalog.BaseCatalog.prototype, {
// version).
getDefaultReleaseVersion: function (track) {
var self = this;
buildmessage.assertInCapture();
self._requireInitialized();
if (!track)

View File

@@ -77,6 +77,7 @@ _.extend(OfficialCatalog.prototype, {
// the in-progress refresh to finish.
refresh: function () {
var self = this;
buildmessage.assertInCapture();
self._requireInitialized();
if (self._refreshFutures) {
@@ -212,6 +213,7 @@ _.extend(CompleteCatalog.prototype, {
// silently ignored.
initialize: function (options) {
var self = this;
buildmessage.assertInCapture();
options = options || {};
@@ -259,9 +261,7 @@ _.extend(CompleteCatalog.prototype, {
var self = this;
opts = opts || {};
self._requireInitialized();
// XXX for now, just doing the assertion if we have to call project
// stuff. but oh, this will be improved.
opts.ignoreProjectDeps || buildmessage.assertInCapture();
buildmessage.assertInCapture();
// Kind of a hack, as per specification. We don't have a constraint solver
// initialized yet. We are probably trying to build the constraint solver
@@ -335,9 +335,12 @@ _.extend(CompleteCatalog.prototype, {
// anyway. When we are using hot code push, we may be restarting the app
// because of a local package change that impacts that catalog. Don't wait
// on the official catalog to refresh data.json, in this case.
// - watchSet: if provided, any files read in reloading packages will be added
// to this set.
refresh: function (options) {
var self = this;
options = options || {};
buildmessage.assertInCapture();
// We need to limit the rate of refresh, or, at least, prevent any sort of
// loops. ForceRefresh will override either one.
@@ -355,7 +358,7 @@ _.extend(CompleteCatalog.prototype, {
self._insertServerPackages(localData);
self._recomputeEffectiveLocalPackages();
self._addLocalPackageOverrides();
self._addLocalPackageOverrides({watchSet: options.watchSet});
self.initialized = true;
// Rebuild the resolver, since packages may have changed.
self._initializeResolver();
@@ -416,8 +419,10 @@ _.extend(CompleteCatalog.prototype, {
// first removing any existing packages that have the same name.
//
// XXX emits buildmessages. are callers expecting that?
_addLocalPackageOverrides: function () {
_addLocalPackageOverrides: function (options) {
var self = this;
options = options || {};
buildmessage.assertInCapture();
// Remove all packages from the catalog that have the same name as
// a local package, along with all of their versions and builds.
@@ -462,8 +467,19 @@ _.extend(CompleteCatalog.prototype, {
if (buildmessage.jobHasMessages())
broken = true;
});
if (options.watchSet) {
options.watchSet.merge(packageSource.pluginWatchSet);
_.each(packageSource.architectures, function (sourceArch) {
options.watchSet.merge(sourceArch.watchSet);
});
}
// Recover by ignoring, but not until after we've augmented the watchSet
// (since we want the watchSet to include files with problems that the
// user may fix!)
if (broken)
return; // recover by ignoring
return;
packageSources[name] = packageSource;
@@ -724,6 +740,7 @@ _.extend(CompleteCatalog.prototype, {
// function twice with the same `name`.
addLocalPackage: function (name, directory) {
var self = this;
buildmessage.assertInCapture();
self._requireInitialized();
var resolvedPath = path.resolve(directory);
@@ -741,20 +758,6 @@ _.extend(CompleteCatalog.prototype, {
self.refresh();
},
// Reverse the effect of addLocalPackage.
removeLocalPackage: function (name) {
var self = this;
self._requireInitialized();
if (! _.has(self.localPackages, name))
throw new Error("no such local package?");
delete self.localPackages[name];
// see #CallingRefreshEveryTimeLocalPackagesChange
self._recomputeEffectiveLocalPackages();
self.refresh();
},
// True if `name` is a local package (is to be loaded via
// localPackageDirs or addLocalPackage rather than from the package
// server)

View File

@@ -24,11 +24,13 @@ var compiler = require('./compiler.js');
var catalog = require('./catalog.js');
var stats = require('./stats.js');
var unipackage = require('./unipackage.js');
var packageLoader = require('./package-loader.js');
// Returns an object with keys:
// record : (a package or version record)
// release : true if it is a release instead of a package.
var getReleaseOrPackageRecord = function(name) {
buildmessage.assertInCapture();
// Too lazy to do string parsing.
var rec = catalog.official.getPackage(name);
var rel = false;
@@ -68,6 +70,96 @@ var formatList = function (items) {
return out;
};
// Seriously, this dies if it can't refresh. Only call it if you're sure you're
// OK that the command doesn't work while offline.
var doOrDie = exports.doOrDie = function (f) {
var ret;
var messages = buildmessage.capture(function () {
ret = f();
});
if (messages.hasMessages()) {
process.stderr.write(messages.formatMessages());
throw main.ExitWithCode(1);
}
return ret;
};
var refreshOfficialCatalogOrDie = function () {
doOrDie(function () {
catalog.official.refresh();
});
};
// Internal use only. Makes sure that your Meteor install is totally good to go
// (is "airplane safe"). Specifically, it:
// - Builds all local packages (including their npm dependencies)
// - Ensures that all packages in your current release are downloaded
// - Ensures that all packages used by your app (if any) are downloaded
// (It also ensures you have the dev bundle downloaded, just like every command
// in a checkout.)
//
// The use case is, for example, cloning an app from github, running this
// command, then getting on an airplane.
//
// This does NOT guarantee a *re*build of all local packages (though it will
// download any new dependencies). If you want to rebuild all local packages,
// call meteor rebuild. That said, rebuild should only be necessary if there's a
// bug in the build tool... otherwise, packages should be rebuilt whenever
// necessary!
main.registerCommand({
name: '--get-ready'
}, function (options) {
// It is not strictly needed, but it is thematically a good idea to refresh
// the official catalog when we call get-ready, since it is an
// internet-requiring action.
refreshOfficialCatalogOrDie();
var loadPackages = function (packagesToLoad, loader) {
buildmessage.assertInCapture();
loader.downloadMissingPackages();
_.each(packagesToLoad, function (name) {
// Calling getPackage on the loader will return a unipackage object, which
// means that the package will be compiled/downloaded. That we throw the
// package variable away afterwards is immaterial.
loader.getPackage(name);
});
};
var messages = buildmessage.capture({
title: 'getting packages ready'
}, function () {
// First, build all accessible *local* packages, whether or not this app
// uses them. Use the "all packages are local" loader.
loadPackages(catalog.complete.getLocalPackageNames(),
new packageLoader.PackageLoader({versions: null}));
// In an app? Get the list of packages used by this app. Calling getVersions
// on the project will ensureDepsUpToDate which will ensure that all builds
// of everything we need from versions have been downloaded. (Calling
// buildPackages may be redundant, but can't hurt.)
if (options.appDir) {
loadPackages(_.keys(project.getVersions()), project.getPackageLoader());
}
// Using a release? Get all the packages in the release.
if (release.current.isProperRelease()) {
var releasePackages = release.current.getPackages();
loadPackages(
_.keys(releasePackages),
new packageLoader.PackageLoader({versions: releasePackages}));
}
});
if (messages.hasMessages()) {
process.stderr.write("\n" + messages.formatMessages());
return 1;
};
console.log("You are ready!");
return 0;
});
///////////////////////////////////////////////////////////////////////////////
// publish a package
@@ -97,12 +189,15 @@ main.registerCommand({
// Refresh the catalog, caching the remote package data on the server. We can
// optimize the workflow by using this data to weed out obviously incorrect
// submissions before they ever hit the wire.
catalog.official.refresh();
refreshOfficialCatalogOrDie();
var packageName = path.basename(options.packageDir);
// Fail early if the package already exists.
if (options.create) {
if (catalog.official.getPackage(packageName)) {
var packageInfo = doOrDie(function () {
return catalog.official.getPackage(packageName);
});
if (packageInfo) {
process.stderr.write("Package already exists. To create a new version of an existing "+
"package, do not use the --create flag! \n");
return 2;
@@ -184,7 +279,7 @@ main.registerCommand({
// then exit with the previous error code.
conn.close();
catalog.official.refresh();
refreshOfficialCatalogOrDie();
return ec;
});
@@ -207,9 +302,12 @@ main.registerCommand({
var versionString = all[1];
// Refresh the catalog, cacheing the remote package data on the server.
catalog.official.refresh(true);
refreshOfficialCatalogOrDie();
if (! catalog.complete.getPackage(name)) {
var packageInfo = doOrDie(function () {
return catalog.complete.getPackage(name);
});
if (! packageInfo) {
process.stderr.write(
"You can't call `meteor publish-for-arch` on package '" + name + "' without\n" +
"publishing it first.\n\n" +
@@ -217,7 +315,9 @@ main.registerCommand({
return 1;
}
var pkgVersion = catalog.official.getVersion(name, versionString);
var pkgVersion = doOrDie(function () {
return catalog.official.getVersion(name, versionString);
});
if (! pkgVersion) {
process.stderr.write(
"You can't call `meteor publish-for-arch` on version " + versionString + " of\n" +
@@ -308,7 +408,7 @@ main.registerCommand({
return 1;
}
catalog.official.refresh(); // XXX buildmessage.capture?
refreshOfficialCatalogOrDie();
return 0;
});
@@ -323,7 +423,7 @@ main.registerCommand({
}, function (options) {
// Refresh the catalog, cacheing the remote package data on the server.
process.stdout.write("Resyncing with package server...\n");
catalog.official.refresh();
refreshOfficialCatalogOrDie();
try {
var conn = packageClient.loggedInPackagesConnection();
@@ -416,7 +516,10 @@ main.registerCommand({
// authorized to publish before we do any complicated/long operations, and
// before we publish its packages.
if (!options['create-track']) {
var trackRecord = catalog.official.getReleaseTrack(relConf.track);
var trackRecord;
doOrDie(function () {
trackRecord = catalog.official.getReleaseTrack(relConf.track);
});
if (!trackRecord) {
process.stderr.write('\n There is no release track named ' + relConf.track +
'. If you are creating a new track, use the --create-track flag.\n');
@@ -650,15 +753,16 @@ main.registerCommand({
continue;
var prebuilt = toPublish[name];
var opts = {
new: !catalog.official.getPackage(name)
};
process.stdout.write("Publishing package: " + name + "\n");
var pubEC; // XXX merge with messages?
messages = buildmessage.capture({
title: "publishing package " + name
}, function () {
var opts = {
new: !catalog.official.getPackage(name)
};
// If we are creating a new package, dsPS will document this for us, so
// we don't need to do this here. Though, in the future, once we are
// done bootstrapping package servers, we should consider having some
@@ -720,7 +824,7 @@ main.registerCommand({
}
// Get it back.
catalog.official.refresh();
refreshOfficialCatalogOrDie();
process.stdout.write("Done creating " + relConf.track + "@" +
relConf.version + "!\n");
@@ -763,12 +867,18 @@ main.registerCommand({
return 1;
}
catalog.official.refresh();
// XXX this is dumb, we should be able to search even if we can't
// refresh. let's make sure to differentiate "horrible parse error while
// refreshing" from "can't connect to catalog"
refreshOfficialCatalogOrDie();
if (options.details) {
var full = options.args[0].split('@');
var name = full[0];
var allRecord = getReleaseOrPackageRecord(name);
var allRecord;
doOrDie(function () {
allRecord = getReleaseOrPackageRecord(name);
});
var record = allRecord.record;
if (!record) {
process.stderr.write("Unknown package or release: " + name + "\n");
@@ -779,11 +889,12 @@ main.registerCommand({
if (!allRecord.isRelease) {
label = "package";
var getRelevantRecord = function (version) {
var versionRecord =
catalog.official.getVersion(name, version);
var myBuilds = _.pluck(
catalog.official.getAllBuilds(name, version),
'buildArchitectures');
var versionRecord = doOrDie(function () {
return catalog.official.getVersion(name, version);
});
var myBuilds = _.pluck(doOrDie(function () {
return catalog.official.getAllBuilds(name, version);
}), 'buildArchitectures');
// Does this package only have a cross-platform build?
if (myBuilds.length === 1) {
var allArches = myBuilds[0].split('+');
@@ -807,12 +918,16 @@ main.registerCommand({
} else {
label = "release";
if (full.length > 1) {
versionRecords = [catalog.official.getReleaseVersion(name, full[1])];
doOrDie(function () {
versionRecords = [catalog.official.getReleaseVersion(name, full[1])];
});
} else {
versionRecords =
_.map(catalog.official.getSortedRecommendedReleaseVersions(name, ""),
function (v) {
return catalog.official.getReleaseVersion(name, v);
return doOrDie(function () {
return catalog.official.getReleaseVersion(name, v);
});
});
}
}
@@ -878,7 +993,7 @@ main.registerCommand({
search = new RegExp(options.args[0]);
} catch (err) {
process.stderr.write(err + "\n");
process.exit(1);
return 1;
}
if (options.maintainer) {
@@ -891,11 +1006,14 @@ main.registerCommand({
// you update to a new version of meteor is not that dire.
selector = function (packageName, isRelease) {
var record;
if (isRelease) {
record = catalog.official.getReleaseTrack(packageName);
} else {
record = catalog.official.getPackage(packageName);
}
// XXX make sure search works while offline
doOrDie(function () {
if (isRelease) {
record = catalog.official.getReleaseTrack(packageName);
} else {
record = catalog.official.getPackage(packageName);
}
});
return packageName.match(search) &&
!!_.findWhere(record.maintainers, {username: username});
};
@@ -907,7 +1025,9 @@ main.registerCommand({
_.each(allPackages, function (pack) {
if (selector(pack, false)) {
var vr = catalog.official.getLatestVersion(pack);
var vr = doOrDie(function () {
return catalog.official.getLatestVersion(pack);
});
if (vr) {
matchingPackages.push(
{ name: pack, description: vr.description });
@@ -916,10 +1036,13 @@ main.registerCommand({
});
_.each(allReleases, function (track) {
if (selector(track, true)) {
var vr = catalog.official.getDefaultReleaseVersion(track);
var vr = doOrDie(function () {
return catalog.official.getDefaultReleaseVersion(track);
});
if (vr) {
var vrlong =
catalog.official.getReleaseVersion(track, vr.version);
var vrlong = doOrDie(function () {
return catalog.official.getReleaseVersion(track, vr.version);
});
matchingReleases.push(
{ name: track, description: vrlong.description });
}
@@ -1040,7 +1163,9 @@ main.registerCommand({
var couldNotContactServer = false;
// Refresh the catalog, cacheing the remote package data on the server.
catalog.official.refresh(true);
// XXX should be able to update even without a refresh, esp to a specific
// server
refreshOfficialCatalogOrDie();
// If you are specifying packaging individually, you probably don't want to
// update the release.
@@ -1051,7 +1176,7 @@ main.registerCommand({
// Some basic checks to make sure that this command is being used correctly.
if (options["packages-only"] && options["patch"]) {
process.stderr.write("There is no such thing as a patch update to packages.");
return 1;;
return 1;
}
if (!options["packages-only"]) {
@@ -1079,7 +1204,9 @@ main.registerCommand({
// but it should be a no-op next time (unless there actually was a new latest
// release in the interim).
if (! release.forced) {
var latestRelease = release.latestDownloaded(releaseTrack);
var latestRelease = doOrDie(function () {
return release.latestDownloaded(releaseTrack);
});
// Are we on some track without ANY recommended releases at all,
// and the user ran 'meteor update' without specifying a release? We
// really can't do much here.
@@ -1179,7 +1306,9 @@ main.registerCommand({
return 1;;
}
var r = appRelease.split('@');
var record = catalog.official.getReleaseVersion(r[0], r[1]);
var record = doOrDie(function () {
return catalog.official.getReleaseVersion(r[0], r[1]);
});
var updateTo = record.patchReleaseVersion;
if (!updateTo) {
process.stderr.write(
@@ -1188,11 +1317,15 @@ main.registerCommand({
}
releaseVersionsToTry = [updateTo];
} else if (release.forced) {
releaseVersionsToTry = [release.current.getReleaseVersion()];
doOrDie(function () {
releaseVersionsToTry = [release.current.getReleaseVersion()];
});
} else {
// XXX clean up all this splitty stuff
var appReleaseInfo = catalog.official.getReleaseVersion(
appRelease.split('@')[0], appRelease.split('@')[1]);
var appReleaseInfo = doOrDie(function () {
return catalog.official.getReleaseVersion(
appRelease.split('@')[0], appRelease.split('@')[1]);
});
var appOrderKey = (appReleaseInfo && appReleaseInfo.orderKey) || null;
releaseVersionsToTry = catalog.official.getSortedRecommendedReleaseVersions(
releaseTrack, appOrderKey);
@@ -1220,21 +1353,35 @@ main.registerCommand({
return 1;
}
var solutionReleaseVersion = _.find(releaseVersionsToTry, function (versionToTry) {
var releaseRecord = catalog.complete.getReleaseVersion(releaseTrack, versionToTry);
var releaseRecord = doOrDie(function () {
return catalog.complete.getReleaseVersion(releaseTrack, versionToTry);
});
if (!releaseRecord)
throw Error("missing release record?");
var constraints = project.calculateCombinedConstraints(releaseRecord.packages);
var constraints = doOrDie(function () {
return project.calculateCombinedConstraints(releaseRecord.packages);
});
try {
solutionPackageVersions = catalog.complete.resolveConstraints(
constraints,
{ previousSolution: previousVersions },
{ ignoreProjectDeps: true });
var messages = buildmessage.capture(function () {
solutionPackageVersions = catalog.complete.resolveConstraints(
constraints,
{ previousSolution: previousVersions },
{ ignoreProjectDeps: true });
});
if (messages.hasMessages()) {
if (process.env.METEOR_UPDATE_DEBUG) {
process.stderr.write(
"Update to release " + releaseTrack + "@" + versionToTry +
" is impossible:\n" + messages.formatMessages());
}
return false;
}
} catch (e) {
// XXX we should make the error handling explicitly detectable, and not
// actually mention failures that are recoverable
process.stderr.write(
"Update to release " + releaseTrack +
"@" + versionToTry + " impossible: " + e.message + "\n");
if (process.env.METEOR_UPDATE_DEBUG) {
process.stderr.write(
"Update to release " + releaseTrack +
"@" + versionToTry + " impossible: " + e.message + "\n");
}
return false;
}
return true;
@@ -1322,13 +1469,21 @@ main.registerCommand({
// Call the constraint solver. This should not fail, since we are not adding
// any constraints that we didn't have before.
var newVersions = catalog.complete.resolveConstraints(allPackages, {
previousSolution: versions,
breaking: !options.minor,
upgrade: upgradePackages
}, {
ignoreProjectDeps: true
var newVersions;
var messages = buildmessage.capture(function () {
newVersions = catalog.complete.resolveConstraints(allPackages, {
previousSolution: versions,
breaking: !options.minor,
upgrade: upgradePackages
}, {
ignoreProjectDeps: true
});
});
if (messages.hasMessages()) {
process.stderr.write("Error resolving constraints for packages:\n"
+ messages.formatMessages());
return 1;
}
// Just for the sake of good messages, check to see if anything changed.
if (_.isEqual(newVersions, versions)) {
@@ -1378,7 +1533,8 @@ main.registerCommand({
var failed = false;
// Refresh the catalog, cacheing the remote package data on the server.
catalog.official.refresh();
// XXX ensure this works while offline
refreshOfficialCatalogOrDie();
// Read in existing package dependencies.
var packages = project.getConstraints();
@@ -1405,17 +1561,19 @@ main.registerCommand({
});
_.each(constraints, function (constraint) {
// Check that the package exists.
if (! catalog.complete.getPackage(constraint.name)) {
process.stderr.write(constraint.name + ": no such package\n");
failed = true;
return;
}
doOrDie(function () {
if (! catalog.complete.getPackage(constraint.name)) {
process.stderr.write(constraint.name + ": no such package\n");
failed = true;
return;
}
});
// If the version was specified, check that the version exists.
if (constraint.version !== null) {
var versionInfo = catalog.complete.getVersion(
constraint.name,
constraint.version);
var versionInfo = doOrDie(function () {
return catalog.complete.getVersion(constraint.name, constraint.version);
});
if (! versionInfo) {
process.stderr.write(
constraint.name + "@" + constraint.version + ": no such version\n");
@@ -1519,7 +1677,9 @@ main.registerCommand({
process.stdout.write("\n");
_.each(constraints, function (constraint) {
var version = newVersions[constraint.name];
var versionRecord = catalog.complete.getVersion(constraint.name, version);
var versionRecord = doOrDie(function () {
return catalog.complete.getVersion(constraint.name, version);
});
if (constraint.constraintString !== null &&
version !== constraint.version) {
process.stdout.write("Added " + constraint.name + " at version " + version +
@@ -1548,7 +1708,8 @@ main.registerCommand({
// server. Technically, we don't need to do this, since it is unlikely that
// new data will change our constraint solver decisions. But as a user, I
// would expect this command to update the local catalog.
catalog.official.refresh(true);
// XXX what if we're offline?
refreshOfficialCatalogOrDie();
// Read in existing package dependencies.
var packages = project.getConstraints();
@@ -1621,7 +1782,7 @@ main.registerCommand({
}, function (options) {
// We want the most recent information.
catalog.official.refresh();
refreshOfficialCatalogOrDie();
var name = options.args[0];
// Yay, checking that options are correct.
@@ -1637,7 +1798,10 @@ main.registerCommand({
}
// Now let's get down to business! Fetching the thing.
var fullRecord = getReleaseOrPackageRecord(name);
var fullRecord;
doOrDie(function () {
fullRecord = getReleaseOrPackageRecord(name);
});
var record = fullRecord.record;
if (!options.list) {
@@ -1669,7 +1833,7 @@ main.registerCommand({
process.stderr.write("\n" + err + "\n");
}
conn.close();
catalog.official.refresh();
refreshOfficialCatalogOrDie();
}
process.stdout.write("\n The maintainers for " + name + " are:\n");
@@ -1682,6 +1846,212 @@ main.registerCommand({
return 0;
});
///////////////////////////////////////////////////////////////////////////////
// admin make-bootstrap-tarballs
///////////////////////////////////////////////////////////////////////////////
main.registerCommand({
name: 'admin make-bootstrap-tarballs',
minArgs: 2,
maxArgs: 2,
hidden: true
}, function (options) {
var releaseNameAndVersion = options.args[0];
var outputDirectory = options.args[1];
// In this function, we want to use the official catalog everywhere, because
// we assume that all packages have been published (along with the release
// obviously) and we want to be sure to only bundle the published versions.
catalog.official.refresh();
var parsed = utils.splitConstraint(releaseNameAndVersion);
if (!parsed.constraint)
throw new main.ShowUsage;
var release = doOrDie(function () {
return catalog.official.getReleaseVersion(
parsed.package, parsed.constraint);
});
if (!release) {
// XXX this could also mean package unknown.
process.stderr.write('Release unknown: ' + releaseNameAndVersion + '\n');
return 1;
}
var toolPkg = release.tool && utils.splitConstraint(release.tool);
if (! (toolPkg && toolPkg.constraint))
throw new Error("bad tool in release: " + toolPkg);
var toolPkgBuilds = doOrDie(function () {
return catalog.official.getAllBuilds(
toolPkg.package, toolPkg.constraint);
});
if (!toolPkgBuilds) {
// XXX this could also mean package unknown.
process.stderr.write('Tool version unknown: ' + release.tool + '\n');
return 1;
}
if (!toolPkgBuilds.length) {
process.stderr.write('Tool version has no builds: ' + release.tool + '\n');
return 1;
}
// XXX check to make sure this is the three arches that we want? it's easier
// during 0.9.0 development to allow it to just decide "ok, i just want to
// build the OSX tarball" though.
var buildArches = _.pluck(toolPkgBuilds, 'buildArchitectures');
var osArches = _.map(buildArches, function (buildArch) {
var subArches = buildArch.split('+');
var osArches = _.filter(subArches, function (subArch) {
return subArch.substr(0, 3) === 'os.';
});
if (osArches.length !== 1) {
throw Error("build architecture " + buildArch + " lacks unique os.*");
}
return osArches[0];
});
process.stderr.write(
'Building bootstrap tarballs for architectures ' +
osArches.join(', ') + '\n');
// Before downloading anything, check that the catalog contains everything we
// need for the OSes that the tool is built for.
var messages = buildmessage.capture(function () {
_.each(osArches, function (osArch) {
_.each(release.packages, function (pkgVersion, pkgName) {
buildmessage.enterJob({
title: "looking up " + pkgName + "@" + pkgVersion + " on " + osArch
}, function () {
if (!catalog.official.getBuildsForArches(pkgName, pkgVersion, [osArch])) {
buildmessage.error("missing build of " + pkgName + "@" + pkgVersion +
" for " + osArch);
}
});
});
});
});
if (messages.hasMessages()) {
process.stderr.write("\n" + messages.formatMessages());
return 1;
};
files.mkdir_p(outputDirectory);
// Get a copy of the data.json.
var dataTmpdir = files.mkdtemp();
var tmpDataJson = path.join(dataTmpdir, 'data.json');
var savedData = packageClient.updateServerPackageData(null, {
packageStorageFile: tmpDataJson
}).data;
if (!savedData) {
// will have already printed an error
return 2;
}
_.each(osArches, function (osArch) {
var tmpdir = files.mkdtemp();
// We're going to build and tar up a tropohouse in a temporary directory; we
// don't want to use any of our local packages, so we use catalog.official
// instead of catalog.
// XXX update to '.meteor' when we combine houses
var tmpTropo = new tropohouse.Tropohouse(
path.join(tmpdir, '.meteor'), catalog.official);
var messages = buildmessage.capture(function () {
buildmessage.enterJob({
title: "downloading tool package " + toolPkg.package + "@" +
toolPkg.constraint
}, function () {
tmpTropo.maybeDownloadPackageForArchitectures({
packageName: toolPkg.package,
version: toolPkg.constraint,
architectures: [osArch] // XXX 'web.browser' too?
});
});
_.each(release.packages, function (pkgVersion, pkgName) {
buildmessage.enterJob({
title: "downloading package " + pkgName + "@" + pkgVersion
}, function () {
tmpTropo.maybeDownloadPackageForArchitectures({
packageName: pkgName,
version: pkgVersion,
architectures: [osArch] // XXX 'web.browser' too?
});
});
});
});
if (messages.hasMessages()) {
process.stderr.write("\n" + messages.formatMessages());
return 1;
}
// Install the data.json file we synced earlier.
files.copyFile(tmpDataJson, config.getPackageStorage(tmpTropo));
// Create the top-level 'meteor' symlink, which links to the latest tool's
// meteor shell script.
var toolUnipackagePath =
tmpTropo.packagePath(toolPkg.package, toolPkg.constraint);
var toolUnipackage = new unipackage.Unipackage;
toolUnipackage.initFromPath(toolPkg.package, toolUnipackagePath);
var toolRecord = _.findWhere(toolUnipackage.toolsOnDisk, {arch: osArch});
if (!toolRecord)
throw Error("missing tool for " + osArch);
fs.symlinkSync(
path.join(
tmpTropo.packagePath(toolPkg.package, toolPkg.constraint, true),
toolRecord.path,
'meteor'),
path.join(tmpTropo.root, 'meteor'));
files.createTarball(
tmpTropo.root,
path.join(outputDirectory, 'meteor-bootstrap-' + osArch + '.tar.gz'));
});
return 0;
});
// We will document how to set banners on things in a later release.
main.registerCommand({
name: 'admin set-banners',
minArgs: 1,
maxArgs: 1,
hidden: true
}, function (options) {
var bannersFile = options.args[0];
try {
var bannersData = fs.readFileSync(bannersFile, 'utf8');
bannersData = JSON.parse(bannersData);
} catch (e) {
process.stderr.write("Could not parse banners file: ");
process.stderr.write(e.message + "\n");
return 1;
}
if (!bannersData.track) {
process.stderr.write("Banners file should have a 'track' key.\n");
return 1;
}
if (!bannersData.banners) {
process.stderr.write("Banners file should have a 'banners' key.\n");
return 1;
}
try {
var conn = packageClient.loggedInPackagesConnection();
} catch (err) {
packageClient.handlePackageServerConnectionError(err);
return 1;
}
conn.call('setBannersOnReleases', bannersData.track,
bannersData.banners);
// Refresh afterwards.
refreshOfficialCatalogOrDie();
return 0;
});
main.registerCommand({
name: 'admin recommend-release',
minArgs: 1,
@@ -1692,7 +2062,7 @@ main.registerCommand({
}, function (options) {
// We want the most recent information.
catalog.official.refresh();
refreshOfficialCatalogOrDie();
var release = options.args[0].split('@');
var name = release[0];
var version = release[1];
@@ -1702,7 +2072,10 @@ main.registerCommand({
}
// Now let's get down to business! Fetching the thing.
var record = catalog.official.getReleaseTrack(name);
var record;
doOrDie(function () {
record = catalog.official.getReleaseTrack(name);
});
if (!record) {
process.stderr.write('\n There is no release track named ' + name + '\n');
return 1;
@@ -1731,7 +2104,7 @@ main.registerCommand({
process.stderr.write("\n" + err + "\n");
}
conn.close();
catalog.official.refresh();
refreshOfficialCatalogOrDie();
return 0;
});
@@ -1744,7 +2117,7 @@ main.registerCommand({
}, function (options) {
// We want the most recent information.
catalog.official.refresh();
refreshOfficialCatalogOrDie();
var package = options.args[0].split('@');
var name = package[0];
var version = package[1];
@@ -1755,7 +2128,9 @@ main.registerCommand({
var ecv = options.args[1];
// Now let's get down to business! Fetching the thing.
var record = catalog.official.getPackage(name);
var record = doOrDie(function () {
return catalog.official.getPackage(name);
});
if (!record) {
process.stderr.write('\n There is no package named ' + name + '\n');
return 1;
@@ -1780,7 +2155,7 @@ main.registerCommand({
process.stderr.write("\n" + err + "\n");
}
conn.close();
catalog.official.refresh();
refreshOfficialCatalogOrDie();
return 0;
});
@@ -1793,12 +2168,14 @@ main.registerCommand({
}, function (options) {
// We want the most recent information.
catalog.official.refresh();
refreshOfficialCatalogOrDie();
var name = options.args[0];
var url = options.args[1];
// Now let's get down to business! Fetching the thing.
var record = catalog.official.getPackage(name);
var record = doOrDie(function () {
return catalog.official.getPackage(name);
});
if (!record) {
process.stderr.write('\n There is no package named ' + name + '\n');
return 1;
@@ -1821,7 +2198,7 @@ main.registerCommand({
process.stderr.write("\n" + err + "\n");
}
conn.close();
catalog.official.refresh();
refreshOfficialCatalogOrDie();
return 0;
});

View File

@@ -19,12 +19,12 @@ var httpHelpers = require('./http-helpers.js');
var archinfo = require('./archinfo.js');
var tropohouse = require('./tropohouse.js');
var packageCache = require('./package-cache.js');
var packageLoader = require('./package-loader.js');
var PackageSource = require('./package-source.js');
var compiler = require('./compiler.js');
var catalog = require('./catalog.js');
var stats = require('./stats.js');
var unipackage = require('./unipackage.js');
var commandsPackages = require('./commands-packages.js');
// The architecture used by Galaxy servers; it's the architecture used
// by 'meteor deploy'.
@@ -60,6 +60,7 @@ var hostedWithGalaxy = function (site) {
// version record for that package.
var getLocalPackages = function () {
var ret = {};
buildmessage.assertInCapture();
var names = catalog.complete.getAllPackageNames();
_.each(names, function (name) {
@@ -71,6 +72,7 @@ var getLocalPackages = function () {
return ret;
};
///////////////////////////////////////////////////////////////////////////////
// options that act like commands
///////////////////////////////////////////////////////////////////////////////
@@ -138,75 +140,6 @@ main.registerCommand({
return 0;
});
// Internal use only. Makes sure that your Meteor install is totally good to go
// (is "airplane safe"). Specifically, it:
// - Builds all local packages (including their npm dependencies)
// - Ensures that all packages in your current release are downloaded
// - Ensures that all packages used by your app (if any) are downloaded
// (It also ensures you have the dev bundle downloaded, just like every command
// in a checkout.)
//
// The use case is, for example, cloning an app from github, running this
// command, then getting on an airplane.
//
// This does NOT guarantee a *re*build of all local packages (though it will
// download any new dependencies). If you want to rebuild all local packages,
// call meteor rebuild. That said, rebuild should only be necessary if there's a
// bug in the build tool... otherwise, packages should be rebuilt whenever
// necessary!
main.registerCommand({
name: '--get-ready'
}, function (options) {
// It is not strictly needed, but it is thematically a good idea to refresh
// the official catalog when we call get-ready, since it is an
// internet-requiring action.
catalog.official.refresh();
var loadPackages = function (packagesToLoad, loader) {
buildmessage.assertInCapture();
loader.downloadMissingPackages();
_.each(packagesToLoad, function (name) {
// Calling getPackage on the loader will return a unipackage object, which
// means that the package will be compiled/downloaded. That we throw the
// package variable away afterwards is immaterial.
loader.getPackage(name);
});
};
var messages = buildmessage.capture({
title: 'getting packages ready'
}, function () {
// First, build all accessible *local* packages, whether or not this app
// uses them. Use the "all packages are local" loader.
loadPackages(catalog.complete.getLocalPackageNames(),
new packageLoader.PackageLoader({versions: null}));
// In an app? Get the list of packages used by this app. Calling getVersions
// on the project will ensureDepsUpToDate which will ensure that all builds
// of everything we need from versions have been downloaded. (Calling
// buildPackages may be redundant, but can't hurt.)
if (options.appDir) {
loadPackages(_.keys(project.getVersions()), project.getPackageLoader());
}
// Using a release? Get all the packages in the release.
if (release.current.isProperRelease()) {
var releasePackages = release.current.getPackages();
loadPackages(
_.keys(releasePackages),
new packageLoader.PackageLoader({versions: releasePackages}));
}
});
if (messages.hasMessages()) {
process.stderr.write("\n" + messages.formatMessages());
return 1;
};
console.log("You are ready!");
return 0;
});
///////////////////////////////////////////////////////////////////////////////
// run
///////////////////////////////////////////////////////////////////////////////
@@ -343,7 +276,9 @@ main.registerCommand({
var relString;
if (release.current.isCheckout()) {
xn = xn.replace(/~cc~/g, "//");
var rel = catalog.complete.getDefaultReleaseVersion();
var rel = commandsPackages.doOrDie(function () {
return catalog.complete.getDefaultReleaseVersion();
});
var relString = rel.track + "@" + rel.version;
} else {
xn = xn.replace(/~cc~/g, "");
@@ -381,10 +316,12 @@ main.registerCommand({
// (In particular, it's not sufficient to create the new app with
// this version of the tools, and then stamp on the correct release
// at the end.)
if (! release.current.isCheckout() &&
release.current.name !== release.latestDownloaded() &&
! release.forced) {
throw new main.SpringboardToLatestRelease;
if (! release.current.isCheckout() && !release.forced) {
var needToSpringboard = commandsPackages.doOrDie(function () {
return release.current.name !== release.latestDownloaded();
});
if (needToSpringboard)
throw new main.SpringboardToLatestRelease;
}
var exampleDir = path.join(__dirname, '..', 'examples');
@@ -532,7 +469,7 @@ main.registerCommand({
process.stderr.write("Invalid architecture: " + options.architecture + "\n");
process.stderr.write(
"Please use one of the following: " + VALID_ARCHITECTURES + "\n");
process.exit(1);
return 1;
}
var bundleArch = options.architecture || archinfo.host();
@@ -979,7 +916,9 @@ main.registerCommand({
if (options.args.length === 0) {
// Only test local packages if no package is specified.
// XXX should this use the new getLocalPackageNames?
var packageList = getLocalPackages();
var packageList = commandsPackages.doOrDie(function () {
return getLocalPackages();
});
if (! packageList) {
// Couldn't load the package list, probably because some package
// has a parse error. Bail out -- this kind of sucks; we would
@@ -1071,12 +1010,18 @@ main.registerCommand({
// compute them for us. This means that right now, we are testing all packages
// as they work together.
var tests = [];
_.each(testPackages, function(name) {
var versionRecord = catalog.complete.getLatestVersion(name);
if (versionRecord && versionRecord.testName) {
tests.push(versionRecord.testName);
}
var messages = buildmessage.capture(function () {
_.each(testPackages, function(name) {
var versionRecord = catalog.complete.getLatestVersion(name);
if (versionRecord && versionRecord.testName) {
tests.push(versionRecord.testName);
}
});
});
if (messages.hasMessages()) {
process.stderr.write(messages.formatMessages());
return 1;
}
project.forceEditPackages(tests, 'add');
@@ -1114,10 +1059,6 @@ main.registerCommand({
});
}
_.each(localPackageNames, function (name) {
catalog.complete.removeLocalPackage(name);
});
return ret;
});
@@ -1204,212 +1145,6 @@ main.registerCommand({
return auth.whoAmICommand(options);
});
///////////////////////////////////////////////////////////////////////////////
// admin make-bootstrap-tarballs
///////////////////////////////////////////////////////////////////////////////
main.registerCommand({
name: 'admin make-bootstrap-tarballs',
minArgs: 2,
maxArgs: 2,
hidden: true,
}, function (options) {
var releaseNameAndVersion = options.args[0];
var outputDirectory = options.args[1];
// In this function, we want to use the official catalog everywhere, because
// we assume that all packages have been published (along with the release
// obviously) and we want to be sure to only bundle the published versions.
catalog.official.refresh();
var parsed = utils.splitConstraint(releaseNameAndVersion);
if (!parsed.constraint)
throw new main.ShowUsage;
var release = catalog.official.getReleaseVersion(parsed.package,
parsed.constraint);
if (!release) {
// XXX this could also mean package unknown.
process.stderr.write('Release unknown: ' + releaseNameAndVersion + '\n');
return 1;
}
var toolPkg = release.tool && utils.splitConstraint(release.tool);
if (! (toolPkg && toolPkg.constraint))
throw new Error("bad tool in release: " + toolPkg);
var toolPkgBuilds = catalog.official.getAllBuilds(
toolPkg.package, toolPkg.constraint);
if (!toolPkgBuilds) {
// XXX this could also mean package unknown.
process.stderr.write('Tool version unknown: ' + release.tool + '\n');
return 1;
}
if (!toolPkgBuilds.length) {
process.stderr.write('Tool version has no builds: ' + release.tool + '\n');
return 1;
}
// XXX check to make sure this is the three arches that we want? it's easier
// during 0.9.0 development to allow it to just decide "ok, i just want to
// build the OSX tarball" though.
var buildArches = _.pluck(toolPkgBuilds, 'buildArchitectures');
var osArches = _.map(buildArches, function (buildArch) {
var subArches = buildArch.split('+');
var osArches = _.filter(subArches, function (subArch) {
return subArch.substr(0, 3) === 'os.';
});
if (osArches.length !== 1) {
throw Error("build architecture " + buildArch + " lacks unique os.*");
}
return osArches[0];
});
process.stderr.write(
'Building bootstrap tarballs for architectures ' +
osArches.join(', ') + '\n');
// Before downloading anything, check that the catalog contains everything we
// need for the OSes that the tool is built for.
var messages = buildmessage.capture(function () {
_.each(osArches, function (osArch) {
_.each(release.packages, function (pkgVersion, pkgName) {
buildmessage.enterJob({
title: "looking up " + pkgName + "@" + pkgVersion + " on " + osArch
}, function () {
if (!catalog.official.getBuildsForArches(pkgName, pkgVersion, [osArch])) {
buildmessage.error("missing build of " + pkgName + "@" + pkgVersion +
" for " + osArch);
}
});
});
});
});
if (messages.hasMessages()) {
process.stderr.write("\n" + messages.formatMessages());
return 1;
};
files.mkdir_p(outputDirectory);
// Get a copy of the data.json.
var dataTmpdir = files.mkdtemp();
var tmpDataJson = path.join(dataTmpdir, 'data.json');
var savedData = packageClient.updateServerPackageData(null, {
packageStorageFile: tmpDataJson
}).data;
if (!savedData) {
// will have already printed an error
process.exit(2);
}
_.each(osArches, function (osArch) {
var tmpdir = files.mkdtemp();
// We're going to build and tar up a tropohouse in a temporary directory; we
// don't want to use any of our local packages, so we use catalog.official
// instead of catalog.
// XXX update to '.meteor' when we combine houses
var tmpTropo = new tropohouse.Tropohouse(
path.join(tmpdir, '.meteor'), catalog.official);
var messages = buildmessage.capture(function () {
buildmessage.enterJob({
title: "downloading tool package " + toolPkg.package + "@" +
toolPkg.constraint
}, function () {
tmpTropo.maybeDownloadPackageForArchitectures({
packageName: toolPkg.package,
version: toolPkg.constraint,
architectures: [osArch] // XXX 'web.browser' too?
});
});
_.each(release.packages, function (pkgVersion, pkgName) {
buildmessage.enterJob({
title: "downloading package " + pkgName + "@" + pkgVersion
}, function () {
tmpTropo.maybeDownloadPackageForArchitectures({
packageName: pkgName,
version: pkgVersion,
architectures: [osArch] // XXX 'web.browser' too?
});
});
});
});
if (messages.hasMessages()) {
process.stderr.write("\n" + messages.formatMessages());
return 1;
}
// Install the data.json file we synced earlier.
files.copyFile(tmpDataJson, config.getPackageStorage(tmpTropo));
// Create the top-level 'meteor' symlink, which links to the latest tool's
// meteor shell script.
var toolUnipackagePath =
tmpTropo.packagePath(toolPkg.package, toolPkg.constraint);
var toolUnipackage = new unipackage.Unipackage;
toolUnipackage.initFromPath(toolPkg.package, toolUnipackagePath);
var toolRecord = _.findWhere(toolUnipackage.toolsOnDisk, {arch: osArch});
if (!toolRecord)
throw Error("missing tool for " + osArch);
fs.symlinkSync(
path.join(
tmpTropo.packagePath(toolPkg.package, toolPkg.constraint, true),
toolRecord.path,
'meteor'),
path.join(tmpTropo.root, 'meteor'));
files.createTarball(
tmpTropo.root,
path.join(outputDirectory, 'meteor-bootstrap-' + osArch + '.tar.gz'));
});
return 0;
});
///////////////////////////////////////////////////////////////////////////////
// admin set-banners
///////////////////////////////////////////////////////////////////////////////
// We will document how to set banners on things in a later release.
main.registerCommand({
name: 'admin set-banners',
minArgs: 1,
maxArgs: 1,
hidden: true,
}, function (options) {
var bannersFile = options.args[0];
try {
var bannersData = fs.readFileSync(bannersFile, 'utf8');
bannersData = JSON.parse(bannersData);
} catch (e) {
process.stderr.write("Could not parse banners file: ");
process.stderr.write(e.message + "\n");
return 1;
}
if (!bannersData.track) {
process.stderr.write("Banners file should have a 'track' key.\n");
return 1;
}
if (!bannersData.banners) {
process.stderr.write("Banners file should have a 'banners' key.\n");
return 1;
}
try {
var conn = packageClient.loggedInPackagesConnection();
} catch (err) {
packageClient.handlePackageServerConnectionError(err);
return 1;
}
conn.call('setBannersOnReleases', bannersData.track,
bannersData.banners);
// Refresh afterwards.
catalog.official.refresh();
return 0;
});
///////////////////////////////////////////////////////////////////////////////
// self-test
///////////////////////////////////////////////////////////////////////////////

View File

@@ -137,7 +137,7 @@ var determineBuildTimeDependencies = function (packageSource,
constraintSolverOpts) {
var ret = {};
constraintSolverOpts = constraintSolverOpts || {};
constraintSolverOpts.ignoreProjectDeps || buildmessage.assertInCapture();
buildmessage.assertInCapture();
// There are some special cases where we know that the package has no source
// files, which means it can't have any interesting build-time
@@ -898,6 +898,7 @@ compiler.compile = function (packageSource, options) {
// so any dependencies that contains plugins have real versions in the
// catalog already. Still, this seems very brittle and we should fix it.
var getPluginProviders = function (versions) {
buildmessage.assertInCapture();
var result = {};
_.each(versions, function (version, name) {
// Direct dependencies only create a build-order constraint if
@@ -918,7 +919,7 @@ var getPluginProviders = function (versions) {
compiler.getBuildOrderConstraints = function (
packageSource, constraintSolverOpts) {
constraintSolverOpts = constraintSolverOpts || {};
constraintSolverOpts.ignoreProjectDeps || buildmessage.assertInCapture();
buildmessage.assertInCapture();
var versions = {}; // map from package name to version to true
var addVersion = function (version, name) {

View File

@@ -76,6 +76,14 @@ var messages = {};
// usage information.
main.ShowUsage = function () {};
// Exception to throw from a helper function inside a command which is identical
// to returning the given exit code from the command. ONLY USE THIS IN HELPERS
// THAT ARE ONLY CALLED DIRECTLY FROM COMMANDS! DON'T BE LAZY AND PUT THROW OF
// THIS IN RANDOM LIBRARY CODE!
main.ExitWithCode = function (code) {
this.code = code;
};
// Exception to throw to skip the process.exit call.
main.WaitForExit = function () {};
@@ -771,7 +779,14 @@ Fiber(function () {
} else {
// Run outside an app dir with no --release flag. Use the latest
// release we know about (in the default track).
releaseName = release.latestDownloaded();
var messages = buildmessage.capture(function () {
releaseName = release.latestDownloaded();
});
if (messages.hasMessages()) {
process.stderr.write("=> Errors while determining latest release:\n" +
messages.formatMessages());
process.exit(1);
}
}
}
@@ -789,7 +804,20 @@ Fiber(function () {
}
try {
var rel = release.load(releaseName);
var rel;
var messages = buildmessage.capture(function () {
rel = release.load(releaseName);
});
if (messages.hasMessages()) {
// XXX The errors that trigger this are likely things like failure to
// load livedata when trying to refresh, or maybe failure to build some
// local packages, or something. They probably aren't "release doesn't
// exist"? But who knows?
process.stderr.write("=> Errors while loading release:\n" +
messages.formatMessages());
process.exit(1);
}
} catch (e) {
var name = releaseName;
if (e instanceof files.OfflineError) {
@@ -1115,8 +1143,15 @@ commandName + ": You're not in a Meteor project directory.\n" +
// Commands that require you to be in a package directory add that package
// as a local package to the catalog. Other random commands don't (but if we
// see a reason for them to, we can change this rule).
catalog.complete.addLocalPackage(path.basename(options.packageDir),
options.packageDir);
messages = buildmessage.capture(function () {
catalog.complete.addLocalPackage(path.basename(options.packageDir),
options.packageDir);
});
if (messages.hasMessages()) {
process.stderr.write("=> Errors while scanning current package:\n\n");
process.stderr.write(messages.formatMessages());
process.exit(1);
}
}
if (command.requiresRelease && ! release.current) {
@@ -1148,24 +1183,35 @@ commandName + ": You're not in a Meteor project directory.\n" +
var ret = command.func(options);
} catch (e) {
if (e === main.ShowUsage || e === main.WaitForExit ||
e === main.SpringboardToLatestRelease)
e === main.SpringboardToLatestRelease ||
e === main.WaitForExit) {
throw new Error(
"you meant 'throw new main.Foo', not 'throw main.Foo'");
if (e instanceof main.ShowUsage) {
} else if (e instanceof main.ShowUsage) {
process.stderr.write(longHelp(commandName) + "\n");
process.exit(1);
}
if (e instanceof main.SpringboardToLatestRelease) {
} else if (e instanceof main.SpringboardToLatestRelease) {
// Load the latest release's metadata so that we can figure out
// the tools version that it uses. We should only do this if
// we know there is some latest release on this track.
var latestRelease = release.load(release.latestDownloaded(e.track));
var latestRelease;
var messages = buildmessage.capture(function () {
latestRelease = release.load(release.latestDownloaded(e.track));
});
if (messages.hasMessages()) {
process.stderr.write("=> Errors while loading latest release:\n\n");
process.stderr.write(messages.formatMessages());
process.exit(1);
}
springboard(latestRelease, latestRelease.name);
// (does not return)
}
if (e instanceof main.WaitForExit)
} else if (e instanceof main.WaitForExit) {
return;
throw e;
} else if (e instanceof main.ExitWithCode) {
process.exit(e.code);
} else {
throw e;
}
}
// Exit. (We will not get here if the command threw an exception

View File

@@ -58,28 +58,6 @@ _.extend(exports.PackageLoader.prototype, {
name, loadPath, self.constraintSolverOpts);
},
containsPlugins: function (name) {
var self = this;
// We don't want to ever look at the catalog in the uniload case. We
// shouldn't ever care about plugins anyway, since uniload should never
// compile real packages from source (it sorta compiles the wrapper "load"
// package, which should avoid calling this function).
if (self.uniloadDir)
throw Error("called containsPlugins for uniload?");
var versionRecord;
if (self.versions === null) {
versionRecord = catalog.complete.getLatestVersion(name);
} else if (_.has(self.versions, name)) {
versionRecord = catalog.complete.getVersion(name, self.versions[name]);
} else {
throw new Error("no version specified for package " + name);
}
return versionRecord.containsPlugins;
},
// As getPackage, but returns the path of the package that would be
// loaded rather than loading the package, and does not take any
// options. Returns null if the package is not available.

View File

@@ -406,6 +406,7 @@ _.extend(PackageSource.prototype, {
// guideline for a repeatable build.
initFromPackageDir: function (name, dir, options) {
var self = this;
buildmessage.assertInCapture();
var isPortable = true;
options = options || {};

View File

@@ -233,6 +233,8 @@ _.extend(Project.prototype, {
// getCurrentCombinedConstraints.
calculateCombinedConstraints : function (releasePackages) {
var self = this;
buildmessage.assertInCapture();
var allDeps = [];
// First, we process the contents of the .meteor/packages file. The
// self.constraints variable is always up to date.

View File

@@ -5,6 +5,7 @@ var project = require('./project.js').project;
var warehouse = require('./warehouse.js');
var catalog = require('./catalog.js');
var utils = require('./utils.js');
var buildmessage = require('./buildmessage.js');
var release = exports;
@@ -91,6 +92,7 @@ _.extend(Release.prototype, {
// (XXX: Or maybe just return "checkout" or something?)
getCurrentToolsVersion: function () {
var self = this;
buildmessage.assertInCapture();
if (release.current.name) {
return self._manifest.tool;
@@ -178,6 +180,7 @@ release.explicit = null;
// in the current project. (taking into account release.forced and whether we're
// currently running from a checkout).
release.usingRightReleaseForApp = function () {
buildmessage.assertInCapture();
if (release.current === null)
throw new Error("no release?");
@@ -195,6 +198,7 @@ release.usingRightReleaseForApp = function () {
// for use. May not be called when running from a checkout.
// 'track' is optional (it defaults to the default track).
release.latestDownloaded = function (track) {
buildmessage.assertInCapture();
if (! files.usesWarehouse())
throw new Error("called from checkout?");
// For self-test only.
@@ -233,6 +237,7 @@ release.latestDownloaded = function (track) {
// in the world (confirmed with server).
release.load = function (name, options) {
options = options || {};
buildmessage.assertInCapture();
if (! name) {
return new Release({ name: null });
@@ -285,6 +290,7 @@ release.setCurrent = function (releaseObject, forced, explicit) {
// XXX hack
release._setCurrentForOldTest = function () {
buildmessage.assertInCapture();
if (process.env.METEOR_SPRINGBOARD_RELEASE) {
release.setCurrent(release.load(process.env.METEOR_SPRINGBOARD_RELEASE),
true);

View File

@@ -397,7 +397,22 @@ _.extend(AppRunner.prototype, {
// tell the catalog to reload local package sources (since their
// dependencies may have changed), and then we should recompute the project
// constraints.
catalog.complete.refresh({ forceRefresh: true });
// XXX the catalog refresh seems overly conservative, but who knows
var refreshWatchSet = new watch.WatchSet;
var refreshMessages = buildmessage.capture(function () {
catalog.complete.refresh({ forceRefresh: true,
watchSet: refreshWatchSet});
});
if (refreshMessages.hasMessages()) {
return {
outcome: 'bundle-fail',
bundleResult: {
errors: refreshMessages,
serverWatchSet: refreshWatchSet
}
};
}
project.reload();
runLog.clearLog();
@@ -411,11 +426,22 @@ _.extend(AppRunner.prototype, {
// release.current), but we still want to detect the mismatch if
// you are testing packages from an app and you 'meteor update'
// that app.
if (self.appDirForVersionCheck &&
! release.usingRightReleaseForApp()) {
return { outcome: 'wrong-release',
releaseNeeded:
project.getMeteorReleaseVersion() };
if (self.appDirForVersionCheck) {
var wrongRelease;
var rightReleaseMessages = buildmessage.capture(function () {
wrongRelease = ! release.usingRightReleaseForApp();
});
if (rightReleaseMessages.hasMessages()) {
return {
outcome: 'bundle-fail',
bundleResult: { errors: rightReleaseMessages }
};
}
if (wrongRelease) {
return { outcome: 'wrong-release',
releaseNeeded: project.getMeteorReleaseVersion()
};
}
}
// Bundle up the app
@@ -425,6 +451,7 @@ _.extend(AppRunner.prototype, {
stats.recordPackages(self.appDir);
});
if (statsMessages.hasMessages()) {
// XXX so this happens any time you're offline?
process.stdout.write("Error talking to stats server:\n" +
statsMessages.formatMessages());
// ... but continue;
@@ -698,8 +725,10 @@ _.extend(AppRunner.prototype, {
self.watchFuture = new Future;
var watchSet = new watch.WatchSet();
watchSet.merge(runResult.bundleResult.serverWatchSet);
watchSet.merge(runResult.bundleResult.clientWatchSet);
if (runResult.bundleResult.serverWatchSet)
watchSet.merge(runResult.bundleResult.serverWatchSet);
if (runResult.bundleResult.clientWatchSet)
watchSet.merge(runResult.bundleResult.clientWatchSet);
var watcher = new watch.Watcher({
watchSet: watchSet,
onChange: function () {

View File

@@ -84,13 +84,15 @@ var execFileSync = function (binary, args) {
})().wait();
};
var captureAndThrow = function (f) {
var doOrThrow = function (f) {
var ret;
var messages = buildmessage.capture(function () {
f();
ret = f();
});
if (messages.hasMessages()) {
throw Error(messages.formatMessages());
}
return ret;
};
///////////////////////////////////////////////////////////////////////////////
@@ -634,7 +636,7 @@ _.extend(Sandbox.prototype, {
// build apps that contain core packages).
var toolPackage, toolPackageDirectory;
captureAndThrow(function () {
doOrThrow(function () {
toolPackage = getToolsPackage();
toolPackageDirectory = '.' + toolPackage.version + '.XXX++'
+ toolPackage.buildArchitectures();
@@ -700,22 +702,31 @@ _.extend(Sandbox.prototype, {
// should be OK.
var oldOffline = catalog.official.offline;
catalog.official.offline = true;
catalog.official.refresh();
doOrThrow(function () {
catalog.official.refresh();
});
_.each(
['autopublish', 'standard-app-packages', 'insecure'],
function (name) {
var versionRec = catalog.official.getLatestVersion(name);
var versionRec = doOrThrow(function () {
return catalog.official.getLatestVersion(name);
});
if (!versionRec) {
catalog.official.offline = false;
catalog.official.refresh();
doOrThrow(function () {
catalog.official.refresh();
});
catalog.official.offline = true;
versionRec = catalog.official.getLatestVersion(name);
versionRec = doOrThrow(function () {
return catalog.official.getLatestVersion(name);
});
if (!versionRec) {
throw new Error(" hack fails for " + name);
}
}
var buildRec = catalog.official.getAllBuilds(
name, versionRec.version)[0];
var buildRec = doOrThrow(function () {
return catalog.official.getAllBuilds(name, versionRec.version)[0];
});
// Insert into packages.
stubCatalog.collections.packages.push({
@@ -1582,6 +1593,6 @@ _.extend(exports, {
expectThrows: expectThrows,
getToolsPackage: getToolsPackage,
execFileSync: execFileSync,
captureAndThrow: captureAndThrow,
doOrThrow: doOrThrow,
testPackageServerUrl: 'https://test-packages.meteor.com'
});

View File

@@ -133,15 +133,25 @@ selftest.define("javascript hot code push", function (options) {
s.mkdir("server");
s.write("server/test.js", "jsVar = 'bar'");
run.match("server restarted");
// Setting the autoupdateVersion to a different string should also
// force the client to restart.
s.write("server/test.js",
"Package.autoupdate.Autoupdate.autoupdateVersion = 'random'");
run.match("server restarted");
run.match("client connected: 0");
run.match("jsVar: undefined");
s.unlink("server/test.js");
run.match("server restarted");
s.write("client/empty.js", "");
run.match("client connected: 0");
// We should not be able to access a server variable from the client.
run.match("jsVar: undefined");
s.unlink("server/test.js");
run.match("server restarted");
s.unlink("client/empty.js");
run.match("client connected: 0");
run.match("client connected: 1");
run.match("jsVar: undefined");
// Break the HTML file. This should kill the server, and print errors.
@@ -169,6 +179,7 @@ selftest.define("javascript hot code push", function (options) {
s.write("client/test.js", "jsVar = 'baz'");
run.match("client connected: 3");
run.match("jsVar: baz");
s.unlink("client/test.js");
run.stop();

View File

@@ -1,6 +1,6 @@
application-configuration@1.0.0
autopublish@1.0.0
autoupdate@1.0.0
autoupdate@1.0.1
binary-heap@1.0.0
blaze-tools@1.0.0
blaze@1.0.1
@@ -20,7 +20,7 @@ jquery@1.0.0
json@1.0.0
livedata@1.0.1
logging@1.0.0
meteor@1.0.1
meteor@1.0.2
minifiers@1.0.0
minimongo@1.0.1
mongo-livedata@1.0.0
@@ -32,10 +32,10 @@ reload@1.0.0
retry@1.0.0
routepolicy@1.0.0
session@1.0.0
spacebars-compiler@1.0.0
spacebars-compiler@1.0.1
spacebars@1.0.0
standard-app-packages@1.0.0
templating@1.0.1
templating@1.0.2
test-package@1.0.0
ui@1.0.0
underscore@1.0.0

View File

@@ -2,7 +2,7 @@
"dependencies": [
[
"meteor",
"1.0.1"
"1.0.2"
],
[
"underscore",
@@ -15,6 +15,6 @@
{}
]
],
"toolVersion": "meteor-tool@1.0.7",
"toolVersion": "meteor-tool@1.0.8",
"format": "1.0"
}

View File

@@ -1,6 +1,6 @@
application-configuration@1.0.0
autopublish@1.0.0
autoupdate@1.0.0
autoupdate@1.0.1
binary-heap@1.0.0
blaze-tools@1.0.0
blaze@1.0.1
@@ -20,7 +20,7 @@ jquery@1.0.0
json@1.0.0
livedata@1.0.1
logging@1.0.0
meteor@1.0.1
meteor@1.0.2
minifiers@1.0.0
minimongo@1.0.1
mongo-livedata@1.0.0
@@ -33,10 +33,10 @@ reload@1.0.0
retry@1.0.0
routepolicy@1.0.0
session@1.0.0
spacebars-compiler@1.0.0
spacebars-compiler@1.0.1
spacebars@1.0.0
standard-app-packages@1.0.0
templating@1.0.1
templating@1.0.2
ui@1.0.0
underscore@1.0.0
webapp@1.0.0

View File

@@ -1,5 +1,5 @@
application-configuration@1.0.0
autoupdate@1.0.0
autoupdate@1.0.1
binary-heap@1.0.0
blaze-tools@1.0.0
blaze@1.0.1
@@ -18,7 +18,7 @@ jquery@1.0.0
json@1.0.0
livedata@1.0.1
logging@1.0.0
meteor@1.0.1
meteor@1.0.2
minifiers@1.0.0
minimongo@1.0.1
mongo-livedata@1.0.0
@@ -30,10 +30,10 @@ reload@1.0.0
retry@1.0.0
routepolicy@1.0.0
session@1.0.0
spacebars-compiler@1.0.0
spacebars-compiler@1.0.1
spacebars@1.0.0
standard-app-packages@1.0.0
templating@1.0.1
templating@1.0.2
ui@1.0.0
underscore@1.0.0
webapp@1.0.0

View File

@@ -9,6 +9,7 @@ var uniload = require('../../uniload.js');
var release = require('../../release.js');
var project = require('../../project.js');
var catalog = require('../../catalog.js');
var buildmessage = require('../../buildmessage.js');
var appWithPublic = path.join(__dirname, 'app-with-public');
var appWithPrivate = path.join(__dirname, 'app-with-private');
@@ -29,11 +30,24 @@ var setAppDir = function (appDir) {
files.getCurrentToolsDir(), 'packages'));
}
catalog.complete.initialize({
localPackageDirs: localPackageDirs
doOrThrow(function () {
catalog.complete.initialize({
localPackageDirs: localPackageDirs
});
});
};
var doOrThrow = function (f) {
var ret;
var messages = buildmessage.capture(function () {
ret = f();
});
if (messages.hasMessages()) {
throw Error(messages.formatMessages());
}
return ret;
};
// These tests make some assumptions about the structure of stars: that there
// are client and server programs inside programs/.
@@ -143,7 +157,9 @@ var runTest = function () {
var Fiber = require('fibers');
Fiber(function () {
release._setCurrentForOldTest();
doOrThrow(function () {
release._setCurrentForOldTest();
});
try {
runTest();

View File

@@ -9,6 +9,7 @@ var bundler = require('../../bundler.js');
var release = require('../../release.js');
var project = require('../../project.js');
var catalog = require('../../catalog.js');
var buildmessage = require('../../buildmessage.js');
var meteorNpm = require('../../meteor-npm.js');
var lastTmpDir = null;
@@ -27,11 +28,24 @@ var setAppDir = function (appDir) {
files.getCurrentToolsDir(), 'packages'));
}
catalog.complete.initialize({
localPackageDirs: localPackageDirs
doOrThrow(function () {
catalog.complete.initialize({
localPackageDirs: localPackageDirs
});
});
};
var doOrThrow = function (f) {
var ret;
var messages = buildmessage.capture(function () {
ret = f();
});
if (messages.hasMessages()) {
throw Error(messages.formatMessages());
}
return ret;
};
///
/// TEST PACKAGE DIR
///
@@ -39,7 +53,9 @@ var tmpPackageDirContainer = tmpDir();
var testPackageDir = path.join(tmpPackageDirContainer, 'test-package');
var reloadPackages = function () {
catalog.complete.refresh();
doOrThrow(function () {
catalog.complete.refresh();
});
};
var updateTestPackage = function (npmDependencies) {
@@ -383,7 +399,9 @@ var runTest = function () {
var Fiber = require('fibers');
Fiber(function () {
setAppDir(appWithPackageDir);
release._setCurrentForOldTest();
doOrThrow(function () {
release._setCurrentForOldTest();
});
meteorNpm._printNpmCalls = true;
try {

View File

@@ -29,11 +29,24 @@ var setAppDir = function (appDir) {
files.getCurrentToolsDir(), 'packages'));
}
catalog.complete.initialize({
localPackageDirs: localPackageDirs
doOrThrow(function () {
catalog.complete.initialize({
localPackageDirs: localPackageDirs
});
});
};
var doOrThrow = function (f) {
var ret;
var messages = buildmessage.capture(function () {
ret = f();
});
if (messages.hasMessages()) {
throw Error(messages.formatMessages());
}
return ret;
};
var runTest = function () {
var readManifest = function (tmpOutputDir) {
return JSON.parse(fs.readFileSync(
@@ -143,7 +156,9 @@ var runTest = function () {
var Fiber = require('fibers');
Fiber(function () {
release._setCurrentForOldTest();
doOrThrow(function () {
release._setCurrentForOldTest();
});
try {
runTest();

View File

@@ -440,7 +440,7 @@ selftest.define("release track defaults to METEOR-CORE",
var run = s.run("publish", "--create");
run.waitSecs(20);
run.matchErr("Unknown release METEOR-CORE@" + releaseVersion);
run.expectExit(8);
run.expectExit(1);
});
});

View File

@@ -20,7 +20,7 @@ selftest.define("springboard", ['checkout', 'net'], function () {
var run;
var toolsPackage;
selftest.captureAndThrow(function() {
selftest.doOrThrow(function() {
toolsPackage = selftest.getToolsPackage();
});
var toolsVersion = toolsPackage.name + '@' +
@@ -125,7 +125,7 @@ selftest.define("springboard", ['checkout', 'net'], function () {
// hackhackhack. If we clean up the hackhackhackhack, then this does not need
// the internets. (Or, to be more specific: our warehouse code tries to fetch
// the packages from the internet. If we could fool it into using local packages
// instead, or think that it alreayd has the packages, it would be ok).
// instead, or think that it already has the packages, it would be ok).
selftest.define("writing versions file", ['checkout', 'net'], function () {
var s = new Sandbox({
warehouse: {
@@ -136,8 +136,8 @@ selftest.define("writing versions file", ['checkout', 'net'], function () {
var run;
var toolsPackage;
selftest.captureAndThrow(function() {
toolsPackage = selftest.getToolsPackage();
selftest.doOrThrow(function() {
toolsPackage = selftest.getToolsPackage();
});
var toolsVersion = toolsPackage.name + '@' +
toolsPackage.version;
@@ -167,9 +167,7 @@ selftest.define("writing versions file", ['checkout', 'net'], function () {
run.expectExit(0);
versions = s.read('.meteor/versions');
if (versions) {
selftest.expectEqual(
"Versions file written with --release.",
"Versions file NOT written with --release.");
selftest.fail("Versions file written with --release.");
}
// Update with --release.
@@ -179,9 +177,7 @@ selftest.define("writing versions file", ['checkout', 'net'], function () {
// version file should exist.
versions = s.read('.meteor/versions');
if (!versions) {
selftest.expectEqual(
"Versions file NOT written after update",
"Versions file written after update.");
selftest.fail("Versions file NOT written after update");
}
});

View File

@@ -36,7 +36,7 @@ var checkMeta = function (appPackages, sessionId, useFakeRelease) {
if (useFakeRelease) {
var toolsPackage;
selftest.captureAndThrow(function() {
selftest.doOrThrow(function() {
toolsPackage = selftest.getToolsPackage();
});
expectedUserAgentInfo.meteorReleaseTrack =

View File

@@ -12,7 +12,7 @@ selftest.define("selftest-from-warehouse", ['checkout'], function () {
var run;
var toolsPackage;
selftest.captureAndThrow(function() {
selftest.doOrThrow(function() {
toolsPackage = selftest.getToolsPackage();
});
var toolsVersion = toolsPackage.name + '@' +

View File

@@ -33,16 +33,25 @@ exports.tryToDownloadUpdate = function (options) {
};
var checkForUpdate = function (showBanner) {
// XXX we should ignore errors here, right? but still do the "can we update
// this app with a locally available release" check.
catalog.official.refresh();
var messages = buildmessage.capture(function () {
catalog.official.refresh();
if (!release.current.isProperRelease())
if (!release.current.isProperRelease())
return;
updateMeteorToolSymlink();
maybeShowBanners();
});
if (messages.hasMessages()) {
// Ignore, since running in the background.
// XXX unfortunately the "can't refresh" message still prints :(
// XXX But maybe if it's just a "we're offline" message we should keep
// going? In case we want to present the "hey there's a locally
// available recommended release?
return;
updateMeteorToolSymlink();
maybeShowBanners();
}
};
var maybeShowBanners = function () {
@@ -120,6 +129,8 @@ var maybeShowBanners = function () {
// Update ~/.meteor/meteor to point to the tool binary from the tools of the
// latest recommended release on the default release track.
var updateMeteorToolSymlink = function () {
buildmessage.assertInCapture();
// Get the latest release version of METEOR-CORE. (*Always* of the default
// track, not of whatever we happen to be running: we always want the tool
// symlink to go to the default track.)