diff --git a/lib/manager/maven/extract.js b/lib/manager/maven/extract.js index 36ad0dcc097d461e22e6d13de16305162c043d64..39cafb16abc4684a6bf6ae1385096002214dd758 100644 --- a/lib/manager/maven/extract.js +++ b/lib/manager/maven/extract.js @@ -27,24 +27,17 @@ function depFromNode(node) { const currentValue = node.valueWithPath('version'); if (groupId && artifactId && currentValue) { const depName = `${groupId}:${artifactId}`; - const result = { + const versionNode = node.descendantWithPath('version'); + const fileReplacePosition = versionNode.position; + const datasource = 'maven'; + const registryUrls = [DEFAULT_MAVEN_REPO]; + return { + datasource, depName, currentValue, + fileReplacePosition, + registryUrls, }; - if (containsPlaceholder(depName)) { - result.skipReason = 'name-placeholder'; - } else if (containsPlaceholder(currentValue)) { - result.skipReason = 'version-placeholder'; - } else if (!isVersion(currentValue)) { - result.skipReason = 'not-a-version'; - } else { - const versionNode = node.descendantWithPath('version'); - const offset = '<version>'.length - 1; - result.fileReplacePosition = versionNode.startTagPosition + offset; - result.datasource = 'maven'; - result.registryUrls = [DEFAULT_MAVEN_REPO]; - } - return result; } return null; } @@ -62,6 +55,42 @@ function deepExtract(node, result = [], isRoot = true) { return result; } +function applyProps(dep, props) { + const depName = dep.depName.replace(/\${.*?}/g, substr => { + const propKey = substr.slice(2, -1).trim(); + const propValue = props[propKey]; + return propValue ? propValue.val : substr; + }); + + let fileReplacePosition = dep.fileReplacePosition; + const currentValue = dep.currentValue.replace(/^\${.*?}$/, substr => { + const propKey = substr.slice(2, -1).trim(); + const propValue = props[propKey]; + if (propValue) { + fileReplacePosition = propValue.fileReplacePosition; + return propValue.val; + } + return substr; + }); + + const result = { + ...dep, + depName, + currentValue, + fileReplacePosition, + }; + + if (containsPlaceholder(depName)) { + result.skipReason = 'name-placeholder'; + } else if (containsPlaceholder(currentValue)) { + result.skipReason = 'version-placeholder'; + } else if (!isVersion(currentValue)) { + result.skipReason = 'not-a-version'; + } + + return result; +} + function extractDependencies(raw) { if (!raw) return null; @@ -80,7 +109,22 @@ function extractDependencies(raw) { result.sourceUrl = sourceUrl; } - result.deps = deepExtract(project); + const propsNode = project.childNamed('properties'); + const props = {}; + if (propsNode && propsNode.children) { + for (const propNode of propsNode.children) { + const key = propNode.name; + const val = propNode.val && propNode.val.trim(); + if (key && val) { + const fileReplacePosition = propNode.position; + const usageCount = 0; + props[key] = { val, fileReplacePosition, usageCount }; + } + } + } + + const withProps = dep => applyProps(dep, props); + result.deps = deepExtract(project).map(withProps); const repositories = project.childNamed('repositories'); if (repositories && repositories.children) { diff --git a/test/_fixtures/maven/simple.pom.xml b/test/_fixtures/maven/simple.pom.xml index e11ebf54d43780b1ac4124b60a3f0d5e29e45849..f7b465e90842f04a926c149c66087f891e91f465 100644 --- a/test/_fixtures/maven/simple.pom.xml +++ b/test/_fixtures/maven/simple.pom.xml @@ -23,6 +23,14 @@ <url>http://example.org/</url> </issueManagement> + <properties> + <quuxGroup>org.example</quuxGroup> + <quuxId>quux</quuxId> + <quuxVersion> + 1.2.3.4 + </quuxVersion> + </properties> + <dependencyManagement> <dependencies> <dependency> @@ -83,9 +91,9 @@ <version>0.0.1</version> </dependency> <dependency> - <groupId>org.example</groupId> - <artifactId>quux</artifactId> - <version>${resourceServerVersion}</version> + <groupId>${quuxGroup}</groupId> + <artifactId>${quuxId}</artifactId> + <version>${quuxVersion}</version> </dependency> <dependency> <groupId>org.example</groupId> diff --git a/test/manager/maven/__snapshots__/extract.spec.js.snap b/test/manager/maven/__snapshots__/extract.spec.js.snap index 6a563704d9514e78f25ab3b518cb1516204bf07e..fd50db6d278e0c21b19e1897e92650d4804921d7 100644 --- a/test/manager/maven/__snapshots__/extract.spec.js.snap +++ b/test/manager/maven/__snapshots__/extract.spec.js.snap @@ -18,7 +18,7 @@ Object { "currentValue": "0.0.1", "datasource": "maven", "depName": "org.example:foo", - "fileReplacePosition": 757, + "fileReplacePosition": 905, "registryUrls": Array [ "https://repo.maven.apache.org/maven2", "https://maven.atlassian.com/content/repositories/atlassian-public/", @@ -28,7 +28,7 @@ Object { "currentValue": "1.0.0", "datasource": "maven", "depName": "org.example:bar", - "fileReplacePosition": 905, + "fileReplacePosition": 1053, "registryUrls": Array [ "https://repo.maven.apache.org/maven2", "https://maven.atlassian.com/content/repositories/atlassian-public/", @@ -38,7 +38,7 @@ Object { "currentValue": "1.8.1", "datasource": "maven", "depName": "org.apache.maven.scm:maven-scm-provider-gitexe", - "fileReplacePosition": 1337, + "fileReplacePosition": 1485, "registryUrls": Array [ "https://repo.maven.apache.org/maven2", "https://maven.atlassian.com/content/repositories/atlassian-public/", @@ -46,24 +46,41 @@ Object { }, Object { "currentValue": "0.0.1", + "datasource": "maven", "depName": "org.example:\${artifact-id-placeholder}", + "fileReplacePosition": 2230, + "registryUrls": Array [ + "https://repo.maven.apache.org/maven2", + "https://maven.atlassian.com/content/repositories/atlassian-public/", + ], "skipReason": "name-placeholder", }, Object { "currentValue": "0.0.1", + "datasource": "maven", "depName": "\${group-id-placeholder}:baz", + "fileReplacePosition": 2380, + "registryUrls": Array [ + "https://repo.maven.apache.org/maven2", + "https://maven.atlassian.com/content/repositories/atlassian-public/", + ], "skipReason": "name-placeholder", }, Object { - "currentValue": "\${resourceServerVersion}", + "currentValue": "1.2.3.4", + "datasource": "maven", "depName": "org.example:quux", - "skipReason": "version-placeholder", + "fileReplacePosition": 698, + "registryUrls": Array [ + "https://repo.maven.apache.org/maven2", + "https://maven.atlassian.com/content/repositories/atlassian-public/", + ], }, Object { "currentValue": "1.2.3", "datasource": "maven", "depName": "org.example:quuz", - "fileReplacePosition": 2529, + "fileReplacePosition": 2673, "registryUrls": Array [ "https://repo.maven.apache.org/maven2", "https://maven.atlassian.com/content/repositories/atlassian-public/", @@ -71,19 +88,31 @@ Object { }, Object { "currentValue": "it's not a version", + "datasource": "maven", "depName": "org.example:quuuz", + "fileReplacePosition": 2813, + "registryUrls": Array [ + "https://repo.maven.apache.org/maven2", + "https://maven.atlassian.com/content/repositories/atlassian-public/", + ], "skipReason": "not-a-version", }, Object { "currentValue": "\${profile-placeholder}", + "datasource": "maven", "depName": "org.example:profile-artifact", + "fileReplacePosition": 3086, + "registryUrls": Array [ + "https://repo.maven.apache.org/maven2", + "https://maven.atlassian.com/content/repositories/atlassian-public/", + ], "skipReason": "version-placeholder", }, Object { "currentValue": "2.17", "datasource": "maven", "depName": "org.apache.maven.plugins:maven-checkstyle-plugin", - "fileReplacePosition": 3218, + "fileReplacePosition": 3362, "registryUrls": Array [ "https://repo.maven.apache.org/maven2", "https://maven.atlassian.com/content/repositories/atlassian-public/", diff --git a/test/manager/maven/index.spec.js b/test/manager/maven/index.spec.js index 38b53aba5b8ff59215250c1183b345e73f70cca5..27492179b6fe5acd8e2aad9d7b621b9ff4824efb 100644 --- a/test/manager/maven/index.spec.js +++ b/test/manager/maven/index.spec.js @@ -51,6 +51,19 @@ describe('manager/maven', () => { expect(updatedDep.currentValue).toEqual(newValue); }); + it('should update existing dependency defined via properties', () => { + const finder = ({ depName }) => depName === 'org.example:quux'; + const newValue = '9.9.9.9-final'; + + const { deps } = extractDependencies(pomContent); + const dep = deps.find(finder); + const upgrade = { ...dep, newValue }; + const updatedContent = updateDependency(pomContent, upgrade); + const updatedDep = extractDependencies(updatedContent).deps.find(finder); + + expect(updatedDep.currentValue).toEqual(newValue); + }); + it('should not touch content if new and old versions are equal', () => { const newValue = '1.2.3';