Skip to content

Commit 5a2e7e4

Browse files
authored
Add version parsing support for non-numeric patches (to include built… (#853)
* Add version parsing support for non-numeric patches (to include built from source `d.d.SSS`) Closes #852
1 parent 0f964ba commit 5a2e7e4

File tree

3 files changed

+85
-22
lines changed

3 files changed

+85
-22
lines changed

.changeset/green-ants-cough.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"simple-git": patch
3+
---
4+
5+
Add version parsing support for non-numeric patches (including "built from source" style `1.11.GIT`)

simple-git/src/lib/tasks/version.ts

+31-22
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import type { SimpleGitApi } from '../simple-git-api';
22
import type { SimpleGit } from '../../../typings';
3-
import { asNumber, ExitCodes } from '../utils';
3+
import { asNumber, ExitCodes, LineParser, parseStringResponse } from '../utils';
44

55
export interface VersionResult {
66
major: number;
77
minor: number;
8-
patch: number;
8+
patch: number | string;
99
agent: string;
1010
installed: boolean;
1111
}
@@ -15,7 +15,7 @@ const NOT_INSTALLED = 'installed=false';
1515
function versionResponse(
1616
major = 0,
1717
minor = 0,
18-
patch = 0,
18+
patch: string | number = 0,
1919
agent = '',
2020
installed = true
2121
): VersionResult {
@@ -30,7 +30,7 @@ function versionResponse(
3030
'toString',
3131
{
3232
value() {
33-
return `${major}.${minor}.${patch}`;
33+
return `${this.major}.${this.minor}.${this.patch}`;
3434
},
3535
configurable: false,
3636
enumerable: false,
@@ -48,24 +48,7 @@ export default function (): Pick<SimpleGit, 'version'> {
4848
return this._runTask({
4949
commands: ['--version'],
5050
format: 'utf-8',
51-
parser(stdOut) {
52-
if (stdOut === NOT_INSTALLED) {
53-
return notInstalledResponse();
54-
}
55-
56-
const version = /version (\d+)\.(\d+)\.(\d+)(?:\s*\((.+)\))?/.exec(stdOut);
57-
58-
if (!version) {
59-
return versionResponse(0, 0, 0, stdOut);
60-
}
61-
62-
return versionResponse(
63-
asNumber(version[1]),
64-
asNumber(version[2]),
65-
asNumber(version[3]),
66-
version[4] || ''
67-
);
68-
},
51+
parser: versionParser,
6952
onError(result, error, done, fail) {
7053
if (result.exitCode === ExitCodes.NOT_FOUND) {
7154
return done(Buffer.from(NOT_INSTALLED));
@@ -77,3 +60,29 @@ export default function (): Pick<SimpleGit, 'version'> {
7760
},
7861
};
7962
}
63+
64+
const parsers: LineParser<VersionResult>[] = [
65+
new LineParser(
66+
/version (\d+)\.(\d+)\.(\d+)(?:\s*\((.+)\))?/,
67+
(result, [major, minor, patch, agent = '']) => {
68+
Object.assign(
69+
result,
70+
versionResponse(asNumber(major), asNumber(minor), asNumber(patch), agent)
71+
);
72+
}
73+
),
74+
new LineParser(
75+
/version (\d+)\.(\d+)\.(\D+)(.+)?$/,
76+
(result, [major, minor, patch, agent = '']) => {
77+
Object.assign(result, versionResponse(asNumber(major), asNumber(minor), patch, agent));
78+
}
79+
),
80+
];
81+
82+
function versionParser(stdOut: string) {
83+
if (stdOut === NOT_INSTALLED) {
84+
return notInstalledResponse();
85+
}
86+
87+
return parseStringResponse(versionResponse(0, 0, 0, stdOut), parsers, stdOut);
88+
}

simple-git/test/unit/version.spec.ts

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { closeWithError, closeWithSuccess, newSimpleGit } from './__fixtures__';
2+
3+
describe('version', () => {
4+
it('sringifies to version', async () => {
5+
const version = newSimpleGit().version();
6+
await closeWithSuccess('git version 2.50.10 (Apple Git-133)');
7+
8+
expect(String(await version)).toBe('2.50.10');
9+
});
10+
11+
it('detects missing', async () => {
12+
const version = newSimpleGit().version();
13+
await closeWithError('FAIL', -2);
14+
15+
expect(await version).toEqual({
16+
installed: false,
17+
major: 0,
18+
minor: 0,
19+
patch: 0,
20+
agent: '',
21+
});
22+
});
23+
24+
it('parses apple', async () => {
25+
const version = newSimpleGit().version();
26+
await closeWithSuccess('git version 2.32.1 (Apple Git-133)');
27+
28+
expect(await version).toEqual({
29+
installed: true,
30+
major: 2,
31+
minor: 32,
32+
patch: 1,
33+
agent: 'Apple Git-133',
34+
});
35+
});
36+
37+
it('parses git from source', async () => {
38+
const version = newSimpleGit().version();
39+
await closeWithSuccess('git version 2.37.GIT');
40+
41+
expect(await version).toEqual({
42+
installed: true,
43+
major: 2,
44+
minor: 37,
45+
patch: 'GIT',
46+
agent: '',
47+
});
48+
});
49+
});

0 commit comments

Comments
 (0)