Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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 @@ -125,13 +125,14 @@ default Lookup lookup() {
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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

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.
Expand All @@ -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);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,19 @@ public DefaultRootLocator() {
.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()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ public Path topDirectory() {
}

@Override
public Path rootDirectory() {
return rootDirectory;
public Optional<Path> rootDirectory() {
return Optional.ofNullable(rootDirectory);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,16 @@
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;
Expand Down Expand Up @@ -76,14 +75,19 @@ public LocalContext(ParserRequest parserRequest) {
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;
}
}
Expand All @@ -101,7 +105,7 @@ public R parse(ParserRequest parserRequest) throws ParserException, IOException

// top/root
context.topDirectory = requireNonNull(getTopDirectory(context));
context.rootDirectory = requireNonNull(getRootDirectory(context));
context.rootDirectory = getRootDirectory(context);

// options
List<O> parsedOptions = parseCliOptions(context);
Expand Down Expand Up @@ -194,11 +198,9 @@ protected Path getTopDirectory(LocalContext context) throws ParserException {
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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -643,11 +643,13 @@ protected void populateRequest(C context, MavenExecutionRequest request) throws
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");
Expand Down
39 changes: 39 additions & 0 deletions maven-cli/src/main/java/org/apache/maven/cling/invoker/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,13 @@
import java.util.HashMap;
import java.util.Map;
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.cli.ParserException;
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;
Expand Down Expand Up @@ -115,6 +120,7 @@ public static Function<String, String> prefix(String prefix, Function<String, St
};
}

@SafeVarargs
public static Function<String, String> or(Function<String, String>... callbacks) {
return s -> {
for (Function<String, String> cb : callbacks) {
Expand Down Expand Up @@ -144,4 +150,37 @@ public static int toPlexusLoggingLevel(Slf4jConfiguration.Level level) {
case ERROR -> Logger.LEVEL_ERROR;
};
}

@Nullable
public static Path findRoot(Path topDirectory) throws ParserException {
requireNonNull(topDirectory, "topDirectory");
Path rootDirectory = null;
for (RootLocator rootLocator : ServiceLoader.load(RootLocator.class).stream()
.map(ServiceLoader.Provider::get)
.toList()) {
rootDirectory = rootLocator.findRoot(topDirectory);
if (rootDirectory != null) {
break;
}
}
if (rootDirectory != null) {
return getCanonicalPath(rootDirectory);
}
return null;
}

@Nonnull
public static Path findMandatoryRoot(Path topDirectory) throws ParserException {
requireNonNull(topDirectory, "topDirectory");
Path rootDirectory;
for (RootLocator rootLocator : ServiceLoader.load(RootLocator.class).stream()
.map(ServiceLoader.Provider::get)
.toList()) {
rootDirectory = rootLocator.findMandatoryRoot(topDirectory);
if (rootDirectory != null) {
return getCanonicalPath(rootDirectory);
}
}
throw new IllegalStateException("how did we get here?");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ protected List<O> parseCliOptions(LocalContext context) throws ParserException,
// 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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
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;
Expand Down Expand Up @@ -259,6 +260,12 @@ protected void toolchains(C context) throws Exception {
@Override
protected void populateRequest(C context, MavenExecutionRequest request) throws Exception {
super.populateRequest(context, request);
if (context.invokerRequest.rootDirectory().isEmpty()) {
// now warn about "no root found"
Path rootDirectory = Utils.findMandatoryRoot(context.invokerRequest.topDirectory());
request.setMultiModuleProjectDirectory(rootDirectory.toFile());
request.setRootDirectory(rootDirectory);
}

MavenOptions options = context.invokerRequest.options();
request.setNoSnapshotUpdates(options.suppressSnapshotUpdates().orElse(false));
Expand All @@ -271,14 +278,16 @@ protected void populateRequest(C context, MavenExecutionRequest request) throws

Path pom = determinePom(context);
request.setPom(pom != null ? pom.toFile() : null);
if (pom != null) {
if (pom.getParent() != null) {
request.setBaseDirectory(pom.getParent().toFile());
}
}

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));
Expand Down