Gradle
  1. Gradle
  2. GRADLE-646

Support custom version conflict strategies

    Details

    • Type: New Feature New Feature
    • Status: Open Open
    • Resolution: Unresolved
    • Affects Version/s: 0.2, 0.3, 0.4, 0.5, 0.5.1, 0.5.2, 0.6, 0.6.1, 0.7, 0.8
    • Fix Version/s: None

      Description

      All the user to create their own version conflict resolution strategies. Mailing list reference: http://www.nabble.com/Force-two-versions-of-a-jar--td25367885.html

        Activity

        Hide
        Tamás Kozma
        added a comment -

        From the user guide:

        If you are familiar with Maven or Ivy approach you will be delighted to learn that:

        • All the concepts that you already know and like are still there and are fully supported by Gradle. [...]
        • Gradle works perfectly with your existent dependency management infrastructure, be it Maven or Ivy. [...] No changes necessary.

        [...]

        In your dependency description you tell Gradle which version of a dependency is needed by another dependency. This frequently leads to conflicts. Different dependencies rely on different versions of another dependency. [...] What Gradle offers you is a resolution strategy, by default the newest version is used.

        Based on this, I believe everyone would assume Gradle has the same flexibility to deal with version conflicts as Ivy does. In any case, I had taken that for granted, only to find this is not the case after investing a lot of time into setting up a Gradle build environment at my company (for .NET projects, which in most aspects went fine this far). This means we cannot use Gradle as it is today, because we want to detect version conflicts early on.

        I looked into the source code, and as far as I can tell, it would be very simple and straightforward to expose Ivy's default conflict resolver (and circular dependency resolver, if we are already at it) setting. I understand that you aim for something more advanced and Gradleish in the long run, but I believe letting users configure such default plugins is a very good first step, would not cross any further plans and would enable most scenarios.

        What do you think? If I sent you a patch for this, would you consider it? Do you see any problems with such a simple approach? Just to reiterate: this is a dealbreaker for us, and as I have seen on forums and mail archives, for others as well.

        Show
        Tamás Kozma
        added a comment - From the user guide: If you are familiar with Maven or Ivy approach you will be delighted to learn that: All the concepts that you already know and like are still there and are fully supported by Gradle. [...] Gradle works perfectly with your existent dependency management infrastructure, be it Maven or Ivy. [...] No changes necessary. [...] In your dependency description you tell Gradle which version of a dependency is needed by another dependency. This frequently leads to conflicts. Different dependencies rely on different versions of another dependency. [...] What Gradle offers you is a resolution strategy, by default the newest version is used. Based on this, I believe everyone would assume Gradle has the same flexibility to deal with version conflicts as Ivy does. In any case, I had taken that for granted, only to find this is not the case after investing a lot of time into setting up a Gradle build environment at my company (for .NET projects, which in most aspects went fine this far). This means we cannot use Gradle as it is today, because we want to detect version conflicts early on. I looked into the source code, and as far as I can tell, it would be very simple and straightforward to expose Ivy's default conflict resolver (and circular dependency resolver, if we are already at it) setting. I understand that you aim for something more advanced and Gradleish in the long run, but I believe letting users configure such default plugins is a very good first step, would not cross any further plans and would enable most scenarios. What do you think? If I sent you a patch for this, would you consider it? Do you see any problems with such a simple approach? Just to reiterate: this is a dealbreaker for us, and as I have seen on forums and mail archives, for others as well.
        Hide
        Adam Murdoch
        added a comment - - edited

        It depends how you tackled it. We want to solve the use case, and I'd like to start with something simple which handles your use case, but which we can later incrementally improve.

        I'd rather not use Ivy's ConflictManager interface on the public Gradle API, as we've just spent a good amount of effort moving away from Ivy's DependencyResolver. This is a dead end, as far as I'm concerned.

        So, if we can get away with (for now) having a small set of hardcoded conflict managers which you can choose from, rather than some general capability to provide custom conflict management, I'd like to go with that. Ideally, we'd start with just 'use latest' and 'don't allow any conflicts' to choose from.

        One question is where this setting belongs. To me, it belongs on Configuration, ie it's a setting that belongs with the other per-resolvable dependencies settings.

        Show
        Adam Murdoch
        added a comment - - edited It depends how you tackled it. We want to solve the use case, and I'd like to start with something simple which handles your use case, but which we can later incrementally improve. I'd rather not use Ivy's ConflictManager interface on the public Gradle API, as we've just spent a good amount of effort moving away from Ivy's DependencyResolver. This is a dead end, as far as I'm concerned. So, if we can get away with (for now) having a small set of hardcoded conflict managers which you can choose from, rather than some general capability to provide custom conflict management, I'd like to go with that. Ideally, we'd start with just 'use latest' and 'don't allow any conflicts' to choose from. One question is where this setting belongs. To me, it belongs on Configuration, ie it's a setting that belongs with the other per-resolvable dependencies settings.
        Hide
        Tamás Kozma
        added a comment -

        I'm sad to hear that you want to hide Ivy even more. For me, the biggest selling point of Gradle is its use of Ivy, a proven and flexible system that I like very much. If I were you I would embrace it instead, so that I could say with confidence that Gradle indeed knows everything that Ivy does, and more. But I guess this is not up for debate and I'm sure you have your reasons.

        However, you saying that exposing Ivy is a dead end, confirms that we should not go with Gradle. It is that very customizability that Ivy offers that enables our use of Gradle. We wrote a custom Ivy resolver for our internal repository, we created an Ivy module descriptor parser for our descriptor format, we plugged in our own Ivy message logger, we would want to use a custom conflict resolver and version matcher to deal with our versioning scheme, and so on.

        But to reply to you, I agree that some built in conflict resolution strategies would be sufficient for most. Besides the latest and the no-conflict strategy, a compatible strategy (for some notation, for example 1.2.+) is often used.

        It might belong to a Configuration logically, but then again, I hardly see a case where you would use two different strategies for two configurations in the same build. It might simplify the build script if you only have a single universal resolution strategy. Also, if you assign it to configurations, you have to think about what should happen when a configuration extends another with a different strategy. I mean not just you, but the user too.

        Show
        Tamás Kozma
        added a comment - I'm sad to hear that you want to hide Ivy even more. For me, the biggest selling point of Gradle is its use of Ivy, a proven and flexible system that I like very much. If I were you I would embrace it instead, so that I could say with confidence that Gradle indeed knows everything that Ivy does, and more. But I guess this is not up for debate and I'm sure you have your reasons. However, you saying that exposing Ivy is a dead end, confirms that we should not go with Gradle. It is that very customizability that Ivy offers that enables our use of Gradle. We wrote a custom Ivy resolver for our internal repository, we created an Ivy module descriptor parser for our descriptor format, we plugged in our own Ivy message logger, we would want to use a custom conflict resolver and version matcher to deal with our versioning scheme, and so on. But to reply to you, I agree that some built in conflict resolution strategies would be sufficient for most. Besides the latest and the no-conflict strategy, a compatible strategy (for some notation, for example 1.2.+) is often used. It might belong to a Configuration logically, but then again, I hardly see a case where you would use two different strategies for two configurations in the same build. It might simplify the build script if you only have a single universal resolution strategy. Also, if you assign it to configurations, you have to think about what should happen when a configuration extends another with a different strategy. I mean not just you, but the user too.
        Hide
        Szczepan Faber
        added a comment -

        @Tamas, some recent development in master should make you happier I've added 2 basic conflict strategies. https://github.com/gradle/gradle/commit/7b9884158f28ce0126933588451c178fb869df31

        There's going to be some polishing around the DSL, yet.

        Show
        Szczepan Faber
        added a comment - @Tamas, some recent development in master should make you happier I've added 2 basic conflict strategies. https://github.com/gradle/gradle/commit/7b9884158f28ce0126933588451c178fb869df31 There's going to be some polishing around the DSL, yet.
        Hide
        Tamás Kozma
        added a comment -

        Way to go

        Show
        Tamás Kozma
        added a comment - Way to go
        Hide
        Szczepan Faber
        added a comment -

        First step in improving management of version conflicts: GRADLE-1899

        Show
        Szczepan Faber
        added a comment - First step in improving management of version conflicts: GRADLE-1899
        Hide
        Jacob Aleksynas
        added a comment -

        I'd love to see one additional conflict manager... The "all" manager from Ivy.

        The main use-case is an upgrade from one library to another.. jmock 1 to 2 or even Junit 3.X -> 4.X where BOTH jars can happily live on the classpath and allow for incremental migration of test cases

        I have quite a bit of this in my codeline and have had a heck of a time working around it.

        Show
        Jacob Aleksynas
        added a comment - I'd love to see one additional conflict manager... The "all" manager from Ivy. The main use-case is an upgrade from one library to another.. jmock 1 to 2 or even Junit 3.X -> 4.X where BOTH jars can happily live on the classpath and allow for incremental migration of test cases I have quite a bit of this in my codeline and have had a heck of a time working around it.
        Hide
        Szczepan Faber
        added a comment -

        Thanks for feedback - very interesting (and legitimate) use case. How did you work around it? Separate configurations and changing the test.classpath property?

        Show
        Szczepan Faber
        added a comment - Thanks for feedback - very interesting (and legitimate) use case. How did you work around it? Separate configurations and changing the test.classpath property?
        Hide
        Jacob Aleksynas
        added a comment -

        Yes, separate config and updating classpaths. This approach gets nasty with transitive dependencies and with extended configurations. so i could only use this approach effectively (read "cleanly") with the test use case above. With other runtime focused issues of this nature; I have to upgrade code and fix the necessity for "all" modules.

        Show
        Jacob Aleksynas
        added a comment - Yes, separate config and updating classpaths. This approach gets nasty with transitive dependencies and with extended configurations. so i could only use this approach effectively (read "cleanly") with the test use case above. With other runtime focused issues of this nature; I have to upgrade code and fix the necessity for "all" modules.

          People

          • Assignee:
            Unassigned
            Reporter:
            Jason Porter
          • Votes:
            7 Vote for this issue
            Watchers:
            10 Start watching this issue

            Dates

            • Created:
              Updated: