How to override the version comparison mechanism?


(Uladzislau Shalamitski) #1

I have three repositories. The first repository contains version 0.2.0-RELEASE. The second contains 0.2.0-NIGHTLY. And the third contains 0.2.0-LOCAL.

I found in the source code that gradle uses a lexicographical comparison. Gradle downloads version 0.2.0-RELEASE because “RELEASE”.compareTo(“NIGHTLY”) > 0 and “RELEASE”.compareTo(“LOCAL”) > 0

Does anyone know how to override this behavior?


(Lance Java) #2

You could define a custom ResolutionStrategy

configurations.all {
   resolutionStrategy {
      eachDependency { DependencyResolveDetails details ->
         def req = details.requested
         if (req.group == 'foo' && req.version.endsWith('-NIGHTLY') {
            details.useVersion doSomeTransformation(req.version)
         }
      }
   }
}

(Uladzislau Shalamitski) #3

Unfortunately it does not work in my case. I don’t request the version that ends with “-NIGHTLY” or “-RELEASE”. I request the version 0.2.+


(Lance Java) #5

Ah, I thought you had a dependency conflict but you are referring to dynamic dependencies. I think this can be done via a ComponentSelectionRule

resolutionStrategy {
   componentSelection {
      Comparator<ComponentSelection> comparator = new MyFantasticVersionComparator()
      Map<String, Set<ComponentSelection>> grouped = [:]
      all { ComponentSelection selection ->
         String key = "${selection.candidate.group}:${selection.candidate.name}"
         def set = grouped[key]
         if (!set) {
            set = new TreeSet(comparator)
            grouped[key] = set
         }
         set<< selection
      }
      for (Set set : grouped.values()) {
         Iterator<ComponentSelection> iterator = set.iterator()
         for (int i = 0; i < set.size() - 1) {
            iterator.next().reject("Better version available")
         }
      }
   }
}

Cannot resolve dependencies that are resolved by Maven
Best Practice Resolving Version Conflicts within Thirdparty Libraries
Proper way to resolve transitive modules with and without Scala variants
(Tim Natzke) #6

The code above no longer seems to work at least in Gradle 5.0. It seems as though it creates the Map and then goes directly to the for loop, skipping over the section adding to the items to the map. After that it finally processes the all closure statement. No items are ever added to the map.

Is there a better way to do this now? Is there away to override the SPECIAL_MEANINGS map in StaticVersionComparator or a way to provide a different comparator?

Here is what I have in my build.gradle:

configurations.all {
resolutionStrategy {
componentSelection {
Comparator comparator = new MyFantasticVersionComparator()
Map<String, Set> grouped = [:]
all { ComponentSelection selection ->
String key = “{selection.candidate.group}:{selection.candidate.module}”
def set = grouped[key]
if (!set) {
set = new TreeSet(comparator)
grouped[key] = set
}
set<< selection
}
for (Set set : grouped.values()) {
Iterator iterator = set.iterator()
for (int i = 0; i < set.size() - 1; i++) {
iterator.next().reject(“Better version available”)
}
}
}
}
}


(uklance) #7

I’m guessing that the timing has changed slightly meaning the execution of the “all” closure is delayed. I’m guessing that you can tweak it slightly to

resolutionStrategy {
   componentSelection {
      Comparator<ComponentSelection> comparator = new MyFantasticVersionComparator()
      Map<String, Set<ComponentSelection>> grouped = [:]
      all { ComponentSelection selection ->
         String key = "${selection.candidate.group}:${selection.candidate.name}"
         def set = grouped[key]
         if (!set) {
            set = new TreeSet(comparator)
            grouped[key] = set
         }
         set<< selection
      }
      boolean isFirst = true 
      all { ComponentSelection selection ->
         if (isFirst) {
            for (Set set : grouped.values()) {
               Iterator<ComponentSelection> iterator = set.iterator()
               for (int i = 0; i < set.size() - 1) {
                  iterator.next().reject("Better version available")
               }
            }
            isFirst = false    
         } 
      } 
   }
}

(Tim Natzke) #8

Looking at the source code in “DefaultVersionedComponentChooser.java” I don’t think this would ever work as it doesn’t loop through every version of the dependency unless you call reject on each one, at which point you would have nothing left.

What I am really looking for is somehow to override the versionComparator in that class.