mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
Fetch NPM dependencies when loading meteor release
You can now be offline to use any package that's been installed
This commit is contained in:
committed by
David Glasser
parent
662754a27d
commit
54859e86d6
@@ -123,6 +123,38 @@ var Package = function () {
|
||||
};
|
||||
|
||||
_.extend(Package.prototype, {
|
||||
// loads a package's package.js file into memory, using
|
||||
// runInThisContext. Wraps the contents of package.js in a closure,
|
||||
// supplying pseudo-globals 'Package' and 'Npm'.
|
||||
initFromPackageDir: function (name, dir) {
|
||||
var self = this;
|
||||
self.name = name;
|
||||
self.source_root = dir;
|
||||
self.serve_root = path.join(path.sep, 'packages', name);
|
||||
|
||||
if (!fs.existsSync(self.source_root))
|
||||
throw new Error("The package named " + self.name + " does not exist.");
|
||||
|
||||
// We use string concatenation to load package.js rather than
|
||||
// directly `require`ing it because that allows us to simplify the
|
||||
// package API (such as supporting Package.on_use rather than
|
||||
// something like Package.current().on_use)
|
||||
|
||||
var fullpath = path.join(self.source_root, 'package.js');
|
||||
var code = fs.readFileSync(fullpath).toString();
|
||||
// \n is necessary in case final line is a //-comment
|
||||
var wrapped = "(function(Package,Npm){" + code + "\n})";
|
||||
// See #runInThisContext
|
||||
//
|
||||
// XXX it'd be nice to runInNewContext so that the package
|
||||
// setup code can't mess with our globals, but objects that
|
||||
// come out of runInNewContext have bizarro antimatter
|
||||
// prototype chains and break 'instanceof Array'. for now,
|
||||
// steer clear
|
||||
var func = require('vm').runInThisContext(wrapped, fullpath, true);
|
||||
func(self.packageFacade, self.npmFacade);
|
||||
},
|
||||
|
||||
// Searches:
|
||||
// - $PACKAGE_DIRS (colon-separated)
|
||||
// - $METEOR/packages
|
||||
@@ -130,7 +162,7 @@ _.extend(Package.prototype, {
|
||||
initFromLocalPackages: function (name) {
|
||||
var packageDir = packages.directoryForLocalPackage(name);
|
||||
if (packageDir) {
|
||||
this._initFromPackageDir(name, packageDir);
|
||||
this.initFromPackageDir(name, packageDir);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -138,7 +170,7 @@ _.extend(Package.prototype, {
|
||||
},
|
||||
|
||||
initFromWarehouse: function (name, version) {
|
||||
this._initFromPackageDir(
|
||||
this.initFromPackageDir(
|
||||
name,
|
||||
path.join(warehouse.getWarehouseDir(), 'packages', name, version));
|
||||
},
|
||||
@@ -237,44 +269,17 @@ _.extend(Package.prototype, {
|
||||
//
|
||||
// @param npmDependencies {Object} eg {gcd: "0.0.0", tar: "0.1.14"}
|
||||
installNpmDependencies: function() {
|
||||
// go through a specialized npm dependencies update process, ensuring
|
||||
// we don't get new versions of any (sub)dependencies. this process
|
||||
// also runs safely multiple times in parallel (which could happen if you
|
||||
// have two apps running locally using the same package)
|
||||
meteorNpm.updateDependencies(this.name, this.npmDir(), this.npmDependencies);
|
||||
if (this.npmDependencies) {
|
||||
// go through a specialized npm dependencies update process, ensuring
|
||||
// we don't get new versions of any (sub)dependencies. this process
|
||||
// also runs safely multiple times in parallel (which could happen if you
|
||||
// have two apps running locally using the same package)
|
||||
meteorNpm.updateDependencies(this.name, this.npmDir(), this.npmDependencies);
|
||||
}
|
||||
},
|
||||
|
||||
npmDir: function () {
|
||||
return path.join(this.source_root, '.npm');
|
||||
},
|
||||
|
||||
_initFromPackageDir: function (name, dir) {
|
||||
var self = this;
|
||||
self.name = name;
|
||||
self.source_root = dir;
|
||||
self.serve_root = path.join(path.sep, 'packages', name);
|
||||
|
||||
if (!fs.existsSync(self.source_root))
|
||||
throw new Error("The package named " + self.name + " does not exist.");
|
||||
|
||||
// We use string concatenation to load package.js rather than
|
||||
// directly `require`ing it because that allows us to simplify the
|
||||
// package API (such as supporting Package.on_use rather than
|
||||
// something like Package.current().on_use)
|
||||
|
||||
var fullpath = path.join(self.source_root, 'package.js');
|
||||
var code = fs.readFileSync(fullpath).toString();
|
||||
// \n is necessary in case final line is a //-comment
|
||||
var wrapped = "(function(Package,Npm){" + code + "\n})";
|
||||
// See #runInThisContext
|
||||
//
|
||||
// XXX it'd be nice to runInNewContext so that the package
|
||||
// setup code can't mess with our globals, but objects that
|
||||
// come out of runInNewContext have bizarro antimatter
|
||||
// prototype chains and break 'instanceof Array'. for now,
|
||||
// steer clear
|
||||
var func = require('vm').runInThisContext(wrapped, fullpath, true);
|
||||
func(self.packageFacade, self.npmFacade);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -302,6 +307,13 @@ var packages = module.exports = {
|
||||
return loadedPackages[name];
|
||||
},
|
||||
|
||||
// load a package directly from a directory. don't cache.
|
||||
loadFromDir: function(name, packageDir) {
|
||||
var pkg = new Package;
|
||||
pkg.initFromPackageDir(name, packageDir);
|
||||
return pkg;
|
||||
},
|
||||
|
||||
// get a package that represents an app. (ignore_files is optional
|
||||
// and if given, it should be an array of regexps for filenames to
|
||||
// ignore when scanning for source files.)
|
||||
|
||||
@@ -144,11 +144,11 @@ var warehouse = module.exports = {
|
||||
}
|
||||
},
|
||||
|
||||
// @param packages {Object} eg {"less": "0.5.0"}
|
||||
_populateWarehouseWithPackages: function(packages) {
|
||||
// @param packagesToPopulate {Object} eg {"less": "0.5.0"}
|
||||
_populateWarehouseWithPackages: function(packagesToPopulate) {
|
||||
var Future = require('fibers/future');
|
||||
var futures = [];
|
||||
_.each(packages, function (version, name) {
|
||||
_.each(packagesToPopulate, function (version, name) {
|
||||
var packageDir = path.join(warehouse.getWarehouseDir(), 'packages', name, version);
|
||||
var packageUrl = PACKAGES_URLBASE + "/packages/" + name + "/" +
|
||||
name + '-' + version + ".tar.gz";
|
||||
@@ -157,7 +157,7 @@ var warehouse = module.exports = {
|
||||
futures.push(Future.wrap(function (cb) {
|
||||
files.getUrl({url: packageUrl, encoding: null}, function (error, result) {
|
||||
if (! error && result)
|
||||
result = { buffer: result, packageDir: packageDir };
|
||||
result = { buffer: result, packageDir: packageDir, name: name };
|
||||
cb(error, result);
|
||||
});
|
||||
})());
|
||||
@@ -173,6 +173,11 @@ var warehouse = module.exports = {
|
||||
files.mkdir_p(tmpPackageDir);
|
||||
files.extractTarGz(result.buffer, tmpPackageDir);
|
||||
fs.renameSync(tmpPackageDir, result.packageDir);
|
||||
|
||||
// fetch npm dependencies
|
||||
var packages = require(path.join(__dirname, "packages.js")); // load late to work around circular require
|
||||
var pkg = packages.loadFromDir(result.name, result.packageDir);
|
||||
pkg.installNpmDependencies();
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
@@ -7,10 +7,6 @@ trap 'echo FAILED' EXIT
|
||||
set -e -x
|
||||
|
||||
|
||||
## Test the Meteor CLI from a checkout
|
||||
./cli-test.sh
|
||||
|
||||
|
||||
## Test the Meteor CLI from an installed engine (tests loading packages
|
||||
## into the warehouse)
|
||||
TMPDIR=$(mktemp -d -t meteor-installed-cli-tests)
|
||||
@@ -39,6 +35,10 @@ export TEST_WAREHOUSE_DIR=$(mktemp -d -t meteor-installed-cli-tests-warehouse) #
|
||||
PACKAGE_DIRS=$METEOR_DIR/tools/cli-test-packages/ $METEOR_DIR/meteor test-packages --once --release=0.0.1
|
||||
|
||||
|
||||
## Test the Meteor CLI from a checkout. We do this last because it is least likely to fail.
|
||||
./cli-test.sh
|
||||
|
||||
|
||||
## Done
|
||||
trap - EXIT
|
||||
echo PASSED
|
||||
|
||||
Reference in New Issue
Block a user