mirror of
https://github.com/renovatebot/renovate.git
synced 2026-10-30 01:08:06 +00:00
87111d8141
* fix(manager/gomod): match gofmt-style unindented closing paren in block end regex gofmt places the closing ) of require/replace/exclude blocks at column 0, but endBlockRegex required at least one leading whitespace character. This caused inExcludeBlock to never reset after an exclude (...) block formatted by gofmt, silently discarding every subsequent line in the file, including all later require/replace blocks. * fix(manager/gomod): correct test expectation for valid version v0.17.3 is a valid version so no skipReason is set; the test incorrectly asserted skipReason: 'invalid-version', copied from other fixtures using the deliberately invalid v1.2 placeholder.
195 lines
5.0 KiB
TypeScript
195 lines
5.0 KiB
TypeScript
import semver from 'semver';
|
|
import { regEx } from '../../../util/regex.ts';
|
|
import { GoDatasource } from '../../datasource/go/index.ts';
|
|
import { GolangVersionDatasource } from '../../datasource/golang-version/index.ts';
|
|
import { isVersion } from '../../versioning/semver/index.ts';
|
|
import type { PackageDependency } from '../types.ts';
|
|
|
|
function trimQuotes(str: string): string {
|
|
return str.replace(regEx(/^"(?<value>.*)"$/), '$<value>');
|
|
}
|
|
|
|
const requireRegex = regEx(
|
|
/^(?<keyword>require)?\s+(?<module>[^\s]+\/?[^\s]+)\s+(?<version>[^\s]+)(?:\s*\/\/\s*(?<comment>[^\s]+)\s*)?$/,
|
|
);
|
|
|
|
const replaceRegex = regEx(
|
|
/^(?<keyword>replace)?\s+(?<module>[^\s]+\/?[^\s]+)\s*=>\s*(?<replacement>[^\s]+)(?:\s+(?<version>[^\s]+))?(?:\s*\/\/\s*(?<comment>[^\s]+)\s*)?$/,
|
|
);
|
|
|
|
export const excludeBlockStartRegex = regEx(/^(?<keyword>exclude)\s+\(\s*$/);
|
|
|
|
export const endBlockRegex = regEx(/^\s*\)\s*$/);
|
|
|
|
const toolRegex = regEx(/^(?<keyword>tool)?\s+(?<module>[^\s]+\/?[^\s]+)\s*$/);
|
|
|
|
const goVersionRegex = regEx(/^\s*go\s+(?<version>[^\s]+)\s*$/);
|
|
|
|
const toolchainVersionRegex = regEx(/^\s*toolchain\s+go(?<version>[^\s]+)\s*$/);
|
|
|
|
const pseudoVersionRegex = regEx(GoDatasource.pversionRegexp);
|
|
|
|
const placeholderPseudoVersion = 'v0.0.0-00010101000000-000000000000';
|
|
|
|
function extractDigest(input: string): string | undefined {
|
|
const match = pseudoVersionRegex.exec(input);
|
|
return match?.groups?.digest;
|
|
}
|
|
|
|
function isPlaceholderPseudoVersion(version: string): boolean {
|
|
return version === placeholderPseudoVersion;
|
|
}
|
|
|
|
export function parseLine(input: string): PackageDependency | null {
|
|
const goVersionMatches = goVersionRegex.exec(input)?.groups;
|
|
if (goVersionMatches) {
|
|
const { version: currentValue } = goVersionMatches;
|
|
|
|
const dep: PackageDependency = {
|
|
datasource: GolangVersionDatasource.id,
|
|
versioning: 'go-mod-directive',
|
|
depType: 'golang',
|
|
depName: 'go',
|
|
currentValue,
|
|
commitMessageTopic: 'go module directive',
|
|
};
|
|
|
|
if (!semver.validRange(currentValue)) {
|
|
dep.skipReason = 'invalid-version';
|
|
}
|
|
|
|
return dep;
|
|
}
|
|
|
|
const toolchainMatches = toolchainVersionRegex.exec(input)?.groups;
|
|
if (toolchainMatches) {
|
|
const { version: currentValue } = toolchainMatches;
|
|
|
|
const dep: PackageDependency = {
|
|
datasource: GolangVersionDatasource.id,
|
|
depType: 'toolchain',
|
|
depName: 'go',
|
|
currentValue,
|
|
commitMessageTopic: 'go toolchain directive',
|
|
};
|
|
|
|
if (!semver.valid(currentValue)) {
|
|
dep.skipReason = 'invalid-version';
|
|
}
|
|
|
|
return dep;
|
|
}
|
|
|
|
const requireMatches = requireRegex.exec(input)?.groups;
|
|
if (requireMatches) {
|
|
const { keyword, module, version: currentValue, comment } = requireMatches;
|
|
|
|
const depName = trimQuotes(module);
|
|
|
|
const dep: PackageDependency = {
|
|
datasource: GoDatasource.id,
|
|
depType: 'require',
|
|
depName,
|
|
currentValue,
|
|
};
|
|
|
|
if (isVersion(currentValue)) {
|
|
const digest = extractDigest(currentValue);
|
|
if (digest) {
|
|
dep.currentDigest = digest;
|
|
dep.digestOneAndOnly = true;
|
|
dep.versioning = 'loose';
|
|
if (isPlaceholderPseudoVersion(currentValue)) {
|
|
dep.skipReason = 'invalid-version';
|
|
}
|
|
}
|
|
} else {
|
|
dep.skipReason = 'invalid-version';
|
|
}
|
|
|
|
if (comment === 'indirect') {
|
|
dep.depType = 'indirect';
|
|
dep.enabled = false;
|
|
}
|
|
|
|
if (!keyword) {
|
|
dep.managerData = { multiLine: true };
|
|
}
|
|
|
|
return dep;
|
|
}
|
|
|
|
const replaceMatches = replaceRegex.exec(input)?.groups;
|
|
if (replaceMatches) {
|
|
const {
|
|
keyword,
|
|
replacement,
|
|
version: currentValue,
|
|
comment,
|
|
} = replaceMatches;
|
|
|
|
const depName = trimQuotes(replacement);
|
|
|
|
const dep: PackageDependency = {
|
|
datasource: GoDatasource.id,
|
|
depType: 'replace',
|
|
depName,
|
|
currentValue,
|
|
};
|
|
|
|
if (isVersion(currentValue)) {
|
|
const digest = extractDigest(currentValue);
|
|
if (digest) {
|
|
dep.currentDigest = digest;
|
|
dep.digestOneAndOnly = true;
|
|
dep.versioning = 'loose';
|
|
if (isPlaceholderPseudoVersion(currentValue)) {
|
|
dep.skipReason = 'invalid-version';
|
|
}
|
|
}
|
|
} else if (currentValue) {
|
|
dep.skipReason = 'invalid-version';
|
|
} else {
|
|
dep.skipReason = 'unspecified-version';
|
|
delete dep.currentValue;
|
|
}
|
|
|
|
if (comment === 'indirect') {
|
|
dep.depType = 'indirect';
|
|
dep.enabled = false;
|
|
}
|
|
|
|
if (!keyword) {
|
|
dep.managerData = { multiLine: true };
|
|
}
|
|
|
|
if (depName.startsWith('/') || depName.startsWith('.')) {
|
|
dep.skipReason = 'local-dependency';
|
|
}
|
|
|
|
return dep;
|
|
}
|
|
|
|
const toolMatches = toolRegex.exec(input)?.groups;
|
|
if (toolMatches) {
|
|
const { keyword, module } = toolMatches;
|
|
|
|
const depName = trimQuotes(module);
|
|
|
|
const dep: PackageDependency = {
|
|
datasource: GoDatasource.id,
|
|
depType: 'tool',
|
|
depName,
|
|
skipReason: 'unversioned-reference',
|
|
};
|
|
|
|
if (!keyword) {
|
|
dep.managerData = { multiLine: true };
|
|
}
|
|
|
|
return dep;
|
|
}
|
|
|
|
return null;
|
|
}
|