From c10b48d3d2967527f9b3107d369b658a7e910016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Hohwiller?= Date: Tue, 6 Aug 2024 12:23:04 +0200 Subject: [PATCH] #507: improve collect variables (#510) --- .../ide/commandlet/EnvironmentCommandlet.java | 27 +++-- .../devonfw/tools/ide/common/SystemPath.java | 9 +- .../tools/ide/context/AbstractIdeContext.java | 11 +- .../devonfw/tools/ide/context/IdeContext.java | 41 +++++-- .../AbstractEnvironmentVariables.java | 51 +++++---- .../ide/environment/EnvironmentVariables.java | 9 +- .../EnvironmentVariablesPropertiesFile.java | 18 ++-- .../EnvironmentVariablesResolved.java | 6 +- .../tools/ide/environment/VariableLine.java | 16 +-- .../tools/ide/environment/VariableSource.java | 21 ++++ .../com/devonfw/tools/ide/tool/mvn/Mvn.java | 77 ++++++++------ .../tools/ide/variable/IdeVariables.java | 2 +- .../commandlet/EnvironmentCommandletTest.java | 100 ++++++++++++++++-- .../commandlet/VersionListCommandletTest.java | 2 +- .../ide/context/AbstractIdeContextTest.java | 18 +++- .../ide/context/AbstractIdeTestContext.java | 29 +++++ .../tools/ide/context/IdeContextTest.java | 3 +- .../tools/ide/context/IdeTestContext.java | 32 +++++- .../IdeTestContextAssertion.java | 7 +- .../ide/environment/VariableLineTest.java | 2 +- .../devonfw/tools/ide/log/IdeLogEntry.java | 21 +++- .../tools/ide/log/IdeTestLoggerAssertion.java | 63 +++++++---- .../tools/ide/log/IdeTestLoggerFactory.java | 15 +++ .../com/devonfw/tools/ide/step/StepTest.java | 4 +- .../resources/ide-projects/basic/_ide/bin/ide | 2 + .../basic/project/home/environment.properties | 2 + .../basic/project/software/mvn/bin/mvn | 5 + 27 files changed, 439 insertions(+), 154 deletions(-) create mode 100644 cli/src/main/java/com/devonfw/tools/ide/environment/VariableSource.java rename cli/src/test/java/com/devonfw/tools/ide/{log => context}/IdeTestContextAssertion.java (86%) create mode 100644 cli/src/test/resources/ide-projects/basic/_ide/bin/ide create mode 100644 cli/src/test/resources/ide-projects/basic/project/home/environment.properties create mode 100644 cli/src/test/resources/ide-projects/basic/project/software/mvn/bin/mvn diff --git a/cli/src/main/java/com/devonfw/tools/ide/commandlet/EnvironmentCommandlet.java b/cli/src/main/java/com/devonfw/tools/ide/commandlet/EnvironmentCommandlet.java index dd7fa6491..abfc28456 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/commandlet/EnvironmentCommandlet.java +++ b/cli/src/main/java/com/devonfw/tools/ide/commandlet/EnvironmentCommandlet.java @@ -1,10 +1,13 @@ package com.devonfw.tools.ide.commandlet; -import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; import java.util.stream.Collectors; import com.devonfw.tools.ide.context.AbstractIdeContext; 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.os.WindowsPathSyntax; import com.devonfw.tools.ide.property.FlagProperty; @@ -59,23 +62,35 @@ public void run() { } } ((AbstractIdeContext) this.context).setPathSyntax(pathSyntax); - Collection variables = this.context.getVariables().collectVariables(); + List variables = this.context.getVariables().collectVariables(); if (this.context.debug().isEnabled()) { - for (String source : variables.stream().map(VariableLine::getSource).collect(Collectors.toSet())) { - this.context.debug("from {}:", source); - for (VariableLine line : variables) { - if (line.getSource().equals(source)) { + Map> type2lines = variables.stream().collect(Collectors.groupingBy(l -> l.getSource().type())); + for (EnvironmentVariablesType type : EnvironmentVariablesType.values()) { + List lines = type2lines.get(type); + if (lines != null) { + boolean sourcePrinted = false; + sortVariables(lines); + for (VariableLine line : lines) { + if (!sourcePrinted) { + this.context.debug("from {}:", line.getSource()); + sourcePrinted = true; + } printEnvLine(line); } } } } else { + sortVariables(variables); for (VariableLine line : variables) { printEnvLine(line); } } } + private static void sortVariables(List lines) { + Collections.sort(lines, (c1, c2) -> c1.getName().compareTo(c2.getName())); + } + private void printEnvLine(VariableLine line) { String lineValue = line.getValue(); lineValue = "\"" + lineValue + "\""; diff --git a/cli/src/main/java/com/devonfw/tools/ide/common/SystemPath.java b/cli/src/main/java/com/devonfw/tools/ide/common/SystemPath.java index e8c9b7e61..53018396a 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/common/SystemPath.java +++ b/cli/src/main/java/com/devonfw/tools/ide/common/SystemPath.java @@ -137,9 +137,12 @@ private static String getTool(Path path, Path ideRoot) { return null; } if (path.startsWith(ideRoot)) { - int i = ideRoot.getNameCount(); - if (path.getNameCount() > i) { - return path.getName(i).toString(); + Path relativized = ideRoot.relativize(path); + int count = relativized.getNameCount(); + if (count >= 3) { + if (relativized.getName(1).toString().equals("software")) { + return relativized.getName(2).toString(); + } } } return null; diff --git a/cli/src/main/java/com/devonfw/tools/ide/context/AbstractIdeContext.java b/cli/src/main/java/com/devonfw/tools/ide/context/AbstractIdeContext.java index 6f4814c5c..ff4419c07 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/context/AbstractIdeContext.java +++ b/cli/src/main/java/com/devonfw/tools/ide/context/AbstractIdeContext.java @@ -320,7 +320,7 @@ public boolean isMock() { return false; } - private SystemPath computeSystemPath() { + protected SystemPath computeSystemPath() { return new SystemPath(this); } @@ -352,7 +352,7 @@ private Path getParentPath(Path dir) { private EnvironmentVariables createVariables() { - AbstractEnvironmentVariables system = EnvironmentVariables.ofSystem(this); + AbstractEnvironmentVariables system = createSystemVariables(); AbstractEnvironmentVariables user = extendVariables(system, this.userHomeIde, EnvironmentVariablesType.USER); AbstractEnvironmentVariables settings = extendVariables(user, this.settingsPath, EnvironmentVariablesType.SETTINGS); // TODO should we keep this workspace properties? Was this feature ever used? @@ -361,7 +361,12 @@ private EnvironmentVariables createVariables() { return conf.resolved(); } - private AbstractEnvironmentVariables extendVariables(AbstractEnvironmentVariables envVariables, Path propertiesPath, EnvironmentVariablesType type) { + protected AbstractEnvironmentVariables createSystemVariables() { + + return EnvironmentVariables.ofSystem(this); + } + + protected AbstractEnvironmentVariables extendVariables(AbstractEnvironmentVariables envVariables, Path propertiesPath, EnvironmentVariablesType type) { Path propertiesFile = null; if (propertiesPath == null) { diff --git a/cli/src/main/java/com/devonfw/tools/ide/context/IdeContext.java b/cli/src/main/java/com/devonfw/tools/ide/context/IdeContext.java index d0f174184..c36e393b5 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/context/IdeContext.java +++ b/cli/src/main/java/com/devonfw/tools/ide/context/IdeContext.java @@ -372,6 +372,25 @@ default void requireOnline(String purpose) { */ Path getSettingsPath(); + /** + * @return the {@link Path} to the templates folder inside the {@link #getSettingsPath() settings}. The relative directory structure in this templates folder + * is to be applied to {@link #getIdeHome() IDE_HOME} when the project is set up. + */ + default Path getSettingsTemplatePath() { + Path settingsFolder = getSettingsPath(); + Path templatesFolder = settingsFolder.resolve(IdeContext.FOLDER_TEMPLATES); + if (!Files.isDirectory(templatesFolder)) { + Path templatesFolderLegacy = settingsFolder.resolve(IdeContext.FOLDER_LEGACY_TEMPLATES); + if (Files.isDirectory(templatesFolderLegacy)) { + templatesFolder = templatesFolderLegacy; + } else { + warning("No templates found in settings git repo neither in {} nor in {} - configuration broken", templatesFolder, templatesFolderLegacy); + return null; + } + } + return templatesFolder; + } + /** * @return the {@link Path} to the {@code conf} folder with instance specific tool configurations and the * {@link EnvironmentVariablesType#CONF user specific project configuration}. @@ -439,13 +458,11 @@ default String getMavenArgs() { if (getIdeHome() == null) { return null; } - Path confFolder = getConfPath(); - Path mvnSettingsFile = confFolder.resolve(Mvn.MVN_CONFIG_FOLDER).resolve(Mvn.SETTINGS_FILE); + Mvn mvn = getCommandletManager().getCommandlet(Mvn.class); + Path mavenConfFolder = mvn.getMavenConfFolder(false); + Path mvnSettingsFile = mavenConfFolder.resolve(Mvn.SETTINGS_FILE); if (!Files.exists(mvnSettingsFile)) { - mvnSettingsFile = confFolder.resolve(Mvn.MVN_CONFIG_LEGACY_FOLDER).resolve(Mvn.SETTINGS_FILE); - if (!Files.exists(mvnSettingsFile)) { - return null; - } + return null; } String settingsPath; WindowsPathSyntax pathSyntax = getPathSyntax(); @@ -460,10 +477,18 @@ default String getMavenArgs() { /** * @return the String value for the variable M2_REPO, or null if called outside an IDEasy installation. */ - default Path getMavenRepoEnvVariable() { + default Path getMavenRepository() { if (getIdeHome() != null) { - return getConfPath().resolve(Mvn.MVN_CONFIG_LEGACY_FOLDER).resolve("repository"); + Path confPath = getConfPath(); + Path m2Folder = confPath.resolve(Mvn.MVN_CONFIG_FOLDER); + if (!Files.isDirectory(m2Folder)) { + Path m2LegacyFolder = confPath.resolve(Mvn.MVN_CONFIG_LEGACY_FOLDER); + if (Files.isDirectory(m2LegacyFolder)) { + m2Folder = m2LegacyFolder; + } + } + return m2Folder.resolve("repository"); } return null; } diff --git a/cli/src/main/java/com/devonfw/tools/ide/environment/AbstractEnvironmentVariables.java b/cli/src/main/java/com/devonfw/tools/ide/environment/AbstractEnvironmentVariables.java index dae728e2b..41c29df41 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/environment/AbstractEnvironmentVariables.java +++ b/cli/src/main/java/com/devonfw/tools/ide/environment/AbstractEnvironmentVariables.java @@ -2,7 +2,6 @@ import java.nio.file.Path; import java.util.ArrayList; -import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -39,7 +38,7 @@ public abstract class AbstractEnvironmentVariables implements EnvironmentVariabl */ protected final IdeContext context; - private String source; + private VariableSource source; /** * The constructor. @@ -74,14 +73,10 @@ public Path getPropertiesFilePath() { } @Override - public String getSource() { + public VariableSource getSource() { if (this.source == null) { - this.source = getType().toString(); - Path propertiesPath = getPropertiesFilePath(); - if (propertiesPath != null) { - this.source = this.source + "@" + propertiesPath; - } + this.source = new VariableSource(getType(), getPropertiesFilePath()); } return this.source; } @@ -101,44 +96,46 @@ protected boolean isExported(String name) { } @Override - public final Collection collectVariables() { + public final List collectVariables() { return collectVariables(false); } @Override - public final Collection collectExportedVariables() { + public final List collectExportedVariables() { return collectVariables(true); } - private final Collection collectVariables(boolean onlyExported) { + private final List collectVariables(boolean onlyExported) { - Map variableNames = new HashMap<>(); - collectVariables(variableNames); - List variables = new ArrayList<>(variableNames.size()); - for (String name : variableNames.keySet()) { - boolean export = isExported(name); - if (!onlyExported || export) { - String value = get(name, false); - if (value != null) { - variables.add(VariableLine.of(export, name, value, variableNames.get(name))); - } - } - } - return variables; + Map variables = new HashMap<>(); + collectVariables(variables, onlyExported, this); + return new ArrayList<>(variables.values()); } /** * @param variables the {@link Map} where to add the names of the variables defined here as keys, and their corresponding source as value. */ - protected void collectVariables(Map variables) { + protected void collectVariables(Map variables, boolean onlyExported, AbstractEnvironmentVariables resolver) { if (this.parent != null) { - this.parent.collectVariables(variables); + this.parent.collectVariables(variables, onlyExported, resolver); } } + protected VariableLine createVariableLine(String name, boolean onlyExported, AbstractEnvironmentVariables resolver) { + + boolean export = resolver.isExported(name); + if (!onlyExported || export) { + String value = resolver.get(name, false); + if (value != null) { + return VariableLine.of(export, name, value, getSource()); + } + } + return null; + } + /** * @param propertiesFilePath the {@link #getPropertiesFilePath() propertiesFilePath} of the child {@link EnvironmentVariables}. * @param type the {@link #getType() type}. @@ -326,7 +323,7 @@ public String inverseResolve(String string, Object src, VariableSyntax syntax) { @Override public String toString() { - return getSource(); + return getSource().toString(); } /** diff --git a/cli/src/main/java/com/devonfw/tools/ide/environment/EnvironmentVariables.java b/cli/src/main/java/com/devonfw/tools/ide/environment/EnvironmentVariables.java index 9d1c7ff04..246294052 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/environment/EnvironmentVariables.java +++ b/cli/src/main/java/com/devonfw/tools/ide/environment/EnvironmentVariables.java @@ -2,6 +2,7 @@ import java.nio.file.Path; import java.util.Collection; +import java.util.List; import java.util.Locale; import com.devonfw.tools.ide.context.IdeContext; @@ -126,9 +127,9 @@ default EnvironmentVariables getByType(EnvironmentVariablesType type) { Path getPropertiesFilePath(); /** - * @return the source identifier describing this {@link EnvironmentVariables} for debugging. + * @return the {@link VariableSource} of this {@link EnvironmentVariables}. */ - String getSource(); + VariableSource getSource(); /** * @return the parent {@link EnvironmentVariables} to inherit from or {@code null} if this is the {@link EnvironmentVariablesType#SYSTEM root} @@ -180,13 +181,13 @@ default EnvironmentVariables findVariable(String name) { /** * @return the {@link Collection} of the {@link VariableLine}s defined by this {@link EnvironmentVariables} including inheritance. */ - Collection collectVariables(); + List collectVariables(); /** * @return the {@link Collection} of the {@link VariableLine#isExport() exported} {@link VariableLine}s defined by this {@link EnvironmentVariables} including * inheritance. */ - Collection collectExportedVariables(); + List collectExportedVariables(); /** * @param string the {@link String} that potentially contains variables in {@link VariableSyntax#CURLY} ("${«variable«}"). Those will be resolved by this diff --git a/cli/src/main/java/com/devonfw/tools/ide/environment/EnvironmentVariablesPropertiesFile.java b/cli/src/main/java/com/devonfw/tools/ide/environment/EnvironmentVariablesPropertiesFile.java index 6413a15bc..a63f50285 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/environment/EnvironmentVariablesPropertiesFile.java +++ b/cli/src/main/java/com/devonfw/tools/ide/environment/EnvironmentVariablesPropertiesFile.java @@ -21,7 +21,7 @@ /** * Implementation of {@link EnvironmentVariables}. */ -final class EnvironmentVariablesPropertiesFile extends EnvironmentVariablesMap { +public final class EnvironmentVariablesPropertiesFile extends EnvironmentVariablesMap { private static final String NEWLINE = "\n"; @@ -40,11 +40,10 @@ final class EnvironmentVariablesPropertiesFile extends EnvironmentVariablesMap { * * @param parent the parent {@link EnvironmentVariables} to inherit from. * @param type the {@link #getType() type}. - * @param source the {@link #getSource() source}. + * @param propertiesFilePath the {@link #getSource() source}. * @param context the {@link IdeContext}. - * @param variables the underlying variables. */ - EnvironmentVariablesPropertiesFile(AbstractEnvironmentVariables parent, EnvironmentVariablesType type, + public EnvironmentVariablesPropertiesFile(AbstractEnvironmentVariables parent, EnvironmentVariablesType type, Path propertiesFilePath, IdeContext context) { super(parent, context); @@ -73,7 +72,7 @@ private void load() { do { line = reader.readLine(); if (line != null) { - VariableLine variableLine = VariableLine.of(line, this.context, this.propertiesFilePath); + VariableLine variableLine = VariableLine.of(line, this.context, getSource()); String name = variableLine.getName(); if (name != null) { variableLine = migrateLine(variableLine, false); @@ -110,7 +109,7 @@ public void save() { do { line = reader.readLine(); if (line != null) { - VariableLine variableLine = VariableLine.of(line, this.context, reader); + VariableLine variableLine = VariableLine.of(line, this.context, getSource()); lines.add(variableLine); } } while (line != null); @@ -189,13 +188,12 @@ protected Map getVariables() { } @Override - protected void collectVariables(Map variableNames) { + protected void collectVariables(Map variables, boolean onlyExported, AbstractEnvironmentVariables resolver) { for (String key : this.variables.keySet()) { - variableNames.put(key, this.propertiesFilePath.toString()); + variables.computeIfAbsent(key, k -> createVariableLine(key, onlyExported, resolver)); } - - super.collectVariables(variableNames); + super.collectVariables(variables, onlyExported, resolver); } @Override diff --git a/cli/src/main/java/com/devonfw/tools/ide/environment/EnvironmentVariablesResolved.java b/cli/src/main/java/com/devonfw/tools/ide/environment/EnvironmentVariablesResolved.java index 5fe2bd426..3b0ca32d8 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/environment/EnvironmentVariablesResolved.java +++ b/cli/src/main/java/com/devonfw/tools/ide/environment/EnvironmentVariablesResolved.java @@ -49,14 +49,14 @@ public EnvironmentVariables resolved() { } @Override - protected void collectVariables(Map variables) { + protected void collectVariables(Map variables, boolean onlyExported, AbstractEnvironmentVariables resolver) { for (VariableDefinition var : IdeVariables.VARIABLES) { if (var.isExport() || var.isForceDefaultValue()) { - variables.put(var.getName(), "defaults"); + variables.computeIfAbsent(var.getName(), k -> createVariableLine(k, onlyExported, resolver)); } } - super.collectVariables(variables); + super.collectVariables(variables, onlyExported, resolver); } @Override diff --git a/cli/src/main/java/com/devonfw/tools/ide/environment/VariableLine.java b/cli/src/main/java/com/devonfw/tools/ide/environment/VariableLine.java index cfc99daf2..6ae0b19dc 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/environment/VariableLine.java +++ b/cli/src/main/java/com/devonfw/tools/ide/environment/VariableLine.java @@ -41,9 +41,9 @@ public String getComment() { } /** - * @return the source of the variable. + * @return the {@link VariableSource} of the variable. */ - public String getSource() { + public VariableSource getSource() { return null; } @@ -85,14 +85,14 @@ static final class Variable extends VariableLine { private final String line; - private final Object source; + private final VariableSource source; Variable(boolean export, String name, String value) { this(export, name, value, null, null); } - private Variable(boolean export, String name, String value, String line, Object source) { + private Variable(boolean export, String name, String value, String line, VariableSource source) { super(); this.export = export; @@ -132,8 +132,8 @@ public String getValue() { } @Override - public String getSource() { - return source.toString(); + public VariableSource getSource() { + return source; } @Override @@ -239,7 +239,7 @@ public String toString() { * @param source the source where the given {@link String} to parse is from (e.g. the file path). * @return the parsed {@link VariableLine}. */ - public static VariableLine of(String line, IdeLogger logger, Object source) { + public static VariableLine of(String line, IdeLogger logger, VariableSource source) { int len = line.length(); int start = 0; @@ -311,7 +311,7 @@ public static VariableLine of(boolean export, String name, String value) { * @param source the {@link #getSource() source} of the variable. * @return the {@link VariableLine} for the given values. */ - public static VariableLine of(boolean export, String name, String value, Object source) { + public static VariableLine of(boolean export, String name, String value, VariableSource source) { return new Variable(export, name, value, null, source); } diff --git a/cli/src/main/java/com/devonfw/tools/ide/environment/VariableSource.java b/cli/src/main/java/com/devonfw/tools/ide/environment/VariableSource.java new file mode 100644 index 000000000..ef28911c8 --- /dev/null +++ b/cli/src/main/java/com/devonfw/tools/ide/environment/VariableSource.java @@ -0,0 +1,21 @@ +package com.devonfw.tools.ide.environment; + +import java.nio.file.Path; + +/** + * {@link Record} for the {@link EnvironmentVariables#getSource() source} of {@link EnvironmentVariables} or {@link VariableLine}. + * + * @param type + * @param properties + */ +public record VariableSource(EnvironmentVariablesType type, Path properties) { + + @Override + public String toString() { + if (this.properties != null) { + return this.type + "@" + this.properties; + } + return this.type.toString(); + } + +} diff --git a/cli/src/main/java/com/devonfw/tools/ide/tool/mvn/Mvn.java b/cli/src/main/java/com/devonfw/tools/ide/tool/mvn/Mvn.java index b52186076..c4c5ef207 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/tool/mvn/Mvn.java +++ b/cli/src/main/java/com/devonfw/tools/ide/tool/mvn/Mvn.java @@ -76,42 +76,13 @@ public boolean install(boolean silent) { public void postInstall() { // locate templates... - boolean legacy = false; - boolean hasMvnTemplates = true; - Path settingsFolder = this.context.getSettingsPath(); - Path templatesFolder = settingsFolder.resolve(IdeContext.FOLDER_TEMPLATES); - if (!Files.isDirectory(templatesFolder)) { - Path templatesFolderLegacy = settingsFolder.resolve(IdeContext.FOLDER_LEGACY_TEMPLATES); - if (Files.isDirectory(templatesFolderLegacy)) { - templatesFolder = templatesFolderLegacy; - } else { - this.context.warning("No maven templates found. Neither in {} nor in {} - configuration broken", - templatesFolder, templatesFolderLegacy); - hasMvnTemplates = false; - } - } - Path templatesConfFolder = templatesFolder.resolve(IdeContext.FOLDER_CONF); - Path templatesConfMvnFolder = templatesConfFolder.resolve(MVN_CONFIG_FOLDER); - if (hasMvnTemplates) { - if (!Files.isDirectory(templatesConfMvnFolder)) { - Path templatesConfMvnLegacyFolder = templatesConfFolder.resolve(MVN_CONFIG_LEGACY_FOLDER); - if (Files.isDirectory(templatesConfMvnLegacyFolder)) { - templatesConfMvnFolder = templatesConfMvnLegacyFolder; - legacy = true; - } else { - this.context.warning("No maven templates found. Neither in {} nor in {} - configuration broken", templatesConfMvnFolder, - templatesConfMvnLegacyFolder); - hasMvnTemplates = false; - } - } + Path templatesConfMvnFolder = getMavenTemplatesFolder(); + if (templatesConfMvnFolder == null) { + return; } // locate real config... - Path confPath = this.context.getConfPath(); - Path mvnConfigPath = confPath.resolve(MVN_CONFIG_FOLDER); - if (!Files.isDirectory(mvnConfigPath) && legacy) { - mvnConfigPath = confPath.resolve(MVN_CONFIG_LEGACY_FOLDER); - } - this.context.getFileAccess().mkdirs(mvnConfigPath); + boolean legacy = templatesConfMvnFolder.getFileName().toString().equals(MVN_CONFIG_LEGACY_FOLDER); + Path mvnConfigPath = getMavenConfFolder(legacy); Path settingsSecurityFile = mvnConfigPath.resolve(SETTINGS_SECURITY_FILE); createSettingsSecurityFile(settingsSecurityFile); @@ -229,4 +200,42 @@ public String getToolHelpArguments() { return "-h"; } + + public Path getMavenTemplatesFolder() { + + Path templatesFolder = this.context.getSettingsTemplatePath(); + if (templatesFolder == null) { + return null; + } + Path templatesConfFolder = templatesFolder.resolve(IdeContext.FOLDER_CONF); + Path templatesConfMvnFolder = templatesConfFolder.resolve(MVN_CONFIG_FOLDER); + if (!Files.isDirectory(templatesConfMvnFolder)) { + Path templatesConfMvnLegacyFolder = templatesConfFolder.resolve(MVN_CONFIG_LEGACY_FOLDER); + if (!Files.isDirectory(templatesConfMvnLegacyFolder)) { + this.context.warning("No maven templates found neither in {} nor in {} - configuration broken", templatesConfMvnFolder, + templatesConfMvnLegacyFolder); + return null; + } + templatesConfMvnFolder = templatesConfMvnLegacyFolder; + } + return templatesConfMvnFolder; + } + + public Path getMavenConfFolder(boolean legacy) { + + Path confPath = this.context.getConfPath(); + Path mvnConfigFolder = confPath.resolve(MVN_CONFIG_FOLDER); + if (!Files.isDirectory(mvnConfigFolder)) { + Path mvnConfigLegacyFolder = confPath.resolve(Mvn.MVN_CONFIG_LEGACY_FOLDER); + if (Files.isDirectory(mvnConfigLegacyFolder)) { + mvnConfigFolder = mvnConfigLegacyFolder; + } else { + if (legacy) { + mvnConfigFolder = mvnConfigLegacyFolder; + } + this.context.getFileAccess().mkdirs(mvnConfigFolder); + } + } + return mvnConfigFolder; + } } diff --git a/cli/src/main/java/com/devonfw/tools/ide/variable/IdeVariables.java b/cli/src/main/java/com/devonfw/tools/ide/variable/IdeVariables.java index bc0a4b47b..62ba32ab0 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/variable/IdeVariables.java +++ b/cli/src/main/java/com/devonfw/tools/ide/variable/IdeVariables.java @@ -45,7 +45,7 @@ public interface IdeVariables { VariableDefinitionString MAVEN_ARGS = new VariableDefinitionString("MAVEN_ARGS", null, c -> c.getMavenArgs(), false, true); /** {@link VariableDefinition} arguments for maven to set the m2 repo location. */ - VariableDefinitionPath M2_REPO = new VariableDefinitionPath("M2_REPO", null, c -> c.getMavenRepoEnvVariable(), false, true); + VariableDefinitionPath M2_REPO = new VariableDefinitionPath("M2_REPO", null, c -> c.getMavenRepository(), false, true); /** {@link VariableDefinition} for {@link com.devonfw.tools.ide.context.IdeContext#getWorkspaceName() WORKSPACE}. */ VariableDefinitionString DOCKER_EDITION = new VariableDefinitionString("DOCKER_EDITION", null, c -> "rancher"); diff --git a/cli/src/test/java/com/devonfw/tools/ide/commandlet/EnvironmentCommandletTest.java b/cli/src/test/java/com/devonfw/tools/ide/commandlet/EnvironmentCommandletTest.java index 59706d139..2837f8e57 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/commandlet/EnvironmentCommandletTest.java +++ b/cli/src/test/java/com/devonfw/tools/ide/commandlet/EnvironmentCommandletTest.java @@ -8,6 +8,7 @@ import com.devonfw.tools.ide.context.IdeTestContext; import com.devonfw.tools.ide.context.IdeTestContextMock; import com.devonfw.tools.ide.log.IdeLogEntry; +import com.devonfw.tools.ide.log.IdeLogLevel; /** * Test of {@link EnvironmentCommandlet}. @@ -15,26 +16,111 @@ public class EnvironmentCommandletTest extends AbstractIdeContextTest { /** - * Test of {@link EnvironmentCommandlet} run. + * Test of {@link EnvironmentCommandlet} run with DEBUG logging (partitioning per type/source). */ @Test - public void testRun() { + public void testRunDebugLogging() { // arrange String path = "project/workspaces/foo-test/my-git-repo"; IdeTestContext context = newContext(PROJECT_BASIC, path, false); EnvironmentCommandlet env = context.getCommandletManager().getCommandlet(EnvironmentCommandlet.class); + Path userProperties = context.getUserHomeIde().resolve("ide.properties"); Path settingsIdeProperties = context.getSettingsPath().resolve("ide.properties"); Path confIdeProperties = context.getConfPath().resolve("ide.properties"); + Path workspaceIdeProperties = context.getWorkspacePath().resolve("ide.properties"); // act env.run(); // assert assertThat(context).log().hasEntriesWithNothingElseInBetween( // - IdeLogEntry.ofDebug("from defaults:"), IdeLogEntry.ofInfo("DOCKER_EDITION=\"docker\""), IdeLogEntry.ofInfo("INTELLIJ_EDITION=\"ultimate\""), // - IdeLogEntry.ofDebug("from " + settingsIdeProperties + ":"), IdeLogEntry.ofInfo("JAVA_VERSION=\"17*\""), - IdeLogEntry.ofInfo("SOME=\"some-${UNDEFINED}\""), IdeLogEntry.ofInfo("BAR=\"bar-some-${UNDEFINED}\""), - IdeLogEntry.ofInfo("IDE_TOOLS=\"mvn,eclipse\""), - IdeLogEntry.ofDebug("from " + confIdeProperties + ":"), IdeLogEntry.ofInfo("MVN_VERSION=\"3.9.1\"") //overwritten by conf + IdeLogEntry.ofDebug("from USER@" + userProperties.toString() + ":"), // + IdeLogEntry.ofInfo("DOCKER_EDITION=\"docker\""), // + IdeLogEntry.ofInfo("FOO=\"foo-bar-some-${UNDEFINED}\""), // + + IdeLogEntry.ofDebug("from SETTINGS@" + settingsIdeProperties + ":"), + IdeLogEntry.ofInfo("BAR=\"bar-some-${UNDEFINED}\""), // + IdeLogEntry.ofInfo("ECLIPSE_VERSION=\"2023-03\""), // + IdeLogEntry.ofInfo("IDE_TOOLS=\"mvn,eclipse\""), // + IdeLogEntry.ofInfo("INTELLIJ_EDITION=\"ultimate\""), // + IdeLogEntry.ofInfo("JAVA_VERSION=\"17*\""), // + IdeLogEntry.ofInfo("TEST_ARGS4=\" settings4\""), // + IdeLogEntry.ofInfo("TEST_ARGSb=\"user10 workspace10 settingsb user1 settings1 workspace1 conf1 user3 workspace3 confa userb\""), // + + IdeLogEntry.ofDebug("from WORKSPACE@" + workspaceIdeProperties + ":"), // + IdeLogEntry.ofInfo("TEST_ARGS10=\"user10 workspace10\""), // + IdeLogEntry.ofInfo("TEST_ARGS3=\" user3 workspace3\""), // + IdeLogEntry.ofInfo("TEST_ARGS9=\"settings9 workspace9\""), // + IdeLogEntry.ofInfo("TEST_ARGSd=\" user1 settings1 workspace1 conf1 userd workspaced\""), // + + IdeLogEntry.ofDebug("from CONF@" + confIdeProperties + ":"), // + IdeLogEntry.ofInfo("MVN_VERSION=\"3.9.1\""), // + IdeLogEntry.ofInfo("SOME=\"some-${UNDEFINED}\""), // + IdeLogEntry.ofInfo("TEST_ARGS1=\" user1 settings1 workspace1 conf1\""), // + IdeLogEntry.ofInfo("TEST_ARGS2=\" user2 conf2\""), // + IdeLogEntry.ofInfo("TEST_ARGS5=\" settings5 conf5\""), // + IdeLogEntry.ofInfo("TEST_ARGS6=\" settings6 workspace6 conf6\""), // + IdeLogEntry.ofInfo("TEST_ARGS7=\"user7 settings7 workspace7 conf7\""), // + IdeLogEntry.ofInfo("TEST_ARGS8=\"settings8 workspace8 conf8\""), // + IdeLogEntry.ofInfo("TEST_ARGSa=\" user1 settings1 workspace1 conf1 user3 workspace3 confa\""), // + IdeLogEntry.ofInfo("TEST_ARGSc=\" user1 settings1 workspace1 conf1 userc settingsc confc\""), // + + IdeLogEntry.ofDebug("from RESOLVED:"), // + IdeLogEntry.ofInfo("HOME=\"" + context.getUserHome() + "\""), // + IdeLogEntry.ofInfo("IDE_HOME=\"" + context.getIdeHome() + "\""), // + IdeLogEntry.ofInfo("export M2_REPO=\"" + context.getUserHome() + "/.m2/repository\""), // + new IdeLogEntry(IdeLogLevel.INFO, "export PATH=", true), // + IdeLogEntry.ofInfo("WORKSPACE=\"foo-test\""), // + IdeLogEntry.ofInfo("WORKSPACE_PATH=\"" + context.getWorkspacePath() + "\"") // + ); + } + + /** + * Test of {@link EnvironmentCommandlet} run with INFO logging (plain variables without source). + */ + @Test + public void testRunInfoLogging() { + + // arrange + String path = "project/workspaces/foo-test/my-git-repo"; + IdeTestContext context = newContext(PROJECT_BASIC, path, false, IdeLogLevel.INFO); + EnvironmentCommandlet env = context.getCommandletManager().getCommandlet(EnvironmentCommandlet.class); + Path userProperties = context.getUserHomeIde().resolve("ide.properties"); + Path settingsIdeProperties = context.getSettingsPath().resolve("ide.properties"); + Path confIdeProperties = context.getConfPath().resolve("ide.properties"); + Path workspaceIdeProperties = context.getWorkspacePath().resolve("ide.properties"); + // act + env.run(); + // assert + assertThat(context).log().hasEntriesWithNothingElseInBetween( // + IdeLogEntry.ofInfo("BAR=\"bar-some-${UNDEFINED}\""), // + IdeLogEntry.ofInfo("DOCKER_EDITION=\"docker\""), // + IdeLogEntry.ofInfo("ECLIPSE_VERSION=\"2023-03\""), // + IdeLogEntry.ofInfo("FOO=\"foo-bar-some-${UNDEFINED}\""), // + IdeLogEntry.ofInfo("HOME=\"" + context.getUserHome() + "\""), // + IdeLogEntry.ofInfo("IDE_HOME=\"" + context.getIdeHome() + "\""), // + IdeLogEntry.ofInfo("IDE_TOOLS=\"mvn,eclipse\""), // + IdeLogEntry.ofInfo("INTELLIJ_EDITION=\"ultimate\""), // + IdeLogEntry.ofInfo("JAVA_VERSION=\"17*\""), // + IdeLogEntry.ofInfo("export M2_REPO=\"" + context.getUserHome() + "/.m2/repository\""), // + IdeLogEntry.ofInfo("MVN_VERSION=\"3.9.1\""), // + new IdeLogEntry(IdeLogLevel.INFO, "export PATH=", true), // + IdeLogEntry.ofInfo("SOME=\"some-${UNDEFINED}\""), // + IdeLogEntry.ofInfo("TEST_ARGS1=\" user1 settings1 workspace1 conf1\""), // + IdeLogEntry.ofInfo("TEST_ARGS10=\"user10 workspace10\""), // + IdeLogEntry.ofInfo("TEST_ARGS2=\" user2 conf2\""), // + IdeLogEntry.ofInfo("TEST_ARGS3=\" user3 workspace3\""), // + IdeLogEntry.ofInfo("TEST_ARGS4=\" settings4\""), // + IdeLogEntry.ofInfo("TEST_ARGS5=\" settings5 conf5\""), // + IdeLogEntry.ofInfo("TEST_ARGS6=\" settings6 workspace6 conf6\""), // + IdeLogEntry.ofInfo("TEST_ARGS7=\"user7 settings7 workspace7 conf7\""), // + IdeLogEntry.ofInfo("TEST_ARGS8=\"settings8 workspace8 conf8\""), // + IdeLogEntry.ofInfo("TEST_ARGS9=\"settings9 workspace9\""), // + IdeLogEntry.ofInfo("TEST_ARGSa=\" user1 settings1 workspace1 conf1 user3 workspace3 confa\""), // + IdeLogEntry.ofInfo("TEST_ARGSb=\"user10 workspace10 settingsb user1 settings1 workspace1 conf1 user3 workspace3 confa userb\""), // + IdeLogEntry.ofInfo("TEST_ARGSc=\" user1 settings1 workspace1 conf1 userc settingsc confc\""), // + IdeLogEntry.ofInfo("TEST_ARGSd=\" user1 settings1 workspace1 conf1 userd workspaced\""), // + IdeLogEntry.ofInfo("WORKSPACE=\"foo-test\""), // + IdeLogEntry.ofInfo("WORKSPACE_PATH=\"" + context.getWorkspacePath() + "\"") // ); } diff --git a/cli/src/test/java/com/devonfw/tools/ide/commandlet/VersionListCommandletTest.java b/cli/src/test/java/com/devonfw/tools/ide/commandlet/VersionListCommandletTest.java index 3305582bd..b5736a001 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/commandlet/VersionListCommandletTest.java +++ b/cli/src/test/java/com/devonfw/tools/ide/commandlet/VersionListCommandletTest.java @@ -23,6 +23,6 @@ public void testVersionListCommandletRun() { // act versionList.run(); // assert - assertThat(context).logAtInfo().hasEntries("3.0.5", "3.1.0", "3.2.1"); + assertThat(context).logAtInfo().hasEntries("3.2.1", "3.1.0", "3.0.5"); } } diff --git a/cli/src/test/java/com/devonfw/tools/ide/context/AbstractIdeContextTest.java b/cli/src/test/java/com/devonfw/tools/ide/context/AbstractIdeContextTest.java index b8ae3da37..84ee34356 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/context/AbstractIdeContextTest.java +++ b/cli/src/test/java/com/devonfw/tools/ide/context/AbstractIdeContextTest.java @@ -10,7 +10,7 @@ import com.devonfw.tools.ide.io.FileAccessImpl; import com.devonfw.tools.ide.io.FileCopyMode; import com.devonfw.tools.ide.io.IdeProgressBarTestImpl; -import com.devonfw.tools.ide.log.IdeTestContextAssertion; +import com.devonfw.tools.ide.log.IdeLogLevel; import com.devonfw.tools.ide.repo.ToolRepositoryMock; /** @@ -64,6 +64,20 @@ protected static IdeTestContext newContext(String testProject, String projectPat */ protected static IdeTestContext newContext(String testProject, String projectPath, boolean copyForMutation) { + return newContext(testProject, projectPath, copyForMutation, IdeLogLevel.TRACE); + } + + /** + * @param testProject the (folder)name of the project test case, in this folder a 'project' folder represents the test project in {@link #TEST_PROJECTS}. E.g. + * "basic". + * @param projectPath the relative path inside the test project where to create the context. + * @param copyForMutation - {@code true} to create a copy of the project that can be modified by the test, {@code false} otherwise (only to save resources if + * you are 100% sure that your test never modifies anything in that project.) + * @param logLevel the {@link IdeLogLevel} used as threshold for logging. + * @return the {@link IdeTestContext} pointing to that project. + */ + protected static IdeTestContext newContext(String testProject, String projectPath, boolean copyForMutation, IdeLogLevel logLevel) { + Path ideRoot = TEST_PROJECTS.resolve(testProject); if (copyForMutation) { Path ideRootCopy = TEST_PROJECTS_COPY.resolve(testProject); @@ -82,7 +96,7 @@ protected static IdeTestContext newContext(String testProject, String projectPat if (Files.isDirectory(repositoryFolder)) { toolRepository = new ToolRepositoryMock(repositoryFolder); } - IdeTestContext context = new IdeTestContext(userDir, toolRepository); + IdeTestContext context = new IdeTestContext(userDir, toolRepository, logLevel); if (toolRepository != null) { toolRepository.setContext(context); } diff --git a/cli/src/test/java/com/devonfw/tools/ide/context/AbstractIdeTestContext.java b/cli/src/test/java/com/devonfw/tools/ide/context/AbstractIdeTestContext.java index 05c5a1766..8d55b32ab 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/context/AbstractIdeTestContext.java +++ b/cli/src/test/java/com/devonfw/tools/ide/context/AbstractIdeTestContext.java @@ -1,10 +1,16 @@ package com.devonfw.tools.ide.context; +import java.nio.file.Files; import java.nio.file.Path; import java.util.HashMap; import java.util.Map; import java.util.function.Function; +import com.devonfw.tools.ide.common.SystemPath; +import com.devonfw.tools.ide.environment.AbstractEnvironmentVariables; +import com.devonfw.tools.ide.environment.EnvironmentVariables; +import com.devonfw.tools.ide.environment.EnvironmentVariablesPropertiesFile; +import com.devonfw.tools.ide.environment.EnvironmentVariablesType; import com.devonfw.tools.ide.io.FileAccess; import com.devonfw.tools.ide.io.IdeProgressBar; import com.devonfw.tools.ide.io.IdeProgressBarTestImpl; @@ -13,6 +19,7 @@ import com.devonfw.tools.ide.os.SystemInfo; import com.devonfw.tools.ide.repo.DefaultToolRepository; import com.devonfw.tools.ide.repo.ToolRepository; +import com.devonfw.tools.ide.variable.IdeVariables; /** * Implementation of {@link IdeContext} for testing. @@ -84,6 +91,28 @@ public IdeProgressBar prepareProgressBar(String taskName, long size) { return progressBar; } + @Override + protected AbstractEnvironmentVariables createSystemVariables() { + + Path home = getUserHome(); + if (home != null) { + Path systemPropertiesFile = home.resolve("environment.properties"); + if (Files.exists(systemPropertiesFile)) { + return new EnvironmentVariablesPropertiesFile(null, EnvironmentVariablesType.SYSTEM, systemPropertiesFile, this); + } + } + return super.createSystemVariables(); + } + + @Override + protected SystemPath computeSystemPath() { + + EnvironmentVariables systemVars = getVariables().getByType(EnvironmentVariablesType.SYSTEM); + String envPath = systemVars.get(IdeVariables.PATH.getName()); + envPath = getVariables().resolve(envPath, systemVars.getSource()); + return new SystemPath(this, envPath); + } + @Override public SystemInfo getSystemInfo() { diff --git a/cli/src/test/java/com/devonfw/tools/ide/context/IdeContextTest.java b/cli/src/test/java/com/devonfw/tools/ide/context/IdeContextTest.java index 01d4820c8..adc90756a 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/context/IdeContextTest.java +++ b/cli/src/test/java/com/devonfw/tools/ide/context/IdeContextTest.java @@ -40,8 +40,7 @@ public void testBasicProjectEnvironment() { assertThat(context.getWorkspacePath().resolve("readme")).hasContent("this is the foo-test workspace of basic"); SystemPath systemPath = IdeVariables.PATH.get(context); assertThat(systemPath).isSameAs(context.getPath()); - String envPath = System.getenv(IdeVariables.PATH.getName()); - envPath = envPath.replaceAll("[\\\\][;]", ";").replaceAll("[\\/][:]", ":"); + String envPath = context.getIdeRoot().resolve("_ide").resolve("bin").toString(); assertThat(systemPath.toString()).isNotEqualTo(envPath).endsWith(envPath); Path softwarePath = context.getSoftwarePath(); Path javaBin = softwarePath.resolve("java/bin"); diff --git a/cli/src/test/java/com/devonfw/tools/ide/context/IdeTestContext.java b/cli/src/test/java/com/devonfw/tools/ide/context/IdeTestContext.java index c53e93723..1bc9b8742 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/context/IdeTestContext.java +++ b/cli/src/test/java/com/devonfw/tools/ide/context/IdeTestContext.java @@ -5,7 +5,6 @@ import java.util.List; import com.devonfw.tools.ide.log.IdeLogLevel; -import com.devonfw.tools.ide.log.IdeTestLogger; import com.devonfw.tools.ide.log.IdeTestLoggerFactory; import com.devonfw.tools.ide.process.ProcessContext; import com.devonfw.tools.ide.repo.ToolRepository; @@ -15,6 +14,8 @@ */ public class IdeTestContext extends AbstractIdeTestContext { + private final IdeTestLoggerFactory loggerFactory; + private LinkedList inputValues; /** @@ -38,13 +39,27 @@ public IdeTestContext(Path userDir, String... answers) { */ public IdeTestContext(Path userDir, ToolRepository toolRepository, String... answers) { - super(new IdeTestLoggerFactory(), userDir, toolRepository, answers); + this(userDir, toolRepository, IdeLogLevel.TRACE, answers); } - @Override - public IdeTestLogger level(IdeLogLevel level) { + /** + * The constructor. + * + * @param userDir the optional {@link Path} to current working directory. + * @param toolRepository the {@link ToolRepository} of the context. If it is set to {@code null} * {@link com.devonfw.tools.ide.repo.DefaultToolRepository} + * will be used. + * @param logLevel the {@link IdeLogLevel} used as threshold for logging. + * @param answers the automatic answers simulating a user in test. + */ + public IdeTestContext(Path userDir, ToolRepository toolRepository, IdeLogLevel logLevel, String... answers) { + + this(new IdeTestLoggerFactory(logLevel), userDir, toolRepository, answers); + } + + private IdeTestContext(IdeTestLoggerFactory loggerFactory, Path userDir, ToolRepository toolRepository, String... answers) { - return (IdeTestLogger) super.level(level); + super(loggerFactory, userDir, toolRepository, answers); + this.loggerFactory = loggerFactory; } @Override @@ -83,4 +98,11 @@ public String askForInput(String message) { return this.inputValues.isEmpty() ? null : this.inputValues.poll(); } + /** + * @return the {@link IdeTestLoggerFactory}. + */ + public IdeTestLoggerFactory getLoggerFactory() { + + return loggerFactory; + } } diff --git a/cli/src/test/java/com/devonfw/tools/ide/log/IdeTestContextAssertion.java b/cli/src/test/java/com/devonfw/tools/ide/context/IdeTestContextAssertion.java similarity index 86% rename from cli/src/test/java/com/devonfw/tools/ide/log/IdeTestContextAssertion.java rename to cli/src/test/java/com/devonfw/tools/ide/context/IdeTestContextAssertion.java index 9e40135de..635e8ee0b 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/log/IdeTestContextAssertion.java +++ b/cli/src/test/java/com/devonfw/tools/ide/context/IdeTestContextAssertion.java @@ -1,6 +1,7 @@ -package com.devonfw.tools.ide.log; +package com.devonfw.tools.ide.context; -import com.devonfw.tools.ide.context.IdeTestContext; +import com.devonfw.tools.ide.log.IdeLogLevel; +import com.devonfw.tools.ide.log.IdeTestLoggerAssertion; /** * Assertion for {@link IdeTestContext}. @@ -25,7 +26,7 @@ public IdeTestContextAssertion(IdeTestContext context) { */ public IdeTestLoggerAssertion log(IdeLogLevel level) { - return new IdeTestLoggerAssertion(context.level(IdeLogLevel.INFO).getEntries(), level); // random level - all loggers share the same list of log entries + return new IdeTestLoggerAssertion(context.getLoggerFactory().getEntries(), level); } /** diff --git a/cli/src/test/java/com/devonfw/tools/ide/environment/VariableLineTest.java b/cli/src/test/java/com/devonfw/tools/ide/environment/VariableLineTest.java index 78354486f..0c587a06a 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/environment/VariableLineTest.java +++ b/cli/src/test/java/com/devonfw/tools/ide/environment/VariableLineTest.java @@ -18,7 +18,7 @@ public class VariableLineTest extends Assertions { private VariableLine line(String line) { - return VariableLine.of(line, LOGGER, "junit-source"); + return VariableLine.of(line, LOGGER, new VariableSource(EnvironmentVariablesType.RESOLVED, null)); } /** diff --git a/cli/src/test/java/com/devonfw/tools/ide/log/IdeLogEntry.java b/cli/src/test/java/com/devonfw/tools/ide/log/IdeLogEntry.java index 4f1d11ed7..fb495ca88 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/log/IdeLogEntry.java +++ b/cli/src/test/java/com/devonfw/tools/ide/log/IdeLogEntry.java @@ -6,7 +6,25 @@ * @param level the {@link IdeLogLevel}. * @param message the message that has been logged. */ -public record IdeLogEntry(IdeLogLevel level, String message) { +public record IdeLogEntry(IdeLogLevel level, String message, boolean contains) { + + public IdeLogEntry(IdeLogLevel level, String message) { + this(level, message, false); + } + + public boolean matches(IdeLogEntry entry) { + + if (this.level != entry.level) { + return false; + } else if (this.contains) { + if (!entry.message.contains(this.message)) { + return false; + } + } else if (!entry.message.equals(this.message)) { + return false; + } + return true; + } public static IdeLogEntry ofError(String message) { @@ -42,4 +60,5 @@ public static IdeLogEntry ofTrace(String message) { return new IdeLogEntry(IdeLogLevel.TRACE, message); } + } diff --git a/cli/src/test/java/com/devonfw/tools/ide/log/IdeTestLoggerAssertion.java b/cli/src/test/java/com/devonfw/tools/ide/log/IdeTestLoggerAssertion.java index 8632c18f4..a83e4bab7 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/log/IdeTestLoggerAssertion.java +++ b/cli/src/test/java/com/devonfw/tools/ide/log/IdeTestLoggerAssertion.java @@ -69,58 +69,73 @@ public void hasEntries(String... messages) { } /** - * @param exprectedEntries the expected {@link com.devonfw.tools.ide.log.IdeLogEntry log entries} in order. + * @param expectedEntries the expected {@link com.devonfw.tools.ide.log.IdeLogEntry log entries} in order. */ - public void hasEntries(IdeLogEntry... exprectedEntries) { + public void hasEntries(IdeLogEntry... expectedEntries) { - hasEntries(false, exprectedEntries); + hasEntries(false, expectedEntries); } /** - * @param exprectedEntries the expected {@link com.devonfw.tools.ide.log.IdeLogEntry log entries} to be logged in order without any other log statement in + * @param expectedEntries the expected {@link com.devonfw.tools.ide.log.IdeLogEntry log entries} to be logged in order without any other log statement in * between them. */ - public void hasEntriesWithNothingElseInBetween(IdeLogEntry... exprectedEntries) { + public void hasEntriesWithNothingElseInBetween(IdeLogEntry... expectedEntries) { - hasEntries(true, exprectedEntries); + hasEntries(true, expectedEntries); } - private void hasEntries(boolean nothingElseInBetween, IdeLogEntry... exprectedEntries) { + private void hasEntries(boolean nothingElseInBetween, IdeLogEntry... expectedEntries) { - assert (exprectedEntries.length > 0); + assert (expectedEntries.length > 0); int i = 0; - for (IdeLogEntry entry : exprectedEntries) { - if (entry.equals(exprectedEntries[i])) { + int max = 0; + for (IdeLogEntry entry : this.entries) { + if (expectedEntries[i].matches(entry)) { i++; } else { if (nothingElseInBetween) { i = 0; - } else if (entry.equals(exprectedEntries[i])) { + } else if (expectedEntries[0].matches(entry)) { i = 1; } } - if (i == exprectedEntries.length) { + if (i == expectedEntries.length) { return; } + if (i > max) { + max = i; + } } StringBuilder error = new StringBuilder(4096); - error.append("Could not find expected log entries:\n"); - for (IdeLogEntry entry : exprectedEntries) { - error.append(entry.level()); - error.append(":"); - error.append(entry.message()); - error.append('\n'); + if (max > 0) { + error.append("Found expected log entries:\n"); + for (i = 0; i < max; i++) { + appendEntry(error, expectedEntries[i]); + } + } + error.append("\nThe first entry that was not matching from a block of "); + error.append(expectedEntries.length); + error.append(" expected log-entries "); + if (nothingElseInBetween) { + error.append("with nothing else logged in between "); } + error.append("was:\n"); + appendEntry(error, expectedEntries[max]); error.append("\nIn the logs of this test:\n"); for (IdeLogEntry entry : this.entries) { - error.append(entry.level()); - error.append(":"); - error.append(entry.message()); - error.append('\n'); + appendEntry(error, entry); } Assertions.fail(error.toString()); } + private static void appendEntry(StringBuilder sb, IdeLogEntry entry) { + sb.append(entry.level()); + sb.append(":"); + sb.append(entry.message()); + sb.append('\n'); + } + private void fulfillsPredicate(Predicate predicate, PredicateMode mode, String errorMessage) { if (this.level != null) { @@ -138,7 +153,9 @@ private void fulfillsPredicate(Predicate predicate, PredicateMode m } } } - Assertions.fail(errorMessage); // no log entry matched by predicate + if (mode == PredicateMode.MATCH_ONE) { + Assertions.fail(errorMessage); // no log entry matched by predicate + } } } diff --git a/cli/src/test/java/com/devonfw/tools/ide/log/IdeTestLoggerFactory.java b/cli/src/test/java/com/devonfw/tools/ide/log/IdeTestLoggerFactory.java index f8cba715a..02589c4a5 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/log/IdeTestLoggerFactory.java +++ b/cli/src/test/java/com/devonfw/tools/ide/log/IdeTestLoggerFactory.java @@ -9,19 +9,34 @@ */ public class IdeTestLoggerFactory implements Function { + private final IdeLogLevel logLevel; + private final List entries; /** * The constructor. */ public IdeTestLoggerFactory() { + this(IdeLogLevel.TRACE); + } + + /** + * The constructor. + * + * @param logLevel the {@link IdeLogLevel} used as threshold for logging. + */ + public IdeTestLoggerFactory(IdeLogLevel logLevel) { super(); + this.logLevel = logLevel; this.entries = new ArrayList<>(512); } @Override public IdeSubLogger apply(IdeLogLevel ideLogLevel) { + if (ideLogLevel.ordinal() < this.logLevel.ordinal()) { + return new IdeSubLoggerNone(ideLogLevel); + } return new IdeTestLogger(ideLogLevel, this.entries); } diff --git a/cli/src/test/java/com/devonfw/tools/ide/step/StepTest.java b/cli/src/test/java/com/devonfw/tools/ide/step/StepTest.java index a2601c50e..56b9bd0dd 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/step/StepTest.java +++ b/cli/src/test/java/com/devonfw/tools/ide/step/StepTest.java @@ -52,9 +52,9 @@ public void testValidUsageSuccessSilent() { assertThat(step.getParameter(1)).isEqualTo("arg2"); assertThat(step.getParameter(2)).isNull(); assertThat(context).log().hasEntries(IdeLogEntry.ofTrace("Starting step Test-Step with params [arg1, arg2]..."), - IdeLogEntry.ofStep("Start: Test-Step"), - IdeLogEntry.ofSuccess("Test-Step"), IdeLogEntry.ofDebug("Step 'Test-Step' ended successfully.")); + assertThat(context).log().hasNoMessage("Start: Test-Step"); + assertThat(context).log().hasNoMessage("Test-Step"); } @Test diff --git a/cli/src/test/resources/ide-projects/basic/_ide/bin/ide b/cli/src/test/resources/ide-projects/basic/_ide/bin/ide new file mode 100644 index 000000000..01f20642f --- /dev/null +++ b/cli/src/test/resources/ide-projects/basic/_ide/bin/ide @@ -0,0 +1,2 @@ +#!/bin/bash +echo "ide $*" diff --git a/cli/src/test/resources/ide-projects/basic/project/home/environment.properties b/cli/src/test/resources/ide-projects/basic/project/home/environment.properties new file mode 100644 index 000000000..c0a59da37 --- /dev/null +++ b/cli/src/test/resources/ide-projects/basic/project/home/environment.properties @@ -0,0 +1,2 @@ +# if this file is present, it will replace and mock System.getenv in the text context +PATH=${IDE_ROOT}/_ide/bin diff --git a/cli/src/test/resources/ide-projects/basic/project/software/mvn/bin/mvn b/cli/src/test/resources/ide-projects/basic/project/software/mvn/bin/mvn new file mode 100644 index 000000000..4a97b4f4a --- /dev/null +++ b/cli/src/test/resources/ide-projects/basic/project/software/mvn/bin/mvn @@ -0,0 +1,5 @@ +#!/bin/bash +if [ "$1" == "-h" ]; then + echo "usage: mvn [options] [] []" +fi +echo "mvn $*"