Skip to content

Commit

Permalink
#754: bullet proof solution for processable output and logging (#777)
Browse files Browse the repository at this point in the history
  • Loading branch information
hohwille authored Nov 21, 2024
1 parent d706ab4 commit d3dfb95
Show file tree
Hide file tree
Showing 31 changed files with 658 additions and 494 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.devonfw.tools.ide.context.IdeContext;
import com.devonfw.tools.ide.context.IdeStartContextImpl;
import com.devonfw.tools.ide.log.IdeLogLevel;
import com.devonfw.tools.ide.log.IdeLogListenerBuffer;
import com.devonfw.tools.ide.log.IdeSubLoggerOut;
import com.devonfw.tools.ide.property.FlagProperty;
import com.devonfw.tools.ide.property.LocaleProperty;
Expand Down Expand Up @@ -61,10 +62,11 @@ public void run() {

IdeLogLevel logLevel = determineLogLevel();
if (this.startContext == null) {
this.startContext = new IdeStartContextImpl(logLevel, level -> new IdeSubLoggerOut(level, null, true, logLevel));
final IdeLogListenerBuffer buffer = new IdeLogListenerBuffer();
this.startContext = new IdeStartContextImpl(logLevel, level -> new IdeSubLoggerOut(level, null, true, logLevel, buffer));
} else if (this.context != null) {
IdeStartContextImpl newStartContext = ((AbstractIdeContext) this.context).getStartContext();
assert (this.startContext == newStartContext);
assert (this.startContext == newStartContext); // fast fail during development via assert
this.startContext = newStartContext;
}
this.startContext.setBatchMode(this.batch.isTrue());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package com.devonfw.tools.ide.commandlet;

import com.devonfw.tools.ide.context.IdeContext;
import com.devonfw.tools.ide.log.IdeLogLevel;
import com.devonfw.tools.ide.log.IdeSubLogger;
import com.devonfw.tools.ide.property.FlagProperty;
import com.devonfw.tools.ide.property.ToolProperty;
import com.devonfw.tools.ide.tool.ToolCommandlet;
import com.devonfw.tools.ide.version.VersionIdentifier;

/**
* An internal {@link Commandlet} to get the installed edition for a tool.
Expand Down Expand Up @@ -53,42 +54,35 @@ public void run() {

ToolCommandlet commandlet = this.tool.getValue();
String configuredEdition = commandlet.getConfiguredEdition();
IdeSubLogger logger = this.context.level(IdeLogLevel.PROCESSABLE);

if (this.installed.isTrue() && !this.configured.isTrue()) { // get installed edition

VersionIdentifier installedVersion = commandlet.getInstalledVersion();
if (installedVersion == null) {
this.context.info("No installation of tool {} was found.", commandlet.getName());
toolInstallInfo(commandlet.getName(), configuredEdition);
String installedEdition = commandlet.getInstalledEdition();
if (commandlet.getInstalledVersion() == null) {
// note: getInstalledEdition() will fallback to configured edition and not return null, therefore we use getInstalledVersion()
toolInstallInfo(commandlet.getName(), configuredEdition, null, commandlet);
} else {
String installedEdition = commandlet.getInstalledEdition();
this.context.info(installedEdition);
logger.log(installedEdition);
}

} else if (!this.installed.isTrue() && this.configured.isTrue()) { // get configured edition

this.context.info(configuredEdition);

logger.log(configuredEdition);
} else { // get both configured and installed edition
String installedEdition = commandlet.getInstalledEdition();

if (configuredEdition.equals(installedEdition)) {
this.context.info(installedEdition);
logger.log(installedEdition);
} else {
if (installedEdition == null) {
this.context.info("No installation of tool {} was found.", commandlet.getName());
} else {
this.context.info("The installed edition for tool {} is {}", commandlet.getName(), installedEdition);
}
toolInstallInfo(commandlet.getName(), configuredEdition);
toolInstallInfo(commandlet.getName(), configuredEdition, installedEdition, commandlet);
}

}

}

private void toolInstallInfo(String toolName, String configuredEdition) {
private void toolInstallInfo(String toolName, String configuredEdition, String installedEdition, ToolCommandlet commandlet) {

if (installedEdition == null) {
this.context.warning("No installation of tool {} was found.", commandlet.getName());
} else {
this.context.info("The installed edition for tool {} is {}", commandlet.getName(), installedEdition);
}
this.context.info("The configured edition for tool {} is {}", toolName, configuredEdition);
this.context.info("To install that edition call the following command:");
this.context.info("ide install {}", toolName);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.devonfw.tools.ide.commandlet;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
Expand All @@ -9,6 +8,8 @@
import com.devonfw.tools.ide.context.IdeContext;
import com.devonfw.tools.ide.environment.EnvironmentVariablesType;
import com.devonfw.tools.ide.environment.VariableLine;
import com.devonfw.tools.ide.log.IdeLogLevel;
import com.devonfw.tools.ide.log.IdeSubLogger;
import com.devonfw.tools.ide.os.WindowsPathSyntax;
import com.devonfw.tools.ide.property.FlagProperty;

Expand Down Expand Up @@ -55,6 +56,7 @@ public void run() {

boolean winCmd = false;
WindowsPathSyntax pathSyntax = null;
IdeSubLogger logger = this.context.level(IdeLogLevel.PROCESSABLE);
if (this.context.getSystemInfo().isWindows()) {
if (this.bash.isTrue()) {
pathSyntax = WindowsPathSyntax.MSYS;
Expand All @@ -77,31 +79,31 @@ public void run() {
this.context.debug("from {}:", line.getSource());
sourcePrinted = true;
}
printEnvLine(line);
logger.log(format(line, winCmd));
}
}
}
} else {
sortVariables(variables);
for (VariableLine line : variables) {
if (winCmd) {
// MS-Dos (aka CMD) has no concept of exported variables
this.context.info(line.getName() + "=" + line.getValue() + "");
} else {
printEnvLine(line);
}
logger.log(format(line, winCmd));
}
}
}

private static void sortVariables(List<VariableLine> lines) {
Collections.sort(lines, (c1, c2) -> c1.getName().compareTo(c2.getName()));
lines.sort((c1, c2) -> c1.getName().compareTo(c2.getName()));
}

private void printEnvLine(VariableLine line) {
String lineValue = line.getValue();
lineValue = "\"" + lineValue + "\"";
line = line.withValue(lineValue);
this.context.info(line.toString());
private String format(VariableLine line, boolean winCmd) {

if (winCmd) {
return line.getName() + "=" + line.getValue();
} else {
String lineValue = line.getValue();
lineValue = "\"" + lineValue + "\"";
line = line.withValue(lineValue);
return line.toString();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.devonfw.tools.ide.commandlet;

import com.devonfw.tools.ide.context.IdeContext;
import com.devonfw.tools.ide.log.IdeLogLevel;
import com.devonfw.tools.ide.property.FlagProperty;
import com.devonfw.tools.ide.version.IdeVersion;

Expand Down Expand Up @@ -41,6 +42,6 @@ public boolean isProcessableOutput() {
@Override
public void run() {

this.context.info(IdeVersion.get());
this.context.level(IdeLogLevel.PROCESSABLE).log(IdeVersion.get());
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.devonfw.tools.ide.commandlet;

import com.devonfw.tools.ide.context.IdeContext;
import com.devonfw.tools.ide.log.IdeLogLevel;
import com.devonfw.tools.ide.log.IdeSubLogger;
import com.devonfw.tools.ide.property.FlagProperty;
import com.devonfw.tools.ide.property.ToolProperty;
import com.devonfw.tools.ide.tool.ToolCommandlet;
Expand Down Expand Up @@ -53,41 +55,33 @@ public void run() {

ToolCommandlet commandlet = this.tool.getValue();
VersionIdentifier configuredVersion = commandlet.getConfiguredVersion();

IdeSubLogger logger = this.context.level(IdeLogLevel.PROCESSABLE);
if (this.installed.isTrue() && !this.configured.isTrue()) {// get installed version

VersionIdentifier installedVersion = commandlet.getInstalledVersion();
if (installedVersion == null) {
this.context.info("No installation of tool {} was found.", commandlet.getName());
toolInstallInfo(commandlet.getName(), configuredVersion);
toolInstallInfo(commandlet.getName(), configuredVersion, null, commandlet);
} else {
this.context.info(installedVersion.toString());
logger.log(installedVersion.toString());
}

} else if (!this.installed.isTrue() && this.configured.isTrue()) {// get configured version

this.context.info(configuredVersion.toString());

logger.log(configuredVersion.toString());
} else { // get both configured and installed version

VersionIdentifier installedVersion = commandlet.getInstalledVersion();
if (configuredVersion.matches(installedVersion)) {
this.context.info(installedVersion.toString());
logger.log(installedVersion.toString());
} else {
if (installedVersion == null) {
this.context.info("No installation of tool {} was found.", commandlet.getName());
} else {
this.context.info("The installed version for tool {} is {}", commandlet.getName(), installedVersion);
}
toolInstallInfo(commandlet.getName(), configuredVersion);
toolInstallInfo(commandlet.getName(), configuredVersion, installedVersion, commandlet);
}

}

}

private void toolInstallInfo(String toolName, VersionIdentifier configuredVersion) {
private void toolInstallInfo(String toolName, VersionIdentifier configuredVersion, VersionIdentifier installedVersion, ToolCommandlet commandlet) {

if (installedVersion == null) {
this.context.info("No installation of tool {} was found.", commandlet.getName());
} else {
this.context.info("The installed version for tool {} is {}", commandlet.getName(), installedVersion);
}
this.context.info("The configured version for tool {} is {}", toolName, configuredVersion);
this.context.info("To install that version call the following command:");
this.context.info("ide install {}", toolName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -828,12 +828,14 @@ private ValidationResult applyAndRun(CliArguments arguments, Commandlet cmd) {
if (!debug().isEnabled()) {
// unless --debug or --trace was supplied, processable output commandlets will disable all log-levels except INFO to prevent other logs interfere
for (IdeLogLevel level : IdeLogLevel.values()) {
if (level != IdeLogLevel.INFO) {
if (level != IdeLogLevel.PROCESSABLE) {
this.startContext.setLogLevel(level, false);
}
}
}
this.startContext.activateLogging();
} else {
this.startContext.activateLogging();
if (!isTest()) {
if (this.ideRoot == null) {
warning("Variable IDE_ROOT is undefined. Please check your installation or run setup script again.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class IdeContextConsole extends AbstractIdeContext {
*/
public IdeContextConsole(IdeLogLevel minLogLevel, Appendable out, boolean colored) {

super(new IdeStartContextImpl(minLogLevel, level -> new IdeSubLoggerOut(level, out, colored, minLogLevel)), null);
super(new IdeStartContextImpl(minLogLevel, level -> new IdeSubLoggerOut(level, out, colored, minLogLevel, null)), null);
if (System.console() == null) {
debug("System console not available - using System.in as fallback");
this.scanner = new Scanner(System.in);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
package com.devonfw.tools.ide.context;

import java.util.Locale;
import java.util.Objects;
import java.util.function.Function;

import com.devonfw.tools.ide.log.AbstractIdeSubLogger;
import com.devonfw.tools.ide.log.IdeLogLevel;
import com.devonfw.tools.ide.log.IdeLoggerImpl;
import com.devonfw.tools.ide.log.IdeSubLogger;
import com.devonfw.tools.ide.log.IdeSubLoggerNone;

/**
* Implementation of {@link IdeStartContext}.
*/
public class IdeStartContextImpl implements IdeStartContext {

private final Function<IdeLogLevel, IdeSubLogger> loggerFactory;

private final IdeSubLogger[] loggers;
public class IdeStartContextImpl extends IdeLoggerImpl implements IdeStartContext {

private boolean offlineMode;

Expand All @@ -31,48 +27,9 @@ public class IdeStartContextImpl implements IdeStartContext {
* @param minLogLevel the minimum enabled {@link IdeLogLevel}.
* @param factory the factory to create active {@link IdeSubLogger} instances.
*/
public IdeStartContextImpl(IdeLogLevel minLogLevel, Function<IdeLogLevel, IdeSubLogger> factory) {

super();
this.loggerFactory = factory;
this.loggers = new IdeSubLogger[IdeLogLevel.values().length];
setLogLevel(minLogLevel);
}

@Override
public IdeSubLogger level(IdeLogLevel level) {

IdeSubLogger logger = this.loggers[level.ordinal()];
Objects.requireNonNull(logger);
return logger;
}
public IdeStartContextImpl(IdeLogLevel minLogLevel, Function<IdeLogLevel, AbstractIdeSubLogger> factory) {

/**
* Sets the log level.
*
* @param logLevel {@link IdeLogLevel}
*/
public void setLogLevel(IdeLogLevel logLevel) {

for (IdeLogLevel level : IdeLogLevel.values()) {
boolean enabled = level.ordinal() >= logLevel.ordinal();
setLogLevel(level, enabled);
}
}

/**
* @param logLevel the {@link IdeLogLevel} to modify.
* @param enabled - {@code true} to enable, {@code false} to disable.
*/
public void setLogLevel(IdeLogLevel logLevel, boolean enabled) {

IdeSubLogger logger;
if (enabled) {
logger = this.loggerFactory.apply(logLevel);
} else {
logger = IdeSubLoggerNone.of(logLevel);
}
this.loggers[logLevel.ordinal()] = logger;
super(minLogLevel, factory);
}

@Override
Expand Down
Loading

0 comments on commit d3dfb95

Please sign in to comment.