On 20/05/10 5:12 AM, Steve Appling wrote:
Resolving a configuration when project dependencies are involved, does not work 
as I expect.  I don't know if this is by design or the result of a bug.  Here 
is a simple example:

Project A ->  Project B ->  Project C.

Excerpt from dependencies report on project A:
runtime - Classpath for running the compiled sources.
|-----gprob:b:1.0:default
     |-----gprob:c:1.0:default
     |      |-----jdom:jdom:1.1:default
     |      |      |-----org.jdom:jdom:1.1:master,runtime,compile,default
     |-----commons-io:commons-io:1.1:default
|-----commons-util:commons-util:final:default

I want to determine the set of all external dependencies for project A 
(including transitive project dependencies).

In project A, configurations.runtime.resolve() results in:
  /Users/sappling/temp/gprob/b/build/libs/b-1.0.jar,
  /Users/sappling/temp/gprob/c/build/libs/c-1.0.jar,
  /Users/sappling/.gradle/cache/org.jdom/jdom/jars/jdom-1.1.jar,
  /Users/sappling/.gradle/cache/commons-io/commons-io/jars/commons-io-1.1.jar,
  
/Users/sappling/.gradle/cache/commons-util/commons-util/jars/commons-util-final.jar

This is what I expect.  It is the default archives for projects b and c and all 
the external dependencies for all 3 projects.

Trying to get only the external dependencies, I tried:
  
configurations.runtime.copyRecursive(DependencySpecs.type(Type.EXTERNAL)).resolve()
This results in only the single external dependency in project A:
  
/Users/sappling/.gradle/cache/commons-util/commons-util/jars/commons-util-final.jar

This is not what I expected, but I don't know if this is by design.  It seems 
inconsistent that project dependencies are resolved transitively for an 
unfiltered configuration, but not for a copied configuration with a filter.

It is by design (though whether this is a good design is another question). What you're asking for above is a copy of the runtime configuration which contains only the direct external dependencies, which is what you end up with. Configuration.copy() and copyRecursive() both work only on the direct dependencies, and happen before the resolve.

Similarly configurations.runtime.allDependencies only gets the dependencies 
directly declared in project A.  Due to the behavior of resolve, one might 
expect getAllDependencies to include transitive project dependencies as well.  
Transitive project dependencies need to be explicitly addressed in the 
Configuration class, both in the documentation and in the API.

The transitive stuff is available in one form or another through Configuration.resolvedConfiguration.

I agress that the Configuration interface needs some work. Cleaning this up is one of my goals once the 0.9 release is out. Exactly how we do this is an open question. Some options:

* Add some general purpose way to traverse the dependency graph of a configuration. This way, you can collect whatever meta-information or artifacts you like, and exclude whatever modules and dependencies you like.

* Add some convenience methods which do common types of traversals: get all the artifacts, get all the project artifacts, and so on.

* Make the API for unresolved and resolved configurations as identical as possible. For example, we could think of a resolved configuration as a read-only copy of the unresolved configuration, with a more complete dependency graph. Sharing as much of the API means you can do the same sorts of queries and filtering on both the unresolved and resolved versions of the configuration.

* Generalising the above, separate the methods which define the dependency graph from the methods which traverse and query the dependency graph. For example, the methods getDependencies() and getAllDependencies() mix 2 concerns: The fact that I want dependencies (rather than, say, files or artifacts) and whether or not I want inherited dependencies in the graph. We might replace these 2 methods with:

- getDependencies() which returns all the dependencies of the Configuration,
- withoutInherited() which creates a copy of the configuration without any inherited dependencies.

This way, you can mix and match the filtering and the querying:

getDependencies()
withoutInherited().getDependencies()
withoutInherited().getFiles()
withoutInherited().getArtifacts()

Similarly, you might have, say, a withoutTransitive() or a matching { .. some predicate .. } which copy and filter the configuration in some way. Perhaps getResolvedConfiguration() would also return a copy of the configuration.

* Separate the publications from the dependencies. That is, split Configuration into 2 parts and give them better names.


--
Adam Murdoch
Gradle Developer
http://www.gradle.org


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

   http://xircles.codehaus.org/manage_email


Reply via email to