From 1307d33b09936ab04e3b92fcded791b8f6d8bd9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Hohwiller?= Date: Thu, 9 Jan 2025 16:37:17 +0100 Subject: [PATCH] #759: completed last things (*.properties in ~) --- .../commandlet/UpgradeSettingsCommandlet.java | 36 ++-- .../tools/ide/context/AbstractIdeContext.java | 37 +--- .../AbstractEnvironmentVariables.java | 11 +- .../ide/environment/EnvironmentVariables.java | 10 + .../EnvironmentVariablesPropertiesFile.java | 198 ++++++++++++------ .../com/devonfw/tools/ide/io/FileAccess.java | 3 + .../devonfw/tools/ide/io/FileAccessImpl.java | 25 ++- .../devonfw/tools/ide/util/DateTimeUtil.java | 16 +- .../UpgradeSettingsCommandletTest.java | 10 +- 9 files changed, 215 insertions(+), 131 deletions(-) diff --git a/cli/src/main/java/com/devonfw/tools/ide/commandlet/UpgradeSettingsCommandlet.java b/cli/src/main/java/com/devonfw/tools/ide/commandlet/UpgradeSettingsCommandlet.java index a9df35177..bedf8dcf0 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/commandlet/UpgradeSettingsCommandlet.java +++ b/cli/src/main/java/com/devonfw/tools/ide/commandlet/UpgradeSettingsCommandlet.java @@ -15,6 +15,7 @@ import com.devonfw.tools.ide.repo.CustomToolsJsonMapper; import com.devonfw.tools.ide.tool.mvn.Mvn; import com.devonfw.tools.ide.variable.IdeVariables; +import com.devonfw.tools.ide.variable.VariableDefinition; /** * {@link Commandlet} to upgrade settings after a migration from devonfw-ide to IDEasy. @@ -97,6 +98,7 @@ void updateProperties() { } } + // update properties (devon.properties -> ide.properties, convert legacy properties) EnvironmentVariables environmentVariables = context.getVariables(); while (environmentVariables != null) { if (environmentVariables instanceof EnvironmentVariablesPropertiesFile environmentVariablesProperties) { @@ -104,32 +106,40 @@ void updateProperties() { } environmentVariables = environmentVariables.getParent(); } - Path templateProperties = this.context.getSettingsTemplatePath().resolve(IdeContext.FOLDER_CONF).resolve(EnvironmentVariables.LEGACY_PROPERTIES); - if (Files.exists(templateProperties)) { - EnvironmentVariablesPropertiesFile environmentVariablesProperties = new EnvironmentVariablesPropertiesFile(null, EnvironmentVariablesType.USER, - templateProperties, this.context); + Path templatePropertiesDir = this.context.getSettingsTemplatePath().resolve(IdeContext.FOLDER_CONF); + if (Files.exists(templatePropertiesDir)) { + EnvironmentVariablesPropertiesFile environmentVariablesProperties = new EnvironmentVariablesPropertiesFile(null, EnvironmentVariablesType.CONF, + templatePropertiesDir, null, this.context); updateProperties(environmentVariablesProperties); } - } private void updateProperties(EnvironmentVariablesPropertiesFile environmentVariables) { Path propertiesFilePath = environmentVariables.getPropertiesFilePath(); - if (propertiesFilePath != null || environmentVariables.getLegacyPropertiesFilePath() != null) { + if (environmentVariables.getLegacyConfiguration() != null) { if (environmentVariables.getType() == EnvironmentVariablesType.SETTINGS) { // adds disabled legacySupportEnabled variable if missing in ide.properties - String legacySupportEnabledName = IdeVariables.IDE_VARIABLE_SYNTAX_LEGACY_SUPPORT_ENABLED.getName(); - String legacySupportEnabledValue = environmentVariables.get(legacySupportEnabledName); - if (!"false".equals(legacySupportEnabledValue)) { - environmentVariables.set(legacySupportEnabledName, "false", false); - } + environmentVariables.set(IdeVariables.IDE_VARIABLE_SYNTAX_LEGACY_SUPPORT_ENABLED.getName(), "false", false); } - if ((propertiesFilePath != null) && propertiesFilePath.endsWith(EnvironmentVariables.LEGACY_PROPERTIES)) { - environmentVariables.remove(IdeVariables.DEVON_IDE_CUSTOM_TOOLS.getName()); + environmentVariables.remove(IdeVariables.DEVON_IDE_CUSTOM_TOOLS.getName()); + for (VariableDefinition var : IdeVariables.VARIABLES) { + String legacyName = var.getLegacyName(); + if (legacyName != null) { + String value = environmentVariables.get(legacyName); + if (value != null) { + String name = var.getName(); + String newValue = environmentVariables.get(name); + if (newValue == null) { + environmentVariables.set(name, value, environmentVariables.isExported(name)); + } + } + environmentVariables.remove(legacyName); + } } updatePropertiesLegacyEdition(environmentVariables, "INTELLIJ_EDITION_TYPE", "INTELLIJ_EDITION", this::mapLegacyIntellijEdition); updatePropertiesLegacyEdition(environmentVariables, "ECLIPSE_EDITION_TYPE", "ECLIPSE_EDITION", this::mapLegacyIntellijEdition); environmentVariables.save(); + this.context.getFileAccess().backup(environmentVariables.getLegacyPropertiesFilePath()); } } 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 eb5e16e46..d1fb11cc2 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 @@ -81,7 +81,7 @@ public abstract class AbstractIdeContext implements IdeContext { private Path softwareExtraPath; - private Path softwareRepositoryPath; + private final Path softwareRepositoryPath; protected Path pluginsPath; @@ -91,15 +91,15 @@ public abstract class AbstractIdeContext implements IdeContext { protected Path urlsPath; - private Path tempPath; + private final Path tempPath; - private Path tempDownloadPath; + private final Path tempDownloadPath; private Path cwd; private Path downloadPath; - private Path toolRepositoryPath; + private final Path toolRepositoryPath; protected Path userHome; @@ -308,11 +308,10 @@ private boolean isIdeHome(Path dir) { private EnvironmentVariables createVariables() { 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? - AbstractEnvironmentVariables workspace = extendVariables(settings, this.workspacePath, EnvironmentVariablesType.WORKSPACE); - AbstractEnvironmentVariables conf = extendVariables(workspace, this.confPath, EnvironmentVariablesType.CONF); + AbstractEnvironmentVariables user = system.extend(this.userHomeIde, EnvironmentVariablesType.USER); + AbstractEnvironmentVariables settings = user.extend(this.settingsPath, EnvironmentVariablesType.SETTINGS); + AbstractEnvironmentVariables workspace = settings.extend(this.workspacePath, EnvironmentVariablesType.WORKSPACE); + AbstractEnvironmentVariables conf = workspace.extend(this.confPath, EnvironmentVariablesType.CONF); return conf.resolved(); } @@ -321,26 +320,6 @@ protected AbstractEnvironmentVariables createSystemVariables() { return EnvironmentVariables.ofSystem(this); } - protected AbstractEnvironmentVariables extendVariables(AbstractEnvironmentVariables envVariables, Path propertiesPath, EnvironmentVariablesType type) { - - Path propertiesFile = null; - if (propertiesPath == null) { - trace("Configuration directory for type {} does not exist.", type); - } else if (Files.isDirectory(propertiesPath)) { - propertiesFile = propertiesPath.resolve(EnvironmentVariables.DEFAULT_PROPERTIES); - boolean legacySupport = (type != EnvironmentVariablesType.USER); - if (legacySupport && !Files.exists(propertiesFile)) { - Path legacyFile = propertiesPath.resolve(EnvironmentVariables.LEGACY_PROPERTIES); - if (Files.exists(legacyFile)) { - propertiesFile = legacyFile; - } - } - } else { - debug("Configuration directory {} does not exist.", propertiesPath); - } - return envVariables.extend(propertiesFile, type); - } - @Override public SystemInfo getSystemInfo() { 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 52445bf7b..2caeafab2 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 @@ -95,9 +95,7 @@ public VariableSource getSource() { protected boolean isExported(String name) { if (this.parent != null) { - if (this.parent.isExported(name)) { - return true; - } + return this.parent.isExported(name); } return false; } @@ -144,13 +142,14 @@ protected VariableLine createVariableLine(String name, boolean onlyExported, Abs } /** - * @param propertiesFilePath the {@link #getPropertiesFilePath() propertiesFilePath} of the child {@link EnvironmentVariables}. + * @param propertiesFolderPath the {@link Path} to the folder containing the {@link #getPropertiesFilePath() properties file} of the child + * {@link EnvironmentVariables}. * @param type the {@link #getType() type}. * @return the new {@link EnvironmentVariables}. */ - public AbstractEnvironmentVariables extend(Path propertiesFilePath, EnvironmentVariablesType type) { + public AbstractEnvironmentVariables extend(Path propertiesFolderPath, EnvironmentVariablesType type) { - return new EnvironmentVariablesPropertiesFile(this, type, propertiesFilePath, this.context); + return new EnvironmentVariablesPropertiesFile(this, type, propertiesFolderPath, null, this.context); } /** 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 b37165449..7d751145d 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 @@ -137,6 +137,16 @@ default EnvironmentVariables getParent() { return null; } + /** + * @param name the {@link com.devonfw.tools.ide.variable.VariableDefinition#getName() name} of the variable to set. + * @param value the new {@link #get(String) value} of the variable to set. May be {@code null} to unset the variable. + * @return the old variable value. + */ + default String set(String name, String value) { + + throw new UnsupportedOperationException(); + } + /** * @param name the {@link com.devonfw.tools.ide.variable.VariableDefinition#getName() name} of the variable to set. * @param value the new {@link #get(String) value} of the variable to set. May be {@code null} to unset the variable. 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 b1437c0fb..112726e7e 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 @@ -5,7 +5,6 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.StandardOpenOption; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -27,7 +26,9 @@ public final class EnvironmentVariablesPropertiesFile extends EnvironmentVariabl private final EnvironmentVariablesType type; - private Path propertiesFilePath; + private final Path propertiesFilePath; + + private final Path legacyPropertiesFilePath; private final Map variables; @@ -35,6 +36,8 @@ public final class EnvironmentVariablesPropertiesFile extends EnvironmentVariabl private final Set modifiedVariables; + private Boolean legacyConfiguration; + /** * The constructor. * @@ -46,29 +49,80 @@ public final class EnvironmentVariablesPropertiesFile extends EnvironmentVariabl public EnvironmentVariablesPropertiesFile(AbstractEnvironmentVariables parent, EnvironmentVariablesType type, Path propertiesFilePath, IdeContext context) { + this(parent, type, getParent(propertiesFilePath), propertiesFilePath, context); + } + + /** + * The constructor. + * + * @param parent the parent {@link EnvironmentVariables} to inherit from. + * @param type the {@link #getType() type}. + * @param propertiesFolderPath the {@link Path} to the folder where the properties file is expected. + * @param propertiesFilePath the {@link #getSource() source}. + * @param context the {@link IdeContext}. + */ + public EnvironmentVariablesPropertiesFile(AbstractEnvironmentVariables parent, EnvironmentVariablesType type, Path propertiesFolderPath, + Path propertiesFilePath, IdeContext context) { + super(parent, context); Objects.requireNonNull(type); assert (type != EnvironmentVariablesType.RESOLVED); this.type = type; - this.propertiesFilePath = propertiesFilePath; + if (propertiesFolderPath == null) { + this.propertiesFilePath = null; + this.legacyPropertiesFilePath = null; + } else { + if (propertiesFilePath == null) { + this.propertiesFilePath = propertiesFolderPath.resolve(DEFAULT_PROPERTIES); + } else { + this.propertiesFilePath = propertiesFilePath; + assert (propertiesFilePath.getParent().equals(propertiesFolderPath)); + } + Path legacyPropertiesFolderPath = propertiesFolderPath; + if (type == EnvironmentVariablesType.USER) { + // ~/devon.properties vs. ~/.ide/ide.properties + legacyPropertiesFolderPath = propertiesFolderPath.getParent(); + } + this.legacyPropertiesFilePath = legacyPropertiesFolderPath.resolve(LEGACY_PROPERTIES); + } this.variables = new HashMap<>(); this.exportedVariables = new HashSet<>(); this.modifiedVariables = new HashSet<>(); load(); } + private static Path getParent(Path path) { + + if (path == null) { + return null; + } + return path.getParent(); + } + private void load() { - if (this.propertiesFilePath == null) { - return; + boolean success = load(this.propertiesFilePath); + if (success) { + this.legacyConfiguration = Boolean.FALSE; + } else { + success = load(this.legacyPropertiesFilePath); + if (success) { + this.legacyConfiguration = Boolean.TRUE; + } } - if (!Files.exists(this.propertiesFilePath)) { - this.context.trace("Properties not found at {}", this.propertiesFilePath); - return; + } + + private boolean load(Path file) { + if (file == null) { + return false; + } + if (!Files.exists(file)) { + this.context.trace("Properties not found at {}", file); + return false; } - this.context.trace("Loading properties from {}", this.propertiesFilePath); - boolean legacyProperties = this.propertiesFilePath.getFileName().toString().equals(LEGACY_PROPERTIES); - try (BufferedReader reader = Files.newBufferedReader(this.propertiesFilePath)) { + this.context.trace("Loading properties from {}", file); + boolean legacyProperties = file.getFileName().toString().equals(LEGACY_PROPERTIES); + try (BufferedReader reader = Files.newBufferedReader(file)) { String line; do { line = reader.readLine(); @@ -86,7 +140,7 @@ private void load() { boolean legacyVariable = IdeVariables.isLegacyVariable(name); if (legacyVariable && !legacyProperties) { this.context.warning("Legacy variable name is used to define variable {} in {} - please cleanup your configuration.", variableLine, - this.propertiesFilePath); + file); } String oldValue = this.variables.get(migratedName); if (oldValue != null) { @@ -94,10 +148,10 @@ private void load() { if (legacyVariable) { // if the legacy name was configured we do not want to override the official variable! this.context.warning("Both legacy variable {} and official variable {} are configured in {} - ignoring legacy variable declaration!", - variableDefinition.getLegacyName(), variableDefinition.getName(), this.propertiesFilePath); + variableDefinition.getLegacyName(), variableDefinition.getName(), file); } else { this.context.warning("Duplicate variable definition {} with old value '{}' and new value '{}' in {}", name, oldValue, migratedValue, - this.propertiesFilePath); + file); this.variables.put(migratedName, migratedValue); } } else { @@ -109,58 +163,39 @@ private void load() { } } } while (line != null); + return true; } catch (IOException e) { - throw new IllegalStateException("Failed to load properties from " + this.propertiesFilePath, e); + throw new IllegalStateException("Failed to load properties from " + file, e); } } @Override public void save() { - if (this.modifiedVariables.isEmpty()) { + boolean isLegecy = Boolean.TRUE.equals(this.legacyConfiguration); + if (this.modifiedVariables.isEmpty() && !isLegecy) { this.context.trace("No changes to save in properties file {}", this.propertiesFilePath); return; } - Path newPropertiesFilePath = this.propertiesFilePath; - String propertiesFileName = this.propertiesFilePath.getFileName().toString(); - Path propertiesParentPath = newPropertiesFilePath.getParent(); - if (LEGACY_PROPERTIES.equals(propertiesFileName)) { - newPropertiesFilePath = propertiesParentPath.resolve(DEFAULT_PROPERTIES); - this.context.info("Converting legacy properties to {}", newPropertiesFilePath); + Path file = this.propertiesFilePath; + if (isLegecy) { + this.context.info("Converting legacy properties to {}", this.propertiesFilePath); + file = this.legacyPropertiesFilePath; } - this.context.getFileAccess().mkdirs(propertiesParentPath); - List lines = new ArrayList<>(); - - // Skip reading if the file does not exist - if (Files.exists(this.propertiesFilePath)) { - try (BufferedReader reader = Files.newBufferedReader(this.propertiesFilePath)) { - String line; - do { - line = reader.readLine(); - if (line != null) { - VariableLine variableLine = VariableLine.of(line, this.context, getSource()); - lines.add(variableLine); - } - } while (line != null); - } catch (IOException e) { - throw new IllegalStateException("Failed to load existing properties from " + this.propertiesFilePath, e); - } - } else { - this.context.debug("Properties file {} does not exist, skipping read.", newPropertiesFilePath); - } + List lines = loadVariableLines(file); - try (BufferedWriter writer = Files.newBufferedWriter(newPropertiesFilePath, StandardOpenOption.CREATE, - StandardOpenOption.TRUNCATE_EXISTING)) { + this.context.getFileAccess().mkdirs(this.propertiesFilePath.getParent()); + try (BufferedWriter writer = Files.newBufferedWriter(this.propertiesFilePath)) { // copy and modify original lines from properties file for (VariableLine line : lines) { VariableLine newLine = migrateLine(line, true); if (newLine == null) { - this.context.debug("Removed variable line '{}' from {}", line, newPropertiesFilePath); + this.context.debug("Removed variable line '{}' from {}", line, this.propertiesFilePath); } else { if (newLine != line) { - this.context.debug("Changed variable line from '{}' to '{}' in {}", line, newLine, newPropertiesFilePath); + this.context.debug("Changed variable line from '{}' to '{}' in {}", line, newLine, this.propertiesFilePath); } writer.append(newLine.toString()); writer.append(NEWLINE); @@ -184,9 +219,31 @@ public void save() { } this.modifiedVariables.clear(); } catch (IOException e) { - throw new IllegalStateException("Failed to save properties to " + newPropertiesFilePath, e); + throw new IllegalStateException("Failed to save properties to " + this.propertiesFilePath, e); + } + this.legacyConfiguration = Boolean.FALSE; + } + + private List loadVariableLines(Path file) { + List lines = new ArrayList<>(); + if (!Files.exists(file)) { + // Skip reading if the file does not exist + this.context.debug("Properties file {} does not exist, skipping read.", file); + return lines; + } + try (BufferedReader reader = Files.newBufferedReader(file)) { + String line; + do { + line = reader.readLine(); + if (line != null) { + VariableLine variableLine = VariableLine.of(line, this.context, getSource()); + lines.add(variableLine); + } + } while (line != null); + } catch (IOException e) { + throw new IllegalStateException("Failed to load existing properties from " + file, e); } - this.propertiesFilePath = newPropertiesFilePath; + return lines; } private VariableLine migrateLine(VariableLine line, boolean saveNotLoad) { @@ -232,7 +289,7 @@ protected void collectVariables(Map variables, boolean onl } @Override - protected boolean isExported(String name) { + public boolean isExported(String name) { if (this.exportedVariables.contains(name)) { return true; @@ -255,17 +312,22 @@ public Path getPropertiesFilePath() { @Override public Path getLegacyPropertiesFilePath() { - if (this.propertiesFilePath == null) { - return null; - } - if (this.propertiesFilePath.getFileName().toString().equals(LEGACY_PROPERTIES)) { - return this.propertiesFilePath; - } - Path legacyProperties = this.propertiesFilePath.getParent().resolve(LEGACY_PROPERTIES); - if (Files.exists(legacyProperties)) { - return legacyProperties; - } - return null; + return this.legacyPropertiesFilePath; + } + + /** + * @return {@code Boolean#TRUE} if the current variable state comes from {@link #getLegacyPropertiesFilePath()}, {@code Boolean#FALSE} if state comes from + * {@link #getPropertiesFilePath()}), and {@code null} if neither of these files existed (nothing was loaded). + */ + public Boolean getLegacyConfiguration() { + + return this.legacyConfiguration; + } + + @Override + public String set(String name, String value) { + + return set(name, value, this.exportedVariables.contains(name)); } @Override @@ -287,16 +349,14 @@ public String set(String name, String value, boolean export) { return oldValue; } - /** - * Removes a property. - * - * @param name name of the property to remove. - */ + @Override public void remove(String name) { - this.variables.remove(name); - this.modifiedVariables.add(name); - this.exportedVariables.remove(name); - this.context.debug("Removed variable name of '{}' in {}", name, this.propertiesFilePath); + String oldValue = this.variables.remove(name); + if (oldValue != null) { + this.modifiedVariables.add(name); + this.exportedVariables.remove(name); + this.context.debug("Removed variable name of '{}' in {}", name, this.propertiesFilePath); + } } } diff --git a/cli/src/main/java/com/devonfw/tools/ide/io/FileAccess.java b/cli/src/main/java/com/devonfw/tools/ide/io/FileAccess.java index 42cc5a5ad..6fb4d47dc 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/io/FileAccess.java +++ b/cli/src/main/java/com/devonfw/tools/ide/io/FileAccess.java @@ -210,6 +210,9 @@ default void extract(Path archiveFile, Path targetDir, Consumer postExtrac /** * Deletes the given {@link Path} idempotent and recursive. + *

+ * ATTENTION: In most cases we want to use {@link #backup(Path)} instead to prevent the user from data loss. + *

* * @param path the {@link Path} to delete. */ diff --git a/cli/src/main/java/com/devonfw/tools/ide/io/FileAccessImpl.java b/cli/src/main/java/com/devonfw/tools/ide/io/FileAccessImpl.java index 11cc23d72..08b0b4e7f 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/io/FileAccessImpl.java +++ b/cli/src/main/java/com/devonfw/tools/ide/io/FileAccessImpl.java @@ -263,20 +263,31 @@ private boolean isJunction(Path path) { @Override public void backup(Path fileOrFolder) { - if (Files.isSymbolicLink(fileOrFolder) || isJunction(fileOrFolder)) { + if ((fileOrFolder != null) && (Files.isSymbolicLink(fileOrFolder) || isJunction(fileOrFolder))) { delete(fileOrFolder); - } else { + } else if ((fileOrFolder != null) && Files.exists(fileOrFolder)) { // fileOrFolder is a directory - Path backupPath = this.context.getIdeHome().resolve(IdeContext.FOLDER_UPDATES).resolve(IdeContext.FOLDER_BACKUPS); LocalDateTime now = LocalDateTime.now(); - String date = DateTimeUtil.formatDate(now); + String date = DateTimeUtil.formatDate(now, true); String time = DateTimeUtil.formatTime(now); - Path backupDatePath = backupPath.resolve(date); - mkdirs(backupDatePath); - Path target = backupDatePath.resolve(fileOrFolder.getFileName().toString() + "_" + time); + String filename = fileOrFolder.getFileName().toString(); + Path backupPath = this.context.getIdeHome().resolve(IdeContext.FOLDER_BACKUPS).resolve(date).resolve(time + "_" + filename); + backupPath = appendParentPath(backupPath, fileOrFolder.getParent(), 2); + mkdirs(backupPath); + Path target = backupPath.resolve(filename); this.context.info("Creating backup by moving {} to {}", fileOrFolder, target); move(fileOrFolder, target); + } else { + this.context.trace("Backup of {} skipped as the path does not exist.", fileOrFolder); + } + } + + private static Path appendParentPath(Path path, Path parent, int max) { + + if ((parent == null) || (max <= 0)) { + return path; } + return appendParentPath(path, parent.getParent(), max - 1).resolve(parent.getFileName()); } @Override diff --git a/cli/src/main/java/com/devonfw/tools/ide/util/DateTimeUtil.java b/cli/src/main/java/com/devonfw/tools/ide/util/DateTimeUtil.java index 0fd836d9a..5dc3116fa 100644 --- a/cli/src/main/java/com/devonfw/tools/ide/util/DateTimeUtil.java +++ b/cli/src/main/java/com/devonfw/tools/ide/util/DateTimeUtil.java @@ -11,7 +11,10 @@ */ public final class DateTimeUtil { - private static final DateTimeFormatter DATE_FORMATTER = new DateTimeFormatterBuilder().appendPattern("YYYY-MM-dd") + private static final DateTimeFormatter DATE_FORMATTER_PATH = new DateTimeFormatterBuilder().appendPattern("YYYY/MM/dd") + .toFormatter(); + + private static final DateTimeFormatter DATE_FORMATTER_NAME = new DateTimeFormatterBuilder().appendPattern("YYYY-MM-dd") .toFormatter(); private static final DateTimeFormatter TIME_FORMATTER = new DateTimeFormatterBuilder().appendPattern("HH-mm-ss") @@ -66,11 +69,16 @@ public static Integer compareDuration(Instant start, Instant end, Duration durat /** * @param temporal the {@link LocalDateTime} to format as date. - * @return the {@link LocalDateTime} formatted as date in the format YYYY-MM-dd. + * @param dirs {@code true} to use "/" as separator to create subfolders per year, month, and date, {@code false} otherwise. + * @return the {@link LocalDateTime} formatted as date in the format YYYY-MM-dd or YYYY/MM/dd. */ - public static String formatDate(LocalDateTime temporal) { + public static String formatDate(LocalDateTime temporal, boolean dirs) { - return temporal.format(DATE_FORMATTER); + if (dirs) { + return temporal.format(DATE_FORMATTER_PATH); + } else { + return temporal.format(DATE_FORMATTER_NAME); + } } /** diff --git a/cli/src/test/java/com/devonfw/tools/ide/commandlet/UpgradeSettingsCommandletTest.java b/cli/src/test/java/com/devonfw/tools/ide/commandlet/UpgradeSettingsCommandletTest.java index cefaf21ed..5552e445a 100644 --- a/cli/src/test/java/com/devonfw/tools/ide/commandlet/UpgradeSettingsCommandletTest.java +++ b/cli/src/test/java/com/devonfw/tools/ide/commandlet/UpgradeSettingsCommandletTest.java @@ -43,14 +43,18 @@ public void testUpdateSettings() throws Exception { */ private void verifyUpdateProperties() throws Exception { - // FIXME assertThat(UPGRADE_SETTINGS_PATH.resolve("home/ide.properties")).exists(); + assertThat(UPGRADE_SETTINGS_PATH.resolve("home/.ide/ide.properties")).exists(); assertThat(UPGRADE_SETTINGS_PATH.resolve("settings/ide.properties")).exists().content().contains("INTELLIJ_EDITION=ultimate") - .doesNotContain("INTELLIJ_EDITION_TYPE"); - assertThat(UPGRADE_SETTINGS_PATH.resolve("settings/ide.properties")).exists().content().contains("IDE_VARIABLE_SYNTAX_LEGACY_SUPPORT_ENABLED=false"); + .doesNotContain("INTELLIJ_EDITION_TYPE").contains("IDE_VARIABLE_SYNTAX_LEGACY_SUPPORT_ENABLED=false"); assertThat(UPGRADE_SETTINGS_PATH.resolve("workspaces/main/ide.properties")).exists(); //assert that file content was changed assertThat(UPGRADE_SETTINGS_PATH.resolve("conf/ide.properties")).exists().content().contains("MVN_VERSION=test"); + // devon.properties have been deleted (moved to backup) + assertThat(UPGRADE_SETTINGS_PATH.resolve("home/devon.properties")).doesNotExist(); + assertThat(UPGRADE_SETTINGS_PATH.resolve("settings/devon.properties")).doesNotExist(); + assertThat(UPGRADE_SETTINGS_PATH.resolve("workspaces/main/devon.properties")).doesNotExist(); + assertThat(UPGRADE_SETTINGS_PATH.resolve("conf/devon.properties")).doesNotExist(); verifyCustomToolsJson(); }