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