-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
[MNG-7344] track dependencyManagement import location in effective Model for MPH-183 #603
[MNG-7344] track dependencyManagement import location in effective Model for MPH-183 #603
Conversation
maven-model/src/main/mdo/maven.mdo
Outdated
@@ -3137,6 +3137,20 @@ | |||
]]> | |||
</description> | |||
</field> | |||
<field> | |||
<name>importedBy</name> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking out loud: there are more ways to define a path to a dependency. Via parent is another one, just like maven-tiles by @talios. There are plans to support import for plugins too.
In the end there's only 1 path, so let's use a more generic name.
Not sure if there is a need to keep track of the type of reference (parent, import-dependency), so let's do that if people ask for it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will look into that approach.
I did consider pluginManagement
as well, but this approach (as-is) would be easy to replicate in the similar DefaultPluginManagementImporter
.
In order to keep track of all references, I think it needs to be tracked elsewhere (and I have not found that location yet - but I will have a look).
In order to support keeping the type of reference, I propose we do not reference an InputLocation
or InputSource
(see also the discussion here) directly, but use a container type that can be extended (for example ReferencedInputLocation
).
return; | ||
} | ||
|
||
while ( hierarchicalSource.getImportedBy() != null ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this loop really necessary? Would love to see an example that needs it. (maybe as an integration test)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had the impression while testing that in long chains (e.g. pom - bom1 - bom2 - bom3 - bom4
) parts of the objects defined in bom4
are copied to bom3
, then bom2
, etc. This loop ensures that we set a new location at the right place, without overwriting any existing. I will however investigate this. Also, I expect this code to be quite different if we decide to go with InputLocation
(see here) so I'll look into that first.
return; | ||
} | ||
|
||
InputSource hierarchicalSource = dependencyLocation.getSource(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is actually very interesting: it looks like it is possible to even use InputLocation instead of InputSource, whcih would give even more details of the path. How about using that instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is interesting. InputLocation
is tied to a specific line in the file, so making those hierarchical would only work for single locations. Given that a dependency has many, we either need to decide on what to track or just modify them all (the latter would of course be much more generic). Since the InputSource
objects are per-file, that is just a quick way to get some order.
Just to check your suggestion, would your idea be that an InputSource
refers to the InputLocation
where it is referenced? In that case (keeping in mind a more generic solution), I think there are a few things to investigate:
- Is there a place in the code where we have access to the
InputLocation
of the reference (parent, import, ...) and theInputSource
of the referenced POM? - In this place in the code, is the model already a tree or is it a graph? I.e., is there only one path from the root POM to every other (indirectly) referenced POM?
A simple test case for the latter could be a project like this:
pom.xml --imports-> bom1
| |
imports imports
| |
v v
parent --imports-> bom2
|
imports
|
v
bom3
There are two paths to resolve a dependency defined in bom3
, ideally there should be a deterministic way to define the path that Maven takes. And that path should (in my opinion) be accurately reflected in the model. Currently my knowledge is too limited to determine how Maven actually resolves this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the effective pom there will be only one route, either bom1
or parent
wins. Saying it differently: if something in bom3 has to be changed and I have access to both bom1 and parent, I need to know which of the 2 has to be changed.
Hey @rfscholte, would it be appropriate to create a new ticket for this? The ticket this work is under is focused on maven-help-plugin, but this is turning out a bit more involved. I'm happy to work on it, but I think it makes sense to make the requirements, reasoning and discussion easily findable at a location where it is expected. If you agree, can you create a ticket and formulate your ideas and expected results? |
I've created https://issues.apache.org/jira/browse/MNG-7344 |
b814fec
to
67465f0
Compare
67465f0
to
38dc034
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
now I need to check MPH-183
and I'd love to have equivalent update for 3.9.x: I'll dig into it later
@@ -83,6 +95,13 @@ public Map<Object, InputLocation> getLocations() { | |||
return locations; | |||
} | |||
|
|||
/** | |||
* Gets the input location that caused this model to be read. | |||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we need an @since
here to remember
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"that caused this model to be read."?
I need to dig more into code to propose another description, but this one is not clear
@@ -20,4 +20,6 @@ | |||
|
|||
public interface InputLocationTracker { | |||
InputLocation getLocation(Object field); | |||
|
|||
InputLocation getImportedFrom(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same @since
} | ||
|
||
public InputSource importedFrom(InputLocation importedFrom) { | ||
return new InputSource(modelId, location, importedFrom); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
really create a new object and forget about it? strange (i did not really dig in depth, just giving initial feedback)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is due to the immutable model, but I think we can simply remove this and make the new constructor public. We don't seem to use it (anymore) upon further inspection...
@@ -64,6 +74,14 @@ public String getModelId() { | |||
return this.modelId; | |||
} | |||
|
|||
public InputLocation getImportedFrom() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same @since
/** | ||
* Get the imported from location. | ||
* | ||
* @return InputLocation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same @since
// And map model v3 to model v4 -> importMgmt(v3).getDelegate() returns a v4 object | ||
importMgmts.add( | ||
org.apache.maven.api.model.DependencyManagement.newBuilder(importMgmt.getDelegate(), true) | ||
.importedFrom(dependency.getDelegate().getLocation("")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
importedFrom should not be assigned to DependencyManagement but to each Dependency, isn't it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hboutemy you're right. It should only map it from model v3 to model v4. We're going to remove the line .importedFrom(dependency.getDelegate().getLocation(""))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes to DefaultModelBuilder
and DefaultDependencyManagementImporter
need to be moved from maven-model-builder
to the implementations in maven-api-impl
, as the ones from maven-model-builder
are kept for compatibility but are not used anymore.
…management-hierarchy-inputsource
@Giovds I've merged, moved the code and fixed a few things, but I cannot push to your branch. |
@gnodet I've merged your changes into this branch. I've also verified that the output is still the same. If you would like to test it yourself, these are the reproduction steps:
|
@mthmulders can you please run the failed integration tests again? I expect it to give a green check mark this time (see https://github.com/infosupport/maven/actions/runs/10215678351) |
@juulhobert I merged another PR which causes a small conflict with this one. |
…ncy-management-hierarchy-inputsource
@gnodet I've merged the changes and pushed it |
The goal of MPH-183 is to print via which BOM(s) a dependencyManagement dependency got in the effective POM in case of dependencyManagement import.
MNG-7344 implements the required tracking in Maven core effective model.
This information was previously not available to the help plugin. This MR:
InputSource
model to keep a hierarchy of sources (which are POM files) by tracking the POM that imported itInputSource
objectsFor now, this code has been written under the assumption that a BOM hierarchy (at least at the point the dependency management blocks are imported) is tree-shaped, without diamonds. That is, given a project
P
with dependencyD
, importing BOMsA
andB
, BOMC
with dependencyD
, onlyA
orB
(not both) can importC
.If such a structure would be possible, the end result may be incorrectly represented as
C via B via A
, which is not correct, because there is no direct relationship betweenA
andB
.Furthermore, at the moment the original
InputSource
of the file is mutated. This makes the hierarchy valid for all imported dependencies, and potentially other parts of the effective POM. This may not be desirable. A relatively minor change, replacingInputSource
objects that are about to be mutated, would solve this issue. In case updating the originalInputSource
is desirable, there may be a better place to set it.Any input on the above points is highly appreciated.
A pull request for printing this information in the effective POM: apache/maven-help-plugin#37
Following this checklist to help us incorporate your
contribution quickly and easily:
for the change (usually before you start working on it). Trivial changes like typos do not
require a JIRA issue. Your pull request should address just this issue, without
pulling in other changes.
[MNG-XXX] - Fixes bug in ApproximateQuantiles
,where you replace
MNG-XXX
with the appropriate JIRA issue. Best practiceis to use the JIRA issue title in the pull request title and in the first line of the
commit message.
mvn clean verify
to make sure basic checks pass. A more thorough check willbe performed on your pull request automatically.
If your pull request is about ~20 lines of code you don't need to sign an
Individual Contributor License Agreement if you are unsure
please ask on the developers list.
To make clear that you license your contribution under
the Apache License Version 2.0, January 2004
you have to acknowledge this by using the following check-box.
I hereby declare this contribution to be licenced under the Apache License Version 2.0, January 2004
In any other case, please file an Apache Individual Contributor License Agreement.