Skip to content

Commit 4e19c37

Browse files
committed
Add collision report as output
Having at least one output also ensures that task is considered up-to-date on second run.
1 parent 9f3cc28 commit 4e19c37

File tree

2 files changed

+48
-17
lines changed

2 files changed

+48
-17
lines changed

src/main/kotlin/io/fuchs/gradle/collisiondetector/DetectCollisionsTask.kt

+28-17
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@ import org.gradle.api.DefaultTask
55
import org.gradle.api.GradleException
66
import org.gradle.api.file.ArchiveOperations
77
import org.gradle.api.file.ConfigurableFileCollection
8+
import org.gradle.api.file.RegularFileProperty
89
import org.gradle.api.tasks.CacheableTask
910
import org.gradle.api.tasks.Classpath
10-
import org.gradle.api.tasks.Input
1111
import org.gradle.api.tasks.InputFiles
12+
import org.gradle.api.tasks.Internal
13+
import org.gradle.api.tasks.OutputFile
1214
import org.gradle.api.tasks.TaskAction
1315
import org.gradle.api.tasks.TaskExecutionException
1416
import org.gradle.api.tasks.util.PatternSet
@@ -25,11 +27,18 @@ abstract class DetectCollisionsTask : DefaultTask() {
2527
@get:Classpath
2628
abstract val configurations: ConfigurableFileCollection
2729

28-
@get:Input
30+
@get:Inject
31+
abstract val archiveOperations: ArchiveOperations
32+
33+
@get:OutputFile
34+
abstract val reportFile: RegularFileProperty
35+
36+
@get:Internal
2937
val collisionFilter: PatternSet = PatternSet()
3038

31-
@get:Inject
32-
protected abstract val archiveOperations: ArchiveOperations
39+
init {
40+
reportFile.convention(project.layout.buildDirectory.file("reports/classpath-collisions.txt"))
41+
}
3342

3443
fun collisionFilter(filterConfig: Action<PatternSet>) {
3544
filterConfig.execute(collisionFilter)
@@ -38,31 +47,33 @@ abstract class DetectCollisionsTask : DefaultTask() {
3847
@TaskAction
3948
fun detectCollisions() {
4049
val collisionDetector = CollisionDetector(findClasspathArtifacts())
41-
4250
val collisions = collisionDetector.detectCollisions()
4351

52+
val resolvedReportFile = reportFile.get().asFile
4453
if (collisions.isNotEmpty()) {
45-
collisions.forEach { logCollisionMessage(it) }
54+
val collisionMessages = collisions.map { toCollisionMessage(it) }
55+
collisionMessages.forEach { logger.error(it) }
56+
resolvedReportFile.writeText(collisionMessages.joinToString("\n"))
4657
throw TaskExecutionException(this, GradleException("Detected unexpected collisions!"))
58+
} else {
59+
resolvedReportFile.writeText("No collisions detected")
4760
}
4861
}
4962

50-
private fun logCollisionMessage(collision: ClasspathCollision) {
63+
private fun toCollisionMessage(collision: ClasspathCollision): String {
5164
val name = collision.classpathEntry
5265
val collisionJars = collision.containingArtifacts
53-
.map { it.artifact }
54-
.sorted()
55-
.joinToString("\n")
56-
.prependIndent(" ")
57-
58-
val message = "Collision detected! Entry $name present in following JARs:\n${collisionJars}"
59-
logger.error(message)
66+
.map { it.artifact }
67+
.sorted()
68+
.joinToString("\n")
69+
.prependIndent(" ")
70+
return "Collision detected! Entry $name present in following JARs:\n${collisionJars}"
6071
}
6172

6273
private fun findClasspathArtifacts(): List<ClasspathArtifact> {
6374
return configurations.files
64-
.filter { it.name.endsWith(".jar") }
65-
.map { toClassPathArtifact(it) }
75+
.filter { it.name.endsWith(".jar") }
76+
.map { toClassPathArtifact(it) }
6677
}
6778

6879
private fun toClassPathArtifact(file: File): ClasspathArtifact {
@@ -72,4 +83,4 @@ abstract class DetectCollisionsTask : DefaultTask() {
7283
}
7384

7485

75-
}
86+
}

src/test/kotlin/io/fuchs/gradle/collisiondetector/testkit/CollisionDetectorPluginTest.kt

+20
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,26 @@ class CollisionDetectorPluginTest {
5555
assertEquals(TaskOutcome.SUCCESS, detectCollisionsTask?.outcome)
5656
}
5757

58+
fun `task is up-to-date in second execution`(@TempDir tempDir: Path) {
59+
copyBuildFileToTempDir("apply_plugin_only.gradle", tempDir)
60+
61+
val buildResult1 = GradleRunner.create()
62+
.withProjectDir(tempDir.toFile())
63+
.withPluginClasspath()
64+
.withArguments(":detectCollisions")
65+
.build()
66+
val buildResult2 = GradleRunner.create()
67+
.withProjectDir(tempDir.toFile())
68+
.withPluginClasspath()
69+
.withArguments(":detectCollisions")
70+
.build()
71+
72+
val detectCollisionsTask1 = buildResult1.task(":detectCollisions")
73+
assertEquals(TaskOutcome.SUCCESS, detectCollisionsTask1?.outcome)
74+
val detectCollisionsTask2 = buildResult2.task(":detectCollisions")
75+
assertEquals(TaskOutcome.UP_TO_DATE, detectCollisionsTask2?.outcome)
76+
}
77+
5878
@Test
5979
fun `detects collisions and fails`(@TempDir tempDir: Path) {
6080
copyBuildFileToTempDir("found_collisions.gradle", tempDir)

0 commit comments

Comments
 (0)