mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
192 lines
6.0 KiB
JavaScript
192 lines
6.0 KiB
JavaScript
var path = require('path');
|
|
var _ = require('underscore');
|
|
var files = require('./files.js');
|
|
var packages = require('./packages.js');
|
|
var warehouse = require('./warehouse.js');
|
|
var bundler = require('./bundler.js');
|
|
var fs = require('fs');
|
|
|
|
// Under the hood, packages in the library (/package/foo), and user
|
|
// applications, are both Packages -- they are just represented
|
|
// differently on disk.
|
|
|
|
// Options:
|
|
// - releaseManifest: a parsed release manifest
|
|
// - localPackageDirs: array of directories to search before checking
|
|
// the manifest and the warehouse. Directories that don't exist (or
|
|
// paths that aren't directories) will be silently ignored.
|
|
var Library = function (options) {
|
|
var self = this;
|
|
options = options || {};
|
|
|
|
self.releaseManifest = options.releaseManifest;
|
|
|
|
// Trim down localPackageDirs to just those that actually exist (and
|
|
// that are actually directories)
|
|
self.localPackageDirs = _.filter(options.localPackageDirs, function (dir) {
|
|
try {
|
|
// use stat rather than lstat since symlink to dir is OK
|
|
var stats = fs.statSync(dir);
|
|
} catch (e) {
|
|
return false;
|
|
}
|
|
return stats.isDirectory();
|
|
});
|
|
|
|
self.loadedPackages = {};
|
|
self.overrides = {}; // package name to package directory
|
|
};
|
|
|
|
_.extend(Library.prototype, {
|
|
// Temporarily add a package to the library (or override a package
|
|
// that actually exists in the library.) `packageName` is the name
|
|
// to use for the package and `packageDir` is the directory that
|
|
// contains its source.
|
|
override: function (packageName, packageDir) {
|
|
var self = this;
|
|
self.overrides[packageName] = packageDir
|
|
},
|
|
|
|
// Force reload of all packages. See description at get().
|
|
refresh: function () {
|
|
var self = this;
|
|
self.loadedPackages = {};
|
|
},
|
|
|
|
// Given a package name as a string, retrieve a Package object. If
|
|
// throwOnError is true, the default, throw an error if the package
|
|
// can't be found. (If false is passed for throwOnError, then return
|
|
// null if the package can't be found.)
|
|
//
|
|
// Searches overrides first, then any localPackageDirs you have
|
|
// provided, then the manifest/warehouse if provided.
|
|
//
|
|
// get() caches the packages it returns, meaning if you call
|
|
// get('foo') and later foo changes on disk, you won't see the
|
|
// changes. To flush the package cache and force all of the packages
|
|
// to be reloaded the next time get() is called for them, see
|
|
// refresh().
|
|
get: function (name, throwOnError) {
|
|
var self = this;
|
|
var packageDir, fromWarehouse = false;
|
|
|
|
// Passed a Package?
|
|
if (name instanceof packages.Package)
|
|
return name;
|
|
|
|
// Packages cached from previous calls
|
|
if (name in self.loadedPackages)
|
|
return self.loadedPackages[name];
|
|
|
|
// If there's an override for this package, use that without
|
|
// looking at any other options.
|
|
if (name in self.overrides)
|
|
packageDir = self.overrides[name];
|
|
|
|
// Try localPackageDirs
|
|
if (! packageDir) {
|
|
for (var i = 0; i < self.localPackageDirs.length; ++i) {
|
|
var packageDir = path.join(self.localPackageDirs[i], name);
|
|
if (fs.existsSync(path.join(packageDir, 'package.js')))
|
|
break;
|
|
packageDir = null;
|
|
}
|
|
}
|
|
|
|
// Try the Meteor distribution, if we have one.
|
|
var version = self.releaseManifest && self.releaseManifest.packages[name];
|
|
if (! packageDir && version) {
|
|
var packageDir = path.join(warehouse.getWarehouseDir(),
|
|
'packages', name, version);
|
|
if (! fs.existsSync(packageDir))
|
|
throw new Error("Package missing from warehouse: " + name +
|
|
" version " + version);
|
|
fromWarehouse = true;
|
|
}
|
|
|
|
if (! packageDir) {
|
|
if (throwOnError === false)
|
|
return null;
|
|
throw new Error("Package not available: " + name);
|
|
}
|
|
|
|
// Load package from disk
|
|
var pkg = new packages.Package(self);
|
|
pkg.initFromPackageDir(name, packageDir);
|
|
pkg.inWarehouse = fromWarehouse;
|
|
self.loadedPackages[name] = pkg;
|
|
|
|
return pkg;
|
|
},
|
|
|
|
// Get a package that represents an app. (ignoreFiles is optional
|
|
// and if given, it should be an array of regexps for filenames to
|
|
// ignore when scanning for source files.)
|
|
getForApp: function (appDir, ignoreFiles) {
|
|
var self = this;
|
|
var pkg = new packages.Package(self);
|
|
pkg.initFromAppDir(appDir, ignoreFiles || []);
|
|
return pkg;
|
|
},
|
|
|
|
// Get all packages available. Returns a map from the package name
|
|
// to a Package object.
|
|
list: function () {
|
|
var self = this;
|
|
var names = [];
|
|
|
|
names = _.keys(self.overrides);
|
|
|
|
_.each(self.localPackageDirs, function (dir) {
|
|
names = _.union(names, fs.readdirSync(dir));
|
|
});
|
|
|
|
if (self.releaseManifest) {
|
|
names = _.union(names, _.keys(self.releaseManifest.packages));
|
|
}
|
|
|
|
var ret = {};
|
|
_.each(names, function (name) {
|
|
var pkg = self.get(name, false);
|
|
if (pkg)
|
|
ret[name] = pkg;
|
|
});
|
|
|
|
return ret;
|
|
}
|
|
});
|
|
|
|
var library = exports;
|
|
_.extend(exports, {
|
|
|
|
Library: Library,
|
|
|
|
// returns a pretty list suitable for showing to the user. input is
|
|
// a list of package objects, each of which must have a name (not be
|
|
// an application package.)
|
|
formatList: function (pkgs) {
|
|
var longest = '';
|
|
_.each(pkgs, function (pkg) {
|
|
if (pkg.name.length > longest.length)
|
|
longest = pkg.name;
|
|
});
|
|
var pad = longest.replace(/./g, ' ');
|
|
// it'd be nice to read the actual terminal width, but I tried
|
|
// several methods and none of them work (COLUMNS isn't set in
|
|
// node's environment; `tput cols` returns a constant 80.) maybe
|
|
// node is doing something weird with ptys.
|
|
var width = 80;
|
|
|
|
var out = '';
|
|
_.each(pkgs, function (pkg) {
|
|
if (pkg.metadata.internal)
|
|
return;
|
|
var name = pkg.name + pad.substr(pkg.name.length);
|
|
var summary = pkg.metadata.summary || 'No description';
|
|
out += (name + " " +
|
|
summary.substr(0, width - 2 - pad.length) + "\n");
|
|
});
|
|
|
|
return out;
|
|
}
|
|
}); |