-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(versioning): add devbox versioning module (#31408)
Co-authored-by: Rhys Arkins <rhys@arkins.net>
- Loading branch information
1 parent
dc6bf16
commit 01a3c2f
Showing
4 changed files
with
181 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import devbox from '.'; | ||
|
||
describe('modules/versioning/devbox/index', () => { | ||
it.each` | ||
version | expected | ||
${'1'} | ${false} | ||
${'01'} | ${false} | ||
${'1.01'} | ${false} | ||
${'1.1'} | ${false} | ||
${'1.3.0'} | ${true} | ||
${'2.1.20'} | ${true} | ||
${'v1.4'} | ${false} | ||
${'V0.5'} | ${false} | ||
${'3.5.0'} | ${true} | ||
${'4.2.21.Final'} | ${false} | ||
${'1234'} | ${false} | ||
${'foo'} | ${false} | ||
${'latest'} | ${false} | ||
${''} | ${false} | ||
${'3.5.0-beta.3'} | ${false} | ||
${'*'} | ${false} | ||
${'x'} | ${false} | ||
${'X'} | ${false} | ||
${'~1.2.3'} | ${false} | ||
${'>1.2.3'} | ${false} | ||
${'^1.2.3'} | ${false} | ||
${'1.2.3-foo'} | ${false} | ||
${'1.2.3foo'} | ${false} | ||
`('isVersion("$version") === $expected', ({ version, expected }) => { | ||
expect(!!devbox.isVersion(version)).toBe(expected); | ||
}); | ||
|
||
it.each` | ||
version | isValid | ||
${'1'} | ${true} | ||
${'01'} | ${false} | ||
${'1.01'} | ${false} | ||
${'1.1'} | ${true} | ||
${'1.3.0'} | ${true} | ||
${'2.1.20'} | ${true} | ||
${'v1.4'} | ${false} | ||
${'V0.5'} | ${false} | ||
${'3.5.0'} | ${true} | ||
${'4.2.21.Final'} | ${false} | ||
${'1234'} | ${true} | ||
${'foo'} | ${false} | ||
${'latest'} | ${true} | ||
${''} | ${false} | ||
${'3.5.0-beta.3'} | ${false} | ||
${'*'} | ${false} | ||
${'x'} | ${false} | ||
${'X'} | ${false} | ||
${'~1.2.3'} | ${false} | ||
${'>1.2.3'} | ${false} | ||
${'^1.2.3'} | ${false} | ||
${'1.2.3-foo'} | ${false} | ||
${'1.2.3foo'} | ${false} | ||
`('isValid("$version") === $isValid', ({ version, isValid }) => { | ||
expect(!!devbox.isValid(version)).toBe(isValid); | ||
}); | ||
|
||
it.each` | ||
version | range | expected | ||
${'1'} | ${'1'} | ${false} | ||
${'1'} | ${'0'} | ${false} | ||
${'1.2.3'} | ${'1'} | ${true} | ||
${'1.2'} | ${'1'} | ${false} | ||
${'1.0.0'} | ${'1'} | ${true} | ||
${'1.2.0'} | ${'1.2'} | ${true} | ||
${'1.2.3'} | ${'1.2'} | ${true} | ||
${'0'} | ${'latest'} | ${false} | ||
${'1.2.3'} | ${'latest'} | ${true} | ||
${'1.2.3.5'} | ${'1.2.3.5'} | ${false} | ||
${'1.2'} | ${'1.2.3'} | ${false} | ||
`( | ||
'matches("$version", "$range") === $expected', | ||
({ version, range, expected }) => { | ||
expect(devbox.matches(version, range)).toBe(expected); | ||
}, | ||
); | ||
|
||
it.each` | ||
version | range | expected | ||
${'1'} | ${'1'} | ${true} | ||
${'1'} | ${'0'} | ${false} | ||
${'1.2.3'} | ${'1'} | ${true} | ||
${'1.2'} | ${'1'} | ${true} | ||
${'1.0.0'} | ${'1'} | ${true} | ||
${'1.2.0'} | ${'1.2'} | ${true} | ||
${'1.2.3'} | ${'1.2'} | ${true} | ||
${'0'} | ${'latest'} | ${true} | ||
${'1.2.3'} | ${'latest'} | ${true} | ||
${'1.2.3.5'} | ${'1.2.3.5'} | ${false} | ||
${'latest'} | ${'latest'} | ${false} | ||
${'latest'} | ${'1.2.3'} | ${false} | ||
${'1.2'} | ${'1.2.3'} | ${true} | ||
`( | ||
'equals("$version", "$range") === $expected', | ||
({ version, range, expected }) => { | ||
expect(devbox.equals(version, range)).toBe(expected); | ||
}, | ||
); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import { regEx } from '../../../util/regex'; | ||
import type { GenericVersion } from '../generic'; | ||
import { GenericVersioningApi } from '../generic'; | ||
import type { VersioningApi } from '../types'; | ||
|
||
export const id = 'devbox'; | ||
export const displayName = 'devbox'; | ||
export const urls = []; | ||
export const supportsRanges = false; | ||
|
||
const validPattern = regEx(/^((\d|[1-9]\d*)(\.(\d|[1-9]\d*)){0,2})$/); | ||
const versionPattern = regEx(/^((\d|[1-9]\d*)(\.(\d|[1-9]\d*)){2})$/); | ||
|
||
class DevboxVersioningApi extends GenericVersioningApi { | ||
protected _parse(version: string): GenericVersion | null { | ||
const matches = validPattern.exec(version); | ||
if (!matches) { | ||
return null; | ||
} | ||
const release = matches[0].split('.').map(Number); | ||
return { release }; | ||
} | ||
|
||
override isValid(version: string): boolean { | ||
if (version === 'latest') { | ||
return true; | ||
} | ||
return this._parse(version) !== null; | ||
} | ||
|
||
override isVersion(version: string): boolean { | ||
if (version === 'latest') { | ||
return false; | ||
} | ||
const matches = versionPattern.exec(version); | ||
return !!matches; | ||
} | ||
|
||
override matches(version: string, range: string): boolean { | ||
return this.isVersion(version) && this.equals(version, range); | ||
} | ||
|
||
protected override _compare(version: string, other: string): number { | ||
const parsed1 = this._parse(version); | ||
const parsed2 = this._parse(other); | ||
|
||
// Treat "latest" as * and always return equal | ||
if (other === 'latest' && parsed1) { | ||
return 0; | ||
} | ||
|
||
// If either version is invalid, return unequal | ||
if (!(parsed1 && parsed2)) { | ||
return 1; | ||
} | ||
// support variable length compare | ||
const length = Math.max(parsed1.release.length, parsed2.release.length); | ||
for (let i = 0; i < length; i += 1) { | ||
// 2.1 and 2.1.0 are equivalent | ||
const part1 = parsed1.release[i]; | ||
const part2 = parsed2.release[i]; | ||
// if part1 or part2 is undefined, we should treat them as equal | ||
// e.g. 1.0.0 === 1.0 | ||
if (part1 !== undefined && part2 !== undefined && part1 !== part2) { | ||
return part1 - part2; | ||
} | ||
} | ||
return 0; | ||
} | ||
} | ||
|
||
export const api: VersioningApi = new DevboxVersioningApi(); | ||
|
||
export default api; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
Devbox's Nixhub uses fairly strict versioning, characters such as ~, ^ and >= are not allowed. | ||
The semver values must not include "\*" or "x". "1.2.3" "1.2" and "1" are the only valid formats. |