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

devonfw / IDEasy / 29803149984

21 Jul 2026 05:08AM UTC coverage: 72.439% (-0.04%) from 72.476%
29803149984

Pull #2179

github

web-flow
Merge c6c1d1813 into 3221b7580
Pull Request #2179: Feature/2165 interactive template variables

4961 of 7574 branches covered (65.5%)

Branch coverage included in aggregate %.

12804 of 16950 relevant lines covered (75.54%)

3.2 hits per line

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

78.57
cli/src/main/java/com/devonfw/tools/ide/context/IdeContext.java
1
package com.devonfw.tools.ide.context;
2

3
import java.nio.file.Files;
4
import java.nio.file.Path;
5

6
import com.devonfw.tools.ide.cli.CliAbortException;
7
import com.devonfw.tools.ide.cli.CliException;
8
import com.devonfw.tools.ide.cli.CliOfflineException;
9
import com.devonfw.tools.ide.commandlet.CommandletManager;
10
import com.devonfw.tools.ide.common.SystemPath;
11
import com.devonfw.tools.ide.environment.EnvironmentVariables;
12
import com.devonfw.tools.ide.environment.EnvironmentVariablesType;
13
import com.devonfw.tools.ide.environment.IdeSystem;
14
import com.devonfw.tools.ide.git.GitContext;
15
import com.devonfw.tools.ide.io.FileAccess;
16
import com.devonfw.tools.ide.io.IdeProgressBar;
17
import com.devonfw.tools.ide.io.IdeProgressBarNone;
18
import com.devonfw.tools.ide.log.IdeLogLevel;
19
import com.devonfw.tools.ide.merge.DirectoryMerger;
20
import com.devonfw.tools.ide.network.NetworkStatus;
21
import com.devonfw.tools.ide.os.SystemInfo;
22
import com.devonfw.tools.ide.os.WindowsPathSyntax;
23
import com.devonfw.tools.ide.process.ProcessContext;
24
import com.devonfw.tools.ide.step.Step;
25
import com.devonfw.tools.ide.tool.corepack.Corepack;
26
import com.devonfw.tools.ide.tool.custom.CustomToolRepository;
27
import com.devonfw.tools.ide.tool.gradle.Gradle;
28
import com.devonfw.tools.ide.tool.mvn.Mvn;
29
import com.devonfw.tools.ide.tool.mvn.MvnRepository;
30
import com.devonfw.tools.ide.tool.npm.Npm;
31
import com.devonfw.tools.ide.tool.npm.NpmRepository;
32
import com.devonfw.tools.ide.tool.pip.PipRepository;
33
import com.devonfw.tools.ide.tool.repository.ToolRepository;
34
import com.devonfw.tools.ide.tool.uv.UvRepository;
35
import com.devonfw.tools.ide.url.model.UrlMetadata;
36
import com.devonfw.tools.ide.variable.IdeVariables;
37
import com.devonfw.tools.ide.version.IdeVersion;
38
import com.devonfw.tools.ide.version.VersionIdentifier;
39

40
/**
41
 * Interface for the context of IDEasy and the potential current project. Central constants for names of files and folders are defined here and should be
42
 * referenced instead of duplicating such string literals across the code-base. All central components can be accessed from here such as:
43
 * <ul>
44
 * <li>{@link #getPath() system path} (abstraction of PATH environment variable)</li>
45
 * <li>{@link #getCommandletManager() commandlet manager} (access {@link com.devonfw.tools.ide.commandlet.Commandlet}s)</li>
46
 * <li>{@link #getFileAccess() file access} (file and I/O operations on a higher level of abstraction)</li>
47
 * <li>{@link #getNetworkStatus() network status} (determine if we are online or offline)</li>
48
 * <li>{@link #newProcess() process context} (start external programs as process including logging, error handling, background and output processing)</li>
49
 * <li>{@link #newStep(String) step} creation (a sub-task that may fail without stopping the overall process)</li>
50
 * <li>{@link #newProgressBar(String, long, String, long) progress bar} (to display long-running progress for UX)</li>
51
 * <li>{@link #getGitContext() git context} (for git operations like clone, fetch, pull, etc.)</li>
52
 * <li>{@link #getSystemInfo() system info} (for information about OS and CPU architecture)</li>
53
 * <li>{@link #getVariables() environment variables} (to access and modify IDEasy variables according to our configuration layout)</li>
54
 *
55
 * <li>{@link #question(Object[], String, Object...) question} (for interaction to let the end-user decide)</li>
56
 * <li>{@link #getUrls() url metadata} (access ide-urls to find versions, download URLs, dependency and security metadata)</li>
57
 * <li>{@link #getDefaultToolRepository() tool repository} (for abstraction of version resolution and download of tools)</li>
58
 * <li>{@link #getSystem() ide system} (abstraction of {@link java.lang.System} for system environment variables)</li>
59
 * </ul>
60
 */
61
public interface IdeContext extends IdeStartContext {
62

63
  /**
64
   * The default settings URL.
65
   *
66
   * @see com.devonfw.tools.ide.commandlet.AbstractUpdateCommandlet
67
   */
68
  String DEFAULT_SETTINGS_REPO_URL = "https://github.com/devonfw/ide-settings.git";
69

70
  /** The name of the workspaces folder. */
71
  String FOLDER_WORKSPACES = "workspaces";
72

73
  /** The name of the {@link #getSettingsPath() settings} folder. */
74
  String FOLDER_SETTINGS = "settings";
75

76
  /** The name of the {@link #getSoftwarePath() software} folder. */
77
  String FOLDER_SOFTWARE = "software";
78

79
  /** The name of the {@link #getUrlsPath() urls} folder. */
80
  String FOLDER_URLS = "urls";
81

82
  /** The name of the conf folder for project specific user configurations. */
83
  String FOLDER_CONF = "conf";
84

85
  /**
86
   * The name of the folder inside IDE_ROOT reserved for IDEasy. Intentionally starting with an underscore and not a dot to prevent effects like OS hiding,
87
   * maven filtering, .gitignore and to distinguish from {@link #FOLDER_DOT_IDE}.
88
   *
89
   * @see #getIdePath()
90
   */
91
  String FOLDER_UNDERSCORE_IDE = "_ide";
92

93
  /**
94
   * The name of the folder inside {@link #FOLDER_UNDERSCORE_IDE} with the current IDEasy installation.
95
   *
96
   * @see #getIdeInstallationPath()
97
   */
98
  String FOLDER_INSTALLATION = "installation";
99

100
  /**
101
   * The name of the hidden folder for IDE configuration in the users home directory or status information in the IDE_HOME directory.
102
   *
103
   * @see #getUserHomeIde()
104
   */
105
  String FOLDER_DOT_IDE = ".ide";
106

107
  /** The name of the updates folder for temporary data and backup. */
108
  String FOLDER_UPDATES = "updates";
109

110
  /** The name of the volume folder for mounting archives like *.dmg. */
111
  String FOLDER_VOLUME = "volume";
112

113
  /** The name of the backups folder for backup. */
114
  String FOLDER_BACKUPS = "backups";
115

116
  /** The name of the logs folder for log-files (in {@link #FOLDER_UNDERSCORE_IDE}). */
117
  String FOLDER_LOGS = "logs";
118

119
  /** The name of the downloads folder. */
120
  String FOLDER_DOWNLOADS = "Downloads";
121

122
  /** The name of the bin folder where executable files are found by default. */
123
  String FOLDER_BIN = "bin";
124

125
  /** The name of the repositories folder where properties files are stores for each repository */
126
  String FOLDER_REPOSITORIES = "repositories";
127

128
  /** The name of the repositories folder where properties files are stores for each repository */
129
  String FOLDER_LEGACY_REPOSITORIES = "projects";
130

131
  /** The name of the Contents folder inside a MacOS app. */
132
  String FOLDER_CONTENTS = "Contents";
133

134
  /** The name of the Resources folder inside a MacOS app. */
135
  String FOLDER_RESOURCES = "Resources";
136

137
  /** The name of the app folder inside a MacOS app. */
138
  String FOLDER_APP = "app";
139

140
  /** The name of the extra folder inside the software folder */
141
  String FOLDER_EXTRA = "extra";
142

143
  /**
144
   * The name of the {@link #getPluginsPath() plugins folder} and also the plugins folder inside the IDE folders of {@link #getSettingsPath() settings} (e.g.
145
   * settings/eclipse/plugins).
146
   */
147
  String FOLDER_PLUGINS = "plugins";
148

149
  /**
150
   * The name of the workspace folder inside the IDE specific {@link #FOLDER_SETTINGS settings} containing the configuration templates in #FOLDER_SETUP
151
   * #FOLDER_UPDATE.
152
   */
153
  String FOLDER_WORKSPACE = "workspace";
154

155
  /**
156
   * The name of the setup folder inside the {@link #FOLDER_WORKSPACE workspace} folder containing the templates for the configuration templates for the initial
157
   * setup of a workspace. This is closely related with the {@link #FOLDER_UPDATE update} folder.
158
   */
159
  String FOLDER_SETUP = "setup";
160

161
  /**
162
   * The name of the update folder inside the {@link #FOLDER_WORKSPACE workspace} folder containing the templates for the configuration templates for the update
163
   * of a workspace. Configurations in this folder will be applied every time the IDE is started. They will override the settings the user may have manually
164
   * configured every time. This is only for settings that have to be the same for every developer in the project. An example would be the number of spaces used
165
   * for indentation and other code-formatting settings. If all developers in a project team use the same formatter settings, this will actively prevent
166
   * diff-wars. However, the entire team needs to agree on these settings.<br> Never configure aspects inside this update folder that may be of personal flavor
167
   * such as the color theme. Otherwise developers will hate you as you actively take away their freedom to customize the IDE to their personal needs and
168
   * wishes. Therefore do all "biased" or "flavored" configurations in {@link #FOLDER_SETUP setup} so these are only pre-configured but can be changed by the
169
   * user as needed.
170
   */
171
  String FOLDER_UPDATE = "update";
172

173
  /**
174
   * The name of the folder inside {@link #FOLDER_UNDERSCORE_IDE _ide} folder containing internal resources and scripts of IDEasy.
175
   */
176
  String FOLDER_INTERNAL = "internal";
177

178
  /** The file where the installed software version is written to as plain text. */
179
  String FILE_SOFTWARE_VERSION = ".ide.software.version";
180

181
  /** The file where the installed software version is written to as plain text. */
182
  String FILE_LEGACY_SOFTWARE_VERSION = ".devon.software.version";
183

184
  /** The file for the license agreement. */
185
  String FILE_LICENSE_AGREEMENT = ".license.agreement";
186

187
  /** The file extension for a {@link java.util.Properties} file. */
188
  String EXT_PROPERTIES = ".properties";
189

190
  /** The default for {@link #getWorkspaceName()}. */
191
  String WORKSPACE_MAIN = "main";
192

193
  /** The folder with the configuration template files from the settings. */
194
  String FOLDER_TEMPLATES = "templates";
195

196
  /** Legacy folder name used as compatibility fallback if {@link #FOLDER_TEMPLATES} does not exist. */
197
  String FOLDER_LEGACY_TEMPLATES = "devon";
198

199
  /** The default folder name for {@link #getIdeRoot() IDE_ROOT}. */
200
  String FOLDER_PROJECTS = "projects";
201

202
  /**
203
   * file containing the current local commit hash of the settings repository.
204
   */
205
  String SETTINGS_COMMIT_ID = ".commit.id";
206

207
  /** The IDEasy ASCII logo. */
208
  String LOGO = """
4✔
209
      __       ___ ___  ___
210
      ╲ ╲     |_ _|   ╲| __|__ _ ____ _
211
       > >     | || |) | _|/ _` (_-< || |
212
      /_/ ___ |___|___/|___╲__,_/__/╲_, |
213
         |___|                       |__/
214
      """.replace('╲', '\\');
2✔
215

216
  /**
217
   * The keyword for project name convention.
218
   */
219
  String SETTINGS_REPOSITORY_KEYWORD = "settings";
220
  String IS_NOT_INSTALLED_BUT_REQUIRED = "is not installed on your computer but required by IDEasy.";
221
  String WINDOWS_GIT_DOWNLOAD_URL = "https://git-scm.com/download/";
222
  String PLEASE_DOWNLOAD_AND_INSTALL_GIT = "Please download and install git";
223

224
  /**
225
   * @return the {@link NetworkStatus} for online check and related operations.
226
   */
227
  NetworkStatus getNetworkStatus();
228

229
  /**
230
   * @return {@code true} if {@link #isOfflineMode() offline mode} is active or we are NOT {@link #isOnline() online}, {@code false} otherwise.
231
   * @deprecated use {@link #getNetworkStatus()}
232
   */
233
  default boolean isOffline() {
234

235
    return getNetworkStatus().isOffline();
4✔
236
  }
237

238
  /**
239
   * @return {@code true} if we are currently online (Internet access is available), {@code false} otherwise.
240
   * @deprecated use {@link #getNetworkStatus()}
241
   */
242
  default boolean isOnline() {
243

244
    return getNetworkStatus().isOnline();
×
245
  }
246

247
  /**
248
   * Print the IDEasy {@link #LOGO logo}.
249
   */
250
  default void printLogo() {
251

252
    AbstractIdeContext.LOG.info(LOGO);
3✔
253
  }
1✔
254

255
  /**
256
   * Asks the user for a single string input.
257
   *
258
   * @param message The information message to display.
259
   * @param defaultValue The default value to return when no input is provided or {@code null} to keep asking until the user entered a non empty value.
260
   * @return The string input from the user, or the default value if no input is provided.
261
   */
262
  String askForInput(String message, String defaultValue);
263

264
  /**
265
   * Asks the user for a single string input.
266
   *
267
   * @param message The information message to display.
268
   * @return The string input from the user.
269
   */
270
  default String askForInput(String message) {
271
    return askForInput(message, null);
5✔
272
  }
273

274
  /**
275
   * Asks the user for a secret value (e.g. a password or API token). Unlike {@link #askForInput(String)} the input will not be echoed to the console while
276
   * typing (if supported by the underlying terminal).
277
   *
278
   * @param message The information message to display.
279
   * @return The secret input from the user.
280
   */
281
  String askForSecret(String message);
282

283
  /**
284
   * @param question the question to ask.
285
   * @param args arguments for filling the templates
286
   * @return {@code true} if the user answered with "yes", {@code false} otherwise ("no").
287
   */
288
  default boolean question(String question, Object... args) {
289

290
    String yes = "yes";
2✔
291
    String option = question(new String[] { yes, "no" }, question, args);
16✔
292
    if (yes.equals(option)) {
4✔
293
      return true;
2✔
294
    }
295
    return false;
2✔
296
  }
297

298
  /**
299
   * @param <O> type of the option. E.g. {@link String}.
300
   * @param options the available options for the user to answer. There should be at least two options given as otherwise the question cannot make sense.
301
   * @param question the question to ask.
302
   * @return the option selected by the user as answer.
303
   */
304
  @SuppressWarnings("unchecked")
305
  <O> O question(O[] options, String question, Object... args);
306

307
  /**
308
   * Will ask the given question. If the user answers with "yes" the method will return and the process can continue. Otherwise if the user answers with "no" an
309
   * exception is thrown to abort further processing.
310
   *
311
   * @param questionTemplate the yes/no question to {@link #question(String, Object...) ask}.
312
   * @param args the arguments to fill the placeholders in the question template.
313
   * @throws CliAbortException if the user answered with "no" and further processing shall be aborted.
314
   */
315
  default void askToContinue(String questionTemplate, Object... args) {
316
    boolean yesContinue = question(questionTemplate, args);
5✔
317
    if (!yesContinue) {
2✔
318
      throw new CliAbortException();
4✔
319
    }
320
  }
1✔
321

322
  /**
323
   * @param purpose the purpose why Internet connection is required.
324
   * @param explicitOnlineCheck if {@code true}, perform an explicit {@link #isOffline()} check; if {@code false} use {@link #isOfflineMode()}.
325
   * @throws CliException if you are {@link #isOffline() offline}.
326
   */
327
  default void requireOnline(String purpose, boolean explicitOnlineCheck) {
328

329
    if (explicitOnlineCheck) {
2✔
330
      if (isOffline()) {
3✔
331
        throw CliOfflineException.ofPurpose(purpose);
3✔
332
      }
333
    } else {
334
      if (isOfflineMode()) {
3!
335
        throw CliOfflineException.ofPurpose(purpose);
3✔
336
      }
337
    }
338
  }
1✔
339

340
  /**
341
   * @return the {@link SystemInfo}.
342
   */
343
  SystemInfo getSystemInfo();
344

345
  /**
346
   * @return the {@link EnvironmentVariables} with full inheritance.
347
   */
348
  EnvironmentVariables getVariables();
349

350
  /**
351
   * @return the {@link FileAccess}.
352
   */
353
  FileAccess getFileAccess();
354

355
  /**
356
   * @return the {@link CommandletManager}.
357
   */
358
  CommandletManager getCommandletManager();
359

360
  /**
361
   * @return the default {@link ToolRepository}.
362
   */
363
  ToolRepository getDefaultToolRepository();
364

365
  /**
366
   * @return the {@link CustomToolRepository}.
367
   */
368
  CustomToolRepository getCustomToolRepository();
369

370
  /**
371
   * @return the {@link MvnRepository}.
372
   */
373
  MvnRepository getMvnRepository();
374

375
  /**
376
   * @return the {@link NpmRepository}.
377
   */
378
  NpmRepository getNpmRepository();
379

380
  /**
381
   * @return the {@link PipRepository}.
382
   */
383
  PipRepository getPipRepository();
384

385
  /**
386
   * @return the {@link UvRepository}.
387
   */
388
  UvRepository getUvRepository();
389

390
  /**
391
   * @return the {@link Path} to the IDE instance directory. You can have as many IDE instances on the same computer as independent tenants for different
392
   *     isolated projects.
393
   * @see com.devonfw.tools.ide.variable.IdeVariables#IDE_HOME
394
   */
395
  Path getIdeHome();
396

397
  /**
398
   * @return the name of the current project.
399
   * @see com.devonfw.tools.ide.variable.IdeVariables#PROJECT_NAME
400
   */
401
  String getProjectName();
402

403
  /**
404
   * @return the IDEasy version the {@link #getIdeHome() current project} was created with or migrated to.
405
   */
406
  VersionIdentifier getProjectVersion();
407

408
  /**
409
   * @param version the new value of {@link #getProjectVersion()}.
410
   */
411
  void setProjectVersion(VersionIdentifier version);
412

413
  /**
414
   * @return the {@link Path} to the IDE installation root directory. This is the top-level folder where the {@link #getIdeHome() IDE instances} are located as
415
   *     sub-folder. There is a reserved ".ide" folder where central IDE data is stored such as the {@link #getUrlsPath() download metadata} and the central
416
   *     software repository.
417
   * @see com.devonfw.tools.ide.variable.IdeVariables#IDE_ROOT
418
   */
419
  Path getIdeRoot();
420

421
  /**
422
   * @param ideRoot the new value of {@link #getIdeRoot() IDE_ROOT}. Typically detected automatically from the environment and working directory, but may need
423
   *     to be set explicitly (e.g. during the initial installation where the {@code IDE_ROOT} environment variable is not yet available but the installation
424
   *     target is already known).
425
   */
426
  void setIdeRoot(Path ideRoot);
427

428
  /**
429
   * @return the {@link Path} to the {@link #FOLDER_UNDERSCORE_IDE}.
430
   * @see #getIdeRoot()
431
   * @see #FOLDER_UNDERSCORE_IDE
432
   */
433
  Path getIdePath();
434

435
  /**
436
   * @return the {@link Path} to the {@link #FOLDER_INSTALLATION installation} folder of IDEasy. This is a link to the (latest) installed release of IDEasy. On
437
   *     upgrade a new release is installed and the link is switched to the new release.
438
   */
439
  default Path getIdeInstallationPath() {
440

441
    Path idePath = getIdePath();
3✔
442
    if (idePath == null) {
2!
443
      return null;
×
444
    }
445
    return idePath.resolve(FOLDER_INSTALLATION);
4✔
446
  }
447

448
  /**
449
   * @return the current working directory ("user.dir"). This is the directory where the user's shell was located when the IDE CLI was invoked.
450
   */
451
  Path getCwd();
452

453
  /**
454
   * @return the {@link Path} for the temporary directory to use. Will be different from the OS specific temporary directory (java.io.tmpDir).
455
   */
456
  Path getTempPath();
457

458
  /**
459
   * @return the {@link Path} for the temporary download directory to use.
460
   */
461
  Path getTempDownloadPath();
462

463
  /**
464
   * @return the {@link Path} to the download metadata (ide-urls). Here a git repository is cloned and updated (pulled) to always have the latest metadata to
465
   *     download tools.
466
   * @see com.devonfw.tools.ide.url.model.folder.UrlRepository
467
   */
468
  Path getUrlsPath();
469

470
  /**
471
   * @return the {@link UrlMetadata}. Will be lazily instantiated and thereby automatically be cloned or pulled (by default).
472
   */
473
  UrlMetadata getUrls();
474

475
  /**
476
   * @return the {@link Path} to the download cache. All downloads will be placed here using a unique naming pattern that allows to reuse these artifacts. So if
477
   *     the same artifact is requested again it will be taken from the cache to avoid downloading it again.
478
   */
479
  Path getDownloadPath();
480

481
  /**
482
   * @return the {@link Path} to the software folder inside {@link #getIdeHome() IDE_HOME}. All tools for that IDE instance will be linked here from the
483
   *     {@link #getSoftwareRepositoryPath() software repository} as sub-folder named after the according tool.
484
   */
485
  Path getSoftwarePath();
486

487
  /**
488
   * @return the {@link Path} to the extra folder inside software folder inside {@link #getIdeHome() IDE_HOME}. All tools for that IDE instance will be linked
489
   *     here from the {@link #getSoftwareRepositoryPath() software repository} as sub-folder named after the according tool.
490
   */
491
  Path getSoftwareExtraPath();
492

493
  /**
494
   * @return the {@link Path} to the global software repository. This is the central directory where the tools are extracted physically on the local disc. Those
495
   *     are shared among all IDE instances (see {@link #getIdeHome() IDE_HOME}) via symbolic links (see {@link #getSoftwarePath()}). Therefore this repository
496
   *     follows the sub-folder structure {@code «repository»/«tool»/«edition»/«version»/}. So multiple versions of the same tool exist here as different
497
   *     folders. Further, such software may not be modified so e.g. installation of plugins and other kind of changes to such tool need to happen strictly out
498
   *     of the scope of this folders.
499
   */
500
  Path getSoftwareRepositoryPath();
501

502
  /**
503
   * @return the {@link Path} to the {@link #FOLDER_PLUGINS plugins folder} inside {@link #getIdeHome() IDE_HOME}. All plugins of the IDE instance will be
504
   *     stored here. For each tool that supports plugins a sub-folder with the tool name will be created where the plugins for that tool get installed.
505
   */
506
  Path getPluginsPath();
507

508
  /**
509
   * @return the {@link Path} to the central tool repository. All tools will be installed in this location using the directory naming schema of
510
   *     {@code «repository»/«tool»/«edition»/«version»/}. Actual {@link #getIdeHome() IDE instances} will only contain symbolic links to the physical tool
511
   *     installations in this repository. This allows to share and reuse tool installations across multiple {@link #getIdeHome() IDE instances}. The variable
512
   *     {@code «repository»} is typically {@code default} for the tools from our standard {@link #getUrlsPath() ide-urls download metadata} but this will
513
   *     differ for custom tools from a private repository.
514
   */
515
  Path getToolRepositoryPath();
516

517
  /**
518
   * @return the {@link Path} to the users home directory. Typically initialized via the {@link System#getProperty(String) system property} "user.home".
519
   * @see com.devonfw.tools.ide.variable.IdeVariables#HOME
520
   */
521
  Path getUserHome();
522

523
  /**
524
   * @return the {@link Path} to the ".ide" subfolder in the {@link #getUserHome() users home directory}.
525
   */
526
  Path getUserHomeIde();
527

528
  /**
529
   * @return the {@link Path} to the {@link #FOLDER_SETTINGS settings} folder with the cloned git repository containing the project configuration.
530
   */
531
  Path getSettingsPath();
532

533
  /**
534
   * @return the {@link Path} to the {@link #FOLDER_REPOSITORIES repositories} folder with legacy fallback if not present or {@code null} if not found.
535
   */
536
  default Path getRepositoriesPath() {
537

538
    Path settingsPath = getSettingsPath();
3✔
539
    if (settingsPath == null) {
2!
540
      return null;
×
541
    }
542
    Path repositoriesPath = settingsPath.resolve(IdeContext.FOLDER_REPOSITORIES);
4✔
543
    if (Files.isDirectory(repositoriesPath)) {
5✔
544
      return repositoriesPath;
2✔
545
    }
546
    Path legacyRepositoriesPath = settingsPath.resolve(IdeContext.FOLDER_LEGACY_REPOSITORIES);
4✔
547
    if (Files.isDirectory(legacyRepositoriesPath)) {
5!
548
      return legacyRepositoriesPath;
×
549
    }
550
    return null;
2✔
551
  }
552

553
  /**
554
   * @return the {@link Path} to the {@code settings} folder with the cloned git repository containing the project configuration only if the settings repository
555
   *     is in fact a git repository.
556
   */
557
  Path getSettingsGitRepository();
558

559
  /**
560
   * @return {@code true} if the settings repository is a symlink or a junction to a code-repository.
561
   */
562
  boolean isSettingsCodeRepository();
563

564
  /**
565
   * @return the {@link Path} to the file containing the last tracked commit Id of the settings repository.
566
   */
567
  Path getSettingsCommitIdPath();
568

569
  /**
570
   * @return the {@link Path} to the templates folder inside the {@link #getSettingsPath() settings}. The relative directory structure in this templates folder
571
   *     is to be applied to {@link #getIdeHome() IDE_HOME} when the project is set up.
572
   */
573
  default Path getSettingsTemplatePath() {
574
    Path settingsFolder = getSettingsPath();
3✔
575
    Path templatesFolder = settingsFolder.resolve(IdeContext.FOLDER_TEMPLATES);
4✔
576
    if (!Files.isDirectory(templatesFolder)) {
5✔
577
      Path templatesFolderLegacy = settingsFolder.resolve(IdeContext.FOLDER_LEGACY_TEMPLATES);
4✔
578
      if (Files.isDirectory(templatesFolderLegacy)) {
5!
579
        templatesFolder = templatesFolderLegacy;
×
580
      } else {
581
        AbstractIdeContext.LOG.warn("No templates found in settings git repo neither in {} nor in {} - configuration broken", templatesFolder,
5✔
582
            templatesFolderLegacy);
583
        return null;
2✔
584
      }
585
    }
586
    return templatesFolder;
2✔
587
  }
588

589
  /**
590
   * @return the {@link Path} to the {@code conf} folder with instance specific tool configurations and the
591
   *     {@link EnvironmentVariablesType#CONF user specific project configuration}.
592
   */
593
  Path getConfPath();
594

595
  /**
596
   * @return the {@link Path} to the workspaces base folder containing the individual {@link #getWorkspacePath(String) workspaces}.
597
   * @see #getWorkspacePath(String)
598
   */
599
  Path getWorkspacesBasePath();
600

601
  /**
602
   * @return the {@link Path} to the workspace.
603
   * @see #getWorkspaceName()
604
   */
605
  Path getWorkspacePath();
606

607
  /**
608
   * @param workspace the specific workspace name.
609
   * @return the {@link Path} to the specified workspace.
610
   */
611
  Path getWorkspacePath(String workspace);
612

613
  /**
614
   * @return the name of the workspace. Defaults to {@link #WORKSPACE_MAIN}.
615
   */
616
  String getWorkspaceName();
617

618
  /**
619
   * @return the value of the system {@link IdeVariables#PATH PATH} variable. It is automatically extended according to the tools available in
620
   *     {@link #getSoftwarePath() software path} unless {@link #getIdeHome() IDE_HOME} was not found.
621
   */
622
  SystemPath getPath();
623

624
  /**
625
   * @return a new {@link ProcessContext} to {@link ProcessContext#run() run} external commands.
626
   */
627
  ProcessContext newProcess();
628

629
  /**
630
   * @param title the {@link IdeProgressBar#getTitle() title}.
631
   * @param size the {@link IdeProgressBar#getMaxSize() expected maximum size}.
632
   * @param unitName the {@link IdeProgressBar#getUnitName() unit name}.
633
   * @param unitSize the {@link IdeProgressBar#getUnitSize() unit size}.
634
   * @return the new {@link IdeProgressBar} to use.
635
   */
636
  IdeProgressBar newProgressBar(String title, long size, String unitName, long unitSize);
637

638
  /**
639
   * @param title the {@link IdeProgressBar#getTitle() title}.
640
   * @param size the {@link IdeProgressBar#getMaxSize() expected maximum size} in bytes.
641
   * @return the new {@link IdeProgressBar} to use.
642
   */
643
  default IdeProgressBar newProgressBarInMib(String title, long size) {
644

645
    if ((size > 0) && (size < 1024)) {
8✔
646
      return new IdeProgressBarNone(title, size, IdeProgressBar.UNIT_NAME_MB, IdeProgressBar.UNIT_SIZE_MB);
8✔
647
    }
648
    return newProgressBar(title, size, IdeProgressBar.UNIT_NAME_MB, IdeProgressBar.UNIT_SIZE_MB);
7✔
649
  }
650

651
  /**
652
   * @param size the {@link IdeProgressBar#getMaxSize() expected maximum size} in bytes.
653
   * @return the new {@link IdeProgressBar} for copy.
654
   */
655
  default IdeProgressBar newProgressBarForDownload(long size) {
656

657
    return newProgressBarInMib(IdeProgressBar.TITLE_DOWNLOADING, size);
5✔
658
  }
659

660
  /**
661
   * @param size the {@link IdeProgressBar#getMaxSize() expected maximum size} in bytes.
662
   * @return the new {@link IdeProgressBar} for extracting.
663
   */
664
  default IdeProgressBar newProgressbarForExtracting(long size) {
665

666
    return newProgressBarInMib(IdeProgressBar.TITLE_EXTRACTING, size);
5✔
667
  }
668

669
  /**
670
   * @param size the {@link IdeProgressBar#getMaxSize() expected maximum size} in bytes.
671
   * @return the new {@link IdeProgressBar} for copy.
672
   */
673
  default IdeProgressBar newProgressbarForCopying(long size) {
674

675
    return newProgressBarInMib(IdeProgressBar.TITLE_COPYING, size);
5✔
676
  }
677

678
  /**
679
   * @param size the {@link IdeProgressBar#getMaxSize() expected maximum} plugin count.
680
   * @return the new {@link IdeProgressBar} to use.
681
   */
682
  default IdeProgressBar newProgressBarForPlugins(long size) {
683
    return newProgressBar(IdeProgressBar.TITLE_INSTALL_PLUGIN, size, IdeProgressBar.UNIT_NAME_PLUGIN, IdeProgressBar.UNIT_SIZE_PLUGIN);
×
684
  }
685

686
  /**
687
   * @return the {@link DirectoryMerger} used to configure and merge the workspace for an {@link com.devonfw.tools.ide.tool.ide.IdeToolCommandlet IDE}.
688
   */
689
  DirectoryMerger getWorkspaceMerger();
690

691
  /**
692
   * @return the {@link Path} to the working directory from where the command is executed.
693
   */
694
  Path getDefaultExecutionDirectory();
695

696
  /**
697
   * @return the {@link IdeSystem} instance wrapping {@link System}.
698
   */
699
  IdeSystem getSystem();
700

701
  /**
702
   * @return the {@link GitContext} used to run several git commands.
703
   */
704
  GitContext getGitContext();
705

706
  /**
707
   * @return the String value for the variable MAVEN_ARGS, or null if called outside an IDEasy installation.
708
   */
709
  default String getMavenArgs() {
710

711
    if (getIdeHome() == null) {
3✔
712
      return null;
2✔
713
    }
714
    Mvn mvn = getCommandletManager().getCommandlet(Mvn.class);
6✔
715
    return mvn.getMavenArgs();
3✔
716
  }
717

718
  /**
719
   * @return the path for the variable GRADLE_USER_HOME, or null if called outside an IDEasy installation.
720
   */
721
  default Path getGradleUserHome() {
722

723
    if (getIdeHome() == null) {
3✔
724
      return null;
2✔
725
    }
726
    Gradle gradle = getCommandletManager().getCommandlet(Gradle.class);
6✔
727
    return gradle.getOrCreateGradleConfFolder();
3✔
728
  }
729

730
  /**
731
   * @return the {@link Path} pointing to the maven configuration directory (where "settings.xml" or "settings-security.xml" are located).
732
   */
733
  default Path getMavenConfigurationFolder() {
734

735
    if (getIdeHome() == null) {
3✔
736
      // fallback to USER_HOME/.m2 folder if called outside an IDEasy project
737
      return getUserHome().resolve(Mvn.MVN_CONFIG_LEGACY_FOLDER);
5✔
738
    }
739
    Mvn mvn = getCommandletManager().getCommandlet(Mvn.class);
6✔
740
    return mvn.getMavenConfigurationFolder();
3✔
741
  }
742

743
  /**
744
   * Updates the current working directory (CWD) and configures the environment paths according to the specified parameters. This method is central to changing
745
   * the IDE's notion of where it operates, affecting where configurations, workspaces, settings, and other resources are located or loaded from.
746
   *
747
   * @return the current {@link Step} of processing.
748
   */
749
  Step getCurrentStep();
750

751
  /**
752
   * @param name the {@link Step#getName() name} of the new {@link Step}.
753
   * @return the new {@link Step} that has been created and started.
754
   */
755
  default Step newStep(String name) {
756

757
    return newStep(name, Step.NO_PARAMS);
5✔
758
  }
759

760
  /**
761
   * @param name the {@link Step#getName() name} of the new {@link Step}.
762
   * @param parameters the {@link Step#getParameter(int) parameters} of the {@link Step}.
763
   * @return the new {@link Step} that has been created and started.
764
   */
765
  default Step newStep(String name, Object... parameters) {
766

767
    return newStep(false, name, parameters);
6✔
768
  }
769

770
  /**
771
   * @param silent the {@link Step#isSilent() silent flag}.
772
   * @param name the {@link Step#getName() name} of the new {@link Step}.
773
   * @param parameters the {@link Step#getParameter(int) parameters} of the {@link Step}.
774
   * @return the new {@link Step} that has been created and started.
775
   */
776
  Step newStep(boolean silent, String name, Object... parameters);
777

778
  /**
779
   * @param lambda the {@link Runnable} to {@link Runnable#run() run} while the {@link com.devonfw.tools.ide.log.IdeLogger logging} is entirely disabled.
780
   *     After this the logging will be enabled again. Collected log messages will then be logged at the end.
781
   */
782
  default void runWithoutLogging(Runnable lambda) {
783

784
    runWithoutLogging(lambda, IdeLogLevel.TRACE);
×
785
  }
×
786

787
  /**
788
   * @param lambda the {@link Runnable} to {@link Runnable#run() run} while the {@link com.devonfw.tools.ide.log.IdeLogger logging} is entirely disabled.
789
   *     After this the logging will be enabled again. Collected log messages will then be logged at the end.
790
   * @param threshold the {@link IdeLogLevel} to use as threshold for filtering logs while logging is disabled and log messages are collected. Use
791
   *     {@link IdeLogLevel#TRACE} to collect all logs and ensure nothing gets lost (will still not log anything that is generally not active in regular
792
   *     logging) and e.g. use {@link IdeLogLevel#ERROR} to discard all logs except errors.
793
   */
794
  void runWithoutLogging(Runnable lambda, IdeLogLevel threshold);
795

796
  /**
797
   * Updates the current working directory (CWD) and configures the environment paths according to the specified parameters. This method is central to changing
798
   * the IDE's notion of where it operates, affecting where configurations, workspaces, settings, and other resources are located or loaded from.
799
   *
800
   * @param ideHome The path to the IDE home directory.
801
   */
802
  default void setIdeHome(Path ideHome) {
803

804
    setCwd(ideHome, WORKSPACE_MAIN, ideHome);
5✔
805
  }
1✔
806

807
  /**
808
   * Updates the current working directory (CWD) and configures the environment paths according to the specified parameters. This method is central to changing
809
   * the IDE's notion of where it operates, affecting where configurations, workspaces, settings, and other resources are located or loaded from.
810
   *
811
   * @param userDir The path to set as the current working directory.
812
   * @param workspace The name of the workspace within the IDE's environment.
813
   * @param ideHome The path to the IDE home directory.
814
   */
815
  void setCwd(Path userDir, String workspace, Path ideHome);
816

817
  /**
818
   * Finds the path to the Bash executable.
819
   *
820
   * @return the {@link Path} to the Bash executable, or {@code null} if Bash is not found.
821
   */
822
  Path findBash();
823

824
  /**
825
   * Finds the path to the Bash executable.
826
   *
827
   * @return the {@link Path} to the Bash executable. Throws a {@link CliException} if no bash was found.
828
   */
829
  default Path findBashRequired() {
830
    Path bash = findBash();
3✔
831
    if (bash == null) {
2!
832
      String message = "Bash " + IS_NOT_INSTALLED_BUT_REQUIRED;
×
833
      if (getSystemInfo().isWindows()) {
×
834
        message += " " + PLEASE_DOWNLOAD_AND_INSTALL_GIT + ":\n " + WINDOWS_GIT_DOWNLOAD_URL;
×
835
        throw new CliException(message);
×
836
      }
837
      bash = Path.of("bash");
×
838
    }
839

840
    return bash;
2✔
841
  }
842

843
  /**
844
   * @return the {@link WindowsPathSyntax} used for {@link Path} conversion or {@code null} for no such conversion (typically if not on Windows).
845
   */
846
  WindowsPathSyntax getPathSyntax();
847

848
  /**
849
   * logs the status of {@link #getIdeHome() IDE_HOME} and {@link #getIdeRoot() IDE_ROOT}.
850
   */
851
  void logIdeHomeAndRootStatus();
852

853
  /**
854
   * @param version the {@link VersionIdentifier} to write.
855
   * @param installationPath the {@link Path directory} where to write the version to a {@link #FILE_SOFTWARE_VERSION version file}.
856
   */
857
  void writeVersionFile(VersionIdentifier version, Path installationPath);
858

859
  /**
860
   * Verifies that current {@link IdeVersion} satisfies {@link IdeVariables#IDE_MIN_VERSION}.
861
   *
862
   * @param throwException whether to throw a {@link CliException} or just log a warning.
863
   */
864
  void verifyIdeMinVersion(boolean throwException);
865

866
  /**
867
   * @return the path for the variable COREPACK_HOME, or null if called outside an IDEasy installation.
868
   */
869
  default Path getCorePackHome() {
870
    if (getIdeHome() == null) {
×
871
      return null;
×
872
    }
873
    Corepack corepack = getCommandletManager().getCommandlet(Corepack.class);
×
874
    return corepack.getOrCreateCorepackHomeFolder();
×
875
  }
876

877
  /**
878
   * @return the path for the variable NPM_CONFIG_USERCONFIG, or null if called outside an IDEasy installation.
879
   */
880
  default Path getNpmConfigUserConfig() {
881
    if (getIdeHome() == null) {
3✔
882
      return null;
2✔
883
    }
884
    Npm npm = getCommandletManager().getCommandlet(Npm.class);
6✔
885
    return npm.getOrCreateNpmConfigUserConfig();
3✔
886
  }
887

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

© 2026 Coveralls, Inc