diff --git a/README.md b/README.md index c7cf84f0..8a905ad2 100644 --- a/README.md +++ b/README.md @@ -160,6 +160,9 @@ This is effectively just a more concise version of `dependencyInsight`: ./gradlew dependencyInsight --configuration unifiedClasspath --dependency jackson-databind ``` +You can check multiple dependencies at once by passing multiple comma-delimited hash values, e.g. +`./gradlew why --hash a60c3ce8,400d4d2a`. + ## ./gradlew checkUnusedConstraints `checkUnusedConstraints` prevents unnecessary constraints from accruing in your `versions.props` file. Run `./gradlew checkUnusedConstraints --fix` to automatically remove any unused constraints from your props file. diff --git a/changelog/@unreleased/pr-916.v2.yml b/changelog/@unreleased/pr-916.v2.yml new file mode 100644 index 00000000..bb7e4f6b --- /dev/null +++ b/changelog/@unreleased/pr-916.v2.yml @@ -0,0 +1,6 @@ +type: improvement +improvement: + description: The `--hash` argument of the `why` task now accepts multiple, comma-separated + hashes. + links: + - https://github.com/palantir/gradle-consistent-versions/pull/916 diff --git a/src/main/java/com/palantir/gradle/versions/WhyDependencyTask.java b/src/main/java/com/palantir/gradle/versions/WhyDependencyTask.java index 3d33a4dd..5793d38f 100644 --- a/src/main/java/com/palantir/gradle/versions/WhyDependencyTask.java +++ b/src/main/java/com/palantir/gradle/versions/WhyDependencyTask.java @@ -16,6 +16,7 @@ package com.palantir.gradle.versions; +import com.google.common.base.Splitter; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import com.google.common.collect.Multimaps; @@ -25,8 +26,10 @@ import com.palantir.gradle.versions.lockstate.Line; import com.palantir.gradle.versions.lockstate.LockStates; import java.nio.file.Path; +import java.util.LinkedHashSet; import java.util.Objects; import java.util.Optional; +import java.util.Set; import java.util.function.Function; import java.util.stream.Stream; import org.gradle.api.DefaultTask; @@ -78,23 +81,27 @@ public final void taskAction() { "./gradlew why requires a '--hash ' from versions.lock" + example.orElse("")); } - lineByHash.get(hashOption.get()).forEach(line -> { - ModuleVersionIdentifier key = MyModuleVersionIdentifier.of(line.group(), line.name(), line.version()); + Set hashes = new LinkedHashSet<>(Splitter.on(",").splitToList(hashOption.get())); - Optional entry = Stream.of( - fullLockState.get().productionDeps(), - fullLockState.get().testDeps()) - .map(state -> state.get(key)) - .filter(Objects::nonNull) - .findFirst(); - Dependents dependents = - entry.orElseThrow(() -> new NullPointerException("Unable to find group/name in fullLockState")); + for (String hash : hashes) { + lineByHash.get(hash).forEach(line -> { + ModuleVersionIdentifier key = MyModuleVersionIdentifier.of(line.group(), line.name(), line.version()); + + Optional entry = Stream.of( + fullLockState.get().productionDeps(), + fullLockState.get().testDeps()) + .map(state -> state.get(key)) + .filter(Objects::nonNull) + .findFirst(); + Dependents dependents = + entry.orElseThrow(() -> new NullPointerException("Unable to find group/name in fullLockState")); - getLogger().lifecycle("{}", key); - LockStates.prettyPrintConstraints(dependents).forEach(pretty -> { - getLogger().lifecycle("\t{}", pretty); + getLogger().lifecycle("{}", key); + LockStates.prettyPrintConstraints(dependents).forEach(pretty -> { + getLogger().lifecycle("\t{}", pretty); + }); + getLogger().lifecycle(""); }); - getLogger().lifecycle(""); - }); + } } } diff --git a/src/test/groovy/com/palantir/gradle/versions/VersionsLockPluginIntegrationSpec.groovy b/src/test/groovy/com/palantir/gradle/versions/VersionsLockPluginIntegrationSpec.groovy index 7fa76289..b5349ac3 100644 --- a/src/test/groovy/com/palantir/gradle/versions/VersionsLockPluginIntegrationSpec.groovy +++ b/src/test/groovy/com/palantir/gradle/versions/VersionsLockPluginIntegrationSpec.groovy @@ -40,7 +40,9 @@ class VersionsLockPluginIntegrationSpec extends IntegrationSpec { "org.slf4j:slf4j-api:1.7.24", "org.slf4j:slf4j-api:1.7.25", "junit:junit:4.10", - "org:test-dep-that-logs:1.0 -> org.slf4j:slf4j-api:1.7.11" + "org:test-dep-that-logs:1.0 -> org.slf4j:slf4j-api:1.7.11", + "org:another-transitive-dependency:3.2.1", + "org:another-direct-dependency:1.2.3 -> org:another-transitive-dependency:3.2.1", ) makePlatformPom(mavenRepo, "org", "platform", "1.0") @@ -534,6 +536,32 @@ class VersionsLockPluginIntegrationSpec extends IntegrationSpec { gradleVersionNumber << GRADLE_VERSIONS } + def "#gradleVersionNumber: why with comma-delimited multiple hashes works"() { + setup: + gradleVersion = gradleVersionNumber + + buildFile << ''' + apply plugin: 'java' + dependencies { + implementation 'ch.qos.logback:logback-classic:1.2.3' // brings in slf4j-api 1.7.25 + implementation 'org:another-direct-dependency:1.2.3' // brings in org:another-transitive-dependency:3.2.1 + } + '''.stripIndent() + + when: + runTasks('--write-locks') + + then: + def result = runTasks('why', '--hash', '400d4d2a,050d6518') // both transitive dependencies + result.output.contains('org.slf4j:slf4j-api:1.7.25') + result.output.contains('ch.qos.logback:logback-classic -> 1.7.25') + result.output.contains('org:another-transitive-dependency:3.2.1') + result.output.contains('org:another-direct-dependency -> 3.2.1') + + where: + gradleVersionNumber << GRADLE_VERSIONS + } + def '#gradleVersionNumber: does not fail if subproject evaluated later applies base plugin in own build file'() { setup: gradleVersion = gradleVersionNumber