How do I use the Ivy Branch paramter while resolving dependencies

Hello All,

In the 2.1 Realease Notes (ref: http://www.gradle.org/docs/current/release-notes#support-for-the-‘branch’-attribute-when-publishing-or-resolving-ivy-modules), it mentions that the Ivy Branch can be used while resolving modules…

The example given is like this:

dependencies {
    components {
        eachComponent { ComponentMetadataDetails details, IvyModuleDescriptor ivyModule ->
            if (details.id.group == 'my.org' && ivyModule.branch == 'testing') {
                details.changing = true
            }
        }
    }
}

My (very limited) understanding is that component metadata is looked at after the dependencies are resolved, but before a particular version is selected.

The seems to indicate that I can look at all the Ivy versions I selected, but not necessarily discard / select the ones I need.

My organisational repo is setup like this (I can’t change it as this time): /repository/[organisation]/[module]/([branch]/)[revision]/artifact.[ext]

So, I’d like to use the [branch] parameter as part of the artifact path, but I can always work around that by adding multiple resolver patterns.

What I think I need to do is to add the ‘branch’ specifier to the “component”, like this:

compile group:'my.org', name:'project', version:'1.0+', branch:'develop'
 compile group:'my.org', name:'logger', version:'1.0+', branch:'release'

But that doesn’t work… can someone tell me how to specify the branch for some of my dependencies?

Thanks, Marc

Marc,

The short answer is that you can’t do this yet. In 2.2 we will be introducing component selection rules that will allow you to programmatically control how versions are selected (i.e. one of the things you will be able to do is query the metadata and reject versions that don’t have a desired branch). If you are interested, I would encourage you to try it out with one of the nightly builds - take a look at the nightly release notes for examples on using selection rules. Note that this stuff is under very active development right now, so treat it accordingly.

Thanks, Gary

Hi Gary,

Thanks for the quick response. It is very appreciated.

That’s really good news that it’s coming in version 2.2… Looking at the release notes, it looks like the selectors will be “separated” from the definition… So reusing my example from above, i’d need something like this?

configurations {
    rejectConfig {
        resolutionStrategy {
            componentSelection {
                all { ComponentSelection selection, IvyModuleDescriptor descriptor, ComponentMetadata metadata ->
                    if (selection.candidate.group == 'my.org' && selection.candidate.module == 'project') {
                        if (descriptor.branch != 'develop')
                            selection.reject("Not in the dev branch")
                        }
                    }
                    if (selection.candidate.group == 'my.org' && selection.candidate.module == 'logger') {
                        if (descriptor.branch != 'release')
                            selection.reject("Not in the release branch")
                        }
                    }
                }
            }
        }
    }
}
  dependencies{
  compile group:'my.org', name:'project', version:'1.0+'
  compile group:'my.org', name:'logger', version:'1.0+'
}

I am happy to write a “generic” selector for this if i could associate the data with the dependency declaration, perhaps by adding a “extra” map to the ExternalModuleDependency class.

I apologize if this isn’t the right forum.

Thanks again for your responsiveness, Marc

Yep, although the configuration has to match (either use rejectConfig or compile for both the rules and the dependencies). Also, to make it a little cleaner, you could use the module targeting and leave off the ComponentMetadata argument if you’re not going to use it. For instance:

configurations {
    compile {
        resolutionStrategy {
            componentSelection {
                module("my.org:project") { ComponentSelection selection, IvyModuleDescriptor descriptor ->
                    if (descriptor.branch != 'develop') {
                        selection.reject("Not in the dev branch")
                    }
                }
                  module("my.org:logger") { ComponentSelection selection, IvyModuleDescriptor descriptor ->
                    if (descriptor.branch != 'release') {
                        selection.reject("Not in the release branch")
                    }
                }
            }
        }
    }
}
dependencies {
  compile group:'my.org', name:'project', version:'1.0+'
  compile group:'my.org', name:'logger', version:'1.0+'
}

If you wanted a generic selector, there’s probably a couple of ways you could do that, but yeah, you’d need to map group:name to branch (maybe in a project extension?) and then populate that mapping (maybe in the dependency configuration closure?).

Hi Gary

I tried using Gradle 2.2.1 with the following to use the branch attribute.

repositories {
    mavenCentral()
    maven { url "http://repo.spring.io/libs-snapshot" }
          ivy {
        url 'http://server/artifactory/repo'
        layout 'pattern', {
            artifact '[organisation]/[module]/trunk/[revision]/[artifact](.[ext])' //only works for trunk branch
        }
    }
}
  configurations {
     compile {
         resolutionStrategy {
             componentSelection {
                 withModule("org.mycompany:project2") { ComponentSelection selection, IvyModuleDescriptor descriptor ->
                      if (descriptor.branch != 'RB-1.40') {
                         selection.reject("Not in the 1.40 branch")
                     }
                 }
             }
         }
     }
}
dependencies {
    compile(group: 'org.mycompanyl', name: 'project1', version: 'latest.integration')
    compile(group: 'org.mycompany', name: 'project2', version: '1.40.43')
}

Here in the artifactory repository server we need to specify the branch from where the artifact needs to be downloaded. But the in the ivy layout artifact pattern defined above I need to specify a branch without which dependency resolution doesn’t work. What should I do in that case? If i leave out the branch in the artifact pattern, it doesn’t work. if I keep the branch value(‘trunk’) then I cannot get to the branch RB-1.40 Please advise.

Thanks Chandra