Gradle-duplicates-plugin

From Evgeny Goldin

Jump to: navigation, search

Contents

Introduction

This plugin locates duplicate libraries in Gradle configurations. Duplicate libraries have different coordinates (group or name) but contain an identically named classes, i.e., classes with identical fully qualified names.


For example, configurations below contain a number of legal Gradle dependencies. Yet, some of them are duplicates:


dependencies {
    compile     'org.springframework:spring-core:3.0.5.RELEASE',
                'org.springframework:spring:2.5.6',
                'commons-beanutils:commons-beanutils:1.8.3',
                'commons-collections:commons-collections:3.2.1'
    testCompile 'org.hamcrest:hamcrest-core:1.2',
                'junit:junit:4.8.2'
}


  • "spring-core" is a subset of "spring"
  • "commons-beanutils" repacks some of "commons-collections" classes


One source of possible duplicates are changes done to library coordinates in Maven repositories, like in Spring example above. When libraries evolve, migrate, grow up and split up they may start naming their artifacts differently. And then having an old and new version of the same library in Gradle configuration causes a duplicate problem.

While developers normally don't add duplicate libraries deliberately, this may still happen due to transitive dependencies brought by another project. Situations when outdated versions of Spring or Apache projects "leak" through transitive dependencies are not uncommon, especially when dependencies are not managed tightly. Once those duplicates found, one should normally exclude an older version from configuration.

Another possible source of duplicate classes in the same configuration are repacking portions of one library in another library, as demonstrated by JUnit and Commons BeanUtils. I believe it's a terrible thing to do and have no simple advice for how to overcome situations when eliminating duplicates is absolutely necessary but both libraries are required. One available option is to remove duplicate classes from offending library manually and deploy new artifact under a different name.


Example

apply plugin: 'groovy'
apply plugin: 'duplicates'
 
buildscript {
    repositories { jcenter() }
    dependencies { classpath 'com.github.goldin.plugins.gradle:duplicates:0.3' }
}
 
repositories { jcenter() }
duplicates   { configurations = [ 'compile', 'testCompile' ] }
 
dependencies {
    compile     'org.springframework:spring-core:3.0.5.RELEASE',
                'org.springframework:spring:2.5.6',
                'commons-beanutils:commons-beanutils:1.8.3',
                'commons-collections:commons-collections:3.2.1'
    testCompile 'org.hamcrest:hamcrest-core:1.2',
                'junit:junit:4.8.2'
}


$ gradle -q duplicates
 
FAILURE: Build failed with an exception.
 
* What went wrong:
Execution failed for task ':duplicates'.
>
  Configuration [compile] - duplicates found in:
  -=-= [org.springframework:spring-core:3.0.5.RELEASE, org.springframework:spring:2.5.6] =-=-
  -=-= [org.springframework:spring:2.5.6, org.springframework:spring-asm:3.0.5.RELEASE] =-=-
  -=-= [commons-beanutils:commons-beanutils:1.8.3, commons-collections:commons-collections:3.2.1] =-=-
 
  Configuration [testCompile] - duplicates found in:
  -=-= [org.springframework:spring-core:3.0.5.RELEASE, org.springframework:spring:2.5.6] =-=-
  -=-= [org.springframework:spring:2.5.6, org.springframework:spring-asm:3.0.5.RELEASE] =-=-
  -=-= [commons-beanutils:commons-beanutils:1.8.3, commons-collections:commons-collections:3.2.1] =-=-
  -=-= [org.hamcrest:hamcrest-core:1.2, junit:junit:4.8.2] =-=-


When "verbose" is true all duplicate classes are printed:


$ gradle -q duplicates
 
FAILURE: Build failed with an exception.
 
* What went wrong:
Execution failed for task ':duplicates'.
>
  Configuration [compile] - duplicates found in:
  -=-= [org.springframework:spring-core:3.0.5.RELEASE, org.springframework:spring:2.5.6] =-=-
   --- [org.springframework.core.AliasRegistry]
   --- [org.springframework.core.AttributeAccessor]
   --- [org.springframework.core.AttributeAccessorSupport]
   ...
  -=-= [org.springframework:spring:2.5.6, org.springframework:spring-asm:3.0.5.RELEASE] =-=-
   --- [org.springframework.asm.AnnotationVisitor]
   --- [org.springframework.asm.AnnotationWriter]
   --- [org.springframework.asm.Attribute]
   ...
  -=-= [commons-beanutils:commons-beanutils:1.8.3, commons-collections:commons-collections:3.2.1] =-=-
   --- [org.apache.commons.collections.ArrayStack]
   --- [org.apache.commons.collections.Buffer]
   --- [org.apache.commons.collections.BufferUnderflowException]
   ...
 
  Configuration [testCompile] - duplicates found in:
  -=-= [org.springframework:spring-core:3.0.5.RELEASE, org.springframework:spring:2.5.6] =-=-
   --- [org.springframework.core.AliasRegistry]
   --- [org.springframework.core.AttributeAccessor]
   --- [org.springframework.core.AttributeAccessorSupport]
   ...
  -=-= [org.springframework:spring:2.5.6, org.springframework:spring-asm:3.0.5.RELEASE] =-=-
   --- [org.springframework.asm.AnnotationVisitor]
   --- [org.springframework.asm.AnnotationWriter]
   ...
  -=-= [commons-beanutils:commons-beanutils:1.8.3, commons-collections:commons-collections:3.2.1] =-=-
   --- [org.apache.commons.collections.ArrayStack]
   --- [org.apache.commons.collections.Buffer]
   ...
  -=-= [org.hamcrest:hamcrest-core:1.2, junit:junit:4.8.2] =-=-
   --- [org.hamcrest.BaseDescription]
   --- [org.hamcrest.BaseMatcher]
   --- [org.hamcrest.CoreMatchers]
   ...


Details

Tasks
  • 'duplicates' - finds duplicate classes in project configurations
Source Code
License
GroovyDoc
Tests
Issue Tracker
Build Server
Repositories,
Coordinates
buildscript {
    repositories { jcenter() }
    dependencies { classpath 'com.github.goldin.plugins.gradle:duplicates:0.3' }
}


duplicates { .. } extension properties


Name Type Default value Description
configurations List<String> null List of configurations to test. All configurations are tested if list is null or empty.
fail boolean true Whether build should fail when duplicate libraries are found.
verbose boolean false Whether all duplicate classes should be printed.
Personal tools