You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by cs...@apache.org on 2024/10/17 08:06:53 UTC
(maven) branch master updated: [MNG-8302] Warn when appropriate (#1810)
This is an automated email from the ASF dual-hosted git repository.
cstamas pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven.git
The following commit(s) were added to refs/heads/master by this push:
new 95e59f2437 [MNG-8302] Warn when appropriate (#1810)
95e59f2437 is described below
commit 95e59f2437d79bbc59fa0faa2f390ef239491eb8
Author: Tamas Cservenak <ta...@cservenak.net>
AuthorDate: Thu Oct 17 10:06:47 2024 +0200
[MNG-8302] Warn when appropriate (#1810)
First, `rootDirectory` is nullable, CLIng code was not assuming this, fixed.
Second, emit the "no root found" warning ONLY when appropriate (when we have a POM in picture).
---
https://issues.apache.org/jira/browse/MNG-8302
---
.../org/apache/maven/api/cli/InvokerRequest.java | 9 +++---
.../maven/api/services/model/RootLocator.java | 4 +++
.../impl/model/rootlocator/DefaultRootLocator.java | 10 +++++--
.../maven/cling/invoker/BaseInvokerRequest.java | 4 +--
.../org/apache/maven/cling/invoker/BaseParser.java | 18 ++++++------
.../apache/maven/cling/invoker/LookupInvoker.java | 8 ++++--
.../java/org/apache/maven/cling/invoker/Utils.java | 33 ++++++++++++++++++++++
.../maven/cling/invoker/mvn/BaseMavenParser.java | 4 +--
.../cling/invoker/mvn/DefaultMavenInvoker.java | 26 +++++++++++++----
9 files changed, 90 insertions(+), 26 deletions(-)
diff --git a/api/maven-api-cli/src/main/java/org/apache/maven/api/cli/InvokerRequest.java b/api/maven-api-cli/src/main/java/org/apache/maven/api/cli/InvokerRequest.java
index 34418a5fcc..d38d0cc633 100644
--- a/api/maven-api-cli/src/main/java/org/apache/maven/api/cli/InvokerRequest.java
+++ b/api/maven-api-cli/src/main/java/org/apache/maven/api/cli/InvokerRequest.java
@@ -125,13 +125,14 @@ public interface InvokerRequest<O extends Options> {
Path topDirectory();
/**
- * Returns the root directory of the Maven invocation.
- * This is determined by the presence of a .mvn directory or a POM with the root="true" property.
+ * Returns the root directory of the Maven invocation, if found. This is determined by the presence of a
+ * {@code .mvn} directory or a POM with the root="true" property but is not always applicable (ie invocation
+ * from outside a checkout).
*
- * @return the root directory path
+ * @return the root directory path, if present
*/
@Nonnull
- Path rootDirectory();
+ Optional<Path> rootDirectory();
/**
* Returns the input stream for the Maven execution, if running in embedded mode.
diff --git a/maven-api-impl/src/main/java/org/apache/maven/api/services/model/RootLocator.java b/maven-api-impl/src/main/java/org/apache/maven/api/services/model/RootLocator.java
index 5b41bec688..5cb8bd841f 100644
--- a/maven-api-impl/src/main/java/org/apache/maven/api/services/model/RootLocator.java
+++ b/maven-api-impl/src/main/java/org/apache/maven/api/services/model/RootLocator.java
@@ -22,6 +22,7 @@ import java.nio.file.Path;
import org.apache.maven.api.Service;
import org.apache.maven.api.annotations.Nonnull;
+import org.apache.maven.api.annotations.Nullable;
/**
* Interface used to locate the root directory for a given project.
@@ -40,6 +41,9 @@ public interface RootLocator extends Service {
+ "Create a .mvn directory in the root directory or add the root=\"true\""
+ " attribute on the root project's model to identify it.";
+ @Nullable
+ Path findRoot(@Nonnull Path basedir);
+
@Nonnull
Path findMandatoryRoot(@Nonnull Path basedir);
diff --git a/maven-api-impl/src/main/java/org/apache/maven/internal/impl/model/rootlocator/DefaultRootLocator.java b/maven-api-impl/src/main/java/org/apache/maven/internal/impl/model/rootlocator/DefaultRootLocator.java
index 19d514b84d..83850082dd 100644
--- a/maven-api-impl/src/main/java/org/apache/maven/internal/impl/model/rootlocator/DefaultRootLocator.java
+++ b/maven-api-impl/src/main/java/org/apache/maven/internal/impl/model/rootlocator/DefaultRootLocator.java
@@ -46,13 +46,19 @@ public class DefaultRootLocator implements RootLocator {
.toList();
}
- @Nonnull
- public Path findMandatoryRoot(@Nonnull Path basedir) {
+ @Override
+ public Path findRoot(Path basedir) {
requireNonNull(basedir, "basedir is null");
Path rootDirectory = basedir;
while (rootDirectory != null && !isRootDirectory(rootDirectory)) {
rootDirectory = rootDirectory.getParent();
}
+ return rootDirectory;
+ }
+
+ @Nonnull
+ public Path findMandatoryRoot(@Nonnull Path basedir) {
+ Path rootDirectory = findRoot(basedir);
Optional<Path> rdf = getRootDirectoryFallback();
if (rootDirectory == null) {
rootDirectory = rdf.orElseThrow(() -> new IllegalStateException(getNoRootMessage()));
diff --git a/maven-cli/src/main/java/org/apache/maven/cling/invoker/BaseInvokerRequest.java b/maven-cli/src/main/java/org/apache/maven/cling/invoker/BaseInvokerRequest.java
index 1aa26ca7be..0b1bd847d7 100644
--- a/maven-cli/src/main/java/org/apache/maven/cling/invoker/BaseInvokerRequest.java
+++ b/maven-cli/src/main/java/org/apache/maven/cling/invoker/BaseInvokerRequest.java
@@ -114,8 +114,8 @@ public abstract class BaseInvokerRequest<T extends Options> implements InvokerRe
}
@Override
- public Path rootDirectory() {
- return rootDirectory;
+ public Optional<Path> rootDirectory() {
+ return Optional.ofNullable(rootDirectory);
}
@Override
diff --git a/maven-cli/src/main/java/org/apache/maven/cling/invoker/BaseParser.java b/maven-cli/src/main/java/org/apache/maven/cling/invoker/BaseParser.java
index 2ae2bd94d6..144ed3d583 100644
--- a/maven-cli/src/main/java/org/apache/maven/cling/invoker/BaseParser.java
+++ b/maven-cli/src/main/java/org/apache/maven/cling/invoker/BaseParser.java
@@ -32,17 +32,16 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
-import java.util.ServiceLoader;
import java.util.function.Function;
import org.apache.maven.api.Constants;
+import org.apache.maven.api.annotations.Nullable;
import org.apache.maven.api.cli.InvokerRequest;
import org.apache.maven.api.cli.Options;
import org.apache.maven.api.cli.Parser;
import org.apache.maven.api.cli.ParserException;
import org.apache.maven.api.cli.ParserRequest;
import org.apache.maven.api.cli.extensions.CoreExtension;
-import org.apache.maven.api.services.model.RootLocator;
import org.apache.maven.cli.CLIReportingUtils;
import org.apache.maven.cli.internal.extension.io.CoreExtensionsStaxReader;
import org.apache.maven.cli.props.MavenPropertiesLoader;
@@ -76,14 +75,19 @@ public abstract class BaseParser<O extends Options, R extends InvokerRequest<O>>
public Map<String, String> systemProperties;
public Map<String, String> userProperties;
public Path topDirectory;
+
+ @Nullable
public Path rootDirectory;
+
public List<CoreExtension> extensions;
public Options options;
public Map<String, String> extraInterpolationSource() {
Map<String, String> extra = new HashMap<>();
extra.put("session.topDirectory", topDirectory.toString());
- extra.put("session.rootDirectory", rootDirectory.toString());
+ if (rootDirectory != null) {
+ extra.put("session.rootDirectory", rootDirectory.toString());
+ }
return extra;
}
}
@@ -101,7 +105,7 @@ public abstract class BaseParser<O extends Options, R extends InvokerRequest<O>>
// top/root
context.topDirectory = requireNonNull(getTopDirectory(context));
- context.rootDirectory = requireNonNull(getRootDirectory(context));
+ context.rootDirectory = getRootDirectory(context);
// options
List<O> parsedOptions = parseCliOptions(context);
@@ -194,11 +198,9 @@ public abstract class BaseParser<O extends Options, R extends InvokerRequest<O>>
return getCanonicalPath(topDirectory);
}
+ @Nullable
protected Path getRootDirectory(LocalContext context) throws ParserException {
- return getCanonicalPath(ServiceLoader.load(RootLocator.class)
- .iterator()
- .next()
- .findMandatoryRoot(requireNonNull(context.topDirectory)));
+ return Utils.findRoot(context.topDirectory);
}
protected Map<String, String> populateSystemProperties(LocalContext context) throws ParserException {
diff --git a/maven-cli/src/main/java/org/apache/maven/cling/invoker/LookupInvoker.java b/maven-cli/src/main/java/org/apache/maven/cling/invoker/LookupInvoker.java
index 2055c54b60..095a2c0226 100644
--- a/maven-cli/src/main/java/org/apache/maven/cling/invoker/LookupInvoker.java
+++ b/maven-cli/src/main/java/org/apache/maven/cling/invoker/LookupInvoker.java
@@ -643,11 +643,13 @@ public abstract class LookupInvoker<
request.setBaseDirectory(context.invokerRequest.topDirectory().toFile());
request.setSystemProperties(toProperties(context.invokerRequest.systemProperties()));
request.setUserProperties(toProperties(context.invokerRequest.userProperties()));
- request.setMultiModuleProjectDirectory(
- context.invokerRequest.rootDirectory().toFile());
- request.setRootDirectory(context.invokerRequest.rootDirectory());
request.setTopDirectory(context.invokerRequest.topDirectory());
+ if (context.invokerRequest.rootDirectory().isPresent()) {
+ request.setMultiModuleProjectDirectory(
+ context.invokerRequest.rootDirectory().get().toFile());
+ request.setRootDirectory(context.invokerRequest.rootDirectory().get());
+ }
request.addPluginGroup("org.apache.maven.plugins");
request.addPluginGroup("org.codehaus.mojo");
diff --git a/maven-cli/src/main/java/org/apache/maven/cling/invoker/Utils.java b/maven-cli/src/main/java/org/apache/maven/cling/invoker/Utils.java
index 8d358bd22d..2cb01e2c19 100644
--- a/maven-cli/src/main/java/org/apache/maven/cling/invoker/Utils.java
+++ b/maven-cli/src/main/java/org/apache/maven/cling/invoker/Utils.java
@@ -24,9 +24,14 @@ import java.nio.file.Path;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
+import java.util.Optional;
import java.util.Properties;
+import java.util.ServiceLoader;
import java.util.function.Function;
+import org.apache.maven.api.annotations.Nonnull;
+import org.apache.maven.api.annotations.Nullable;
+import org.apache.maven.api.services.model.RootLocator;
import org.apache.maven.cli.logging.Slf4jConfiguration;
import org.apache.maven.execution.MavenExecutionRequest;
import org.codehaus.plexus.interpolation.AbstractValueSource;
@@ -42,6 +47,7 @@ import static java.util.Objects.requireNonNull;
public final class Utils {
private Utils() {}
+ @Nullable
public static File toFile(Path path) {
if (path != null) {
return path.toFile();
@@ -49,6 +55,7 @@ public final class Utils {
return null;
}
+ @Nonnull
public static String stripLeadingAndTrailingQuotes(String str) {
requireNonNull(str, "str");
final int length = str.length();
@@ -61,6 +68,7 @@ public final class Utils {
return str;
}
+ @Nonnull
public static Path getCanonicalPath(Path path) {
requireNonNull(path, "path");
try {
@@ -70,6 +78,7 @@ public final class Utils {
}
}
+ @Nonnull
public static Map<String, String> toMap(Properties properties) {
requireNonNull(properties, "properties");
HashMap<String, String> map = new HashMap<>();
@@ -79,6 +88,7 @@ public final class Utils {
return map;
}
+ @Nonnull
public static Properties toProperties(Map<String, String> properties) {
requireNonNull(properties, "properties");
Properties map = new Properties();
@@ -88,6 +98,7 @@ public final class Utils {
return map;
}
+ @Nonnull
public static BasicInterpolator createInterpolator(Collection<Map<String, String>> properties) {
StringSearchInterpolator interpolator = new StringSearchInterpolator();
interpolator.addValueSource(new AbstractValueSource(false) {
@@ -105,6 +116,7 @@ public final class Utils {
return interpolator;
}
+ @Nonnull
public static Function<String, String> prefix(String prefix, Function<String, String> cb) {
return s -> {
String v = null;
@@ -115,6 +127,8 @@ public final class Utils {
};
}
+ @SafeVarargs
+ @Nonnull
public static Function<String, String> or(Function<String, String>... callbacks) {
return s -> {
for (Function<String, String> cb : callbacks) {
@@ -144,4 +158,23 @@ public final class Utils {
case ERROR -> Logger.LEVEL_ERROR;
};
}
+
+ @Nullable
+ public static Path findRoot(Path topDirectory) {
+ requireNonNull(topDirectory, "topDirectory");
+ Path rootDirectory =
+ ServiceLoader.load(RootLocator.class).iterator().next().findRoot(topDirectory);
+ if (rootDirectory != null) {
+ return getCanonicalPath(rootDirectory);
+ }
+ return null;
+ }
+
+ @Nonnull
+ public static Path findMandatoryRoot(Path topDirectory) {
+ requireNonNull(topDirectory, "topDirectory");
+ return getCanonicalPath(Optional.ofNullable(
+ ServiceLoader.load(RootLocator.class).iterator().next().findMandatoryRoot(topDirectory))
+ .orElseThrow());
+ }
}
diff --git a/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvn/BaseMavenParser.java b/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvn/BaseMavenParser.java
index 76dbc5de51..d2b5752f0c 100644
--- a/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvn/BaseMavenParser.java
+++ b/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvn/BaseMavenParser.java
@@ -42,8 +42,8 @@ public abstract class BaseMavenParser<O extends MavenOptions, R extends MavenInv
// CLI args
result.add(parseMavenCliOptions(context.parserRequest.args()));
// maven.config; if exists
- Path mavenConfig = context.rootDirectory.resolve(".mvn/maven.config");
- if (Files.isRegularFile(mavenConfig)) {
+ Path mavenConfig = context.rootDirectory != null ? context.rootDirectory.resolve(".mvn/maven.config") : null;
+ if (mavenConfig != null && Files.isRegularFile(mavenConfig)) {
result.add(parseMavenConfigOptions(mavenConfig));
}
return result;
diff --git a/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvn/DefaultMavenInvoker.java b/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvn/DefaultMavenInvoker.java
index e8d4ed23d1..0b6a4fca32 100644
--- a/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvn/DefaultMavenInvoker.java
+++ b/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvn/DefaultMavenInvoker.java
@@ -43,6 +43,7 @@ import org.apache.maven.cli.CLIReportingUtils;
import org.apache.maven.cli.event.ExecutionEventLogger;
import org.apache.maven.cling.invoker.LookupInvoker;
import org.apache.maven.cling.invoker.ProtoLookup;
+import org.apache.maven.cling.invoker.Utils;
import org.apache.maven.eventspy.internal.EventSpyDispatcher;
import org.apache.maven.exception.DefaultExceptionHandler;
import org.apache.maven.exception.ExceptionHandler;
@@ -259,6 +260,12 @@ public abstract class DefaultMavenInvoker<
@Override
protected void populateRequest(C context, MavenExecutionRequest request) throws Exception {
super.populateRequest(context, request);
+ if (context.invokerRequest.rootDirectory().isEmpty()) {
+ // maven requires this to be set; so default it (and see below at POM)
+ request.setMultiModuleProjectDirectory(
+ context.invokerRequest.topDirectory().toFile());
+ request.setRootDirectory(context.invokerRequest.topDirectory());
+ }
MavenOptions options = context.invokerRequest.options();
request.setNoSnapshotUpdates(options.suppressSnapshotUpdates().orElse(false));
@@ -270,15 +277,24 @@ public abstract class DefaultMavenInvoker<
request.setGlobalChecksumPolicy(determineGlobalChecksumPolicy(context));
Path pom = determinePom(context);
- request.setPom(pom != null ? pom.toFile() : null);
+ if (pom != null) {
+ request.setPom(pom.toFile());
+ if (pom.getParent() != null) {
+ request.setBaseDirectory(pom.getParent().toFile());
+ }
+
+ // project present, but we could not determine rootDirectory: extra work needed
+ if (context.invokerRequest.rootDirectory().isEmpty()) {
+ Path rootDirectory = Utils.findMandatoryRoot(context.invokerRequest.topDirectory());
+ request.setMultiModuleProjectDirectory(rootDirectory.toFile());
+ request.setRootDirectory(rootDirectory);
+ }
+ }
+
request.setTransferListener(
determineTransferListener(context, options.noTransferProgress().orElse(false)));
request.setExecutionListener(determineExecutionListener(context));
- if ((request.getPom() != null) && (request.getPom().getParentFile() != null)) {
- request.setBaseDirectory(request.getPom().getParentFile());
- }
-
request.setResumeFrom(options.resumeFrom().orElse(null));
request.setResume(options.resume().orElse(false));
request.setMakeBehavior(determineMakeBehavior(context));