On 30/08/2013, at 7:38 AM, Adam Murdoch <adam.murd...@gradleware.com> wrote:

> 
> On 30/08/2013, at 6:39 AM, johnrengelman <john.r.engel...@gmail.com> wrote:
> 
>> I've gone back to the drawing board and came up with a simpler solution where
>> in ExternalResourceResolver
>> I check for any artifact existing and then only mark the artifact as
>> resolved by that repository if one is found.
> 
> We want to behave differently in this case for the Maven cache compared to 
> arbitrary repository. It's expected in the Maven cache for an artefact to be 
> missing, but it means a badly formed module everywhere else.
> 
> I think we want something like this:
> 
> 1. If we find a pom and no artifact in the Maven cache
>       * If we can find the module in some other repository, silently ignore 
> the stuff in the Maven cache and use the module from the other repository.
>       * If we cannot find the module in some other repository, fail with an 
> 'artefact missing' exception.
> 2. If we find a pom and no artefact in some repository, fail with an 
> 'artefact missing' exception.
> 
> Or, perhaps it might be nicer in #2 if we warn instead of fail when we can 
> find the module in another repository.
> 
> Regardless of exactly what we do here, it's not the resolvers responsibility 
> to decide whether to fail or continue the search. Instead, it should just 
> communicate what it found, so that `UserResolverChain`, which is coordinating 
> the search, can take care of stopping or continuing or whatever. To do this, 
> we might add some new states to 
> `BuildableModuleVersionMetaDataResolveResult`, so that the resolver can let 
> the search algorithm know that it found a badly formed or partial module.

Thinking about this a little more:

There are some performance implications here, in that we'd be probing whether 
remote artefacts exist before we know whether we need them, or which artefacts 
we need. For example, the module version may later be evicted by conflict 
resolution, in which case the question of whether the artefact exists or the 
module is badly formed is not really relevant. Or, a more interesting example: 
my-lib:1.2 depends on other-lib:1.4@jar and my-lib:1.3 depends on 
other-lib:1.4@zip. If conflict resolution chooses my-lib:1.3, then we only care 
if the zip exists.

Similarly, there are some usability implications, in that we'd be failing or 
complaining about broken things before we know whether we need them or not.

So, I think we want an algorithm something like this:

To resolve the metadata for a dependency:

1. ExternalResourceResolver.getDependency() does not check the artefacts. It 
only considers the meta-data.
2. UserResolverChain stops as soon as something finds the meta-data for a 
dependency, in the case of a static dependency. For a dynamic dependency it 
queries all resolvers and selects the 'best' match.

That is, we stop as soon as we think we have the meta-data for a module.

The graph is then resolved, and we lock down exactly which versions and 
artefacts we need.

Then, to resolve an artefact:

1. UserResolverChain uses the resolver which found the meta-data for the 
selected version.
2. If found, then we're finished.
3. If not found, and this is not a Maven cache, then fail (or maybe warn and 
continue on).
4. Otherwise, search in the other repositories for the selected version:
        1. Fetch the meta-data for the selected version. If not found, continue 
to the next repository.
        2. Compare the meta-data with that from the original repository. If it 
is different, then fail (or maybe warn an continue on).
        3. Fetch the artefact. If not found, then fail (or maybe warn and 
continue on).

That is, we prefer the repository where we found the meta-data, but we can deal 
with a partial module and look for a copy elsewhere.

For now, I wouldn't bother with trying to generalise this, and would go with 
something like your original plan:

1. For a Maven cache, if the pom exists and there are no other artefacts and 
the packaging is not pom, then mark the module as 'not found' (and maybe log an 
info or debug message informing the user of that fact).
2. For everything else, do not check whether the artefacts exists or not. If 
the meta-data is found, then the module must be used.


--
Adam Murdoch
Gradle Co-founder
http://www.gradle.org
VP of Engineering, Gradleware Inc. - Gradle Training, Support, Consulting
http://www.gradleware.com

Join us at the Gradle eXchange 2013, Oct 28th in London, UK: 
http://skillsmatter.com/event/java-jee/gradle-exchange-2013



Reply via email to