From de05ef057ad459e37865ac5fb9dfd5578913ece9 Mon Sep 17 00:00:00 2001 From: Sergei Zharinov <zharinov@users.noreply.github.com> Date: Tue, 6 Feb 2024 18:51:41 -0300 Subject: [PATCH] refactor: Move irrelevant functions from the regex helper (#27100) --- lib/config/validation.ts | 8 ++- lib/modules/datasource/docker/index.ts | 2 +- lib/modules/platform/bitbucket/index.ts | 8 ++- lib/util/http/host-rules.ts | 2 +- lib/util/package-rules/base-branches.ts | 2 +- lib/util/package-rules/current-value.ts | 2 +- lib/util/package-rules/current-version.ts | 2 +- lib/util/package-rules/repositories.ts | 2 +- lib/util/regex.spec.ts | 24 +------ lib/util/regex.ts | 39 ----------- lib/util/string-match.spec.ts | 25 +++++++ lib/util/string-match.ts | 70 +++++++++++++++++++ lib/util/string.spec.ts | 10 +-- lib/util/string.ts | 35 ---------- lib/workers/global/autodiscover.ts | 2 +- lib/workers/repository/process/index.ts | 2 +- .../repository/process/lookup/filter.ts | 2 +- 17 files changed, 118 insertions(+), 119 deletions(-) create mode 100644 lib/util/string-match.spec.ts create mode 100644 lib/util/string-match.ts diff --git a/lib/config/validation.ts b/lib/config/validation.ts index f302fb005c..f1d0a36ca8 100644 --- a/lib/config/validation.ts +++ b/lib/config/validation.ts @@ -8,8 +8,12 @@ import type { } from '../modules/manager/custom/regex/types'; import type { CustomManager } from '../modules/manager/custom/types'; import type { HostRule } from '../types/host-rules'; -import { configRegexPredicate, isConfigRegex, regEx } from '../util/regex'; -import { anyMatchRegexOrMinimatch } from '../util/string'; +import { regEx } from '../util/regex'; +import { + anyMatchRegexOrMinimatch, + configRegexPredicate, + isConfigRegex, +} from '../util/string-match'; import * as template from '../util/template'; import { hasValidSchedule, diff --git a/lib/modules/datasource/docker/index.ts b/lib/modules/datasource/docker/index.ts index ea9e6dd897..0653cc22f6 100644 --- a/lib/modules/datasource/docker/index.ts +++ b/lib/modules/datasource/docker/index.ts @@ -8,7 +8,7 @@ import type { HttpResponse } from '../../../util/http/types'; import { hasKey } from '../../../util/object'; import { regEx } from '../../../util/regex'; import { type AsyncResult, Result } from '../../../util/result'; -import { isDockerDigest } from '../../../util/string'; +import { isDockerDigest } from '../../../util/string-match'; import { ensurePathPrefix, joinUrlParts, diff --git a/lib/modules/platform/bitbucket/index.ts b/lib/modules/platform/bitbucket/index.ts index 660e9dd732..dc6301ae89 100644 --- a/lib/modules/platform/bitbucket/index.ts +++ b/lib/modules/platform/bitbucket/index.ts @@ -10,7 +10,7 @@ import { BitbucketHttp, setBaseUrl } from '../../../util/http/bitbucket'; import type { HttpOptions } from '../../../util/http/types'; import { regEx } from '../../../util/regex'; import { sanitize } from '../../../util/sanitize'; -import { isUUID } from '../../../util/string'; +import { UUIDRegex } from '../../../util/string-match'; import type { BranchStatusConfig, CreatePRConfig, @@ -701,7 +701,11 @@ export async function addReviewers( const body = { title, reviewers: reviewers.map((username: string) => { - const key = isUUID(username) ? 'uuid' : 'username'; + const isUUID = + username.startsWith('{') && + username.endsWith('}') && + UUIDRegex.test(username.slice(1, -1)); + const key = isUUID ? 'uuid' : 'username'; return { [key]: username, }; diff --git a/lib/util/http/host-rules.ts b/lib/util/http/host-rules.ts index 2572891f7c..009d18450e 100644 --- a/lib/util/http/host-rules.ts +++ b/lib/util/http/host-rules.ts @@ -10,7 +10,7 @@ import { logger } from '../../logger'; import { hasProxy } from '../../proxy'; import type { HostRule } from '../../types'; import * as hostRules from '../host-rules'; -import { anyMatchRegexOrMinimatch } from '../string'; +import { anyMatchRegexOrMinimatch } from '../string-match'; import { parseUrl } from '../url'; import { dnsLookup } from './dns'; import { keepAliveAgents } from './keep-alive'; diff --git a/lib/util/package-rules/base-branches.ts b/lib/util/package-rules/base-branches.ts index dd6241ad2f..c95e66cbf7 100644 --- a/lib/util/package-rules/base-branches.ts +++ b/lib/util/package-rules/base-branches.ts @@ -1,6 +1,6 @@ import is from '@sindresorhus/is'; import type { PackageRule, PackageRuleInputConfig } from '../../config/types'; -import { configRegexPredicate } from '../regex'; +import { configRegexPredicate } from '../string-match'; import { Matcher } from './base'; export class BaseBranchesMatcher extends Matcher { diff --git a/lib/util/package-rules/current-value.ts b/lib/util/package-rules/current-value.ts index 5f3f24a0d3..449274f229 100644 --- a/lib/util/package-rules/current-value.ts +++ b/lib/util/package-rules/current-value.ts @@ -1,7 +1,7 @@ import is from '@sindresorhus/is'; import type { PackageRule, PackageRuleInputConfig } from '../../config/types'; import { logger } from '../../logger'; -import { configRegexPredicate } from '../regex'; +import { configRegexPredicate } from '../string-match'; import { Matcher } from './base'; export class CurrentValueMatcher extends Matcher { diff --git a/lib/util/package-rules/current-version.ts b/lib/util/package-rules/current-version.ts index b4f89db904..82ea5db9bf 100644 --- a/lib/util/package-rules/current-version.ts +++ b/lib/util/package-rules/current-version.ts @@ -2,7 +2,7 @@ import is from '@sindresorhus/is'; import type { PackageRule, PackageRuleInputConfig } from '../../config/types'; import { logger } from '../../logger'; import * as allVersioning from '../../modules/versioning'; -import { configRegexPredicate } from '../regex'; +import { configRegexPredicate } from '../string-match'; import { Matcher } from './base'; export class CurrentVersionMatcher extends Matcher { diff --git a/lib/util/package-rules/repositories.ts b/lib/util/package-rules/repositories.ts index ac99ef4d0f..3b7158e8cc 100644 --- a/lib/util/package-rules/repositories.ts +++ b/lib/util/package-rules/repositories.ts @@ -1,6 +1,6 @@ import is from '@sindresorhus/is'; import type { PackageRule, PackageRuleInputConfig } from '../../config/types'; -import { anyMatchRegexOrMinimatch } from '../string'; +import { anyMatchRegexOrMinimatch } from '../string-match'; import { Matcher } from './base'; export class RepositoriesMatcher extends Matcher { diff --git a/lib/util/regex.spec.ts b/lib/util/regex.spec.ts index 923e5769fd..4252ed17b0 100644 --- a/lib/util/regex.spec.ts +++ b/lib/util/regex.spec.ts @@ -1,6 +1,6 @@ import RE2 from 're2'; import { CONFIG_VALIDATION } from '../constants/error-messages'; -import { configRegexPredicate, regEx } from './regex'; +import { regEx } from './regex'; describe('util/regex', () => { beforeEach(() => { @@ -37,26 +37,4 @@ describe('util/regex', () => { const regex = await import('./regex'); expect(regex.regEx('foo')).toBeInstanceOf(RegExp); }); - - describe('configRegexPredicate', () => { - it('allows valid regex pattern', () => { - expect(configRegexPredicate('/hello/')).not.toBeNull(); - }); - - it('invalidates invalid regex pattern', () => { - expect(configRegexPredicate('/^test\\d+$/m')).toBeNull(); - }); - - it('allows the i flag in regex pattern', () => { - expect(configRegexPredicate('/^test\\d+$/i')).not.toBeNull(); - }); - - it('allows negative regex pattern', () => { - expect(configRegexPredicate('!/^test\\d+$/i')).not.toBeNull(); - }); - - it('does not allow non-regex input', () => { - expect(configRegexPredicate('hello')).toBeNull(); - }); - }); }); diff --git a/lib/util/regex.ts b/lib/util/regex.ts index 719dfce054..947a312a80 100644 --- a/lib/util/regex.ts +++ b/lib/util/regex.ts @@ -72,42 +72,3 @@ export function escapeRegExp(input: string): string { } export const newlineRegex = regEx(/\r?\n/); - -const configValStart = regEx(/^!?\//); -const configValEnd = regEx(/\/i?$/); - -export function isConfigRegex(input: unknown): input is string { - return ( - is.string(input) && configValStart.test(input) && configValEnd.test(input) - ); -} - -function parseConfigRegex(input: string): RegExp | null { - try { - const regexString = input - .replace(configValStart, '') - .replace(configValEnd, ''); - return input.endsWith('i') ? regEx(regexString, 'i') : regEx(regexString); - } catch (err) { - // no-op - } - return null; -} - -type ConfigRegexPredicate = (s: string) => boolean; - -export function configRegexPredicate( - input: string, -): ConfigRegexPredicate | null { - if (isConfigRegex(input)) { - const configRegex = parseConfigRegex(input); - if (configRegex) { - const isPositive = !input.startsWith('!'); - return (x: string): boolean => { - const res = configRegex.test(x); - return isPositive ? res : !res; - }; - } - } - return null; -} diff --git a/lib/util/string-match.spec.ts b/lib/util/string-match.spec.ts new file mode 100644 index 0000000000..02ab8c4598 --- /dev/null +++ b/lib/util/string-match.spec.ts @@ -0,0 +1,25 @@ +import { configRegexPredicate } from './string-match'; + +describe('util/string-match', () => { + describe('configRegexPredicate', () => { + it('allows valid regex pattern', () => { + expect(configRegexPredicate('/hello/')).not.toBeNull(); + }); + + it('invalidates invalid regex pattern', () => { + expect(configRegexPredicate('/^test\\d+$/m')).toBeNull(); + }); + + it('allows the i flag in regex pattern', () => { + expect(configRegexPredicate('/^test\\d+$/i')).not.toBeNull(); + }); + + it('allows negative regex pattern', () => { + expect(configRegexPredicate('!/^test\\d+$/i')).not.toBeNull(); + }); + + it('does not allow non-regex input', () => { + expect(configRegexPredicate('hello')).toBeNull(); + }); + }); +}); diff --git a/lib/util/string-match.ts b/lib/util/string-match.ts new file mode 100644 index 0000000000..42c7b234fa --- /dev/null +++ b/lib/util/string-match.ts @@ -0,0 +1,70 @@ +import is from '@sindresorhus/is'; +import { minimatch } from './minimatch'; +import { regEx } from './regex'; + +export function isDockerDigest(input: string): boolean { + return /^sha256:[a-f0-9]{64}$/i.test(input); +} + +export function matchRegexOrMinimatch(input: string, pattern: string): boolean { + if (pattern.length > 2 && pattern.startsWith('/') && pattern.endsWith('/')) { + try { + const regex = regEx(pattern.slice(1, -1)); + return regex.test(input); + } catch (err) { + return false; + } + } + + return minimatch(pattern, { dot: true }).match(input); +} + +export function anyMatchRegexOrMinimatch( + input: string, + patterns: string[], +): boolean | null { + return patterns.some((pattern) => matchRegexOrMinimatch(input, pattern)); +} + +export const UUIDRegex = regEx( + /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i, +); + +const configValStart = regEx(/^!?\//); +const configValEnd = regEx(/\/i?$/); + +export function isConfigRegex(input: unknown): input is string { + return ( + is.string(input) && configValStart.test(input) && configValEnd.test(input) + ); +} + +function parseConfigRegex(input: string): RegExp | null { + try { + const regexString = input + .replace(configValStart, '') + .replace(configValEnd, ''); + return input.endsWith('i') ? regEx(regexString, 'i') : regEx(regexString); + } catch (err) { + // no-op + } + return null; +} + +type ConfigRegexPredicate = (s: string) => boolean; + +export function configRegexPredicate( + input: string, +): ConfigRegexPredicate | null { + if (isConfigRegex(input)) { + const configRegex = parseConfigRegex(input); + if (configRegex) { + const isPositive = !input.startsWith('!'); + return (x: string): boolean => { + const res = configRegex.test(x); + return isPositive ? res : !res; + }; + } + } + return null; +} diff --git a/lib/util/string.spec.ts b/lib/util/string.spec.ts index 3afa60e9f2..9df3c52ac2 100644 --- a/lib/util/string.spec.ts +++ b/lib/util/string.spec.ts @@ -1,4 +1,4 @@ -import { coerceString, isUUID, looseEquals, replaceAt } from './string'; +import { coerceString, looseEquals, replaceAt } from './string'; describe('util/string', () => { describe('replaceAt', () => { @@ -40,12 +40,4 @@ describe('util/string', () => { expect(coerceString(null)).toBe(''); expect(coerceString(null, 'foo')).toBe('foo'); }); - - describe('isUUID', () => { - it('proper checks valid and invalid UUID strings', () => { - expect(isUUID('{90b6646d-1724-4a64-9fd9-539515fe94e9}')).toBe(true); - expect(isUUID('{90B6646D-1724-4A64-9FD9-539515FE94E9}')).toBe(true); - expect(isUUID('not-a-uuid')).toBe(false); - }); - }); }); diff --git a/lib/util/string.ts b/lib/util/string.ts index 3944412038..4ad6797651 100644 --- a/lib/util/string.ts +++ b/lib/util/string.ts @@ -1,6 +1,3 @@ -import { minimatch } from './minimatch'; -import { regEx } from './regex'; - // Return true if the match string is found at index in content export function matchAt( content: string, @@ -56,10 +53,6 @@ export function looseEquals( return a.localeCompare(b, undefined, { sensitivity: 'base' }) === 0; } -export function isDockerDigest(input: string): boolean { - return /^sha256:[a-f0-9]{64}$/i.test(input); -} - export function titleCase(input: string): string { const words = input.toLowerCase().split(' '); @@ -97,31 +90,3 @@ export function coerceString( ): string { return val ?? def ?? ''; } - -export function matchRegexOrMinimatch(input: string, pattern: string): boolean { - if (pattern.length > 2 && pattern.startsWith('/') && pattern.endsWith('/')) { - try { - const regex = regEx(pattern.slice(1, -1)); - return regex.test(input); - } catch (err) { - return false; - } - } - - return minimatch(pattern, { dot: true }).match(input); -} - -export function anyMatchRegexOrMinimatch( - input: string, - patterns: string[], -): boolean | null { - return patterns.some((pattern) => matchRegexOrMinimatch(input, pattern)); -} - -const UUIDRegex = regEx( - /^\{[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\}$/i, -); - -export function isUUID(input: string): boolean { - return UUIDRegex.test(input); -} diff --git a/lib/workers/global/autodiscover.ts b/lib/workers/global/autodiscover.ts index f70f925f03..2e9f1216cd 100644 --- a/lib/workers/global/autodiscover.ts +++ b/lib/workers/global/autodiscover.ts @@ -3,7 +3,7 @@ import type { AllConfig } from '../../config/types'; import { logger } from '../../logger'; import { platform } from '../../modules/platform'; import { minimatchFilter } from '../../util/minimatch'; -import { configRegexPredicate, isConfigRegex } from '../../util/regex'; +import { configRegexPredicate, isConfigRegex } from '../../util/string-match'; // istanbul ignore next function repoName(value: string | { repository: string }): string { diff --git a/lib/workers/repository/process/index.ts b/lib/workers/repository/process/index.ts index cef8b546c1..22aac60464 100644 --- a/lib/workers/repository/process/index.ts +++ b/lib/workers/repository/process/index.ts @@ -11,8 +11,8 @@ import { scm } from '../../../modules/platform/scm'; import { getCache } from '../../../util/cache/repository'; import { clone } from '../../../util/clone'; import { getBranchList } from '../../../util/git'; -import { configRegexPredicate } from '../../../util/regex'; import { addSplit } from '../../../util/split'; +import { configRegexPredicate } from '../../../util/string-match'; import type { BranchConfig } from '../../types'; import { readDashboardBody } from '../dependency-dashboard'; import { ExtractResult, extract, lookup, update } from './extract-update'; diff --git a/lib/workers/repository/process/lookup/filter.ts b/lib/workers/repository/process/lookup/filter.ts index bdcc4371e9..3efcc43978 100644 --- a/lib/workers/repository/process/lookup/filter.ts +++ b/lib/workers/repository/process/lookup/filter.ts @@ -6,7 +6,7 @@ import type { VersioningApi } from '../../../../modules/versioning'; import * as npmVersioning from '../../../../modules/versioning/npm'; import * as pep440 from '../../../../modules/versioning/pep440'; import * as poetryVersioning from '../../../../modules/versioning/poetry'; -import { configRegexPredicate } from '../../../../util/regex'; +import { configRegexPredicate } from '../../../../util/string-match'; import type { FilterConfig } from './types'; export function filterVersions( -- GitLab