Merge pull request #9234 from meteor/windows-springboarding-subtleties

[WIP] Automatically switch between 64- and 32-bit Windows builds.
This commit is contained in:
Ben Newman
2017-10-16 08:40:46 -04:00
committed by GitHub
4 changed files with 107 additions and 41 deletions

View File

@@ -15,6 +15,7 @@ var projectContextModule = require('../project-context.js');
var catalog = require('../packaging/catalog/catalog.js');
var buildmessage = require('../utils/buildmessage.js');
var httpHelpers = require('../utils/http-helpers.js');
const archinfo = require('../utils/archinfo.js');
var main = exports;
@@ -425,44 +426,44 @@ var springboard = function (rel, options) {
console.log("WILL SPRINGBOARD TO", rel.getToolsPackageAtVersion());
}
var archinfo = require('../utils/archinfo.js');
var isopack = require('../isobuild/isopack.js');
const toolsPkg = rel.getToolsPackage();
const toolsVersion = rel.getToolsVersion();
const serverArchitectures = catalog.official.filterArchesWithBuilds(
toolsPkg,
toolsVersion,
archinfo.acceptableMeteorToolArches(),
);
var toolsPkg = rel.getToolsPackage();
var toolsVersion = rel.getToolsVersion();
var packageMapModule = require('../packaging/package-map.js');
var versionMap = {};
versionMap[toolsPkg] = toolsVersion;
var packageMap = new packageMapModule.PackageMap(versionMap);
if (serverArchitectures.length === 0) {
var release = catalog.official.getDefaultReleaseVersion();
var releaseName = release.track + "@" + release.version;
if (process.platform === "win32") {
// Make sure the tool we are trying to download has been built for Windows
var buildsForHostArch = catalog.official.getBuildsForArches(
rel.getToolsPackage(), rel.getToolsVersion(), [archinfo.host()]);
Console.error(
"This project uses " + rel.getDisplayName() + ", which isn't",
"available on this platform. To work with this app on all supported",
"platforms, use", Console.command("meteor update --release " + releaseName),
"to pin this app to the newest compatible release."
);
if (! buildsForHostArch) {
var release = catalog.official.getDefaultReleaseVersion();
var releaseName = release.track + "@" + release.version;
Console.error(
"This project uses " + rel.getDisplayName() + ", which isn't",
"available on Windows. To work with this app on all supported",
"platforms, use", Console.command("meteor update --release " + releaseName),
"to pin this app to the newest Windows-compatible release.");
process.exit(1);
}
process.exit(1);
}
const packageMapModule = require('../packaging/package-map.js');
const packageMap = new packageMapModule.PackageMap({
[toolsPkg]: toolsVersion,
});
// XXX split better
Console.withProgressDisplayVisible(function () {
var messages = buildmessage.capture(
{ title: "downloading the command-line tool" }, function () {
catalog.runAndRetryWithRefreshIfHelpful(function () {
tropohouse.default.downloadPackagesMissingFromMap(packageMap);
var messages = buildmessage.capture({
title: "downloading the command-line tool"
}, function () {
catalog.runAndRetryWithRefreshIfHelpful(function () {
tropohouse.default.downloadPackagesMissingFromMap(packageMap, {
serverArchitectures,
});
}
);
});
});
if (messages.hasMessages()) {
// We have failed to download the tool that we are supposed to springboard
@@ -482,16 +483,32 @@ var springboard = function (rel, options) {
}
});
var packagePath = tropohouse.default.packagePath(toolsPkg, toolsVersion);
var toolIsopack = new isopack.Isopack;
const isopack = require('../isobuild/isopack.js');
const packagePath = tropohouse.default.packagePath(toolsPkg, toolsVersion);
const toolIsopack = new isopack.Isopack;
toolIsopack.initFromPath(toolsPkg, packagePath);
var toolRecord = _.findWhere(toolIsopack.toolsOnDisk,
{arch: archinfo.host()});
let toolRecord = null;
serverArchitectures.some(arch => {
return toolRecord = _.findWhere(toolIsopack.toolsOnDisk, { arch });
});
if (!toolRecord) {
throw Error("missing tool for " + archinfo.host() + " in " +
toolsPkg + "@" + toolsVersion);
}
var executable = files.pathJoin(packagePath, toolRecord.path, 'meteor');
const newToolsDir = files.pathJoin(packagePath, toolRecord.path);
if (files.realpath(newToolsDir) ===
files.realpath(files.getCurrentToolsDir())) {
if (options.mayReturn) {
// Return instead of springboarding, if we are allowed to keep using
// the current tools without restarting the process.
return;
}
}
const executable = files.pathJoin(newToolsDir, "meteor");
// Strip off the "node" and "meteor.js" from argv and replace it with the
// appropriate tools's meteor shell script.
@@ -1129,10 +1146,23 @@ Fiber(function () {
// update, because the correct tools version will have been chosen
// the first time around. It will also never happen if the current
// release is a checkout, because that doesn't make any sense.
if (release.current && release.current.isProperRelease() &&
release.current.getToolsPackageAtVersion() !== files.getToolsVersion()) {
springboard(release.current, { fromApp: releaseFromApp });
// Does not return!
if (release.current &&
release.current.isProperRelease()) {
if (files.getToolsVersion() !==
release.current.getToolsPackageAtVersion()) {
springboard(release.current, {
fromApp: releaseFromApp,
mayReturn: false,
})
// Does not return!
} else if (archinfo.canSwitchTo64Bit()) {
springboard(release.current, {
fromApp: releaseFromApp,
// Switching to a 64-bit meteor-tool build may fail, in which case
// we should continue on as usual.
mayReturn: true,
});
}
}
// Check for the '--help' option.

View File

@@ -640,6 +640,12 @@ _.extend(RemoteCatalog.prototype, {
return solution; // might be null!
},
filterArchesWithBuilds: function (name, version, arches) {
return arches.filter(arch => {
return !! this.getBuildsForArches(name, version, [arch]);
});
},
// Returns general (non-version-specific) information about a
// release track, or null if there is no such release track.
getReleaseTrack: function (name) {

View File

@@ -201,8 +201,11 @@ export function updateMeteorToolSymlink(printErrors) {
latestReleaseToolPackage,
tropohouse.default.packagePath(latestReleaseToolPackage,
latestReleaseToolVersion));
var toolRecord = _.findWhere(toolIsopack.toolsOnDisk,
{arch: archinfo.host()});
var toolRecord = null;
archinfo.acceptableMeteorToolArches().some(arch => {
return toolRecord = _.findWhere(toolIsopack.toolsOnDisk, { arch });
});
// XXX maybe we shouldn't throw from this background thing
// counter: this is super weird and should never ever happen.

View File

@@ -182,6 +182,33 @@ var host = function () {
return _host;
};
// In order to springboard to earlier Meteor releases that did not have
// 64-bit Windows builds, Windows installations must be allowed to
// download 32-bit builds of meteor-tool.
exports.acceptableMeteorToolArches = function () {
if (os.platform() === "win32") {
switch (utils.architecture()) {
case "x86_32":
return ["os.windows.x86_32"];
case "x86_64":
return [
"os.windows.x86_64",
"os.windows.x86_32",
];
}
}
return [host()];
};
// 64-bit Windows machines that have been using a 32-bit version of Meteor
// are eligible to switch to 64-bit beginning with Meteor 1.6, which is
// the first version of Meteor that contains this code.
exports.canSwitchTo64Bit = function () {
return utils.architecture() === "x86_64" &&
host === "os.windows.x86_32";
};
// True if `host` (an architecture name such as 'os.linux.x86_64') can run
// programs of architecture `program` (which might be something like 'os',
// 'os.linux', or 'os.linux.x86_64').