import type { RangeStrategy } from '../../../types/versioning.ts'; import { regEx } from '../../../util/regex.ts'; import { coerceString } from '../../../util/string.ts'; import { api as npm } from '../npm/index.ts'; import { api as pep440 } from '../pep440/index.ts'; import type { NewValueConfig, VersioningApi } from '../types.ts'; import { ascendingRange, descendingRange, exactVersion, inclusiveBound, lowerBound, matchVersion, upperBound, versionGroup, } from './pattern.ts'; import { npm2rezplus, padZeroes, pep4402rezInclusiveBound, rez2npm, rez2pep440, } from './transform.ts'; export const id = 'rez'; export const displayName = 'rez'; export const urls = ['[Rez package manager](https://github.com/nerdvegas/rez)']; export const supportsRanges = true; export const supportedRangeStrategies: RangeStrategy[] = [ 'bump', 'widen', 'replace', ]; function equals(a: string, b: string): boolean { try { return npm.equals(padZeroes(a), padZeroes(b)); } catch /* istanbul ignore next */ { return pep440.equals(a, b); } } function getMajor(version: string): number | null { try { return npm.getMajor(padZeroes(version)); } catch /* istanbul ignore next */ { return pep440.getMajor(version); } } function getMinor(version: string): number | null { try { return npm.getMinor(padZeroes(version)); } catch /* istanbul ignore next */ { return pep440.getMinor(version); } } function getPatch(version: string): number | null { try { return npm.getPatch(padZeroes(version)); } catch /* istanbul ignore next */ { return pep440.getPatch(version); } } function isGreaterThan(a: string, b: string): boolean { try { return npm.isGreaterThan(padZeroes(a), padZeroes(b)); } catch /* istanbul ignore next */ { return pep440.isGreaterThan(a, b); } } function isLessThanRange(version: string, range: string): boolean { return ( npm.isVersion(padZeroes(version)) && !!npm.isLessThanRange?.(padZeroes(version), rez2npm(range)) ); } export function isValid(input: string): boolean { return npm.isValid(rez2npm(input)); } function isStable(version: string): boolean { return npm.isStable(padZeroes(version)); } function isVersion(input: string): boolean { return npm.isVersion(padZeroes(rez2npm(input))); } function matches(version: string, range: string): boolean { return ( npm.isVersion(padZeroes(version)) && npm.matches(padZeroes(version), rez2npm(range)) ); } function getSatisfyingVersion( versions: string[], range: string, ): string | null { return npm.getSatisfyingVersion(versions, rez2npm(range)); } function minSatisfyingVersion( versions: string[], range: string, ): string | null { return npm.minSatisfyingVersion(versions, rez2npm(range)); } function isSingleVersion(constraint: string): boolean { return ( (constraint.trim().startsWith('==') && isVersion(constraint.trim().substring(2).trim())) || isVersion(constraint.trim()) ); } function sortVersions(a: string, b: string): number { return npm.sortVersions(padZeroes(a), padZeroes(b)); } function matchVersionPrecision( currentValue: string, newVersion: string, ): string | null { if (!matchVersion.test(currentValue) || !isVersion(newVersion)) { return null; } const precision = currentValue.split('.').length; return newVersion.split('.').slice(0, precision).join('.'); } function getNewValue({ currentValue, rangeStrategy, currentVersion, newVersion, }: NewValueConfig): string | null { const precisionMatchedVersion = matchVersionPrecision( currentValue, newVersion, ); if (precisionMatchedVersion) { return precisionMatchedVersion; } const pep440Value = pep440.getNewValue({ currentValue: rez2pep440(currentValue), rangeStrategy, currentVersion, newVersion, }); if (exactVersion.test(currentValue)) { return pep440Value; } if (pep440Value && inclusiveBound.test(currentValue)) { return pep4402rezInclusiveBound(pep440Value); } if (pep440Value && lowerBound.test(currentValue)) { if (currentValue.includes('+')) { return npm2rezplus(pep440Value); } return pep440Value; } if (pep440Value && upperBound.test(currentValue)) { return pep440Value; } const matchAscRange = ascendingRange.exec(currentValue); if (pep440Value && matchAscRange?.groups) { // Replace version numbers but keep rez format, otherwise we just end up trying // to convert every single case separately. const lowerBoundAscCurrent = matchAscRange.groups.range_lower_asc; const upperBoundAscCurrent = matchAscRange.groups.range_upper_asc; const lowerAscVersionCurrent = matchAscRange.groups.range_lower_asc_version; const upperAscVersionCurrent = matchAscRange.groups.range_upper_asc_version; const [lowerBoundAscPep440, upperBoundAscPep440] = pep440Value.split(', '); const lowerAscVersionNew = coerceString( regEx(versionGroup).exec(lowerBoundAscPep440)?.[0], ); const upperAscVersionNew = coerceString( regEx(versionGroup).exec(upperBoundAscPep440)?.[0], ); const lowerBoundAscNew = lowerBoundAscCurrent.replace( lowerAscVersionCurrent, lowerAscVersionNew, ); const upperBoundAscNew = upperBoundAscCurrent.replace( upperAscVersionCurrent, upperAscVersionNew, ); const separator = currentValue.includes(',') ? ',' : ''; return lowerBoundAscNew + separator + upperBoundAscNew; } const matchDscRange = descendingRange.exec(currentValue); if (pep440Value && matchDscRange?.groups) { // Replace version numbers but keep rez format, otherwise we just end up trying // to convert every single case separately. const upperBoundDescCurrent = matchDscRange.groups.range_upper_desc; const lowerBoundDescCurrent = matchDscRange.groups.range_lower_desc; const upperDescVersionCurrent = matchDscRange.groups.range_upper_desc_version; const lowerDescVersionCurrent = matchDscRange.groups.range_lower_desc_version; const [lowerBoundDescPep440, upperBoundDescPep440] = pep440Value.split(', '); const upperDescVersionNew = coerceString( regEx(versionGroup).exec(upperBoundDescPep440)?.[0], ); const lowerDescVersionNew = coerceString( regEx(versionGroup).exec(lowerBoundDescPep440)?.[0], ); const upperBoundDescNew = upperBoundDescCurrent.replace( upperDescVersionCurrent, upperDescVersionNew, ); const lowerBoundDescNew = lowerBoundDescCurrent.replace( lowerDescVersionCurrent, lowerDescVersionNew, ); // Descending ranges are only supported with a comma. const separator = ','; return upperBoundDescNew + separator + lowerBoundDescNew; } return null; } function isCompatible(version: string): boolean { return isVersion(version); } export const api: VersioningApi = { equals, getMajor, getMinor, getPatch, getNewValue, getSatisfyingVersion, isCompatible, isGreaterThan, isLessThanRange, isSingleVersion, isStable, isValid, isVersion, matches, minSatisfyingVersion, sortVersions, }; export default api;