Skip to content

Commit

Permalink
feat(versioning): add devbox versioning module (#31408)
Browse files Browse the repository at this point in the history
Co-authored-by: Rhys Arkins <rhys@arkins.net>
  • Loading branch information
burritobill and rarkins authored Dec 20, 2024
1 parent dc6bf16 commit 01a3c2f
Show file tree
Hide file tree
Showing 4 changed files with 181 additions and 0 deletions.
2 changes: 2 additions & 0 deletions lib/modules/versioning/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import * as composer from './composer';
import * as conan from './conan';
import * as deb from './deb';
import * as debian from './debian';
import * as devbox from './devbox';
import * as docker from './docker';
import * as git from './git';
import * as glasskube from './glasskube';
Expand Down Expand Up @@ -52,6 +53,7 @@ api.set(composer.id, composer.api);
api.set(conan.id, conan.api);
api.set(deb.id, deb.api);
api.set(debian.id, debian.api);
api.set(devbox.id, devbox.api);
api.set(docker.id, docker.api);
api.set(git.id, git.api);
api.set(glasskube.id, glasskube.api);
Expand Down
103 changes: 103 additions & 0 deletions lib/modules/versioning/devbox/index.spec.ts
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);
},
);
});
74 changes: 74 additions & 0 deletions lib/modules/versioning/devbox/index.ts
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;
2 changes: 2 additions & 0 deletions lib/modules/versioning/devbox/readme.md
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.

0 comments on commit 01a3c2f

Please sign in to comment.