From b3390514a4dc080afc49ecdcfee5c7fe1245349e Mon Sep 17 00:00:00 2001 From: Jamie Magee <JamieMagee@users.noreply.github.com> Date: Sat, 23 Nov 2019 21:44:55 +0100 Subject: [PATCH] refactor(eslint): fix eslint warnings in manager (#4865) --- lib/manager/buildkite/extract.ts | 4 +- lib/manager/bundler/extract.ts | 4 +- lib/manager/cargo/artifacts.ts | 2 +- lib/manager/cargo/extract.ts | 94 ++++---- lib/manager/composer/extract.ts | 6 +- lib/manager/gradle-wrapper/update.ts | 38 ++-- lib/manager/gradle/build-gradle.ts | 222 +++++++++--------- lib/manager/gradle/gradle-updates-report.ts | 28 +-- lib/manager/gradle/index.ts | 149 ++++++------ lib/manager/helm-requirements/update.ts | 41 ++-- lib/manager/homebrew/extract.ts | 168 +++++++------- lib/manager/homebrew/update.ts | 238 ++++++++++---------- lib/manager/homebrew/util.ts | 12 +- lib/manager/index.ts | 6 +- lib/manager/leiningen/extract.ts | 9 +- lib/manager/maven/extract.ts | 4 +- lib/manager/mix/artifacts.ts | 2 +- lib/manager/npm/extract/index.ts | 58 ++--- lib/manager/npm/extract/locked-versions.ts | 4 +- lib/manager/npm/extract/monorepo.ts | 2 +- lib/manager/npm/post-update/index.ts | 9 +- lib/manager/npm/update.ts | 146 ++++++------ lib/manager/pipenv/extract.ts | 50 ++-- lib/manager/poetry/artifacts.ts | 2 +- lib/manager/poetry/extract.ts | 56 ++--- lib/manager/pub/update.ts | 14 +- lib/manager/sbt/extract.ts | 44 ++-- lib/manager/swift/extract.ts | 2 +- lib/manager/travis/package.ts | 4 +- 29 files changed, 723 insertions(+), 695 deletions(-) diff --git a/lib/manager/buildkite/extract.ts b/lib/manager/buildkite/extract.ts index 7fde4a27d4..9e5711f181 100644 --- a/lib/manager/buildkite/extract.ts +++ b/lib/manager/buildkite/extract.ts @@ -2,9 +2,7 @@ import { logger } from '../../logger'; import { isVersion } from '../../versioning/semver'; import { PackageFile, PackageDependency } from '../common'; -export { extractPackageFile }; - -function extractPackageFile(content: string): PackageFile | null { +export function extractPackageFile(content: string): PackageFile | null { const deps: PackageDependency[] = []; try { const lines = content.split('\n'); diff --git a/lib/manager/bundler/extract.ts b/lib/manager/bundler/extract.ts index 3deb6481f9..056981c31d 100644 --- a/lib/manager/bundler/extract.ts +++ b/lib/manager/bundler/extract.ts @@ -4,9 +4,7 @@ import { PackageFile, PackageDependency } from '../common'; import { platform } from '../../platform'; import { regEx } from '../../util/regex'; -export { extractPackageFile }; - -async function extractPackageFile( +export async function extractPackageFile( content: string, fileName?: string ): Promise<PackageFile | null> { diff --git a/lib/manager/cargo/artifacts.ts b/lib/manager/cargo/artifacts.ts index 125990df72..54ea4ab13a 100644 --- a/lib/manager/cargo/artifacts.ts +++ b/lib/manager/cargo/artifacts.ts @@ -13,7 +13,7 @@ export async function updateArtifacts( newPackageFileContent: string, config: UpdateArtifactsConfig ): Promise<UpdateArtifactsResult[] | null> { - await logger.debug(`cargo.updateArtifacts(${packageFileName})`); + logger.debug(`cargo.updateArtifacts(${packageFileName})`); if (updatedDeps === undefined || updatedDeps.length < 1) { logger.debug('No updated cargo deps - returning null'); return null; diff --git a/lib/manager/cargo/extract.ts b/lib/manager/cargo/extract.ts index 8e4219e25b..b248839997 100644 --- a/lib/manager/cargo/extract.ts +++ b/lib/manager/cargo/extract.ts @@ -4,53 +4,6 @@ import { isValid } from '../../versioning/cargo'; import { PackageDependency, PackageFile } from '../common'; import { CargoConfig, CargoSection } from './types'; -export function extractPackageFile( - content: string, - fileName: string -): PackageFile | null { - logger.trace(`cargo.extractPackageFile(${fileName})`); - let parsedContent: CargoConfig; - try { - parsedContent = parse(content); - } catch (err) { - logger.debug({ err }, 'Error parsing Cargo.toml file'); - return null; - } - /* - There are the following sections in Cargo.toml: - [dependencies] - [dev-dependencies] - [build-dependencies] - [target.*.dependencies] - */ - const targetSection = parsedContent.target; - // An array of all dependencies in the target section - let targetDeps: PackageDependency[] = []; - if (targetSection) { - const targets = Object.keys(targetSection); - targets.forEach(target => { - const targetContent = parsedContent.target[target]; - // Dependencies for `${target}` - const deps = [ - ...extractFromSection(targetContent, 'dependencies', target), - ...extractFromSection(targetContent, 'dev-dependencies', target), - ...extractFromSection(targetContent, 'build-dependencies', target), - ]; - targetDeps = targetDeps.concat(deps); - }); - } - const deps = [ - ...extractFromSection(parsedContent, 'dependencies'), - ...extractFromSection(parsedContent, 'dev-dependencies'), - ...extractFromSection(parsedContent, 'build-dependencies'), - ...targetDeps, - ]; - if (!deps.length) { - return null; - } - return { deps }; -} - function extractFromSection( parsedContent: CargoSection, section: keyof CargoSection, @@ -108,3 +61,50 @@ function extractFromSection( }); return deps; } + +export function extractPackageFile( + content: string, + fileName: string +): PackageFile | null { + logger.trace(`cargo.extractPackageFile(${fileName})`); + let parsedContent: CargoConfig; + try { + parsedContent = parse(content); + } catch (err) { + logger.debug({ err }, 'Error parsing Cargo.toml file'); + return null; + } + /* + There are the following sections in Cargo.toml: + [dependencies] + [dev-dependencies] + [build-dependencies] + [target.*.dependencies] + */ + const targetSection = parsedContent.target; + // An array of all dependencies in the target section + let targetDeps: PackageDependency[] = []; + if (targetSection) { + const targets = Object.keys(targetSection); + targets.forEach(target => { + const targetContent = parsedContent.target[target]; + // Dependencies for `${target}` + const deps = [ + ...extractFromSection(targetContent, 'dependencies', target), + ...extractFromSection(targetContent, 'dev-dependencies', target), + ...extractFromSection(targetContent, 'build-dependencies', target), + ]; + targetDeps = targetDeps.concat(deps); + }); + } + const deps = [ + ...extractFromSection(parsedContent, 'dependencies'), + ...extractFromSection(parsedContent, 'dev-dependencies'), + ...extractFromSection(parsedContent, 'build-dependencies'), + ...targetDeps, + ]; + if (!deps.length) { + return null; + } + return { deps }; +} diff --git a/lib/manager/composer/extract.ts b/lib/manager/composer/extract.ts index 4358ef9589..4569bb98fa 100644 --- a/lib/manager/composer/extract.ts +++ b/lib/manager/composer/extract.ts @@ -31,16 +31,12 @@ interface ComposerConfig { * * Entries with type vcs or git will be added to repositories, * other entries will be added to registryUrls - * - * @param repoJson - * @param repositories - * @param registryUrls */ function parseRepositories( repoJson: ComposerConfig['repositories'], repositories: Record<string, Repo>, registryUrls: string[] -) { +): void { try { let packagist = true; Object.entries(repoJson).forEach(([key, repo]) => { diff --git a/lib/manager/gradle-wrapper/update.ts b/lib/manager/gradle-wrapper/update.ts index 0886e9ede6..3f12310618 100644 --- a/lib/manager/gradle-wrapper/update.ts +++ b/lib/manager/gradle-wrapper/update.ts @@ -2,6 +2,25 @@ import got from '../../util/got'; import { logger } from '../../logger'; import { Upgrade } from '../common'; +function replaceType(url: string): string { + return url.replace('bin', 'all'); +} + +async function getChecksum(url: string): Promise<string> { + try { + const response = await got(url); + return response.body as string; + } catch (err) { + if (err.statusCode === 404 || err.code === 'ENOTFOUND') { + logger.info('Gradle checksum lookup failure: not found'); + logger.debug({ err }); + } else { + logger.warn({ err }, 'Gradle checksum lookup failure: Unknown error'); + } + throw err; + } +} + export async function updateDependency( fileContent: string, upgrade: Upgrade @@ -34,22 +53,3 @@ export async function updateDependency( return null; } } - -function replaceType(url: string): string { - return url.replace('bin', 'all'); -} - -async function getChecksum(url: string): Promise<string> { - try { - const response = await got(url); - return response.body as string; - } catch (err) { - if (err.statusCode === 404 || err.code === 'ENOTFOUND') { - logger.info('Gradle checksum lookup failure: not found'); - logger.debug({ err }); - } else { - logger.warn({ err }, 'Gradle checksum lookup failure: Unknown error'); - } - throw err; - } -} diff --git a/lib/manager/gradle/build-gradle.ts b/lib/manager/gradle/build-gradle.ts index d22b7ac493..8188e11ebd 100644 --- a/lib/manager/gradle/build-gradle.ts +++ b/lib/manager/gradle/build-gradle.ts @@ -22,40 +22,95 @@ interface UpdateFunction { ): string; } -export function updateGradleVersion( - buildGradleContent: string, - dependency: GradleDependency, - newVersion: string -): string { - if (dependency) { - const updateFunctions: UpdateFunction[] = [ - updateVersionLiterals, - updateLocalVariables, - updateGlobalVariables, - updatePropertyFileGlobalVariables, - updateKotlinVariablesByExtra, - ]; +// https://github.com/patrikerdes/gradle-use-latest-versions-plugin/blob/8cf9c3917b8b04ba41038923cab270d2adda3aa6/src/main/groovy/se/patrikerdes/DependencyUpdate.groovy#L27-L29 +function moduleStringVersionFormatMatch(dependency: GradleDependency): RegExp { + return new RegExp( + `(["']${dependency.group}:${dependency.name}:)[^$].*?(([:@].*?)?["'])` + ); +} - // eslint-disable-next-line guard-for-in - for (const updateFunctionIndex in updateFunctions) { - const updateFunction = updateFunctions[updateFunctionIndex]; - const gradleContentUpdated = updateFunction( - dependency, - buildGradleContent, - newVersion - ); - if (gradleContentUpdated) { - return gradleContentUpdated; - } - } - } - return buildGradleContent; +function groovyPluginStringVersionFormatMatch( + dependency: GradleDependency +): RegExp { + return new RegExp( + `(id\\s+["']${dependency.group}["']\\s+version\\s+["'])[^$].*?(["'])` + ); +} + +function kotlinPluginStringVersionFormatMatch( + dependency: GradleDependency +): RegExp { + return new RegExp( + `(id\\("${dependency.group}"\\)\\s+version\\s+")[^$].*?(")` + ); +} + +function moduleMapVersionFormatMatch(dependency: GradleDependency): RegExp { + // prettier-ignore + return new RegExp( + `(group\\s*:\\s*["']${dependency.group}["']\\s*,\\s*` + + `name\\s*:\\s*["']${dependency.name}["']\\s*,\\s*` + + `version\\s*:\\s*["']).*?(["'])` + ); +} + +function moduleKotlinNamedArgumentVersionFormatMatch( + dependency: GradleDependency +): RegExp { + // prettier-ignore + return new RegExp( + `(group\\s*=\\s*"${dependency.group}"\\s*,\\s*` + + `name\\s*=\\s*"${dependency.name}"\\s*,\\s*` + + `version\\s*=\\s*").*?(")` + ); +} + +function moduleMapVariableVersionFormatMatch( + dependency: GradleDependency +): RegExp { + // prettier-ignore + return new RegExp( + `group\\s*:\\s*["']${dependency.group}["']\\s*,\\s*` + + `name\\s*:\\s*["']${dependency.name}["']\\s*,\\s*` + + `version\\s*:\\s*([^\\s"')]+)\\s*` + ); +} + +function moduleKotlinNamedArgumentVariableVersionFormatMatch( + dependency: GradleDependency +): RegExp { + // prettier-ignore + return new RegExp( + `group\\s*=\\s*"${dependency.group}"\\s*,\\s*` + + `name\\s*=\\s*"${dependency.name}"\\s*,\\s*` + + `version\\s*=\\s*([^\\s"]+?)[\\s\\),]` + ); +} + +function moduleStringVariableInterpolationVersionFormatMatch( + dependency: GradleDependency +): RegExp { + return new RegExp( + `["']${dependency.group}:${dependency.name}:\\$([^{].*?)["']` + ); +} + +function moduleStringVariableExpressionVersionFormatMatch( + dependency: GradleDependency +): RegExp { + return new RegExp( + `["']${dependency.group}:${dependency.name}:\\$\{([^{].*?)}["']` + ); +} + +function variableDefinitionFormatMatch(variable: string): RegExp { + return new RegExp(`(${variable}\\s*=\\s*?["'])(.*)(["'])`); } export function collectVersionVariables( dependencies: BuildDependency[], buildGradleContent: string -) { +): void { for (const dep of dependencies) { const dependency: GradleDependency = { ...dep, @@ -77,7 +132,7 @@ export function collectVersionVariables( } } -export function init() { +export function init(): void { variables = {}; } @@ -177,87 +232,32 @@ function updatePropertyFileGlobalVariables( return null; } -// https://github.com/patrikerdes/gradle-use-latest-versions-plugin/blob/8cf9c3917b8b04ba41038923cab270d2adda3aa6/src/main/groovy/se/patrikerdes/DependencyUpdate.groovy#L27-L29 -function moduleStringVersionFormatMatch(dependency: GradleDependency): RegExp { - return new RegExp( - `(["']${dependency.group}:${dependency.name}:)[^$].*?(([:@].*?)?["'])` - ); -} - -function groovyPluginStringVersionFormatMatch( - dependency: GradleDependency -): RegExp { - return new RegExp( - `(id\\s+["']${dependency.group}["']\\s+version\\s+["'])[^$].*?(["'])` - ); -} - -function kotlinPluginStringVersionFormatMatch( - dependency: GradleDependency -): RegExp { - return new RegExp( - `(id\\("${dependency.group}"\\)\\s+version\\s+")[^$].*?(")` - ); -} - -function moduleMapVersionFormatMatch(dependency: GradleDependency): RegExp { - // prettier-ignore - return new RegExp( - `(group\\s*:\\s*["']${dependency.group}["']\\s*,\\s*` + - `name\\s*:\\s*["']${dependency.name}["']\\s*,\\s*` + - `version\\s*:\\s*["']).*?(["'])` - ); -} - -function moduleKotlinNamedArgumentVersionFormatMatch( - dependency: GradleDependency -): RegExp { - // prettier-ignore - return new RegExp( - `(group\\s*=\\s*"${dependency.group}"\\s*,\\s*` + - `name\\s*=\\s*"${dependency.name}"\\s*,\\s*` + - `version\\s*=\\s*").*?(")` - ); -} - -function moduleMapVariableVersionFormatMatch( - dependency: GradleDependency -): RegExp { - // prettier-ignore - return new RegExp( - `group\\s*:\\s*["']${dependency.group}["']\\s*,\\s*` + - `name\\s*:\\s*["']${dependency.name}["']\\s*,\\s*` + - `version\\s*:\\s*([^\\s"')]+)\\s*` - ); -} - -function moduleKotlinNamedArgumentVariableVersionFormatMatch( - dependency: GradleDependency -): RegExp { - // prettier-ignore - return new RegExp( - `group\\s*=\\s*"${dependency.group}"\\s*,\\s*` + - `name\\s*=\\s*"${dependency.name}"\\s*,\\s*` + - `version\\s*=\\s*([^\\s"]+?)[\\s\\),]` - ); -} - -function moduleStringVariableInterpolationVersionFormatMatch( - dependency: GradleDependency -): RegExp { - return new RegExp( - `["']${dependency.group}:${dependency.name}:\\$([^{].*?)["']` - ); -} - -function moduleStringVariableExpressionVersionFormatMatch( - dependency: GradleDependency -): RegExp { - return new RegExp( - `["']${dependency.group}:${dependency.name}:\\$\{([^{].*?)}["']` - ); -} +export function updateGradleVersion( + buildGradleContent: string, + dependency: GradleDependency, + newVersion: string +): string { + if (dependency) { + const updateFunctions: UpdateFunction[] = [ + updateVersionLiterals, + updateLocalVariables, + updateGlobalVariables, + updatePropertyFileGlobalVariables, + updateKotlinVariablesByExtra, + ]; -function variableDefinitionFormatMatch(variable: string): RegExp { - return new RegExp(`(${variable}\\s*=\\s*?["'])(.*)(["'])`); + // eslint-disable-next-line guard-for-in + for (const updateFunctionIndex in updateFunctions) { + const updateFunction = updateFunctions[updateFunctionIndex]; + const gradleContentUpdated = updateFunction( + dependency, + buildGradleContent, + newVersion + ); + if (gradleContentUpdated) { + return gradleContentUpdated; + } + } + } + return buildGradleContent; } diff --git a/lib/manager/gradle/gradle-updates-report.ts b/lib/manager/gradle/gradle-updates-report.ts index 3bf70518ff..45db9b5aa1 100644 --- a/lib/manager/gradle/gradle-updates-report.ts +++ b/lib/manager/gradle/gradle-updates-report.ts @@ -27,7 +27,7 @@ export interface BuildDependency { registryUrls?: string[]; } -async function createRenovateGradlePlugin(localDir: string) { +async function createRenovateGradlePlugin(localDir: string): Promise<void> { const content = ` import groovy.json.JsonOutput import org.gradle.api.internal.artifacts.dependencies.DefaultExternalModuleDependency @@ -67,19 +67,6 @@ gradle.buildFinished { await writeFile(gradleInitFile, content); } -async function extractDependenciesFromUpdatesReport( - localDir: string -): Promise<BuildDependency[]> { - const gradleProjectConfigurations = await readGradleReport(localDir); - - const dependencies = gradleProjectConfigurations - .map(mergeDependenciesWithRepositories, []) - .reduce(flatternDependencies, []) - .reduce(combineReposOnDuplicatedDependencies, []); - - return dependencies.map(gradleModule => buildDependency(gradleModule)); -} - async function readGradleReport(localDir: string): Promise<GradleProject[]> { const renovateReportFilename = join( localDir, @@ -148,6 +135,19 @@ function buildDependency( }; } +async function extractDependenciesFromUpdatesReport( + localDir: string +): Promise<BuildDependency[]> { + const gradleProjectConfigurations = await readGradleReport(localDir); + + const dependencies = gradleProjectConfigurations + .map(mergeDependenciesWithRepositories, []) + .reduce(flatternDependencies, []) + .reduce(combineReposOnDuplicatedDependencies, []); + + return dependencies.map(gradleModule => buildDependency(gradleModule)); +} + export { extractDependenciesFromUpdatesReport, createRenovateGradlePlugin, diff --git a/lib/manager/gradle/index.ts b/lib/manager/gradle/index.ts index 25bc1cc988..b06e63c652 100644 --- a/lib/manager/gradle/index.ts +++ b/lib/manager/gradle/index.ts @@ -21,6 +21,78 @@ const GRADLE_DEPENDENCY_REPORT_OPTIONS = '--init-script renovate-plugin.gradle renovate'; const TIMEOUT_CODE = 143; +async function canExecute(path: string): Promise<boolean> { + try { + await access(path, constants.X_OK); + return true; + } catch { + return false; + } +} + +async function getGradleCommandLine( + config: ExtractConfig, + cwd: string +): Promise<string> { + let cmd: string; + const gradlewPath = upath.join(cwd, 'gradlew'); + const gradlewExists = await exists(gradlewPath); + const gradlewExecutable = gradlewExists && (await canExecute(gradlewPath)); + + if (config.binarySource === 'docker') { + cmd = `docker run --rm `; + // istanbul ignore if + if (config.dockerUser) { + cmd += `--user=${config.dockerUser} `; + } + cmd += `-v "${cwd}":"${cwd}" -w "${cwd}" `; + cmd += `renovate/gradle gradle`; + } else if (gradlewExecutable) { + cmd = './gradlew'; + } else if (gradlewExists) { + cmd = 'sh gradlew'; + } else { + cmd = 'gradle'; + } + return cmd + ' ' + GRADLE_DEPENDENCY_REPORT_OPTIONS; +} + +async function executeGradle( + config: ExtractConfig, + cwd: string +): Promise<void> { + let stdout: string; + let stderr: string; + const gradleTimeout = + config.gradle && config.gradle.timeout + ? config.gradle.timeout * 1000 + : undefined; + const cmd = await getGradleCommandLine(config, cwd); + try { + logger.debug({ cmd }, 'Start gradle command'); + ({ stdout, stderr } = await exec(cmd, { + cwd, + timeout: gradleTimeout, + })); + } catch (err) { + // istanbul ignore if + if (err.code === TIMEOUT_CODE) { + logger.error(' Process killed. Possibly gradle timed out.'); + } + // istanbul ignore if + if (err.message.includes('Could not resolve all files for configuration')) { + logger.debug({ err }, 'Gradle error'); + logger.warn('Gradle resolution error'); + return; + } + logger.warn({ err, cmd }, 'Gradle run failed'); + logger.info('Aborting Renovate due to Gradle lookup errors'); + throw new Error('registry-failure'); + } + logger.debug(stdout + stderr); + logger.info('Gradle report complete'); +} + export async function extractAllPackageFiles( config: ExtractConfig, packageFiles: string[] @@ -82,6 +154,10 @@ export async function extractAllPackageFiles( return gradleFiles; } +function buildGradleDependency(config: Upgrade): GradleDependency { + return { group: config.depGroup, name: config.name, version: config.version }; +} + export function updateDependency( fileContent: string, upgrade: Upgrade @@ -96,77 +172,4 @@ export function updateDependency( ); } -function buildGradleDependency(config: Upgrade): GradleDependency { - return { group: config.depGroup, name: config.name, version: config.version }; -} - -async function executeGradle(config: ExtractConfig, cwd: string) { - let stdout: string; - let stderr: string; - const gradleTimeout = - config.gradle && config.gradle.timeout - ? config.gradle.timeout * 1000 - : undefined; - const cmd = await getGradleCommandLine(config, cwd); - try { - logger.debug({ cmd }, 'Start gradle command'); - ({ stdout, stderr } = await exec(cmd, { - cwd, - timeout: gradleTimeout, - })); - } catch (err) { - // istanbul ignore if - if (err.code === TIMEOUT_CODE) { - logger.error(' Process killed. Possibly gradle timed out.'); - } - // istanbul ignore if - if (err.message.includes('Could not resolve all files for configuration')) { - logger.debug({ err }, 'Gradle error'); - logger.warn('Gradle resolution error'); - return; - } - logger.warn({ err, cmd }, 'Gradle run failed'); - logger.info('Aborting Renovate due to Gradle lookup errors'); - throw new Error('registry-failure'); - } - logger.debug(stdout + stderr); - logger.info('Gradle report complete'); -} - -async function getGradleCommandLine( - config: ExtractConfig, - cwd: string -): Promise<string> { - let cmd: string; - const gradlewPath = upath.join(cwd, 'gradlew'); - const gradlewExists = await exists(gradlewPath); - const gradlewExecutable = gradlewExists && (await canExecute(gradlewPath)); - - if (config.binarySource === 'docker') { - cmd = `docker run --rm `; - // istanbul ignore if - if (config.dockerUser) { - cmd += `--user=${config.dockerUser} `; - } - cmd += `-v "${cwd}":"${cwd}" -w "${cwd}" `; - cmd += `renovate/gradle gradle`; - } else if (gradlewExecutable) { - cmd = './gradlew'; - } else if (gradlewExists) { - cmd = 'sh gradlew'; - } else { - cmd = 'gradle'; - } - return cmd + ' ' + GRADLE_DEPENDENCY_REPORT_OPTIONS; -} - -async function canExecute(path: string): Promise<boolean> { - try { - await access(path, constants.X_OK); - return true; - } catch { - return false; - } -} - export const language = 'java'; diff --git a/lib/manager/helm-requirements/update.ts b/lib/manager/helm-requirements/update.ts index ff0f651608..80f4d56ac9 100644 --- a/lib/manager/helm-requirements/update.ts +++ b/lib/manager/helm-requirements/update.ts @@ -3,8 +3,32 @@ import yaml from 'js-yaml'; import is from '@sindresorhus/is'; import { logger } from '../../logger'; +import { Upgrade } from '../common'; -export function updateDependency(fileContent, upgrade) { +// Return true if the match string is found at index in content +function matchAt(content: string, index: number, match: string): boolean { + return content.substring(index, index + match.length) === match; +} + +// Replace oldString with newString at location index of content +function replaceAt( + content: string, + index: number, + oldString: string, + newString: string +): string { + logger.debug(`Replacing ${oldString} with ${newString} at index ${index}`); + return ( + content.substr(0, index) + + newString + + content.substr(index + oldString.length) + ); +} + +export function updateDependency( + fileContent: string, + upgrade: Upgrade +): string | null { logger.trace({ config: upgrade }, 'updateDependency()'); if (!upgrade || !upgrade.depName || !upgrade.newValue) { logger.debug('Failed to update dependency, invalid upgrade'); @@ -58,18 +82,3 @@ export function updateDependency(fileContent, upgrade) { } return newFileContent; } - -// Return true if the match string is found at index in content -function matchAt(content, index, match) { - return content.substring(index, index + match.length) === match; -} - -// Replace oldString with newString at location index of content -function replaceAt(content, index, oldString, newString) { - logger.debug(`Replacing ${oldString} with ${newString} at index ${index}`); - return ( - content.substr(0, index) + - newString + - content.substr(index + oldString.length) - ); -} diff --git a/lib/manager/homebrew/extract.ts b/lib/manager/homebrew/extract.ts index ccc5135107..f8884fba91 100644 --- a/lib/manager/homebrew/extract.ts +++ b/lib/manager/homebrew/extract.ts @@ -3,58 +3,22 @@ import { skip, isSpace, removeComments } from './util'; import { logger } from '../../logger'; import { PackageFile, PackageDependency } from '../common'; -// TODO: Maybe check if quotes/double-quotes are balanced -export function extractPackageFile(content: string): PackageFile | null { - logger.trace('extractPackageFile()'); - /* - 1. match "class className < Formula" - 2. extract className - 3. extract url field (get depName from url) - 4. extract sha256 field - */ - const cleanContent = removeComments(content); - const className = extractClassName(cleanContent); - if (!className) { - logger.debug('Invalid class definition'); +function parseSha256(idx: number, content: string): string | null { + let i = idx; + i += 'sha256'.length; + i = skip(i, content, c => { + return isSpace(c); + }); + if (content[i] !== '"' && content[i] !== "'") { return null; } - const url = extractUrl(cleanContent); - if (!url) { - logger.debug('Invalid URL field'); - } - const urlPathResult = parseUrlPath(url); - let skipReason: string; - let currentValue: string = null; - let ownerName: string = null; - let repoName: string = null; - if (urlPathResult) { - currentValue = urlPathResult.currentValue; - ownerName = urlPathResult.ownerName; - repoName = urlPathResult.repoName; - } else { - logger.debug('Error: Unsupported URL field'); - skipReason = 'unsupported-url'; - } - const sha256 = extractSha256(cleanContent); - if (!sha256 || sha256.length !== 64) { - logger.debug('Error: Invalid sha256 field'); - skipReason = 'invalid-sha256'; - } - const dep: PackageDependency = { - depName: `${ownerName}/${repoName}`, - managerData: { ownerName, repoName, sha256, url }, - currentValue, - datasource: 'github', - }; - if (skipReason) { - dep.skipReason = skipReason; - if (skipReason === 'unsupported-url') { - dep.depName = className; - dep.datasource = null; - } - } - const deps = [dep]; - return { deps }; + i += 1; + let j = i; + j = skip(i, content, c => { + return c !== '"' && c !== "'"; + }); + const sha256 = content.slice(i, j); + return sha256; } function extractSha256(content: string): string | null { @@ -66,22 +30,23 @@ function extractSha256(content: string): string | null { return parseSha256(i, content); } -function parseSha256(idx: number, content: string): string | null { +function parseUrl(idx: number, content: string): string | null { let i = idx; - i += 'sha256'.length; + i += 'url'.length; i = skip(i, content, c => { return isSpace(c); }); - if (content[i] !== '"' && content[i] !== "'") { + const chr = content[i]; + if (chr !== '"' && chr !== "'") { return null; } i += 1; let j = i; j = skip(i, content, c => { - return c !== '"' && c !== "'"; + return c !== '"' && c !== "'" && !isSpace(c); }); - const sha256 = content.slice(i, j); - return sha256; + const url = content.slice(i, j); + return url; } function extractUrl(content: string): string | null { @@ -142,34 +107,6 @@ export function parseUrlPath(urlStr: string): UrlPathParsedResult | null { } } -function parseUrl(idx: number, content: string): string | null { - let i = idx; - i += 'url'.length; - i = skip(i, content, c => { - return isSpace(c); - }); - const chr = content[i]; - if (chr !== '"' && chr !== "'") { - return null; - } - i += 1; - let j = i; - j = skip(i, content, c => { - return c !== '"' && c !== "'" && !isSpace(c); - }); - const url = content.slice(i, j); - return url; -} - -function extractClassName(content: string): string | null { - const classRegExp = /(^|\s)class\s/; - let i = content.search(classRegExp); - if (isSpace(content[i])) { - i += 1; - } - return parseClassHeader(i, content); -} - /* This function parses the "class className < Formula" header and returns the className and index of the character just after the header */ function parseClassHeader(idx: number, content: string): string | null { @@ -205,3 +142,66 @@ function parseClassHeader(idx: number, content: string): string | null { } return className; } + +function extractClassName(content: string): string | null { + const classRegExp = /(^|\s)class\s/; + let i = content.search(classRegExp); + if (isSpace(content[i])) { + i += 1; + } + return parseClassHeader(i, content); +} + +// TODO: Maybe check if quotes/double-quotes are balanced +export function extractPackageFile(content: string): PackageFile | null { + logger.trace('extractPackageFile()'); + /* + 1. match "class className < Formula" + 2. extract className + 3. extract url field (get depName from url) + 4. extract sha256 field + */ + const cleanContent = removeComments(content); + const className = extractClassName(cleanContent); + if (!className) { + logger.debug('Invalid class definition'); + return null; + } + const url = extractUrl(cleanContent); + if (!url) { + logger.debug('Invalid URL field'); + } + const urlPathResult = parseUrlPath(url); + let skipReason: string; + let currentValue: string = null; + let ownerName: string = null; + let repoName: string = null; + if (urlPathResult) { + currentValue = urlPathResult.currentValue; + ownerName = urlPathResult.ownerName; + repoName = urlPathResult.repoName; + } else { + logger.debug('Error: Unsupported URL field'); + skipReason = 'unsupported-url'; + } + const sha256 = extractSha256(cleanContent); + if (!sha256 || sha256.length !== 64) { + logger.debug('Error: Invalid sha256 field'); + skipReason = 'invalid-sha256'; + } + const dep: PackageDependency = { + depName: `${ownerName}/${repoName}`, + managerData: { ownerName, repoName, sha256, url }, + currentValue, + datasource: 'github', + }; + if (skipReason) { + dep.skipReason = skipReason; + if (skipReason === 'unsupported-url') { + dep.depName = className; + dep.datasource = null; + } + } + const deps = [dep]; + return { deps }; +} diff --git a/lib/manager/homebrew/update.ts b/lib/manager/homebrew/update.ts index 1508b324e6..fd4b23b687 100644 --- a/lib/manager/homebrew/update.ts +++ b/lib/manager/homebrew/update.ts @@ -6,81 +6,40 @@ import got from '../../util/got'; import { logger } from '../../logger'; import { Upgrade } from '../common'; -// TODO: Refactor -export async function updateDependency( +function replaceUrl( + idx: number, content: string, - upgrade: Upgrade -): Promise<string> { - logger.trace('updateDependency()'); - /* - 1. Update url field 2. Update sha256 field - */ - let newContent = content; - let newUrl: string; - // Example urls: - // "https://github.com/bazelbuild/bazel-watcher/archive/v0.8.2.tar.gz" - // "https://github.com/aide/aide/releases/download/v0.16.1/aide-0.16.1.tar.gz" - const oldParsedUrlPath = parseUrlPath(upgrade.managerData.url); - if (!oldParsedUrlPath) { - logger.debug( - `Failed to update - upgrade.managerData.url is invalid ${upgrade.depName}` - ); - return content; - } - let newSha256; - try { - newUrl = `https://github.com/${upgrade.managerData.ownerName}/${ - upgrade.managerData.repoName - }/releases/download/${upgrade.newValue}/${ - upgrade.managerData.repoName - }-${coerce(upgrade.newValue)}.tar.gz`; - newSha256 = await fromStream(got.stream(newUrl), { - algorithm: 'sha256', - }); - } catch (errOuter) { - logger.debug( - `Failed to download release download for ${upgrade.depName} - trying archive instead` - ); - try { - newUrl = `https://github.com/${upgrade.managerData.ownerName}/${upgrade.managerData.repoName}/archive/${upgrade.newValue}.tar.gz`; - newSha256 = await fromStream(got.stream(newUrl), { - algorithm: 'sha256', - }); - } catch (errInner) { - logger.debug( - `Failed to download archive download for ${upgrade.depName} - update failed` - ); - return content; - } - } - if (!newSha256) { - logger.debug( - `Failed to generate new sha256 for ${upgrade.depName} - update failed` - ); - return content; - } - const newParsedUrlPath = parseUrlPath(newUrl); - if (!newParsedUrlPath) { - logger.debug(`Failed to update url for dependency ${upgrade.depName}`); - return content; - } - if (upgrade.newValue !== newParsedUrlPath.currentValue) { - logger.debug(`Failed to update url for dependency ${upgrade.depName}`); - return content; - } - newContent = updateUrl(content, upgrade.managerData.url, newUrl); - if (!newContent) { - logger.debug(`Failed to update url for dependency ${upgrade.depName}`); - return content; - } - newContent = updateSha256(newContent, upgrade.managerData.sha256, newSha256); - if (!newContent) { - logger.debug(`Failed to update sha256 for dependency ${upgrade.depName}`); - return content; + oldUrl: string, + newUrl: string +): string | null { + let i = idx; + i += 'url'.length; + i = skip(i, content, c => isSpace(c)); + const chr = content[i]; + if (chr !== '"' && chr !== "'") { + return null; } + i += 1; + const newContent = + content.substring(0, i) + content.substring(i).replace(oldUrl, newUrl); return newContent; } +function getUrlTestContent( + content: string, + oldUrl: string, + newUrl: string +): string { + const urlRegExp = /(^|\s)url(\s)/; + const cleanContent = removeComments(content); + let j = cleanContent.search(urlRegExp); + if (isSpace(cleanContent[j])) { + j += 1; + } + const testContent = replaceUrl(j, cleanContent, oldUrl, newUrl); + return testContent; +} + function updateUrl( content: string, oldUrl: string, @@ -110,29 +69,14 @@ function updateUrl( return newContent; } -function getUrlTestContent( - content: string, - oldUrl: string, - newUrl: string -): string { - const urlRegExp = /(^|\s)url(\s)/; - const cleanContent = removeComments(content); - let j = cleanContent.search(urlRegExp); - if (isSpace(cleanContent[j])) { - j += 1; - } - const testContent = replaceUrl(j, cleanContent, oldUrl, newUrl); - return testContent; -} - -function replaceUrl( +function replaceSha256( idx: number, content: string, - oldUrl: string, - newUrl: string + oldSha256: string, + newSha256: string ): string | null { let i = idx; - i += 'url'.length; + i += 'sha256'.length; i = skip(i, content, c => isSpace(c)); const chr = content[i]; if (chr !== '"' && chr !== "'") { @@ -140,10 +84,26 @@ function replaceUrl( } i += 1; const newContent = - content.substring(0, i) + content.substring(i).replace(oldUrl, newUrl); + content.substring(0, i) + + content.substring(i).replace(oldSha256, newSha256); return newContent; } +function getSha256TestContent( + content: string, + oldSha256: string, + newSha256: string +): string | null { + const sha256RegExp = /(^|\s)sha256(\s)/; + const cleanContent = removeComments(content); + let j = cleanContent.search(sha256RegExp); + if (isSpace(cleanContent[j])) { + j += 1; + } + const testContent = replaceSha256(j, cleanContent, oldSha256, newSha256); + return testContent; +} + function updateSha256( content: string, oldSha256: string, @@ -173,37 +133,77 @@ function updateSha256( return newContent; } -function getSha256TestContent( +// TODO: Refactor +export async function updateDependency( content: string, - oldSha256: string, - newSha256: string -): string | null { - const sha256RegExp = /(^|\s)sha256(\s)/; - const cleanContent = removeComments(content); - let j = cleanContent.search(sha256RegExp); - if (isSpace(cleanContent[j])) { - j += 1; + upgrade: Upgrade +): Promise<string> { + logger.trace('updateDependency()'); + /* + 1. Update url field 2. Update sha256 field + */ + let newContent = content; + let newUrl: string; + // Example urls: + // "https://github.com/bazelbuild/bazel-watcher/archive/v0.8.2.tar.gz" + // "https://github.com/aide/aide/releases/download/v0.16.1/aide-0.16.1.tar.gz" + const oldParsedUrlPath = parseUrlPath(upgrade.managerData.url); + if (!oldParsedUrlPath) { + logger.debug( + `Failed to update - upgrade.managerData.url is invalid ${upgrade.depName}` + ); + return content; } - const testContent = replaceSha256(j, cleanContent, oldSha256, newSha256); - return testContent; -} - -function replaceSha256( - idx: number, - content: string, - oldSha256: string, - newSha256: string -): string | null { - let i = idx; - i += 'sha256'.length; - i = skip(i, content, c => isSpace(c)); - const chr = content[i]; - if (chr !== '"' && chr !== "'") { - return null; + let newSha256; + try { + newUrl = `https://github.com/${upgrade.managerData.ownerName}/${ + upgrade.managerData.repoName + }/releases/download/${upgrade.newValue}/${ + upgrade.managerData.repoName + }-${coerce(upgrade.newValue)}.tar.gz`; + newSha256 = await fromStream(got.stream(newUrl), { + algorithm: 'sha256', + }); + } catch (errOuter) { + logger.debug( + `Failed to download release download for ${upgrade.depName} - trying archive instead` + ); + try { + newUrl = `https://github.com/${upgrade.managerData.ownerName}/${upgrade.managerData.repoName}/archive/${upgrade.newValue}.tar.gz`; + newSha256 = await fromStream(got.stream(newUrl), { + algorithm: 'sha256', + }); + } catch (errInner) { + logger.debug( + `Failed to download archive download for ${upgrade.depName} - update failed` + ); + return content; + } + } + if (!newSha256) { + logger.debug( + `Failed to generate new sha256 for ${upgrade.depName} - update failed` + ); + return content; + } + const newParsedUrlPath = parseUrlPath(newUrl); + if (!newParsedUrlPath) { + logger.debug(`Failed to update url for dependency ${upgrade.depName}`); + return content; + } + if (upgrade.newValue !== newParsedUrlPath.currentValue) { + logger.debug(`Failed to update url for dependency ${upgrade.depName}`); + return content; + } + newContent = updateUrl(content, upgrade.managerData.url, newUrl); + if (!newContent) { + logger.debug(`Failed to update url for dependency ${upgrade.depName}`); + return content; + } + newContent = updateSha256(newContent, upgrade.managerData.sha256, newSha256); + if (!newContent) { + logger.debug(`Failed to update sha256 for dependency ${upgrade.depName}`); + return content; } - i += 1; - const newContent = - content.substring(0, i) + - content.substring(i).replace(oldSha256, newSha256); return newContent; } diff --git a/lib/manager/homebrew/util.ts b/lib/manager/homebrew/util.ts index 54ea340c43..132400e447 100644 --- a/lib/manager/homebrew/util.ts +++ b/lib/manager/homebrew/util.ts @@ -17,12 +17,6 @@ export function isSpace(c: string): boolean { return /\s/.test(c); } -export function removeComments(content: string): string { - let newContent = removeLineComments(content); - newContent = removeMultiLineComments(newContent); - return newContent; -} - // Remove line comments starting with # function removeLineComments(content: string): string { let newContent = ''; @@ -65,3 +59,9 @@ function removeMultiLineComments(content: string): string { } return newContent; } + +export function removeComments(content: string): string { + let newContent = removeLineComments(content); + newContent = removeMultiLineComments(newContent); + return newContent; +} diff --git a/lib/manager/index.ts b/lib/manager/index.ts index 5686143849..ca83916117 100644 --- a/lib/manager/index.ts +++ b/lib/manager/index.ts @@ -68,8 +68,10 @@ const languageList = [ 'rust', ]; -export const get = <T extends keyof ManagerApi>(manager: string, name: T) => - managers[manager][name]; +export const get = <T extends keyof ManagerApi>( + manager: string, + name: T +): ManagerApi[T] => managers[manager][name]; export const getLanguageList = (): string[] => languageList; export const getManagerList = (): string[] => managerList; diff --git a/lib/manager/leiningen/extract.ts b/lib/manager/leiningen/extract.ts index 6735329cfa..9f22be4890 100644 --- a/lib/manager/leiningen/extract.ts +++ b/lib/manager/leiningen/extract.ts @@ -36,11 +36,12 @@ export function extractFromVectors( let version = ''; let fileReplacePosition: number = null; - const isSpace = (ch: string) => ch && /[\s,]/.test(ch); + const isSpace = (ch: string): boolean => ch && /[\s,]/.test(ch); - const cleanStrLiteral = (s: string) => s.replace(/^"/, '').replace(/"$/, ''); + const cleanStrLiteral = (s: string): string => + s.replace(/^"/, '').replace(/"$/, ''); - const yieldDep = () => { + const yieldDep = (): void => { if (artifactId && version && fileReplacePosition) { result.push({ ...ctx, @@ -122,7 +123,7 @@ function extractLeinRepos(content: string): string[] { } export function extractPackageFile(content: string): PackageFile { - const collect = (key: string, ctx: ExtractContext) => { + const collect = (key: string, ctx: ExtractContext): PackageDependency[] => { let result: PackageDependency[] = []; let restContent = trimAtKey(content, key); while (restContent) { diff --git a/lib/manager/maven/extract.ts b/lib/manager/maven/extract.ts index a2aa24cb87..89407ca3d7 100644 --- a/lib/manager/maven/extract.ts +++ b/lib/manager/maven/extract.ts @@ -20,7 +20,7 @@ export function parsePom(raw: string): XmlDocument | null { return project; } -export function containsPlaceholder(str: string) { +export function containsPlaceholder(str: string): boolean { return /\${.*?}/g.test(str); } @@ -73,7 +73,7 @@ function applyProps( dep: PackageDependency<Record<string, any>>, props: MavenProp ): PackageDependency<Record<string, any>> { - const replaceAll = (str: string) => + const replaceAll = (str: string): string => str.replace(/\${.*?}/g, substr => { const propKey = substr.slice(2, -1).trim(); const propValue = props[propKey]; diff --git a/lib/manager/mix/artifacts.ts b/lib/manager/mix/artifacts.ts index 7728a5c402..fb81f9c1f0 100644 --- a/lib/manager/mix/artifacts.ts +++ b/lib/manager/mix/artifacts.ts @@ -12,7 +12,7 @@ export async function updateArtifacts( newPackageFileContent: string, config: UpdateArtifactsConfig ): Promise<UpdateArtifactsResult[] | null> { - await logger.debug(`mix.getArtifacts(${packageFileName})`); + logger.debug(`mix.getArtifacts(${packageFileName})`); if (updatedDeps.length < 1) { logger.debug('No updated mix deps - returning null'); return null; diff --git a/lib/manager/npm/extract/index.ts b/lib/manager/npm/extract/index.ts index 5ef5a11d77..72b3d68de6 100644 --- a/lib/manager/npm/extract/index.ts +++ b/lib/manager/npm/extract/index.ts @@ -17,30 +17,6 @@ import { import { NpmPackage } from './common'; import { platform } from '../../../platform'; -export async function extractAllPackageFiles( - config: ExtractConfig, - packageFiles: string[] -): Promise<PackageFile[]> { - const npmFiles: PackageFile[] = []; - for (const packageFile of packageFiles) { - const content = await platform.getFile(packageFile); - if (content) { - const deps = await extractPackageFile(content, packageFile, config); - if (deps) { - npmFiles.push({ - packageFile, - manager: 'npm', - ...deps, - }); - } - } else { - logger.info({ packageFile }, 'packageFile has no content'); - } - } - await postExtract(npmFiles); - return npmFiles; -} - export async function extractPackageFile( content: string, fileName: string, @@ -152,7 +128,11 @@ export async function extractPackageFile( volta: 'volta', }; - function extractDependency(depType: string, depName: string, input: string) { + function extractDependency( + depType: string, + depName: string, + input: string + ): PackageDependency { const dep: PackageDependency = {}; if (!validateNpmPackageName(depName).validForOldPackages) { dep.skipReason = 'invalid-name'; @@ -350,7 +330,31 @@ export async function extractPackageFile( }; } -export async function postExtract(packageFiles: PackageFile[]) { - await detectMonorepos(packageFiles); +export async function postExtract(packageFiles: PackageFile[]): Promise<void> { + detectMonorepos(packageFiles); await getLockedVersions(packageFiles); } + +export async function extractAllPackageFiles( + config: ExtractConfig, + packageFiles: string[] +): Promise<PackageFile[]> { + const npmFiles: PackageFile[] = []; + for (const packageFile of packageFiles) { + const content = await platform.getFile(packageFile); + if (content) { + const deps = await extractPackageFile(content, packageFile, config); + if (deps) { + npmFiles.push({ + packageFile, + manager: 'npm', + ...deps, + }); + } + } else { + logger.info({ packageFile }, 'packageFile has no content'); + } + } + await postExtract(npmFiles); + return npmFiles; +} diff --git a/lib/manager/npm/extract/locked-versions.ts b/lib/manager/npm/extract/locked-versions.ts index 553a6eb1f2..9f96a01069 100644 --- a/lib/manager/npm/extract/locked-versions.ts +++ b/lib/manager/npm/extract/locked-versions.ts @@ -4,7 +4,9 @@ import { getNpmLock } from './npm'; import { getYarnLock } from './yarn'; import { PackageFile } from '../../common'; -export async function getLockedVersions(packageFiles: PackageFile[]) { +export async function getLockedVersions( + packageFiles: PackageFile[] +): Promise<void> { const lockFileCache: Record<string, Record<string, string>> = {}; logger.debug('Finding locked versions'); for (const packageFile of packageFiles) { diff --git a/lib/manager/npm/extract/monorepo.ts b/lib/manager/npm/extract/monorepo.ts index 64adb9ebb1..f06f14f97f 100644 --- a/lib/manager/npm/extract/monorepo.ts +++ b/lib/manager/npm/extract/monorepo.ts @@ -14,7 +14,7 @@ function matchesAnyPattern(val: string, patterns: string[]): boolean { return res; } -export function detectMonorepos(packageFiles: Partial<PackageFile>[]) { +export function detectMonorepos(packageFiles: Partial<PackageFile>[]): void { logger.debug('Detecting Lerna and Yarn Workspaces'); for (const p of packageFiles) { const { diff --git a/lib/manager/npm/post-update/index.ts b/lib/manager/npm/post-update/index.ts index 26a0df2528..ddc0e41496 100644 --- a/lib/manager/npm/post-update/index.ts +++ b/lib/manager/npm/post-update/index.ts @@ -14,7 +14,8 @@ import { platform } from '../../../platform'; // Strips empty values, deduplicates, and returns the directories from filenames // istanbul ignore next -const getDirs = (arr: string[]) => Array.from(new Set(arr.filter(Boolean))); +const getDirs = (arr: string[]): string[] => + Array.from(new Set(arr.filter(Boolean))); export interface DetermineLockFileDirsResult { yarnLockDirs: string[]; @@ -109,7 +110,7 @@ export function determineLockFileDirs( export async function writeExistingFiles( config: PostUpdateConfig, packageFiles: AdditionalPackageFiles -) { +): Promise<void> { const lernaJson = await platform.getFile('lerna.json'); if (lernaJson) { logger.debug(`Writing repo lerna.json (${config.localDir})`); @@ -237,7 +238,9 @@ export async function writeExistingFiles( } // istanbul ignore next -export async function writeUpdatedPackageFiles(config: PostUpdateConfig) { +export async function writeUpdatedPackageFiles( + config: PostUpdateConfig +): Promise<void> { logger.trace({ config }, 'writeUpdatedPackageFiles'); logger.debug('Writing any updated package files'); if (!config.updatedPackageFiles) { diff --git a/lib/manager/npm/update.ts b/lib/manager/npm/update.ts index b8f01da296..c24b044236 100644 --- a/lib/manager/npm/update.ts +++ b/lib/manager/npm/update.ts @@ -3,6 +3,79 @@ import { inc, ReleaseType } from 'semver'; import { logger } from '../../logger'; import { Upgrade } from '../common'; +// Return true if the match string is found at index in content +function matchAt(content: string, index: number, match: string): boolean { + return content.substring(index, index + match.length) === match; +} + +// Replace oldString with newString at location index of content +function replaceAt( + content: string, + index: number, + oldString: string, + newString: string +): string { + logger.debug(`Replacing ${oldString} with ${newString} at index ${index}`); + return ( + content.substr(0, index) + + newString + + content.substr(index + oldString.length) + ); +} + +export function bumpPackageVersion( + content: string, + currentValue: string, + bumpVersion: ReleaseType | string +): string { + if (!bumpVersion) { + return content; + } + logger.debug( + { bumpVersion, currentValue }, + 'Checking if we should bump package.json version' + ); + let newPjVersion; + try { + if (bumpVersion.startsWith('mirror:')) { + const mirrorPackage = bumpVersion.replace('mirror:', ''); + const parsedContent = JSON.parse(content); + newPjVersion = + (parsedContent.dependencies || {})[mirrorPackage] || + (parsedContent.devDependencies || {})[mirrorPackage] || + (parsedContent.optionalDependencies || {})[mirrorPackage] || + (parsedContent.peerDependencies || {})[mirrorPackage]; + if (!newPjVersion) { + logger.warn('bumpVersion mirror package not found: ' + mirrorPackage); + return content; + } + } else { + newPjVersion = inc(currentValue, bumpVersion as ReleaseType); + } + logger.debug({ newPjVersion }); + const bumpedContent = content.replace( + /("version":\s*")[^"]*/, + `$1${newPjVersion}` + ); + if (bumpedContent === content) { + logger.debug('Version was already bumped'); + } else { + logger.info('Bumped package.json version'); + } + return bumpedContent; + } catch (err) { + logger.warn( + { + content, + currentValue, + bumpVersion, + }, + 'Failed to bumpVersion' + ); + return content; + } +} + export function updateDependency( fileContent: string, upgrade: Upgrade @@ -135,76 +208,3 @@ export function updateDependency( return null; } } - -// Return true if the match string is found at index in content -function matchAt(content: string, index: number, match: string): boolean { - return content.substring(index, index + match.length) === match; -} - -// Replace oldString with newString at location index of content -function replaceAt( - content: string, - index: number, - oldString: string, - newString: string -): string { - logger.debug(`Replacing ${oldString} with ${newString} at index ${index}`); - return ( - content.substr(0, index) + - newString + - content.substr(index + oldString.length) - ); -} - -export function bumpPackageVersion( - content: string, - currentValue: string, - bumpVersion: ReleaseType | string -): string { - if (!bumpVersion) { - return content; - } - logger.debug( - { bumpVersion, currentValue }, - 'Checking if we should bump package.json version' - ); - let newPjVersion; - try { - if (bumpVersion.startsWith('mirror:')) { - const mirrorPackage = bumpVersion.replace('mirror:', ''); - const parsedContent = JSON.parse(content); - newPjVersion = - (parsedContent.dependencies || {})[mirrorPackage] || - (parsedContent.devDependencies || {})[mirrorPackage] || - (parsedContent.optionalDependencies || {})[mirrorPackage] || - (parsedContent.peerDependencies || {})[mirrorPackage]; - if (!newPjVersion) { - logger.warn('bumpVersion mirror package not found: ' + mirrorPackage); - return content; - } - } else { - newPjVersion = inc(currentValue, bumpVersion as ReleaseType); - } - logger.debug({ newPjVersion }); - const bumpedContent = content.replace( - /("version":\s*")[^"]*/, - `$1${newPjVersion}` - ); - if (bumpedContent === content) { - logger.debug('Version was already bumped'); - } else { - logger.info('Bumped package.json version'); - } - return bumpedContent; - } catch (err) { - logger.warn( - { - content, - currentValue, - bumpVersion, - }, - 'Failed to bumpVersion' - ); - return content; - } -} diff --git a/lib/manager/pipenv/extract.ts b/lib/manager/pipenv/extract.ts index 16759d0f55..0d55810035 100644 --- a/lib/manager/pipenv/extract.ts +++ b/lib/manager/pipenv/extract.ts @@ -33,31 +33,6 @@ interface PipRequirement { git?: string; } -export function extractPackageFile(content: string): PackageFile | null { - logger.debug('pipenv.extractPackageFile()'); - - let pipfile: PipFile; - try { - pipfile = toml.parse(content); - } catch (err) { - logger.debug({ err }, 'Error parsing Pipfile'); - return null; - } - const res: PackageFile = { deps: [] }; - if (pipfile.source) { - res.registryUrls = pipfile.source.map(source => source.url); - } - - res.deps = [ - ...extractFromSection(pipfile, 'packages'), - ...extractFromSection(pipfile, 'dev-packages'), - ]; - if (res.deps.length) { - return res; - } - return null; -} - function extractFromSection( pipfile: PipFile, section: 'packages' | 'dev-packages' @@ -134,3 +109,28 @@ function extractFromSection( .filter(Boolean); return deps; } + +export function extractPackageFile(content: string): PackageFile | null { + logger.debug('pipenv.extractPackageFile()'); + + let pipfile: PipFile; + try { + pipfile = toml.parse(content); + } catch (err) { + logger.debug({ err }, 'Error parsing Pipfile'); + return null; + } + const res: PackageFile = { deps: [] }; + if (pipfile.source) { + res.registryUrls = pipfile.source.map(source => source.url); + } + + res.deps = [ + ...extractFromSection(pipfile, 'packages'), + ...extractFromSection(pipfile, 'dev-packages'), + ]; + if (res.deps.length) { + return res; + } + return null; +} diff --git a/lib/manager/poetry/artifacts.ts b/lib/manager/poetry/artifacts.ts index f70e0e3847..355ebd0785 100644 --- a/lib/manager/poetry/artifacts.ts +++ b/lib/manager/poetry/artifacts.ts @@ -13,7 +13,7 @@ export async function updateArtifacts( newPackageFileContent: string, config: UpdateArtifactsConfig ): Promise<UpdateArtifactsResult[] | null> { - await logger.debug(`poetry.updateArtifacts(${packageFileName})`); + logger.debug(`poetry.updateArtifacts(${packageFileName})`); if (updatedDeps === undefined || updatedDeps.length < 1) { logger.debug('No updated poetry deps - returning null'); return null; diff --git a/lib/manager/poetry/extract.ts b/lib/manager/poetry/extract.ts index 8bb1abed9e..53c705ded3 100644 --- a/lib/manager/poetry/extract.ts +++ b/lib/manager/poetry/extract.ts @@ -4,34 +4,6 @@ import { logger } from '../../logger'; import { PackageFile, PackageDependency } from '../common'; import { PoetryFile, PoetrySection } from './types'; -export function extractPackageFile( - content: string, - fileName: string -): PackageFile | null { - logger.trace(`poetry.extractPackageFile(${fileName})`); - let pyprojectfile: PoetryFile; - try { - pyprojectfile = parse(content); - } catch (err) { - logger.debug({ err }, 'Error parsing pyproject.toml file'); - return null; - } - if (!(pyprojectfile.tool && pyprojectfile.tool.poetry)) { - logger.debug(`${fileName} contains no poetry section`); - return null; - } - const deps = [ - ...extractFromSection(pyprojectfile, 'dependencies'), - ...extractFromSection(pyprojectfile, 'dev-dependencies'), - ...extractFromSection(pyprojectfile, 'extras'), - ]; - if (!deps.length) { - return null; - } - - return { deps, registryUrls: extractRegistries(pyprojectfile) }; -} - function extractFromSection( parsedFile: PoetryFile, section: keyof PoetrySection @@ -106,3 +78,31 @@ function extractRegistries(pyprojectfile: PoetryFile): string[] { return Array.from(registryUrls); } + +export function extractPackageFile( + content: string, + fileName: string +): PackageFile | null { + logger.trace(`poetry.extractPackageFile(${fileName})`); + let pyprojectfile: PoetryFile; + try { + pyprojectfile = parse(content); + } catch (err) { + logger.debug({ err }, 'Error parsing pyproject.toml file'); + return null; + } + if (!(pyprojectfile.tool && pyprojectfile.tool.poetry)) { + logger.debug(`${fileName} contains no poetry section`); + return null; + } + const deps = [ + ...extractFromSection(pyprojectfile, 'dependencies'), + ...extractFromSection(pyprojectfile, 'dev-dependencies'), + ...extractFromSection(pyprojectfile, 'extras'), + ]; + if (!deps.length) { + return null; + } + + return { deps, registryUrls: extractRegistries(pyprojectfile) }; +} diff --git a/lib/manager/pub/update.ts b/lib/manager/pub/update.ts index 53c3680346..547c9eaa64 100644 --- a/lib/manager/pub/update.ts +++ b/lib/manager/pub/update.ts @@ -10,19 +10,21 @@ export function updateDependency( if (currentValue === newValue) return fileContent; const sectionBeginRegExp = new RegExp(`^${depType}:`); - const isSectionBegin = (line: string) => sectionBeginRegExp.test(line); - const isSectionEnd = (line: string) => /^[^\s]/.test(line); + const isSectionBegin = (line: string): boolean => + sectionBeginRegExp.test(line); + const isSectionEnd = (line: string): boolean => /^[^\s]/.test(line); const simpleDepRegExp = new RegExp(`^\\s+${depName}:\\s*[^\\s]+\\s*$`); - const isOneLineDep = (line: string) => simpleDepRegExp.test(line); + const isOneLineDep = (line: string): boolean => simpleDepRegExp.test(line); const multilineDepRegExp = new RegExp(`^\\s+${depName}:\\s*$`); - const isMultilineDepRegExp = (line: string) => multilineDepRegExp.test(line); + const isMultilineDepRegExp = (line: string): boolean => + multilineDepRegExp.test(line); const versionRegExp = new RegExp('^\\s+version:\\s*[^\\s]+\\s*$'); - const isVersionLine = (line: string) => versionRegExp.test(line); + const isVersionLine = (line: string): boolean => versionRegExp.test(line); - const isValidVersion = (line: string) => { + const isValidVersion = (line: string): boolean => { const version = load(line.replace(/^.*:\s*/, '')).toString(); return version === currentValue; }; diff --git a/lib/manager/sbt/extract.ts b/lib/manager/sbt/extract.ts index 05e7a132cb..c8e57addd7 100644 --- a/lib/manager/sbt/extract.ts +++ b/lib/manager/sbt/extract.ts @@ -1,43 +1,53 @@ import { DEFAULT_MAVEN_REPO } from '../maven/extract'; import { PackageFile, PackageDependency } from '../common'; -const isComment = (str: string) => /^\s*\/\//.test(str); +const isComment = (str: string): boolean => /^\s*\/\//.test(str); -const isSingleLineDep = (str: string) => +const isSingleLineDep = (str: string): boolean => /^\s*(libraryDependencies|dependencyOverrides)\s*\+=\s*/.test(str); -const isDepsBegin = (str: string) => +const isDepsBegin = (str: string): boolean => /^\s*(libraryDependencies|dependencyOverrides)\s*\+\+=\s*/.test(str); -const isPluginDep = (str: string) => /^\s*addSbtPlugin\s*\(.*\)\s*$/.test(str); +const isPluginDep = (str: string): boolean => + /^\s*addSbtPlugin\s*\(.*\)\s*$/.test(str); -const isStringLiteral = (str: string) => /^"[^"]*"$/.test(str); +const isStringLiteral = (str: string): boolean => /^"[^"]*"$/.test(str); -const isScalaVersion = (str: string) => +const isScalaVersion = (str: string): boolean => /^\s*scalaVersion\s*:=\s*"[^"]*"\s*$/.test(str); -const getScalaVersion = (str: string) => + +const getScalaVersion = (str: string): string => str.replace(/^\s*scalaVersion\s*:=\s*"/, '').replace(/"\s*$/, ''); -const isScalaVersionVariable = (str: string) => +const isScalaVersionVariable = (str: string): boolean => /^\s*scalaVersion\s*:=\s*[_a-zA-Z][_a-zA-Z0-9]*\s*$/.test(str); -const getScalaVersionVariable = (str: string) => + +const getScalaVersionVariable = (str: string): string => str.replace(/^\s*scalaVersion\s*:=\s*/, '').replace(/\s*$/, ''); -const isResolver = (str: string) => +const isResolver = (str: string): boolean => /^\s*(resolvers\s*\+\+?=\s*(Seq\()?)?"[^"]*"\s*at\s*"[^"]*"[\s,)]*$/.test( str ); -const getResolverUrl = (str: string) => +const getResolverUrl = (str: string): string => str .replace(/^\s*(resolvers\s*\+\+?=\s*(Seq\()?)?"[^"]*"\s*at\s*"/, '') .replace(/"[\s,)]*$/, ''); -const isVarDef = (str: string) => +const isVarDef = (str: string): boolean => /^\s*val\s+[_a-zA-Z][_a-zA-Z0-9]*\s*=\s*"[^"]*"\s*$/.test(str); -const getVarName = (str: string) => + +const getVarName = (str: string): string => str.replace(/^\s*val\s+/, '').replace(/\s*=\s*"[^"]*"\s*$/, ''); -const isVarName = (str: string) => /^[_a-zA-Z][_a-zA-Z0-9]*$/.test(str); -const getVarInfo = (str: string, ctx: ParseContext) => { + +const isVarName = (str: string): boolean => + /^[_a-zA-Z][_a-zA-Z0-9]*$/.test(str); + +const getVarInfo = ( + str: string, + ctx: ParseContext +): { val: string; fileReplacePosition: number } => { const { fileOffset } = ctx; const rightPart = str.replace(/^\s*val\s+[_a-zA-Z][_a-zA-Z0-9]*\s*=\s*"/, ''); const fileReplacePosition = str.search(rightPart) + fileOffset; @@ -59,10 +69,10 @@ function parseDepExpr( const { scalaVersion, fileOffset, variables } = ctx; let { depType } = ctx; - const isValidToken = (str: string) => + const isValidToken = (str: string): boolean => isStringLiteral(str) || (isVarName(str) && !!variables[str]); - const resolveToken = (str: string) => + const resolveToken = (str: string): string => isStringLiteral(str) ? str.replace(/^"/, '').replace(/"$/, '') : variables[str].val; diff --git a/lib/manager/swift/extract.ts b/lib/manager/swift/extract.ts index 80746f4e02..1b447b0e92 100644 --- a/lib/manager/swift/extract.ts +++ b/lib/manager/swift/extract.ts @@ -153,7 +153,7 @@ export function extractPackageFile( let currentValue: string = null; let fileReplacePosition: number = null; - function yieldDep() { + function yieldDep(): void { const depName = getDepName(lookupName); if (depName && currentValue && fileReplacePosition) { const dep: PackageDependency = { diff --git a/lib/manager/travis/package.ts b/lib/manager/travis/package.ts index 558309c466..ade8a333d9 100644 --- a/lib/manager/travis/package.ts +++ b/lib/manager/travis/package.ts @@ -25,7 +25,7 @@ type NodeJsData = Record<string, NodeJsSchedule>; let policies: NodeJsPolicies; let refreshDate: Date; -function generatePolicies() { +function generatePolicies(): void { policies = { all: [], lts: [], @@ -56,7 +56,7 @@ function generatePolicies() { policies.lts_latest.push(policies.lts[policies.lts.length - 1]); } -function checkPolicies() { +function checkPolicies(): void { if (policies && refreshDate > new Date()) { return; } -- GitLab