diff --git a/java/maven/src/org/netbeans/modules/maven/execute/MavenCommandLineExecutor.java b/java/maven/src/org/netbeans/modules/maven/execute/MavenCommandLineExecutor.java index 2419314862b6..df4de54c5044 100644 --- a/java/maven/src/org/netbeans/modules/maven/execute/MavenCommandLineExecutor.java +++ b/java/maven/src/org/netbeans/modules/maven/execute/MavenCommandLineExecutor.java @@ -25,6 +25,7 @@ import java.net.MalformedURLException; import java.net.URL; import java.nio.charset.Charset; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; @@ -663,7 +664,8 @@ ProcessBuilder constructBuilder(final RunConfig clonedConfig, InputOutput ioput) File mavenHome = null; File wrapper = null; if (MavenSettings.getDefault().isPreferMavenWrapper()) { - wrapper = searchMavenWrapper(config); + // wrapper will be an absolute or relative path, do not "absolutize" after searchMavenWrapper + wrapper = searchMavenWrapper(clonedConfig); } if (wrapper != null) { constructeur = new WrapperShellConstructor(wrapper); @@ -754,11 +756,11 @@ ProcessBuilder constructBuilder(final RunConfig clonedConfig, InputOutput ioput) return builder; } - - private static void printGray(InputOutput io, String text) { + + private static void printColor(InputOutput io, String text, IOColors.OutputType style) { if (IOColorLines.isSupported(io)) { try { - IOColorLines.println(io, text, IOColors.getColor(io, IOColors.OutputType.LOG_DEBUG)); + IOColorLines.println(io, text, IOColors.getColor(io, style)); } catch (IOException ex) { Exceptions.printStackTrace(ex); } @@ -767,6 +769,10 @@ private static void printGray(InputOutput io, String text) { } } + private static void printGray(InputOutput io, String text) { + printColor(io, text, IOColors.OutputType.LOG_DEBUG); + } + private void processIssue153101(IOException x, InputOutput ioput) { //#153101 if (x.getMessage() != null && x.getMessage().contains("CreateProcess error=5")) { @@ -893,6 +899,43 @@ static boolean isMultiThreadedMaven(List params) { } return false; } + + /** + * Tries to relativize wrapper path. The execution starts in a {@link RunConfig#getExecutionDirectory() }, + * assuming one of the project or parent project directories. If wrapper is present, it should be inside + * project, so relative paths between project modules should work. This is how "normal humans" run and use + * mvnw wrapper. In addition, it avoids issues with the wrapper script when the project has a space + * in its path - there's most probably no spaces in module names - but it is NOT forbidden !! + * + * @param wrapper wrapper file + * @param config execution config + * @return relativized path, if possible. + */ + @NbBundle.Messages({ + "WARN_SpaceInPath=Warning: A space in project path or module name may prevent mvnw wrapper to function properly." + }) + private File resolveWrapperPath(File wrapper, RunConfig config) { + File absWrapper = wrapper.getAbsoluteFile(); + File executionDir = config.getExecutionDirectory(); + Path absWrapperDir = absWrapper.toPath().getParent(); + Path absDir = executionDir.getAbsoluteFile().toPath(); + + if (absWrapperDir.startsWith(absDir) || absDir.startsWith(absWrapperDir)) { + Path relative = absDir.relativize(wrapper.getAbsoluteFile().toPath()); + if (!relative.toString().contains(" ")) { // NOI18N + if (relative.getNameCount() == 1) { + // prevent searching on PATH + return Paths.get(".").resolve(relative).toFile(); // NOI18N + } else { + return relative.toFile(); + } + } + } + if (absWrapper.toString().contains(" ")) { + printColor(io, Bundle.WARN_SpaceInPath(), IOColors.OutputType.LOG_WARNING); + } + return absWrapper; + } private File searchMavenWrapper(RunConfig config) { String fileName = Utilities.isWindows() ? "mvnw.cmd" : "mvnw"; //NOI18N @@ -902,7 +945,7 @@ private File searchMavenWrapper(RunConfig config) { if (baseDir != null) { File mvnw = new File(baseDir, fileName); if (mvnw.exists()) { - return mvnw; + return resolveWrapperPath(mvnw, config); } } project = project.getParent(); @@ -914,7 +957,7 @@ private File searchMavenWrapper(RunConfig config) { private static class WrapperShellConstructor implements Constructor { private final @NonNull File wrapper; - + WrapperShellConstructor(@NonNull File wrapper) { this.wrapper = wrapper; } @@ -925,7 +968,7 @@ public List construct() { //if maven.bat file is in space containing path, we need to quote with simple quotes. String quote = "\""; List toRet = new ArrayList<>(); - toRet.add(quoteSpaces(wrapper.getAbsolutePath(), quote)); + toRet.add(quoteSpaces(wrapper.getPath(), quote)); if (Utilities.isWindows()) { //#153101, since #228901 always on windows use cmd /c toRet.add(0, "/c"); //NOI18N