/
extract.ts
86 lines (84 loc) · 2.85 KB
/
extract.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
import { validRange } from 'semver';
import * as datasourceGo from '../../datasource/go';
import { logger } from '../../logger';
import { SkipReason } from '../../types';
import { isVersion } from '../../versioning/semver';
import type { PackageDependency, PackageFile } from '../types';
function getDep(
lineNumber: number,
match: RegExpMatchArray,
type: string
): PackageDependency {
const [, , currentValue] = match;
let [, depName] = match;
depName = depName.replace(/"/g, '');
const dep: PackageDependency = {
managerData: {
lineNumber,
},
depName,
depType: type,
currentValue,
};
if (isVersion(currentValue)) {
dep.datasource = datasourceGo.id;
} else {
dep.skipReason = SkipReason.UnsupportedVersion;
}
const digestMatch = /v0\.0.0-\d{14}-([a-f0-9]{12})/.exec(currentValue);
if (digestMatch) {
[, dep.currentDigest] = digestMatch;
dep.digestOneAndOnly = true;
}
return dep;
}
export function extractPackageFile(content: string): PackageFile | null {
logger.trace({ content }, 'gomod.extractPackageFile()');
const constraints: Record<string, any> = {};
const deps: PackageDependency[] = [];
try {
const lines = content.split('\n');
for (let lineNumber = 0; lineNumber < lines.length; lineNumber += 1) {
let line = lines[lineNumber];
if (line.startsWith('go ') && validRange(line.replace('go ', ''))) {
constraints.go = line.replace('go ', '^');
}
const replaceMatch = /^replace\s+[^\s]+[\s]+[=][>]\s+([^\s]+)\s+([^\s]+)/.exec(
line
);
if (replaceMatch) {
const dep = getDep(lineNumber, replaceMatch, 'replace');
deps.push(dep);
}
const requireMatch = /^require\s+([^\s]+)\s+([^\s]+)/.exec(line);
if (requireMatch && !line.endsWith('// indirect')) {
logger.trace({ lineNumber }, `require line: "${line}"`);
const dep = getDep(lineNumber, requireMatch, 'require');
deps.push(dep);
}
if (line.trim() === 'require (') {
logger.trace(`Matched multi-line require on line ${lineNumber}`);
do {
lineNumber += 1;
line = lines[lineNumber];
const multiMatch = /^\s+([^\s]+)\s+([^\s]+)/.exec(line);
logger.trace(`reqLine: "${line}"`);
if (multiMatch && !line.endsWith('// indirect')) {
logger.trace({ lineNumber }, `require line: "${line}"`);
const dep = getDep(lineNumber, multiMatch, 'require');
dep.managerData.multiLine = true;
deps.push(dep);
} else if (line.trim() !== ')') {
logger.debug(`No multi-line match: ${line}`);
}
} while (line.trim() !== ')');
}
}
} catch (err) /* istanbul ignore next */ {
logger.warn({ err }, 'Error extracting go modules');
}
if (!deps.length) {
return null;
}
return { constraints, deps };
}