Repository dudup'ing

The gradle-versions-plugin tries to aggregate all repositories before searching for dependency updates. This was done because originally it used a detached configuration to perform the resolution where the dependency version was set to a latest query. The current version modifies a copy of the original configuration, so this aggregation is no longer necessary.

It turns out the aggregation is error prone due to RepositoryHandler determining uniqueness based on the repository’s name. If duplicate repositories are added without an explicit name then both are listed and redundant queries are issued. If different repositories are added with conflicting names, e.g. maven { name = ... url = ... }, then only the first is added. Repositories themselves do not have an equality definition.

It appears that there are 3 options,

  1. Perform no aggregation and resolve each configuration using the repositories associated with it. This has the benefit of not using unnecessary repositories (e.g. plugin repository for compile scoped dependencies) with the cavet of a smaller scanning radius.
  2. Attempt to infer equality by inspecting the repository’s configuration (may be error prone)
  3. Allow duplicates (slower resolution)

What is the Gradle teams advice?

Duplicate names shouldn’t be the default. If two maven repositories are added one should be named “maven1” and one should be named “maven2” based on what I see in the gradle codebase at https://github.com/gradle/gradle/blob/master/subprojects/core/src/main/groovy/org/gradle/api/internal/artifacts/DefaultArtifactRepositoryContainer.java#L86-114

Can you create a small reproducible example that demos your problem?

cheers,
René

buildscript {
  repositories {
    maven { url = 'https://jcenter.bintray.com/' }
  }
}

repositories {
  maven { url = 'https://repo1.maven.org/maven2/' }
}

def repos = project.allprojects.collectMany { Project proj ->
  (proj.repositories + proj.buildscript.repositories)
}

println '\nAdd to existing set'
repos.each { project.repositories.add(it) }
project.repositories.each { println it.name + ': ' + it.url }

println '\nClear and add'
project.repositories.clear()
project.repositories.addAll(repos)
project.repositories.each { println it.name + ': ' + it.url }
$ gradle

Add to existing set
maven: https://repo1.maven.org/maven2/

Clear and add
maven: https://repo1.maven.org/maven2/
maven: https://jcenter.bintray.com/

It turns out that add and addAll result in different behavior.

If you change both to the same url then the addAll has duplicates (name and url).

We could easily solve this, if Gradle offered a way to check repository instances for equality (ignoring the name property of course). We could do that in the plugin manually, but I think the right place to do that would be inside Gradle itself. A plugin should not need to know that for example mavenCentral() and maven { url 'https://repo1.maven.org/maven2/'} are equal.

René, please advise based on the provided sample. The differing behavior of add and addAll should be fixed at a minimum.