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

fixes #160: when the direct dependency is optional, flattened its transitive dependencies and set them as optional #164

Merged
merged 3 commits into from
Jul 16, 2020

Conversation

yangnuoyu
Copy link
Contributor

@yangnuoyu yangnuoyu commented Jun 30, 2020

Code change in this pr:

  1. add codes (line 1073 - 1076) to set the artifact of dependency node as optional when its parent is optional. Since we will visit the parent node first, it will finally set all the nodes in a subtree whose root node is optional as optional.
  2. add two tests "flatten-dependency-all-optional" and "flatten-dependency-all-depmgnt-optional" to check the code change.
  3. fix some style issue.
    @stephaniewang526 @saturnism @elharo

… its transitive dependencies and set them as optional
@stephaniewang526
Copy link
Contributor

LGTM.

Out of curiosity, did you run some code formatter? Is that why the formatting changes came in?

@yangnuoyu
Copy link
Contributor Author

LGTM.

Out of curiosity, did you run some code formatter? Is that why the formatting changes came in?

I just saw the format issue and change it by myself.

@yangnuoyu yangnuoyu marked this pull request as ready for review June 30, 2020 22:54
@stephaniewang526
Copy link
Contributor

stephaniewang526 commented Jun 30, 2020

@olamy PTAL fixes #160

Copy link
Contributor

@elharo elharo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not clear on why this is desirable. is there an issue that explains this?

assert "core" == originalProject.dependencies.dependency.artifactId.text()
assert "true" == originalProject.dependencies.dependency.optional.text()

File flattendPom = new File( basedir, '.flattened-pom.xml' )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flattend --> flattenned

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

File flattendPom = new File( basedir, '.flattened-pom.xml' )
assert flattendPom.exists()

def flattendProject = new XmlSlurper().parse( flattendPom )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flattend --> flattenned

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

File flattendPom = new File( basedir, '.flattened-pom.xml' )
assert flattendPom.exists()

def flattendProject = new XmlSlurper().parse( flattendPom )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flattend --> flattenned

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@saturnism
Copy link
Contributor

i still feel that we should drop the entire subtree of an optional dependency, and let maven work it out itself.

Copy link
Contributor

@elharo elharo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tend to agree with Ray. What is the reason for including dependencies of an optional dependency?

@yangnuoyu
Copy link
Contributor Author

i still feel that we should drop the entire subtree of an optional dependency, and let maven work it out itself.

I tend to agree with Ray. What is the reason for including dependencies of an optional dependency?

The main reason is that the result of dependency:tree for dependency plugin 3.1.2 keeps the entire subtree of an direct optional dependency. The flatten-maven-plugin uses the same class in dependency plugin so I do not want to make a big change for it.

Copy link
Contributor

@elharo elharo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The goal should be to mirror what Maven does for the compile time and runtime classpaths, which drops this tree. mvn dependency:tree is an afterthought.

@saturnism
Copy link
Contributor

saturnism commented Jul 8, 2020

another question is, what if we have a tree that looks like this?

A
+- B (optional)
|  +- C
+- C

If we set the C under B optional, what happened to the real C that we really wanted to use that's not optional?

This is a non-issue if we simply keep B as optional and drop the subtree.

So this becomes:

A
+- B (optional)
+- C

In another scenario, where if C is optional

A
+- B
|  +- C (optional)
|     +- D
+- C
   +- D

It would become:

A
+- B
+- C
+- D

@yangnuoyu
Copy link
Contributor Author

another question is, what if we have a tree that looks like this?

A
+- B (optional)
|  +- C
+- C

If we set the C under B optional, what happened to the real C that we really wanted to use that's not optional?

This is a non-issue if we simply keep B as optional and drop the subtree.

So this becomes:

A
+- B (optional)
+- C

In another scenario, where if C is optional

A
+- B
|  +- C (optional)
|     +- D
+- C
   +- D

It would become:

A
+- B
+- C
+- D

I am thinking of removing the subtree but it still works in these two cases if we keep the subtree. In the first case, flatten-maven-plugin will choose the closer C and set the optional C as verbose, so the result will be the one you expected. In the second case, optional C is transitive so it will be dropped by flatten-maven-plugin before actually flatten the dependency tree.

return true;
}
if (node.getState() != DependencyNode.INCLUDED) return true;
if (node.getState() != DependencyNode.INCLUDED) {
return true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i know this is in the previous code, but should this actually return false, as we discussed in a separate call in the past?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that returning true will omit the current depNode but still visit its children. I will check whether it will make any difference if we return false.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

quick ping ot see if we've checked this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@saturnism all tests passed if it returns false.

}
if (node.getParent().getArtifact().isOptional())
{
node.getArtifact().setOptional(true);
Copy link
Contributor

@saturnism saturnism Jul 9, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my other concern is that we are mutating a node, but prob can't be helped.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can try to use HashSet to record the artifact we want to set as "optional" so we do not need to change the node.

@yangnuoyu
Copy link
Contributor Author

The goal should be to mirror what Maven does for the compile time and runtime classpaths, which drops this tree. mvn dependency:tree is an afterthought.

I run the command "mvn org.apache.maven.plugins:maven-dependency-plugin:3.1.2:list -f pom.xml -DincludeScope=runtime" to make sure I check the compile time and runtime dependencies. The result still includes the direct optional dependency and its transitive dependencies which is marked as "optional"

For example: there is a pom file with only the dependency "junit:junit:4.13" which is optional (and hamcrest-core is a no-optional compile transitive dependency of junit):

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13</version>
      <optional>true</optional>
    </dependency>
  </dependencies>

When I run the command "mvn org.apache.maven.plugins:maven-dependency-plugin:3.1.2:list -f pom.xml -DincludeScope=runtime", the result is as follows:

[INFO] --- maven-dependency-plugin:3.1.2:list (default-cli) @ test ---
[INFO] 
[INFO] The following files have been resolved:
[INFO]    junit:junit:jar:4.13:compile (optional)  -- module junit [auto]
[INFO]    org.hamcrest:hamcrest-core:jar:1.3:compile (optional)  -- module hamcrest.core (auto)

The result shows that Maven still see the hamcrest-core in the compile time and runtime.

@yangnuoyu
Copy link
Contributor Author

@stephaniewang526 @saturnism @elharo @olamy Updated, PTAL

@olamy olamy merged commit 45eb5df into mojohaus:master Jul 16, 2020
olamy pushed a commit that referenced this pull request May 3, 2022
…nsitive dependencies and set them as optional (#164)

* fixes #160: when the direct dependency is optional, flattened its transitive dependencies and set them as optional

* remove optional dependency subtree

* return false in visitor when node is not included
@olamy olamy mentioned this pull request May 3, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants