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

[MPH-168] effective-pom should support multi-module project #76

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

broodjetom
Copy link

@broodjetom broodjetom commented Oct 28, 2022

Following this checklist to help us incorporate your
contribution quickly and easily:

  • Make sure there is a JIRA issue filed
    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.
  • Each commit in the pull request should have a meaningful subject line and body.
  • Format the pull request title like [MPH-XXX] - Fixes bug in ApproximateQuantiles,
    where you replace MPH-XXX with the appropriate JIRA issue. Best practice
    is to use the JIRA issue title in the pull request title and in the first line of the
    commit message.
  • Write a pull request description that is detailed enough to understand what the pull request does, how, and why.
  • Run mvn clean verify to make sure basic checks pass. A more thorough check will
    be performed on your pull request automatically.
  • You have run the integration tests successfully (mvn -Prun-its clean verify).

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.


This PR closes https://issues.apache.org/jira/browse/MPH-168.

I have chosen to solve this issue using a new parameter individual. I chose this name because you are generating an effective POM for each project/module individually. It is already possible to generate an effective POM across for each project/module, but it will put it in a single result/file. Please, advice on this naming if you like it or what it should be changed to.

I have not yet built the support of specifying output in combination with individual. For now, it will always output the effective POM to ${projectDirectory}/target/effective.pom.xml. In the issue it mentions setting the output to ${project.build.directory}/effective-pom.xml, but I'm not sure how to transform the variable part in it per project.

image

IMO the code does not look very clean, I think some of it could be refactored, but I'm not sure in what way.

@broodjetom broodjetom changed the title Feature/mph 168 [MPH-168] effective-pom should support multi-module project Oct 28, 2022
@broodjetom
Copy link
Author

broodjetom commented Oct 28, 2022

I have tried some things with the output. The problem is that variables in the command line parameters are resolved before reaching the Mojo. So, when I do:

mvn clean help:effective-pom -Dindividual -Doutput="${project.build.directory}/effective.pom.xml"

I get the following output:

[INFO] --- maven-help-plugin:3.3.1-SNAPSHOT:effective-pom (default-cli) @ triplem ---
[INFO] Effective-POM written to: C:\Users\TomS\TempProjects\triplem\target\effective.pom.xml
[INFO] Effective-POM written to: C:\Users\TomS\TempProjects\triplem\target\effective.pom.xml
[INFO] Effective-POM written to: C:\Users\TomS\TempProjects\triplem\target\effective.pom.xml
[INFO] Effective-POM written to: C:\Users\TomS\TempProjects\triplem\target\effective.pom.xml
[INFO] Effective-POM written to: C:\Users\TomS\TempProjects\triplem\target\effective.pom.xml
[INFO] Effective-POM written to: C:\Users\TomS\TempProjects\triplem\target\effective.pom.xml
[INFO] Effective-POM written to: C:\Users\TomS\TempProjects\triplem\target\effective.pom.xml

Therefore, I currently have the output path hardcoded set to the target directory of the relevant module. We could go for the option of making the output parameter relative to the target directory. But that would not really make sense.

We could also choose to allow to specify a directory as output and give each of the effective POMs a reference to the module name. That way, they do not overwrite each other. But in that case, you might bump into modules having the same name.

Please, let me know what your preferred solution is.

Copy link

@mthmulders mthmulders left a comment

Choose a reason for hiding this comment

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

Thanks for this effort!

I'd appreciate if the new property individual would not automatically set output.

Could you make it in such a way that individual would output to standard out, unless output was set? If individual=true and output are set, I would interpret output as relative to the base directory of the module for which each individual effective pom was generated.

When the user only specifies the individual flag, it will create individual effective POMs and print it to standard out. When the output parameter is specified, it is used to write the ouput to files, relative to the (sub)project the effective POM is for. The output parameter is parsed as a File so contains the full path. We replace the basedir of that path to get the actual location where the effective POM should be written to. That would fail in case of a relative path going up the tree. Therefore, if the basedir cannot be found, we take the name of the output path and use only that.
@broodjetom
Copy link
Author

If have changed it to where the effective POMs are written to standard out when the output flag is not set.

When the output flag is set, we need to interpret that as relative to the build directory of the (sub)project. A problem is actually that output flag will be parsed as a file, and thus contains the full absolute path (including the drive on Windows). Luckily, the project where we run the command from is available and provides a basedir.

I have used this to do some testing:
image
You can see the full path on top (triplem).

If you run the following command from the main module:

mvn clean help:effective-pom -Dindividual -Doutput="effective/effective.pom.xml"
Parameter Value
basedir C:\Users\TomS\TempProjects\triplem
output C:\Users\TomS\TempProjects\triplem\effective\effective.pom.xml

To then get the relative output I made it to remove the basedir from the output path, meaning you are left with effective\effective.pom.xml.

[INFO] Effective POM written to: C:\Users\TomS\TempProjects\triplem\target\effective\effective.pom.xml
[INFO] Effective POM written to: C:\Users\TomS\TempProjects\triplem\drinks\cola\target\effective\effective.pom.xml
[INFO] Effective POM written to: C:\Users\TomS\TempProjects\triplem\drinks\fanta\target\effective\effective.pom.xml
[INFO] Effective POM written to: C:\Users\TomS\TempProjects\triplem\drinks\target\effective\effective.pom.xml
[INFO] Effective POM written to: C:\Users\TomS\TempProjects\triplem\chocolate\bounty\target\effective\effective.pom.xml
[INFO] Effective POM written to: C:\Users\TomS\TempProjects\triplem\chocolate\mars\target\effective\effective.pom.xml
[INFO] Effective POM written to: C:\Users\TomS\TempProjects\triplem\chocolate\target\effective\effective.pom.xml

Now run the following command from the main module:

mvn clean help:effective-pom -Dindividual -Doutput="../effective.pom.xml"
Parameter Value
basedir C:\Users\TomS\TempProjects\triplem
output C:\Users\TomS\TempProjects\effective.pom.xml

Now the output does not actually contain the basedir. In that case I have currently implemented it to just look at the name of the output path, which now is effective.pom.xml and use that as a file name in the build directory.

[INFO] Effective POM written to: C:\Users\TomS\TempProjects\triplem\target\effective.pom.xml
[INFO] Effective POM written to: C:\Users\TomS\TempProjects\triplem\drinks\cola\target\effective.pom.xml
[INFO] Effective POM written to: C:\Users\TomS\TempProjects\triplem\drinks\fanta\target\effective.pom.xml
[INFO] Effective POM written to: C:\Users\TomS\TempProjects\triplem\drinks\target\effective.pom.xml
[INFO] Effective POM written to: C:\Users\TomS\TempProjects\triplem\chocolate\bounty\target\effective.pom.xml
[INFO] Effective POM written to: C:\Users\TomS\TempProjects\triplem\chocolate\mars\target\effective.pom.xml
[INFO] Effective POM written to: C:\Users\TomS\TempProjects\triplem\chocolate\target\effective.pom.xml

As a conclusion, you are now able to specify a relative path, but there is a constraint on relative paths going up the file tree. Please let me know if you see another solution?

{
String rawOutputPath = output.getPath();
String rawBasedirPath = project.getBasedir().getPath();
String result = rawOutputPath.contains( rawBasedirPath )
Copy link

Choose a reason for hiding this comment

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

This brute-force searching of strings is not the correct way to process paths. Even in the best of worlds, there are all sorts of cases this won't work with (e.g. if the paths are not normalized, and contains ../, etc. In addition you're using contains(), which even with this approach isn't correct (it looks even in the middle of the string).

Instead of searching raw strings, you should be using path manipulation methods for semantic Path objects. For example, there's a method made to do exactly what you want: Path.relativize(). And if you don't have a Path, you can create one from a string. You can also can convert from the old File model to the new Java NIO Path model and back.

If you're not used to working with semantic path objects, you might start at Oracle's The Path Class tutorial, which includes Path Operations explanations..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants