mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
Merge branch 'library-refactor-downloads' into library-refactor
This commit is contained in:
@@ -1784,12 +1784,10 @@ exports.bundle = function (options) {
|
||||
// Pick up any additional targets in /programs
|
||||
// Step 1: scan for targets and make a list. We will reload if you create a
|
||||
// new subdir in 'programs', or create 'programs' itself.
|
||||
var programsDir = path.join(appDir, 'programs');
|
||||
var programs = [];
|
||||
var programsSubdirs = watch.readAndWatchDirectory(watchSet, {
|
||||
absPath: programsDir,
|
||||
include: [/\/$/],
|
||||
exclude: [/^\./]
|
||||
var programsDir = project.getProgramsDirectory(appDir);
|
||||
var programsSubdirs = project.getProgramsSubdirs(appDir, {
|
||||
watchSet: watchSet
|
||||
});
|
||||
|
||||
_.each(programsSubdirs, function (item) {
|
||||
@@ -1882,7 +1880,7 @@ exports.bundle = function (options) {
|
||||
// it
|
||||
|
||||
var pkg = packageCache.packageCache.
|
||||
loadPackageAtPath(p.name, p.loadPath);
|
||||
loadPackageAtPath(p.name, p.path);
|
||||
var target;
|
||||
switch (p.type) {
|
||||
case "server":
|
||||
|
||||
@@ -189,7 +189,7 @@ main.registerCommand({
|
||||
var allPackages = project.getIndirectDependencies(options.appDir);
|
||||
|
||||
var messages = buildmessage.capture(function () {
|
||||
_.forEach(allPackages, function (version, name) {
|
||||
_.forEach(allPackages, function (versions, name) {
|
||||
// Calling getPackage on the loader will return a unipackage object, which
|
||||
// means that the package will be compiled/downloaded. That we throw the
|
||||
// package variable away afterwards is immaterial.
|
||||
@@ -602,7 +602,6 @@ main.registerCommand({
|
||||
failed = true;
|
||||
return;
|
||||
}
|
||||
console.log(constraint);
|
||||
|
||||
// If the version was specified, check that the version exists.
|
||||
if ( constraint.versionConstraint !== "none") {
|
||||
@@ -617,16 +616,16 @@ main.registerCommand({
|
||||
}
|
||||
}
|
||||
// Check that the constraint is new. If we are already using the package at
|
||||
// the same constraint, return from this function.
|
||||
if (_.has(packages, constraint.name) &&
|
||||
constraint.versionConstraint === packages[constraint.name] ) {
|
||||
// the same constraint in the app, return from this function.
|
||||
if (_.has(packages.appDeps, constraint.name) &&
|
||||
packages.appDeps[constraint.name] === constraint.versionConstraint) {
|
||||
process.stderr.write(constraint.name + " with version constraint " +
|
||||
constraint.versionConstraint + " has already been added.\n");
|
||||
failed = true;
|
||||
}
|
||||
|
||||
// Add the package to our direct dependency constraints that we get from .meteor/packages.
|
||||
packages[constraint.name] = constraint.versionConstraint;
|
||||
packages.appDeps[constraint.name] = constraint.versionConstraint;
|
||||
});
|
||||
|
||||
// If the user asked for invalid packages, then the user probably expects a
|
||||
@@ -644,9 +643,12 @@ main.registerCommand({
|
||||
// Call the constraint solver.
|
||||
var constraintSolver = require('./constraint-solver.js');
|
||||
var resolver = new constraintSolver.Resolver;
|
||||
// Combine into one object mapping package name to list of
|
||||
// constraints, to pass in to the constraint solver.
|
||||
var allPackages = project.combineAppAndProgramDependencies(packages);
|
||||
// XXX: constraint solver currently ignores versions, but it should not.
|
||||
// XXX: this would also be the place to add no-update options.
|
||||
var newVersions = resolver.resolve(packages);
|
||||
var newVersions = resolver.resolve(allPackages);
|
||||
if ( ! newVersions) {
|
||||
// XXX: Better error handling.
|
||||
process.stderr.write("Cannot resolve package dependencies.");
|
||||
@@ -663,31 +665,36 @@ main.registerCommand({
|
||||
messageLog.push("removed dependency on " + packageName);
|
||||
});
|
||||
|
||||
// Install the new versions.
|
||||
// Install the new versions. If all new versions were installed
|
||||
// successfully, then `setDependencies` also records dependency
|
||||
// changes in the .meteor/versions file.
|
||||
//
|
||||
// Makes sure we have enough builds of the package downloaded such that
|
||||
// we can load a browser slice and a slice that will run on this
|
||||
// system. (Later we may also need to download more builds to be able to
|
||||
// deploy to another architecture.)
|
||||
var downloaded = project.setDependencies(
|
||||
options.appDir,
|
||||
packages.appDeps,
|
||||
newVersions
|
||||
);
|
||||
|
||||
_.each(newVersions, function(version, packageName) {
|
||||
if ( failed )
|
||||
if (failed)
|
||||
return;
|
||||
|
||||
if (_.has(versions, packageName) &&
|
||||
versions[packageName] == version ) {
|
||||
versions[packageName] === version) {
|
||||
// Nothing changed. Skip this.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we have enough builds of the package downloaded such that
|
||||
// we can load a browser slice and a slice that will run on this
|
||||
// system. (Later we may also need to download more builds to be able to
|
||||
// deploy to another architecture.)
|
||||
var available = tropohouse.maybeDownloadPackageForArchitectures(
|
||||
catalog.getVersion(packageName, version),
|
||||
// XXX we also download the deploy arch now, because we don't run the
|
||||
// constraint solver / downloader anywhere other than add-package yet.
|
||||
['browser', archinfo.host(), XXX_DEPLOY_ARCH]);
|
||||
if (! available) {
|
||||
if (! downloaded[packageName] || downloaded[packageName] !== version) {
|
||||
// XXX maybe we shouldn't be letting the constraint solver choose
|
||||
// things that don't have the right arches?
|
||||
process.stderr.write("Package " + packageName +
|
||||
" has no compatible build for version " +
|
||||
version);
|
||||
version + "\n");
|
||||
failed = true;
|
||||
return;
|
||||
}
|
||||
@@ -700,7 +707,7 @@ main.registerCommand({
|
||||
|
||||
// If the previous versions file had this, then we are upgrading, if it did
|
||||
// not, then we must be adding this package anew.
|
||||
if ( _.has(versions, packageName )) {
|
||||
if (_.has(versions, packageName)) {
|
||||
messageLog.push("upgraded " + packageName + " from version " +
|
||||
versions[packageName] +
|
||||
" to version " + newVersions[packageName]);
|
||||
@@ -713,9 +720,6 @@ main.registerCommand({
|
||||
if (failed)
|
||||
return 1;
|
||||
|
||||
// Record dependency changes.
|
||||
project.rewriteDependencies(options.appDir, packages, newVersions);
|
||||
|
||||
// Show the user the messageLog of packages we added.
|
||||
_.each(messageLog, function (msg) {
|
||||
process.stdout.write(msg + "\n");
|
||||
@@ -762,12 +766,12 @@ main.registerCommand({
|
||||
_.each(options.args, function (packageName) {
|
||||
// Check that we are using the package. We don't check if the package
|
||||
// exists. You should be able to remove non-existent packages.
|
||||
if (! _.has(packages, packageName)) {
|
||||
if (! _.has(packages.appDeps, packageName)) {
|
||||
process.stderr.write( packageName + " is not in this project \n");
|
||||
}
|
||||
|
||||
// Remove the package from our dependency list.
|
||||
delete packages[packageName];
|
||||
delete packages.appDeps[packageName];
|
||||
});
|
||||
|
||||
// Get the contents of our versions file. We need to pass them to the
|
||||
@@ -780,7 +784,8 @@ main.registerCommand({
|
||||
var resolver = new constraintSolver.Resolver;
|
||||
// XXX: constraint solver currently ignores versions, but it should not.
|
||||
// XXX: this would also be the place to add no-update options.
|
||||
var newVersions = resolver.resolve(packages);
|
||||
var newVersions = resolver.resolve(
|
||||
project.combineAppAndProgramDependencies(packages));
|
||||
if ( ! newVersions) {
|
||||
// This should never really happen.
|
||||
process.stderr.write("Cannot resolve package dependencies.");
|
||||
@@ -798,7 +803,7 @@ main.registerCommand({
|
||||
});
|
||||
|
||||
// Write the dependency files with the right versions
|
||||
project.rewriteDependencies(options.appDir, packages, newVersions);
|
||||
project.setDependencies(options.appDir, packages.appDeps, newVersions);
|
||||
|
||||
// Show the user the messageLog of everything we removed.
|
||||
_.each(messageLog, function (msg) {
|
||||
@@ -831,7 +836,7 @@ main.registerCommand({
|
||||
var items = [];
|
||||
if (options.using) {
|
||||
var packages = project.getDirectDependencies(options.appDir);
|
||||
_.each(packages, function (version, name) {
|
||||
_.each(packages.appDeps, function (version, name) {
|
||||
var versionInfo = catalog.getVersion(name, version);
|
||||
if (!versionInfo) {
|
||||
process.stderr.write("Cannot process package list. Unknown: " + name +
|
||||
@@ -1362,16 +1367,9 @@ main.registerCommand({
|
||||
// The catalog doesn't know about other programs in your app. Let's blow
|
||||
// away their .build directories if they have them, and not rebuild
|
||||
// them. Sort of hacky, but eh.
|
||||
var programsDir = path.join(options.appDir, 'programs');
|
||||
try {
|
||||
var programs = fs.readdirSync(programsDir);
|
||||
} catch (e) {
|
||||
// OK if the programs directory doesn't exist; that'll just leave
|
||||
// 'programs' empty.
|
||||
if (e.code !== "ENOENT")
|
||||
throw e;
|
||||
}
|
||||
_.each(programs, function (program) {
|
||||
var programsDir = project.getProgramsDirectory(options.appDir);
|
||||
var programsSubdirs = project.getProgramsSubdirs(options.appDir);
|
||||
_.each(programsSubdirs, function (program) {
|
||||
files.rm_recursive(path.join(programsDir, program, '.build'));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ var deepClone = function (v) {
|
||||
// For some reason, _.map doesn't work in this context on Opera (weird test
|
||||
// failures).
|
||||
ret = [];
|
||||
for (i = 0; i < v.length; i++)
|
||||
for (var i = 0; i < v.length; i++)
|
||||
ret[i] = deepClone(v[i]);
|
||||
return ret;
|
||||
}
|
||||
@@ -244,7 +244,8 @@ var rejectExactDeps = function (deps) { return _.reject(deps, isExact); };
|
||||
// converts dependencies from simple format to the structured format
|
||||
var toStructuredDeps = function (dependencies) {
|
||||
var structuredDeps = [];
|
||||
_.each(dependencies, function (details, packageName) {
|
||||
|
||||
var addStructuredDep = function (packageName, details) {
|
||||
// if details is null, it means 'no constraint'
|
||||
if (typeof details === "string" || details === null) {
|
||||
structuredDeps.push(_.extend(
|
||||
@@ -253,6 +254,16 @@ var toStructuredDeps = function (dependencies) {
|
||||
} else {
|
||||
structuredDeps.push(_.extend({ packageName: packageName }, details));
|
||||
}
|
||||
};
|
||||
|
||||
_.each(dependencies, function (details, packageName) {
|
||||
if (_.isArray(details)) {
|
||||
_.each(details, function (constraint) {
|
||||
addStructuredDep(packageName, constraint);
|
||||
});
|
||||
} else {
|
||||
addStructuredDep(packageName, details);
|
||||
}
|
||||
});
|
||||
return structuredDeps;
|
||||
};
|
||||
|
||||
121
tools/project.js
121
tools/project.js
@@ -3,6 +3,9 @@ var path = require('path');
|
||||
var _ = require('underscore');
|
||||
var files = require('./files.js');
|
||||
var utils = require('./utils.js');
|
||||
var tropohouse = require('./tropohouse.js');
|
||||
var archinfo = require('./archinfo.js');
|
||||
var watch = require('./watch.js');
|
||||
|
||||
var project = exports;
|
||||
|
||||
@@ -74,9 +77,64 @@ project.processPerConstraintLines = function(lines) {
|
||||
|
||||
};
|
||||
|
||||
// Read in the .meteor/packages file.
|
||||
project.getProgramsDirectory = function (appDir) {
|
||||
return path.join(appDir, "programs");
|
||||
};
|
||||
|
||||
// Return the list of subdirectories containing programs in the
|
||||
// app. Options can include:
|
||||
// - watchSet: if provided, the app's programs directory will be added to it
|
||||
project.getProgramsSubdirs = function (appDir, options) {
|
||||
options = options || {};
|
||||
var programsDir = project.getProgramsDirectory(appDir);
|
||||
var readOptions = {
|
||||
absPath: programsDir,
|
||||
include: [/\/$/],
|
||||
exclude: [/^\./]
|
||||
};
|
||||
if (options.watchSet) {
|
||||
return watch.readAndWatchDirectory(options.watchSet, readOptions);
|
||||
} else {
|
||||
return watch.readDirectory(readOptions);
|
||||
}
|
||||
};
|
||||
|
||||
// Read direct dependencies from the .meteor/packages file and from
|
||||
// programs in this app.
|
||||
//
|
||||
// Returns an object with keys:
|
||||
// - appDeps: object mapping package names to version constraints
|
||||
// - programsDeps: an object mapping program name to program deps,
|
||||
// where program deps is an object mapping package names to version
|
||||
// constraints.
|
||||
project.getDirectDependencies = function(appDir) {
|
||||
return project.processPerConstraintLines(getPackagesLines(appDir));
|
||||
var appDeps = project.processPerConstraintLines(getPackagesLines(appDir));
|
||||
|
||||
var programsDeps = {};
|
||||
var programsSubdirs = project.getProgramsSubdirs(appDir);
|
||||
var PackageSource;
|
||||
_.each(programsSubdirs, function (item) {
|
||||
if (! PackageSource) {
|
||||
PackageSource = require('./package-source.js');
|
||||
}
|
||||
|
||||
var programName = item.substr(0, item.length - 1);
|
||||
programsDeps[programName] = {};
|
||||
|
||||
var programSubdir = path.join(project.getProgramsDirectory(appDir), item);
|
||||
var programSource = new PackageSource(programSubdir);
|
||||
programSource.initFromPackageDir(programName, programSubdir);
|
||||
_.each(programSource.slices, function (sourceSlice) {
|
||||
_.each(sourceSlice.uses, function (use) {
|
||||
programsDeps[programName][use["package"]] = use.constraint || "none";
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
appDeps: appDeps,
|
||||
programsDeps: programsDeps
|
||||
};
|
||||
};
|
||||
|
||||
// Get a list of constraints from the .meteor/versions file.
|
||||
@@ -85,7 +143,7 @@ project.getIndirectDependencies = function(appDir) {
|
||||
};
|
||||
|
||||
// Write the .meteor/versions file after running the constraint solver.
|
||||
project.rewriteDependencies = function (appDir, deps, versions) {
|
||||
var rewriteDependencies = function (appDir, deps, versions) {
|
||||
|
||||
// Rewrite the packages file. Do this first, since the versions file is
|
||||
// derived from the packages file.
|
||||
@@ -112,10 +170,58 @@ project.rewriteDependencies = function (appDir, deps, versions) {
|
||||
lines.join(''), 'utf8');
|
||||
};
|
||||
|
||||
|
||||
// Call this after running the constraint solver. Downloads the
|
||||
// necessary package builds and writes the .meteor/versions and
|
||||
// .meteor/packages files with the results of the constraint solver.
|
||||
//
|
||||
// Only writes to .meteor/versions if all the requested versions were
|
||||
// available from the package server.
|
||||
//
|
||||
// Returns an object whose keys are package names and values are
|
||||
// versions that were successfully downloaded.
|
||||
project.setDependencies = function (appDir, deps, versions) {
|
||||
var downloadedPackages = {};
|
||||
_.each(versions, function (version, name) {
|
||||
var packageVersionInfo = { packageName: name, version: version };
|
||||
// XXX error handling
|
||||
var available = tropohouse.maybeDownloadPackageForArchitectures(
|
||||
packageVersionInfo,
|
||||
['browser', archinfo.host()]
|
||||
);
|
||||
if (available) {
|
||||
downloadedPackages[name] = version;
|
||||
}
|
||||
});
|
||||
|
||||
if (_.keys(downloadedPackages).length === _.keys(versions).length) {
|
||||
rewriteDependencies(appDir, deps, versions);
|
||||
}
|
||||
return downloadedPackages;
|
||||
};
|
||||
|
||||
var meteorReleaseFilePath = function (appDir) {
|
||||
return path.join(appDir, '.meteor', 'release');
|
||||
};
|
||||
|
||||
// Helper function. Given an object `deps` as returned from
|
||||
// `getDirectDependencies`, combine all the direct dependencies (for the
|
||||
// app and its programs) into a single object mapping package name to a
|
||||
// list of version constraints, which can be passed into the constraint
|
||||
// solver.
|
||||
project.combineAppAndProgramDependencies = function (deps) {
|
||||
var allDeps = {};
|
||||
_.each(deps.appDeps, function (constraint, packageName) {
|
||||
allDeps[packageName] = [constraint];
|
||||
});
|
||||
_.each(deps.programsDeps, function (deps, programName) {
|
||||
_.each(deps, function (constraint, packageName) {
|
||||
allDeps[packageName] = allDeps[packageName] || [];
|
||||
allDeps[packageName].push(constraint);
|
||||
});
|
||||
});
|
||||
return allDeps;
|
||||
};
|
||||
|
||||
// Run the constraint solver to determine the package versions to use.
|
||||
//
|
||||
@@ -127,20 +233,23 @@ project.generatePackageLoader = function (appDir) {
|
||||
var versions = project.getIndirectDependencies(appDir);
|
||||
var packages = project.getDirectDependencies(appDir);
|
||||
|
||||
// package name -> list of version constraints
|
||||
var allPackages = project.combineAppAndProgramDependencies(packages);
|
||||
|
||||
// XXX: We are manually adding ctl here, but we should do this in a more
|
||||
// principled manner.
|
||||
var constraintSolver = require('./constraint-solver.js');
|
||||
var resolver = new constraintSolver.Resolver;
|
||||
// XXX: constraint solver currently ignores versions, but it should not.
|
||||
var newVersions = resolver.resolve(
|
||||
_.extend(packages, { "ctl" : "none" }));
|
||||
_.extend(allPackages, { "ctl" : ["none"] }));
|
||||
if ( ! newVersions) {
|
||||
return { outcome: 'conflicting-versions' };
|
||||
}
|
||||
|
||||
// Write out the new versions file.
|
||||
// Download any necessary package builds and write out the new versions file.
|
||||
delete packages["ctl"];
|
||||
project.rewriteDependencies(appDir, packages, newVersions);
|
||||
project.setDependencies(appDir, packages.appDeps, newVersions);
|
||||
|
||||
var newVersionsReform = {};
|
||||
_.each(newVersions, function (version, name) {
|
||||
|
||||
Reference in New Issue
Block a user