Skip to content

Commit

Permalink
feat(composer): support stability modifiers (#6050) (#6057)
Browse files Browse the repository at this point in the history
  • Loading branch information
hussainweb committed May 1, 2020
1 parent e1b4b7f commit 8f66b5e
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 14 deletions.
62 changes: 62 additions & 0 deletions lib/versioning/composer/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ describe('semver.equals(a, b)', () => {
it('should pad really short version', () => {
expect(semver.equals('v1.0.0', '1')).toBe(true);
});
it('should translate stability modifier', () => {
expect(semver.equals('1.0@alpha3', '1.0.0-alpha.3')).toBe(true);
expect(semver.equals('1.0@beta', '1.0.0-beta')).toBe(true);
expect(semver.equals('1.0@rc2', '1.0.0-rc.2')).toBe(true);
});
});
describe('semver.isGreaterThan(a, b)', () => {
it('should pad short version', () => {
Expand Down Expand Up @@ -49,6 +54,11 @@ describe('semver.isValid(input)', () => {
expect(semver.isValid('^1.2.3')).toBeTruthy();
expect(semver.isValid('>1.2.3')).toBeTruthy();
});
it('should support ranges with stability modifiers', () => {
expect(semver.isValid('~1.2.3@beta1')).toBeTruthy();
expect(semver.isValid('^1.2.3@alpha')).toBeTruthy();
expect(semver.isValid('>1.2.3@rc2')).toBeTruthy();
});
});
describe('semver.isVersion(input)', () => {
it('should support simple semver', () => {
Expand Down Expand Up @@ -88,6 +98,22 @@ describe('semver.maxSatisfyingVersion()', () => {
)
).toBe('0.5.0');
});
it('handles prereleases', () => {
expect(
semver.maxSatisfyingVersion(
[
'0.4.0',
'0.5.0',
'4.0.0-beta1',
'4.0.0-beta2',
'4.2.0-beta1',
'4.2.0-beta2',
'5.0.0',
],
'~4@beta'
)
).toBe('4.0.0-beta2');
});
});
describe('semver.minSatisfyingVersion()', () => {
it('handles massaged tilde', () => {
Expand All @@ -110,6 +136,22 @@ describe('semver.minSatisfyingVersion()', () => {
)
).toBe('0.4.0');
});
it('handles prereleases', () => {
expect(
semver.minSatisfyingVersion(
[
'0.4.0',
'0.5.0',
'4.0.0-beta1',
'4.0.0',
'4.2.0-beta1',
'4.2.0-beta2',
'5.0.0',
],
'~4@beta'
)
).toBe('4.0.0-beta1');
});
});
describe('semver.matches()', () => {
it('handles massaged tilde', () => {
Expand Down Expand Up @@ -286,6 +328,26 @@ describe('semver.getNewValue()', () => {
})
).toEqual('^v1.1');
});
it('bumps short caret with stability modifiers', () => {
expect(
semver.getNewValue({
currentValue: '^v1.0@beta',
rangeStrategy: 'bump',
fromVersion: '1.0.0-beta3',
toVersion: '1.0.0-beta5',
})
).toEqual('^v1.0.0@beta5');
});
it('replaces short caret with stability modifiers', () => {
expect(
semver.getNewValue({
currentValue: '^v1.0@beta',
rangeStrategy: 'replace',
fromVersion: '1.0.0-beta3',
toVersion: '2.0.0-beta5',
})
).toEqual('^v2.0.0@beta5');
});
it('handles differing lengths', () => {
expect(
semver.getNewValue({
Expand Down
62 changes: 48 additions & 14 deletions lib/versioning/composer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,66 @@ export const urls = [
export const supportsRanges = true;
export const supportedRangeStrategies = ['bump', 'extend', 'pin', 'replace'];

function getVersionParts(input: string): [string, string] {
const versionParts = input.split('-');
if (versionParts.length === 1) {
return [input, ''];
}

return [versionParts[0], '-' + versionParts[1]];
}

function padZeroes(input: string): string {
const sections = input.split('.');
const [output, stability] = getVersionParts(input);

const sections = output.split('.');
while (sections.length < 3) {
sections.push('0');
}
return sections.join('.');
return sections.join('.') + stability;
}

function removeLeadingV(input: string): string {
return input.replace(/^v/i, '');
function convertStabilitiyModifier(input: string): string {
// Handle stability modifiers.
const versionParts = input.split('@');
if (versionParts.length === 1) {
return input;
}

// 1.0@beta2 to 1.0-beta.2
const stability = versionParts[1].replace(
/(?:^|\s)(beta|alpha|rc)([1-9][0-9]*)(?: |$)/gi,
'$1.$2'
);

// If there is a stability part, npm semver expects the version
// to be full
return padZeroes(versionParts[0]) + '-' + stability;
}

function normalizeVersion(input: string): string {
let output = input;
output = output.replace(/(^|>|>=|\^|~)v/i, '$1');
return convertStabilitiyModifier(output);
}

function composer2npm(input: string): string {
const cleanInput = removeLeadingV(input);
const cleanInput = normalizeVersion(input);
if (npm.isVersion(cleanInput)) {
return cleanInput;
}
if (npm.isVersion(padZeroes(cleanInput))) {
return padZeroes(cleanInput);
}
let output = cleanInput;
const [versionId, stability] = getVersionParts(cleanInput);
let output = versionId;

// ~4 to ^4 and ~4.1 to ^4.1
output = output.replace(/(?:^|\s)~([1-9][0-9]*(?:\.[0-9]*)?)(?: |$)/g, '^$1');
// ~0.4 to >=0.4 <1
output = output.replace(/(?:^|\s)~(0\.[1-9][0-9]*)(?: |$)/g, '>=$1 <1');
return output;

return output + stability;
}

const equals = (a: string, b: string): boolean =>
Expand Down Expand Up @@ -116,15 +150,15 @@ function getNewValue({
newValue = `${operator}${toMajor}.${toMinor}`;
}
} else if (
npm.isVersion(padZeroes(toVersion)) &&
npm.isValid(currentValue) &&
composer2npm(currentValue) === removeLeadingV(currentValue)
npm.isVersion(padZeroes(normalizeVersion(toVersion))) &&
npm.isValid(normalizeVersion(currentValue)) &&
composer2npm(currentValue) === normalizeVersion(currentValue)
) {
newValue = npm.getNewValue({
currentValue,
currentValue: normalizeVersion(currentValue),
rangeStrategy,
fromVersion,
toVersion: padZeroes(toVersion),
fromVersion: normalizeVersion(fromVersion),
toVersion: padZeroes(normalizeVersion(toVersion)),
});
}
if (currentValue.includes(' || ')) {
Expand All @@ -151,7 +185,7 @@ function getNewValue({
if (currentValue.split('.')[0].includes('v')) {
newValue = newValue.replace(/([0-9])/, 'v$1');
}
return newValue;
return newValue.replace('-', '@');
}

function sortVersions(a: string, b: string): number {
Expand Down

0 comments on commit 8f66b5e

Please sign in to comment.