-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
index.ts
111 lines (95 loc) · 2.82 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import simpleGit from 'simple-git';
import * as packageCache from '../../util/cache/package';
import * as semver from '../../versioning/semver';
import type { DigestConfig, GetReleasesConfig, ReleaseResult } from '../types';
export const id = 'git-refs';
export const registryUrlRestriction = 'disallowed';
const cacheMinutes = 10;
// git will prompt for known hosts or passwords, unless we activate BatchMode
process.env.GIT_SSH_COMMAND = 'ssh -o BatchMode=yes';
export interface RawRefs {
type: string;
value: string;
hash: string;
}
export async function getRawRefs({
lookupName,
}: GetReleasesConfig): Promise<RawRefs[] | null> {
const git = simpleGit();
const cacheNamespace = 'git-raw-refs';
const cachedResult = await packageCache.get<RawRefs[]>(
cacheNamespace,
lookupName
);
/* istanbul ignore next line */
if (cachedResult) {
return cachedResult;
}
// fetch remote tags
const lsRemote = await git.listRemote([lookupName]);
if (!lsRemote) {
return null;
}
const refMatch = /(?<hash>.*?)\s+refs\/(?<type>.*?)\/(?<value>.*)/;
const headMatch = /(?<hash>.*?)\s+HEAD/;
const refs = lsRemote
.trim()
.split('\n')
.map((line) => line.trim())
.map((line) => {
let match = refMatch.exec(line);
if (match) {
return {
type: match.groups.type,
value: match.groups.value,
hash: match.groups.hash,
};
}
match = headMatch.exec(line);
if (match) {
return {
type: '',
value: 'HEAD',
hash: match.groups.hash,
};
}
// istanbul ignore next
return null;
})
.filter(Boolean)
.filter((ref) => ref.type !== 'pull' && !ref.value.endsWith('^{}'));
await packageCache.set(cacheNamespace, lookupName, refs, cacheMinutes);
return refs;
}
export async function getReleases({
lookupName,
}: GetReleasesConfig): Promise<ReleaseResult | null> {
const rawRefs: RawRefs[] = await getRawRefs({ lookupName });
const refs = rawRefs
.filter((ref) => ref.type === 'tags' || ref.type === 'heads')
.map((ref) => ref.value)
.filter((ref) => semver.isVersion(ref));
const uniqueRefs = [...new Set(refs)];
const sourceUrl = lookupName.replace(/\.git$/, '').replace(/\/$/, '');
const result: ReleaseResult = {
sourceUrl,
releases: uniqueRefs.map((ref) => ({
version: ref,
gitRef: ref,
newDigest: rawRefs.find((rawRef) => rawRef.value === ref).hash,
})),
};
return result;
}
export async function getDigest(
{ lookupName }: Partial<DigestConfig>,
newValue?: string
): Promise<string | null> {
const rawRefs: RawRefs[] = await getRawRefs({ lookupName });
const findValue = newValue || 'HEAD';
const ref = rawRefs.find((rawRef) => rawRef.value === findValue);
if (ref) {
return ref.hash;
}
return null;
}