[GRADLE-560] Mapping of Ivy dependency lookups insufficient Created: 21/Jul/09  Updated: 04/Jan/13  Resolved: 24/Nov/10

Status: Resolved
Project: Gradle
Affects Version/s: 0.7
Fix Version/s: 0.9-rc-1

Type: Improvement
Reporter: Spencer Allain Assignee: Hans Dockter
Resolution: Fixed Votes: 0

Attachments: File build.gradle    

 Description   

The shortened string form of a dependency is:
[group]:name[:version][:classifier]

Mappings of all of the values are:
Maven:
group -> groupId
name -> artifactId
version -> version
classifier -> classifier
ext -> type

http://ant.apache.org/ivy/history/trunk/concept.html#patterns
Ivy:
group -> [organization]
name -> [module] and [artifact]
version -> [revision]
classifier -> [classifier] (not actually a normal tag)
ext -> [type] and [ext]

[branch] always unset
[conf] always set to 'default'
[originalname] doesn't actually resolve as a token, so it remains '[originalname]'

The biggest issue is not being able to adjust [artifact] individually:

Consider jsf and richfaces as two modules.

/repo/sun/jsf/1.1/jars/
jsf-api.jar
jsf-impl.jar

/repo/jboss/richfaces/jars/
richfaces-api-3.2.1.GA.jar
richfaces-impl-3.2.1.GA.jar
richfaces-ui-3.2.1.GA.jar

Short of mis-using 'classifier', without being able to specify [artifact] different from [module], there isn't any pattern that matches the desired jars.

Even more complex is sl4fj which can't even work with a pattern attempting to abuse 'classifier' (and this is just a subset of jars):

/repo/slf4j.org/slf4j/1.5.8/jars/
jul-to-slf4j-1.5.8.jar
log4j-over-slf4j-1.5.8.jar
slf4j-api-1.5.8.jar
slf4j-ext-1.5.8.jar
slf4j-migrator-1.5.8.jar

Simply by being able to specify [artifact] differently from [module] (like you already can in straight Ivy) these mappings are trivial.

gradle should allow specifying an optional 'artifact' property that would be used with Ivy mappings to allow for just such dependency cases.



 Comments   
Comment by Hans Dockter [ 21/Jul/09 ]

You can do this. But unfortunately this is not mentioned in the user's guide yet. Have a look at the samples/dependencies/build.gradle. There we define artifacts for a classifier dependency. This should be really mentioned in the user's guide.

Comment by Spencer Allain [ 21/Jul/09 ]

Below is a very trivial build.gradle file that exhibits behavior that is very unexpected (at least to me)

build.gradle
==================================================================================
usePlugin 'war'

def path = '/'

repositories
{
flatDir name: 'localRepository',
dirs: path
}

repositories.localRepository
{
// Default flatDir pattern is '[artifact]([revision])([classifier]).[ext]'

def pattern1 =
'[organization]/[module]/[branch]/[revision]/[type]/[artifact]/[ext]/[conf]/[originalname]/[classifier]'

addArtifactPattern(path + pattern1)
}

dependencies
{
compile('group1:name1:version1:classifier1')
{
artifact

{ name = 'name' group = 'group' module = 'module' artifact = 'artifact' type = 'type' extension = 'extension' classifier = 'classifier' version = 'version' configuration = 'configuration' branch = 'branch' }

}
}
==================================================================================

Snippet of relevant output
==================================================================================
==== localRepository: tried

– artifact group#name1;version!name.extension(type):

//name-version-classifier.extension

/group/name1//version/type/name/extension/default/[originalname]/classifier

– artifact group#name1;version!name1.jar:

//name1-version-classifier1.jar

/group/name1//version/jar/name1/jar/default/[originalname]/classifier1
==================================================================================

Here is what's really confusing me:

1. 'group' and 'version' take precedence over the initially specified values ('group1' and 'version1')
2. 'name1' is applied to [module], whereas 'name' is applied to [artifact]
3. 'type' and 'extension' seem to actually work, yet branch does not
4. 'configurations' is not accepted, and 'configuration' doesn't appear to be passed through (probably same with 'module' and 'artifact')

Comment by Spencer Allain [ 21/Jul/09 ]

Wiki messed up the formatting, I probably should have just uploaded a file in the first place.

Comment by Hans Dockter [ 21/Jul/09 ]

I think Gradle should complain about the above instead of doing rather mysterious things. But the behavior is explainable.

  • As in Ivy (http://ant.apache.org/ivy/history/2.1.0-rc1/ivyfile/dependency-artifact.html), Gradle artifacts don't have a version, group or module property. This is set by the containing dependency. What happens in your example, is that the artifact closure tries to apply version and group to an Gradle artifact. As the Gradle artifact does not have those properties, it applies it to the outer closure which is configuring the dependency, thus overwriting the initial settings. This should not happen. Another thing that is problematic is, that Groovy does not respect the private modifier of the name, group and version fields. They are supposed to be immutable (and need to be, as they form the key and are stored in a set).
  • We don't support the branch property yet in our dependency handling.
  • Our aim is to have a simpler domain model for dependencies than Ivy. Therefore we don't support bidirectional many-many associations between configurations and dependencies. We have a one-directional 1-many. An artifact always to belongs to one configuration, which is the one its dependency is assigned to. There is no configuration property. As we don't use XML or configuration, this makes things much simpler and by using Groovy in a smart way you still can avoid redundant code.
  • compile('group1:name1:version1:classifier1') already defines a module with one explicit artifact (That is the way we implement classifiers, as they are not natively supported by Ivy). If you explicitly declare an artifact anyway, it might be good enough to just say: compile('group1:name1:version1'). But it depends on what you want to achieve.
  • Gradle uses Ivy under the hood but has its own rich domain model to express dependencies. This is then translated during the resolve into Ivy's domain model. We still use native Ivy resolvers but want to provide Gradle objects for describing resolvers soon.

FYI: you can nest code within

{code}
mycode
{code}.

This will keep the formatting.

Generated at Wed Jun 30 11:33:08 CDT 2021 using Jira 8.4.2#804003-sha1:d21414fc212e3af190e92c2d2ac41299b89402cf.