Thanks for great feedback!
2 sie 2014 02:05 "Adam Murdoch" <[email protected]> napisał(a):

>
> On 1 Aug 2014, at 9:18 pm, Szczepan Faber <[email protected]> wrote:
>
> More thoughts on conflict resolution, Adam-style :)
>
> 1. The starting use case is avoiding conflicting guava and
> google-collections on the same classpath. We'll enable that by
> offering an API to declare that a module (group+name)
> replaces/supersedes/deprecates a different module (group+name). This
> use is a starting point to more interesting use cases which I will
> describe in later. While designing the DSL and the behavior we need to
> be cautious about those other use cases, so that we can develop this
> feature incrementally. We will use guava an collections as an example.
>
> 2. In a standalone project, a guava-collections issue is not that
> problematic, it can be sorted out by editing the build file (change
> the dependencies, add an 'exclude', add force rule, etc.). The use
> case is getting interesting in on an enterprise level, where the
> organisation wants to solve the problem in the shared plugin suite,
> instead of getting each team solve the problem on their own.
> Well-known deprecations like collections-guava could be even encoded
> in Gradle out of the box, but that's a different topic.
>
>
> Absolutely we should. There are some backwards compatibility implications
> if we were to add more meta-data about certain modules over time.
>
>
> 3. Current APIs for influencing the dependency resolution (forcing
> versions, dependency resolve rules) offer only "unconditional"
> manipulation to the dependencies that are being resolved. Let's map
> the collections-guava problem to the current API: we could force
> collections to become guava via dependency resolve rule. The effect
> is:
> - only collections in graph - guava is used
> a) only guava in graph - guava is used
> b) both collections in graph - guava is used (collections are forced
> into guava)
> c) only collections in graph - guava is used
> This is what I mean by 'unconditional' manipulation - if collections
> appear in graph it is _always_ replaced with guava. And this is not
> quite what we want...
>
> 4. We want the replacement rule to get activated only when both
> collections and guava are in the graph.
>
>
> I would think about it somewhat differently. We don’t want to
> conditionally activate some rule here. Instead, we want to use some facts
> about collections and guava to both detect conflicts between the two and
> also to resolve such conflicts.
>
> So, collections was replaced by guava. This is a fact that is true
> regardless of whether one or both or neither of them are in the graph.
>
> This fact implies a few further facts:
>
> - Collections and guava conflict with each other. They provide the same
> API and shouldn’t both be present in a classpath. When resolving a
> dependency graph, we have to select one of these to use.
> - Guava is newer than collections, so if we happen to resolve conflicts by
> selecting the newer of two conflicting modules, we should select the guava
> module over the collections module.
>
> We’d use these facts in other places. For example, when reporting on
> dependencies that are out-of-date, we should consider versions of guava as
> candidate upgrades for any dependencies on collections. Same when we’re
> offering suggestions in the IDE or when generating a dependency lock file.
>
> For this use case, what we’re after is a DSL to let you state these facts
> about various modules. We don’t want an DSL where you provide imperative
> code that implements the mechanics of detecting or resolving the conflicts.
> This allows us to implement everything efficiently and also to reuse these
> facts in other contexts beyond resolving a dependency graph.
>
>
> If only collections appear in
> the graph - there is no need to replace it with guava. Perhaps guava
> and collection is not the best example because early guava is
> completely backwards compatible with latest collections. So in theory,
> we could unconditionally replace collections with an early version of
> guava via existing dependency resolve rule API. However, let's imagine
> that replacement source and target are not that quite compatible or
> that someone is using an _early_ version of collections which is not
> quite compatible with _early_ guava.
>
>
> Compatibility is a different concern.
>
> You can think of the different versions of a given module in the same way
> as replacement of one module by another. If I have A version 1.2 and A
> version 1.3, then we can say 'A version 1.2 was replaced by A version 1.3’,
> with the same implications.
>
> All we’re doing with replacement is saying something about the history of
> some thing. This doesn’t say anything about its compatibility over time.
> Or, more accurately, this doesn’t say anything more than what the version
> of a thing says about compatibility.
>
> Similar to the history of a thing, there are also facts about the
> compatibility of a thing over time that we want to use as input to
> resolving a dependency graph, as part of resolving conflicts. If I have A
> and B in the dependency graph and they conflict, and A is newer than B,
> then I can select A only if A is compatible with B. Otherwise I have to
> either fail the resolve or find some C that is newer than A and B and that
> is compatible with both of them.
>
> We’d also use facts about compatibility when resolving a graph where
> things are provided - eg the android SDK or the Windows API or whatever: If
> I have A and B is in the dependency graph and they conflict, and A is
> provided (and so can’t be substituted) and A is not compatible with B, then
> I have to fail the resolve.
>
> Facts about compatibility are useful in other places beyond dependency
> resolution. For example, when updating a dependency lock file, we might
> skip candidates that are not compatible with what we’re currently using. Or
> when offering suggestions in the IDE we might distinguish between
> candidates that are compatible and not compatible.
>
>
>
> 5. The implementation is tricker than our current forcing/dependency
> resolve rules. Consider dependency graph traversal scenarios:
> - first we encounter collections, we happily use it and continue
> traversing.
> - then we encounter guava - oups - we need to evict already resolved
> module collections and continue traversing. (It's more complicated
> than that, as we resolve conflicts only when we cannot traverse any
> further).
>
> In fact, it does not really differ from the standard, version-based
> conflict resolution. I wanted to point out the difference between
> existing dependency resolve rules implementation. The latter does not
> need to consider already-resolved modules.
>
>
> That’s right. The things we currently call ‘dependency resolve rules’ are
> dependency (edge) replacement rules. They don’t have anything with conflict
> handling. They’re very much not ‘everything that affects dependency
> resolution’ rules.
>
>
> 6. Other features to consider:
> - module is replaced with a set of modules ('spring' ->
> 'spring-core', 'spring-aop', etc.)
> - set of modules is replaced with a single module (I don't know any
> real example for that)
> - api module and impl module use consistent version
>
> 7. Given that there are more ways to influence the dependency
> resolution, and specifically, to replace/force certain dependencies
> with others we should think about improving diagnostics on why certain
> dependency ended up in the graph and why this particular version is
> used. Our reports and API already provides 'selection reason'
> information but I'm afraid it's not enough. A dependency can be
> manipulated during resolution by different rules, applied by different
> plugins and a flat information like 'dependency resolve rule was used'
> is not enough IMHO. There can be a stream of actions that affects the
> selected version of a dependency.
>
>
> This is something the general-purpose model rules has to address, and so
> the plan is that the ad hoc rule handling that we currently have in a few
> places in dependency management will be replaced by the general-purpose
> stuff, and will pick up the insight and reporting goodness that it provides.
>
>
> 8. I made up my mind about the DSL. I'm easy and I can totally be
> convinced to something else. Yet, here's my current preference:
>
> a) I would reuse some existing low-level, imperative API, like the
> component rules or dependency resolve rules, for example:
>
>  eachDependency { details ->
>    if (details.target.name == 'google-collections') {
>     details.replacedBy ‘com.google.guava:guava'
>
>
> The eachDependency() method is used to replace one dependency edge with
> another. It doesn’t make any sense to say something about the history of a
> module here.
>
> If we were to add a low level mechanism, it should be given the meta-data
> for a given module and allow the rules to say things like:
>
> - This module conflicts with modules with these ids.
> - This module is newer than modules with these ids.
> - This module is or is not compatible with modules with these ids.
>
>
>    }
>  }
>
> b) I would add some higher level api that would use a). For example:
>
> dependencies {
>   components {
>
>     
> modules("com.google.collections:google-collections").deprecatedBy("com.google.guava:guava")
>     //or replacedBy(), supersededBy()
>   }
> }
>
> Thoughts?
>
>
> We should only add the high level API.
>
>
> On Fri, Aug 1, 2014 at 11:30 AM, Szczepan Faber <[email protected]>
> wrote:
>
> This is a typo, the spec is work in progress. Initially we thought
> about 'replaces' but we've changed that into 'replacedBy' but I forgot
> to reverse the source and target :)
>
> So:
>
> google-collections is replaced by guava
> guava replaces google-collections
>
> Thanks for pointing this out. I'll do more speccing and get back to
> the mailing list.
>
> Cheers!
>
> On Fri, Aug 1, 2014 at 9:38 AM, Heinrich Filter
> <[email protected]> wrote:
>
> Hi Szczepan,
>
> I'm new around the Gradle community but would love to start contributing
> more. Please feel free to point out any "conventions" that I miss.
>
> For me the "replacedBy" keyword is a bit confusing. In your example:
> 'guava' was replace by 'google-collections'. In my mind that implies that
> 'google-collection' is the *newer* dependency and not, as you state in the
> doc, the older version.
>
> I would think that 'guava' rather *replaces* or *supersedes*
> 'google-collections'.
>
> Or am thinking about this the wrong way?
>
> Regards,
> Heinrich
>
> On 31 Jul 2014, at 3:27 PM, Szczepan Faber <[email protected]> wrote:
>
> Hey,
>
> I've started speccing improvements to conflict resolution here:
>
> https://github.com/gradle/gradle/blob/master/design-docs/conflict-resolution-spec.md
> (there's a big DSL mock-up down the bottom).
>
> It would be good to start discussing the DSL additions here on the
> mailing list. Please give feedback about the DSL or the use cases,
> etc. I haven't decided myself on the DSL :) I'll keep you in loop on
> how the design goes.
>
> Cheers!
> --
> Szczepan Faber
> Core dev@gradle; Founder@mockito
>
> ---------------------------------------------------------------------
> To unsubscribe from this list, please visit:
>
>   http://xircles.codehaus.org/manage_email
>
>
>
>
> **********************************************************************
> This email and all content are subject to the following disclaimer
>
> http://content.momentum.co.za/content/legal/disclaimer_email.htm
>
> **********************************************************************
>
> ---------------------------------------------------------------------
> To unsubscribe from this list, please visit:
>
>    http://xircles.codehaus.org/manage_email
>
>
>
>
>
> --
> Szczepan Faber
> Core dev@gradle; Founder@mockito
>
>
>
>
> --
> Szczepan Faber
> Core dev@gradle; Founder@mockito
>
> ---------------------------------------------------------------------
> To unsubscribe from this list, please visit:
>
>    http://xircles.codehaus.org/manage_email
>
>
>
>
> --
> Adam Murdoch
> Gradle Co-founder
> http://www.gradle.org
> CTO Gradleware Inc. - Gradle Training, Support, Consulting
> http://www.gradleware.com
>
>
>
>

Reply via email to