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

Use relative wrapper paths to prevent space-in-path bugs #7558

Merged
merged 1 commit into from
Jul 10, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
Expand All @@ -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")) {
Expand Down Expand Up @@ -893,6 +899,43 @@ static boolean isMultiThreadedMaven(List<String> 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
Expand All @@ -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();
Expand All @@ -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;
}
Expand All @@ -925,7 +968,7 @@ public List<String> construct() {
//if maven.bat file is in space containing path, we need to quote with simple quotes.
String quote = "\"";
List<String> 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
Expand Down
Loading