[MNG-8421] Move all of logging setup to LookupInvoker; mvnenc IT (#1964)

Currently mvnenc is unable to log to file (-l) as logging setup is incomplete, move all of this logic to LookupInvoker. Also, create prompt in mvnenc only when needed. Finally, implement needed changes to support mvnenc ITs and add mvnenc IT.

Other changes:
* get rid of `distributionFileName` dirty hack, is remnant from old ITs
* fix CI re removal of that above and use of site that is brain-dead

---

https://issues.apache.org/jira/browse/MNG-8421
This commit is contained in:
Tamas Cservenak 2024-12-12 09:43:12 +01:00 committed by GitHub
parent 9c77221cbc
commit 5b7a6de55a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 336 additions and 126 deletions

View File

@ -56,7 +56,7 @@ jobs:
- name: Build Maven distributions
shell: bash
run: ./mvnw verify -e -B -V -DdistributionFileName=apache-maven -Dmaven.repo.local=$HOME/.m2/repository/cached
run: ./mvnw verify -e -B -V -Dmaven.repo.local=$HOME/.m2/repository/cached
- name: List contents of target directory
shell: bash
@ -117,9 +117,14 @@ jobs:
run: |
mkdir -p maven-local
if [ "${{ runner.os }}" = "Windows" ]; then
unzip maven-dist/apache-maven-bin.zip -d maven-local
unzip maven-dist/apache-maven-*-bin.zip -d maven-local
# Get the name of the extracted directory
MAVEN_DIR=$(ls maven-local)
# Move contents up one level
mv "maven-local/$MAVEN_DIR"/* maven-local/
rm -r "maven-local/$MAVEN_DIR"
else
tar xzf maven-dist/apache-maven-bin.tar.gz -C maven-local --strip-components 1
tar xzf maven-dist/apache-maven-*-bin.tar.gz -C maven-local --strip-components 1
fi
echo "MAVEN_HOME=$PWD/maven-local" >> $GITHUB_ENV
echo "$PWD/maven-local/bin" >> $GITHUB_PATH
@ -133,9 +138,13 @@ jobs:
maven-${{ runner.os }}-full-
maven-${{ runner.os }}-
- name: Build with downloaded Maven
shell: bash
run: mvn verify -e -B -V -Dmaven.repo.local=$HOME/.m2/repository/cached
- name: Build site with downloaded Maven
shell: bash
run: mvn verify site -e -B -V -Preporting -Dmaven.repo.local=$HOME/.m2/repository/cached
run: mvn site -e -B -V -Preporting -Dmaven.repo.local=$HOME/.m2/repository/cached
integration-tests:
needs: initial-build
@ -172,14 +181,14 @@ jobs:
run: |
mkdir -p maven-local
if [ "${{ runner.os }}" = "Windows" ]; then
unzip maven-dist/apache-maven-bin.zip -d maven-local
unzip maven-dist/apache-maven-*-bin.zip -d maven-local
# Get the name of the extracted directory
MAVEN_DIR=$(ls maven-local)
# Move contents up one level
mv "maven-local/$MAVEN_DIR"/* maven-local/
rm -r "maven-local/$MAVEN_DIR"
else
tar xzf maven-dist/apache-maven-bin.tar.gz -C maven-local --strip-components 1
tar xzf maven-dist/apache-maven-*-bin.tar.gz -C maven-local --strip-components 1
fi
echo "MAVEN_HOME=$PWD/maven-local" >> $GITHUB_ENV
echo "$PWD/maven-local/bin" >> $GITHUB_PATH

View File

@ -32,10 +32,6 @@ under the License.
<name>Apache Maven Distribution</name>
<description>The Apache Maven distribution, source and binary, in zip and tar.gz formats.</description>
<properties>
<distributionFileName>${distributionId}-${project.version}</distributionFileName>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
@ -162,7 +158,6 @@ under the License.
</pluginRepositories>
<build>
<finalName>${distributionFileName}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>

View File

@ -35,6 +35,7 @@ import org.apache.maven.api.cli.Logger;
import org.apache.maven.api.services.Lookup;
import org.apache.maven.api.settings.Settings;
import org.apache.maven.cling.logging.Slf4jConfiguration;
import org.apache.maven.logging.BuildEventListener;
import org.jline.terminal.Terminal;
import org.slf4j.ILoggerFactory;
@ -86,6 +87,8 @@ public class LookupContext implements AutoCloseable {
public ContainerCapsule containerCapsule;
public Lookup lookup;
public BuildEventListener buildEventListener;
// paths user can override from CLI, and we need to set on MavenExReq
public Path installationSettingsPath;
public Path projectSettingsPath;

View File

@ -69,7 +69,10 @@ import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.internal.impl.SettingsUtilsV4;
import org.apache.maven.jline.FastTerminal;
import org.apache.maven.jline.MessageUtils;
import org.apache.maven.logging.BuildEventListener;
import org.apache.maven.logging.LoggingOutputStream;
import org.apache.maven.logging.ProjectBuildLogAppender;
import org.apache.maven.logging.SimpleBuildEventListener;
import org.apache.maven.logging.api.LogLevelRecorder;
import org.apache.maven.slf4j.MavenSimpleLogger;
import org.jline.terminal.Terminal;
@ -228,6 +231,23 @@ public abstract class LookupInvoker<C extends LookupContext> implements Invoker
context.slf4jConfiguration.setRootLoggerLevel(context.loggerLevel);
// else fall back to default log level specified in conf
// see https://issues.apache.org/jira/browse/MNG-2570
// Create the build log appender; also sets MavenSimpleLogger sink
ProjectBuildLogAppender projectBuildLogAppender =
new ProjectBuildLogAppender(determineBuildEventListener(context));
context.closeables.add(projectBuildLogAppender);
}
protected BuildEventListener determineBuildEventListener(C context) {
if (context.buildEventListener == null) {
context.buildEventListener = doDetermineBuildEventListener(context);
}
return context.buildEventListener;
}
protected BuildEventListener doDetermineBuildEventListener(C context) {
Consumer<String> writer = determineWriter(context);
return new SimpleBuildEventListener(writer);
}
protected void createTerminal(C context) {

View File

@ -22,7 +22,6 @@ import org.apache.maven.Maven;
import org.apache.maven.api.cli.InvokerRequest;
import org.apache.maven.cling.invoker.LookupContext;
import org.apache.maven.eventspy.internal.EventSpyDispatcher;
import org.apache.maven.logging.BuildEventListener;
@SuppressWarnings("VisibilityModifier")
public class MavenContext extends LookupContext {
@ -30,7 +29,6 @@ public class MavenContext extends LookupContext {
super(invokerRequest);
}
public BuildEventListener buildEventListener;
public EventSpyDispatcher eventSpyDispatcher;
public Maven maven;

View File

@ -27,7 +27,6 @@ import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -68,11 +67,8 @@ import org.apache.maven.execution.ProfileActivation;
import org.apache.maven.execution.ProjectActivation;
import org.apache.maven.jline.MessageUtils;
import org.apache.maven.lifecycle.LifecycleExecutionException;
import org.apache.maven.logging.BuildEventListener;
import org.apache.maven.logging.LoggingExecutionListener;
import org.apache.maven.logging.MavenTransferListener;
import org.apache.maven.logging.ProjectBuildLogAppender;
import org.apache.maven.logging.SimpleBuildEventListener;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.PlexusContainer;
import org.eclipse.aether.DefaultRepositoryCache;
@ -149,27 +145,6 @@ public abstract class MavenInvoker<C extends MavenContext> extends LookupInvoker
}
}
@Override
protected void configureLogging(C context) throws Exception {
super.configureLogging(context);
// Create the build log appender
ProjectBuildLogAppender projectBuildLogAppender =
new ProjectBuildLogAppender(determineBuildEventListener(context));
context.closeables.add(projectBuildLogAppender);
}
protected BuildEventListener determineBuildEventListener(C context) {
if (context.buildEventListener == null) {
context.buildEventListener = doDetermineBuildEventListener(context);
}
return context.buildEventListener;
}
protected BuildEventListener doDetermineBuildEventListener(C context) {
Consumer<String> writer = determineWriter(context);
return new SimpleBuildEventListener(writer);
}
@Override
protected void customizeSettingsRequest(C context, SettingsBuilderRequest settingsBuilderRequest) throws Exception {
if (context.eventSpyDispatcher != null) {

View File

@ -23,7 +23,6 @@ import java.util.Map;
import org.apache.maven.api.cli.InvokerRequest;
import org.apache.maven.cling.invoker.LookupContext;
import org.jline.consoleui.prompt.ConsolePrompt;
import org.jline.reader.LineReader;
import org.jline.utils.AttributedString;
import org.jline.utils.AttributedStringBuilder;
@ -40,7 +39,6 @@ public class EncryptContext extends LookupContext {
public List<AttributedString> header;
public AttributedStyle style;
public LineReader reader;
public ConsolePrompt prompt;
public void addInHeader(String text) {
addInHeader(AttributedStyle.DEFAULT, text);

View File

@ -26,13 +26,11 @@ import org.apache.maven.api.cli.mvnenc.EncryptOptions;
import org.apache.maven.cling.invoker.LookupInvoker;
import org.apache.maven.cling.invoker.ProtoLookup;
import org.apache.maven.cling.utils.CLIReportingUtils;
import org.jline.consoleui.prompt.ConsolePrompt;
import org.jline.reader.LineReaderBuilder;
import org.jline.reader.UserInterruptException;
import org.jline.terminal.Terminal;
import org.jline.utils.AttributedStyle;
import org.jline.utils.Colors;
import org.jline.utils.OSUtils;
/**
* mvnenc invoker implementation.
@ -76,17 +74,9 @@ public class EncryptInvoker extends LookupInvoker<EncryptContext> {
Thread executeThread = Thread.currentThread();
context.terminal.handle(Terminal.Signal.INT, signal -> executeThread.interrupt());
ConsolePrompt.UiConfig config;
if (OSUtils.IS_WINDOWS) {
config = new ConsolePrompt.UiConfig(">", "( )", "(x)", "( )");
} else {
config = new ConsolePrompt.UiConfig("", "", "", "");
}
config.setCancellableFirstPrompt(true);
context.reader =
LineReaderBuilder.builder().terminal(context.terminal).build();
context.prompt = new ConsolePrompt(context.reader, context.terminal, config);
EncryptOptions options = (EncryptOptions) context.invokerRequest.options();
if (options.goals().isEmpty() || options.goals().get().size() != 1) {
@ -102,14 +92,13 @@ public class EncryptInvoker extends LookupInvoker<EncryptContext> {
return goal.execute(context);
} catch (InterruptedException | InterruptedIOException | UserInterruptException e) {
context.terminal.writer().println("Goal canceled by user.");
context.logger.error("Goal canceled by user.");
return CANCELED;
} catch (Exception e) {
if (context.invokerRequest.options().showErrors().orElse(false)) {
context.terminal.writer().println(e.getMessage());
e.printStackTrace(context.terminal.writer());
context.logger.error(e.getMessage(), e);
} else {
context.terminal.writer().println(e.getMessage());
context.logger.error(e.getMessage());
}
return ERROR;
} finally {
@ -118,9 +107,9 @@ public class EncryptInvoker extends LookupInvoker<EncryptContext> {
}
protected int badGoalsErrorMessage(String message, EncryptContext context) {
context.terminal.writer().println(message);
context.terminal.writer().println("Supported goals are: " + String.join(", ", context.goals.keySet()));
context.terminal.writer().println("Use -h to display help.");
context.logger.error(message);
context.logger.error("Supported goals are: " + String.join(", ", context.goals.keySet()));
context.logger.error("Use -h to display help.");
return BAD_OPERATION;
}
}

View File

@ -39,12 +39,10 @@ public abstract class ConfiguredGoalSupport extends GoalSupport {
@Override
public int execute(EncryptContext context) throws Exception {
if (!validateConfiguration(context)) {
context.terminal
.writer()
.println(messageBuilderFactory
.builder()
.error("Maven Encryption is not configured, run `mvnenc init` first.")
.build());
context.logger.error(messageBuilderFactory
.builder()
.error("Maven Encryption is not configured, run `mvnenc init` first.")
.build());
return ERROR;
}
return doExecute(context);
@ -59,36 +57,32 @@ public abstract class ConfiguredGoalSupport extends GoalSupport {
}
protected void dumpResponse(EncryptContext context, String indent, SecDispatcher.ValidationResponse response) {
context.terminal
.writer()
.println(messageBuilderFactory
.builder()
.format(
response.isValid()
? messageBuilderFactory
.builder()
.success("%sConfiguration validation of %s: %s")
.build()
: messageBuilderFactory
.builder()
.failure("%sConfiguration validation of %s: %s")
.build(),
indent,
response.getSource(),
response.isValid() ? "VALID" : "INVALID"));
context.logger.info(messageBuilderFactory
.builder()
.format(
response.isValid()
? messageBuilderFactory
.builder()
.success("%sConfiguration validation of %s: %s")
.build()
: messageBuilderFactory
.builder()
.failure("%sConfiguration validation of %s: %s")
.build(),
indent,
response.getSource(),
response.isValid() ? "VALID" : "INVALID")
.build());
for (Map.Entry<SecDispatcher.ValidationResponse.Level, List<String>> entry :
response.getReport().entrySet()) {
Consumer<String> consumer = s -> context.terminal
.writer()
.println(messageBuilderFactory.builder().info(s).build());
Consumer<String> consumer = s ->
context.logger.info(messageBuilderFactory.builder().info(s).build());
if (entry.getKey() == SecDispatcher.ValidationResponse.Level.ERROR) {
consumer = s -> context.terminal
.writer()
.println(messageBuilderFactory.builder().error(s).build());
consumer = s -> context.logger.error(
messageBuilderFactory.builder().error(s).build());
} else if (entry.getKey() == SecDispatcher.ValidationResponse.Level.WARNING) {
consumer = s -> context.terminal
.writer()
.println(messageBuilderFactory.builder().warning(s).build());
consumer = s -> context.logger.warn(
messageBuilderFactory.builder().warning(s).build());
}
for (String line : entry.getValue()) {
consumer.accept(indent + " " + line);

View File

@ -29,7 +29,7 @@ import org.codehaus.plexus.components.secdispatcher.SecDispatcher;
import static org.apache.maven.cling.invoker.mvnenc.EncryptInvoker.OK;
/**
* The "diag" goal.
* The "diag" goal. It should always run, despite it overrides configured goal support.
*/
@Singleton
@Named("diag")
@ -40,8 +40,13 @@ public class Diag extends ConfiguredGoalSupport {
}
@Override
protected int doExecute(EncryptContext context) {
public int execute(EncryptContext context) {
dumpResponse(context, "", secDispatcher.validateConfiguration());
return OK;
}
@Override
protected int doExecute(EncryptContext context) throws Exception {
throw new IllegalStateException("Cannot reach here");
}
}

View File

@ -45,6 +45,7 @@ import org.jline.reader.Completer;
import org.jline.reader.LineReader;
import org.jline.reader.ParsedLine;
import org.jline.utils.Colors;
import org.jline.utils.OSUtils;
import static org.apache.maven.cling.invoker.mvnenc.EncryptInvoker.BAD_OPERATION;
import static org.apache.maven.cling.invoker.mvnenc.EncryptInvoker.OK;
@ -64,26 +65,30 @@ public class Init extends InteractiveGoalSupport {
@Override
public int doExecute(EncryptContext context) throws Exception {
context.addInHeader(context.style.italic().bold().foreground(Colors.rgbColor("yellow")), "goal: init");
context.addInHeader("");
ConsolePrompt prompt = context.prompt;
EncryptOptions options = (EncryptOptions) context.invokerRequest.options();
boolean force = options.force().orElse(false);
boolean yes = options.yes().orElse(false);
if (configExists() && !force) {
context.terminal
.writer()
.println(
messageBuilderFactory
.builder()
.error(
"Error: configuration exist. Use --force if you want to reset existing configuration."));
context.logger.error(messageBuilderFactory
.builder()
.error("Error: configuration exist. Use --force if you want to reset existing configuration.")
.build());
return BAD_OPERATION;
}
context.addInHeader(context.style.italic().bold().foreground(Colors.rgbColor("yellow")), "goal: init");
context.addInHeader("");
ConsolePrompt.UiConfig promptConfig;
if (OSUtils.IS_WINDOWS) {
promptConfig = new ConsolePrompt.UiConfig(">", "( )", "(x)", "( )");
} else {
promptConfig = new ConsolePrompt.UiConfig("", "", "", "");
}
promptConfig.setCancellableFirstPrompt(true);
ConsolePrompt prompt = new ConsolePrompt(context.reader, context.terminal, promptConfig);
SettingsSecurity config = secDispatcher.readConfiguration(true);
// reset config

View File

@ -35,7 +35,7 @@ under the License.
<properties>
<maven3version>3.9.9</maven3version>
<maven4version>4.0.0-rc-1</maven4version>
<maven4version>${project.version}</maven4version>
</properties>
<dependencies>
@ -55,6 +55,14 @@ under the License.
<artifactId>junit-jupiter-params</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>apache-maven</artifactId>
<version>${project.version}</version>
<classifier>bin</classifier>
<type>zip</type>
<scope>test</scope>
</dependency>
</dependencies>
<build>
@ -64,7 +72,17 @@ under the License.
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>prepare-maven-distros</id>
<id>prepare-maven4-distro</id>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<phase>generate-test-resources</phase>
<configuration>
<includeArtifactIds>apache-maven</includeArtifactIds>
</configuration>
</execution>
<execution>
<id>prepare-maven3-distro</id>
<goals>
<goal>unpack</goal>
</goals>
@ -78,13 +96,6 @@ under the License.
<classifier>bin</classifier>
<type>zip</type>
</artifactItem>
<artifactItem>
<groupId>org.apache.maven</groupId>
<artifactId>apache-maven</artifactId>
<version>${maven4version}</version>
<classifier>bin</classifier>
<type>zip</type>
</artifactItem>
</artifactItems>
</configuration>
</execution>

View File

@ -34,6 +34,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
@ -54,6 +55,9 @@ import static java.util.Objects.requireNonNull;
* long as instance of this class is not closed. Subsequent execution requests over same installation home are cached.
*/
public class EmbeddedMavenExecutor implements Executor {
protected static final Map<String, String> MAIN_CLASSES =
Map.of("mvn", "org.apache.maven.cling.MavenCling", "mvnenc", "org.apache.maven.cling.MavenEncCling");
protected static final class Context {
private final URLClassLoader bootClassLoader;
private final String version;
@ -62,7 +66,7 @@ public class EmbeddedMavenExecutor implements Executor {
private final ClassLoader tccl;
private final Function<ExecutorRequest, Integer> exec;
public Context(
private Context(
URLClassLoader bootClassLoader,
String version,
Object classWorld,
@ -78,13 +82,38 @@ public class EmbeddedMavenExecutor implements Executor {
}
}
protected static class Key {
private final Path installationDirectory;
private final String command;
private Key(Path installationDirectory, String command) {
this.installationDirectory = installationDirectory;
this.command = command;
}
@Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) {
return false;
}
Key key = (Key) o;
return Objects.equals(installationDirectory, key.installationDirectory)
&& Objects.equals(command, key.command);
}
@Override
public int hashCode() {
return Objects.hash(installationDirectory, command);
}
}
protected final boolean cacheContexts;
protected final AtomicBoolean closed;
protected final PrintStream originalStdout;
protected final PrintStream originalStderr;
protected final Properties originalProperties;
protected final ClassLoader originalClassLoader;
protected final ConcurrentHashMap<Path, Context> contexts;
protected final ConcurrentHashMap<Key, Context> contexts;
public EmbeddedMavenExecutor() {
this(true);
@ -163,8 +192,10 @@ public class EmbeddedMavenExecutor implements Executor {
protected Context mayCreate(ExecutorRequest executorRequest) {
Path mavenHome = ExecutorRequest.getCanonicalPath(executorRequest.installationDirectory());
String command = executorRequest.command();
Key key = new Key(mavenHome, command);
if (cacheContexts) {
return contexts.computeIfAbsent(mavenHome, k -> doCreate(mavenHome, executorRequest));
return contexts.computeIfAbsent(key, k -> doCreate(mavenHome, executorRequest));
} else {
return doCreate(mavenHome, executorRequest);
}
@ -172,9 +203,9 @@ public class EmbeddedMavenExecutor implements Executor {
protected Context doCreate(Path mavenHome, ExecutorRequest executorRequest) {
if (!Files.isDirectory(mavenHome)) {
throw new IllegalArgumentException("Installation directory must point to existing directory");
throw new IllegalArgumentException("Installation directory must point to existing directory: " + mavenHome);
}
if (!Objects.equals(executorRequest.command(), ExecutorRequest.MVN)) {
if (!MAIN_CLASSES.containsKey(executorRequest.command())) {
throw new IllegalArgumentException(
getClass().getSimpleName() + " does not support command " + executorRequest.command());
}
@ -187,7 +218,8 @@ public class EmbeddedMavenExecutor implements Executor {
Path boot = mavenHome.resolve("boot");
Path m2conf = mavenHome.resolve("bin/m2.conf");
if (!Files.isDirectory(boot) || !Files.isRegularFile(m2conf)) {
throw new IllegalArgumentException("Installation directory does not point to Maven installation");
throw new IllegalArgumentException(
"Installation directory does not point to Maven installation: " + mavenHome);
}
Properties properties = prepareProperties(executorRequest);
@ -220,6 +252,10 @@ public class EmbeddedMavenExecutor implements Executor {
if (version.startsWith("3.")) {
// 3.x
if (!ExecutorRequest.MVN.equals(executorRequest.command())) {
throw new IllegalArgumentException(getClass().getSimpleName() + "w/ mvn3 does not support command "
+ executorRequest.command());
}
Constructor<?> newMavenCli = cliClass.getConstructor(classWorld.getClass());
Object mavenCli = newMavenCli.newInstance(classWorld);
Class<?>[] parameterTypes = {String[].class, String.class, PrintStream.class, PrintStream.class};
@ -284,7 +320,8 @@ public class EmbeddedMavenExecutor implements Executor {
properties.setProperty("maven.home", mavenHome.toString());
properties.setProperty(
"maven.multiModuleProjectDirectory", request.cwd().toString());
properties.setProperty("maven.mainClass", "org.apache.maven.cling.MavenCling");
String mainClass = requireNonNull(MAIN_CLASSES.get(request.command()), "mainClass");
properties.setProperty("maven.mainClass", mainClass);
properties.setProperty(
"library.jline.path", mavenHome.resolve("lib/jline-native").toString());
// TODO: is this needed?

View File

@ -22,7 +22,6 @@ import java.nio.file.Path;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.maven.api.annotations.Nullable;
@ -112,8 +111,7 @@ public class HelperImpl implements ExecutorHelper {
}
private Executor getExecutorByRequest(ExecutorRequest request) {
if (Objects.equals(request.command(), ExecutorRequest.MVN)
&& request.environmentVariables().orElse(Collections.emptyMap()).isEmpty()
if (request.environmentVariables().orElse(Collections.emptyMap()).isEmpty()
&& request.jvmArguments().orElse(Collections.emptyList()).isEmpty()) {
return getExecutor(Mode.EMBEDDED, request);
} else {

View File

@ -35,6 +35,25 @@ import org.junit.jupiter.api.io.TempDir;
import static org.junit.jupiter.api.Assertions.assertEquals;
public abstract class MavenExecutorTestSupport {
@Test
void mvnenc(
@TempDir(cleanup = CleanupMode.ON_SUCCESS) Path cwd,
@TempDir(cleanup = CleanupMode.ON_SUCCESS) Path userHome)
throws Exception {
String logfile = "m4.log";
execute(
cwd.resolve(logfile),
List.of(mvn4ExecutorRequestBuilder()
.command("mvnenc")
.cwd(cwd)
.userHomeDirectory(userHome)
.argument("diag")
.argument("-l")
.argument(logfile)
.build()));
System.out.println(Files.readString(cwd.resolve(logfile)));
}
@Disabled("JUnit on Windows fails to clean up as mvn3 seems does not close log file properly")
@Test
void dump3(

View File

@ -715,7 +715,7 @@ under the License.
<unzip dest="${mavenHome}" src="${project.build.directory}/maven-bin.zip">
<globmapper from="apache-maven-${mavenVersion}/*" handledirsep="true" to="*" />
</unzip>
<chmod dir="${mavenHome}/bin" includes="mvn,mvnDebug" perm="ugo+rx" />
<chmod dir="${mavenHome}/bin" includes="mvn,mvnDebug,mvnenc" perm="ugo+rx" />
</target>
</configuration>
</execution>
@ -758,7 +758,7 @@ under the License.
<unzip dest="${mavenHome}" src="${mavenDistro}">
<regexpmapper from="^([^/]+)/(.*)$" handledirsep="true" to="\2" />
</unzip>
<chmod dir="${mavenHome}/bin" includes="mvn,mvnDebug" perm="ugo+rx" />
<chmod dir="${mavenHome}/bin" includes="mvn,mvnDebug,mvnenc" perm="ugo+rx" />
</target>
</configuration>
</execution>

View File

@ -0,0 +1,73 @@
/*
* 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.it;
import java.nio.file.Path;
import org.junit.jupiter.api.Test;
/**
* This is a test set for <a href="https://issues.apache.org/jira/browse/MNG-8421">MNG-8421</a>.
*/
class MavenITmng8421MavenEncryptionTest extends AbstractMavenIntegrationTestCase {
MavenITmng8421MavenEncryptionTest() {
super("[4.0.0-rc-2-SNAPSHOT,)");
}
/**
* Verify that empty home causes diag output as expected.
*/
@Test
void testEmptyHome() throws Exception {
Path basedir = extractResources("/mng-8421").getAbsoluteFile().toPath();
Path home = basedir.resolve("home1");
Verifier verifier = newVerifier(basedir.toString());
verifier.setLogFileName("home1.txt");
verifier.setUserHomeDirectory(home);
verifier.setExecutable("mvnenc");
verifier.addCliArgument("diag");
verifier.execute();
verifier.verifyTextInLog("[ERROR]");
verifier.verifyTextInLog("No configuration file found");
verifier.verifyTextInLog("settings-security4.xml");
}
/**
* Verify that set-upo home causes diag output as expected.
*/
@Test
void testSetupHome() throws Exception {
Path basedir = extractResources("/mng-8421").getAbsoluteFile().toPath();
Path home = basedir.resolve("home2");
Verifier verifier = newVerifier(basedir.toString());
verifier.setLogFileName("home2.txt");
verifier.setUserHomeDirectory(home);
verifier.setExecutable("mvnenc");
verifier.addCliArgument("diag");
verifier.execute();
verifier.verifyErrorFreeLog();
verifier.verifyTextInLog("[INFO] Configuration validation of MavenSecDispatcher: VALID");
verifier.verifyTextInLog("[WARNING] Configured environment variable not exist");
}
}

View File

@ -100,6 +100,7 @@ public class TestSuiteOrdering implements ClassOrderer {
* the tests are to finishing. Newer tests are also more likely to fail, so this is
* a fail fast technique as well.
*/
suite.addTestSuite(MavenITmng8421MavenEncryptionTest.class);
suite.addTestSuite(MavenITmng8400CanonicalMavenHomeTest.class);
suite.addTestSuite(MavenITmng8385PropertyContributoSPITest.class);
suite.addTestSuite(MavenITmng8383UnknownTypeDependenciesTest.class);

View File

@ -0,0 +1 @@
This is an empty home

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<settingsSecurity>
<!-- created with Maven 3.9.9: "masterpassword" -->
<master>{biSS3+PaKIMH9acY9wBZjfuzSTrkkrXjgDa7jWvW+ew=}</master>
</settingsSecurity>

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<settingsSecurity xmlns="http://codehaus-plexus.github.io/plexus-sec-dispatcher/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://codehaus-plexus.github.io/plexus-sec-dispatcher/4.0.0 https://codehaus-plexus.github.io/xsd/plexus-sec-dispatcher-4.0.0.xsd">
<modelVersion>4.0</modelVersion>
<defaultDispatcher>master</defaultDispatcher>
<configurations>
<configuration>
<name>master</name>
<properties>
<property>
<name>source</name>
<value>env:MAVEN_MASTER_PASSWORD</value>
</property>
<property>
<name>cipher</name>
<value>AES/GCM/NoPadding</value>
</property>
</properties>
</configuration>
</configurations>
</settingsSecurity>

View File

@ -0,0 +1 @@
This is fully setup home

View File

@ -92,7 +92,7 @@ public class Verifier {
private final Path tempBasedir; // empty basedir for queries
private final Path userHomeDirectory;
private Path userHomeDirectory;
private final List<String> defaultCliArguments;
@ -102,6 +102,8 @@ public class Verifier {
private final List<String> cliArguments = new ArrayList<>();
private String executable = ExecutorRequest.MVN;
private boolean autoClean = true;
private boolean forkJvm = false;
@ -144,8 +146,16 @@ public class Verifier {
}
}
public void setUserHomeDirectory(Path userHomeDirectory) {
this.userHomeDirectory = requireNonNull(userHomeDirectory);
}
public String getExecutable() {
return ExecutorRequest.MVN;
return executable;
}
public void setExecutable(String executable) {
this.executable = requireNonNull(executable);
}
public void execute() throws VerificationException {
@ -221,6 +231,7 @@ public class Verifier {
try {
ExecutorRequest.Builder builder = executorHelper
.executorRequest()
.command(executable)
.cwd(basedir)
.userHomeDirectory(userHomeDirectory)
.arguments(args);