How to iterate through cached dependencies without resolving them?


(Matias Bjarland) #1

I want to iterate through the dependencies for a particular configuration in my build. During this iteration I need the group, name, and version of the dependency as well as the artifact (jar) file.

I know of a few ways of iterating through dependencies:

1 .

configurations.myconfig.resolvedConfiguration.resolvedArtifacts.each { ResolvedArtifact artifact ->
  def id = artifact.moduleVersion.id
  println "$artifact.file, $id.group, $id.name, $id.version"
}

this gives me all the information I need, but for the specific iteration in question I don’t want to resolve (and download) the dependencies externally, just use the ones that are already in the cache.

2 .

configurations.myconfig.dependencies.each { Dependency d ->
  println "${d.group}, ${d.name}, ${d.version}"
  //no way of getting hold of the artifact files?
}

which doesn’t work as I can’t get hold of the files.

3 .

configurations.myconfig.each { File f ->
   println "$f.canonicalPath"
  //no way of getting hold of group,name,version?
}

which doesn’t work as I get the file but not the [group,name,version] for the dependency.

So how would I go about doing this? I am probably missing something, but have failed to figure this out after trawling the docs for a while.

I am aware of the offline switch in m8, but I was hoping for a programmatic way of accomplishing this.


(Luke Daley) #2

Short answer is that you can’t. The cache is completely opaque so there is not going to be any DSL api that deals with it.

How to solve this depends on what you need to do with this information.


#3

I don’t think there’s currently a way to do what you wish.

Can you tell us why you want to do this? Why is it important not to resolve the dependencies? What would you like to do for dependencies that are not in the cache?

Basically, getting the artifact files for a dependency is ‘resolving’ the dependency. There is no way to access the cached artifact files directly without resolving. The configuration gets populated with artifact files when it is resolved. (Your example 3 above will resolve the dependencies, so it’s a subset of 1).


(Matias Bjarland) #4

Thank you both for the answers. I didn’t realize configurations.myconfig.each actually resolves the dependencies but that makes sense now that you point it out.

The short answer is we have some custom artifact handling in settings.gradle. The artifact handling is run on every build and is required for building up the gradle multi-project structure on the fly. I have a DSL in settings for dealing with this customness. As this is currently run on every build execution, performance becomes crucial.

The artifacts in question are quite large and the idea was to have a switch in the DSL for turning off artifact resolution entirely (e.g. freezeArtifacts true or similar). With the switch on, I just want to iterate over the existing files in the cache (if any), and do some analysis on them. The goal being that the user of the dsl can turn off artifact resolution to increase performance when needed.

I have seen mentioned on the forums that resolution “configuration time” is generally a bad idea. Depending on the answers here we might try to figure out a way to eliminate this entirely.

A couple of questions:

  • If I have the resolutionStrategy settings set to some very long period, is there still a significant performance penalty when iterating through the artifacts?

  • In 1.0-milestone-8-20120126000026+0100, the ‘–offline’ switch doesn’t seem to make any difference to execution times. Could be because I have a lan-local artifactory server, but still made me curious. I can see that the switch makes it possible to disconnect from the network without resolution errors, but somehow I would have expected a performance increase from eliminating network resolution. Should there be one?


(Luke Daley) #5

I still don’t really understand what’s going on. So if the following doesn’t help you might have to get more specific.

If the artifacts you are resolving aren’t dynamic or changing, then the settings won’t do anything for you. The same for ‘–offline’. Offline simply forces the use of expired dynamic or changing repositories instead of checking for updates.

One thing you could look at it is Configuration.getResolvedConfiguration().getLenientConfiguration(). In theory you could use that in conjunction with ‘–offline’ to only get what’s in the cache but I don’t think that this is a good idea generally as it’s probably not really what you want.

Also, I’d be concerned about this kind of conditional build behaviour. That’s likely to end up being a support problem.


#6

As Luke pointed out, if you’re not seeing any performance improvement with ‘–offline’ then you’re not going to see any performance improvements by avoiding remote resolution.

However, there’s a bunch of stuff going on in dependency resolution that doesn’t involve network access: parsing the meta-data files, building/resolving the dependency graph, etc. I’m curious to know how slow this actually is for you.

Can you run the build with --profile and check out how long dependency resolution is taking?


(Matias Bjarland) #7

Thank you both for taking the time and the insight into gradle workings. I think I now understand the philosophy behind the gradle cache and artifact handlig a bit better and will bring that with me going forward.

I have run the build in question with --profile and the total resolution time is usually order of fractions of a second. On my macbook pro with an ssd it tends to land around 0.2s-0.6s. This is quite acceptable and we will leave the resolution logic as is for the time being.

On a related note: I think the current gradle documentation is very high quality for a build tool (I mean let’s for some kicks and giggles compare with ant which has been around for 12 years) or for any java framework for that matter. The format and spirit of the documentation is however usually focused more on “how to get things done” than “how things work” or “what the philosophy behind this is”. Perhaps it would be worth infusing some more nuggets of this type into the documentation?

If nothing else it might spare you lengthy questions like this one on the forums. Luke’s initial answer “The cache is completely opaque so there is not going to be any DSL api that deals with it.” for example nails it. It tells me how the authors intended me to use the tool and let’s me know that hacking it in other ways is going to be working against the grain. Perfect.

Thanks again. I consider this question answered.


(Luke Daley) #8

Thanks Matias.

Good ideas regarding docs and the cache. We’ve got a big review of the userguide coming up so I’ll feed this into the process.

Cheers.