Skip to content

Commit

Permalink
Merge pull request #2 from rspieldenner/master
Browse files Browse the repository at this point in the history
Move to gradle 2.13 for an internal release
  • Loading branch information
rspieldenner authored Mar 16, 2017
2 parents 9deff88 + 57ce765 commit c8f0aea
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 70 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
0.2.0 / 2017-03-15
==================

* Move to gradle 2.13

0.1.0 / 2017-03-13
==================

Expand Down
8 changes: 7 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,14 @@ contacts {
}
}

configurations.all {
resolutionStrategy {
force "com.netflix.nebula:nebula-test:4.4.2"
}
}

dependencies {
testCompile "com.netflix.nebula:nebula-test:5.+"
testCompile "com.netflix.nebula:nebula-test:4.4.2"
}

description = "A base plugin to improve dependency insight and handle all dependency applies"
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.4.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-2.13-bin.zip
Original file line number Diff line number Diff line change
Expand Up @@ -16,96 +16,150 @@
package com.netflix.nebula.dependencybase.tasks

import com.netflix.nebula.dependencybase.DependencyManagement
import org.gradle.api.Action
import org.gradle.api.DefaultTask
import org.gradle.api.InvalidUserDataException
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.component.ModuleComponentIdentifier
import org.gradle.api.artifacts.result.DependencyResult
import org.gradle.api.artifacts.result.ResolutionResult
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.VersionComparator
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.VersionSelectorScheme
import org.gradle.api.internal.tasks.options.Option
import org.gradle.api.specs.Spec
import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.diagnostics.DependencyInsightReportTask
import org.gradle.api.tasks.diagnostics.internal.dsl.DependencyResultSpecNotationConverter
import org.gradle.api.tasks.diagnostics.internal.graph.DependencyGraphRenderer
import org.gradle.api.tasks.diagnostics.internal.graph.LegendRenderer
import org.gradle.api.tasks.diagnostics.internal.graph.NodeRenderer
import org.gradle.api.tasks.diagnostics.internal.graph.nodes.RenderableDependency
import org.gradle.api.tasks.diagnostics.internal.insight.DependencyInsightReporter
import org.gradle.internal.graph.GraphRenderer
import org.gradle.internal.logging.text.StyledTextOutput
import java.util.*
import org.gradle.logging.StyledTextOutput
import org.gradle.logging.StyledTextOutputFactory
import javax.inject.Inject

/**
* Mostly a copy of DependencyInsightReportTask from gradle/gradle which is under a Apache 2.0 license. Modified to Kotlin.
* Modified to provide more information on why a dependenecy version was selected.
*/
open class NebulaDependencyInsightReportTask : DependencyInsightReportTask() {
open class NebulaDependencyInsightReportTask : DefaultTask() {
var reasonLookup: DependencyManagement? = null

/**
* Configuration to look the dependency in
*/
var configuration: Configuration? = null

/**
* Selects the dependency (or dependencies if multiple matches found) to show the report for.
*/
var dependencySpec: Spec<DependencyResult>? = null

@Inject
open fun getTextOutputFactory(): StyledTextOutputFactory {
throw UnsupportedOperationException()
}

@Inject
open fun getVersionSelectorScheme(): VersionSelectorScheme {
throw UnsupportedOperationException()
}

@Inject
open fun getVersionComparator(): VersionComparator {
throw UnsupportedOperationException();
}

/**
* Configures the dependency to show the report for.
* Multiple notation formats are supported: Strings, instances of {@link Spec}
* and groovy closures. Spec and closure receive {@link DependencyResult} as parameter.
* Examples of String notation: 'org.slf4j:slf4j-api', 'slf4j-api', or simply: 'slf4j'.
* The input may potentially match multiple dependencies.
* See also {@link DependencyInsightReportTask#setDependencySpec(Spec)}
* <p>
* This method is exposed to the command line interface. Example usage:
* <pre>gradle dependencyInsight --dependency slf4j</pre>
*
* @param dependencyInsightNotation
*/
@Option(option = "dependency", description = "Shows the details of given dependency.")
fun setDependencySpec(dependencyInsightNotation: Any) {
val parser = DependencyResultSpecNotationConverter.parser()
this.dependencySpec = parser.parseNotation(dependencyInsightNotation)
}

/**
* Sets the configuration (via name) to look the dependency in.
* <p>
* This method is exposed to the command line interface. Example usage:
* <pre>gradle dependencyInsight --configuration runtime --dependency slf4j</pre>
*
* @param configurationName
*/
@Option(option = "configuration", description = "Looks for the dependency in given configuration.")
fun setConfiguration(configurationName: String) {
this.configuration = project.configurations.getByName(configurationName)
}

@TaskAction
override fun report() {
val configuration = getConfiguration() ?: throw InvalidUserDataException("Dependency insight report cannot be generated because the input configuration was not specified. "
+ "\nIt can be specified from the command line, e.g: '" + path + " --configuration someConf --dependency someDep'")
fun report() {
val conf = configuration ?:
throw InvalidUserDataException("Dependency insight report cannot be generated because the input configuration was not specified. "
+ "\nIt can be specified from the command line, e.g: '$path --configuration someConf --dependency someDep'")

if (dependencySpec == null) {
val depSpec = dependencySpec ?:
throw InvalidUserDataException("Dependency insight report cannot be generated because the dependency to show was not specified."
+ "\nIt can be specified from the command line, e.g: '" + path + " --dependency someDep'")
}

+ "\nIt can be specified from the command line, e.g: '$path --dependency someDep'")

val output = textOutputFactory.create(javaClass)
val renderer = GraphRenderer(output)
val output: StyledTextOutput = getTextOutputFactory().create(javaClass)
val renderer: GraphRenderer = GraphRenderer(output)

val result = configuration!!.getIncoming().getResolutionResult()
val result: ResolutionResult = conf.incoming.resolutionResult;

val selectedDependencies = LinkedHashSet<DependencyResult>()
result.allDependencies(Action<DependencyResult> { dependencyResult ->
if (dependencySpec.isSatisfiedBy(dependencyResult)) {
selectedDependencies.add(dependencyResult)
val selectedDependencies: MutableSet<DependencyResult> = mutableSetOf()
result.allDependencies {
if (depSpec.isSatisfiedBy(it)) {
selectedDependencies.add(it)
}
})
}

if (selectedDependencies.isEmpty()) {
output.println("No dependencies matching given input were found in " + configuration.toString())
output.println("No dependencies matching given input were found in ${conf}")
return
}

val sortedDeps = DependencyInsightReporter().prepare(selectedDependencies, getVersionSelectorScheme(), getVersionComparator())

val nodeRenderer = NodeRenderer { target, node, alreadyRendered ->
val leaf = node.children.isEmpty()
target.text(if (leaf) configuration!!.getName() else node.name)
target.text(if (leaf) conf.name else node.name)
if (alreadyRendered && !leaf) {
target.withStyle(StyledTextOutput.Style.Info).text(" (*)")
}
}

val legendRenderer = LegendRenderer(output)
val dependencyGraphRenderer = DependencyGraphRenderer(renderer, nodeRenderer, legendRenderer)
val dependencyGraphRenderer = DependencyGraphRenderer(renderer, nodeRenderer)

var i = 1
for (dependency in sortedDeps) {
renderer.visit({ out ->
out.withStyle(StyledTextOutput.Style.Identifier).text(dependency.name)

renderer.visit( { out ->
out.withStyle(StyledTextOutput.Style.Identifier).text(dependency.name);
if (dependency.description?.isNotEmpty()?:false) {
out.withStyle(StyledTextOutput.Style.Description).text(" (${reasonLookup?.getReason(configuration.name, calculateCoordinateFromId(dependency.id))})")
out.withStyle(StyledTextOutput.Style.Description).text(" (${reasonLookup?.getReason(conf.name, calculateCoordinateFromId(dependency.id))})")
}

when (dependency.resolutionState) {
RenderableDependency.ResolutionState.FAILED -> out.withStyle(StyledTextOutput.Style.Failure).text(" FAILED")
RenderableDependency.ResolutionState.RESOLVED -> {
}
RenderableDependency.ResolutionState.UNRESOLVED -> out.withStyle(StyledTextOutput.Style.Failure).text(" (n)")
if (!dependency.isResolvable) {
out.withStyle(StyledTextOutput.Style.Failure).text(" FAILED")
}
}, true)
}, true);
dependencyGraphRenderer.render(dependency)
val last = i++ == sortedDeps.size
if (!last) {
output.println()
}

}

output.println()
output.println(reasonLookup?.getGlobalMessages())
legendRenderer.printLegend()
dependencyGraphRenderer.printLegend()
}

fun calculateCoordinateFromId(id: Any): String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@
*/
package com.netflix.nebula.dependencybase

import nebula.test.IntegrationTestKitSpec
import nebula.test.IntegrationSpec
import nebula.test.dependencies.DependencyGraphBuilder
import nebula.test.dependencies.GradleDependencyGenerator

class RecommendationDependencyBasePluginIntegrationSpec extends IntegrationTestKitSpec {
class RecommendationDependencyBasePluginIntegrationSpec extends IntegrationSpec {
def "recommend versions of dependencies are explained in dependencyInsightEnhanced"() {
given:
setup1Dependency()
Expand All @@ -28,7 +28,9 @@ class RecommendationDependencyBasePluginIntegrationSpec extends IntegrationTestK
def results = runTasks("dependencyInsightEnhanced", "--configuration", "compileClasspath", "--dependency", "foo")

then:
results.output.contains "test.nebula:foo:1.0.0 (recommend 1.0.0 via NebulaTest)"
println results?.standardError
println results?.standardOutput
results.standardOutput.contains "test.nebula:foo:1.0.0 (recommend 1.0.0 via NebulaTest)"
}

def "forces reported"() {
Expand All @@ -39,7 +41,7 @@ class RecommendationDependencyBasePluginIntegrationSpec extends IntegrationTestK
def results = runTasks("dependencyInsightEnhanced", "--configuration", "compileClasspath", "--dependency", "foo")

then:
results.output.contains "test.nebula:foo:1.0.0 (forced, recommend 2.0.0 via NebulaTest)"
results.standardOutput.contains "test.nebula:foo:1.0.0 (forced, recommend 2.0.0 via NebulaTest)"
}

def "multiproject sees recommendations"() {
Expand All @@ -50,19 +52,19 @@ class RecommendationDependencyBasePluginIntegrationSpec extends IntegrationTestK
def onefoo = runTasks(":one:dependencyInsightEnhanced", "--configuration", "compileClasspath", "--dependency", "foo")

then:
onefoo.output.contains "test.nebula:foo:1.0.0 (recommend 1.0.0 via NebulaTest)"
onefoo.standardOutput.contains "test.nebula:foo:1.0.0 (recommend 1.0.0 via NebulaTest)"

when:
def twofoo = runTasks(":two:dependencyInsightEnhanced", "--configuration", "compileClasspath", "--dependency", "foo")

then:
twofoo.output.contains "test.nebula:foo:1.0.0 (recommend 1.0.0 via NebulaTest)"
twofoo.standardOutput.contains "test.nebula:foo:1.0.0 (recommend 1.0.0 via NebulaTest)"

when:
def twobar = runTasks(":two:dependencyInsightEnhanced", "--configuration", "compileClasspath", "--dependency", "bar")

then:
twobar.output.contains "test.nebula:bar:2.0.0 (recommend 2.0.0 via NebulaTest)"
twobar.standardOutput.contains "test.nebula:bar:2.0.0 (recommend 2.0.0 via NebulaTest)"
}

def "detect complete substitute foo to bar and give insight"() {
Expand All @@ -74,10 +76,11 @@ class RecommendationDependencyBasePluginIntegrationSpec extends IntegrationTestK
generator.generateTestMavenRepo()
buildFile << """\
plugins {
id "nebula.dependency-base"
id "java"
}
apply plugin: "nebula.dependency-base"
repositories {
${generator.mavenRepositoryBlock}
}
Expand All @@ -95,15 +98,15 @@ class RecommendationDependencyBasePluginIntegrationSpec extends IntegrationTestK
project.nebulaDependencyBase.addReason("compileClasspath", "test.nebula:bar", "possible replacement of test.nebula:foo", "test")
dependencies {
implementation "test.nebula:foo:1.0.0"
compile "test.nebula:foo:1.0.0"
}
""".stripIndent()

when:
def results = runTasks("dependencyInsightEnhanced", "--configuration", "compileClasspath", "--dependency", "foo")

then:
results.output.contains "test.nebula:bar:2.0.0 (possible replacement of test.nebula:foo)"
results.standardOutput.contains "test.nebula:bar:2.0.0 (possible replacement of test.nebula:foo)"
}

def setup1Dependency() {
Expand All @@ -113,10 +116,11 @@ class RecommendationDependencyBasePluginIntegrationSpec extends IntegrationTestK

buildFile << """\
plugins {
id "nebula.dependency-base"
id "java"
}
apply plugin: "nebula.dependency-base"
repositories {
${generator.mavenRepositoryBlock}
}
Expand All @@ -134,7 +138,7 @@ class RecommendationDependencyBasePluginIntegrationSpec extends IntegrationTestK
project.nebulaDependencyBase.addRecommendation("compileClasspath", "test.nebula:foo", "1.0.0", "NebulaTest", "test")
dependencies {
implementation "test.nebula:foo"
compile "test.nebula:foo"
}
""".stripIndent()
}
Expand All @@ -149,9 +153,9 @@ class RecommendationDependencyBasePluginIntegrationSpec extends IntegrationTestK

buildFile << """\
plugins {
id "nebula.dependency-base"
id "java"
}
apply plugin: "nebula.dependency-base"
repositories {
${generator.mavenRepositoryBlock}
Expand All @@ -166,13 +170,12 @@ class RecommendationDependencyBasePluginIntegrationSpec extends IntegrationTestK
}
dependencies {
implementation "test.nebula:foo"
compile "test.nebula:foo"
}
""".stripIndent()
}

def setupMultiproject() {
keepFiles = true
def graph = new DependencyGraphBuilder()
.addModule("test.nebula:foo:1.0.0")
.addModule("test.nebula:bar:2.0.0")
Expand All @@ -181,9 +184,7 @@ class RecommendationDependencyBasePluginIntegrationSpec extends IntegrationTestK
generator.generateTestMavenRepo()

buildFile << """\
plugins {
id "nebula.dependency-base"
}
apply plugin: "nebula.dependency-base"
subprojects {
apply plugin: "nebula.dependency-base"
Expand Down
Loading

0 comments on commit c8f0aea

Please sign in to comment.