• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

devonfw / IDEasy / 16992639699

15 Aug 2025 02:54PM UTC coverage: 69.372% (-0.1%) from 69.51%
16992639699

push

github

web-flow
#1451: fix merge:id default for single attribute (#1452)

3362 of 5289 branches covered (63.57%)

Branch coverage included in aggregate %.

8731 of 12143 relevant lines covered (71.9%)

3.16 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.15
cli/src/main/java/com/devonfw/tools/ide/merge/FileMerger.java
1
package com.devonfw.tools.ide.merge;
2

3
import java.io.IOException;
4
import java.nio.file.Files;
5
import java.nio.file.Path;
6
import java.nio.file.StandardCopyOption;
7
import java.util.regex.Matcher;
8

9
import com.devonfw.tools.ide.context.IdeContext;
10
import com.devonfw.tools.ide.environment.EnvironmentVariables;
11
import com.devonfw.tools.ide.variable.IdeVariables;
12
import com.devonfw.tools.ide.variable.VariableDefinition;
13
import com.devonfw.tools.ide.variable.VariableSyntax;
14

15
/**
16
 * {@link WorkspaceMerger} responsible for a single type of file.
17
 */
18
public abstract class FileMerger extends AbstractWorkspaceMerger {
19

20
  protected final boolean legacySupport;
21

22
  /**
23
   * The constructor.
24
   *
25
   * @param context the {@link #context}.
26
   */
27
  public FileMerger(IdeContext context) {
28

29
    super(context);
3✔
30
    this.legacySupport = Boolean.TRUE.equals(IdeVariables.IDE_VARIABLE_SYNTAX_LEGACY_SUPPORT_ENABLED.get(context));
7✔
31
  }
1✔
32

33
  /**
34
   * @param sourceFile Path to source file.
35
   * @param targetFile Path to target file.
36
   */
37
  protected void copy(Path sourceFile, Path targetFile) {
38

39
    ensureParentDirectoryExists(targetFile);
2✔
40
    try {
41
      Files.copy(sourceFile, targetFile, StandardCopyOption.REPLACE_EXISTING);
10✔
42
    } catch (Exception e) {
×
43
      throw new IllegalStateException("Failed to copy file " + sourceFile + " to " + targetFile, e);
×
44
    }
1✔
45
  }
1✔
46

47
  @Override
48
  public final int merge(Path setup, Path update, EnvironmentVariables variables, Path workspace) {
49
    try {
50
      doMerge(setup, update, variables, workspace);
6✔
51
    } catch (Exception e) {
×
52
      this.context.error(e, "Failed to merge workspace file {} with update template {} and setup file {}!", workspace, update, setup);
×
53
      return 1;
×
54
    }
1✔
55
    return 0;
2✔
56
  }
57

58
  /**
59
   * Same as {@link #merge(Path, Path, EnvironmentVariables, Path)} but without error handling.
60
   *
61
   * @param setup the setup {@link Path} for creation.
62
   * @param update the update {@link Path} for creation and update.
63
   * @param variables the {@link EnvironmentVariables} to {@link EnvironmentVariables#resolve(String, Object) resolve variables}.
64
   * @param workspace the workspace {@link Path} to create or update.
65
   */
66
  protected abstract void doMerge(Path setup, Path update, EnvironmentVariables variables, Path workspace);
67

68
  @Override
69
  public void upgrade(Path workspaceFile) {
70

71
    try {
72
      boolean modified = doUpgrade(workspaceFile);
4✔
73
      if (modified) {
2✔
74
        this.context.debug("Successfully migrated file {}", workspaceFile);
11✔
75
      } else {
76
        this.context.trace("Nothing to migrate in file {}", workspaceFile);
10✔
77
      }
78
    } catch (Exception e) {
×
79
      throw new IllegalStateException("Failed to update file " + workspaceFile, e);
×
80
    }
1✔
81
  }
1✔
82

83
  /**
84
   * @param workspaceFile the {@link Path} to the file to migrate.
85
   * @return {@code true} if the file was migrated (modified), {@code false} otherwise.
86
   * @throws Exception on error.
87
   * @see #upgrade(Path)
88
   */
89
  protected abstract boolean doUpgrade(Path workspaceFile) throws Exception;
90

91
  /**
92
   * Implementation for {@link #doUpgrade(Path)} in case of simple text file format.
93
   *
94
   * @param workspaceFile the {@link Path} to the file to migrate.
95
   * @return {@code true} if the file was migrated (modified), {@code false} otherwise.
96
   * @throws IOException on error.
97
   */
98
  protected boolean doUpgradeTextContent(Path workspaceFile) throws IOException {
99

100
    String content = Files.readString(workspaceFile);
3✔
101
    String migratedContent = upgradeWorkspaceContent(content);
4✔
102
    boolean modified = !migratedContent.equals(content);
8✔
103
    if (modified) {
2✔
104
      Files.writeString(workspaceFile, migratedContent);
6✔
105
    }
106
    return modified;
2✔
107
  }
108

109
  /**
110
   * @param content the content from a workspace template file that may contain legacy stuff like old variable syntax.
111
   * @return the given {@link String} with potential legacy constructs being resolved.
112
   */
113
  protected String upgradeWorkspaceContent(String content) {
114

115
    VariableSyntax syntax = VariableSyntax.CURLY;
2✔
116
    Matcher matcher = syntax.getPattern().matcher(content);
5✔
117
    StringBuilder sb = null;
2✔
118
    while (matcher.find()) {
3✔
119
      if (sb == null) {
2✔
120
        sb = new StringBuilder(content.length() + 8);
8✔
121
      }
122
      String variableName = syntax.getVariable(matcher);
4✔
123
      String replacement;
124
      VariableDefinition<?> variableDefinition = IdeVariables.get(variableName);
3✔
125
      if (variableDefinition != null) {
2✔
126
        variableName = variableDefinition.getName(); // ensure legacy name gets replaced with new name
3✔
127
        replacement = VariableSyntax.SQUARE.create(variableName);
5✔
128
      } else if (variableName.equals("SETTINGS_PATH")) {
4!
129
        replacement = "$[IDE_HOME]/settings";
3✔
130
      } else {
131
        replacement = matcher.group(); // leave ${variableName} untouched
×
132
      }
133
      matcher.appendReplacement(sb, Matcher.quoteReplacement(replacement));
6✔
134
    }
1✔
135
    if (sb == null) {
2✔
136
      return content;
2✔
137
    }
138
    matcher.appendTail(sb);
4✔
139
    return sb.toString().replace("\\conf\\.m2\\", "/conf/.m2/").replace("/conf/.m2/", "/conf/mvn/");
9✔
140
  }
141

142

143
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc