Allow space instead of @ in .meteor/versions

This change allows the tool to *read* .meteor/versions whether it uses
"@" or " " as a package/version separator.  It does not change how
.meteor/versions is written out.

Background:
The convention in the new Version Solver is that "foo@1.2.3" means a
constraint, which is satisfied by "foo 1.2.4" but not "foo 1.2.2", which
are specific versions of a package.  This convention avoids the same
confusion of .meteor/packages being a list of constraints while
.meteor/versions is conceptually a list of (package,version) pairs, even
though both look like package@version.

We'd like to replace "@" by " " in .meteor/versions from now on.
Unfortunately, even if the new tool can read old .meteor/versions files,
the old tool wouldn't be able to read the new style.  If in some release
of Meteor, we start writing .meteor/versions that use spaces, you won't
be able to switch between newer and older releases of Meteor without
getting a hard error about a malformed versions file in your app.

What we can do, at least, is start letting the tool read the better
format now, and maybe in the future we can switch.

This change also makes parsePackageAtVersion stand alone, instead of
being defined in terms of parsePackageConstraint, which is nice.
This commit is contained in:
David Greenspan
2015-04-12 16:27:31 -07:00
parent 6a22e377de
commit 4106e8cade

View File

@@ -218,33 +218,42 @@ exports.validatePackageName = function (name, options) {
}
};
// Parse a string of the form package@version into an object of the form
// {name, version}.
// Parse a string of the form `package + " " + version` into an object
// of the form {package, version}. For backwards compatibility,
// an "@" separator instead of a space is also accepted.
//
// Lines of `.meteor/versions` and the contents of `.meteor/release`
// are parsed by this function.
exports.parsePackageAtVersion = function (packageAtVersionString, options) {
// A string that has to look like "package@version" isn't really a
// constraint, it's just a string of the form (package + "@" + version).
// However, using parsePackageConstraint in the implementation is too
// convenient to pass up (especially in terms of error-handling quality).
var parsedConstraint = exports.parsePackageConstraint(packageAtVersionString,
options);
if (! parsedConstraint) {
// It must be that options.useBuildmessage and an error has been
// registered. Otherwise, parsePackageConstraint would succeed or throw.
return null;
}
var alternatives = parsedConstraint.versionConstraint.alternatives;
if (! (alternatives.length === 1 &&
alternatives[0].type === 'compatible-with')) {
if (options && options.useBuildmessage) {
buildmessage.error("Malformed package@version: " + packageAtVersionString,
{ file: options.buildmessageFile });
return null;
} else {
throw new Error("Malformed package@version: " + packageAtVersionString);
var error = null;
var separatorPos = Math.max(packageAtVersionString.lastIndexOf(' '),
packageAtVersionString.lastIndexOf('@'));
if (separatorPos < 0) {
error = new Error("Malformed package version: " +
JSON.stringify(packageAtVersionString));
} else {
var package = packageAtVersionString.slice(0, separatorPos);
var version = packageAtVersionString.slice(separatorPos+1);
try {
packageVersionParser.validatePackageName(package);
// validate the version, ignoring the parsed result:
packageVersionParser.parse(version);
} catch (e) {
if (! e.versionParserError) {
throw e;
}
error = e;
}
if (! error) {
return { package: package, version: version };
}
}
return { package: parsedConstraint.package,
version: alternatives[0].versionString };
// `error` holds an Error
if (! (options && options.useBuildmessage)) {
throw error;
}
buildmessage.error(error.message, { file: options.buildmessageFile });
return null;
};
// Check for invalid package names. Currently package names can only contain