mirror of
https://github.com/apache/maven-mvnd.git
synced 2026-01-13 07:04:14 +08:00
Let -h/--help display also mvnd specific options #243
This commit is contained in:
@@ -19,12 +19,10 @@
|
||||
package org.apache.maven.cli;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -96,6 +94,7 @@ import org.mvndaemon.mvnd.common.Environment;
|
||||
import org.mvndaemon.mvnd.logging.internal.Slf4jLoggerManager;
|
||||
import org.mvndaemon.mvnd.logging.smart.AbstractLoggingSpy;
|
||||
import org.mvndaemon.mvnd.logging.smart.LoggingExecutionListener;
|
||||
import org.mvndaemon.mvnd.logging.smart.LoggingOutputStream;
|
||||
import org.slf4j.ILoggerFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -252,7 +251,7 @@ public class DaemonMavenCli {
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
System.err.println("Unable to parse maven.config: " + e.getMessage());
|
||||
cliManager.displayHelp(System.out);
|
||||
AbstractLoggingSpy.instance().append(MvndHelpFormatter.displayHelp(cliManager));
|
||||
throw e;
|
||||
}
|
||||
|
||||
@@ -264,16 +263,12 @@ public class DaemonMavenCli {
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
System.err.println("Unable to parse command line options: " + e.getMessage());
|
||||
cliManager.displayHelp(System.out);
|
||||
AbstractLoggingSpy.instance().append(MvndHelpFormatter.displayHelp(cliManager));
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (cliRequest.commandLine.hasOption(CLIManager.HELP)) {
|
||||
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try (PrintStream out = new PrintStream(baos, false, StandardCharsets.UTF_8.name())) {
|
||||
cliManager.displayHelp(out);
|
||||
}
|
||||
AbstractLoggingSpy.instance().append(null, new String(baos.toByteArray(), StandardCharsets.UTF_8));
|
||||
AbstractLoggingSpy.instance().append(MvndHelpFormatter.displayHelp(cliManager));
|
||||
throw new ExitException(0);
|
||||
}
|
||||
|
||||
@@ -342,6 +337,11 @@ public class DaemonMavenCli {
|
||||
MessageUtils.setColorEnabled(false);
|
||||
}
|
||||
|
||||
// Workaround for https://github.com/mvndaemon/mvnd/issues/39
|
||||
final ch.qos.logback.classic.Logger mvndLogger = (ch.qos.logback.classic.Logger) slf4jLoggerFactory
|
||||
.getLogger("org.mvndaemon.mvnd");
|
||||
mvndLogger.setLevel(ch.qos.logback.classic.Level.toLevel(System.getProperty("mvnd.log.level", "INFO")));
|
||||
|
||||
// LOG STREAMS
|
||||
if (cliRequest.commandLine.hasOption(CLIManager.LOG_FILE)) {
|
||||
File logFile = new File(cliRequest.commandLine.getOptionValue(CLIManager.LOG_FILE));
|
||||
@@ -357,17 +357,16 @@ public class DaemonMavenCli {
|
||||
// Ignore
|
||||
//
|
||||
}
|
||||
} else {
|
||||
System.setOut(new LoggingOutputStream(s -> mvndLogger.info("[stdout] " + s)).printStream());
|
||||
System.setErr(new LoggingOutputStream(s -> mvndLogger.error("[stderr] " + s)).printStream());
|
||||
}
|
||||
|
||||
// Workaround for https://github.com/mvndaemon/mvnd/issues/39
|
||||
ch.qos.logback.classic.Logger mvndLogger = (ch.qos.logback.classic.Logger) slf4jLoggerFactory
|
||||
.getLogger("org.mvndaemon.mvnd");
|
||||
mvndLogger.setLevel(ch.qos.logback.classic.Level.toLevel(System.getProperty("mvnd.log.level", "INFO")));
|
||||
}
|
||||
|
||||
private void version(CliRequest cliRequest) throws ExitException {
|
||||
if (cliRequest.debug || cliRequest.commandLine.hasOption(CLIManager.VERSION)) {
|
||||
AbstractLoggingSpy.instance().append(null, CLIReportingUtils.showVersion());
|
||||
AbstractLoggingSpy.instance().append(CLIReportingUtils.showVersion());
|
||||
if (cliRequest.commandLine.hasOption(CLIManager.VERSION)) {
|
||||
throw new ExitException(0);
|
||||
}
|
||||
|
||||
183
daemon/src/main/java/org/apache/maven/cli/MvndHelpFormatter.java
Normal file
183
daemon/src/main/java/org/apache/maven/cli/MvndHelpFormatter.java
Normal file
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed 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.cli;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import org.apache.commons.cli.HelpFormatter;
|
||||
import org.mvndaemon.mvnd.common.Environment;
|
||||
import org.mvndaemon.mvnd.common.OptionType;
|
||||
|
||||
/**
|
||||
* Combines the help message from the stock Maven with {@code mvnd}'s help message.
|
||||
*/
|
||||
public class MvndHelpFormatter {
|
||||
private static final Pattern HTML_TAGS_PATTERN = Pattern.compile("<[^>]*>");
|
||||
private static final Pattern COLUMNS_DETECTOR_PATTERN = Pattern.compile("^[ ]+[^s]");
|
||||
private static final Pattern WS_PATTERN = Pattern.compile("\\s+");
|
||||
|
||||
static String toPlainText(String javadocText) {
|
||||
return HTML_TAGS_PATTERN.matcher(javadocText).replaceAll("");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Maven option descriptions combined with mvnd options descriptions
|
||||
*
|
||||
* @param cliManager
|
||||
* @return the string containing the help message
|
||||
*/
|
||||
public static String displayHelp(CLIManager cliManager) {
|
||||
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try (PrintStream out = new PrintStream(baos, false, StandardCharsets.UTF_8.name())) {
|
||||
cliManager.displayHelp(out);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
final String mvnHelp = new String(baos.toByteArray(), StandardCharsets.UTF_8);
|
||||
final Matcher m = COLUMNS_DETECTOR_PATTERN.matcher(mvnHelp);
|
||||
final String indent = m.find() ? m.group() : " ";
|
||||
|
||||
final String lineSeparator = System.lineSeparator();
|
||||
final StringBuilder help = new StringBuilder(mvnHelp)
|
||||
.append(lineSeparator)
|
||||
.append("mvnd specific options:")
|
||||
.append(lineSeparator);
|
||||
|
||||
Environment.documentedEntries()
|
||||
.forEach(entry -> {
|
||||
final Environment env = entry.getEntry();
|
||||
help.append(lineSeparator);
|
||||
int indentPos = help.length() + indent.length();
|
||||
int lineEnd = help.length() + HelpFormatter.DEFAULT_WIDTH;
|
||||
spaces(help, HelpFormatter.DEFAULT_LEFT_PAD);
|
||||
help
|
||||
.append("-D")
|
||||
.append(env.getProperty())
|
||||
.append("=<")
|
||||
.append(env.getType().name().toLowerCase(Locale.ROOT))
|
||||
.append('>');
|
||||
|
||||
final List<String> opts = env.getOptions();
|
||||
if (!opts.isEmpty()) {
|
||||
for (String opt : opts) {
|
||||
help
|
||||
.append(',')
|
||||
.append(opt);
|
||||
}
|
||||
help
|
||||
.append(" <")
|
||||
.append(env.getType().name().toLowerCase(Locale.ROOT))
|
||||
.append('>');
|
||||
}
|
||||
help.append(' ');
|
||||
|
||||
spaces(help, indentPos - help.length());
|
||||
wrap(help, toPlainText(entry.getJavaDoc()), HelpFormatter.DEFAULT_WIDTH, lineEnd, indent);
|
||||
|
||||
indentedLine(help, "Default", env.getDefault(), indent);
|
||||
indentedLine(help, "Env. variable", env.getEnvironmentVariable(), indent);
|
||||
|
||||
});
|
||||
|
||||
help
|
||||
.append(lineSeparator)
|
||||
.append(lineSeparator)
|
||||
.append("mvnd value types:")
|
||||
.append(lineSeparator);
|
||||
|
||||
OptionType.documentedEntries()
|
||||
.forEach(entry -> {
|
||||
final OptionType type = entry.getEntry();
|
||||
help.append(lineSeparator);
|
||||
int indentPos = help.length() + indent.length();
|
||||
int lineEnd = help.length() + HelpFormatter.DEFAULT_WIDTH;
|
||||
spaces(help, HelpFormatter.DEFAULT_LEFT_PAD);
|
||||
help.append(type.name().toLowerCase(Locale.ROOT));
|
||||
spaces(help, indentPos - help.length());
|
||||
wrap(help, toPlainText(entry.getJavaDoc()), HelpFormatter.DEFAULT_WIDTH, lineEnd, indent);
|
||||
});
|
||||
|
||||
return help.toString();
|
||||
}
|
||||
|
||||
private static void indentedLine(final StringBuilder stringBuilder, String key, final String value, final String indent) {
|
||||
int lineEnd;
|
||||
if (value != null) {
|
||||
lineEnd = stringBuilder.length() + HelpFormatter.DEFAULT_WIDTH;
|
||||
stringBuilder
|
||||
.append(System.lineSeparator())
|
||||
.append(indent);
|
||||
wrap(stringBuilder, key + ": " + value, HelpFormatter.DEFAULT_WIDTH, lineEnd, indent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Word-wrap the given {@code text} to the given {@link StringBuilder}
|
||||
*
|
||||
* @param stringBuilder the {@link StringBuilder} to append to
|
||||
* @param text the text to wrap and append
|
||||
* @param lineLength the preferred line length
|
||||
* @param nextLineEnd the length of the {@code stringBuilder} at which the current line should end
|
||||
* @param indent the indentation string
|
||||
*/
|
||||
static void wrap(StringBuilder stringBuilder, String text, int lineLength, int nextLineEnd, String indent) {
|
||||
final StringTokenizer st = new StringTokenizer(text, " \t\n\r", true);
|
||||
String lastWs = null;
|
||||
while (st.hasMoreTokens()) {
|
||||
final String token = st.nextToken();
|
||||
if (WS_PATTERN.matcher(token).matches()) {
|
||||
lastWs = token;
|
||||
} else {
|
||||
if (stringBuilder.length() + token.length() + (lastWs != null ? lastWs.length() : 0) < nextLineEnd) {
|
||||
if (lastWs != null) {
|
||||
stringBuilder.append(lastWs);
|
||||
}
|
||||
stringBuilder.append(token);
|
||||
|
||||
} else {
|
||||
nextLineEnd = stringBuilder.length() + lineLength;
|
||||
stringBuilder
|
||||
.append(System.lineSeparator())
|
||||
.append(indent)
|
||||
.append(token);
|
||||
}
|
||||
lastWs = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Append {@code count} spaces to the given {@code stringBuilder}
|
||||
*
|
||||
* @param stringBuilder the {@link StringBuilder} to append to
|
||||
* @param count the number of spaces to append
|
||||
* @return the given {@code stringBuilder}
|
||||
*/
|
||||
static StringBuilder spaces(StringBuilder stringBuilder, int count) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
stringBuilder.append(' ');
|
||||
}
|
||||
return stringBuilder;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -121,8 +121,7 @@ public class Server implements AutoCloseable, Runnable {
|
||||
List<String> opts = new ArrayList<>();
|
||||
Arrays.stream(Environment.values())
|
||||
.filter(Environment::isDiscriminating)
|
||||
.map(v -> v.getProperty() + "=" + v.asString())
|
||||
.forEach(opts::add);
|
||||
.forEach(envKey -> envKey.asOptional().ifPresent(val -> opts.add(envKey.getProperty() + "=" + val)));
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(opts.stream().collect(Collectors.joining(
|
||||
"\n ", "Initializing daemon with properties:\n ", "\n")));
|
||||
@@ -638,11 +637,13 @@ public class Server implements AutoCloseable, Runnable {
|
||||
this.queue = queue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish(int exitCode) throws Exception {
|
||||
queue.add(new Message.BuildFinished(exitCode));
|
||||
queue.add(Message.STOP_SINGLETON);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail(Throwable t) throws Exception {
|
||||
queue.add(new BuildException(t));
|
||||
queue.add(Message.STOP_SINGLETON);
|
||||
|
||||
@@ -34,11 +34,21 @@ public abstract class AbstractLoggingSpy {
|
||||
AbstractLoggingSpy.instance = instance;
|
||||
}
|
||||
|
||||
public void append(String event) {
|
||||
append(null, event);
|
||||
}
|
||||
|
||||
public void append(String projectId, String event) {
|
||||
String msg = event.endsWith("\n") ? event.substring(0, event.length() - 1) : event;
|
||||
onProjectLog(projectId, msg);
|
||||
}
|
||||
|
||||
public void finish(int exitCode) throws Exception {
|
||||
}
|
||||
|
||||
public void fail(Throwable t) throws Exception {
|
||||
}
|
||||
|
||||
protected void notifySessionStart(ExecutionEvent event) {
|
||||
onStartSession(event.getSession());
|
||||
}
|
||||
|
||||
@@ -17,20 +17,12 @@ package org.mvndaemon.mvnd.logging.smart;
|
||||
|
||||
import org.apache.maven.execution.ExecutionEvent;
|
||||
import org.apache.maven.execution.ExecutionListener;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.MDC;
|
||||
|
||||
public class LoggingExecutionListener implements ExecutionListener {
|
||||
|
||||
private final ExecutionListener delegate;
|
||||
|
||||
static {
|
||||
Logger logger = LoggerFactory.getLogger("org.mvndaemon.mvnd");
|
||||
System.setOut(new LoggingOutputStream(s -> logger.info("[stdout] " + s)).printStream());
|
||||
System.setErr(new LoggingOutputStream(s -> logger.info("[stderr] " + s)).printStream());
|
||||
}
|
||||
|
||||
public LoggingExecutionListener(ExecutionListener delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user