Make rootDirectory mandatory

This commit is contained in:
Tamas Cservenak 2024-10-08 16:10:21 +02:00
parent 4d4ce16cb9
commit d8b1e80424
13 changed files with 162 additions and 44 deletions

View File

@ -0,0 +1,30 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.maven.api.services.model;
import java.nio.file.Path;
import org.apache.maven.api.Service;
/**
* Interface used to detect is a given directory "root directory".
*/
public interface RootDetector extends Service {
boolean isRootDirectory(Path dir);
}

View File

@ -22,7 +22,6 @@ 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.
@ -42,27 +41,10 @@ public interface RootLocator extends Service {
+ " attribute on the root project's model to identify it.";
@Nonnull
default Path findMandatoryRoot(@Nullable Path basedir) {
Path rootDirectory = findRoot(basedir);
if (rootDirectory == null) {
throw new IllegalStateException(getNoRootMessage());
}
return rootDirectory;
}
@Nullable
default Path findRoot(@Nullable Path basedir) {
Path rootDirectory = basedir;
while (rootDirectory != null && !isRootDirectory(rootDirectory)) {
rootDirectory = rootDirectory.getParent();
}
return rootDirectory;
}
Path findMandatoryRoot(@Nonnull Path basedir);
@Nonnull
default String getNoRootMessage() {
return UNABLE_TO_FIND_ROOT_PROJECT_MESSAGE;
}
boolean isRootDirectory(Path dir);
}

View File

@ -637,7 +637,7 @@ public class DefaultModelBuilder implements ModelBuilder {
try {
rootDirectory = session.getRootDirectory();
} catch (IllegalStateException e) {
rootDirectory = session.getService(RootLocator.class).findRoot(top);
rootDirectory = session.getService(RootLocator.class).findMandatoryRoot(top);
}
// Locate and normalize the root POM if it exists, fallback to top otherwise

View File

@ -0,0 +1,85 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.maven.internal.impl.model.rootlocator;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.ServiceLoader;
import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.api.di.Named;
import org.apache.maven.api.services.model.RootDetector;
import org.apache.maven.api.services.model.RootLocator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static java.util.Objects.requireNonNull;
@Named
public class DefaultRootLocator implements RootLocator {
private final Logger logger = LoggerFactory.getLogger(getClass());
private final List<RootDetector> rootDetectors;
public DefaultRootLocator() {
this.rootDetectors = ServiceLoader.load(RootDetector.class).stream()
.map(ServiceLoader.Provider::get)
.toList();
}
@Nonnull
public Path findMandatoryRoot(@Nonnull Path basedir) {
requireNonNull(basedir, "basedir is null");
Path rootDirectory = basedir;
while (rootDirectory != null && !isRootDirectory(rootDirectory)) {
rootDirectory = rootDirectory.getParent();
}
Optional<Path> rdf = getRootDirectoryFallback();
if (rootDirectory == null) {
rootDirectory = rdf.orElseThrow(() -> new IllegalStateException(getNoRootMessage()));
logger.warn(getNoRootMessage());
} else {
if (rdf.isPresent() && !Objects.equals(rootDirectory, rdf.get())) {
logger.warn("Project root directory and multiModuleProjectDirectory are not aligned");
}
}
return rootDirectory;
}
protected boolean isRootDirectory(Path dir) {
requireNonNull(dir, "dir is null");
for (RootDetector rootDetector : rootDetectors) {
if (rootDetector.isRootDirectory(dir)) {
return true;
}
}
return false;
}
protected Optional<Path> getRootDirectoryFallback() {
String mmpd = System.getProperty("maven.multiModuleProjectDirectory");
if (mmpd != null) {
return Optional.of(Paths.get(mmpd));
}
return Optional.empty();
}
}

View File

@ -0,0 +1,33 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.maven.internal.impl.model.rootlocator;
import java.nio.file.Files;
import java.nio.file.Path;
import org.apache.maven.api.di.Named;
import org.apache.maven.api.services.model.RootDetector;
@Named
public class DotMvnRootDetector implements RootDetector {
@Override
public boolean isRootDirectory(Path dir) {
return Files.isDirectory(dir.resolve(".mvn"));
}
}

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.maven.internal.impl.model;
package org.apache.maven.internal.impl.model.rootlocator;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
@ -27,28 +27,13 @@ import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import org.apache.maven.api.annotations.Nullable;
import org.apache.maven.api.di.Named;
import org.apache.maven.api.services.model.RootLocator;
import org.apache.maven.api.services.model.RootDetector;
@Named
public class DefaultRootLocator implements RootLocator {
@Override
@Nullable
public Path findRoot(Path basedir) {
Path rootDirectory = basedir;
while (rootDirectory != null && !isRootDirectory(rootDirectory)) {
rootDirectory = rootDirectory.getParent();
}
return rootDirectory;
}
public class PomXmlRootDetector implements RootDetector {
@Override
public boolean isRootDirectory(Path dir) {
if (Files.isDirectory(dir.resolve(".mvn"))) {
return true;
}
// we're too early to use the modelProcessor ...
Path pom = dir.resolve("pom.xml");
try (InputStream is = Files.newInputStream(pom)) {

View File

@ -0,0 +1,2 @@
org.apache.maven.internal.impl.model.rootlocator.DotMvnRootDetector
org.apache.maven.internal.impl.model.rootlocator.PomXmlRootDetector

View File

@ -0,0 +1 @@
org.apache.maven.internal.impl.model.rootlocator.DefaultRootLocator

View File

@ -47,8 +47,8 @@ import org.apache.maven.internal.impl.model.DefaultPathTranslator;
import org.apache.maven.internal.impl.model.DefaultPluginManagementInjector;
import org.apache.maven.internal.impl.model.DefaultProfileInjector;
import org.apache.maven.internal.impl.model.DefaultProfileSelector;
import org.apache.maven.internal.impl.model.DefaultRootLocator;
import org.apache.maven.internal.impl.model.ProfileActivationFilePathInterpolator;
import org.apache.maven.internal.impl.model.rootlocator.DefaultRootLocator;
import org.apache.maven.internal.impl.resolver.DefaultArtifactDescriptorReader;
import org.apache.maven.internal.impl.resolver.DefaultModelResolver;
import org.apache.maven.internal.impl.resolver.DefaultVersionRangeResolver;

View File

@ -44,10 +44,10 @@ 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;
import org.apache.maven.model.root.RootLocator;
import org.apache.maven.properties.internal.EnvironmentUtils;
import org.apache.maven.properties.internal.SystemProperties;
@ -199,7 +199,7 @@ public abstract class BaseParser<O extends Options, R extends InvokerRequest<O>>
protected Path getRootDirectory(LocalContext context) throws ParserException {
RootLocator rootLocator =
ServiceLoader.load(RootLocator.class).iterator().next();
Path rootDirectory = rootLocator.findRoot(requireNonNull(context.topDirectory));
Path rootDirectory = rootLocator.findMandatoryRoot(requireNonNull(context.topDirectory));
Optional<Path> rdf = getRootDirectoryFallback(context);
if (rootDirectory == null) {

View File

@ -29,7 +29,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
/**
* @deprecated use {@link org.apache.maven.api.services.ModelBuilder} instead
* @deprecated use {@link org.apache.maven.api.services.model.RootLocator} instead
*/
@Named
@Deprecated(since = "4.0.0")

View File

@ -35,7 +35,7 @@ import org.apache.maven.api.annotations.Nullable;
* or a {@code pom.xml} containing the {@code root="true"} attribute.
*
* @see DefaultRootLocator
* @deprecated use {@link org.apache.maven.api.services.ModelBuilder} instead
* @deprecated use {@link org.apache.maven.api.services.model.RootLocator} instead
*/
@Deprecated(since = "4.0.0")
public interface RootLocator {

View File

@ -47,8 +47,8 @@ import org.apache.maven.internal.impl.model.DefaultPathTranslator;
import org.apache.maven.internal.impl.model.DefaultPluginManagementInjector;
import org.apache.maven.internal.impl.model.DefaultProfileInjector;
import org.apache.maven.internal.impl.model.DefaultProfileSelector;
import org.apache.maven.internal.impl.model.DefaultRootLocator;
import org.apache.maven.internal.impl.model.ProfileActivationFilePathInterpolator;
import org.apache.maven.internal.impl.model.rootlocator.DefaultRootLocator;
import org.apache.maven.internal.impl.resolver.DefaultArtifactDescriptorReader;
import org.apache.maven.internal.impl.resolver.DefaultVersionRangeResolver;
import org.apache.maven.internal.impl.resolver.DefaultVersionResolver;