From d62e2a715aa27b3843840d647d0d41755341d3a2 Mon Sep 17 00:00:00 2001 From: Jonas Rutishauser Date: Thu, 14 Nov 2024 15:56:51 +0100 Subject: [PATCH 1/3] feat(maven): Add replacement support First part to solve issue #5667 --- docs/usage/configuration-options.md | 1 - lib/modules/manager/maven/update.spec.ts | 123 ++++++++++++++++++++++- lib/modules/manager/maven/update.ts | 73 ++++++++++++-- 3 files changed, 184 insertions(+), 13 deletions(-) diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index dc974e1bd17b08..5742a10cb1017a 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -3161,7 +3161,6 @@ Managers which do not support replacement: - `gomod` - `gradle` - `homebrew` -- `maven` - `regex` - `sbt` diff --git a/lib/modules/manager/maven/update.spec.ts b/lib/modules/manager/maven/update.spec.ts index a6f9a5717a361e..1b82a9b47647c3 100644 --- a/lib/modules/manager/maven/update.spec.ts +++ b/lib/modules/manager/maven/update.spec.ts @@ -10,12 +10,127 @@ const prereleaseContent = Fixtures.get(`prerelease.pom.xml`); describe('modules/manager/maven/update', () => { describe('updateDependency', () => { - it('should return null for replacement', () => { + it('should update version', () => { const res = updateDependency({ - fileContent: '', - upgrade: { updateType: 'replacement' }, + fileContent: simpleContent, + upgrade: { + updateType: 'patch', + depName: 'org.example:foo', + currentValue: '0.0.1', + fileReplacePosition: 905, + newValue: '0.0.2', + }, }); - expect(res).toBeNull(); + + const project = new XmlDocument(res!); + expect( + project.valueWithPath( + 'dependencyManagement.dependencies.dependency.version', + ), + ).toBe('0.0.2'); + }); + + it('should do simple replacement', () => { + const res = updateDependency({ + fileContent: simpleContent, + upgrade: { + updateType: 'replacement', + depName: 'org.example:foo', + currentValue: '0.0.1', + fileReplacePosition: 905, + newName: 'org.example.new:foo', + newValue: '0.0.1', + }, + }); + + const project = new XmlDocument(res!); + expect( + project.valueWithPath( + 'dependencyManagement.dependencies.dependency.groupId', + ), + ).toBe('org.example.new'); + }); + + it('should do full replacement', () => { + const res = updateDependency({ + fileContent: simpleContent, + upgrade: { + updateType: 'replacement', + depName: 'org.example:foo', + currentValue: '0.0.1', + fileReplacePosition: 905, + newName: 'org.example.new:bar', + newValue: '0.0.2', + }, + }); + + const project = new XmlDocument(res!); + expect( + project.valueWithPath( + 'dependencyManagement.dependencies.dependency.groupId', + ), + ).toBe('org.example.new'); + expect( + project.valueWithPath( + 'dependencyManagement.dependencies.dependency.artifactId', + ), + ).toBe('bar'); + expect( + project.valueWithPath( + 'dependencyManagement.dependencies.dependency.version', + ), + ).toBe('0.0.2'); + }); + + it('should do replacement if version is first', () => { + const res = updateDependency({ + fileContent: + simpleContent.slice(0, 814) + + simpleContent.slice(890, 923) + + simpleContent.slice(814, 890) + + simpleContent.slice(923), + upgrade: { + updateType: 'replacement', + depName: 'org.example:foo', + currentValue: '0.0.1', + fileReplacePosition: 829, + newName: 'org.example.new:bar', + newValue: '0.0.1', + }, + }); + + const project = new XmlDocument(res!); + expect( + project.valueWithPath( + 'dependencyManagement.dependencies.dependency.groupId', + ), + ).toBe('org.example.new'); + expect( + project.valueWithPath( + 'dependencyManagement.dependencies.dependency.artifactId', + ), + ).toBe('bar'); + expect( + project.valueWithPath( + 'dependencyManagement.dependencies.dependency.version', + ), + ).toBe('0.0.1'); + }); + + it('should ignore replacement if name does not match', () => { + const res = updateDependency({ + fileContent: simpleContent, + upgrade: { + updateType: 'replacement', + depName: 'org.example.old:bar', + currentValue: '0.0.1', + fileReplacePosition: 905, + newName: 'org.example:foo', + newValue: '0.0.1', + }, + }); + + expect(res).toBe(simpleContent); }); }); diff --git a/lib/modules/manager/maven/update.ts b/lib/modules/manager/maven/update.ts index b22261c0a85162..d61de975f22402 100644 --- a/lib/modules/manager/maven/update.ts +++ b/lib/modules/manager/maven/update.ts @@ -15,14 +15,54 @@ export function updateAtPosition( upgrade: Upgrade, endingAnchor: string, ): string | null { - const { depName, currentValue, newValue, fileReplacePosition } = upgrade; - const leftPart = fileContent.slice(0, fileReplacePosition); + const { depName, newName, currentValue, newValue, fileReplacePosition } = + upgrade; + let leftPart = fileContent.slice(0, fileReplacePosition); const rightPart = fileContent.slice(fileReplacePosition); const versionClosePosition = rightPart.indexOf(endingAnchor); - const restPart = rightPart.slice(versionClosePosition); + let restPart = rightPart.slice(versionClosePosition); const versionPart = rightPart.slice(0, versionClosePosition); const version = versionPart.trim(); - if (version === newValue) { + if (newName) { + const blockStart = Math.max( + leftPart.lastIndexOf(' 0) { + leftBlock = updateValue(leftBlock, 'groupId', groupId, newGroupId); + } else { + rightBlock = updateValue(rightBlock, 'groupId', groupId, newGroupId); + } + if (leftBlock.indexOf(' 0) { + leftBlock = updateValue( + leftBlock, + 'artifactId', + artifactId, + newArtifactId, + ); + } else { + rightBlock = updateValue( + rightBlock, + 'artifactId', + artifactId, + newArtifactId, + ); + } + leftPart = leftPart.slice(0, blockStart) + leftBlock; + restPart = rightBlock + restPart.slice(blockEnd); + } else if (version === newValue) { return fileContent; } if (version === currentValue || upgrade.groupName) { @@ -38,10 +78,6 @@ export function updateDependency({ fileContent, upgrade, }: UpdateDependencyConfig): string | null { - if (upgrade.updateType === 'replacement') { - logger.warn('maven manager does not support replacement updates yet'); - return null; - } const offset = fileContent.indexOf('<'); const spaces = fileContent.slice(0, offset); const restContent = fileContent.slice(offset); @@ -141,3 +177,24 @@ function isSnapshot( const lastPart = prerelease?.at(-1); return is.string(lastPart) && lastPart.endsWith('SNAPSHOT'); } + +function updateValue( + content: string, + nodeName: string, + oldValue: string, + newValue: string, +): string { + const elementStart = content.indexOf('<' + nodeName); + const start = content.slice(elementStart).indexOf('>') + elementStart + 1; + const end = content.slice(start).indexOf(' Date: Wed, 18 Dec 2024 19:38:20 +0100 Subject: [PATCH 2/3] Simplify test setup --- lib/modules/manager/maven/update.spec.ts | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/lib/modules/manager/maven/update.spec.ts b/lib/modules/manager/maven/update.spec.ts index 1b82a9b47647c3..91b06eac3e2bdc 100644 --- a/lib/modules/manager/maven/update.spec.ts +++ b/lib/modules/manager/maven/update.spec.ts @@ -1,4 +1,5 @@ // TODO #22198 +import { codeBlock } from 'common-tags'; import { XmlDocument } from 'xmldoc'; import { Fixtures } from '../../../../test/fixtures'; import { bumpPackageVersion, updateDependency } from './update'; @@ -84,16 +85,24 @@ describe('modules/manager/maven/update', () => { it('should do replacement if version is first', () => { const res = updateDependency({ - fileContent: - simpleContent.slice(0, 814) + - simpleContent.slice(890, 923) + - simpleContent.slice(814, 890) + - simpleContent.slice(923), + fileContent: codeBlock` + + + + + 0.0.1 + foo + org.example + + + + + `, upgrade: { updateType: 'replacement', depName: 'org.example:foo', currentValue: '0.0.1', - fileReplacePosition: 829, + fileReplacePosition: 132, newName: 'org.example.new:bar', newValue: '0.0.1', }, From 7242078917fa7fff7e86030b6202722d1a1d57a8 Mon Sep 17 00:00:00 2001 From: Jonas Rutishauser Date: Sun, 5 Jan 2025 18:57:37 +0100 Subject: [PATCH 3/3] Apply review suggestions --- lib/modules/manager/maven/update.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/modules/manager/maven/update.ts b/lib/modules/manager/maven/update.ts index d61de975f22402..1c88b45e4b0208 100644 --- a/lib/modules/manager/maven/update.ts +++ b/lib/modules/manager/maven/update.ts @@ -185,8 +185,8 @@ function updateValue( newValue: string, ): string { const elementStart = content.indexOf('<' + nodeName); - const start = content.slice(elementStart).indexOf('>') + elementStart + 1; - const end = content.slice(start).indexOf('', elementStart) + 1; + const end = content.indexOf('