Files
meteor/tools/cli/dev-bundle.js
Jesse Rosenberger 0dac129770 Introduce os.windows.x86_64 architecture for 64-bit Windows.
This commit reverts much of the work @hwillson had put in place for
meteor/meteor#9173, which made it possible for 32-bit and 64-bit
Mongo versions to exist in harmony within the same dev-bundle.  That
hard work was not in vein though as it offered invaluable research.
Ultimately, this showed that a more aggressive approach would be ideal,
even if the proposed option would have worked great in the short-term.

In the wake of the news that Mongo would no longer be supporting 32-bit
versions, these changes are important so 32-bit users of Meteor can
continue to have a functioning Mongo binary in development, while still
allowing Meteor to ship newer Mongo (e.g. 3.4+) binaries for 64-bit
users.  This is particularly relevant for Windows users, who have
previously only had 32-bit Meteor builds and represented a majority of
"32-bit" development, despite the fact most of their hosts supported
64-bit.  During another time in Meteor's life, this made sense.

This commit takes improved functionality to the next level (and makes
the aforementioned changes obsolete) by introducing support for building
and shipping Meteor for Windows in a 64-bit flavor (in addition to
32-bit), which will hopefully solve a number of performance matters on
Windows by using binaries which are pre-compiled for 64-bit, rather than
forcing the Windows kernel to deal with 32-bit binaries.  While Windows
has shown it's quite capable of dealing with such a situation, it seems
more and more clear (given improvements in underlying dependencies) that
performance gains could be had by freeing Windows of its 32-bit work.

This commit also further perpetuates the "archinfo" plot-line with more
story (about Windows) and various spelling corrections.
2017-10-14 13:36:29 -04:00

213 lines
4.6 KiB
JavaScript

// Note that this file is required before we install our Babel hooks in
// ../tool-env/install-babel.js, so we can't use ES2015+ syntax here.
// This file replicates some functionality from elsewhere in tools code,
// but that's unavoidable if we don't want to install Babel and load all
// the rest of the code every time we run `meteor npm` or `meteor node`.
var fs = require("fs");
var path = require("path");
var links = require("./dev-bundle-links.js");
var rootDir = path.resolve(__dirname, "..", "..");
var defaultDevBundlePromise =
Promise.resolve(path.join(rootDir, "dev_bundle"));
function getDevBundleDir() {
// Note that this code does not care if we are running meteor from a
// checkout, because it's always better to respect the .meteor/release
// file of the current app, if possible.
var releaseFile = find(
process.cwd(),
makeStatTest("isFile"),
".meteor", "release"
);
if (! releaseFile) {
return defaultDevBundlePromise;
}
var localDir = path.join(path.dirname(releaseFile), "local");
if (! statOrNull(localDir, "isDirectory")) {
try {
fs.mkdirSync(localDir);
} catch (e) {
return defaultDevBundlePromise;
}
}
var devBundleLink = path.join(localDir, "dev_bundle");
var devBundleStat = statOrNull(devBundleLink);
if (devBundleStat) {
return new Promise(function (resolve) {
resolve(links.readLink(devBundleLink));
});
}
var release = fs.readFileSync(
releaseFile, "utf8"
).replace(/^\s+|\s+$/g, "");
if (! /^METEOR@\d+/.test(release)) {
return defaultDevBundlePromise;
}
return Promise.resolve(
getDevBundleForRelease(release)
).then(function (devBundleDir) {
if (devBundleDir) {
links.makeLink(devBundleDir, devBundleLink);
return devBundleDir;
}
return defaultDevBundlePromise;
});
}
function getDevBundleForRelease(release) {
var parts = release.split("@");
if (parts.length < 2) {
return null;
}
var track = parts[0];
var version = parts.slice(1).join("@");
var packageMetadataDir = find(
rootDir,
makeStatTest("isDirectory"),
".meteor", "package-metadata"
);
if (! packageMetadataDir) {
return null;
}
var meteorToolDir = path.resolve(
packageMetadataDir,
"..", "packages", "meteor-tool"
);
var meteorToolStat = statOrNull(meteorToolDir, "isDirectory");
if (! meteorToolStat) {
return null;
}
var dbPath = path.join(
packageMetadataDir,
"v2.0.1",
"packages.data.db"
);
var dbStat = statOrNull(dbPath, "isFile");
if (! dbStat) {
return null;
}
var sqlite3 = require("sqlite3");
var db = new sqlite3.Database(dbPath);
return new Promise(function (resolve, reject) {
db.get(
"SELECT content FROM releaseVersions WHERE track=? AND version=?",
[track, version],
function (error, data) {
error ? reject(error) : resolve(data);
}
);
}).then(function (data) {
if (data) {
var tool = JSON.parse(data.content).tool;
var devBundleDir = path.join(
meteorToolDir,
tool.split("@").slice(1).join("@"),
"mt-" + getHostArch(),
"dev_bundle"
);
var devBundleStat = statOrNull(devBundleDir, "isDirectory");
if (devBundleStat) {
return devBundleDir;
}
}
return null;
}).catch(function (error) {
console.error(error.stack || error);
return null;
});
}
function statOrNull(path, statMethod) {
try {
var stat = fs.statSync(path);
} catch (e) {
if (e.code !== "ENOENT") {
throw e;
}
}
if (stat) {
if (typeof statMethod === "string") {
if (stat[statMethod]()) {
return stat;
}
} else {
return stat;
}
}
return null;
}
function find(dir, predicate) {
var joinArgs = Array.prototype.slice.call(arguments, 2);
joinArgs.unshift(null);
while (true) {
joinArgs[0] = dir;
var joined = path.join.apply(path, joinArgs);
if (predicate(joined)) {
return joined;
}
var parentDir = path.dirname(dir);
if (parentDir === dir) break;
dir = parentDir;
}
return null;
}
function makeStatTest(method) {
return function (file) {
return statOrNull(file, method);
};
}
function getHostArch() {
if (process.platform === "win32") {
if (process.arch === "x64") {
return "os.windows.x86_64";
}
return "os.windows.x86_32";
}
if (process.platform === "linux") {
if (process.arch === "x64") {
return "os.linux.x86_64";
}
return "os.linux.x86_32";
}
if (process.platform === "darwin") {
return "os.osx.x86_64";
}
}
module.exports = getDevBundleDir().catch(function (error) {
return defaultDevBundlePromise;
});