Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The exclude won't be able to exclude rewritten dependency #17964

Closed
attix-zhang opened this issue Aug 5, 2021 · 5 comments · Fixed by #18131
Closed

The exclude won't be able to exclude rewritten dependency #17964

attix-zhang opened this issue Aug 5, 2021 · 5 comments · Fixed by #18131
Assignees
Labels
a:bug in:dependency-declarations variant notation attributes capability substitution @support Issues owned by GBT support team
Milestone

Comments

@attix-zhang
Copy link
Contributor

Even if I add an exclude rule to exclude "com.google.guava:guava", if other dependencies are rewritten to "com.google.guava:guava", I will still get it in the dependency graph.

Take the following project for example:

plugins {
    id 'java'
}

repositories {
    mavenCentral()
}

configurations.all {
    resolutionStrategy.dependencySubstitution {
        substitute module("com.jcraft:jsch") using module("com.google.guava:guava:20.0") because "No reason, just for test"
    }
    exclude group: "com.google.guava", module: "guava"
}

dependencies {
    implementation group: 'org.apache.hadoop', name: 'hadoop-common', version: '2.6.0'
}

I already added an exclude rule: exclude group: "com.google.guava", module: "guava"

However, I still get guava in my dependency graph

Expected Behavior

If I exclude a dependency, I should not have it in my dependency graph anymore. No matter what.

Current Behavior

clone this repo: https://github.com/attix-zhang/test-gradle-exclude-with-substitution

and then run ./gradlew dependencyInsight --dependency com.google.guava:guava --configuration compileClasspath,

You will still get guava in the compileClasspath.

➜  test-gradle-exclude-with-substitution git:(main) ./gradlew dependencyInsight --dependency com.google.guava:guava --configuration compileClasspath

> Task :dependencyInsight
com.google.guava:guava:20.0 (selected by rule)
   variant "compile" [
      org.gradle.status              = release (not requested)
      org.gradle.usage               = java-api
      org.gradle.libraryelements     = jar (compatible with: classes)
      org.gradle.category            = library

      Requested attributes not found in the selected variant:
         org.gradle.dependency.bundling = external
         org.gradle.jvm.environment     = standard-jvm
         org.gradle.jvm.version         = 8
   ]

com.jcraft:jsch:0.1.42 -> com.google.guava:guava:20.0
\--- org.apache.hadoop:hadoop-common:2.6.0
     \--- compileClasspath

A web-based, searchable dependency report is available by adding the --scan option.

BUILD SUCCESSFUL in 1s

Context

Our company has some dependency substitution rules and every project is required to use. With this bug, each individual project is unable to exclude dependencies cleanly.

Steps to Reproduce

git clone https://github.com/attix-zhang/test-gradle-exclude-with-substitution.git
cd test-gradle-exclude-with-substitution
./gradlew dependencyInsight --dependency com.google.guava:guava --configuration compileClasspath

Your Environment

  • Machine: Macbook Big Sur 11.5.1
  • Java:
openjdk version "1.8.0_292"
OpenJDK Runtime Environment (Zulu 8.54.0.21-CA-macosx) (build 1.8.0_292-b10)
OpenJDK 64-Bit Server VM (Zulu 8.54.0.21-CA-macosx) (build 25.292-b10, mixed mode)
@mlopatkin mlopatkin added the in:dependency-declarations variant notation attributes capability substitution label Aug 6, 2021
@ljacomet
Copy link
Member

ljacomet commented Aug 19, 2021

This is indeed a consequence of the way excludes are processed in dependency graph resolution:

  • The logic filters out dependencies according to excludes
  • The remaining dependencies are checked for applicable substitutions

As a consequence:

  • If you exclude foo and have a rule that replaces bar with foo, foo can appear in the results when your graph contains bar
  • If you exclude foo and have a rule that replaces foo with bar, and nothing else brings in bar, then bar will not appear in the results

Ideally Gradle should fix that first use case while I believe the second one is an OK behavior.

For implementation details, check NodeState#visitDependencies.

Note that a workaround to fix this in your case is to make sure to exclude as well the source of the substitution.

@ljacomet ljacomet added the @support Issues owned by GBT support team label Aug 19, 2021
@attix-zhang
Copy link
Contributor Author

Thanks for the suggestions. However, it is almost impossible to add both exclude to thousands of projects.

Due to this issue, the central dependencies substation rule we had will cause a lot of projects at our company to break.
Would you mind prioritize this issue higher? Thanks a lot!

@attix-zhang
Copy link
Contributor Author

Hi @ljacomet , I tried to submit a pull request to fix it issue, how could I get it reviewed from the Gradle community?

@ljacomet
Copy link
Member

Thanks for submitting the PR, just started the tests and conversation over there.

@ljacomet
Copy link
Member

ljacomet commented Sep 1, 2021

Potential backport request for 6.9.x: #18163

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a:bug in:dependency-declarations variant notation attributes capability substitution @support Issues owned by GBT support team
Projects
None yet
3 participants