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

devonfw / IDEasy / 19681245351

25 Nov 2025 07:13PM UTC coverage: 69.164% (+0.02%) from 69.147%
19681245351

Pull #1569

github

web-flow
Merge e3efba70a into ec798104b
Pull Request #1569: Add support for comma-separated workspace values in repository configuration

3650 of 5789 branches covered (63.05%)

Branch coverage included in aggregate %.

9476 of 13189 relevant lines covered (71.85%)

3.15 hits per line

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

56.38
cli/src/main/java/com/devonfw/tools/ide/git/repository/RepositoryCommandlet.java
1
package com.devonfw.tools.ide.git.repository;
2

3
import java.nio.file.Files;
4
import java.nio.file.Path;
5
import java.util.List;
6
import java.util.Set;
7

8
import com.devonfw.tools.ide.commandlet.Commandlet;
9
import com.devonfw.tools.ide.context.IdeContext;
10
import com.devonfw.tools.ide.git.GitContext;
11
import com.devonfw.tools.ide.git.GitUrl;
12
import com.devonfw.tools.ide.io.FileAccess;
13
import com.devonfw.tools.ide.property.RepositoryProperty;
14
import com.devonfw.tools.ide.step.Step;
15
import com.devonfw.tools.ide.tool.ToolCommandlet;
16
import com.devonfw.tools.ide.tool.ide.IdeToolCommandlet;
17

18
/**
19
 * {@link Commandlet} to setup one or multiple GIT repositories for development.
20
 */
21
public class RepositoryCommandlet extends Commandlet {
22

23
  /** the repository to setup. */
24
  public final RepositoryProperty repository;
25

26
  /**
27
   * The constructor.
28
   *
29
   * @param context the {@link IdeContext}.
30
   */
31
  public RepositoryCommandlet(IdeContext context) {
32

33
    super(context);
3✔
34
    addKeyword(getName());
4✔
35
    addKeyword("setup");
3✔
36
    this.repository = add(new RepositoryProperty("", false, "repository"));
11✔
37
  }
1✔
38

39
  @Override
40
  public String getName() {
41

42
    return "repository";
2✔
43
  }
44

45
  @Override
46
  public void run() {
47

48
    Path repositoryFile = this.repository.getValue();
5✔
49

50
    if (repositoryFile != null) {
2✔
51
      // Handle the case when a specific repository is provided
52
      doImportRepository(repositoryFile, true);
5✔
53
    } else {
54
      // If no specific repository is provided, check for repositories folder
55
      Path repositoriesPath = this.context.getRepositoriesPath();
4✔
56
      if (repositoriesPath == null) {
2✔
57
        this.context.warning("Cannot find folder 'repositories' nor 'projects' in your settings.");
4✔
58
        return;
1✔
59
      }
60
      List<Path> propertiesFiles = this.context.getFileAccess()
5✔
61
          .listChildren(repositoriesPath, path -> path.getFileName().toString().endsWith(".properties"));
8✔
62
      boolean forceMode = this.context.isForceMode() || this.context.isForceRepositories();
12!
63
      for (Path propertiesFile : propertiesFiles) {
10✔
64
        doImportRepository(propertiesFile, forceMode);
4✔
65
      }
1✔
66
    }
67
  }
1✔
68

69
  private void doImportRepository(Path repositoryFile, boolean forceMode) {
70

71
    String repositoryFilename = repositoryFile.getFileName().toString();
4✔
72
    final String repositoryId;
73
    if (repositoryFilename.endsWith(IdeContext.EXT_PROPERTIES)) {
4!
74
      repositoryId = repositoryFilename.substring(0, repositoryFilename.length() - IdeContext.EXT_PROPERTIES.length());
10✔
75
    } else {
76
      repositoryId = repositoryFilename;
×
77
    }
78
    this.context.newStep("Setup of repository " + repositoryId, repositoryFile).run(() -> {
18✔
79
      doImportRepository(repositoryFile, forceMode, repositoryId);
5✔
80
    });
1✔
81
  }
1✔
82

83
  private void doImportRepository(Path repositoryFile, boolean forceMode, String repositoryId) {
84
    RepositoryConfig repositoryConfig = RepositoryConfig.loadProperties(repositoryFile, this.context);
5✔
85
    if (!repositoryConfig.active()) {
3!
86
      if (forceMode) {
2✔
87
        this.context.info("Setup of repository {} is forced, hence proceeding ...", repositoryId);
11✔
88
      } else {
89
        this.context.info("Skipping repository {} because it is not active - use --force to setup all repositories ...", repositoryId);
10✔
90
        return;
1✔
91
      }
92
    }
93
    GitUrl gitUrl = repositoryConfig.asGitUrl();
3✔
94
    if (gitUrl == null) {
2!
95
      // error was already logged.
96
      return;
×
97
    }
98
    this.context.debug("Repository configuration: {}", repositoryConfig);
10✔
99
    List<Path> repositoryPaths = getRepositoryPaths(repositoryConfig, repositoryId);
5✔
100
    Path ideStatusDir = this.context.getIdeHome().resolve(IdeContext.FOLDER_DOT_IDE);
6✔
101
    this.context.getFileAccess().mkdirs(ideStatusDir);
5✔
102
    
103
    for (Path repositoryPath : repositoryPaths) {
10✔
104
      String workspaceName = getWorkspaceName(repositoryPath);
4✔
105
      if (Files.isDirectory(repositoryPath.resolve(GitContext.GIT_FOLDER))) {
7!
106
        this.context.info("Repository {} already exists in workspace {} at {}", repositoryId, workspaceName, repositoryPath);
×
107
        if (!(this.context.isForceMode() || this.context.isForceRepositories())) {
×
108
          this.context.info("Ignoring repository {} in workspace {} - use --force or --force-repositories to rerun setup.", repositoryId, workspaceName);
×
109
          continue;
×
110
        }
111
      }
112
      Path repositoryCreatedStatusFile = ideStatusDir.resolve("repository." + repositoryId + "." + workspaceName);
6✔
113
      if (Files.exists(repositoryCreatedStatusFile)) {
5!
114
        if (!(this.context.isForceMode() || this.context.isForceRepositories())) {
×
115
          this.context.info("Ignoring repository {} in workspace {} because it was already setup before - use --force or --force-repositories for recreation.", repositoryId, workspaceName);
×
116
          continue;
×
117
        }
118
      }
119
      boolean success = cloneOrPullRepository(repositoryPath, gitUrl, repositoryCreatedStatusFile);
6✔
120
      if (success) {
2!
121
        buildRepository(repositoryConfig, repositoryPath);
5✔
122
        importRepository(repositoryConfig, repositoryPath, repositoryId);
5✔
123
      }
124
    }
1✔
125
  }
1✔
126

127
  private boolean cloneOrPullRepository(Path repositoryPath, GitUrl gitUrl, Path repositoryCreatedStatusFile) {
128

129
    FileAccess fileAccess = this.context.getFileAccess();
4✔
130
    return this.context.newStep("Clone or pull repository").run(() -> {
12✔
131
      fileAccess.mkdirs(repositoryPath);
3✔
132
      this.context.getGitContext().pullOrClone(gitUrl, repositoryPath);
6✔
133
      fileAccess.touch(repositoryCreatedStatusFile);
3✔
134
    });
1✔
135
  }
136

137
  private List<Path> getRepositoryPaths(RepositoryConfig repositoryConfig, String repositoryId) {
138
    Set<String> workspaces = repositoryConfig.workspaces();
3✔
139
    if (workspaces == null || workspaces.isEmpty()) {
5!
140
      workspaces = Set.of(IdeContext.WORKSPACE_MAIN);
×
141
    }
142
    String repositoryRelativePath = repositoryConfig.path();
3✔
143
    if (repositoryRelativePath == null) {
2✔
144
      repositoryRelativePath = repositoryId;
2✔
145
    }
146
    List<Path> repositoryPaths = new java.util.ArrayList<>();
4✔
147
    for (String workspace : workspaces) {
10✔
148
      Path workspacePath = this.context.getIdeHome().resolve(IdeContext.FOLDER_WORKSPACES).resolve(workspace);
8✔
149
      repositoryPaths.add(workspacePath.resolve(repositoryRelativePath));
6✔
150
    }
1✔
151
    return repositoryPaths;
2✔
152
  }
153

154
  private String getWorkspaceName(Path repositoryPath) {
155
    Path workspacesFolder = this.context.getIdeHome().resolve(IdeContext.FOLDER_WORKSPACES);
6✔
156
    Path relativePath = workspacesFolder.relativize(repositoryPath);
4✔
157
    return relativePath.getName(0).toString();
5✔
158
  }
159

160
  private boolean buildRepository(RepositoryConfig repositoryConfig, Path repositoryPath) {
161
    String buildCmd = repositoryConfig.buildCmd();
3✔
162
    if (buildCmd != null && !buildCmd.isEmpty()) {
2!
163
      return this.context.newStep("Build repository via: " + buildCmd).run(() -> {
×
164
        String[] command = buildCmd.split("\\s+");
×
165
        ToolCommandlet commandlet = this.context.getCommandletManager().getToolCommandlet(command[0]);
×
166
        if (commandlet == null) {
×
167
          String displayName = (command[0] == null || command[0].isBlank()) ? "<empty>" : "'" + command[0] + "'";
×
168
          this.context.error("Cannot build repository. Required tool '{}' not found. Please check your repository's build_cmd configuration value.", displayName);
×
169
          return;
×
170
        }
171
        commandlet.reset();
×
172
        for (int i = 1; i < command.length; i++) {
×
173
          commandlet.arguments.addValue(command[i]);
×
174
        }
175
        Path executionDirectory = repositoryPath;
×
176
        String path = repositoryConfig.buildPath();
×
177
        if (path != null) {
×
178
          executionDirectory = executionDirectory.resolve(path);
×
179
        }
180
        commandlet.setExecutionDirectory(executionDirectory);
×
181
        commandlet.run();
×
182
      });
×
183
    } else {
184
      this.context.debug("Build command not set. Skipping build for repository.");
4✔
185
      return true;
2✔
186
    }
187
  }
188

189
  private void importRepository(RepositoryConfig repositoryConfig, Path repositoryPath, String repositoryId) {
190

191
    Set<String> imports = repositoryConfig.imports();
3✔
192
    if ((imports == null) || imports.isEmpty()) {
5!
193
      this.context.debug("Repository {} has no IDE configured for import.", repositoryId);
10✔
194
      return;
1✔
195
    }
196
    for (String ide : imports) {
×
197
      Step step = this.context.newStep("Importing repository " + repositoryId + " into " + ide);
×
198
      step.run(() -> {
×
199
        ToolCommandlet commandlet = this.context.getCommandletManager().getToolCommandlet(ide);
×
200
        if (commandlet == null) {
×
201
          String displayName = (ide == null || ide.isBlank()) ? "<empty>" : "'" + ide + "'";
×
202
          step.error("Cannot import repository '{}'. Required IDE '{}' not found. Please check your repository's imports configuration.", repositoryId, displayName);
×
203
        } else if (commandlet instanceof IdeToolCommandlet ideCommandlet) {
×
204
          ideCommandlet.importRepository(repositoryPath);
×
205
        } else {
206
          step.error("Repository {} has import {} configured that is not an IDE!", repositoryId, ide);
×
207
        }
208
      });
×
209
    }
×
210
  }
×
211
}
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

© 2025 Coveralls, Inc