mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
De-dup package name/constraint parsing code
Now we can all any of them from even before uniload is ready in the tool I <3 symlinks
This commit is contained in:
@@ -1,116 +0,0 @@
|
||||
var semver = Npm.require('semver');
|
||||
|
||||
PackageVersion = {};
|
||||
|
||||
// Conceptually we have three types of constraints:
|
||||
// 1. "compatible-with" - A@x.y.z - constraints package A to version x.y.z or
|
||||
// higher, as long as the version is backwards compatible with x.y.z.
|
||||
// "pick A compatible with x.y.z"
|
||||
// It is the default type.
|
||||
// 2. "exactly" - A@=x.y.z - constraints package A only to version x.y.z and
|
||||
// nothing else.
|
||||
// "pick A exactly at x.y.z"
|
||||
// 3. "at-least" - A@>=x.y.z - constraints package A to version x.y.z or higher.
|
||||
// "pick A at least at x.y.z"
|
||||
// This one is only used internally by the constraint solver --- end users
|
||||
// shouldn't be allowed to specify it, and you need to specially request it
|
||||
// with the "allowAtLeast" option.
|
||||
PackageVersion.parseVersionConstraint = function (versionString, options) {
|
||||
options = options || {};
|
||||
var versionDesc = { version: null, type: "compatible-with",
|
||||
constraintString: versionString };
|
||||
|
||||
if (versionString === "none" || versionString === null) {
|
||||
versionDesc.type = "at-least";
|
||||
versionDesc.version = "0.0.0";
|
||||
return versionDesc;
|
||||
}
|
||||
|
||||
if (versionString.charAt(0) === '=') {
|
||||
versionDesc.type = "exactly";
|
||||
versionString = versionString.substr(1);
|
||||
} else if (options.allowAtLeast && versionString.substr(0, 2) === '>=') {
|
||||
versionDesc.type = "at-least";
|
||||
versionString = versionString.substr(2);
|
||||
}
|
||||
|
||||
// XXX check for a dash in the version in case of foo@1.2.3-rc0
|
||||
|
||||
if (! semver.valid(versionString)) {
|
||||
throwVersionParserError(
|
||||
"Version string must look like semver (eg '1.2.3'), not '"
|
||||
+ versionString + "'.");
|
||||
}
|
||||
|
||||
versionDesc.version = versionString;
|
||||
|
||||
return versionDesc;
|
||||
};
|
||||
|
||||
PackageVersion.parseConstraint = function (constraintString, options) {
|
||||
if (typeof constraintString !== "string")
|
||||
throw new TypeError("constraintString must be a string");
|
||||
options = options || {};
|
||||
|
||||
var splitted = constraintString.split('@');
|
||||
|
||||
var constraint = { name: "", version: null,
|
||||
type: "compatible-with", constraintString: null };
|
||||
var name = splitted[0];
|
||||
var versionString = splitted[1];
|
||||
|
||||
if (splitted.length > 2) {
|
||||
// throw error complaining about @
|
||||
PackageVersion.validatePackageName('a@');
|
||||
}
|
||||
PackageVersion.validatePackageName(name);
|
||||
|
||||
constraint.name = name;
|
||||
|
||||
if (splitted.length === 2 && !versionString) {
|
||||
throwVersionParserError(
|
||||
"Version constraint for package '" + name +
|
||||
"' cannot be empty; leave off the @ if you don't want to constrain " +
|
||||
"the version.");
|
||||
}
|
||||
|
||||
if (versionString) {
|
||||
_.extend(constraint,
|
||||
PackageVersion.parseVersionConstraint(versionString, options));
|
||||
}
|
||||
|
||||
return constraint;
|
||||
};
|
||||
|
||||
// XXX duplicates code in utils.js, sigh. but we need to run
|
||||
// this before we can load packages.
|
||||
PackageVersion.validatePackageName = function (packageName, options) {
|
||||
options = options || {};
|
||||
|
||||
var badChar = packageName.match(/[^a-z0-9:.\-]/);
|
||||
if (badChar) {
|
||||
if (options.detailedColonExplanation) {
|
||||
throwVersionParserError(
|
||||
"Bad character in package name: " + JSON.stringify(badChar[0]) +
|
||||
". Package names can only contain lowercase ASCII alphanumerics, " +
|
||||
"dash, or dot. If you plan to publish a package, it must be " +
|
||||
"prefixed with your Meteor developer username and a colon.");
|
||||
}
|
||||
throwVersionParserError(
|
||||
"Package names can only contain lowercase ASCII alphanumerics, dash, " +
|
||||
"dot, or colon, not " + JSON.stringify(badChar[0]) + ".");
|
||||
}
|
||||
if (!/[a-z]/.test(packageName)) {
|
||||
throwVersionParserError("Package names must contain a lowercase ASCII letter.");
|
||||
}
|
||||
if (packageName[0] === '.') {
|
||||
throwVersionParserError("Package names may not begin with a dot.");
|
||||
}
|
||||
};
|
||||
// XXX duplicates code in utils.js, sigh. but we need to run
|
||||
// this before we can load packages.
|
||||
var throwVersionParserError = function (message) {
|
||||
var e = new Error(message);
|
||||
e.versionParserError = true;
|
||||
throw e;
|
||||
};
|
||||
1
packages/package-version-parser/package-version-parser.js
Symbolic link
1
packages/package-version-parser/package-version-parser.js
Symbolic link
@@ -0,0 +1 @@
|
||||
../../tools/package-version-parser.js
|
||||
126
tools/package-version-parser.js
Normal file
126
tools/package-version-parser.js
Normal file
@@ -0,0 +1,126 @@
|
||||
// This file is in tools/package-version-parser.js and is symlinked into
|
||||
// packages/package-version-parser/package-version-parser.js. It's part
|
||||
// of both the tool and the package! We don't use uniload for it because
|
||||
// it needs to be used as part of initializing the uniload catalog.
|
||||
|
||||
var inTool = typeof Package === 'undefined';
|
||||
|
||||
var PV;
|
||||
if (inTool) {
|
||||
PV = exports;
|
||||
} else {
|
||||
PackageVersion = PV = {};
|
||||
}
|
||||
|
||||
var semver = inTool ? require ('semver') : Npm.require('semver');
|
||||
var __ = inTool ? require('underscore') : _;
|
||||
|
||||
// Conceptually we have three types of constraints:
|
||||
// 1. "compatible-with" - A@x.y.z - constraints package A to version x.y.z or
|
||||
// higher, as long as the version is backwards compatible with x.y.z.
|
||||
// "pick A compatible with x.y.z"
|
||||
// It is the default type.
|
||||
// 2. "exactly" - A@=x.y.z - constraints package A only to version x.y.z and
|
||||
// nothing else.
|
||||
// "pick A exactly at x.y.z"
|
||||
// 3. "at-least" - A@>=x.y.z - constraints package A to version x.y.z or higher.
|
||||
// "pick A at least at x.y.z"
|
||||
// This one is only used internally by the constraint solver --- end users
|
||||
// shouldn't be allowed to specify it, and you need to specially request it
|
||||
// with the "allowAtLeast" option.
|
||||
PV.parseVersionConstraint = function (versionString, options) {
|
||||
options = options || {};
|
||||
var versionDesc = { version: null, type: "compatible-with",
|
||||
constraintString: versionString };
|
||||
|
||||
if (versionString === "none" || versionString === null) {
|
||||
versionDesc.type = "at-least";
|
||||
versionDesc.version = "0.0.0";
|
||||
return versionDesc;
|
||||
}
|
||||
|
||||
if (versionString.charAt(0) === '=') {
|
||||
versionDesc.type = "exactly";
|
||||
versionString = versionString.substr(1);
|
||||
} else if (options.allowAtLeast && versionString.substr(0, 2) === '>=') {
|
||||
versionDesc.type = "at-least";
|
||||
versionString = versionString.substr(2);
|
||||
}
|
||||
|
||||
// XXX check for a dash in the version in case of foo@1.2.3-rc0
|
||||
|
||||
if (! semver.valid(versionString)) {
|
||||
throwVersionParserError(
|
||||
"Version string must look like semver (eg '1.2.3'), not '"
|
||||
+ versionString + "'.");
|
||||
}
|
||||
|
||||
versionDesc.version = versionString;
|
||||
|
||||
return versionDesc;
|
||||
};
|
||||
|
||||
PV.parseConstraint = function (constraintString, options) {
|
||||
if (typeof constraintString !== "string")
|
||||
throw new TypeError("constraintString must be a string");
|
||||
options = options || {};
|
||||
|
||||
var splitted = constraintString.split('@');
|
||||
|
||||
var constraint = { name: "", version: null,
|
||||
type: "compatible-with", constraintString: null };
|
||||
var name = splitted[0];
|
||||
var versionString = splitted[1];
|
||||
|
||||
if (splitted.length > 2) {
|
||||
// throw error complaining about @
|
||||
PV.validatePackageName('a@');
|
||||
}
|
||||
PV.validatePackageName(name);
|
||||
|
||||
constraint.name = name;
|
||||
|
||||
if (splitted.length === 2 && !versionString) {
|
||||
throwVersionParserError(
|
||||
"Version constraint for package '" + name +
|
||||
"' cannot be empty; leave off the @ if you don't want to constrain " +
|
||||
"the version.");
|
||||
}
|
||||
|
||||
if (versionString) {
|
||||
__.extend(constraint,
|
||||
PV.parseVersionConstraint(versionString, options));
|
||||
}
|
||||
|
||||
return constraint;
|
||||
};
|
||||
|
||||
PV.validatePackageName = function (packageName, options) {
|
||||
options = options || {};
|
||||
|
||||
var badChar = packageName.match(/[^a-z0-9:.\-]/);
|
||||
if (badChar) {
|
||||
if (options.detailedColonExplanation) {
|
||||
throwVersionParserError(
|
||||
"Bad character in package name: " + JSON.stringify(badChar[0]) +
|
||||
". Package names can only contain lowercase ASCII alphanumerics, " +
|
||||
"dash, or dot. If you plan to publish a package, it must be " +
|
||||
"prefixed with your Meteor developer username and a colon.");
|
||||
}
|
||||
throwVersionParserError(
|
||||
"Package names can only contain lowercase ASCII alphanumerics, dash, " +
|
||||
"dot, or colon, not " + JSON.stringify(badChar[0]) + ".");
|
||||
}
|
||||
if (!/[a-z]/.test(packageName)) {
|
||||
throwVersionParserError("Package names must contain a lowercase ASCII letter.");
|
||||
}
|
||||
if (packageName[0] === '.') {
|
||||
throwVersionParserError("Package names may not begin with a dot.");
|
||||
}
|
||||
};
|
||||
|
||||
var throwVersionParserError = function (message) {
|
||||
var e = new Error(message);
|
||||
e.versionParserError = true;
|
||||
throw e;
|
||||
};
|
||||
@@ -4,6 +4,7 @@ var _ = require('underscore');
|
||||
var archinfo = require('./archinfo.js');
|
||||
var files = require('./files.js');
|
||||
var main = require('./main.js');
|
||||
var packageVersionParser = require('./package-version-parser.js');
|
||||
var semver = require('semver');
|
||||
var os = require('os');
|
||||
var fs = require('fs');
|
||||
@@ -140,26 +141,9 @@ exports.randomPort = function () {
|
||||
return 20000 + Math.floor(Math.random() * 10000);
|
||||
};
|
||||
|
||||
(function () {
|
||||
var PackageVersion = null;
|
||||
|
||||
var maybeLoadPackageVersionParser = function () {
|
||||
if (PackageVersion)
|
||||
return;
|
||||
var uniload = require('./uniload.js');
|
||||
var Package = uniload.load({packages: ['package-version-parser']});
|
||||
PackageVersion = Package['package-version-parser'].PackageVersion;
|
||||
};
|
||||
|
||||
exports.parseVersionConstraint = function () {
|
||||
maybeLoadPackageVersionParser();
|
||||
return PackageVersion.parseVersionConstraint.apply(this, arguments);
|
||||
};
|
||||
exports.parseConstraint = function () {
|
||||
maybeLoadPackageVersionParser();
|
||||
return PackageVersion.parseConstraint.apply(this, arguments);
|
||||
};
|
||||
})();
|
||||
exports.parseVersionConstraint = packageVersionParser.parseVersionConstraint;
|
||||
exports.parseConstraint = packageVersionParser.parseConstraint;
|
||||
exports.validatePackageName = packageVersionParser.validatePackageName;
|
||||
|
||||
// XXX should unify this with utils.parseConstraint
|
||||
exports.splitConstraint = function (constraint) {
|
||||
@@ -196,44 +180,6 @@ exports.dealConstraint = function (constraint, pkg) {
|
||||
// eg package-client.js) prints and throws the "exit with code 1" exception
|
||||
// on failure.
|
||||
|
||||
|
||||
// XXX duplicates code in package-version-parser.js, sigh. but we need to run
|
||||
// this before we can load packages.
|
||||
exports.validatePackageName = function (packageName, options) {
|
||||
options = options || {};
|
||||
|
||||
var badChar = packageName.match(/[^a-z0-9:.\-]/);
|
||||
if (badChar) {
|
||||
if (options.detailedColonExplanation) {
|
||||
throwVersionParserError(
|
||||
"Bad character in package name: " + JSON.stringify(badChar[0]) +
|
||||
". Package names can only contain lowercase ASCII alphanumerics, " +
|
||||
"dash, or dot. If you plan to publish a package, it must be " +
|
||||
"prefixed with your Meteor developer username and a colon.");
|
||||
}
|
||||
throwVersionParserError(
|
||||
"Package names can only contain lowercase ASCII alphanumerics, dash, " +
|
||||
"dot, or colon, not " + JSON.stringify(badChar[0]) + ".");
|
||||
}
|
||||
if (!/[a-z]/.test(packageName)) {
|
||||
throwVersionParserError("Package names must contain a lowercase ASCII letter.");
|
||||
}
|
||||
if (packageName[0] === '.') {
|
||||
throwVersionParserError("Package names may not begin with a dot.");
|
||||
}
|
||||
};
|
||||
// XXX duplicates code in package-version-parser.js, sigh. but we need to run
|
||||
// this before we can load packages.
|
||||
var throwVersionParserError = function (message) {
|
||||
var e = new Error(message);
|
||||
e.versionParserError = true;
|
||||
throw e;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Returns a bool saying whether it is valid or not. Use validatePackageName
|
||||
// if you want a nice error message.
|
||||
exports.isValidPackageName = function (packageName) {
|
||||
try {
|
||||
exports.validatePackageName(packageName);
|
||||
|
||||
Reference in New Issue
Block a user