merging packaging into uvf

This commit is contained in:
ekatek
2014-05-28 13:26:48 -07:00
15 changed files with 330 additions and 205 deletions

View File

@@ -3,19 +3,14 @@ var Fiber = Npm.require('fibers');
var Future = Npm.require(path.join('fibers', 'future'));
Meteor._noYieldsAllowed = function (f) {
// "Fiber" and "yield" are both in the global namespace. The yield function is
// at both "yield" and "Fiber.yield". (It's also at require('fibers').yield
// but that is because require('fibers') === Fiber.)
var savedYield = Fiber.yield;
Fiber.yield = function () {
throw new Error("Can't call yield in a noYieldsAllowed block!");
};
global.yield = Fiber.yield;
try {
return f();
} finally {
Fiber.yield = savedYield;
global.yield = savedYield;
}
};

View File

@@ -232,6 +232,7 @@ _.extend(CompleteCatalog.prototype, {
// project root path has not been initialized, we are probably running
// outside of a project, and have nothing to look at for guidance.
if (opts.ignoreProjectDeps || !project.rootDir) {
console.log("ignore project deps & resolve");
return self.resolver.resolve(deps, constr, resolverOpts);
}

View File

@@ -308,8 +308,9 @@ main.registerCommand({
// at the end.)
if (! release.current.isCheckout() &&
release.current.name !== release.latestDownloaded() &&
! release.forced)
! release.forced) {
throw new main.SpringboardToLatestRelease;
}
var exampleDir = path.join(__dirname, '..', 'examples');
var examples = _.reject(fs.readdirSync(exampleDir), function (e) {
@@ -425,18 +426,28 @@ main.registerCommand({
return 1;
}
// Unless --release was passed (meaning that either the user asked for a
// particular release, or that we _just did_ this and springboarded at
// #UpdateSpringboard), go get the latest release and switch to it. (We
// already know what the latest release is because we refreshed the catalog
// above.)
// This is the release track we'll end up on --- either because it's
// the explicitly specified (with --release) track; or because we
// didn't specify a release and it's the app's current release (if we're
// in an app dir), since non-forced updates don't change the track.
// XXX better error checking on release.current.name
// XXX add a method to release.current
var releaseTrack = release.current.getReleaseTrack();
// Unless --release was passed (in which case we ought to already have
// springboarded to that release), go get the latest release and switch to
// it. (We already know what the latest release is because we refreshed the
// catalog above.) Note that after springboarding, we will hit this again
// (because springboarding to a specific release does NOT set release.forced),
// but it should be a no-op next time (unless there actually was a new latest
// release in the interim).
if (! release.forced) {
if (! release.current ||
release.current.name !== release.latestDownloaded()) {
release.current.name !== release.latestDownloaded(releaseTrack)) {
// The user asked for the latest release (well, they "asked for it" by not
// passing --release). We're not currently running the latest release (we
// may have even just learned about it). #UpdateSpringboard
throw new main.SpringboardToLatestRelease;
// passing --release). We're not currently running the latest release on
// this track (we may have even just learned about it). #UpdateSpringboard
throw new main.SpringboardToLatestRelease(releaseTrack);
}
}
@@ -449,7 +460,7 @@ main.registerCommand({
// If we're not in an app, then we're done (other than maybe printing some
// stuff).
if (! options.appDir) {
if (release.forced) {
if (release.forced || process.env.METEOR_SPRINGBOARD_RELEASE) {
// We get here if:
// 1) the user ran 'meteor update' and we found a new version
// 2) the user ran 'meteor update --release xyz' (regardless of
@@ -457,7 +468,9 @@ main.registerCommand({
//
// In case (1), we downloaded and installed the update and then
// we springboarded (at #UpdateSpringboard above), causing
// release.forced to be true.
// $METEOR_SPRINGBOARD_RELEASE to be true.
// XXX probably should have a better interface than looking directly
// at the env var here
//
// In case (2), we downloaded, installed, and springboarded to
// the requested release in the initialization code, before the
@@ -487,12 +500,6 @@ main.registerCommand({
// Otherwise, we have to upgrade the app too, if the release changed.
var appRelease = project.getMeteorReleaseVersion();
if (appRelease !== null && appRelease === release.current.name) {
// Note that in this case, release.forced is true iff --release was actually
// passed on the command-line: #UpdateSpringboard can't have occured. Why?
// Well, if the user didn't specify --release but we're in an app, then
// release.current.name must have been taken from the app, and
// #UpdateSpringboard only happens if needs to try to change the app
// release, and this is the message for not needing to change the release.
var maybeTheLatestRelease = release.forced ? "" : ", the latest release";
var maybeOnThisComputer =
couldNotContactServer ? "\ninstalled on this computer" : "";
@@ -504,6 +511,7 @@ main.registerCommand({
// OK, let's figure out what release fits with our package constraints!
<<<<<<< HEAD
// XXX this will actually be a loop over possible releases in the non-force
// case
// XXX better error checking on name
@@ -534,76 +542,148 @@ main.registerCommand({
// XXX did we have to change some package versions? we should probably
// mention that fact.
// XXX error handling.
// Find upgraders (in order) necessary to upgrade the app for the new
// release (new metadata file formats, etc, or maybe even updating renamed
// APIs).
//
// * If this is a pre-engine app with no .meteor/release file, run
// all upgraders.
// * If the app didn't have a release because it was created by a
// checkout, don't run any upgraders.
//
// We're going to need the list of upgraders from the old release
// (the release the app was using previously) to decide what
// upgraders to run. It's possible that we don't have it downloaded
// yet (if they checked out the project and immediately ran 'meteor
// update --release foo'), so it's important to do this before we
// actually update the project.
var upgradersToRun;
if (appRelease === "none") {
upgradersToRun = [];
=======
var releaseVersionsToTry;
if (release.forced) {
releaseVersionsToTry = [release.current.getReleaseVersion()];
} else {
var oldUpgraders;
if (appRelease === null) {
oldUpgraders = [];
} else {
try {
var oldRelease = release.load(appRelease);
} catch (e) {
if (e instanceof files.OfflineError) {
process.stderr.write(
"You need to be online to do this. Please check your internet connection.\n");
return 1;
}
if (e instanceof warehouse.NoSuchReleaseError) {
// In this situation it's tempting to just print a warning and
// skip the updaters, but I can't figure out how to explain
// what's happening to the user, so let's just do this.
process.stderr.write(
"This project says that it uses version " + appRelease + " of Meteor, but you\n" +
"don't have that version of Meteor installed and the Meteor update servers\n" +
"don't have it either. Please edit the .meteor/release file in the project\n" +
"project and change it to a valid Meteor release.\n");
return 1;
}
throw e;
}
oldUpgraders = oldRelease.getUpgraders();
// XXX clean up all this splitty stuff
var appReleaseInfo = catalog.getReleaseVersion(
appRelease.split('@')[0], appRelease.split('@')[1]);
var appOrderKey = (appReleaseInfo && appReleaseInfo.orderKey) || null;
releaseVersionsToTry = catalog.getSortedRecommendedReleaseVersions(
releaseTrack, appOrderKey);
if (!releaseVersionsToTry.length) {
// XXX make error better, and make sure that the "already there" error
// above truly does cover every other case
var maybeOnThisComputer =
couldNotContactServer ? "\ninstalled on this computer" : "";
console.log(
"This project is already at Meteor %s, which is newer than the latest release%s.",
appRelease, maybeOnThisComputer);
return;
}
upgradersToRun = _.difference(release.current.getUpgraders(), oldUpgraders);
}
// Write the release to .meteor/release.
project.writeMeteorReleaseVersion(release.current.name);
// Now run the upgraders.
_.each(upgradersToRun, function (upgrader) {
require("./upgraders.js").runUpgrader(upgrader, options.appDir);
var solutionPackageVersions = null;
var directDependencies = project.getDirectDependencies(options.appDir);
var previousVersions = project.getIndirectDependencies(options.appDir);
var solutionReleaseVersion = _.find(releaseVersionsToTry, function (versionToTry) {
var releaseRecord = catalog.getReleaseVersion(releaseTrack, versionToTry);
if (!releaseRecord)
throw Error("missing release record?");
var constraints = project.combinedConstraints(
directDependencies, releaseRecord.packages);
try {
solutionPackageVersions = catalog.resolveConstraints(
constraints, { previousSolution: previousVersions });
} catch (e) {
// XXX we should make the error handling explicitly detectable, and not
// actually mention failures that are recoverable
process.stderr.write(
"XXX Update to release " + releaseTrack +
"@" + versionToTry + " impossible: " + e.message + "\n");
return false;
}
return true;
});
if (!solutionReleaseVersion) {
// XXX put an error here when we stop doing an error on every failure above
return 1;
}
var solutionReleaseName = releaseTrack + '@' + solutionReleaseVersion;
// We could at this point springboard to solutionRelease (which is no newer
// than the release we are currently running), but there's no clear advantage
// to this yet. The main reason might be if we decide to delete some
// backward-compatibility code which knows how to deal with an older release,
// but if we actually do that, we can change this code to add the extra
// springboard at that time.
// XXX did we have to change some package versions? we should probably
// mention that fact.
// XXX reimplement upgraders (or don't, until we need them).
// // Find upgraders (in order) necessary to upgrade the app for the new
// // release (new metadata file formats, etc, or maybe even updating renamed
// // APIs).
// //
// // * If this is a pre-engine app with no .meteor/release file, run
// // all upgraders.
// // * If the app didn't have a release because it was created by a
// // checkout, don't run any upgraders.
// //
// // We're going to need the list of upgraders from the old release
// // (the release the app was using previously) to decide what
// // upgraders to run. It's possible that we don't have it downloaded
// // yet (if they checked out the project and immediately ran 'meteor
// // update --release foo'), so it's important to do this before we
// // actually update the project.
// var upgradersToRun;
// if (appRelease === "none") {
// upgradersToRun = [];
// } else {
// var oldUpgraders;
// if (appRelease === null) {
// oldUpgraders = [];
// } else {
// try {
// var oldRelease = release.load(appRelease);
// } catch (e) {
// if (e instanceof files.OfflineError) {
// process.stderr.write(
// "You need to be online to do this. Please check your internet connection.\n");
// return 1;
// }
// if (e instanceof warehouse.NoSuchReleaseError) {
// // In this situation it's tempting to just print a warning and
// // skip the updaters, but I can't figure out how to explain
// // what's happening to the user, so let's just do this.
// process.stderr.write(
// "This project says that it uses version " + appRelease + " of Meteor, but you\n" +
// "don't have that version of Meteor installed and the Meteor update servers\n" +
// "don't have it either. Please edit the .meteor/release file in the project\n" +
// "project and change it to a valid Meteor release.\n");
// return 1;
// }
// throw e;
// }
// oldUpgraders = oldRelease.getUpgraders();
// }
// // XXX release.current needs to be replaced with solutionReleaseName
// upgradersToRun = _.difference(release.current.getUpgraders(), oldUpgraders);
// }
// Write the new versions to .meteor/packages and .meteor/versions.
project.setDependencies(options.appDir, directDependencies.appDeps,
solutionPackageVersions);
// Write the release to .meteor/release.
project.writeMeteorReleaseVersion(solutionReleaseName);
// XXX redo upgrader support
// // Now run the upgraders.
// _.each(upgradersToRun, function (upgrader) {
// require("./upgraders.js").runUpgrader(upgrader, options.appDir);
// });
// This is the right spot to do any other changes we need to the app in
// order to update it for the new release.
console.log("%s: updated to Meteor %s.",
path.basename(options.appDir), release.current.name);
path.basename(options.appDir), solutionReleaseName);
// Print any notices relevant to this upgrade.
// XXX This doesn't include package-specific notices for packages that
// are included transitively (eg, packages used by app packages).
var packages = project.getConstraints();
// var packages = project.getPackages(options.appDir);
// XXX reimplement "notices" for tropohouse
// warehouse.printNotices(appRelease, release.current.name, packages);
});
@@ -839,6 +919,7 @@ main.registerCommand({
}
});
// Get the contents of our versions file, we will want them in order to remove
// to the user what we removed.
var versions = project.getVersions();

View File

@@ -124,9 +124,7 @@ _.extend(exports, {
return process.env.METEOR_PACKAGE_SERVER_URL;
var host = config.getPackageServerDomain();
console.log("XXX: currently using http, not https for package server.");
return "http://" + host;
// return addScheme(host);
return addScheme(host);
},
getPackageServerDomain: function () {

View File

@@ -76,3 +76,16 @@ exports.waitForOne = function (/* futures */) {
return combinedFuture.wait();
};
exports.noYieldsAllowed = function (f) {
var savedYield = Fiber.yield;
Fiber.yield = function () {
throw new Error("Can't call yield in a noYieldsAllowed block!");
};
try {
return f();
} finally {
Fiber.yield = savedYield;
}
};

View File

@@ -595,6 +595,14 @@ files.writeFileAtomically = function (filename, contents) {
fs.renameSync(tmpFile, filename);
};
// Like fs.symlinkSync, but creates a temporay link and renames it over the
// file; this means it works even if the file already exists.
files.symlinkOverSync = function (linkText, file) {
var tmpSymlink = file + ".tmp" + utils.randomToken();
fs.symlinkSync(linkText, tmpSymlink);
fs.renameSync(tmpSymlink, file);
};
// Run a program synchronously and, assuming it returns success (0),
// return whatever it wrote to stdout, as a string. Otherwise (if it
// did not exit gracefully and return 0) return null. As node has

View File

@@ -80,7 +80,11 @@ main.WaitForExit = function () {};
// Exception to throw from a command to exit, restart, and reinvoke
// the command with the latest available (downloaded) Meteor release.
main.SpringboardToLatestRelease = function () {};
// If track is specified, it uses the latest available in the given
// track instead of the default track.
main.SpringboardToLatestRelease = function (track) {
this.track = track;
};
// Register a command-line command.
//
@@ -632,6 +636,7 @@ Fiber(function () {
// #ImprovingCrossVersionOptionParsing.
var releaseOverride = null;
var releaseForced = false;
if (_.has(rawOptions, '--release')) {
if (rawOptions['--release'].length > 1) {
process.stderr.write(
@@ -640,6 +645,7 @@ Fiber(function () {
process.exit(1);
}
releaseOverride = rawOptions['--release'][0];
releaseForced = true;
if (! releaseOverride) {
process.stderr.write(
"The --release option needs a value.\n" +
@@ -650,6 +656,12 @@ Fiber(function () {
}
if (_.has(process.env, 'METEOR_SPRINGBOARD_RELEASE')) {
// See #SpringboardEnvironmentVar
// Note that this does *NOT* cause release.forced to be true.
// release.forced should only be set when the user actually
// ran with --release, not just because (eg) they ran
// 'meteor update' and we springboarded to the latest release.
// (It's important that 'meteor update' be able to tell these
// conditions apart even after the springboard!)
releaseOverride = process.env['METEOR_SPRINGBOARD_RELEASE'];
}
@@ -702,7 +714,7 @@ Fiber(function () {
}
} else {
// Run outside an app dir with no --release flag. Use the latest
// release we know about.
// release we know about (in the default track).
releaseName = release.latestDownloaded();
}
}
@@ -743,7 +755,7 @@ Fiber(function () {
throw e;
}
release.setCurrent(rel, /* forced */ !! releaseOverride);
release.setCurrent(rel, releaseForced);
}
// If we're not running the correct version of the tools for this
@@ -1054,7 +1066,7 @@ commandName + ": You're not in a Meteor package directory.\n");
if (e instanceof main.SpringboardToLatestRelease) {
// Load the latest release's metadata so that we can figure out
// the tools version that it uses.
var latestRelease = release.load(release.latestDownloaded());
var latestRelease = release.load(release.latestDownloaded(e.track));
springboard(latestRelease, latestRelease.name);
// (does not return)
}

View File

@@ -100,6 +100,7 @@ var Project = function () {
self._depsUpToDate = false;
};
<<<<<<< HEAD
_.extend(Project.prototype, {
// Set a given root directory as the project's root directory. Figure out all
// relevant file paths and read in data that is independent of the constraint

View File

@@ -37,6 +37,20 @@ _.extend(Release.prototype, {
return this.name === null;
},
getReleaseTrack: function () {
var self = this;
if (! self.isProperRelease())
throw new Error("not a proper release?");
return self.name.split('@')[0];
},
getReleaseVersion: function () {
var self = this;
if (! self.isProperRelease())
throw new Error("not a proper release?");
return self.name.split('@')[1];
},
// Return the package name for the command-line tools that this release
// uses. Valid only for proper releases.
getToolsPackage: function () {
@@ -161,14 +175,17 @@ release.usingRightReleaseForApp = function () {
// Return the name of the latest release that is downloaded and ready
// for use. May not be called when running from a checkout.
release.latestDownloaded = function () {
// 'track' is optional (it defaults to the default track).
release.latestDownloaded = function (track) {
if (! files.usesWarehouse())
throw new Error("called from checkout?");
// For self-test only.
if (process.env.METEOR_TEST_LATEST_RELEASE)
return process.env.METEOR_TEST_LATEST_RELEASE;
var defaultRelease = catalog.official.getDefaultReleaseVersion();
if (!defaultRelease) {
throw new Error("no latest release available?");
}

View File

@@ -167,7 +167,6 @@ selftest.define("add packages", function () {
run = s.run("--once");
run = s.run("add", "say-something@1.0.0", "--offline-catalog");
run.match("Successfully added");
checkPackages(s,

View File

@@ -184,5 +184,17 @@ _.extend(exports.Tropohouse.prototype, {
unipackage.saveToPath(packageDir);
return true;
},
latestMeteorSymlink: function () {
var self = this;
var path = path.join(self.root, 'meteor');
return fs.readlinkSync(path);
},
replaceLatestMeteorSymlink: function (linkText) {
var self = this;
var path = path.join(self.root, 'meteor');
files.symlinkOverSync(linkText, path);
}
});

View File

@@ -336,7 +336,7 @@ _.extend(Unipackage.prototype, {
// recover by returning by no builds
return null;
}
return _.where(self.builds, { arch: chosenArch })[0];
return _.findWhere(self.builds, { arch: chosenArch });
},
// Load this package's plugins into memory, if they haven't already

View File

@@ -1,31 +1,15 @@
var path = require('path');
var inFiber = require('./fiber-helpers.js').inFiber;
var files = require('./files.js');
var warehouse = require('./warehouse.js');
var tropohouse = require('./tropohouse.js');
var httpHelpers = require('./http-helpers.js');
var config = require('./config.js');
var release = require('./release.js');
var runLog = require('./run-log.js');
/**
* Downloads the current manifest file and returns it. Throws
* files.OfflineError if we are offline, or throws some other
* exception if the server turned down our request.
*/
exports.getManifest = function () {
// Automated self-test support. You can set an environment variable
// to stub out the manifest fetch with a particular value, or to
// throw OfflineError.
if (process.env.METEOR_TEST_UPDATE_MANIFEST === "offline")
throw new files.OfflineError(new Error("scripted failure for tests"));
if (process.env.METEOR_TEST_UPDATE_MANIFEST)
return JSON.parse(process.env.METEOR_TEST_UPDATE_MANIFEST);
return httpHelpers.getUrl({
url: config.getUpdateManifestUrl(),
json: true,
useSessionHeader: true
});
};
var catalog = require('./catalog.js');
var archinfo = require('./archinfo.js');
var unipackage = require('./unipackage.js');
var utils = require('./utils.js');
/**
* Check to see if an update is available. If so, download and install
@@ -42,69 +26,107 @@ exports.tryToDownloadUpdate = function (options) {
if (checkInProgress)
return;
checkInProgress = true;
check(!!options.showBanner);
checkForUpdate(!!options.showBanner);
checkInProgress = false;
};
var check = function (showBanner) {
var manifest = null;
try {
manifest = exports.getManifest();
} catch (e) {
// Ignore error (eg, offline), but still do the "can we update this app
// with a locally available release" check.
}
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.serverCatalog.refresh(true);
if (!files.usesWarehouse())
if (!release.isProperRelease())
return;
// XXX in the future support release channels other than stable
var manifestLatestRelease =
manifest && manifest.releases && manifest.releases.stable &&
manifest.releases.stable.version;
var localLatestRelease = warehouse.latestRelease();
if (manifestLatestRelease && manifestLatestRelease !== localLatestRelease) {
// The manifest is telling us about a release that isn't our latest
// release! First, print a banner... but only if we've never printed a
// banner for this release before. (Or, well... only if this release isn't
// the last release which has had a banner printed.)
if (manifest.releases.stable.banner &&
warehouse.lastPrintedBannerRelease() !== manifestLatestRelease) {
if (showBanner) {
runLog.log("");
runLog.log(manifest.releases.stable.banner);
runLog.log("");
}
warehouse.writeLastPrintedBannerRelease(manifestLatestRelease);
} else {
// Already printed this banner, or maybe there is no banner.
if (showBanner) {
runLog.log("=> Meteor " + manifestLatestRelease +
" is being downloaded in the background.");
}
}
warehouse.fetchLatestRelease();
// We should now have fetched the latest release, which *probably* is
// manifestLatestRelease. As long as it's changed from the one it was
// before we tried to fetch it, print that out.
var newLatestRelease = warehouse.latestRelease();
if (showBanner && newLatestRelease !== localLatestRelease) {
runLog.log(
"=> Meteor " + newLatestRelease +
" is available. Update this project with 'meteor update'.");
}
var currentReleaseTrack = release.current.getTrack();
var latestRelease = catalog.serverCatalog.getDefaultRelease(
currentReleaseTrack);
// Maybe you're on some random track with nothing recommended. That's OK.
if (!latestRelease)
return;
var latestReleaseToolParts = latestRelease.tool.split('@');
var latestReleaseToolPackage = latestReleaseToolParts[0];
var latestReleaseToolVersion = latestReleaseToolParts[1];
var relativeToolPath = tropohouse.default.packagePath(
latestReleaseToolPackage, latestReleaseToolVersion, true);
var localLatestReleaseLink = tropohouse.default.latestMeteorSymlink();
if (utils.startsWith(localLatestReleaseLink, relativeToolPath + path.sep)) {
// The latest release from the catalog is not where the ~/.meteor0/meteor
// symlink points to. Let's make sure we have that release on disk,
// and then update the symlink.
// XXX download the packages too?
tropohouse.default.maybeDownloadPackageForArchitectures(
{packageName: latestReleaseToolPackage,
version: latestReleaseToolVersion},
[archinfo.host()]);
var toolUnipackage = new unipackage.Unipackage;
toolUnipackage.initFromPath(
latestReleaseToolPackage,
tropohouse.default.packagePath(latestReleaseToolPackage,
latestReleaseToolVersion));
var toolRecord = _.findWhere(toolUnipackage.toolsOnDisk,
{arch: archinfo.host()});
// XXX maybe we shouldn't throw from this background thing
if (!toolRecord)
throw Error("latest release has no tool?");
console.log("XXX updating tool symlink for",
latestRelease.track + "@" + latestRelease.version);
tropohouse.default.replaceLatestMeteorSymlink(
path.join(relativeToolPath, toolRecord.path, 'meteor'));
}
// We didn't do a global update (or we're not online), but do we need to
// update this app? Specifically: is our local latest release something
// other than this app's release, and the user didn't specify a specific
// release at the command line with --release?
if (showBanner &&
localLatestRelease !== release.current.name &&
! release.forced) {
runLog.log(
"=> Meteor " + localLatestRelease +
" is available. Update this project with 'meteor update'.");
}
// XXX print banners
// var manifestLatestRelease =
// manifest && manifest.releases && manifest.releases.stable &&
// manifest.releases.stable.version;
// var localLatestRelease = warehouse.latestRelease();
// if (manifestLatestRelease && manifestLatestRelease !== localLatestRelease) {
// // The manifest is telling us about a release that isn't our latest
// // release! First, print a banner... but only if we've never printed a
// // banner for this release before. (Or, well... only if this release isn't
// // the last release which has had a banner printed.)
// if (manifest.releases.stable.banner &&
// warehouse.lastPrintedBannerRelease() !== manifestLatestRelease) {
// if (showBanner) {
// runLog.log("");
// runLog.log(manifest.releases.stable.banner);
// runLog.log("");
// }
// warehouse.writeLastPrintedBannerRelease(manifestLatestRelease);
// } else {
// // Already printed this banner, or maybe there is no banner.
// if (showBanner) {
// runLog.log("=> Meteor " + manifestLatestRelease +
// " is being downloaded in the background.");
// }
// }
// warehouse.fetchLatestRelease();
// // We should now have fetched the latest release, which *probably* is
// // manifestLatestRelease. As long as it's changed from the one it was
// // before we tried to fetch it, print that out.
// var newLatestRelease = warehouse.latestRelease();
// if (showBanner && newLatestRelease !== localLatestRelease) {
// runLog.log(
// "=> Meteor " + newLatestRelease +
// " is available. Update this project with 'meteor update'.");
// }
// return;
// }
// // We didn't do a global update (or we're not online), but do we need to
// // update this app? Specifically: is our local latest release something
// // other than this app's release, and the user didn't specify a specific
// // release at the command line with --release?
// if (showBanner &&
// localLatestRelease !== release.current.name &&
// ! release.forced) {
// runLog.log(
// "=> Meteor " + localLatestRelease +
// " is available. Update this project with 'meteor update'.");
// }
};

View File

@@ -273,4 +273,9 @@ exports.isDirectory = function (dir) {
return false;
}
return stats.isDirectory();
// XXX from Underscore.String (http://epeli.github.com/underscore.string/)
exports.startsWith = function(str, starts) {
return str.length >= starts.length &&
str.substring(0, starts.length) === starts;
};

View File

@@ -34,14 +34,6 @@ var fiberHelpers = require('./fiber-helpers.js');
var WAREHOUSE_URLBASE = 'https://warehouse.meteor.com';
// Like fs.symlinkSync, but creates a temporay link and renames it over the
// file; this means it works even if the file already exists.
var symlinkOverSync = function (linkText, file) {
var tmpSymlink = file + ".tmp" + utils.randomToken();
fs.symlinkSync(linkText, tmpSymlink);
fs.renameSync(tmpSymlink, file);
};
var warehouse = exports;
_.extend(warehouse, {
// An exception meaning that you asked for a release that doesn't
@@ -122,37 +114,6 @@ _.extend(warehouse, {
}
},
// returns true if we updated the latest symlink
// XXX make errors prettier
fetchLatestRelease: function (options) {
options = options || {};
var manifest = updater.getManifest();
// XXX in the future support release channels other than stable
var releaseName = manifest && manifest.releases &&
manifest.releases.stable && manifest.releases.stable.version;
if (! releaseName)
throw new Error("no stable release found?");
var latestReleaseManifest = warehouse._populateWarehouseForRelease(
releaseName, !!options.showInstalling);
// First, make sure the latest tools symlink reflects the latest installed
// release.
if (latestReleaseManifest.tools !== warehouse.latestTools()) {
symlinkOverSync(latestReleaseManifest.tools,
warehouse._latestToolsSymlinkPath());
}
var storedLatestRelease = warehouse.latestRelease();
if (storedLatestRelease === releaseName)
return false;
symlinkOverSync(releaseName + '.release.json',
warehouse._latestReleaseSymlinkPath());
return true;
},
packageExistsInWarehouse: function (name, version) {
// A package exists if its directory exists. (We used to look for a
// particular file name ("package.js") inside the directory, but since we