UNPKG

renovate

Version:

Automated dependency updates. Flexible so you don't need to be.

283 lines • 9.67 kB
"use strict"; /** * @fileoverview Contains classes that represent a Bazel module version. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.BzlmodVersion = exports.VersionPart = exports.Identifier = void 0; /** * Represents a single value in a VersionPart. For example, the version string * `1.2.3` has three identifiers: `1`, `2`, `3`. */ class Identifier { /** * Returns the identifier as a string. */ asString; /** * If the identifier only contains digits, this is the numeric value. * Otherwise, it is `0`. */ asNumber; /** * Specifies whether the identifier only contains digits. */ isDigitsOnly; /** * Regular expression used to identify whether an identifier value only * contains digits. */ static digitsOnlyMatcher = /^[0-9]+$/; /** * @param value The value that is parsed for the Bazel module version parts. */ constructor(value) { if (value === '') { throw new Error('Identifier value cannot be empty.'); } this.asString = value; if (Identifier.digitsOnlyMatcher.test(value)) { this.isDigitsOnly = true; this.asNumber = parseInt(value); } else { this.isDigitsOnly = false; this.asNumber = 0; } } /** * Determines whether this identifier and another identifier are equal. */ equals(other) { return this.asString === other.asString; } /** * Determines whether this identifier comes before the other identifier. */ isLessThan(other) { // This logic mirrors the comparison logic in // https://cs.opensource.google/bazel/bazel/+/refs/heads/master:src/main/java/com/google/devtools/build/lib/bazel/bzlmod/Version.java // isDigitsOnly: true first if (this.isDigitsOnly !== other.isDigitsOnly) { return this.isDigitsOnly; } if (this.asNumber !== other.asNumber) { return this.asNumber < other.asNumber; } return this.asString < other.asString; } } exports.Identifier = Identifier; /** * A collection of {@link Identifier} values that represent a portion of a * Bazel module version. */ class VersionPart extends Array { /** * Creates a {@link VersionPart} populated with the provided identifiers. */ static create(...items) { const idents = items.map((item) => { if (typeof item === 'string') { return new Identifier(item); } return item; }); const vp = new VersionPart(); vp.push(...idents); return vp; } /** * The string representation of the version part. */ get asString() { return this.map((ident) => ident.asString).join('.'); } /** * Specifies whether this contains any identifiers. */ get isEmpty() { return this.length === 0; } /** * Returns the equivalent of the a Semver major value. */ get major() { return this.length > 0 ? this[0].asNumber : 0; } /** * Returns the equivalent of the a Semver minor value. */ get minor() { return this.length > 1 ? this[1].asNumber : 0; } /** * Returns the equivalent of the a Semver patch value. */ get patch() { return this.length > 2 ? this[2].asNumber : 0; } /** * Determines whether this version part is equal to the other. */ equals(other) { if (this.length !== other.length) { return false; } for (let i = 0; i < this.length; i++) { const a = this[i]; const b = other[i]; if (!a.equals(b)) { return false; } } return true; } /** * Determines whether this version part comes before the other. */ isLessThan(other) { // This logic mirrors the comparison logic in // https://cs.opensource.google/bazel/bazel/+/refs/heads/master:src/main/java/com/google/devtools/build/lib/bazel/bzlmod/Version.java if (this.equals(other)) { return false; } // Non-empty are first if (this.length === 0 && other.length !== 0) { return false; } if (other.length === 0 && this.length !== 0) { return true; } const shortestLen = this.length < other.length ? this.length : other.length; for (let i = 0; i < shortestLen; i++) { const a = this[i]; const b = other[i]; if (!a.equals(b)) { return a.isLessThan(b); } } return this.length < other.length; } } exports.VersionPart = VersionPart; /** * Represents a version in the Bazel module system. The version format we support is * `RELEASE[-PRERELEASE][+BUILD]`, where `RELEASE`, `PRERELEASE`, and `BUILD` are * each a sequence of "identifiers" (defined as a non-empty sequence of ASCII alphanumerical * characters and hyphens) separated by dots. The `RELEASE` part may not contain hyphens. * * Otherwise, this format is identical to SemVer, especially in terms of the comparison algorithm * (https://semver.org/#spec-item-11). In other words, this format is intentionally looser than * SemVer; in particular: * * - the "release" part isn't limited to exactly 3 segments (major, minor, patch), but can be * fewer or more; * - each segment in the "release" part can be identifiers instead of just numbers (so letters * are also allowed -- although hyphens are not). * * Any valid SemVer version is a valid Bazel module version. Additionally, two SemVer versions * `a` and `b` compare `a < b` iff the same holds when they're compared as Bazel * module versions. * * The special "empty string" version can also be used, and compares higher than everything else. * It signifies that there is a NonRegistryOverride for a module. */ class BzlmodVersion { original; release; prerelease; build; /** * The regular expression that identifies a valid Bazel module version. */ static versionMatcher = /^(?<release>[a-zA-Z0-9.]+)(?:-(?<prerelease>[a-zA-Z0-9.-]+))?(?:\+(?<build>[a-zA-Z0-9.-]+))?$/; /** * @param version The string that is parsed for the Bazel module version * values. */ constructor(version) { this.original = version; if (version === '') { this.release = VersionPart.create(); this.prerelease = VersionPart.create(); this.build = VersionPart.create(); return; } const vparts = BzlmodVersion.versionMatcher.exec(version)?.groups; if (!vparts) { throw new Error(`Invalid Bazel module version: ${version}`); } // The regex check above ensures that we will have a release group. const rparts = vparts.release.split('.'); this.release = VersionPart.create(...rparts); const pparts = vparts.prerelease ? vparts.prerelease.split('.') : []; this.prerelease = VersionPart.create(...pparts); // Do not parse the build value. Treat it as a single value. const bparts = vparts.build ? [vparts.build] : []; this.build = VersionPart.create(...bparts); } /** * Specifies whether this is a pre-release version. */ get isPrerelease() { return !this.prerelease.isEmpty; } // Comparison /** * Determines whether this Bazel module version is equal to the other. * * @param other The other version for the comparison. * @param ignoreBuild? If specified, determines whether the build value is * evaluated as part of the equality check. This is useful when * determining precedence. */ equals(other, ignoreBuild) { if (ignoreBuild) { return (this.release.equals(other.release) && this.prerelease.equals(other.prerelease)); } return (this.release.equals(other.release) && this.prerelease.equals(other.prerelease) && this.build.equals(other.build)); } /** * Determines whether this Bazel module version comes before the other. */ isLessThan(other) { // This logic mirrors the comparison logic in // https://cs.opensource.google/bazel/bazel/+/refs/heads/master:src/main/java/com/google/devtools/build/lib/bazel/bzlmod/Version.java if (this.release.isLessThan(other.release)) { return true; } // Ensure that prerelease is listed before regular releases if (this.isPrerelease && !other.isPrerelease) { return true; } if (this.prerelease.isLessThan(other.prerelease)) { return true; } // NOTE: We ignore the build value for precedence comparison per the Semver spec. // https://semver.org/#spec-item-10 return false; } /** * Determines whether this Bazel module version comes after the other. */ isGreaterThan(other) { return BzlmodVersion.defaultCompare(this, other) === 1; } /** * Evaluates two Bazel module versions and returns a value specifying whether * a < b (-1), a == b (0), or a > b (1). */ static defaultCompare(a, b) { if (a.equals(b, true)) { return 0; } if (a.isLessThan(b)) { return -1; } return 1; } } exports.BzlmodVersion = BzlmodVersion; //# sourceMappingURL=bzlmod-version.js.map