fix: refactor regex to use re2 (#12216)

Co-authored-by: Rhys Arkins <rhys@arkins.net>
This commit is contained in:
RahulGautamSingh 2021-10-20 10:23:49 +05:45 committed by GitHub
parent eef4c2f11f
commit da73178171
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
88 changed files with 519 additions and 376 deletions

View file

@ -2,6 +2,7 @@ import { GalaxyCollectionDatasource } from '../../datasource/galaxy-collection';
import * as datasourceGitTags from '../../datasource/git-tags'; import * as datasourceGitTags from '../../datasource/git-tags';
import * as datasourceGithubTags from '../../datasource/github-tags'; import * as datasourceGithubTags from '../../datasource/github-tags';
import { SkipReason } from '../../types'; import { SkipReason } from '../../types';
import { regEx } from '../../util/regex';
import type { PackageDependency } from '../types'; import type { PackageDependency } from '../types';
import { import {
blockLineRegEx, blockLineRegEx,
@ -17,7 +18,7 @@ function interpretLine(
): void { ): void {
const localDependency = dependency; const localDependency = dependency;
const key = lineMatch[2]; const key = lineMatch[2];
const value = lineMatch[3].replace(/["']/g, ''); const value = lineMatch[3].replace(regEx(/["']/g), '');
switch (key) { switch (key) {
case 'name': { case 'name': {
localDependency.managerData.name = value; localDependency.managerData.name = value;
@ -60,10 +61,13 @@ function handleGitDep(
} }
// source definition without version appendix // source definition without version appendix
const source = nameMatch.groups.source; const source = nameMatch.groups.source;
const massagedDepName = nameMatch.groups.depName.replace(/.git$/, ''); const massagedDepName = nameMatch.groups.depName.replace(
regEx(/.git$/),
''
);
dep.depName = `${nameMatch.groups.hostname}/${massagedDepName}`; dep.depName = `${nameMatch.groups.hostname}/${massagedDepName}`;
// remove leading `git+` from URLs like `git+https://...` // remove leading `git+` from URLs like `git+https://...`
dep.lookupName = source.replace(/git\+/, ''); dep.lookupName = source.replace(regEx(/git\+/), '');
// if version is declared using version appendix `<source url>,v1.2.0`, use it // if version is declared using version appendix `<source url>,v1.2.0`, use it
if (nameMatch.groups.version) { if (nameMatch.groups.version) {

View file

@ -1,4 +1,5 @@
import { logger } from '../../logger'; import { logger } from '../../logger';
import { regEx } from '../../util/regex';
import type { PackageDependency, PackageFile } from '../types'; import type { PackageDependency, PackageFile } from '../types';
import { extractCollections } from './collections'; import { extractCollections } from './collections';
import { extractCollectionsMetaDataFile } from './collections-metadata'; import { extractCollectionsMetaDataFile } from './collections-metadata';
@ -26,7 +27,7 @@ export default function extractPackageFile(
fileName: string fileName: string
): PackageFile | null { ): PackageFile | null {
logger.trace('ansible-galaxy.extractPackageFile()'); logger.trace('ansible-galaxy.extractPackageFile()');
const galaxyFileNameRegEx = /galaxy\.ya?ml$/; const galaxyFileNameRegEx = regEx(/galaxy\.ya?ml$/);
const deps: PackageDependency[] = []; const deps: PackageDependency[] = [];
const lines = content.split('\n'); const lines = content.split('\n');
@ -44,10 +45,12 @@ export default function extractPackageFile(
}; };
// find role and collection block // find role and collection block
lines.forEach((line, index) => { lines.forEach((line, index) => {
if (/^collections:/.exec(line)) { if (regEx(/^collections:/).exec(line)) {
// TODO #12071
positions.collections = index; positions.collections = index;
} }
if (/^roles:/.exec(line)) { if (regEx(/^roles:/).exec(line)) {
// TODO #12071
positions.roles = index; positions.roles = index;
} }
}); });

View file

@ -1,6 +1,7 @@
import { GalaxyDatasource } from '../../datasource/galaxy'; import { GalaxyDatasource } from '../../datasource/galaxy';
import * as datasourceGitTags from '../../datasource/git-tags'; import * as datasourceGitTags from '../../datasource/git-tags';
import { SkipReason } from '../../types'; import { SkipReason } from '../../types';
import { regEx } from '../../util/regex';
import type { PackageDependency } from '../types'; import type { PackageDependency } from '../types';
import { import {
blockLineRegEx, blockLineRegEx,
@ -16,7 +17,7 @@ function interpretLine(
): PackageDependency { ): PackageDependency {
const localDependency: PackageDependency = dependency; const localDependency: PackageDependency = dependency;
const key = lineMatch[2]; const key = lineMatch[2];
const value = lineMatch[3].replace(/["']/g, ''); const value = lineMatch[3].replace(regEx(/["']/g), '');
switch (key) { switch (key) {
case 'name': { case 'name': {
localDependency.managerData.name = value; localDependency.managerData.name = value;
@ -54,9 +55,9 @@ function finalize(dependency: PackageDependency): boolean {
const sourceMatch = nameMatchRegex.exec(source); const sourceMatch = nameMatchRegex.exec(source);
if (sourceMatch) { if (sourceMatch) {
dep.datasource = datasourceGitTags.id; dep.datasource = datasourceGitTags.id;
dep.depName = sourceMatch.groups.depName.replace(/.git$/, ''); dep.depName = sourceMatch.groups.depName.replace(regEx(/.git$/), '');
// remove leading `git+` from URLs like `git+https://...` // remove leading `git+` from URLs like `git+https://...`
dep.lookupName = source.replace(/git\+/, ''); dep.lookupName = source.replace(regEx(/git\+/), '');
} else if (galaxyDepRegex.exec(source)) { } else if (galaxyDepRegex.exec(source)) {
dep.datasource = GalaxyDatasource.id; dep.datasource = GalaxyDatasource.id;
dep.depName = dep.managerData.src; dep.depName = dep.managerData.src;

View file

@ -1,8 +1,12 @@
import { regEx } from '../../util/regex';
export const newBlockRegEx = /^\s*-\s*((\w+):\s*(.*))$/; export const newBlockRegEx = /^\s*-\s*((\w+):\s*(.*))$/;
export const blockLineRegEx = /^\s*((\w+):\s*(.*))$/; export const blockLineRegEx = /^\s*((\w+):\s*(.*))$/;
export const galaxyDepRegex = /[\w-]+\.[\w-]+/; export const galaxyDepRegex = /[\w-]+\.[\w-]+/;
export const dependencyRegex = /^dependencies:/; export const dependencyRegex = /^dependencies:/;
export const galaxyRegEx = export const galaxyRegEx = regEx(
/^\s+(?<lookupName>[\w.]+):\s*["'](?<version>.+)["']\s*/; /^\s+(?<lookupName>[\w.]+):\s*["'](?<version>.+)["']\s*/
export const nameMatchRegex = );
/(?<source>((git\+)?(?:(git|ssh|https?):\/\/)?(.*@)?(?<hostname>[\w.-]+)(?:(:\d+)?\/|:))(?<depName>[\w./-]+)(?:\.git)?)(,(?<version>[\w.]*))?/; export const nameMatchRegex = regEx(
/(?<source>((git\+)?(?:(git|ssh|https?):\/\/)?(.*@)?(?<hostname>[\w.-]+)(?:(:\d+)?\/|:))(?<depName>[\w./-]+)(?:\.git)?)(,(?<version>[\w.]*))?/
);

View file

@ -1,4 +1,5 @@
import { logger } from '../../logger'; import { logger } from '../../logger';
import { regEx } from '../../util/regex';
import * as dockerVersioning from '../../versioning/docker'; import * as dockerVersioning from '../../versioning/docker';
import { getDep } from '../dockerfile/extract'; import { getDep } from '../dockerfile/extract';
import type { PackageDependency, PackageFile } from '../types'; import type { PackageDependency, PackageFile } from '../types';
@ -8,7 +9,7 @@ export default function extractPackageFile(
): PackageFile | null { ): PackageFile | null {
logger.trace('ansible.extractPackageFile()'); logger.trace('ansible.extractPackageFile()');
let deps: PackageDependency[] = []; let deps: PackageDependency[] = [];
const re = /^\s*image:\s*'?"?([^\s'"]+)'?"?\s*$/; const re = regEx(/^\s*image:\s*'?"?([^\s'"]+)'?"?\s*$/);
for (const line of content.split('\n')) { for (const line of content.split('\n')) {
const match = re.exec(line); const match = re.exec(line);
if (match) { if (match) {

View file

@ -1,4 +1,7 @@
export const keyValueExtractionRegex = import { regEx } from '../../util/regex';
/^\s*(?<key>[^\s]+):\s+"?(?<value>[^"\s]+)"?\s*$/;
export const keyValueExtractionRegex = regEx(
/^\s*(?<key>[^\s]+):\s+"?(?<value>[^"\s]+)"?\s*$/
);
// looks for `apiVersion: argoproj.io/ // looks for `apiVersion: argoproj.io/
export const fileTestRegex = /\s*apiVersion:\s*argoproj.io\/\s*/; export const fileTestRegex = regEx(/\s*apiVersion:\s*argoproj.io\/\s*/);

View file

@ -1,9 +1,10 @@
import { id as githubReleaseDatasource } from '../../datasource/github-releases'; import { id as githubReleaseDatasource } from '../../datasource/github-releases';
import { logger } from '../../logger'; import { logger } from '../../logger';
import { regEx } from '../../util/regex';
import { id as semverVersioning } from '../../versioning/semver'; import { id as semverVersioning } from '../../versioning/semver';
import type { PackageDependency, PackageFile } from '../types'; import type { PackageDependency, PackageFile } from '../types';
const VERSION_REGEX = /^\s+VERSION="(.*)"$/m; const VERSION_REGEX = regEx(/^\s+VERSION="(.*)"$/m);
export function extractPackageFile(fileContent: string): PackageFile | null { export function extractPackageFile(fileContent: string): PackageFile | null {
logger.trace('batect.extractPackageFile()'); logger.trace('batect.extractPackageFile()');

View file

@ -8,6 +8,7 @@ import * as datasourceGithubTags from '../../datasource/github-tags';
import * as datasourceGo from '../../datasource/go'; import * as datasourceGo from '../../datasource/go';
import { logger } from '../../logger'; import { logger } from '../../logger';
import { SkipReason } from '../../types'; import { SkipReason } from '../../types';
import { regEx } from '../../util/regex';
import * as dockerVersioning from '../../versioning/docker'; import * as dockerVersioning from '../../versioning/docker';
import type { PackageDependency, PackageFile } from '../types'; import type { PackageDependency, PackageFile } from '../types';
import type { UrlParsedResult } from './types'; import type { UrlParsedResult } from './types';
@ -50,7 +51,7 @@ function parseUrl(urlString: string): UrlParsedResult | null {
const lexer = moo.states({ const lexer = moo.states({
main: { main: {
lineComment: { match: /#.*?$/ }, lineComment: { match: /#.*?$/ }, // TODO #12070
leftParen: { match: '(' }, leftParen: { match: '(' },
rightParen: { match: ')' }, rightParen: { match: ')' },
longDoubleQuoted: { longDoubleQuoted: {
@ -178,48 +179,48 @@ export function extractPackageFile(
let digest: string; let digest: string;
let repository: string; let repository: string;
let registry: string; let registry: string;
let match = /name\s*=\s*"([^"]+)"/.exec(def); let match = regEx(/name\s*=\s*"([^"]+)"/).exec(def);
if (match) { if (match) {
[, depName] = match; [, depName] = match;
} }
match = /digest\s*=\s*"([^"]+)"/.exec(def); match = regEx(/digest\s*=\s*"([^"]+)"/).exec(def);
if (match) { if (match) {
[, digest] = match; [, digest] = match;
} }
match = /registry\s*=\s*"([^"]+)"/.exec(def); match = regEx(/registry\s*=\s*"([^"]+)"/).exec(def);
if (match) { if (match) {
[, registry] = match; [, registry] = match;
} }
match = /repository\s*=\s*"([^"]+)"/.exec(def); match = regEx(/repository\s*=\s*"([^"]+)"/).exec(def);
if (match) { if (match) {
[, repository] = match; [, repository] = match;
} }
match = /remote\s*=\s*"([^"]+)"/.exec(def); match = regEx(/remote\s*=\s*"([^"]+)"/).exec(def);
if (match) { if (match) {
[, remote] = match; [, remote] = match;
} }
match = /tag\s*=\s*"([^"]+)"/.exec(def); match = regEx(/tag\s*=\s*"([^"]+)"/).exec(def);
if (match) { if (match) {
[, currentValue] = match; [, currentValue] = match;
} }
match = /url\s*=\s*"([^"]+)"/.exec(def); match = regEx(/url\s*=\s*"([^"]+)"/).exec(def);
if (match) { if (match) {
[, url] = match; [, url] = match;
} }
match = /urls\s*=\s*\[\s*"([^\]]+)",?\s*\]/.exec(def); match = regEx(/urls\s*=\s*\[\s*"([^\]]+)",?\s*\]/).exec(def);
if (match) { if (match) {
const urls = match[1].replace(/\s/g, '').split('","'); const urls = match[1].replace(regEx(/\s/g), '').split('","');
url = urls.find(parseUrl); url = urls.find(parseUrl);
} }
match = /commit\s*=\s*"([^"]+)"/.exec(def); match = regEx(/commit\s*=\s*"([^"]+)"/).exec(def);
if (match) { if (match) {
[, commit] = match; [, commit] = match;
} }
match = /sha256\s*=\s*"([^"]+)"/.exec(def); match = regEx(/sha256\s*=\s*"([^"]+)"/).exec(def);
if (match) { if (match) {
[, sha256] = match; [, sha256] = match;
} }
match = /importpath\s*=\s*"([^"]+)"/.exec(def); match = regEx(/importpath\s*=\s*"([^"]+)"/).exec(def);
if (match) { if (match) {
[, importpath] = match; [, importpath] = match;
} }
@ -256,10 +257,9 @@ export function extractPackageFile(
dep.datasource = datasourceGo.id; dep.datasource = datasourceGo.id;
dep.lookupName = importpath; dep.lookupName = importpath;
if (remote) { if (remote) {
const remoteMatch = const remoteMatch = regEx(
/https:\/\/github\.com(?:.*\/)(([a-zA-Z]+)([-])?([a-zA-Z]+))/.exec( /https:\/\/github\.com(?:.*\/)(([a-zA-Z]+)([-])?([a-zA-Z]+))/
remote ).exec(remote);
);
if (remoteMatch && remoteMatch[0].length === remote.length) { if (remoteMatch && remoteMatch[0].length === remote.length) {
dep.lookupName = remote.replace('https://', ''); dep.lookupName = remote.replace('https://', '');
} else { } else {
@ -282,7 +282,7 @@ export function extractPackageFile(
const parsedUrl = parseUrl(url); const parsedUrl = parseUrl(url);
dep.depName = depName; dep.depName = depName;
dep.repo = parsedUrl.repo; dep.repo = parsedUrl.repo;
if (/^[a-f0-9]{40}$/i.test(parsedUrl.currentValue)) { if (regEx(/^[a-f0-9]{40}$/i).test(parsedUrl.currentValue)) {
dep.currentDigest = parsedUrl.currentValue; dep.currentDigest = parsedUrl.currentValue;
} else { } else {
dep.currentValue = parsedUrl.currentValue; dep.currentValue = parsedUrl.currentValue;

View file

@ -12,8 +12,8 @@ function updateWithNewVersion(
currentValue: string, currentValue: string,
newValue: string newValue: string
): string { ): string {
const replaceFrom = currentValue.replace(/^v/, ''); const replaceFrom = currentValue.replace(regEx(/^v/), '');
const replaceTo = newValue.replace(/^v/, ''); const replaceTo = newValue.replace(regEx(/^v/), '');
let newContent = content; let newContent = content;
do { do {
newContent = newContent.replace(replaceFrom, replaceTo); newContent = newContent.replace(replaceFrom, replaceTo);
@ -22,7 +22,7 @@ function updateWithNewVersion(
} }
function extractUrl(flattened: string): string[] | null { function extractUrl(flattened: string): string[] | null {
const urlMatch = /url="(.*?)"/.exec(flattened); const urlMatch = regEx(/url="(.*?)"/).exec(flattened);
if (!urlMatch) { if (!urlMatch) {
logger.debug('Cannot locate urls in new definition'); logger.debug('Cannot locate urls in new definition');
return null; return null;
@ -31,16 +31,16 @@ function extractUrl(flattened: string): string[] | null {
} }
function extractUrls(content: string): string[] | null { function extractUrls(content: string): string[] | null {
const flattened = content.replace(/\n/g, '').replace(/\s/g, ''); const flattened = content.replace(regEx(/\n/g), '').replace(regEx(/\s/g), '');
const urlsMatch = /urls?=\[.*?\]/.exec(flattened); const urlsMatch = regEx(/urls?=\[.*?\]/).exec(flattened);
if (!urlsMatch) { if (!urlsMatch) {
return extractUrl(flattened); return extractUrl(flattened);
} }
const urls = urlsMatch[0] const urls = urlsMatch[0]
.replace(/urls?=\[/, '') .replace(regEx(/urls?=\[/), '')
.replace(/,?\]$/, '') .replace(regEx(/,?\]$/), '')
.split(',') .split(',')
.map((url) => url.replace(/"/g, '')); .map((url) => url.replace(regEx(/"/g), ''));
return urls; return urls;
} }
@ -83,7 +83,7 @@ async function getHashFromUrls(urls: string[]): Promise<string | null> {
} }
function setNewHash(content: string, hash: string): string { function setNewHash(content: string, hash: string): string {
return content.replace(/(sha256\s*=\s*)"[^"]+"/, `$1"${hash}"`); return content.replace(regEx(/(sha256\s*=\s*)"[^"]+"/), `$1"${hash}"`);
} }
export async function updateDependency({ export async function updateDependency({
@ -97,19 +97,19 @@ export async function updateDependency({
let newDef: string; let newDef: string;
if (upgrade.depType === 'container_pull') { if (upgrade.depType === 'container_pull') {
newDef = upgrade.managerData.def newDef = upgrade.managerData.def
.replace(/(tag\s*=\s*)"[^"]+"/, `$1"${upgrade.newValue}"`) .replace(regEx(/(tag\s*=\s*)"[^"]+"/), `$1"${upgrade.newValue}"`)
.replace(/(digest\s*=\s*)"[^"]+"/, `$1"${upgrade.newDigest}"`); .replace(regEx(/(digest\s*=\s*)"[^"]+"/), `$1"${upgrade.newDigest}"`);
} }
if ( if (
upgrade.depType === 'git_repository' || upgrade.depType === 'git_repository' ||
upgrade.depType === 'go_repository' upgrade.depType === 'go_repository'
) { ) {
newDef = upgrade.managerData.def newDef = upgrade.managerData.def
.replace(/(tag\s*=\s*)"[^"]+"/, `$1"${upgrade.newValue}"`) .replace(regEx(/(tag\s*=\s*)"[^"]+"/), `$1"${upgrade.newValue}"`)
.replace(/(commit\s*=\s*)"[^"]+"/, `$1"${upgrade.newDigest}"`); .replace(regEx(/(commit\s*=\s*)"[^"]+"/), `$1"${upgrade.newDigest}"`);
if (upgrade.currentDigest && upgrade.updateType !== 'digest') { if (upgrade.currentDigest && upgrade.updateType !== 'digest') {
newDef = newDef.replace( newDef = newDef.replace(
/(commit\s*=\s*)"[^"]+".*?\n/, regEx(/(commit\s*=\s*)"[^"]+".*?\n/),
`$1"${upgrade.newDigest}", # ${upgrade.newValue}\n` `$1"${upgrade.newDigest}", # ${upgrade.newValue}\n`
); );
} }

View file

@ -1,6 +1,7 @@
import * as datasourceGithubTags from '../../datasource/github-tags'; import * as datasourceGithubTags from '../../datasource/github-tags';
import { logger } from '../../logger'; import { logger } from '../../logger';
import { SkipReason } from '../../types'; import { SkipReason } from '../../types';
import { regEx } from '../../util/regex';
import { isVersion } from '../../versioning/semver'; import { isVersion } from '../../versioning/semver';
import type { PackageDependency, PackageFile } from '../types'; import type { PackageDependency, PackageFile } from '../types';
@ -13,16 +14,21 @@ export function extractPackageFile(content: string): PackageFile | null {
for (let lineNumber = 1; lineNumber <= lines.length; lineNumber += 1) { for (let lineNumber = 1; lineNumber <= lines.length; lineNumber += 1) {
const lineIdx = lineNumber - 1; const lineIdx = lineNumber - 1;
const line = lines[lineIdx]; const line = lines[lineIdx];
const pluginsSection = /^(?<pluginsIndent>\s*)(-?\s*)plugins:/.exec(line); const pluginsSection = regEx(
/^(?<pluginsIndent>\s*)(-?\s*)plugins:/
).exec(line); // TODO #12071
if (pluginsSection) { if (pluginsSection) {
logger.trace(`Matched plugins on line ${lineNumber}`); logger.trace(`Matched plugins on line ${lineNumber}`);
isPluginsSection = true; isPluginsSection = true;
pluginsIndent = pluginsSection.groups.pluginsIndent; pluginsIndent = pluginsSection.groups.pluginsIndent;
} else if (isPluginsSection) { } else if (isPluginsSection) {
logger.debug(`serviceImageLine: "${line}"`); logger.debug(`serviceImageLine: "${line}"`);
const { currentIndent } = /^(?<currentIndent>\s*)/.exec(line).groups; const { currentIndent } = regEx(/^(?<currentIndent>\s*)/).exec(
const depLineMatch = line
/^\s+(?:-\s+)?(?<depName>[^#]+)#(?<currentValue>[^:]+)/.exec(line); ).groups; // TODO #12071
const depLineMatch = regEx(
/^\s+(?:-\s+)?(?<depName>[^#]+)#(?<currentValue>[^:]+)/
).exec(line); // TODO #12071
if (currentIndent.length <= pluginsIndent.length) { if (currentIndent.length <= pluginsIndent.length) {
isPluginsSection = false; isPluginsSection = false;
pluginsIndent = ''; pluginsIndent = '';

View file

@ -16,6 +16,7 @@ import {
writeLocalFile, writeLocalFile,
} from '../../util/fs'; } from '../../util/fs';
import { getRepoStatus } from '../../util/git'; import { getRepoStatus } from '../../util/git';
import { regEx } from '../../util/regex';
import { add } from '../../util/sanitize'; import { add } from '../../util/sanitize';
import { isValid } from '../../versioning/ruby'; import { isValid } from '../../versioning/ruby';
import type { UpdateArtifact, UpdateArtifactsResult } from '../types'; import type { UpdateArtifact, UpdateArtifactsResult } from '../types';
@ -46,8 +47,8 @@ async function getRubyConstraint(
if (rubyVersionFileContent) { if (rubyVersionFileContent) {
logger.debug('Using ruby version specified in .ruby-version'); logger.debug('Using ruby version specified in .ruby-version');
rubyConstraint = rubyVersionFileContent rubyConstraint = rubyVersionFileContent
.replace(/^ruby-/, '') .replace(regEx(/^ruby-/), '')
.replace(/\n/g, '') .replace(regEx(/\n/g), '')
.trim(); .trim();
} }
} }
@ -234,7 +235,7 @@ export async function updateArtifacts(
memCache.set('bundlerArtifactsError', BUNDLER_INVALID_CREDENTIALS); memCache.set('bundlerArtifactsError', BUNDLER_INVALID_CREDENTIALS);
throw new Error(BUNDLER_INVALID_CREDENTIALS); throw new Error(BUNDLER_INVALID_CREDENTIALS);
} }
const resolveMatchRe = new RegExp('\\s+(.*) was resolved to', 'g'); const resolveMatchRe = regEx('\\s+(.*) was resolved to', 'g');
if (output.match(resolveMatchRe) && !config.isLockFileMaintenance) { if (output.match(resolveMatchRe) && !config.isLockFileMaintenance) {
logger.debug({ err }, 'Bundler has a resolve error'); logger.debug({ err }, 'Bundler has a resolve error');
const resolveMatches = []; const resolveMatches = [];

View file

@ -23,6 +23,7 @@ export async function extractPackageFile(
sourceMatch = sourceMatch =
sourceMatch || sourceMatch ||
regEx(`^source ${delimiter}([^${delimiter}]+)${delimiter}\\s*$`).exec( regEx(`^source ${delimiter}([^${delimiter}]+)${delimiter}\\s*$`).exec(
// TODO #12071
line line
); );
} }
@ -33,13 +34,13 @@ export async function extractPackageFile(
for (const delimiter of delimiters) { for (const delimiter of delimiters) {
rubyMatch = rubyMatch =
rubyMatch || rubyMatch ||
regEx(`^ruby ${delimiter}([^${delimiter}]+)${delimiter}`).exec(line); regEx(`^ruby ${delimiter}([^${delimiter}]+)${delimiter}`).exec(line); // TODO #12071
} }
if (rubyMatch) { if (rubyMatch) {
res.constraints = { ruby: rubyMatch[1] }; res.constraints = { ruby: rubyMatch[1] };
} }
const gemMatchRegex = const gemMatchRegex =
/^\s*gem\s+(['"])(?<depName>[^'"]+)\1(\s*,\s*(?<currentValue>(['"])[^'"]+\5(\s*,\s*\5[^'"]+\5)?))?/; /^\s*gem\s+(['"])(?<depName>[^'"]+)\1(\s*,\s*(?<currentValue>(['"])[^'"]+\5(\s*,\s*\5[^'"]+\5)?))?/; // TODO #12070 #12071
const gemMatch = gemMatchRegex.exec(line); const gemMatch = gemMatchRegex.exec(line);
if (gemMatch) { if (gemMatch) {
const dep: PackageDependency = { const dep: PackageDependency = {
@ -48,7 +49,7 @@ export async function extractPackageFile(
}; };
if (gemMatch.groups.currentValue) { if (gemMatch.groups.currentValue) {
const currentValue = gemMatch.groups.currentValue; const currentValue = gemMatch.groups.currentValue;
dep.currentValue = /\s*,\s*/.test(currentValue) dep.currentValue = regEx(/\s*,\s*/).test(currentValue) // TODO #12071
? currentValue ? currentValue
: currentValue.slice(1, -1); : currentValue.slice(1, -1);
} else { } else {
@ -59,12 +60,12 @@ export async function extractPackageFile(
} }
res.deps.push(dep); res.deps.push(dep);
} }
const groupMatch = /^group\s+(.*?)\s+do/.exec(line); const groupMatch = regEx(/^group\s+(.*?)\s+do/).exec(line); // TODO #12071
if (groupMatch) { if (groupMatch) {
const depTypes = groupMatch[1] const depTypes = groupMatch[1]
.split(',') .split(',')
.map((group) => group.trim()) .map((group) => group.trim())
.map((group) => group.replace(/^:/, '')); .map((group) => group.replace(regEx(/^:/), '')); // TODO #12071
const groupLineNumber = lineNumber; const groupLineNumber = lineNumber;
let groupContent = ''; let groupContent = '';
let groupLine = ''; let groupLine = '';
@ -72,7 +73,7 @@ export async function extractPackageFile(
lineNumber += 1; lineNumber += 1;
groupLine = lines[lineNumber]; groupLine = lines[lineNumber];
if (groupLine !== 'end') { if (groupLine !== 'end') {
groupContent += (groupLine || '').replace(/^ {2}/, '') + '\n'; groupContent += (groupLine || '').replace(regEx(/^ {2}/), '') + '\n'; // TODO #12071
} }
} }
const groupRes = await extractPackageFile(groupContent); const groupRes = await extractPackageFile(groupContent);
@ -91,7 +92,7 @@ export async function extractPackageFile(
} }
for (const delimiter of delimiters) { for (const delimiter of delimiters) {
const sourceBlockMatch = regEx( const sourceBlockMatch = regEx(
`^source\\s+${delimiter}(.*?)${delimiter}\\s+do` `^source\\s+${delimiter}(.*?)${delimiter}\\s+do` // TODO #12071
).exec(line); ).exec(line);
if (sourceBlockMatch) { if (sourceBlockMatch) {
const repositoryUrl = sourceBlockMatch[1]; const repositoryUrl = sourceBlockMatch[1];
@ -107,7 +108,7 @@ export async function extractPackageFile(
sourceLine = 'end'; sourceLine = 'end';
} }
if (sourceLine !== 'end') { if (sourceLine !== 'end') {
sourceContent += sourceLine.replace(/^ {2}/, '') + '\n'; sourceContent += sourceLine.replace(regEx(/^ {2}/), '') + '\n'; // TODO #12071
} }
} }
const sourceRes = await extractPackageFile(sourceContent); const sourceRes = await extractPackageFile(sourceContent);
@ -125,7 +126,7 @@ export async function extractPackageFile(
} }
} }
} }
const platformsMatch = /^platforms\s+(.*?)\s+do/.test(line); const platformsMatch = regEx(/^platforms\s+(.*?)\s+do/).test(line); // TODO #12071
if (platformsMatch) { if (platformsMatch) {
const platformsLineNumber = lineNumber; const platformsLineNumber = lineNumber;
let platformsContent = ''; let platformsContent = '';
@ -134,7 +135,7 @@ export async function extractPackageFile(
lineNumber += 1; lineNumber += 1;
platformsLine = lines[lineNumber]; platformsLine = lines[lineNumber];
if (platformsLine !== 'end') { if (platformsLine !== 'end') {
platformsContent += platformsLine.replace(/^ {2}/, '') + '\n'; platformsContent += platformsLine.replace(regEx(/^ {2}/), '') + '\n'; // TODO #12071
} }
} }
const platformsRes = await extractPackageFile(platformsContent); const platformsRes = await extractPackageFile(platformsContent);
@ -151,7 +152,7 @@ export async function extractPackageFile(
); );
} }
} }
const ifMatch = /^if\s+(.*?)/.test(line); const ifMatch = regEx(/^if\s+(.*?)/).test(line); // TODO #12071
if (ifMatch) { if (ifMatch) {
const ifLineNumber = lineNumber; const ifLineNumber = lineNumber;
let ifContent = ''; let ifContent = '';
@ -160,7 +161,7 @@ export async function extractPackageFile(
lineNumber += 1; lineNumber += 1;
ifLine = lines[lineNumber]; ifLine = lines[lineNumber];
if (ifLine !== 'end') { if (ifLine !== 'end') {
ifContent += ifLine.replace(/^ {2}/, '') + '\n'; ifContent += ifLine.replace(regEx(/^ {2}/), '') + '\n'; // TODO #12071
} }
} }
const ifRes = await extractPackageFile(ifContent); const ifRes = await extractPackageFile(ifContent);
@ -194,7 +195,9 @@ export async function extractPackageFile(
dep.lockedVersion = lockedDepValue; dep.lockedVersion = lockedDepValue;
} }
} }
const bundledWith = /\nBUNDLED WITH\n\s+(.*?)(\n|$)/.exec(lockContent); const bundledWith = regEx(/\nBUNDLED WITH\n\s+(.*?)(\n|$)/).exec(
lockContent
);
if (bundledWith) { if (bundledWith) {
res.constraints = res.constraints || {}; res.constraints = res.constraints || {};
res.constraints.bundler = bundledWith[1]; res.constraints.bundler = bundledWith[1];

View file

@ -1,7 +1,7 @@
import { logger } from '../../logger'; import { logger } from '../../logger';
import { isVersion } from '../../versioning/ruby'; import { isVersion } from '../../versioning/ruby';
const DEP_REGEX = new RegExp('(?<=\\().*(?=\\))'); const DEP_REGEX = new RegExp('(?<=\\().*(?=\\))'); // TODO #12070
export function extractLockFileEntries( export function extractLockFileEntries(
lockFileContent: string lockFileContent: string
): Map<string, string> { ): Map<string, string> {

View file

@ -2,6 +2,7 @@ import moo from 'moo';
import { ProgrammingLanguage } from '../../constants'; import { ProgrammingLanguage } from '../../constants';
import { id as datasource } from '../../datasource/nuget'; import { id as datasource } from '../../datasource/nuget';
import { SkipReason } from '../../types'; import { SkipReason } from '../../types';
import { regEx } from '../../util/regex';
import { PackageDependency, PackageFile } from '../types'; import { PackageDependency, PackageFile } from '../types';
export const language = ProgrammingLanguage.NET; export const language = ProgrammingLanguage.NET;
@ -12,13 +13,13 @@ export const defaultConfig = {
const lexer = moo.states({ const lexer = moo.states({
main: { main: {
lineComment: { match: /\/\/.*?$/ }, lineComment: { match: /\/\/.*?$/ }, // TODO #12070
multiLineComment: { match: /\/\*[^]*?\*\//, lineBreaks: true }, multiLineComment: { match: /\/\*[^]*?\*\//, lineBreaks: true }, // TODO #12070
dependency: { dependency: {
match: /^#(?:addin|tool|module|load|l)\s+(?:nuget|dotnet):.*$/, match: /^#(?:addin|tool|module|load|l)\s+(?:nuget|dotnet):.*$/, // TODO #12070
}, },
dependencyQuoted: { dependencyQuoted: {
match: /^#(?:addin|tool|module|load|l)\s+"(?:nuget|dotnet):[^"]+"\s*$/, match: /^#(?:addin|tool|module|load|l)\s+"(?:nuget|dotnet):[^"]+"\s*$/, // TODO #12070
value: (s: string) => s.trim().slice(1, -1), value: (s: string) => s.trim().slice(1, -1),
}, },
unknown: moo.fallback, unknown: moo.fallback,
@ -27,7 +28,7 @@ const lexer = moo.states({
function parseDependencyLine(line: string): PackageDependency | null { function parseDependencyLine(line: string): PackageDependency | null {
try { try {
let url = line.replace(/^[^:]*:/, ''); let url = line.replace(regEx(/^[^:]*:/), '');
const isEmptyHost = url.startsWith('?'); const isEmptyHost = url.startsWith('?');
url = isEmptyHost ? `http://localhost/${url}` : url; url = isEmptyHost ? `http://localhost/${url}` : url;

View file

@ -7,6 +7,7 @@ import {
readLocalFile, readLocalFile,
writeLocalFile, writeLocalFile,
} from '../../util/fs'; } from '../../util/fs';
import { regEx } from '../../util/regex';
import type { UpdateArtifact, UpdateArtifactsResult } from '../types'; import type { UpdateArtifact, UpdateArtifactsResult } from '../types';
async function cargoUpdate( async function cargoUpdate(
@ -39,7 +40,7 @@ async function cargoUpdate(
// by the outer try { } catch {} and processed normally. // by the outer try { } catch {} and processed normally.
const msgStart = 'error: There are multiple'; const msgStart = 'error: There are multiple';
if (err.code === 101 && err.stderr.startsWith(msgStart)) { if (err.code === 101 && err.stderr.startsWith(msgStart)) {
cmd = cmd.replace(/ --package.*/, ''); cmd = cmd.replace(regEx(/ --package.*/), '');
await exec(cmd, execOptions); await exec(cmd, execOptions);
} else { } else {
throw err; // this is caught below throw err; // this is caught below

View file

@ -1,8 +1,10 @@
import { CdnJsDatasource } from '../../datasource/cdnjs'; import { CdnJsDatasource } from '../../datasource/cdnjs';
import { regEx } from '../../util/regex';
import type { PackageDependency, PackageFile } from '../types'; import type { PackageDependency, PackageFile } from '../types';
export const cloudflareUrlRegex = export const cloudflareUrlRegex = regEx(
/\/\/cdnjs\.cloudflare\.com\/ajax\/libs\/(?<depName>[^/]+?)\/(?<currentValue>[^/]+?)\/(?<asset>[-/_.a-zA-Z0-9]+)/; /\/\/cdnjs\.cloudflare\.com\/ajax\/libs\/(?<depName>[^/]+?)\/(?<currentValue>[^/]+?)\/(?<asset>[-/_.a-zA-Z0-9]+)/
);
export function extractPackageFile(content: string): PackageFile { export function extractPackageFile(content: string): PackageFile {
const deps: PackageDependency[] = []; const deps: PackageDependency[] = [];

View file

@ -1,5 +1,6 @@
import { OrbDatasource } from '../../datasource/orb'; import { OrbDatasource } from '../../datasource/orb';
import { logger } from '../../logger'; import { logger } from '../../logger';
import { regEx } from '../../util/regex';
import * as npmVersioning from '../../versioning/npm'; import * as npmVersioning from '../../versioning/npm';
import { getDep } from '../dockerfile/extract'; import { getDep } from '../dockerfile/extract';
import type { PackageDependency, PackageFile } from '../types'; import type { PackageDependency, PackageFile } from '../types';
@ -10,7 +11,7 @@ export function extractPackageFile(content: string): PackageFile | null {
const lines = content.split('\n'); const lines = content.split('\n');
for (let lineNumber = 0; lineNumber < lines.length; lineNumber += 1) { for (let lineNumber = 0; lineNumber < lines.length; lineNumber += 1) {
const line = lines[lineNumber]; const line = lines[lineNumber];
const orbs = /^\s*orbs:\s*$/.exec(line); const orbs = regEx(/^\s*orbs:\s*$/).exec(line); // TODO #12071
if (orbs) { if (orbs) {
logger.trace(`Matched orbs on line ${lineNumber}`); logger.trace(`Matched orbs on line ${lineNumber}`);
let foundOrbOrNoop: boolean; let foundOrbOrNoop: boolean;
@ -18,14 +19,14 @@ export function extractPackageFile(content: string): PackageFile | null {
foundOrbOrNoop = false; foundOrbOrNoop = false;
const orbLine = lines[lineNumber + 1]; const orbLine = lines[lineNumber + 1];
logger.trace(`orbLine: "${orbLine}"`); logger.trace(`orbLine: "${orbLine}"`);
const yamlNoop = /^\s*(#|$)/.exec(orbLine); const yamlNoop = regEx(/^\s*(#|$)/).exec(orbLine); // TODO #12071
if (yamlNoop) { if (yamlNoop) {
logger.debug('orbNoop'); logger.debug('orbNoop');
foundOrbOrNoop = true; foundOrbOrNoop = true;
lineNumber += 1; lineNumber += 1;
continue; // eslint-disable-line no-continue continue; // eslint-disable-line no-continue
} }
const orbMatch = /^\s+([^:]+):\s(.+)$/.exec(orbLine); const orbMatch = regEx(/^\s+([^:]+):\s(.+)$/).exec(orbLine); // TODO #12071
if (orbMatch) { if (orbMatch) {
logger.trace('orbMatch'); logger.trace('orbMatch');
foundOrbOrNoop = true; foundOrbOrNoop = true;
@ -46,7 +47,7 @@ export function extractPackageFile(content: string): PackageFile | null {
} }
} while (foundOrbOrNoop); } while (foundOrbOrNoop);
} }
const match = /^\s*-? image:\s*'?"?([^\s'"]+)'?"?\s*$/.exec(line); const match = regEx(/^\s*-? image:\s*'?"?([^\s'"]+)'?"?\s*$/).exec(line); // TODO #12071
if (match) { if (match) {
const currentFrom = match[1]; const currentFrom = match[1];
const dep = getDep(currentFrom); const dep = getDep(currentFrom);

View file

@ -10,9 +10,10 @@ import {
writeLocalFile, writeLocalFile,
} from '../../util/fs'; } from '../../util/fs';
import { getRepoStatus } from '../../util/git'; import { getRepoStatus } from '../../util/git';
import { regEx } from '../../util/regex';
import type { UpdateArtifact, UpdateArtifactsResult } from '../types'; import type { UpdateArtifact, UpdateArtifactsResult } from '../types';
const pluginRegex = /^\s*plugin\s*(['"])(?<plugin>[^'"]+)\1/; const pluginRegex = /^\s*plugin\s*(['"])(?<plugin>[^'"]+)\1/; // TODO #12070
function getPluginCommands(content: string): string[] { function getPluginCommands(content: string): string[] {
const result = new Set<string>(); const result = new Set<string>();
@ -62,7 +63,7 @@ export async function updateArtifacts({
return null; return null;
} }
const match = new RegExp(/^COCOAPODS: (?<cocoapodsVersion>.*)$/m).exec( const match = regEx(/^COCOAPODS: (?<cocoapodsVersion>.*)$/m).exec(
existingLockFileContent existingLockFileContent
); );
const tagConstraint = match?.groups?.cocoapodsVersion ?? null; const tagConstraint = match?.groups?.cocoapodsVersion ?? null;

View file

@ -5,16 +5,17 @@ import * as datasourcePod from '../../datasource/pod';
import { logger } from '../../logger'; import { logger } from '../../logger';
import { SkipReason } from '../../types'; import { SkipReason } from '../../types';
import { getSiblingFileName, localPathExists } from '../../util/fs'; import { getSiblingFileName, localPathExists } from '../../util/fs';
import { regEx } from '../../util/regex';
import type { PackageDependency, PackageFile } from '../types'; import type { PackageDependency, PackageFile } from '../types';
import type { ParsedLine } from './types'; import type { ParsedLine } from './types';
const regexMappings = [ const regexMappings = [
/^\s*pod\s+(['"])(?<spec>[^'"/]+)(\/(?<subspec>[^'"]+))?\1/, /^\s*pod\s+(['"])(?<spec>[^'"/]+)(\/(?<subspec>[^'"]+))?\1/, // TODO #12070
/^\s*pod\s+(['"])[^'"]+\1\s*,\s*(['"])(?<currentValue>[^'"]+)\2\s*$/, /^\s*pod\s+(['"])[^'"]+\1\s*,\s*(['"])(?<currentValue>[^'"]+)\2\s*$/, // TODO #12070
/,\s*:git\s*=>\s*(['"])(?<git>[^'"]+)\1/, /,\s*:git\s*=>\s*(['"])(?<git>[^'"]+)\1/, // TODO #12070
/,\s*:tag\s*=>\s*(['"])(?<tag>[^'"]+)\1/, /,\s*:tag\s*=>\s*(['"])(?<tag>[^'"]+)\1/, // TODO #12070
/,\s*:path\s*=>\s*(['"])(?<path>[^'"]+)\1/, /,\s*:path\s*=>\s*(['"])(?<path>[^'"]+)\1/, // TODO #12070
/^\s*source\s*(['"])(?<source>[^'"]+)\1/, /^\s*source\s*(['"])(?<source>[^'"]+)\1/, // TODO #12070
]; ];
export function parseLine(line: string): ParsedLine { export function parseLine(line: string): ParsedLine {
@ -23,7 +24,7 @@ export function parseLine(line: string): ParsedLine {
return result; return result;
} }
for (const regex of Object.values(regexMappings)) { for (const regex of Object.values(regexMappings)) {
const match = regex.exec(line.replace(/#.*$/, '')); const match = regex.exec(line.replace(regEx(/#.*$/), '')); // TODO #12071
if (match?.groups) { if (match?.groups) {
result = { ...result, ...match.groups }; result = { ...result, ...match.groups };
} }
@ -50,10 +51,9 @@ export function parseLine(line: string): ParsedLine {
export function gitDep(parsedLine: ParsedLine): PackageDependency | null { export function gitDep(parsedLine: ParsedLine): PackageDependency | null {
const { depName, git, tag } = parsedLine; const { depName, git, tag } = parsedLine;
const platformMatch = const platformMatch = regEx(
/[@/](?<platform>github|gitlab)\.com[:/](?<account>[^/]+)\/(?<repo>[^/]+)/.exec( /[@/](?<platform>github|gitlab)\.com[:/](?<account>[^/]+)\/(?<repo>[^/]+)/
git ).exec(git);
);
if (platformMatch) { if (platformMatch) {
const { account, repo, platform } = platformMatch?.groups || {}; const { account, repo, platform } = platformMatch?.groups || {};
@ -65,7 +65,7 @@ export function gitDep(parsedLine: ParsedLine): PackageDependency | null {
return { return {
datasource, datasource,
depName, depName,
lookupName: `${account}/${repo.replace(/\.git$/, '')}`, lookupName: `${account}/${repo.replace(regEx(/\.git$/), '')}`,
currentValue: tag, currentValue: tag,
}; };
} }
@ -103,7 +103,7 @@ export async function extractPackageFile(
}: ParsedLine = parsedLine; }: ParsedLine = parsedLine;
if (source) { if (source) {
registryUrls.push(source.replace(/\/*$/, '')); registryUrls.push(source.replace(regEx(/\/*$/), '')); // TODO #12071
} }
if (depName) { if (depName) {

View file

@ -19,6 +19,7 @@ import {
} from '../../util/fs'; } from '../../util/fs';
import { getRepoStatus } from '../../util/git'; import { getRepoStatus } from '../../util/git';
import * as hostRules from '../../util/host-rules'; import * as hostRules from '../../util/host-rules';
import { regEx } from '../../util/regex';
import type { UpdateArtifact, UpdateArtifactsResult } from '../types'; import type { UpdateArtifact, UpdateArtifactsResult } from '../types';
import type { AuthJson } from './types'; import type { AuthJson } from './types';
import { import {
@ -80,7 +81,7 @@ export async function updateArtifacts({
}: UpdateArtifact): Promise<UpdateArtifactsResult[] | null> { }: UpdateArtifact): Promise<UpdateArtifactsResult[] | null> {
logger.debug(`composer.updateArtifacts(${packageFileName})`); logger.debug(`composer.updateArtifacts(${packageFileName})`);
const lockFileName = packageFileName.replace(/\.json$/, '.lock'); const lockFileName = packageFileName.replace(regEx(/\.json$/), '.lock');
const existingLockFileContent = await readLocalFile(lockFileName, 'utf8'); const existingLockFileContent = await readLocalFile(lockFileName, 'utf8');
if (!existingLockFileContent) { if (!existingLockFileContent) {
logger.debug('No composer.lock found'); logger.debug('No composer.lock found');

View file

@ -4,6 +4,7 @@ import * as datasourcePackagist from '../../datasource/packagist';
import { logger } from '../../logger'; import { logger } from '../../logger';
import { SkipReason } from '../../types'; import { SkipReason } from '../../types';
import { readLocalFile } from '../../util/fs'; import { readLocalFile } from '../../util/fs';
import { regEx } from '../../util/regex';
import { api as semverComposer } from '../../versioning/composer'; import { api as semverComposer } from '../../versioning/composer';
import type { PackageDependency, PackageFile } from '../types'; import type { PackageDependency, PackageFile } from '../types';
import type { import type {
@ -21,7 +22,7 @@ import type {
* See https://github.com/composer/composer/blob/750a92b4b7aecda0e5b2f9b963f1cb1421900675/src/Composer/Repository/ComposerRepository.php#L815 * See https://github.com/composer/composer/blob/750a92b4b7aecda0e5b2f9b963f1cb1421900675/src/Composer/Repository/ComposerRepository.php#L815
*/ */
function transformRegUrl(url: string): string { function transformRegUrl(url: string): string {
return url.replace(/(\/packages\.json)$/, ''); return url.replace(regEx(/(\/packages\.json)$/), ''); // TODO #12071
} }
/** /**
@ -94,7 +95,7 @@ export async function extractPackageFile(
const res: PackageFile = { deps: [] }; const res: PackageFile = { deps: [] };
// handle lockfile // handle lockfile
const lockfilePath = fileName.replace(/\.json$/, '.lock'); const lockfilePath = fileName.replace(regEx(/\.json$/), '.lock');
const lockContents = await readLocalFile(lockfilePath, 'utf8'); const lockContents = await readLocalFile(lockfilePath, 'utf8');
let lockParsed: ComposerLock; let lockParsed: ComposerLock;
if (lockContents) { if (lockContents) {
@ -163,7 +164,7 @@ export async function extractPackageFile(
(item) => item.name === dep.depName (item) => item.name === dep.depName
); );
if (lockedDep && semverComposer.isVersion(lockedDep.version)) { if (lockedDep && semverComposer.isVersion(lockedDep.version)) {
dep.lockedVersion = lockedDep.version.replace(/^v/i, ''); dep.lockedVersion = lockedDep.version.replace(regEx(/^v/i), ''); // TODO #12071
} }
} }
deps.push(dep); deps.push(dep);

View file

@ -1,11 +1,14 @@
import { ClojureDatasource } from '../../datasource/clojure'; import { ClojureDatasource } from '../../datasource/clojure';
import { regEx } from '../../util/regex';
import { expandDepName } from '../leiningen/extract'; import { expandDepName } from '../leiningen/extract';
import type { PackageDependency, PackageFile } from '../types'; import type { PackageDependency, PackageFile } from '../types';
export function extractPackageFile(content: string): PackageFile { export function extractPackageFile(content: string): PackageFile {
const deps: PackageDependency[] = []; const deps: PackageDependency[] = [];
const regex = /([^{\s,]*)[\s,]*{[\s,]*:mvn\/version[\s,]+"([^"]+)"[\s,]*}/; const regex = regEx(
/([^{\s,]*)[\s,]*{[\s,]*:mvn\/version[\s,]+"([^"]+)"[\s,]*}/
);
let rest = content; let rest = content;
let match = regex.exec(rest); let match = regex.exec(rest);
let offset = 0; let offset = 0;

View file

@ -1,6 +1,7 @@
import is from '@sindresorhus/is'; import is from '@sindresorhus/is';
import { load } from 'js-yaml'; import { load } from 'js-yaml';
import { logger } from '../../logger'; import { logger } from '../../logger';
import { regEx } from '../../util/regex';
import { getDep } from '../dockerfile/extract'; import { getDep } from '../dockerfile/extract';
import type { PackageFile } from '../types'; import type { PackageFile } from '../types';
import type { DockerComposeConfig } from './types'; import type { DockerComposeConfig } from './types';
@ -56,7 +57,7 @@ export function extractPackageFile(
return null; return null;
} }
try { try {
const lineMapper = new LineMapper(content, /^\s*image:/); const lineMapper = new LineMapper(content, regEx(/^\s*image:/));
// docker-compose v1 places the services at the top level, // docker-compose v1 places the services at the top level,
// docker-compose v2+ places the services within a 'services' key // docker-compose v2+ places the services within a 'services' key

View file

@ -2,6 +2,7 @@ import is from '@sindresorhus/is';
import * as datasourceDocker from '../../datasource/docker'; import * as datasourceDocker from '../../datasource/docker';
import { logger } from '../../logger'; import { logger } from '../../logger';
import { SkipReason } from '../../types'; import { SkipReason } from '../../types';
import { regEx } from '../../util/regex';
import * as ubuntuVersioning from '../../versioning/ubuntu'; import * as ubuntuVersioning from '../../versioning/ubuntu';
import type { PackageDependency, PackageFile } from '../types'; import type { PackageDependency, PackageFile } from '../types';
@ -32,7 +33,7 @@ export function splitImageParts(currentFrom: string): PackageDependency {
return dep; return dep;
} }
const quayRegex = /^quay\.io(?::[1-9][0-9]{0,4})?/i; const quayRegex = regEx(/^quay\.io(?::[1-9][0-9]{0,4})?/i);
export function getDep( export function getDep(
currentFrom: string, currentFrom: string,
@ -89,7 +90,7 @@ export function extractPackageFile(content: string): PackageFile | null {
const stageNames: string[] = []; const stageNames: string[] = [];
const fromMatches = content.matchAll( const fromMatches = content.matchAll(
/^[ \t]*FROM(?:\\\r?\n| |\t|#.*?\r?\n|[ \t]--[a-z]+=\w+?)*[ \t](?<image>\S+)(?:(?:\\\r?\n| |\t|#.*\r?\n)+as[ \t]+(?<name>\S+))?/gim /^[ \t]*FROM(?:\\\r?\n| |\t|#.*?\r?\n|[ \t]--[a-z]+=\w+?)*[ \t](?<image>\S+)(?:(?:\\\r?\n| |\t|#.*\r?\n)+as[ \t]+(?<name>\S+))?/gim // TODO #12070
); );
for (const fromMatch of fromMatches) { for (const fromMatch of fromMatches) {
@ -116,7 +117,7 @@ export function extractPackageFile(content: string): PackageFile | null {
} }
const copyFromMatches = content.matchAll( const copyFromMatches = content.matchAll(
/^[ \t]*COPY(?:\\\r?\n| |\t|#.*\r?\n|[ \t]--[a-z]+=\w+?)*[ \t]--from=(?<image>\S+)/gim /^[ \t]*COPY(?:\\\r?\n| |\t|#.*\r?\n|[ \t]--[a-z]+=\w+?)*[ \t]--from=(?<image>\S+)/gim // TODO #12070
); );
for (const copyFromMatch of copyFromMatches) { for (const copyFromMatch of copyFromMatches) {

View file

@ -1,4 +1,5 @@
import { logger } from '../../logger'; import { logger } from '../../logger';
import { regEx } from '../../util/regex';
import { getDep } from '../dockerfile/extract'; import { getDep } from '../dockerfile/extract';
import type { PackageDependency, PackageFile } from '../types'; import type { PackageDependency, PackageFile } from '../types';
@ -8,7 +9,7 @@ export function extractPackageFile(content: string): PackageFile | null {
const lines = content.split('\n'); const lines = content.split('\n');
for (let lineNumber = 0; lineNumber < lines.length; lineNumber += 1) { for (let lineNumber = 0; lineNumber < lines.length; lineNumber += 1) {
const line = lines[lineNumber]; const line = lines[lineNumber];
const match = /^\s* image:\s*'?"?([^\s'"]+)'?"?\s*$/.exec(line); const match = regEx(/^\s* image:\s*'?"?([^\s'"]+)'?"?\s*$/).exec(line); // TODO #12071
if (match) { if (match) {
const currentFrom = match[1]; const currentFrom = match[1];
const dep = getDep(currentFrom); const dep = getDep(currentFrom);

View file

@ -6,6 +6,7 @@ import * as datasourceGitRefs from '../../datasource/git-refs';
import { logger } from '../../logger'; import { logger } from '../../logger';
import { simpleGitConfig } from '../../util/git/config'; import { simpleGitConfig } from '../../util/git/config';
import { getHttpUrl, getRemoteUrlWithToken } from '../../util/git/url'; import { getHttpUrl, getRemoteUrlWithToken } from '../../util/git/url';
import { regEx } from '../../util/regex';
import type { ExtractConfig, PackageFile } from '../types'; import type { ExtractConfig, PackageFile } from '../types';
import { GitModule } from './types'; import { GitModule } from './types';
@ -32,7 +33,7 @@ async function getUrl(
return URL.resolve(`${remoteUrl}/`, path); return URL.resolve(`${remoteUrl}/`, path);
} }
const headRefRe = /ref: refs\/heads\/(?<branch>\w+)\s/; const headRefRe = regEx(/ref: refs\/heads\/(?<branch>\w+)\s/);
async function getDefaultBranch(subModuleUrl: string): Promise<string> { async function getDefaultBranch(subModuleUrl: string): Promise<string> {
const val = await Git().listRemote(['--symref', subModuleUrl, 'HEAD']); const val = await Git().listRemote(['--symref', subModuleUrl, 'HEAD']);
@ -71,11 +72,11 @@ async function getModules(
])) ?? /* istanbul ignore next: should never happen */ '' ])) ?? /* istanbul ignore next: should never happen */ ''
) )
.trim() .trim()
.split(/\n/) .split(regEx(/\n/))
.filter((s) => !!s); .filter((s) => !!s);
for (const line of modules) { for (const line of modules) {
const [, name, path] = line.split(/submodule\.(.+?)\.path\s(.+)/); const [, name, path] = line.split(regEx(/submodule\.(.+?)\.path\s(.+)/)); // TODO #12071
res.push({ name, path }); res.push({ name, path });
} }
} catch (err) /* istanbul ignore next */ { } catch (err) /* istanbul ignore next */ {
@ -104,8 +105,8 @@ export default async function extractPackageFile(
try { try {
const [currentDigest] = (await git.subModule(['status', path])) const [currentDigest] = (await git.subModule(['status', path]))
.trim() .trim()
.replace(/^[-+]/, '') .replace(regEx(/^[-+]/), '') // TODO #12071
.split(/\s/); .split(regEx(/\s/)); // TODO #12071
const subModuleUrl = await getUrl(git, gitModulesPath, name); const subModuleUrl = await getUrl(git, gitModulesPath, name);
// hostRules only understands HTTP URLs // hostRules only understands HTTP URLs
// Find HTTP URL, then apply token // Find HTTP URL, then apply token

View file

@ -1,16 +1,18 @@
import * as githubTagsDatasource from '../../datasource/github-tags'; import * as githubTagsDatasource from '../../datasource/github-tags';
import { logger } from '../../logger'; import { logger } from '../../logger';
import { SkipReason } from '../../types'; import { SkipReason } from '../../types';
import { regEx } from '../../util/regex';
import * as dockerVersioning from '../../versioning/docker'; import * as dockerVersioning from '../../versioning/docker';
import { getDep } from '../dockerfile/extract'; import { getDep } from '../dockerfile/extract';
import type { PackageDependency, PackageFile } from '../types'; import type { PackageDependency, PackageFile } from '../types';
const dockerRe = /^\s+uses: docker:\/\/([^"]+)\s*$/; const dockerRe = regEx(/^\s+uses: docker:\/\/([^"]+)\s*$/);
const actionRe = const actionRe = regEx(
/^\s+-?\s+?uses: (?<replaceString>(?<depName>[\w-]+\/[\w-]+)(?<path>\/.*)?@(?<currentValue>.+?)(?: # renovate: tag=(?<tag>.+?))?)\s*?$/; /^\s+-?\s+?uses: (?<replaceString>(?<depName>[\w-]+\/[\w-]+)(?<path>\/.*)?@(?<currentValue>.+?)(?: # renovate: tag=(?<tag>.+?))?)\s*?$/
);
// SHA1 or SHA256, see https://github.blog/2020-10-19-git-2-29-released/ // SHA1 or SHA256, see https://github.blog/2020-10-19-git-2-29-released/
const shaRe = /^[a-z0-9]{40}|[a-z0-9]{64}$/; const shaRe = regEx(/^[a-z0-9]{40}|[a-z0-9]{64}$/);
export function extractPackageFile(content: string): PackageFile | null { export function extractPackageFile(content: string): PackageFile | null {
logger.trace('github-actions.extractPackageFile()'); logger.trace('github-actions.extractPackageFile()');

View file

@ -3,6 +3,7 @@ import { load } from 'js-yaml';
import * as datasourceGitlabTags from '../../datasource/gitlab-tags'; import * as datasourceGitlabTags from '../../datasource/gitlab-tags';
import { logger } from '../../logger'; import { logger } from '../../logger';
import { SkipReason } from '../../types'; import { SkipReason } from '../../types';
import { regEx } from '../../util/regex';
import { replaceReferenceTags } from '../gitlabci/utils'; import { replaceReferenceTags } from '../gitlabci/utils';
import type { ExtractConfig, PackageDependency, PackageFile } from '../types'; import type { ExtractConfig, PackageDependency, PackageFile } from '../types';
@ -45,7 +46,9 @@ export function extractPackageFile(
if (includeObj?.file && includeObj.project) { if (includeObj?.file && includeObj.project) {
const dep = extractDepFromIncludeFile(includeObj); const dep = extractDepFromIncludeFile(includeObj);
if (config.endpoint) { if (config.endpoint) {
dep.registryUrls = [config.endpoint.replace(/\/api\/v4\/?/, '')]; dep.registryUrls = [
config.endpoint.replace(regEx(/\/api\/v4\/?/), ''),
]; // TODO #12071
} }
deps.push(dep); deps.push(dep);
} }

View file

@ -7,13 +7,12 @@ import type { ExtractConfig, PackageDependency, PackageFile } from '../types';
import type { GitlabPipeline } from './types'; import type { GitlabPipeline } from './types';
import { replaceReferenceTags } from './utils'; import { replaceReferenceTags } from './utils';
const commentsRe = /^\s*#/; const commentsRe = /^\s*#/; // TODO #12070
const whitespaceRe = /^(?<whitespace>\s*)/; const whitespaceRe = /^(?<whitespace>\s*)/; // TODO #12070
const imageRe = const imageRe =
/^(?<whitespace>\s*)image:(?:\s+['"]?(?<image>[^\s'"]+)['"]?)?\s*$/; /^(?<whitespace>\s*)image:(?:\s+['"]?(?<image>[^\s'"]+)['"]?)?\s*$/; // TODO #12070
const nameRe = /^\s*name:\s+['"]?(?<depName>[^\s'"]+)['"]?\s*$/; const nameRe = /^\s*name:\s+['"]?(?<depName>[^\s'"]+)['"]?\s*$/; // TODO #12070
const serviceRe = /^\s*-\s*(?:name:\s+)?['"]?(?<depName>[^\s'"]+)['"]?\s*$/; const serviceRe = /^\s*-\s*(?:name:\s+)?['"]?(?<depName>[^\s'"]+)['"]?\s*$/; // TODO #12070
function skipCommentLines( function skipCommentLines(
lines: string[], lines: string[],
lineNumber: number lineNumber: number
@ -62,7 +61,7 @@ export function extractPackageFile(content: string): PackageFile | null {
} }
} }
} }
const services = /^\s*services:\s*$/.test(line); const services = /^\s*services:\s*$/.test(line); // TODO #12071 #12070
if (services) { if (services) {
logger.trace(`Matched services on line ${lineNumber}`); logger.trace(`Matched services on line ${lineNumber}`);
let foundImage: boolean; let foundImage: boolean;
@ -121,7 +120,7 @@ export async function extractAllPackageFiles(
if (is.array(doc?.include)) { if (is.array(doc?.include)) {
for (const includeObj of doc.include) { for (const includeObj of doc.include) {
if (is.string(includeObj.local)) { if (is.string(includeObj.local)) {
const fileObj = includeObj.local.replace(/^\//, ''); const fileObj = includeObj.local.replace(/^\//, ''); // TODO #12071 #12070
if (!seen.has(fileObj)) { if (!seen.has(fileObj)) {
seen.add(fileObj); seen.add(fileObj);
filesToExamine.push(fileObj); filesToExamine.push(fileObj);
@ -129,7 +128,7 @@ export async function extractAllPackageFiles(
} }
} }
} else if (is.string(doc?.include)) { } else if (is.string(doc?.include)) {
const fileObj = doc.include.replace(/^\//, ''); const fileObj = doc.include.replace(/^\//, ''); // TODO #12071 #12070
if (!seen.has(fileObj)) { if (!seen.has(fileObj)) {
seen.add(fileObj); seen.add(fileObj);
filesToExamine.push(fileObj); filesToExamine.push(fileObj);

View file

@ -9,6 +9,7 @@ import { ExecOptions, exec } from '../../util/exec';
import { ensureCacheDir, readLocalFile, writeLocalFile } from '../../util/fs'; import { ensureCacheDir, readLocalFile, writeLocalFile } from '../../util/fs';
import { getRepoStatus } from '../../util/git'; import { getRepoStatus } from '../../util/git';
import { find } from '../../util/host-rules'; import { find } from '../../util/host-rules';
import { regEx } from '../../util/regex';
import { isValid } from '../../versioning/semver'; import { isValid } from '../../versioning/semver';
import type { import type {
PackageDependency, PackageDependency,
@ -48,10 +49,10 @@ function getUpdateImportPathCmds(
if (gomodModCompatibility) { if (gomodModCompatibility) {
if ( if (
gomodModCompatibility.startsWith('v') && gomodModCompatibility.startsWith('v') &&
isValid(gomodModCompatibility.replace(/^v/, '')) isValid(gomodModCompatibility.replace(regEx(/^v/), ''))
) { ) {
installMarwanModArgs = installMarwanModArgs.replace( installMarwanModArgs = installMarwanModArgs.replace(
/@latest$/, regEx(/@latest$/),
`@${gomodModCompatibility}` `@${gomodModCompatibility}`
); );
} else { } else {
@ -76,7 +77,7 @@ function useModcacherw(goVersion: string): boolean {
return true; return true;
} }
const [, majorPart, minorPart] = /(\d+)\.(\d+)/.exec(goVersion) ?? []; const [, majorPart, minorPart] = regEx(/(\d+)\.(\d+)/).exec(goVersion) ?? [];
const [major, minor] = [majorPart, minorPart].map((x) => parseInt(x, 10)); const [major, minor] = [majorPart, minorPart].map((x) => parseInt(x, 10));
return ( return (
@ -94,7 +95,7 @@ export async function updateArtifacts({
}: UpdateArtifact): Promise<UpdateArtifactsResult[] | null> { }: UpdateArtifact): Promise<UpdateArtifactsResult[] | null> {
logger.debug(`gomod.updateArtifacts(${goModFileName})`); logger.debug(`gomod.updateArtifacts(${goModFileName})`);
const sumFileName = goModFileName.replace(/\.mod$/, '.sum'); const sumFileName = goModFileName.replace(regEx(/\.mod$/), '.sum');
const existingGoSumContent = await readLocalFile(sumFileName); const existingGoSumContent = await readLocalFile(sumFileName);
if (!existingGoSumContent) { if (!existingGoSumContent) {
logger.debug('No go.sum found'); logger.debug('No go.sum found');
@ -107,7 +108,7 @@ export async function updateArtifacts({
try { try {
const massagedGoMod = newGoModContent.replace( const massagedGoMod = newGoModContent.replace(
/\n(replace\s+[^\s]+\s+=>\s+\.\.\/.*)/g, regEx(/\n(replace\s+[^\s]+\s+=>\s+\.\.\/.*)/g),
'\n// renovate-replace $1' '\n// renovate-replace $1'
); );
if (massagedGoMod !== newGoModContent) { if (massagedGoMod !== newGoModContent) {
@ -237,7 +238,7 @@ export async function updateArtifacts({
const finalGoModContent = ( const finalGoModContent = (
await readLocalFile(goModFileName, 'utf8') await readLocalFile(goModFileName, 'utf8')
).replace(/\/\/ renovate-replace /g, ''); ).replace(regEx(/\/\/ renovate-replace /g), '');
if (finalGoModContent !== newGoModContent) { if (finalGoModContent !== newGoModContent) {
logger.debug('Found updated go.mod after go.sum update'); logger.debug('Found updated go.mod after go.sum update');
res.push({ res.push({

View file

@ -2,6 +2,7 @@ import { validRange } from 'semver';
import * as datasourceGo from '../../datasource/go'; import * as datasourceGo from '../../datasource/go';
import { logger } from '../../logger'; import { logger } from '../../logger';
import { SkipReason } from '../../types'; import { SkipReason } from '../../types';
import { regEx } from '../../util/regex';
import { isVersion } from '../../versioning/semver'; import { isVersion } from '../../versioning/semver';
import type { PackageDependency, PackageFile } from '../types'; import type { PackageDependency, PackageFile } from '../types';
@ -12,7 +13,7 @@ function getDep(
): PackageDependency { ): PackageDependency {
const [, , currentValue] = match; const [, , currentValue] = match;
let [, depName] = match; let [, depName] = match;
depName = depName.replace(/"/g, ''); depName = depName.replace(regEx(/"/g), '');
const dep: PackageDependency = { const dep: PackageDependency = {
managerData: { managerData: {
lineNumber, lineNumber,
@ -26,7 +27,7 @@ function getDep(
} else { } else {
dep.skipReason = SkipReason.UnsupportedVersion; dep.skipReason = SkipReason.UnsupportedVersion;
} }
const digestMatch = /v0\.0.0-\d{14}-([a-f0-9]{12})/.exec(currentValue); const digestMatch = regEx(/v0\.0.0-\d{14}-([a-f0-9]{12})/).exec(currentValue);
if (digestMatch) { if (digestMatch) {
[, dep.currentDigest] = digestMatch; [, dep.currentDigest] = digestMatch;
dep.digestOneAndOnly = true; dep.digestOneAndOnly = true;
@ -45,13 +46,14 @@ export function extractPackageFile(content: string): PackageFile | null {
if (line.startsWith('go ') && validRange(line.replace('go ', ''))) { if (line.startsWith('go ') && validRange(line.replace('go ', ''))) {
constraints.go = line.replace('go ', '^'); constraints.go = line.replace('go ', '^');
} }
const replaceMatch = const replaceMatch = regEx(
/^replace\s+[^\s]+[\s]+[=][>]\s+([^\s]+)\s+([^\s]+)/.exec(line); /^replace\s+[^\s]+[\s]+[=][>]\s+([^\s]+)\s+([^\s]+)/
).exec(line); // TODO #12071
if (replaceMatch) { if (replaceMatch) {
const dep = getDep(lineNumber, replaceMatch, 'replace'); const dep = getDep(lineNumber, replaceMatch, 'replace');
deps.push(dep); deps.push(dep);
} }
const requireMatch = /^require\s+([^\s]+)\s+([^\s]+)/.exec(line); const requireMatch = regEx(/^require\s+([^\s]+)\s+([^\s]+)/).exec(line); // TODO #12071
if (requireMatch && !line.endsWith('// indirect')) { if (requireMatch && !line.endsWith('// indirect')) {
logger.trace({ lineNumber }, `require line: "${line}"`); logger.trace({ lineNumber }, `require line: "${line}"`);
const dep = getDep(lineNumber, requireMatch, 'require'); const dep = getDep(lineNumber, requireMatch, 'require');
@ -62,7 +64,7 @@ export function extractPackageFile(content: string): PackageFile | null {
do { do {
lineNumber += 1; lineNumber += 1;
line = lines[lineNumber]; line = lines[lineNumber];
const multiMatch = /^\s+([^\s]+)\s+([^\s]+)/.exec(line); const multiMatch = regEx(/^\s+([^\s]+)\s+([^\s]+)/).exec(line); // TODO #12071
logger.trace(`reqLine: "${line}"`); logger.trace(`reqLine: "${line}"`);
if (multiMatch && !line.endsWith('// indirect')) { if (multiMatch && !line.endsWith('// indirect')) {
logger.trace({ lineNumber }, `require line: "${line}"`); logger.trace({ lineNumber }, `require line: "${line}"`);

View file

@ -1,10 +1,11 @@
import { logger } from '../../logger'; import { logger } from '../../logger';
import { regEx } from '../../util/regex';
import type { UpdateDependencyConfig } from '../types'; import type { UpdateDependencyConfig } from '../types';
function getDepNameWithNoVersion(depName: string): string { function getDepNameWithNoVersion(depName: string): string {
let depNameNoVersion = depName.split('/').slice(0, 3).join('/'); let depNameNoVersion = depName.split('/').slice(0, 3).join('/');
if (depNameNoVersion.startsWith('gopkg.in')) { if (depNameNoVersion.startsWith('gopkg.in')) {
depNameNoVersion = depNameNoVersion.replace(/\.v\d+$/, ''); depNameNoVersion = depNameNoVersion.replace(regEx(/\.v\d+$/), '');
} }
return depNameNoVersion; return depNameNoVersion;
} }
@ -31,14 +32,14 @@ export function updateDependency({
} }
let updateLineExp: RegExp; let updateLineExp: RegExp;
if (depType === 'replace') { if (depType === 'replace') {
updateLineExp = new RegExp( updateLineExp = regEx(
/^(replace\s+[^\s]+[\s]+[=][>]+\s+)([^\s]+\s+)([^\s]+)/ /^(replace\s+[^\s]+[\s]+[=][>]+\s+)([^\s]+\s+)([^\s]+)/
); );
} else if (depType === 'require') { } else if (depType === 'require') {
if (upgrade.managerData.multiLine) { if (upgrade.managerData.multiLine) {
updateLineExp = new RegExp(/^(\s+[^\s]+)(\s+)([^\s]+)/); updateLineExp = regEx(/^(\s+[^\s]+)(\s+)([^\s]+)/);
} else { } else {
updateLineExp = new RegExp(/^(require\s+[^\s]+)(\s+)([^\s]+)/); updateLineExp = regEx(/^(require\s+[^\s]+)(\s+)([^\s]+)/);
} }
} }
if (updateLineExp && !updateLineExp.test(lineToChange)) { if (updateLineExp && !updateLineExp.test(lineToChange)) {
@ -86,7 +87,7 @@ export function updateDependency({
// Replace version // Replace version
const [oldV] = upgrade.currentValue.split('.'); const [oldV] = upgrade.currentValue.split('.');
newLine = newLine.replace( newLine = newLine.replace(
new RegExp(`/${oldV}(\\s+)`), regEx(`/${oldV}(\\s+)`),
`/v${upgrade.newMajor}$1` `/v${upgrade.newMajor}$1`
); );
} }

View file

@ -6,6 +6,7 @@ import {
readLocalFile, readLocalFile,
writeLocalFile, writeLocalFile,
} from '../../../util/fs'; } from '../../../util/fs';
import { regEx } from '../../../util/regex';
import type { import type {
BuildDependency, BuildDependency,
GradleDependencyWithRepos, GradleDependencyWithRepos,
@ -144,11 +145,12 @@ export async function extractDependenciesFromUpdatesReport(
if (depName.endsWith('_%%')) { if (depName.endsWith('_%%')) {
return { return {
...dep, ...dep,
depName: depName.replace(/_%%/, ''), depName: depName.replace(regEx(/_%%/), ''), // TODO #12071
datasource: datasourceSbtPackage.id, datasource: datasourceSbtPackage.id,
}; };
} }
if (/^%.*%$/.test(currentValue)) { if (regEx(/^%.*%$/).test(currentValue)) {
// TODO #12071
return { ...dep, skipReason: 'version-placeholder' }; return { ...dep, skipReason: 'version-placeholder' };
} }
return dep; return dep;

View file

@ -1,8 +1,9 @@
import moo from 'moo'; import moo from 'moo';
import { regEx } from '../../../util/regex';
import { TokenType } from './common'; import { TokenType } from './common';
import type { StringInterpolation, Token } from './types'; import type { StringInterpolation, Token } from './types';
const escapedCharRegex = /\\['"bfnrt\\]/; const escapedCharRegex = /\\['"bfnrt\\]/; // TODO #12070
const escapedChars = { const escapedChars = {
[TokenType.EscapedChar]: { [TokenType.EscapedChar]: {
match: escapedCharRegex, match: escapedCharRegex,
@ -23,17 +24,17 @@ const escapedChars = {
const lexer = moo.states({ const lexer = moo.states({
// Top-level Groovy lexemes // Top-level Groovy lexemes
main: { main: {
[TokenType.LineComment]: { match: /\/\/.*?$/ }, [TokenType.LineComment]: { match: /\/\/.*?$/ }, // TODO #12070
[TokenType.MultiComment]: { match: /\/\*[^]*?\*\//, lineBreaks: true }, [TokenType.MultiComment]: { match: /\/\*[^]*?\*\//, lineBreaks: true }, // TODO #12070
[TokenType.Newline]: { match: /\r?\n/, lineBreaks: true }, [TokenType.Newline]: { match: /\r?\n/, lineBreaks: true }, // TODO #12070
[TokenType.Space]: { match: /[ \t\r]+/ }, [TokenType.Space]: { match: /[ \t\r]+/ }, // TODO #12070
[TokenType.Semicolon]: ';', [TokenType.Semicolon]: ';',
[TokenType.Colon]: ':', [TokenType.Colon]: ':',
[TokenType.Dot]: '.', [TokenType.Dot]: '.',
[TokenType.Comma]: ',', [TokenType.Comma]: ',',
[TokenType.Operator]: /(?:==|\+=?|-=?|\/=?|\*\*?|\.+|:)/, [TokenType.Operator]: /(?:==|\+=?|-=?|\/=?|\*\*?|\.+|:)/, // TODO #12070
[TokenType.Assignment]: '=', [TokenType.Assignment]: '=',
[TokenType.Word]: { match: /[a-zA-Z$_][a-zA-Z0-9$_]+/ }, [TokenType.Word]: { match: /[a-zA-Z$_][a-zA-Z0-9$_]+/ }, // TODO #12070
[TokenType.LeftParen]: { match: '(' }, [TokenType.LeftParen]: { match: '(' },
[TokenType.RightParen]: { match: ')' }, [TokenType.RightParen]: { match: ')' },
[TokenType.LeftBracket]: { match: '[' }, [TokenType.LeftBracket]: { match: '[' },
@ -85,12 +86,12 @@ const lexer = moo.states({
variable: { variable: {
// Supported: ${foo}, $foo, ${ foo.bar.baz }, $foo.bar.baz // Supported: ${foo}, $foo, ${ foo.bar.baz }, $foo.bar.baz
match: match:
/\${\s*[a-zA-Z_][a-zA-Z0-9_]*(?:\s*\.\s*[a-zA-Z_][a-zA-Z0-9_]*)*\s*}|\$[a-zA-Z_][a-zA-Z0-9_]*(?:\.[a-zA-Z_][a-zA-Z0-9_]*)*/, /\${\s*[a-zA-Z_][a-zA-Z0-9_]*(?:\s*\.\s*[a-zA-Z_][a-zA-Z0-9_]*)*\s*}|\$[a-zA-Z_][a-zA-Z0-9_]*(?:\.[a-zA-Z_][a-zA-Z0-9_]*)*/, // TODO #12070
value: (x: string): string => value: (x: string): string =>
x.replace(/^\${?\s*/, '').replace(/\s*}$/, ''), x.replace(regEx(/^\${?\s*/), '').replace(regEx(/\s*}$/), ''),
}, },
[TokenType.IgnoredInterpolationStart]: { [TokenType.IgnoredInterpolationStart]: {
match: /\${/, match: /\${/, // TODO #12070
push: TokenType.IgnoredInterpolationStart, push: TokenType.IgnoredInterpolationStart,
}, },
[TokenType.Chars]: moo.fallback, [TokenType.Chars]: moo.fallback,

View file

@ -111,7 +111,7 @@ export function isTOMLFile(path: string): boolean {
} }
export function toAbsolutePath(packageFile: string): string { export function toAbsolutePath(packageFile: string): string {
return upath.join(packageFile.replace(/^[/\\]*/, '/')); return upath.join(packageFile.replace(regEx(/^[/\\]*/), '/'));
} }
export function reorderFiles(packageFiles: string[]): string[] { export function reorderFiles(packageFiles: string[]): string[] {

View file

@ -1,7 +1,8 @@
import { hasKey } from '../../util/object'; import { hasKey } from '../../util/object';
import { regEx } from '../../util/regex';
import { HelmDockerImageDependency } from './types'; import { HelmDockerImageDependency } from './types';
const parentKeyRe = /image$/i; const parentKeyRe = regEx(/image$/i);
/** /**
* Type guard to determine whether a given partial Helm values.yaml object potentially * Type guard to determine whether a given partial Helm values.yaml object potentially

View file

@ -3,11 +3,12 @@ import { loadAll } from 'js-yaml';
import { HelmDatasource } from '../../datasource/helm'; import { HelmDatasource } from '../../datasource/helm';
import { logger } from '../../logger'; import { logger } from '../../logger';
import { SkipReason } from '../../types'; import { SkipReason } from '../../types';
import { regEx } from '../../util/regex';
import type { ExtractConfig, PackageDependency, PackageFile } from '../types'; import type { ExtractConfig, PackageDependency, PackageFile } from '../types';
import type { Doc } from './types'; import type { Doc } from './types';
const isValidChartName = (name: string): boolean => const isValidChartName = (name: string): boolean =>
!/[!@#$%^&*(),.?":{}/|<>A-Z]/.test(name); !regEx(/[!@#$%^&*(),.?":{}/|<>A-Z]/).test(name);
export function extractPackageFile( export function extractPackageFile(
content: string, content: string,

View file

@ -20,7 +20,7 @@ export function bumpPackageVersion(
} }
logger.debug({ newChartVersion }); logger.debug({ newChartVersion });
bumpedContent = content.replace( bumpedContent = content.replace(
/^(version:\s*).*$/m, /^(version:\s*).*$/m, // TODO #12070
`$1${newChartVersion}` `$1${newChartVersion}`
); );
if (bumpedContent === content) { if (bumpedContent === content) {

View file

@ -1,6 +1,7 @@
import * as datasourceGithubTags from '../../datasource/github-tags'; import * as datasourceGithubTags from '../../datasource/github-tags';
import { logger } from '../../logger'; import { logger } from '../../logger';
import { SkipReason } from '../../types'; import { SkipReason } from '../../types';
import { regEx } from '../../util/regex';
import type { PackageDependency, PackageFile } from '../types'; import type { PackageDependency, PackageFile } from '../types';
import type { UrlPathParsedResult } from './types'; import type { UrlPathParsedResult } from './types';
import { isSpace, removeComments, skip } from './util'; import { isSpace, removeComments, skip } from './util';
@ -19,7 +20,7 @@ function parseSha256(idx: number, content: string): string | null {
} }
function extractSha256(content: string): string | null { function extractSha256(content: string): string | null {
const sha256RegExp = /(^|\s)sha256(\s)/; const sha256RegExp = regEx(/(^|\s)sha256(\s)/);
let i = content.search(sha256RegExp); let i = content.search(sha256RegExp);
if (isSpace(content[i])) { if (isSpace(content[i])) {
i += 1; i += 1;
@ -42,7 +43,7 @@ function parseUrl(idx: number, content: string): string | null {
} }
function extractUrl(content: string): string | null { function extractUrl(content: string): string | null {
const urlRegExp = /(^|\s)url(\s)/; const urlRegExp = regEx(/(^|\s)url(\s)/);
let i = content.search(urlRegExp); let i = content.search(urlRegExp);
// content.search() returns -1 if not found // content.search() returns -1 if not found
if (i === -1) { if (i === -1) {
@ -117,7 +118,7 @@ function parseClassHeader(idx: number, content: string): string | null {
} }
function extractClassName(content: string): string | null { function extractClassName(content: string): string | null {
const classRegExp = /(^|\s)class\s/; const classRegExp = regEx(/(^|\s)class\s/);
let i = content.search(classRegExp); let i = content.search(classRegExp);
if (isSpace(content[i])) { if (isSpace(content[i])) {
i += 1; i += 1;

View file

@ -1,10 +1,13 @@
import { CdnJsDatasource } from '../../datasource/cdnjs'; import { CdnJsDatasource } from '../../datasource/cdnjs';
import { regEx } from '../../util/regex';
import { cloudflareUrlRegex } from '../cdnurl/extract'; import { cloudflareUrlRegex } from '../cdnurl/extract';
import type { PackageDependency, PackageFile } from '../types'; import type { PackageDependency, PackageFile } from '../types';
const regex = /<\s*(script|link)\s+[^>]*?\/?>/i; const regex = regEx(/<\s*(script|link)\s+[^>]*?\/?>/i);
const integrityRegex = /\s+integrity\s*=\s*("|')(?<currentDigest>[^"']+)/; const integrityRegex = regEx(
/\s+integrity\s*=\s*("|')(?<currentDigest>[^"']+)/
);
export function extractDep(tag: string): PackageDependency | null { export function extractDep(tag: string): PackageDependency | null {
const match = cloudflareUrlRegex.exec(tag); const match = cloudflareUrlRegex.exec(tag);

View file

@ -3,11 +3,12 @@ import * as datasourceJenkins from '../../datasource/jenkins-plugins';
import { logger } from '../../logger'; import { logger } from '../../logger';
import { SkipReason } from '../../types'; import { SkipReason } from '../../types';
import { isSkipComment } from '../../util/ignore'; import { isSkipComment } from '../../util/ignore';
import { regEx } from '../../util/regex';
import * as dockerVersioning from '../../versioning/docker'; import * as dockerVersioning from '../../versioning/docker';
import type { PackageDependency, PackageFile } from '../types'; import type { PackageDependency, PackageFile } from '../types';
import type { JenkinsPlugin, JenkinsPlugins } from './types'; import type { JenkinsPlugin, JenkinsPlugins } from './types';
const YamlExtension = /\.ya?ml$/; const YamlExtension = regEx(/\.ya?ml$/);
function getDependency(plugin: JenkinsPlugin): PackageDependency { function getDependency(plugin: JenkinsPlugin): PackageDependency {
const dep: PackageDependency = { const dep: PackageDependency = {
@ -70,8 +71,9 @@ function extractYaml(content: string): PackageDependency[] {
function extractText(content: string): PackageDependency[] { function extractText(content: string): PackageDependency[] {
const deps: PackageDependency[] = []; const deps: PackageDependency[] = [];
const regex = const regex = regEx(
/^\s*(?<depName>[\d\w-]+):(?<currentValue>[^#\s]+)[#\s]*(?<comment>.*)$/; /^\s*(?<depName>[\d\w-]+):(?<currentValue>[^#\s]+)[#\s]*(?<comment>.*)$/
);
for (const line of content.split('\n')) { for (const line of content.split('\n')) {
const match = regex.exec(line); const match = regex.exec(line);

View file

@ -1,4 +1,5 @@
import { logger } from '../../logger'; import { logger } from '../../logger';
import { regEx } from '../../util/regex';
import { getDep } from '../dockerfile/extract'; import { getDep } from '../dockerfile/extract';
import type { PackageDependency, PackageFile } from '../types'; import type { PackageDependency, PackageFile } from '../types';
@ -7,13 +8,14 @@ export function extractPackageFile(content: string): PackageFile | null {
let deps: PackageDependency[] = []; let deps: PackageDependency[] = [];
const isKubernetesManifest = const isKubernetesManifest =
/\s*apiVersion\s*:/.test(content) && /\s*kind\s*:/.test(content); regEx(/\s*apiVersion\s*:/).test(content) &&
regEx(/\s*kind\s*:/).test(content);
if (!isKubernetesManifest) { if (!isKubernetesManifest) {
return null; return null;
} }
for (const line of content.split('\n')) { for (const line of content.split('\n')) {
const match = /^\s*-?\s*image:\s*'?"?([^\s'"]+)'?"?\s*$/.exec(line); const match = regEx(/^\s*-?\s*image:\s*'?"?([^\s'"]+)'?"?\s*$/).exec(line); // TODO #12071
if (match) { if (match) {
const currentFrom = match[1]; const currentFrom = match[1];
const dep = getDep(currentFrom); const dep = getDep(currentFrom);

View file

@ -5,14 +5,16 @@ import * as datasourceGitTags from '../../datasource/git-tags';
import * as datasourceGitHubTags from '../../datasource/github-tags'; import * as datasourceGitHubTags from '../../datasource/github-tags';
import { logger } from '../../logger'; import { logger } from '../../logger';
import { SkipReason } from '../../types'; import { SkipReason } from '../../types';
import { regEx } from '../../util/regex';
import { splitImageParts } from '../dockerfile/extract'; import { splitImageParts } from '../dockerfile/extract';
import type { PackageDependency, PackageFile } from '../types'; import type { PackageDependency, PackageFile } from '../types';
import type { Image, Kustomize } from './types'; import type { Image, Kustomize } from './types';
// URL specifications should follow the hashicorp URL format // URL specifications should follow the hashicorp URL format
// https://github.com/hashicorp/go-getter#url-format // https://github.com/hashicorp/go-getter#url-format
const gitUrl = const gitUrl = regEx(
/^(?:git::)?(?<url>(?:(?:(?:http|https|ssh):\/\/)?(?:.*@)?)?(?<path>(?:[^:/\s]+(?::[0-9]+)?[:/])?(?<project>[^/\s]+\/[^/\s]+)))(?<subdir>[^?\s]*)\?ref=(?<currentValue>.+)$/; /^(?:git::)?(?<url>(?:(?:(?:http|https|ssh):\/\/)?(?:.*@)?)?(?<path>(?:[^:/\s]+(?::[0-9]+)?[:/])?(?<project>[^/\s]+\/[^/\s]+)))(?<subdir>[^?\s]*)\?ref=(?<currentValue>.+)$/
);
export function extractBase(base: string): PackageDependency | null { export function extractBase(base: string): PackageDependency | null {
const match = gitUrl.exec(base); const match = gitUrl.exec(base);

View file

@ -1,15 +1,16 @@
import { ClojureDatasource } from '../../datasource/clojure'; import { ClojureDatasource } from '../../datasource/clojure';
import { regEx } from '../../util/regex';
import type { PackageDependency, PackageFile } from '../types'; import type { PackageDependency, PackageFile } from '../types';
import type { ExtractContext, ExtractedVariables } from './types'; import type { ExtractContext, ExtractedVariables } from './types';
export function trimAtKey(str: string, kwName: string): string | null { export function trimAtKey(str: string, kwName: string): string | null {
const regex = new RegExp(`:${kwName}(?=\\s)`); const regex = new RegExp(`:${kwName}(?=\\s)`); // TODO #12070
const keyOffset = str.search(regex); const keyOffset = str.search(regex);
if (keyOffset < 0) { if (keyOffset < 0) {
return null; return null;
} }
const withSpaces = str.slice(keyOffset + kwName.length + 1); const withSpaces = str.slice(keyOffset + kwName.length + 1);
const valueOffset = withSpaces.search(/[^\s]/); const valueOffset = withSpaces.search(regEx(/[^\s]/));
if (valueOffset < 0) { if (valueOffset < 0) {
return null; return null;
} }
@ -35,16 +36,16 @@ export function extractFromVectors(
let artifactId = ''; let artifactId = '';
let version = ''; let version = '';
const isSpace = (ch: string): boolean => ch && /[\s,]/.test(ch); const isSpace = (ch: string): boolean => ch && regEx(/[\s,]/).test(ch);
const cleanStrLiteral = (s: string): string => const cleanStrLiteral = (s: string): string =>
s.replace(/^"/, '').replace(/"$/, ''); s.replace(regEx(/^"/), '').replace(regEx(/"$/), '');
const yieldDep = (): void => { const yieldDep = (): void => {
if (artifactId && version) { if (artifactId && version) {
const depName = expandDepName(cleanStrLiteral(artifactId)); const depName = expandDepName(cleanStrLiteral(artifactId));
if (version.startsWith('~')) { if (version.startsWith('~')) {
const currentValue = vars[version.replace(/^~\s*/, '')]; const currentValue = vars[version.replace(regEx(/^~\s*/), '')];
if (currentValue) { if (currentValue) {
result.push({ result.push({
...ctx, ...ctx,
@ -102,7 +103,7 @@ function extractLeinRepos(content: string): string[] {
const result = []; const result = [];
const repoContent = trimAtKey( const repoContent = trimAtKey(
content.replace(/;;.*(?=[\r\n])/g, ''), // get rid of comments content.replace(/;;.*(?=[\r\n])/g, ''), // get rid of comments // TODO #12070
'repositories' 'repositories'
); );
@ -122,16 +123,19 @@ function extractLeinRepos(content: string): string[] {
} }
} }
const repoSectionContent = repoContent.slice(0, endIdx); const repoSectionContent = repoContent.slice(0, endIdx);
const matches = repoSectionContent.match(/"https?:\/\/[^"]*"/g) || []; const matches = repoSectionContent.match(/"https?:\/\/[^"]*"/g) || []; // TODO #12070
const urls = matches.map((x) => x.replace(/^"/, '').replace(/"$/, '')); const urls = matches.map((x) =>
x.replace(regEx(/^"/), '').replace(regEx(/"$/), '')
); // TODO #12071
urls.forEach((url) => result.push(url)); urls.forEach((url) => result.push(url));
} }
return result; return result;
} }
const defRegex = const defRegex = regEx(
/^[\s,]*\([\s,]*def[\s,]+(?<varName>[-+*=<>.!?#$%&_|a-zA-Z][-+*=<>.!?#$%&_|a-zA-Z0-9']+)[\s,]*"(?<stringValue>[^"]*)"[\s,]*\)[\s,]*$/; /^[\s,]*\([\s,]*def[\s,]+(?<varName>[-+*=<>.!?#$%&_|a-zA-Z][-+*=<>.!?#$%&_|a-zA-Z0-9']+)[\s,]*"(?<stringValue>[^"]*)"[\s,]*\)[\s,]*$/
);
export function extractVariables(content: string): ExtractedVariables { export function extractVariables(content: string): ExtractedVariables {
const result: ExtractedVariables = {}; const result: ExtractedVariables = {};

View file

@ -6,6 +6,7 @@ import { MAVEN_REPO } from '../../datasource/maven/common';
import { logger } from '../../logger'; import { logger } from '../../logger';
import { SkipReason } from '../../types'; import { SkipReason } from '../../types';
import { readLocalFile } from '../../util/fs'; import { readLocalFile } from '../../util/fs';
import { regEx } from '../../util/regex';
import type { ExtractConfig, PackageDependency, PackageFile } from '../types'; import type { ExtractConfig, PackageDependency, PackageFile } from '../types';
import type { MavenProp } from './types'; import type { MavenProp } from './types';
@ -33,7 +34,7 @@ export function parsePom(raw: string): XmlDocument | null {
} }
function containsPlaceholder(str: string): boolean { function containsPlaceholder(str: string): boolean {
return /\${.*?}/g.test(str); return regEx(/\${.*?}/g).test(str);
} }
function depFromNode(node: XmlElement): PackageDependency | null { function depFromNode(node: XmlElement): PackageDependency | null {
@ -95,7 +96,7 @@ function applyProps(
props: MavenProp props: MavenProp
): PackageDependency<Record<string, any>> { ): PackageDependency<Record<string, any>> {
const replaceAll = (str: string): string => const replaceAll = (str: string): string =>
str.replace(/\${.*?}/g, (substr) => { str.replace(regEx(/\${.*?}/g), (substr) => {
const propKey = substr.slice(2, -1).trim(); const propKey = substr.slice(2, -1).trim();
const propValue = props[propKey]; const propValue = props[propKey];
return propValue ? propValue.val : substr; return propValue ? propValue.val : substr;
@ -107,19 +108,22 @@ function applyProps(
let fileReplacePosition = dep.fileReplacePosition; let fileReplacePosition = dep.fileReplacePosition;
let propSource = null; let propSource = null;
let groupName = null; let groupName = null;
const currentValue = dep.currentValue.replace(/^\${.*?}$/, (substr) => { const currentValue = dep.currentValue.replace(
const propKey = substr.slice(2, -1).trim(); regEx(/^\${.*?}$/),
const propValue = props[propKey]; (substr) => {
if (propValue) { const propKey = substr.slice(2, -1).trim();
if (!groupName) { const propValue = props[propKey];
groupName = propKey; if (propValue) {
if (!groupName) {
groupName = propKey;
}
fileReplacePosition = propValue.fileReplacePosition;
propSource = propValue.packageFile;
return propValue.val;
} }
fileReplacePosition = propValue.fileReplacePosition; return substr;
propSource = propValue.packageFile;
return propValue.val;
} }
return substr; );
});
const result: PackageDependency = { const result: PackageDependency = {
...dep, ...dep,

View file

@ -1,20 +1,21 @@
import { id as npmId } from '../../datasource/npm'; import { id as npmId } from '../../datasource/npm';
import { logger } from '../../logger'; import { logger } from '../../logger';
import { regEx } from '../../util/regex';
import type { PackageDependency, PackageFile } from '../types'; import type { PackageDependency, PackageFile } from '../types';
export function extractPackageFile(content: string): PackageFile | null { export function extractPackageFile(content: string): PackageFile | null {
let deps: PackageDependency[] = []; let deps: PackageDependency[] = [];
const npmDepends = /\nNpm\.depends\({([\s\S]*?)}\);/.exec(content); const npmDepends = regEx(/\nNpm\.depends\({([\s\S]*?)}\);/).exec(content);
if (!npmDepends) { if (!npmDepends) {
return null; return null;
} }
try { try {
deps = npmDepends[1] deps = npmDepends[1]
.replace(/(\s|\\n|\\t|'|")/g, '') .replace(regEx(/(\s|\\n|\\t|'|")/g), '')
.split(',') .split(',')
.map((dep) => dep.trim()) .map((dep) => dep.trim())
.filter((dep) => dep.length) .filter((dep) => dep.length)
.map((dep) => dep.split(/:(.*)/)) .map((dep) => dep.split(regEx(/:(.*)/))) // TODO #12071
.map((arr) => { .map((arr) => {
const [depName, currentValue] = arr; const [depName, currentValue] = arr;
// istanbul ignore if // istanbul ignore if

View file

@ -2,11 +2,13 @@ import { HexDatasource } from '../../datasource/hex';
import { logger } from '../../logger'; import { logger } from '../../logger';
import { SkipReason } from '../../types'; import { SkipReason } from '../../types';
import { findLocalSiblingOrParent, localPathExists } from '../../util/fs'; import { findLocalSiblingOrParent, localPathExists } from '../../util/fs';
import { regEx } from '../../util/regex';
import type { PackageDependency, PackageFile } from '../types'; import type { PackageDependency, PackageFile } from '../types';
const depSectionRegExp = /defp\s+deps.*do/g; const depSectionRegExp = regEx(/defp\s+deps.*do/g);
const depMatchRegExp = const depMatchRegExp = regEx(
/{:(\w+),\s*([^:"]+)?:?\s*"([^"]+)",?\s*(organization: "(.*)")?.*}/gm; /{:(\w+),\s*([^:"]+)?:?\s*"([^"]+)",?\s*(organization: "(.*)")?.*}/gm
);
export async function extractPackageFile( export async function extractPackageFile(
content: string, content: string,

View file

@ -26,12 +26,12 @@ function parseDepName(depType: string, key: string): string {
return key; return key;
} }
const [, depName] = /((?:@[^/]+\/)?[^/@]+)$/.exec(key) ?? []; const [, depName] = /((?:@[^/]+\/)?[^/@]+)$/.exec(key) ?? []; // TODO #12070
return depName; return depName;
} }
const RE_REPOSITORY_GITHUB_SSH_FORMAT = const RE_REPOSITORY_GITHUB_SSH_FORMAT =
/(?:git@)github.com:([^/]+)\/([^/.]+)(?:\.git)?/; /(?:git@)github.com:([^/]+)\/([^/.]+)(?:\.git)?/; // TODO #12070
export async function extractPackageFile( export async function extractPackageFile(
content: string, content: string,
@ -106,11 +106,11 @@ export async function extractPackageFile(
} else { } else {
npmrc = config.npmrc || ''; npmrc = config.npmrc || '';
if (npmrc.length) { if (npmrc.length) {
npmrc = npmrc.replace(/\n?$/, '\n'); npmrc = npmrc.replace(/\n?$/, '\n'); // TODO #12070
} }
if (repoNpmrc?.includes('package-lock')) { if (repoNpmrc?.includes('package-lock')) {
logger.debug('Stripping package-lock setting from .npmrc'); logger.debug('Stripping package-lock setting from .npmrc');
repoNpmrc = repoNpmrc.replace(/(^|\n)package-lock.*?(\n|$)/g, '\n'); repoNpmrc = repoNpmrc.replace(/(^|\n)package-lock.*?(\n|$)/g, '\n'); // TODO #12070
} }
if (repoNpmrc.includes('=${') && !getGlobalConfig().exposeAllEnv) { if (repoNpmrc.includes('=${') && !getGlobalConfig().exposeAllEnv) {
logger.debug( logger.debug(
@ -272,10 +272,10 @@ export async function extractPackageFile(
const matchUrlSshFormat = RE_REPOSITORY_GITHUB_SSH_FORMAT.exec(depNamePart); const matchUrlSshFormat = RE_REPOSITORY_GITHUB_SSH_FORMAT.exec(depNamePart);
if (matchUrlSshFormat === null) { if (matchUrlSshFormat === null) {
githubOwnerRepo = depNamePart githubOwnerRepo = depNamePart
.replace(/^github:/, '') .replace(/^github:/, '') // TODO #12070
.replace(/^git\+/, '') .replace(/^git\+/, '') // TODO #12070
.replace(/^https:\/\/github\.com\//, '') .replace(/^https:\/\/github\.com\//, '') // TODO #12070
.replace(/\.git$/, ''); .replace(/\.git$/, ''); // TODO #12070
const githubRepoSplit = githubOwnerRepo.split('/'); const githubRepoSplit = githubOwnerRepo.split('/');
if (githubRepoSplit.length !== 2) { if (githubRepoSplit.length !== 2) {
dep.skipReason = SkipReason.UnknownVersion; dep.skipReason = SkipReason.UnknownVersion;
@ -287,7 +287,7 @@ export async function extractPackageFile(
githubRepo = matchUrlSshFormat[2]; githubRepo = matchUrlSshFormat[2];
githubOwnerRepo = `${githubOwner}/${githubRepo}`; githubOwnerRepo = `${githubOwner}/${githubRepo}`;
} }
const githubValidRegex = /^[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}$/; const githubValidRegex = /^[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}$/; // TODO #12070
if ( if (
!githubValidRegex.test(githubOwner) || !githubValidRegex.test(githubOwner) ||
!githubValidRegex.test(githubRepo) !githubValidRegex.test(githubRepo)
@ -302,8 +302,8 @@ export async function extractPackageFile(
dep.lookupName = githubOwnerRepo; dep.lookupName = githubOwnerRepo;
dep.pinDigests = false; dep.pinDigests = false;
} else if ( } else if (
/^[0-9a-f]{7}$/.test(depRefPart) || /^[0-9a-f]{7}$/.test(depRefPart) || // TODO #12070
/^[0-9a-f]{40}$/.test(depRefPart) /^[0-9a-f]{40}$/.test(depRefPart) // TODO #12070
) { ) {
dep.currentRawValue = dep.currentValue; dep.currentRawValue = dep.currentValue;
dep.currentValue = null; dep.currentValue = null;

View file

@ -105,7 +105,7 @@ export async function detectPnpmWorkspaces(
packageFilters !== null && packageFilters !== null &&
matchesAnyPattern( matchesAnyPattern(
packageFile, packageFile,
packageFilters.map((filter) => filter.replace(/\/?$/, '/package.json')) packageFilters.map((filter) => filter.replace(/\/?$/, '/package.json')) // TODO #12070 #12071
); );
if (isPackageInWorkspace) { if (isPackageInWorkspace) {
p.pnpmShrinkwrap = lockFilePath; p.pnpmShrinkwrap = lockFilePath;

View file

@ -23,6 +23,7 @@ import {
} from '../../../util/fs'; } from '../../../util/fs';
import { branchExists, getFile, getRepoStatus } from '../../../util/git'; import { branchExists, getFile, getRepoStatus } from '../../../util/git';
import * as hostRules from '../../../util/host-rules'; import * as hostRules from '../../../util/host-rules';
import { regEx } from '../../../util/regex';
import type { PackageFile, PostUpdateConfig, Upgrade } from '../../types'; import type { PackageFile, PostUpdateConfig, Upgrade } from '../../types';
import { getZeroInstallPaths } from '../extract/yarn'; import { getZeroInstallPaths } from '../extract/yarn';
import * as lerna from './lerna'; import * as lerna from './lerna';
@ -340,8 +341,8 @@ async function updateYarnOffline(
if (mirrorLine) { if (mirrorLine) {
const mirrorPath = mirrorLine const mirrorPath = mirrorLine
.split(' ')[1] .split(' ')[1]
.replace(/"/g, '') .replace(regEx(/"/g), '')
.replace(/\/?$/, '/'); .replace(regEx(/\/?$/), '/');
resolvedPaths.push(upath.join(lockFileDir, mirrorPath)); resolvedPaths.push(upath.join(lockFileDir, mirrorPath));
} }
} }
@ -489,7 +490,7 @@ export async function getAdditionalFiles(
logger.debug(`${npmLock} needs updating`); logger.debug(`${npmLock} needs updating`);
updatedArtifacts.push({ updatedArtifacts.push({
name: npmLock, name: npmLock,
contents: res.lockFile.replace(new RegExp(`${token}`, 'g'), ''), contents: res.lockFile.replace(regEx(`${token}`, 'g'), ''),
}); });
} }
} }

View file

@ -1,6 +1,7 @@
import { satisfies, validRange } from 'semver'; import { satisfies, validRange } from 'semver';
import { logger } from '../../../logger'; import { logger } from '../../../logger';
import { getSiblingFileName, readLocalFile } from '../../../util/fs'; import { getSiblingFileName, readLocalFile } from '../../../util/fs';
import { regEx } from '../../../util/regex';
import { isStable } from '../../../versioning/node'; import { isStable } from '../../../versioning/node';
import type { PostUpdateConfig } from '../../types'; import type { PostUpdateConfig } from '../../types';
@ -8,7 +9,7 @@ async function getNodeFile(filename: string): Promise<string> | null {
try { try {
const constraint = (await readLocalFile(filename, 'utf8')) const constraint = (await readLocalFile(filename, 'utf8'))
.split('\n')[0] .split('\n')[0]
.replace(/^v/, ''); .replace(regEx(/^v/), '');
if (validRange(constraint)) { if (validRange(constraint)) {
logger.debug(`Using node constraint "${constraint}" from ${filename}`); logger.debug(`Using node constraint "${constraint}" from ${filename}`);
return constraint; return constraint;

View file

@ -1,5 +1,6 @@
import is from '@sindresorhus/is'; import is from '@sindresorhus/is';
import * as hostRules from '../../../util/host-rules'; import * as hostRules from '../../../util/host-rules';
import { regEx } from '../../../util/regex';
import { validateUrl } from '../../../util/url'; import { validateUrl } from '../../../util/url';
export interface HostRulesResult { export interface HostRulesResult {
@ -18,7 +19,7 @@ export function processHostRules(): HostRulesResult {
for (const hostRule of npmHostRules) { for (const hostRule of npmHostRules) {
if (hostRule.resolvedHost) { if (hostRule.resolvedHost) {
let uri = hostRule.matchHost; let uri = hostRule.matchHost;
uri = validateUrl(uri) ? uri.replace(/^https?:/, '') : `//${uri}/`; uri = validateUrl(uri) ? uri.replace(regEx(/^https?:/), '') : `//${uri}/`; // TODO #12071
if (hostRule.token) { if (hostRule.token) {
const key = hostRule.authType === 'Basic' ? '_auth' : '_authToken'; const key = hostRule.authType === 'Basic' ? '_auth' : '_authToken';
additionalNpmrcContent.push(`${uri}:${key}=${hostRule.token}`); additionalNpmrcContent.push(`${uri}:${key}=${hostRule.token}`);

View file

@ -12,6 +12,7 @@ import { logger } from '../../../logger';
import { ExternalHostError } from '../../../types/errors/external-host-error'; import { ExternalHostError } from '../../../types/errors/external-host-error';
import { ExecOptions, exec } from '../../../util/exec'; import { ExecOptions, exec } from '../../../util/exec';
import { readFile, remove } from '../../../util/fs'; import { readFile, remove } from '../../../util/fs';
import { regEx } from '../../../util/regex';
import type { PostUpdateConfig, Upgrade } from '../../types'; import type { PostUpdateConfig, Upgrade } from '../../types';
import { getNodeConstraint } from './node-version'; import { getNodeConstraint } from './node-version';
import { GenerateLockFileResult } from './types'; import { GenerateLockFileResult } from './types';
@ -32,7 +33,7 @@ export async function checkYarnrc(
.split('\n') .split('\n')
.find((line) => line.startsWith('yarn-path ')); .find((line) => line.startsWith('yarn-path '));
if (pathLine) { if (pathLine) {
yarnPath = pathLine.replace(/^yarn-path\s+"?(.+?)"?$/, '$1'); yarnPath = pathLine.replace(regEx(/^yarn-path\s+"?(.+?)"?$/), '$1');
} }
} }
} catch (err) /* istanbul ignore next */ { } catch (err) /* istanbul ignore next */ {

View file

@ -1,5 +1,6 @@
import type { PackageJson } from 'type-fest'; import type { PackageJson } from 'type-fest';
import { logger } from '../../../../logger'; import { logger } from '../../../../logger';
import { regEx } from '../../../../util/regex';
import { api as semver } from '../../../../versioning/npm'; import { api as semver } from '../../../../versioning/npm';
import type { PackageLockOrEntry, ParentDependency } from './types'; import type { PackageLockOrEntry, ParentDependency } from './types';
@ -31,7 +32,7 @@ export function findDepConstraints(
if (parentDepName && requires) { if (parentDepName && requires) {
let constraint = requires[depName]; let constraint = requires[depName];
if (constraint) { if (constraint) {
constraint = constraint.replace(/(\d)rc$/, '$1-rc'); constraint = constraint.replace(regEx(/(\d)rc$/), '$1-rc');
// istanbul ignore else // istanbul ignore else
if (semver.isValid(constraint)) { if (semver.isValid(constraint)) {
if (semver.matches(currentVersion, constraint)) { if (semver.matches(currentVersion, constraint)) {

View file

@ -31,7 +31,7 @@ export function bumpPackageVersion(
} }
logger.debug({ newPjVersion }); logger.debug({ newPjVersion });
bumpedContent = content.replace( bumpedContent = content.replace(
/("version":\s*")[^"]*/, /("version":\s*")[^"]*/, // TODO #12070
`$1${newPjVersion}` `$1${newPjVersion}`
); );
if (bumpedContent === content) { if (bumpedContent === content) {

View file

@ -13,6 +13,7 @@ import {
writeLocalFile, writeLocalFile,
} from '../../util/fs'; } from '../../util/fs';
import * as hostRules from '../../util/host-rules'; import * as hostRules from '../../util/host-rules';
import { regEx } from '../../util/regex';
import type { import type {
UpdateArtifact, UpdateArtifact,
UpdateArtifactsConfig, UpdateArtifactsConfig,
@ -88,7 +89,7 @@ export async function updateArtifacts({
}: UpdateArtifact): Promise<UpdateArtifactsResult[] | null> { }: UpdateArtifact): Promise<UpdateArtifactsResult[] | null> {
logger.debug(`nuget.updateArtifacts(${packageFileName})`); logger.debug(`nuget.updateArtifacts(${packageFileName})`);
if (!/(?:cs|vb|fs)proj$/i.test(packageFileName)) { if (!regEx(/(?:cs|vb|fs)proj$/i).test(packageFileName)) {
// This could be implemented in the future if necessary. // This could be implemented in the future if necessary.
// It's not that easy though because the questions which // It's not that easy though because the questions which
// project file to restore how to determine which lock files // project file to restore how to determine which lock files

View file

@ -21,7 +21,7 @@ import { getConfiguredRegistries } from './util';
* so we don't include it in the extracting regexp * so we don't include it in the extracting regexp
*/ */
const checkVersion = const checkVersion =
/^\s*(?:[[])?(?:(?<currentValue>[^"(,[\]]+)\s*(?:,\s*[)\]]|])?)\s*$/; /^\s*(?:[[])?(?:(?<currentValue>[^"(,[\]]+)\s*(?:,\s*[)\]]|])?)\s*$/; // TODO #12070
const elemNames = new Set([ const elemNames = new Set([
'PackageReference', 'PackageReference',
'PackageVersion', 'PackageVersion',

View file

@ -5,6 +5,7 @@ import { XmlDocument } from 'xmldoc';
import * as datasourceNuget from '../../datasource/nuget'; import * as datasourceNuget from '../../datasource/nuget';
import { logger } from '../../logger'; import { logger } from '../../logger';
import { readFile } from '../../util/fs'; import { readFile } from '../../util/fs';
import { regEx } from '../../util/regex';
import type { Registry } from './types'; import type { Registry } from './types';
async function readFileAsXmlDocument(file: string): Promise<XmlDocument> { async function readFileAsXmlDocument(file: string): Promise<XmlDocument> {
@ -68,7 +69,7 @@ export async function getConfiguredRegistries(
logger.debug(`clearing registry URLs`); logger.debug(`clearing registry URLs`);
registries.length = 0; registries.length = 0;
} else if (child.name === 'add') { } else if (child.name === 'add') {
const isHttpUrl = /^https?:\/\//i.test(child.attr.value); const isHttpUrl = regEx(/^https?:\/\//i).test(child.attr.value); // TODO #12071
if (isHttpUrl) { if (isHttpUrl) {
let registryUrl = child.attr.value; let registryUrl = child.attr.value;
if (child.attr.protocolVersion) { if (child.attr.protocolVersion) {

View file

@ -5,6 +5,7 @@ import { logger } from '../../logger';
import { ExecOptions, exec } from '../../util/exec'; import { ExecOptions, exec } from '../../util/exec';
import { deleteLocalFile, readLocalFile, writeLocalFile } from '../../util/fs'; import { deleteLocalFile, readLocalFile, writeLocalFile } from '../../util/fs';
import { getRepoStatus } from '../../util/git'; import { getRepoStatus } from '../../util/git';
import { regEx } from '../../util/regex';
import type { import type {
UpdateArtifact, UpdateArtifact,
UpdateArtifactsConfig, UpdateArtifactsConfig,
@ -42,7 +43,7 @@ export async function updateArtifacts({
newPackageFileContent: newInputContent, newPackageFileContent: newInputContent,
config, config,
}: UpdateArtifact): Promise<UpdateArtifactsResult[] | null> { }: UpdateArtifact): Promise<UpdateArtifactsResult[] | null> {
const outputFileName = inputFileName.replace(/(\.in)?$/, '.txt'); const outputFileName = inputFileName.replace(regEx(/(\.in)?$/), '.txt');
logger.debug( logger.debug(
`pipCompile.updateArtifacts(${inputFileName}->${outputFileName})` `pipCompile.updateArtifacts(${inputFileName}->${outputFileName})`
); );

View file

@ -3,6 +3,7 @@ import { TEMPORARY_ERROR } from '../../constants/error-messages';
import { logger } from '../../logger'; import { logger } from '../../logger';
import { ExecOptions, exec } from '../../util/exec'; import { ExecOptions, exec } from '../../util/exec';
import { readLocalFile } from '../../util/fs'; import { readLocalFile } from '../../util/fs';
import { regEx } from '../../util/regex';
import type { UpdateArtifact, UpdateArtifactsResult } from '../types'; import type { UpdateArtifact, UpdateArtifactsResult } from '../types';
export async function updateArtifacts({ export async function updateArtifacts({
@ -18,7 +19,7 @@ export async function updateArtifacts({
} }
try { try {
const cmd: string[] = []; const cmd: string[] = [];
const rewrittenContent = newPackageFileContent.replace(/\\\n/g, ''); const rewrittenContent = newPackageFileContent.replace(regEx(/\\\n/g), '');
const lines = rewrittenContent.split('\n').map((line) => line.trim()); const lines = rewrittenContent.split('\n').map((line) => line.trim());
for (const dep of updatedDeps) { for (const dep of updatedDeps) {
const hashLine = lines.find( const hashLine = lines.find(

View file

@ -5,6 +5,7 @@ import { PypiDatasource } from '../../datasource/pypi';
import { logger } from '../../logger'; import { logger } from '../../logger';
import { SkipReason } from '../../types'; import { SkipReason } from '../../types';
import { isSkipComment } from '../../util/ignore'; import { isSkipComment } from '../../util/ignore';
import { regEx } from '../../util/regex';
import type { ExtractConfig, PackageDependency, PackageFile } from '../types'; import type { ExtractConfig, PackageDependency, PackageFile } from '../types';
export const packagePattern = export const packagePattern =
@ -12,7 +13,10 @@ export const packagePattern =
const extrasPattern = '(?:\\s*\\[[^\\]]+\\])?'; const extrasPattern = '(?:\\s*\\[[^\\]]+\\])?';
const rangePattern: string = RANGE_PATTERN; const rangePattern: string = RANGE_PATTERN;
const specifierPartPattern = `\\s*${rangePattern.replace(/\?<\w+>/g, '?:')}`; const specifierPartPattern = `\\s*${rangePattern.replace(
regEx(/\?<\w+>/g),
'?:'
)}`;
const specifierPattern = `${specifierPartPattern}(?:\\s*,${specifierPartPattern})*`; const specifierPattern = `${specifierPartPattern}(?:\\s*,${specifierPartPattern})*`;
export const dependencyPattern = `(${packagePattern})(${extrasPattern})(${specifierPattern})`; export const dependencyPattern = `(${packagePattern})(${extrasPattern})(${specifierPattern})`;
@ -49,7 +53,7 @@ export function extractPackageFile(
} }
registryUrls = registryUrls.concat(extraUrls); registryUrls = registryUrls.concat(extraUrls);
const regex = new RegExp(`^${dependencyPattern}$`, 'g'); const regex = regEx(`^${dependencyPattern}$`, 'g');
const deps = content const deps = content
.split('\n') .split('\n')
.map((rawline) => { .map((rawline) => {
@ -84,15 +88,18 @@ export function extractPackageFile(
if (registryUrls.length > 0) { if (registryUrls.length > 0) {
res.registryUrls = registryUrls.map((url) => { res.registryUrls = registryUrls.map((url) => {
// handle the optional quotes in eg. `--extra-index-url "https://foo.bar"` // handle the optional quotes in eg. `--extra-index-url "https://foo.bar"`
const cleaned = url.replace(/^"/, '').replace(/"$/, ''); const cleaned = url.replace(regEx(/^"/), '').replace(regEx(/"$/), ''); // TODO #12071
if (!getGlobalConfig().exposeAllEnv) { if (!getGlobalConfig().exposeAllEnv) {
return cleaned; return cleaned;
} }
// interpolate any environment variables // interpolate any environment variables
return cleaned.replace( return cleaned.replace(
/(\$[A-Za-z\d_]+)|(\${[A-Za-z\d_]+})/g, regEx(/(\$[A-Za-z\d_]+)|(\${[A-Za-z\d_]+})/g), // TODO #12071
(match) => { (match) => {
const envvar = match.substring(1).replace(/^{/, '').replace(/}$/, ''); const envvar = match
.substring(1)
.replace(regEx(/^{/), '')
.replace(regEx(/}$/), ''); // TODO #12071
const sub = process.env[envvar]; const sub = process.env[envvar];
return sub || match; return sub || match;
} }

View file

@ -4,6 +4,7 @@ import { logger } from '../../logger';
import { SkipReason } from '../../types'; import { SkipReason } from '../../types';
import { exec } from '../../util/exec'; import { exec } from '../../util/exec';
import { isSkipComment } from '../../util/ignore'; import { isSkipComment } from '../../util/ignore';
import { regEx } from '../../util/regex';
import { dependencyPattern } from '../pip_requirements/extract'; import { dependencyPattern } from '../pip_requirements/extract';
import type { ExtractConfig, PackageDependency, PackageFile } from '../types'; import type { ExtractConfig, PackageDependency, PackageFile } from '../types';
import type { PythonSetup } from './types'; import type { PythonSetup } from './types';
@ -63,7 +64,7 @@ export async function extractSetupFile(
}); });
if (res.stderr) { if (res.stderr) {
const stderr = res.stderr const stderr = res.stderr
.replace(/.*\n\s*import imp/, '') .replace(regEx(/.*\n\s*import imp/), '')
.trim() .trim()
.replace('fatal: No names found, cannot describe anything.', ''); .replace('fatal: No names found, cannot describe anything.', '');
if (stderr.length) { if (stderr.length) {
@ -97,7 +98,7 @@ export async function extractPackageFile(
requires.push(...req); requires.push(...req);
} }
} }
const regex = new RegExp(`^${dependencyPattern}`); const regex = regEx(`^${dependencyPattern}`);
const lines = content.split('\n'); const lines = content.split('\n');
const deps = requires const deps = requires
.map((req) => { .map((req) => {

View file

@ -5,15 +5,16 @@ import { PypiDatasource } from '../../datasource/pypi';
import { logger } from '../../logger'; import { logger } from '../../logger';
import { SkipReason } from '../../types'; import { SkipReason } from '../../types';
import { localPathExists } from '../../util/fs'; import { localPathExists } from '../../util/fs';
import { regEx } from '../../util/regex';
import type { PackageDependency, PackageFile } from '../types'; import type { PackageDependency, PackageFile } from '../types';
import type { PipFile } from './types'; import type { PipFile } from './types';
// based on https://www.python.org/dev/peps/pep-0508/#names // based on https://www.python.org/dev/peps/pep-0508/#names
const packageRegex = /^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$/i; const packageRegex = regEx(/^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$/i);
const rangePattern: string = RANGE_PATTERN; const rangePattern: string = RANGE_PATTERN;
const specifierPartPattern = `\\s*${rangePattern.replace( const specifierPartPattern = `\\s*${rangePattern.replace(
/\?<\w+>/g, regEx(/\?<\w+>/g),
'?:' '?:'
)}\\s*`; )}\\s*`;
const specifierPattern = `${specifierPartPattern}(?:,${specifierPartPattern})*`; const specifierPattern = `${specifierPartPattern}(?:,${specifierPartPattern})*`;
@ -24,7 +25,7 @@ function extractFromSection(
if (!(section in pipfile)) { if (!(section in pipfile)) {
return []; return [];
} }
const specifierRegex = new RegExp(`^${specifierPattern}$`); const specifierRegex = regEx(`^${specifierPattern}$`);
const pipfileSection = pipfile[section]; const pipfileSection = pipfile[section];
const deps = Object.entries(pipfileSection) const deps = Object.entries(pipfileSection)

View file

@ -89,13 +89,13 @@ function extractDependency(
// This splits "git@private.registry.com:user/repo" -> "private.registry.com" "user/repo // This splits "git@private.registry.com:user/repo" -> "private.registry.com" "user/repo
regEx('^git@(?<hostname>[^:]+):(?<depName>\\S*)'), regEx('^git@(?<hostname>[^:]+):(?<depName>\\S*)'),
// This split "git://github.com/pre-commit/pre-commit-hooks" -> "github.com" "pre-commit/pre-commit-hooks" // This split "git://github.com/pre-commit/pre-commit-hooks" -> "github.com" "pre-commit/pre-commit-hooks"
/^git:\/\/(?<hostname>[^/]+)\/(?<depName>\S*)/, regEx(/^git:\/\/(?<hostname>[^/]+)\/(?<depName>\S*)/),
]; ];
for (const urlMatcher of urlMatchers) { for (const urlMatcher of urlMatchers) {
const match = urlMatcher.exec(repository); const match = urlMatcher.exec(repository);
if (match) { if (match) {
const hostname = match.groups.hostname; const hostname = match.groups.hostname;
const depName = match.groups.depName.replace(/\.git$/i, ''); const depName = match.groups.depName.replace(regEx(/\.git$/i), ''); // TODO 12071
const sourceDef = determineDatasource(repository, hostname); const sourceDef = determineDatasource(repository, hostname);
return { return {
...sourceDef, ...sourceDef,

View file

@ -2,38 +2,42 @@ import * as datasourceMaven from '../../datasource/maven';
import { MAVEN_REPO } from '../../datasource/maven/common'; import { MAVEN_REPO } from '../../datasource/maven/common';
import * as datasourceSbtPackage from '../../datasource/sbt-package'; import * as datasourceSbtPackage from '../../datasource/sbt-package';
import * as datasourceSbtPlugin from '../../datasource/sbt-plugin'; import * as datasourceSbtPlugin from '../../datasource/sbt-plugin';
import { regEx } from '../../util/regex';
import { get } from '../../versioning'; import { get } from '../../versioning';
import * as mavenVersioning from '../../versioning/maven'; import * as mavenVersioning from '../../versioning/maven';
import type { PackageDependency, PackageFile } from '../types'; import type { PackageDependency, PackageFile } from '../types';
import type { ParseContext, ParseOptions } from './types'; import type { ParseContext, ParseOptions } from './types';
const stripComment = (str: string): string => str.replace(/(^|\s+)\/\/.*$/, ''); const stripComment = (str: string): string =>
str.replace(regEx(/(^|\s+)\/\/.*$/), '');
const isSingleLineDep = (str: string): boolean => const isSingleLineDep = (str: string): boolean =>
/^\s*(libraryDependencies|dependencyOverrides)\s*\+=\s*/.test(str); regEx(/^\s*(libraryDependencies|dependencyOverrides)\s*\+=\s*/).test(str);
const isDepsBegin = (str: string): boolean => const isDepsBegin = (str: string): boolean =>
/^\s*(libraryDependencies|dependencyOverrides)\s*\+\+=\s*/.test(str); regEx(/^\s*(libraryDependencies|dependencyOverrides)\s*\+\+=\s*/).test(str);
const isPluginDep = (str: string): boolean => const isPluginDep = (str: string): boolean =>
/^\s*addSbtPlugin\s*\(.*\)\s*$/.test(str); regEx(/^\s*addSbtPlugin\s*\(.*\)\s*$/).test(str);
const isStringLiteral = (str: string): boolean => /^"[^"]*"$/.test(str); const isStringLiteral = (str: string): boolean => regEx(/^"[^"]*"$/).test(str);
const isScalaVersion = (str: string): boolean => const isScalaVersion = (str: string): boolean =>
/^\s*scalaVersion\s*:=\s*"[^"]*"[\s,]*$/.test(str); regEx(/^\s*scalaVersion\s*:=\s*"[^"]*"[\s,]*$/).test(str);
const getScalaVersion = (str: string): string => const getScalaVersion = (str: string): string =>
str.replace(/^\s*scalaVersion\s*:=\s*"/, '').replace(/"[\s,]*$/, ''); str
.replace(regEx(/^\s*scalaVersion\s*:=\s*"/), '')
.replace(regEx(/"[\s,]*$/), '');
const isPackageFileVersion = (str: string): boolean => const isPackageFileVersion = (str: string): boolean =>
/^(version\s*:=\s*).*$/.test(str); regEx(/^(version\s*:=\s*).*$/).test(str);
const getPackageFileVersion = (str: string): string => const getPackageFileVersion = (str: string): string =>
str str
.replace(/^\s*version\s*:=\s*/, '') .replace(regEx(/^\s*version\s*:=\s*/), '')
.replace(/[\s,]*$/, '') .replace(regEx(/[\s,]*$/), '')
.replace(/"/g, ''); .replace(regEx(/"/g), '');
/* /*
https://www.scala-sbt.org/release/docs/Cross-Build.html#Publishing+conventions https://www.scala-sbt.org/release/docs/Cross-Build.html#Publishing+conventions
@ -54,62 +58,64 @@ const normalizeScalaVersion = (str: string): string => {
return str; return str;
} }
} }
if (/^\d+\.\d+\.\d+$/.test(str)) { if (regEx(/^\d+\.\d+\.\d+$/).test(str)) {
return str.replace(/^(\d+)\.(\d+)\.\d+$/, '$1.$2'); return str.replace(regEx(/^(\d+)\.(\d+)\.\d+$/), '$1.$2');
} }
// istanbul ignore next // istanbul ignore next
return str; return str;
}; };
const isScalaVersionVariable = (str: string): boolean => const isScalaVersionVariable = (str: string): boolean =>
/^\s*scalaVersion\s*:=\s*[_a-zA-Z][_a-zA-Z0-9]*[\s,]*$/.test(str); regEx(/^\s*scalaVersion\s*:=\s*[_a-zA-Z][_a-zA-Z0-9]*[\s,]*$/).test(str);
const getScalaVersionVariable = (str: string): string => const getScalaVersionVariable = (str: string): string =>
str.replace(/^\s*scalaVersion\s*:=\s*/, '').replace(/[\s,]*$/, ''); str
.replace(regEx(/^\s*scalaVersion\s*:=\s*/), '')
.replace(regEx(/[\s,]*$/), '');
const isResolver = (str: string): boolean => const isResolver = (str: string): boolean =>
/^\s*(resolvers\s*\+\+?=\s*(Seq\()?)?"[^"]*"\s*at\s*"[^"]*"[\s,)]*$/.test( regEx(
str /^\s*(resolvers\s*\+\+?=\s*(Seq\()?)?"[^"]*"\s*at\s*"[^"]*"[\s,)]*$/
); ).test(str);
const getResolverUrl = (str: string): string => const getResolverUrl = (str: string): string =>
str str
.replace(/^\s*(resolvers\s*\+\+?=\s*(Seq\()?)?"[^"]*"\s*at\s*"/, '') .replace(regEx(/^\s*(resolvers\s*\+\+?=\s*(Seq\()?)?"[^"]*"\s*at\s*"/), '')
.replace(/"[\s,)]*$/, ''); .replace(regEx(/"[\s,)]*$/), '');
const isVarDependency = (str: string): boolean => const isVarDependency = (str: string): boolean =>
/^\s*(private\s*)?(lazy\s*)?val\s[_a-zA-Z][_a-zA-Z0-9]*\s*=.*(%%?).*%.*/.test( regEx(
str /^\s*(private\s*)?(lazy\s*)?val\s[_a-zA-Z][_a-zA-Z0-9]*\s*=.*(%%?).*%.*/
); ).test(str);
const isVarDef = (str: string): boolean => const isVarDef = (str: string): boolean =>
/^\s*(private\s*)?(lazy\s*)?val\s+[_a-zA-Z][_a-zA-Z0-9]*\s*=\s*"[^"]*"\s*$/.test( regEx(
str /^\s*(private\s*)?(lazy\s*)?val\s+[_a-zA-Z][_a-zA-Z0-9]*\s*=\s*"[^"]*"\s*$/
); ).test(str);
const isVarSeqSingleLine = (str: string): boolean => const isVarSeqSingleLine = (str: string): boolean =>
/^\s*(private\s*)?(lazy\s*)?val\s+[_a-zA-Z][_a-zA-Z0-9]*\s*=\s*Seq\(.*\).*\s*$/.test( regEx(
str /^\s*(private\s*)?(lazy\s*)?val\s+[_a-zA-Z][_a-zA-Z0-9]*\s*=\s*Seq\(.*\).*\s*$/
); ).test(str);
const isVarSeqMultipleLine = (str: string): boolean => const isVarSeqMultipleLine = (str: string): boolean =>
/^\s*(private\s*)?(lazy\s*)?val\s+[_a-zA-Z][_a-zA-Z0-9]*\s*=\s*Seq\(.*[^)]*.*$/.test( regEx(
str /^\s*(private\s*)?(lazy\s*)?val\s+[_a-zA-Z][_a-zA-Z0-9]*\s*=\s*Seq\(.*[^)]*.*$/
); ).test(str);
const getVarName = (str: string): string => const getVarName = (str: string): string =>
str str
.replace(/^\s*(private\s*)?(lazy\s*)?val\s+/, '') .replace(regEx(/^\s*(private\s*)?(lazy\s*)?val\s+/), '')
.replace(/\s*=\s*"[^"]*"\s*$/, ''); .replace(regEx(/\s*=\s*"[^"]*"\s*$/), '');
const isVarName = (str: string): boolean => const isVarName = (str: string): boolean =>
/^[_a-zA-Z][_a-zA-Z0-9]*$/.test(str); regEx(/^[_a-zA-Z][_a-zA-Z0-9]*$/).test(str);
const getVarInfo = (str: string, ctx: ParseContext): { val: string } => { const getVarInfo = (str: string, ctx: ParseContext): { val: string } => {
const rightPart = str.replace( const rightPart = str.replace(
/^\s*(private\s*)?(lazy\s*)?val\s+[_a-zA-Z][_a-zA-Z0-9]*\s*=\s*"/, regEx(/^\s*(private\s*)?(lazy\s*)?val\s+[_a-zA-Z][_a-zA-Z0-9]*\s*=\s*"/),
'' ''
); );
const val = rightPart.replace(/"\s*$/, ''); const val = rightPart.replace(regEx(/"\s*$/), '');
return { val }; return { val };
}; };
@ -125,15 +131,15 @@ function parseDepExpr(
const resolveToken = (str: string): string => const resolveToken = (str: string): string =>
isStringLiteral(str) isStringLiteral(str)
? str.replace(/^"/, '').replace(/"$/, '') ? str.replace(regEx(/^"/), '').replace(regEx(/"$/), '')
: variables[str].val; : variables[str].val;
const tokens = expr const tokens = expr
.trim() .trim()
.split(/("[^"]*")/g) .split(regEx(/("[^"]*")/g))
.map((x) => (/"[^"]*"/.test(x) ? x : x.replace(/[()]+/g, ''))) .map((x) => (regEx(/"[^"]*"/).test(x) ? x : x.replace(regEx(/[()]+/g), ''))) // TODO #12071
.join('') .join('')
.split(/\s*(%%?)\s*|\s*classifier\s*/); .split(regEx(/\s*(%%?)\s*|\s*classifier\s*/));
const [ const [
rawGroupId, rawGroupId,
@ -183,7 +189,7 @@ function parseDepExpr(
const currentValue = resolveToken(rawVersion); const currentValue = resolveToken(rawVersion);
if (!depType && rawScope) { if (!depType && rawScope) {
depType = rawScope.replace(/^"/, '').replace(/"$/, ''); depType = rawScope.replace(regEx(/^"/), '').replace(regEx(/"$/), '');
} }
const result: PackageDependency = { const result: PackageDependency = {
@ -243,13 +249,15 @@ function parseSbtLine(
registryUrls.push(url); registryUrls.push(url);
} else if (isVarSeqSingleLine(line)) { } else if (isVarSeqSingleLine(line)) {
isMultiDeps = false; isMultiDeps = false;
const depExpr = line.replace(/^.*Seq\(\s*/, '').replace(/\).*$/, ''); const depExpr = line
.replace(regEx(/^.*Seq\(\s*/), '')
.replace(regEx(/\).*$/), '');
dep = parseDepExpr(depExpr, { dep = parseDepExpr(depExpr, {
...ctx, ...ctx,
}); });
} else if (isVarSeqMultipleLine(line)) { } else if (isVarSeqMultipleLine(line)) {
isMultiDeps = true; isMultiDeps = true;
const depExpr = line.replace(/^.*Seq\(\s*/, ''); const depExpr = line.replace(regEx(/^.*Seq\(\s*/), '');
dep = parseDepExpr(depExpr, { dep = parseDepExpr(depExpr, {
...ctx, ...ctx,
}); });
@ -258,7 +266,7 @@ function parseSbtLine(
} else if (isVarDependency(line)) { } else if (isVarDependency(line)) {
isMultiDeps = false; isMultiDeps = false;
const depExpr = line.replace( const depExpr = line.replace(
/^\s*(private\s*)?(lazy\s*)?val\s[_a-zA-Z][_a-zA-Z0-9]*\s*=\s*/, regEx(/^\s*(private\s*)?(lazy\s*)?val\s[_a-zA-Z][_a-zA-Z0-9]*\s*=\s*/),
'' ''
); );
dep = parseDepExpr(depExpr, { dep = parseDepExpr(depExpr, {
@ -266,14 +274,14 @@ function parseSbtLine(
}); });
} else if (isSingleLineDep(line)) { } else if (isSingleLineDep(line)) {
isMultiDeps = false; isMultiDeps = false;
const depExpr = line.replace(/^.*\+=\s*/, ''); const depExpr = line.replace(regEx(/^.*\+=\s*/), '');
dep = parseDepExpr(depExpr, { dep = parseDepExpr(depExpr, {
...ctx, ...ctx,
}); });
} else if (isPluginDep(line)) { } else if (isPluginDep(line)) {
isMultiDeps = false; isMultiDeps = false;
const rightPart = line.replace(/^\s*addSbtPlugin\s*\(/, ''); const rightPart = line.replace(regEx(/^\s*addSbtPlugin\s*\(/), '');
const depExpr = rightPart.replace(/\)\s*$/, ''); const depExpr = rightPart.replace(regEx(/\)\s*$/), '');
dep = parseDepExpr(depExpr, { dep = parseDepExpr(depExpr, {
...ctx, ...ctx,
depType: 'plugin', depType: 'plugin',
@ -281,8 +289,8 @@ function parseSbtLine(
} else if (isDepsBegin(line)) { } else if (isDepsBegin(line)) {
isMultiDeps = true; isMultiDeps = true;
} else if (isMultiDeps) { } else if (isMultiDeps) {
const rightPart = line.replace(/^[\s,]*/, ''); const rightPart = line.replace(regEx(/^[\s,]*/), '');
const depExpr = rightPart.replace(/[\s,]*$/, ''); const depExpr = rightPart.replace(regEx(/[\s,]*$/), '');
dep = parseDepExpr(depExpr, { dep = parseDepExpr(depExpr, {
...ctx, ...ctx,
}); });
@ -332,7 +340,7 @@ export function extractPackageFile(content: string): PackageFile {
if (!content) { if (!content) {
return null; return null;
} }
const lines = content.split(/\n/).map(stripComment); const lines = content.split(regEx(/\n/)).map(stripComment);
return lines.reduce(parseSbtLine, { return lines.reduce(parseSbtLine, {
registryUrls: [MAVEN_REPO], registryUrls: [MAVEN_REPO],
deps: [], deps: [],

View file

@ -1,5 +1,6 @@
import { ReleaseType, inc } from 'semver'; import { ReleaseType, inc } from 'semver';
import { logger } from '../../logger'; import { logger } from '../../logger';
import { regEx } from '../../util/regex';
import type { BumpPackageVersionResult } from '../types'; import type { BumpPackageVersionResult } from '../types';
export function bumpPackageVersion( export function bumpPackageVersion(
@ -18,7 +19,7 @@ export function bumpPackageVersion(
return { bumpedContent }; return { bumpedContent };
} }
bumpedContent = content.replace( bumpedContent = content.replace(
/^(version\s*:=\s*).*$/m, regEx(/^(version\s*:=\s*).*$/m),
`$1"${bumpedVersion}"` `$1"${bumpedVersion}"`
); );

View file

@ -1,14 +1,15 @@
import { PypiDatasource } from '../../datasource/pypi'; import { PypiDatasource } from '../../datasource/pypi';
import { regEx } from '../../util/regex';
import pep440 from '../../versioning/pep440'; import pep440 from '../../versioning/pep440';
import type { PackageDependency, PackageFile, Result } from '../types'; import type { PackageDependency, PackageFile, Result } from '../types';
function getSectionName(str: string): string { function getSectionName(str: string): string {
const [, sectionName] = /^\[\s*([^\s]+)\s*]\s*$/.exec(str) || []; const [, sectionName] = regEx(/^\[\s*([^\s]+)\s*]\s*$/).exec(str) || []; // TODO #12071
return sectionName; return sectionName;
} }
function getSectionRecord(str: string): string { function getSectionRecord(str: string): string {
const [, sectionRecord] = /^([^\s]+)\s+=/.exec(str) || []; const [, sectionRecord] = regEx(/^([^\s]+)\s+=/).exec(str) || []; // TODO #12071
return sectionRecord; return sectionRecord;
} }
@ -33,7 +34,7 @@ function parseDep(
record: string record: string
): PackageDependency | null { ): PackageDependency | null {
const [, depName, , currentValue] = const [, depName, , currentValue] =
/\s+([-_a-zA-Z0-9]*)(\[.*\])?\s*(.*)/.exec(line) || []; regEx(/\s+([-_a-zA-Z0-9]*)(\[.*\])?\s*(.*)/).exec(line) || [];
if ( if (
section && section &&
record && record &&
@ -64,7 +65,7 @@ export function extractPackageFile(
const deps: PackageDependency[] = []; const deps: PackageDependency[] = [];
content content
.split('\n') .split('\n')
.map((line) => line.replace(/[;#].*$/, '').trimRight()) .map((line) => line.replace(regEx(/[;#].*$/), '').trimRight()) // TODO #12071
.forEach((rawLine) => { .forEach((rawLine) => {
let line = rawLine; let line = rawLine;
const newSectionName = getSectionName(line); const newSectionName = getSectionName(line);
@ -74,7 +75,7 @@ export function extractPackageFile(
} else { } else {
if (newSectionRecord) { if (newSectionRecord) {
sectionRecord = newSectionRecord; sectionRecord = newSectionRecord;
line = rawLine.replace(/^[^=]*=\s*/, '\t'); line = rawLine.replace(regEx(/^[^=]*=\s*/), '\t'); // TODO #12071
} }
const dep = parseDep(line, sectionName, sectionRecord); const dep = parseDep(line, sectionName, sectionRecord);
if (dep) { if (dep) {

View file

@ -1,21 +1,22 @@
import * as datasourceGitTags from '../../datasource/git-tags'; import * as datasourceGitTags from '../../datasource/git-tags';
import { regEx } from '../../util/regex';
import type { PackageDependency, PackageFile } from '../types'; import type { PackageDependency, PackageFile } from '../types';
import type { MatchResult } from './types'; import type { MatchResult } from './types';
const regExps = { const regExps = {
wildcard: /^.*?/, wildcard: regEx(/^.*?/),
space: /(\s+|\/\/[^\n]*|\/\*.*\*\/)+/s, space: regEx(/(\s+|\/\/[^\n]*|\/\*.*\*\/)+/, 's'),
depsKeyword: /dependencies/, depsKeyword: regEx(/dependencies/),
colon: /:/, colon: regEx(/:/),
beginSection: /\[/, beginSection: regEx(/\[/),
endSection: /],?/, endSection: regEx(/],?/),
package: /\s*.\s*package\s*\(\s*/, package: regEx(/\s*.\s*package\s*\(\s*/),
urlKey: /url/, urlKey: regEx(/url/),
stringLiteral: /"[^"]+"/, stringLiteral: regEx(/"[^"]+"/),
comma: /,/, comma: regEx(/,/),
from: /from/, from: regEx(/from/),
rangeOp: /\.\.[.<]/, rangeOp: regEx(/\.\.[.<]/),
exactVersion: /\.\s*exact\s*\(\s*/, exactVersion: regEx(/\.\s*exact\s*\(\s*/),
}; };
const WILDCARD = 'wildcard'; const WILDCARD = 'wildcard';
@ -116,9 +117,9 @@ function getDepName(url: string): string | null {
const { host, pathname } = new URL(url); const { host, pathname } = new URL(url);
if (host === 'github.com' || host === 'gitlab.com') { if (host === 'github.com' || host === 'gitlab.com') {
return pathname return pathname
.replace(/^\//, '') .replace(regEx(/^\//), '')
.replace(/\.git$/, '') .replace(regEx(/\.git$/), '')
.replace(/\/$/, ''); .replace(regEx(/\/$/), '');
} }
return url; return url;
} catch (e) { } catch (e) {
@ -224,7 +225,7 @@ export function extractPackageFile(
yieldDep(); yieldDep();
state = null; state = null;
} else if (label === STRING_LITERAL) { } else if (label === STRING_LITERAL) {
lookupName = substr.replace(/^"/, '').replace(/"$/, ''); lookupName = substr.replace(regEx(/^"/), '').replace(regEx(/"$/), '');
state = '.package(url: [depName]'; state = '.package(url: [depName]';
} else if (label === PACKAGE) { } else if (label === PACKAGE) {
yieldDep(); yieldDep();

View file

@ -1,5 +1,6 @@
import is from '@sindresorhus/is'; import is from '@sindresorhus/is';
import { logger } from '../../logger'; import { logger } from '../../logger';
import { regEx } from '../../util/regex';
import type { ExtractConfig, PackageDependency, PackageFile } from '../types'; import type { ExtractConfig, PackageDependency, PackageFile } from '../types';
import { TerraformDependencyTypes } from './common'; import { TerraformDependencyTypes } from './common';
import { extractLocks, findLockFile, readLockFile } from './lockfile/util'; import { extractLocks, findLockFile, readLockFile } from './lockfile/util';
@ -26,8 +27,9 @@ import {
getTerraformDependencyType, getTerraformDependencyType,
} from './util'; } from './util';
const dependencyBlockExtractionRegex = const dependencyBlockExtractionRegex = regEx(
/^\s*(?<type>[a-z_]+)\s+("(?<lookupName>[^"]+)"\s+)?("(?<terraformName>[^"]+)"\s+)?{\s*$/; /^\s*(?<type>[a-z_]+)\s+("(?<lookupName>[^"]+)"\s+)?("(?<terraformName>[^"]+)"\s+)?{\s*$/
);
const contentCheckList = [ const contentCheckList = [
'module "', 'module "',
'provider "', 'provider "',

View file

@ -31,7 +31,7 @@ export class TerraformProviderHash {
// add double space, the filename and a new line char // add double space, the filename and a new line char
rootHash.update(' '); rootHash.update(' ');
const fileName = file.replace(/^.*[\\/]/, ''); const fileName = file.replace(/^.*[\\/]/, ''); // TODO #12070
rootHash.update(fileName); rootHash.update(fileName);
rootHash.update('\n'); rootHash.update('\n');
} }

View file

@ -9,12 +9,12 @@ import type {
} from './types'; } from './types';
const providerStartLineRegex = const providerStartLineRegex =
/^provider "(?<registryUrl>[^/]*)\/(?<namespace>[^/]*)\/(?<depName>[^/]*)"/; /^provider "(?<registryUrl>[^/]*)\/(?<namespace>[^/]*)\/(?<depName>[^/]*)"/; // TODO #12070
const versionLineRegex = const versionLineRegex =
/^(?<prefix>[\s]*version[\s]*=[\s]*")(?<version>[^"']+)(?<suffix>".*)$/; /^(?<prefix>[\s]*version[\s]*=[\s]*")(?<version>[^"']+)(?<suffix>".*)$/; // TODO #12070
const constraintLineRegex = const constraintLineRegex =
/^(?<prefix>[\s]*constraints[\s]*=[\s]*")(?<constraint>[^"']+)(?<suffix>".*)$/; /^(?<prefix>[\s]*constraints[\s]*=[\s]*")(?<constraint>[^"']+)(?<suffix>".*)$/; // TODO #12070
const hashLineRegex = /^(?<prefix>\s*")(?<hash>[^"]+)(?<suffix>",.*)$/; const hashLineRegex = /^(?<prefix>\s*")(?<hash>[^"]+)(?<suffix>",.*)$/; // TODO #12070
const lockFile = '.terraform.lock.hcl'; const lockFile = '.terraform.lock.hcl';

View file

@ -3,16 +3,19 @@ import * as datasourceGithubTags from '../../datasource/github-tags';
import { TerraformModuleDatasource } from '../../datasource/terraform-module'; import { TerraformModuleDatasource } from '../../datasource/terraform-module';
import { logger } from '../../logger'; import { logger } from '../../logger';
import { SkipReason } from '../../types'; import { SkipReason } from '../../types';
import { regEx } from '../../util/regex';
import type { PackageDependency } from '../types'; import type { PackageDependency } from '../types';
import { TerraformDependencyTypes } from './common'; import { TerraformDependencyTypes } from './common';
import { extractTerraformProvider } from './providers'; import { extractTerraformProvider } from './providers';
import type { ExtractionResult } from './types'; import type { ExtractionResult } from './types';
export const githubRefMatchRegex = export const githubRefMatchRegex = regEx(
/github\.com([/:])(?<project>[^/]+\/[a-z0-9-_.]+).*\?ref=(?<tag>.*)$/i; /github\.com([/:])(?<project>[^/]+\/[a-z0-9-_.]+).*\?ref=(?<tag>.*)$/i
export const gitTagsRefMatchRegex = );
/(?:git::)?(?<url>(?:http|https|ssh):\/\/(?:.*@)?(?<path>.*.*\/(?<project>.*\/.*)))\?ref=(?<tag>.*)$/; export const gitTagsRefMatchRegex = regEx(
const hostnameMatchRegex = /^(?<hostname>([\w|\d]+\.)+[\w|\d]+)/; /(?:git::)?(?<url>(?:http|https|ssh):\/\/(?:.*@)?(?<path>.*.*\/(?<project>.*\/.*)))\?ref=(?<tag>.*)$/
);
const hostnameMatchRegex = regEx(/^(?<hostname>([\w|\d]+\.)+[\w|\d]+)/);
export function extractTerraformModule( export function extractTerraformModule(
startingLine: number, startingLine: number,
@ -32,7 +35,7 @@ export function analyseTerraformModule(dep: PackageDependency): void {
const gitTagsRefMatch = gitTagsRefMatchRegex.exec(dep.managerData.source); const gitTagsRefMatch = gitTagsRefMatchRegex.exec(dep.managerData.source);
/* eslint-disable no-param-reassign */ /* eslint-disable no-param-reassign */
if (githubRefMatch) { if (githubRefMatch) {
dep.lookupName = githubRefMatch.groups.project.replace(/\.git$/, ''); dep.lookupName = githubRefMatch.groups.project.replace(regEx(/\.git$/), '');
dep.depType = 'module'; dep.depType = 'module';
dep.depName = 'github.com/' + dep.lookupName; dep.depName = 'github.com/' + dep.lookupName;
dep.currentValue = githubRefMatch.groups.tag; dep.currentValue = githubRefMatch.groups.tag;

View file

@ -2,6 +2,7 @@ import is from '@sindresorhus/is';
import { TerraformProviderDatasource } from '../../datasource/terraform-provider'; import { TerraformProviderDatasource } from '../../datasource/terraform-provider';
import { logger } from '../../logger'; import { logger } from '../../logger';
import { SkipReason } from '../../types'; import { SkipReason } from '../../types';
import { regEx } from '../../util/regex';
import type { PackageDependency } from '../types'; import type { PackageDependency } from '../types';
import { TerraformDependencyTypes } from './common'; import { TerraformDependencyTypes } from './common';
import type { ProviderLock } from './lockfile/types'; import type { ProviderLock } from './lockfile/types';
@ -12,8 +13,9 @@ import {
massageProviderLookupName, massageProviderLookupName,
} from './util'; } from './util';
export const sourceExtractionRegex = export const sourceExtractionRegex = regEx(
/^(?:(?<hostname>(?:[a-zA-Z0-9]+\.+)+[a-zA-Z0-9]+)\/)?(?:(?<namespace>[^/]+)\/)?(?<type>[^/]+)/; /^(?:(?<hostname>(?:[a-zA-Z0-9]+\.+)+[a-zA-Z0-9]+)\/)?(?:(?<namespace>[^/]+)\/)?(?<type>[^/]+)/
);
export function extractTerraformProvider( export function extractTerraformProvider(
startingLine: number, startingLine: number,
@ -36,11 +38,12 @@ export function extractTerraformProvider(
} }
const line = lines[lineNumber]; const line = lines[lineNumber];
// istanbul ignore next // istanbul ignore next
if (is.string(line)) { if (is.string(line)) {
// `{` will be counted wit +1 and `}` with -1. Therefore if we reach braceCounter == 0. We have found the end of the terraform block // `{` will be counted wit +1 and `}` with -1. Therefore if we reach braceCounter == 0. We have found the end of the terraform block
const openBrackets = (line.match(/\{/g) || []).length; const openBrackets = (line.match(/\{/g) || []).length; // TODO #12071 #12070
const closedBrackets = (line.match(/\}/g) || []).length; const closedBrackets = (line.match(/\}/g) || []).length; // TODO #12071 #12070
braceCounter = braceCounter + openBrackets - closedBrackets; braceCounter = braceCounter + openBrackets - closedBrackets;
// only update fields inside the root block // only update fields inside the root block

View file

@ -1,3 +1,4 @@
import { regEx } from '../../util/regex';
import type { PackageDependency } from '../types'; import type { PackageDependency } from '../types';
import { TerraformDependencyTypes } from './common'; import { TerraformDependencyTypes } from './common';
import type { ProviderLock } from './lockfile/types'; import type { ProviderLock } from './lockfile/types';
@ -5,7 +6,7 @@ import { analyzeTerraformProvider } from './providers';
import type { ExtractionResult } from './types'; import type { ExtractionResult } from './types';
import { keyValueExtractionRegex } from './util'; import { keyValueExtractionRegex } from './util';
export const providerBlockExtractionRegex = /^\s*(?<key>[^\s]+)\s+=\s+{/; export const providerBlockExtractionRegex = regEx(/^\s*(?<key>[^\s]+)\s+=\s+{/);
function extractBlock( function extractBlock(
lineNum: number, lineNum: number,

View file

@ -20,8 +20,8 @@ export function extractTerraformRequiredVersion(
const line = lines[lineNumber]; const line = lines[lineNumber];
// `{` will be counted wit +1 and `}` with -1. Therefore if we reach braceCounter == 0. We have found the end of the terraform block // `{` will be counted wit +1 and `}` with -1. Therefore if we reach braceCounter == 0. We have found the end of the terraform block
const openBrackets = (line.match(/\{/g) || []).length; const openBrackets = (line.match(/\{/g) || []).length; // TODO #12070
const closedBrackets = (line.match(/\}/g) || []).length; const closedBrackets = (line.match(/\}/g) || []).length; // TODO #12070
braceCounter = braceCounter + openBrackets - closedBrackets; braceCounter = braceCounter + openBrackets - closedBrackets;
const kvMatch = keyValueExtractionRegex.exec(line); const kvMatch = keyValueExtractionRegex.exec(line);

View file

@ -1,12 +1,15 @@
import { TerraformProviderDatasource } from '../../datasource/terraform-provider'; import { TerraformProviderDatasource } from '../../datasource/terraform-provider';
import { regEx } from '../../util/regex';
import type { PackageDependency } from '../types'; import type { PackageDependency } from '../types';
import { TerraformDependencyTypes } from './common'; import { TerraformDependencyTypes } from './common';
import type { ProviderLock } from './lockfile/types'; import type { ProviderLock } from './lockfile/types';
export const keyValueExtractionRegex = export const keyValueExtractionRegex = regEx(
/^\s*(?<key>[^\s]+)\s+=\s+"(?<value>[^"]+)"\s*$/; /^\s*(?<key>[^\s]+)\s+=\s+"(?<value>[^"]+)"\s*$/
export const resourceTypeExtractionRegex = );
/^\s*resource\s+"(?<type>[^\s]+)"\s+"(?<name>[^"]+)"\s*{/; export const resourceTypeExtractionRegex = regEx(
/^\s*resource\s+"(?<type>[^\s]+)"\s+"(?<name>[^"]+)"\s*{/
);
export function getTerraformDependencyType( export function getTerraformDependencyType(
value: string value: string
@ -40,7 +43,7 @@ export function checkFileContainsDependency(
return checkList.some((check) => content.includes(check)); return checkList.some((check) => content.includes(check));
} }
const pathStringRegex = /(.|..)?(\/[^/])+/; const pathStringRegex = regEx(/(.|..)?(\/[^/])+/);
export function checkIfStringIsPath(path: string): boolean { export function checkIfStringIsPath(path: string): boolean {
const match = pathStringRegex.exec(path); const match = pathStringRegex.exec(path);
return !!match; return !!match;

View file

@ -1,4 +1,5 @@
import { logger } from '../../logger'; import { logger } from '../../logger';
import { regEx } from '../../util/regex';
import type { PackageDependency, PackageFile } from '../types'; import type { PackageDependency, PackageFile } from '../types';
import { TerragruntDependencyTypes } from './common'; import { TerragruntDependencyTypes } from './common';
import { analyseTerragruntModule, extractTerragruntModule } from './modules'; import { analyseTerragruntModule, extractTerragruntModule } from './modules';
@ -8,7 +9,7 @@ import {
getTerragruntDependencyType, getTerragruntDependencyType,
} from './util'; } from './util';
const dependencyBlockExtractionRegex = /^\s*(?<type>[a-z_]+)\s+{\s*$/; const dependencyBlockExtractionRegex = regEx(/^\s*(?<type>[a-z_]+)\s+{\s*$/);
const contentCheckList = ['terraform {']; const contentCheckList = ['terraform {'];
export function extractPackageFile(content: string): PackageFile | null { export function extractPackageFile(content: string): PackageFile | null {

View file

@ -3,16 +3,19 @@ import * as datasourceGithubTags from '../../datasource/github-tags';
import { TerraformModuleDatasource } from '../../datasource/terraform-module'; import { TerraformModuleDatasource } from '../../datasource/terraform-module';
import { logger } from '../../logger'; import { logger } from '../../logger';
import { SkipReason } from '../../types'; import { SkipReason } from '../../types';
import { regEx } from '../../util/regex';
import type { PackageDependency } from '../types'; import type { PackageDependency } from '../types';
import { TerragruntDependencyTypes } from './common'; import { TerragruntDependencyTypes } from './common';
import { extractTerragruntProvider } from './providers'; import { extractTerragruntProvider } from './providers';
import type { ExtractionResult } from './types'; import type { ExtractionResult } from './types';
export const githubRefMatchRegex = export const githubRefMatchRegex = regEx(
/github\.com([/:])(?<project>[^/]+\/[a-z0-9-_.]+).*\?ref=(?<tag>.*)$/i; /github\.com([/:])(?<project>[^/]+\/[a-z0-9-_.]+).*\?ref=(?<tag>.*)$/i
export const gitTagsRefMatchRegex = );
/(?:git::)?(?<url>(?:http|https|ssh):\/\/(?:.*@)?(?<path>.*.*\/(?<project>.*\/.*)))\?ref=(?<tag>.*)$/; export const gitTagsRefMatchRegex = regEx(
const hostnameMatchRegex = /^(?<hostname>([\w|\d]+\.)+[\w|\d]+)/; /(?:git::)?(?<url>(?:http|https|ssh):\/\/(?:.*@)?(?<path>.*.*\/(?<project>.*\/.*)))\?ref=(?<tag>.*)$/
);
const hostnameMatchRegex = regEx(/^(?<hostname>([\w|\d]+\.)+[\w|\d]+)/);
export function extractTerragruntModule( export function extractTerragruntModule(
startingLine: number, startingLine: number,
@ -34,7 +37,7 @@ export function analyseTerragruntModule(dep: PackageDependency): void {
/* eslint-disable no-param-reassign */ /* eslint-disable no-param-reassign */
if (githubRefMatch) { if (githubRefMatch) {
dep.depType = 'github'; dep.depType = 'github';
dep.lookupName = githubRefMatch.groups.project.replace(/\.git$/, ''); dep.lookupName = githubRefMatch.groups.project.replace(regEx(/\.git$/), '');
dep.depName = 'github.com/' + dep.lookupName; dep.depName = 'github.com/' + dep.lookupName;
dep.currentValue = githubRefMatch.groups.tag; dep.currentValue = githubRefMatch.groups.tag;
dep.datasource = datasourceGithubTags.id; dep.datasource = datasourceGithubTags.id;

View file

@ -1,10 +1,12 @@
import { regEx } from '../../util/regex';
import type { PackageDependency } from '../types'; import type { PackageDependency } from '../types';
import { TerragruntDependencyTypes } from './common'; import { TerragruntDependencyTypes } from './common';
import type { ExtractionResult } from './types'; import type { ExtractionResult } from './types';
import { keyValueExtractionRegex } from './util'; import { keyValueExtractionRegex } from './util';
export const sourceExtractionRegex = export const sourceExtractionRegex = regEx(
/^(?:(?<hostname>(?:[a-zA-Z0-9]+\.+)+[a-zA-Z0-9]+)\/)?(?:(?<namespace>[^/]+)\/)?(?<type>[^/]+)/; /^(?:(?<hostname>(?:[a-zA-Z0-9]+\.+)+[a-zA-Z0-9]+)\/)?(?:(?<namespace>[^/]+)\/)?(?<type>[^/]+)/
);
function extractBracesContent(content): number { function extractBracesContent(content): number {
const stack = []; const stack = [];

View file

@ -1,6 +1,9 @@
import { regEx } from '../../util/regex';
import { TerragruntDependencyTypes } from './common'; import { TerragruntDependencyTypes } from './common';
export const keyValueExtractionRegex = /^\s*source\s+=\s+"(?<value>[^"]+)"\s*$/; export const keyValueExtractionRegex = regEx(
/^\s*source\s+=\s+"(?<value>[^"]+)"\s*$/
);
export function getTerragruntDependencyType( export function getTerragruntDependencyType(
value: string value: string

View file

@ -14,6 +14,7 @@ import { logger } from '../../logger';
import { BranchStatus, PrState, VulnerabilityAlert } from '../../types'; import { BranchStatus, PrState, VulnerabilityAlert } from '../../types';
import * as git from '../../util/git'; import * as git from '../../util/git';
import * as hostRules from '../../util/host-rules'; import * as hostRules from '../../util/host-rules';
import { regEx } from '../../util/regex';
import { sanitize } from '../../util/sanitize'; import { sanitize } from '../../util/sanitize';
import { ensureTrailingSlash } from '../../util/url'; import { ensureTrailingSlash } from '../../util/url';
import type { import type {
@ -678,7 +679,7 @@ export function massageMarkdown(input: string): string {
'you tick the rebase/retry checkbox', 'you tick the rebase/retry checkbox',
'rename PR to start with "rebase!"' 'rename PR to start with "rebase!"'
) )
.replace(new RegExp(`\n---\n\n.*?<!-- rebase-check -->.*?\n`), ''); .replace(regEx(`\n---\n\n.*?<!-- rebase-check -->.*?\n`), '');
} }
/* istanbul ignore next */ /* istanbul ignore next */

View file

@ -20,6 +20,7 @@ import {
BitbucketServerHttp, BitbucketServerHttp,
setBaseUrl, setBaseUrl,
} from '../../util/http/bitbucket-server'; } from '../../util/http/bitbucket-server';
import { regEx } from '../../util/regex';
import { sanitize } from '../../util/sanitize'; import { sanitize } from '../../util/sanitize';
import { ensureTrailingSlash, getQueryString } from '../../util/url'; import { ensureTrailingSlash, getQueryString } from '../../util/url';
import type { import type {
@ -784,7 +785,7 @@ export async function ensureCommentRemoval({
// Pull Request // Pull Request
const escapeHash = (input: string): string => const escapeHash = (input: string): string =>
input ? input.replace(/#/g, '%23') : input; input ? input.replace(regEx(/#/g), '%23') : input;
export async function createPr({ export async function createPr({
sourceBranch, sourceBranch,
@ -991,10 +992,10 @@ export function massageMarkdown(input: string): string {
'you tick the rebase/retry checkbox', 'you tick the rebase/retry checkbox',
'rename PR to start with "rebase!"' 'rename PR to start with "rebase!"'
) )
.replace(/<\/?summary>/g, '**') .replace(regEx(/<\/?summary>/g), '**')
.replace(/<\/?details>/g, '') .replace(regEx(/<\/?details>/g), '')
.replace(new RegExp(`\n---\n\n.*?<!-- rebase-check -->.*?(\n|$)`), '') .replace(regEx(`\n---\n\n.*?<!-- rebase-check -->.*?(\n|$)`), '')
.replace(new RegExp('<!--.*?-->', 'g'), ''); .replace(regEx('<!--.*?-->', 'g'), '');
} }
export function getVulnerabilityAlerts(): Promise<VulnerabilityAlert[]> { export function getVulnerabilityAlerts(): Promise<VulnerabilityAlert[]> {

View file

@ -8,6 +8,7 @@ import { BranchStatus, PrState, VulnerabilityAlert } from '../../types';
import * as git from '../../util/git'; import * as git from '../../util/git';
import * as hostRules from '../../util/host-rules'; import * as hostRules from '../../util/host-rules';
import { BitbucketHttp, setBaseUrl } from '../../util/http/bitbucket'; import { BitbucketHttp, setBaseUrl } from '../../util/http/bitbucket';
import { regEx } from '../../util/regex';
import { sanitize } from '../../util/sanitize'; import { sanitize } from '../../util/sanitize';
import type { import type {
BranchStatusConfig, BranchStatusConfig,
@ -173,7 +174,7 @@ export async function initRepo({
// Converts API hostnames to their respective HTTP git hosts: // Converts API hostnames to their respective HTTP git hosts:
// `api.bitbucket.org` to `bitbucket.org` // `api.bitbucket.org` to `bitbucket.org`
// `api-staging.<host>` to `staging.<host>` // `api-staging.<host>` to `staging.<host>`
const hostnameWithoutApiPrefix = /api[.|-](.+)/.exec(hostname)[1]; const hostnameWithoutApiPrefix = regEx(/api[.|-](.+)/).exec(hostname)[1];
const url = git.getUrl({ const url = git.getUrl({
protocol: 'https', protocol: 'https',
@ -286,7 +287,7 @@ export async function getPr(prNo: number): Promise<Pr | null> {
} }
const escapeHash = (input: string): string => const escapeHash = (input: string): string =>
input ? input.replace(/#/g, '%23') : input; input ? input.replace(regEx(/#/g), '%23') : input;
interface BranchResponse { interface BranchResponse {
target: { target: {
@ -462,10 +463,10 @@ export function massageMarkdown(input: string): string {
'you tick the rebase/retry checkbox', 'you tick the rebase/retry checkbox',
'rename PR to start with "rebase!"' 'rename PR to start with "rebase!"'
) )
.replace(/<\/?summary>/g, '**') .replace(regEx(/<\/?summary>/g), '**')
.replace(/<\/?details>/g, '') .replace(regEx(/<\/?details>/g), '')
.replace(new RegExp(`\n---\n\n.*?<!-- rebase-check -->.*?\n`), '') .replace(regEx(`\n---\n\n.*?<!-- rebase-check -->.*?\n`), '')
.replace(/\]\(\.\.\/pull\//g, '](../../pull-requests/'); .replace(regEx(/\]\(\.\.\/pull\//g), '](../../pull-requests/');
} }
export async function ensureIssue({ export async function ensureIssue({

View file

@ -1,3 +1,5 @@
import { regEx } from '../../util/regex';
export function smartLinks(body: string): string { export function smartLinks(body: string): string {
return body?.replace(/\]\(\.\.\/pull\//g, '](pulls/'); return body?.replace(regEx(/\]\(\.\.\/pull\//g), '](pulls/');
} }

View file

@ -23,6 +23,7 @@ import { getCache } from '../../util/cache/repository';
import * as git from '../../util/git'; import * as git from '../../util/git';
import * as hostRules from '../../util/host-rules'; import * as hostRules from '../../util/host-rules';
import * as githubHttp from '../../util/http/github'; import * as githubHttp from '../../util/http/github';
import { regEx } from '../../util/regex';
import { sanitize } from '../../util/sanitize'; import { sanitize } from '../../util/sanitize';
import { ensureTrailingSlash } from '../../util/url'; import { ensureTrailingSlash } from '../../util/url';
import type { import type {
@ -78,7 +79,7 @@ const defaults = {
}; };
const escapeHash = (input: string): string => const escapeHash = (input: string): string =>
input ? input.replace(/#/g, '%23') : input; input ? input.replace(regEx(/#/g), '%23') : input;
export async function initPlatform({ export async function initPlatform({
endpoint, endpoint,
@ -768,7 +769,7 @@ export async function getBranchPr(branchName: string): Promise<Pr | null> {
return null; return null;
} }
try { try {
const title = autoclosedPr.title.replace(/ - autoclosed$/, ''); const title = autoclosedPr.title.replace(regEx(/ - autoclosed$/), '');
await githubApi.patchJson(`repos/${config.repository}/pulls/${number}`, { await githubApi.patchJson(`repos/${config.repository}/pulls/${number}`, {
body: { body: {
state: 'open', state: 'open',
@ -1181,7 +1182,7 @@ export async function addReviewers(
const userReviewers = reviewers.filter((e) => !e.startsWith('team:')); const userReviewers = reviewers.filter((e) => !e.startsWith('team:'));
const teamReviewers = reviewers const teamReviewers = reviewers
.filter((e) => e.startsWith('team:')) .filter((e) => e.startsWith('team:'))
.map((e) => e.replace(/^team:/, '')); .map((e) => e.replace(regEx(/^team:/), '')); // TODO #12071
try { try {
await githubApi.postJson( await githubApi.postJson(
`repos/${ `repos/${
@ -1623,9 +1624,12 @@ export function massageMarkdown(input: string): string {
} }
const massagedInput = massageMarkdownLinks(input) const massagedInput = massageMarkdownLinks(input)
// to be safe, replace all github.com links with renovatebot redirector // to be safe, replace all github.com links with renovatebot redirector
.replace(/href="https?:\/\/github.com\//g, 'href="https://togithub.com/') .replace(
.replace(/]\(https:\/\/github\.com\//g, '](https://togithub.com/') regEx(/href="https?:\/\/github.com\//g),
.replace(/]: https:\/\/github\.com\//g, ']: https://togithub.com/'); 'href="https://togithub.com/'
)
.replace(regEx(/]\(https:\/\/github\.com\//g), '](https://togithub.com/')
.replace(regEx(/]: https:\/\/github\.com\//g), ']: https://togithub.com/');
return smartTruncate(massagedInput, 60000); return smartTruncate(massagedInput, 60000);
} }

View file

@ -3,6 +3,7 @@ import remark from 'remark';
import type { Plugin, Transformer } from 'unified'; import type { Plugin, Transformer } from 'unified';
import { logger } from '../../logger'; import { logger } from '../../logger';
import { hasKey } from '../../util/object'; import { hasKey } from '../../util/object';
import { regEx } from '../../util/regex';
interface UrlMatch { interface UrlMatch {
start: number; start: number;
@ -11,10 +12,10 @@ interface UrlMatch {
} }
const urlRegex = const urlRegex =
/(?:https?:)?(?:\/\/)?(?:www\.)?(?<!api\.)(?:to)?github\.com\/[-_a-z0-9]+\/[-_a-z0-9]+\/(?:discussions|issues|pull)\/[0-9]+(?:#[-_a-z0-9]+)?/i; /(?:https?:)?(?:\/\/)?(?:www\.)?(?<!api\.)(?:to)?github\.com\/[-_a-z0-9]+\/[-_a-z0-9]+\/(?:discussions|issues|pull)\/[0-9]+(?:#[-_a-z0-9]+)?/i; // TODO #12070
function massageLink(input: string): string { function massageLink(input: string): string {
return input.replace(/(?:to)?github\.com/i, 'togithub.com'); return input.replace(regEx(/(?:to)?github\.com/i), 'togithub.com'); // TODO #12071
} }
function collectLinkPosition(input: string, matches: UrlMatch[]): Plugin { function collectLinkPosition(input: string, matches: UrlMatch[]): Plugin {

View file

@ -22,6 +22,7 @@ import * as git from '../../util/git';
import * as hostRules from '../../util/host-rules'; import * as hostRules from '../../util/host-rules';
import { HttpResponse } from '../../util/http'; import { HttpResponse } from '../../util/http';
import { setBaseUrl } from '../../util/http/gitlab'; import { setBaseUrl } from '../../util/http/gitlab';
import { regEx } from '../../util/regex';
import { sanitize } from '../../util/sanitize'; import { sanitize } from '../../util/sanitize';
import { ensureTrailingSlash, getQueryString, parseUrl } from '../../util/url'; import { ensureTrailingSlash, getQueryString, parseUrl } from '../../util/url';
import type { import type {
@ -150,7 +151,7 @@ export async function getRepos(): Promise<string[]> {
} }
function urlEscape(str: string): string { function urlEscape(str: string): string {
return str ? str.replace(/\//g, '%2F') : str; return str ? str.replace(regEx(/\//g), '%2F') : str;
} }
export async function getRawFile( export async function getRawFile(
@ -669,9 +670,9 @@ export async function mergePr({ id }: MergePRConfig): Promise<boolean> {
export function massageMarkdown(input: string): string { export function massageMarkdown(input: string): string {
let desc = input let desc = input
.replace(/Pull Request/g, 'Merge Request') .replace(regEx(/Pull Request/g), 'Merge Request')
.replace(/PR/g, 'MR') .replace(regEx(/PR/g), 'MR')
.replace(/\]\(\.\.\/pull\//g, '](!'); .replace(regEx(/\]\(\.\.\/pull\//g), '](!');
if (lt(defaults.version, '13.4.0')) { if (lt(defaults.version, '13.4.0')) {
logger.debug( logger.debug(
@ -1073,7 +1074,9 @@ export async function ensureComment({
}: EnsureCommentConfig): Promise<boolean> { }: EnsureCommentConfig): Promise<boolean> {
const sanitizedContent = sanitize(content); const sanitizedContent = sanitize(content);
const massagedTopic = topic const massagedTopic = topic
? topic.replace(/Pull Request/g, 'Merge Request').replace(/PR/g, 'MR') ? topic
.replace(regEx(/Pull Request/g), 'Merge Request')
.replace(regEx(/PR/g), 'MR')
: topic; : topic;
const comments = await getComments(number); const comments = await getComments(number);
let body: string; let body: string;
@ -1082,7 +1085,9 @@ export async function ensureComment({
if (topic) { if (topic) {
logger.debug(`Ensuring comment "${massagedTopic}" in #${number}`); logger.debug(`Ensuring comment "${massagedTopic}" in #${number}`);
body = `### ${topic}\n\n${sanitizedContent}`; body = `### ${topic}\n\n${sanitizedContent}`;
body = body.replace(/Pull Request/g, 'Merge Request').replace(/PR/g, 'MR'); body = body
.replace(regEx(/Pull Request/g), 'Merge Request')
.replace(regEx(/PR/g), 'MR');
comments.forEach((comment: { body: string; id: number }) => { comments.forEach((comment: { body: string; id: number }) => {
if (comment.body.startsWith(`### ${massagedTopic}\n\n`)) { if (comment.body.startsWith(`### ${massagedTopic}\n\n`)) {
commentId = comment.id; commentId = comment.id;

View file

@ -1,10 +1,12 @@
import { regEx } from '../../util/regex';
export function readOnlyIssueBody(body: string): string { export function readOnlyIssueBody(body: string): string {
return body return body
.replace(' only once you click their checkbox below', '') .replace(' only once you click their checkbox below', '')
.replace(' unless you click a checkbox below', '') .replace(' unless you click a checkbox below', '')
.replace(' To discard all commits and start over, click on a checkbox.', '') .replace(' To discard all commits and start over, click on a checkbox.', '')
.replace(/ Click (?:on |)a checkbox.*\./g, '') .replace(regEx(/ Click (?:on |)a checkbox.*\./g), '')
.replace(/\[ ] <!-- \w*-branch.*-->/g, ''); .replace(regEx(/\[ ] <!-- \w*-branch.*-->/g), '');
} }
export default readOnlyIssueBody; export default readOnlyIssueBody;