Hi,

I'd like to make a change to how we resolve dynamic versions, in particular 
when a module is published without a meta-data file. This would be a breaking 
change.

Currently, to resolve a dynamic version for a given repository:

1. For each meta-data pattern:
        1. List versions that match this pattern (using maven-metadata.xml or a 
directory listing).
        2. Order the versions from highest to lowest.
        3. For each version that matches the version selector, check for the 
meta-data file. If it exists, use this version.
2. For each artefact referenced in the dependency (usually just a jar):
        1. For each artefact pattern:
                1. List versions that match this pattern (using 
maven-metadata.xml or a directory listing).
                2. Order the versions from highest to lowest.
                3. For each version that matches the version selector, check 
for the artefact. If it exists, use this version.

There are a few issues with this:

1. If a meta-data file is not published for a module, then we scan all of the 
versions looking for the meta-data file before starting the scan again looking 
for the artefacts. For a 'latest.$status' version, this means scanning all of 
the versions that have ever been published.

2. If a module switches from publishing to not publishing a meta-data file, 
then the algorithm above will lock on to the highest version with a meta-data 
file and ignore any later versions without a meta-data file.

3. For most repository layouts, we end up listing the same directory multiple 
times, when meta-data files are not published.

Things get more complex when you add in multiple repositories, as we iterate 
over the repositories applying the matching above and then choose the highest 
version found from each repository, regardless of whether it has meta-data or 
not.

I'd like to split the matching into 2 discrete stages: firstly, determine all 
the potential versions without verifying that they exist, then scan this list 
looking for the first version that exists. Specifically:

1. Calculate the set of candidate versions
        1. For each meta-data pattern, if we've not seen this pattern yet, list 
versions that match this pattern. Add to the set of candidates.
        2. For each artefact pattern, if we've not seen this pattern yet, list 
versions that match this pattern. Add to the set of candidates.
2. For each candidate version from highest to lowest
        1. If this version does not match the version selector, skip.
        2. For each meta-data pattern, check for the meta-data file. If it 
exists:
                1. Download and parse the meta-data.
                2. If the version selector does not accept the meta-data, skip. 
Otherwise, use this version.
        3. Use default meta-data for this version. If the version selector does 
not accept the meta-data, skip.
        3. For each referenced artefact
                1. For each artefact pattern, check for the artefact. If it 
exists, use this version.

This addresses the above issues. It is also a step towards the overall 
structure that we want for the dependency resolution algorithm, where as we 
traverse dependencies in the graph, we resolve first to a set of candidate 
versions and later narrow this down to a single version as we traverse the 
graph and apply conflict resolution.

The downside of this change is that it will break a build that relies on the 
behaviour for issue #2 above. That is, a build that:

1. Consumes a module that has switched from publishing meta-data files to not 
publishing meta-data files, and
2. Expects that resolving adds an implicit 'and has a meta-data file' to the 
version selector.

The workaround for these builds is to replace the dynamic version with either a 
version range or a specific version, either in the dependency declarations or 
via a forced version.

Given this, I think this is a reasonable breaking change to make.


--
Adam Murdoch
Gradle Co-founder
http://www.gradle.org
VP of Engineering, Gradleware Inc. - Gradle Training, Support, Consulting
http://www.gradleware.com

Reply via email to