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

devonfw / IDEasy / 26101908636

19 May 2026 01:55PM UTC coverage: 70.982% (+0.003%) from 70.979%
26101908636

Pull #1859

github

web-flow
Merge cf4a7f717 into b4eeee25f
Pull Request #1859: #1392: Smart completions

4472 of 6964 branches covered (64.22%)

Branch coverage included in aggregate %.

11521 of 15567 relevant lines covered (74.01%)

3.14 hits per line

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

77.78
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.url.model.UrlMetadata;
35
import com.devonfw.tools.ide.variable.IdeVariables;
36
import com.devonfw.tools.ide.version.IdeVersion;
37
import com.devonfw.tools.ide.version.VersionIdentifier;
38

39
/**
40
 * Interface for interaction with the user allowing to input and output information.
41
 */
42
public interface IdeContext extends IdeStartContext {
43

44
  /**
45
   * The default settings URL.
46
   *
47
   * @see com.devonfw.tools.ide.commandlet.AbstractUpdateCommandlet
48
   */
49
  String DEFAULT_SETTINGS_REPO_URL = "https://github.com/devonfw/ide-settings.git";
50

51
  /** The name of the workspaces folder. */
52
  String FOLDER_WORKSPACES = "workspaces";
53

54
  /** The name of the {@link #getSettingsPath() settings} folder. */
55
  String FOLDER_SETTINGS = "settings";
56

57
  /** The name of the {@link #getSoftwarePath() software} folder. */
58
  String FOLDER_SOFTWARE = "software";
59

60
  /** The name of the {@link #getUrlsPath() urls} folder. */
61
  String FOLDER_URLS = "urls";
62

63
  /** The name of the conf folder for project specific user configurations. */
64
  String FOLDER_CONF = "conf";
65

66
  /**
67
   * 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,
68
   * maven filtering, .gitignore and to distinguish from {@link #FOLDER_DOT_IDE}.
69
   *
70
   * @see #getIdePath()
71
   */
72
  String FOLDER_UNDERSCORE_IDE = "_ide";
73

74
  /**
75
   * The name of the folder inside {@link #FOLDER_UNDERSCORE_IDE} with the current IDEasy installation.
76
   *
77
   * @see #getIdeInstallationPath()
78
   */
79
  String FOLDER_INSTALLATION = "installation";
80

81
  /**
82
   * The name of the hidden folder for IDE configuration in the users home directory or status information in the IDE_HOME directory.
83
   *
84
   * @see #getUserHomeIde()
85
   */
86
  String FOLDER_DOT_IDE = ".ide";
87

88
  /** The name of the updates folder for temporary data and backup. */
89
  String FOLDER_UPDATES = "updates";
90

91
  /** The name of the volume folder for mounting archives like *.dmg. */
92
  String FOLDER_VOLUME = "volume";
93

94
  /** The name of the backups folder for backup. */
95
  String FOLDER_BACKUPS = "backups";
96

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

100
  /** The name of the downloads folder. */
101
  String FOLDER_DOWNLOADS = "Downloads";
102

103
  /** The name of the bin folder where executable files are found by default. */
104
  String FOLDER_BIN = "bin";
105

106
  /** The name of the repositories folder where properties files are stores for each repository */
107
  String FOLDER_REPOSITORIES = "repositories";
108

109
  /** The name of the repositories folder where properties files are stores for each repository */
110
  String FOLDER_LEGACY_REPOSITORIES = "projects";
111

112
  /** The name of the Contents folder inside a MacOS app. */
113
  String FOLDER_CONTENTS = "Contents";
114

115
  /** The name of the Resources folder inside a MacOS app. */
116
  String FOLDER_RESOURCES = "Resources";
117

118
  /** The name of the app folder inside a MacOS app. */
119
  String FOLDER_APP = "app";
120

121
  /** The name of the extra folder inside the software folder */
122
  String FOLDER_EXTRA = "extra";
123

124
  /**
125
   * The name of the {@link #getPluginsPath() plugins folder} and also the plugins folder inside the IDE folders of {@link #getSettingsPath() settings} (e.g.
126
   * settings/eclipse/plugins).
127
   */
128
  String FOLDER_PLUGINS = "plugins";
129

130
  /**
131
   * The name of the workspace folder inside the IDE specific {@link #FOLDER_SETTINGS settings} containing the configuration templates in #FOLDER_SETUP
132
   * #FOLDER_UPDATE.
133
   */
134
  String FOLDER_WORKSPACE = "workspace";
135

136
  /**
137
   * The name of the setup folder inside the {@link #FOLDER_WORKSPACE workspace} folder containing the templates for the configuration templates for the initial
138
   * setup of a workspace. This is closely related with the {@link #FOLDER_UPDATE update} folder.
139
   */
140
  String FOLDER_SETUP = "setup";
141

142
  /**
143
   * The name of the update folder inside the {@link #FOLDER_WORKSPACE workspace} folder containing the templates for the configuration templates for the update
144
   * 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
145
   * 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
146
   * for indentation and other code-formatting settings. If all developers in a project team use the same formatter settings, this will actively prevent
147
   * 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
148
   * 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
149
   * 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
150
   * user as needed.
151
   */
152
  String FOLDER_UPDATE = "update";
153

154
  /**
155
   * The name of the folder inside {@link #FOLDER_UNDERSCORE_IDE _ide} folder containing internal resources and scripts of IDEasy.
156
   */
157
  String FOLDER_INTERNAL = "internal";
158

159
  /** The file where the installed software version is written to as plain text. */
160
  String FILE_SOFTWARE_VERSION = ".ide.software.version";
161

162
  /** The file where the installed software version is written to as plain text. */
163
  String FILE_LEGACY_SOFTWARE_VERSION = ".devon.software.version";
164

165
  /** The file for the license agreement. */
166
  String FILE_LICENSE_AGREEMENT = ".license.agreement";
167

168
  /** The file extension for a {@link java.util.Properties} file. */
169
  String EXT_PROPERTIES = ".properties";
170

171
  /** The default for {@link #getWorkspaceName()}. */
172
  String WORKSPACE_MAIN = "main";
173

174
  /** The folder with the configuration template files from the settings. */
175
  String FOLDER_TEMPLATES = "templates";
176

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

180
  /** The default folder name for {@link #getIdeRoot() IDE_ROOT}. */
181
  String FOLDER_PROJECTS = "projects";
182

183
  /**
184
   * file containing the current local commit hash of the settings repository.
185
   */
186
  String SETTINGS_COMMIT_ID = ".commit.id";
187

188
  /** The IDEasy ASCII logo. */
189
  String LOGO = """
4✔
190
      __       ___ ___  ___
191
      ╲ ╲     |_ _|   ╲| __|__ _ ____ _
192
       > >     | || |) | _|/ _` (_-< || |
193
      /_/ ___ |___|___/|___╲__,_/__/╲_, |
194
         |___|                       |__/
195
      """.replace('╲', '\\');
2✔
196

197
  /**
198
   * The keyword for project name convention.
199
   */
200
  String SETTINGS_REPOSITORY_KEYWORD = "settings";
201
  String IS_NOT_INSTALLED_BUT_REQUIRED = "is not installed on your computer but required by IDEasy.";
202
  String WINDOWS_GIT_DOWNLOAD_URL = "https://git-scm.com/download/";
203
  String PLEASE_DOWNLOAD_AND_INSTALL_GIT = "Please download and install git";
204

205
  /**
206
   * @return the {@link NetworkStatus} for online check and related operations.
207
   */
208
  NetworkStatus getNetworkStatus();
209

210
  /**
211
   * @return {@code true} if {@link #isOfflineMode() offline mode} is active or we are NOT {@link #isOnline() online}, {@code false} otherwise.
212
   * @deprecated use {@link #getNetworkStatus()}
213
   */
214
  default boolean isOffline() {
215

216
    return getNetworkStatus().isOffline();
4✔
217
  }
218

219
  /**
220
   * @return {@code true} if we are currently online (Internet access is available), {@code false} otherwise.
221
   * @deprecated use {@link #getNetworkStatus()}
222
   */
223
  default boolean isOnline() {
224

225
    return getNetworkStatus().isOnline();
×
226
  }
227

228
  /**
229
   * Print the IDEasy {@link #LOGO logo}.
230
   */
231
  default void printLogo() {
232

233
    AbstractIdeContext.LOG.info(LOGO);
3✔
234
  }
1✔
235

236
  /**
237
   * Asks the user for a single string input.
238
   *
239
   * @param message The information message to display.
240
   * @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.
241
   * @return The string input from the user, or the default value if no input is provided.
242
   */
243
  String askForInput(String message, String defaultValue);
244

245
  /**
246
   * Asks the user for a single string input.
247
   *
248
   * @param message The information message to display.
249
   * @return The string input from the user.
250
   */
251
  default String askForInput(String message) {
252
    return askForInput(message, null);
5✔
253
  }
254

255
  /**
256
   * @param question the question to ask.
257
   * @param args arguments for filling the templates
258
   * @return {@code true} if the user answered with "yes", {@code false} otherwise ("no").
259
   */
260
  default boolean question(String question, Object... args) {
261

262
    String yes = "yes";
2✔
263
    String option = question(new String[] { yes, "no" }, question, args);
16✔
264
    if (yes.equals(option)) {
4!
265
      return true;
2✔
266
    }
267
    return false;
×
268
  }
269

270
  /**
271
   * @param <O> type of the option. E.g. {@link String}.
272
   * @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.
273
   * @param question the question to ask.
274
   * @return the option selected by the user as answer.
275
   */
276
  @SuppressWarnings("unchecked")
277
  <O> O question(O[] options, String question, Object... args);
278

279
  /**
280
   * 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
281
   * exception is thrown to abort further processing.
282
   *
283
   * @param questionTemplate the yes/no question to {@link #question(String, Object...) ask}.
284
   * @param args the arguments to fill the placeholders in the question template.
285
   * @throws CliAbortException if the user answered with "no" and further processing shall be aborted.
286
   */
287
  default void askToContinue(String questionTemplate, Object... args) {
288
    boolean yesContinue = question(questionTemplate, args);
5✔
289
    if (!yesContinue) {
2!
290
      throw new CliAbortException();
×
291
    }
292
  }
1✔
293

294
  /**
295
   * @param purpose the purpose why Internet connection is required.
296
   * @param explicitOnlineCheck if {@code true}, perform an explicit {@link #isOffline()} check; if {@code false} use {@link #isOfflineMode()}.
297
   * @throws CliException if you are {@link #isOffline() offline}.
298
   */
299
  default void requireOnline(String purpose, boolean explicitOnlineCheck) {
300

301
    if (explicitOnlineCheck) {
2✔
302
      if (isOffline()) {
3✔
303
        throw CliOfflineException.ofPurpose(purpose);
3✔
304
      }
305
    } else {
306
      if (isOfflineMode()) {
3!
307
        throw CliOfflineException.ofPurpose(purpose);
3✔
308
      }
309
    }
310
  }
1✔
311

312
  /**
313
   * @return the {@link SystemInfo}.
314
   */
315
  SystemInfo getSystemInfo();
316

317
  /**
318
   * @return the {@link EnvironmentVariables} with full inheritance.
319
   */
320
  EnvironmentVariables getVariables();
321

322
  /**
323
   * @return the {@link FileAccess}.
324
   */
325
  FileAccess getFileAccess();
326

327
  /**
328
   * @return the {@link CommandletManager}.
329
   */
330
  CommandletManager getCommandletManager();
331

332
  /**
333
   * @return the default {@link ToolRepository}.
334
   */
335
  ToolRepository getDefaultToolRepository();
336

337
  /**
338
   * @return the {@link CustomToolRepository}.
339
   */
340
  CustomToolRepository getCustomToolRepository();
341

342
  /**
343
   * @return the {@link MvnRepository}.
344
   */
345
  MvnRepository getMvnRepository();
346

347
  /**
348
   * @return the {@link NpmRepository}.
349
   */
350
  NpmRepository getNpmRepository();
351

352
  /**
353
   * @return the {@link PipRepository}.
354
   */
355
  PipRepository getPipRepository();
356

357
  /**
358
   * @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
359
   *     isolated projects.
360
   * @see com.devonfw.tools.ide.variable.IdeVariables#IDE_HOME
361
   */
362
  Path getIdeHome();
363

364
  /**
365
   * @return the name of the current project.
366
   * @see com.devonfw.tools.ide.variable.IdeVariables#PROJECT_NAME
367
   */
368
  String getProjectName();
369

370
  /**
371
   * @return the IDEasy version the {@link #getIdeHome() current project} was created with or migrated to.
372
   */
373
  VersionIdentifier getProjectVersion();
374

375
  boolean isTest();
376

377
  /**
378
   * @param version the new value of {@link #getProjectVersion()}.
379
   */
380
  void setProjectVersion(VersionIdentifier version);
381

382
  /**
383
   * @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
384
   *     sub-folder. There is a reserved ".ide" folder where central IDE data is stored such as the {@link #getUrlsPath() download metadata} and the central
385
   *     software repository.
386
   * @see com.devonfw.tools.ide.variable.IdeVariables#IDE_ROOT
387
   */
388
  Path getIdeRoot();
389

390
  /**
391
   * @return the {@link Path} to the {@link #FOLDER_UNDERSCORE_IDE}.
392
   * @see #getIdeRoot()
393
   * @see #FOLDER_UNDERSCORE_IDE
394
   */
395
  Path getIdePath();
396

397
  /**
398
   * @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
399
   *     upgrade a new release is installed and the link is switched to the new release.
400
   */
401
  default Path getIdeInstallationPath() {
402

403
    Path idePath = getIdePath();
3✔
404
    if (idePath == null) {
2!
405
      return null;
×
406
    }
407
    return idePath.resolve(FOLDER_INSTALLATION);
4✔
408
  }
409

410
  /**
411
   * @return the current working directory ("user.dir"). This is the directory where the user's shell was located when the IDE CLI was invoked.
412
   */
413
  Path getCwd();
414

415
  /**
416
   * @return the {@link Path} for the temporary directory to use. Will be different from the OS specific temporary directory (java.io.tmpDir).
417
   */
418
  Path getTempPath();
419

420
  /**
421
   * @return the {@link Path} for the temporary download directory to use.
422
   */
423
  Path getTempDownloadPath();
424

425
  /**
426
   * @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
427
   *     download tools.
428
   * @see com.devonfw.tools.ide.url.model.folder.UrlRepository
429
   */
430
  Path getUrlsPath();
431

432
  /**
433
   * @return the {@link UrlMetadata}. Will be lazily instantiated and thereby automatically be cloned or pulled (by default).
434
   */
435
  UrlMetadata getUrls();
436

437
  /**
438
   * @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
439
   *     the same artifact is requested again it will be taken from the cache to avoid downloading it again.
440
   */
441
  Path getDownloadPath();
442

443
  /**
444
   * @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
445
   *     {@link #getSoftwareRepositoryPath() software repository} as sub-folder named after the according tool.
446
   */
447
  Path getSoftwarePath();
448

449
  /**
450
   * @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
451
   *     here from the {@link #getSoftwareRepositoryPath() software repository} as sub-folder named after the according tool.
452
   */
453
  Path getSoftwareExtraPath();
454

455
  /**
456
   * @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
457
   *     are shared among all IDE instances (see {@link #getIdeHome() IDE_HOME}) via symbolic links (see {@link #getSoftwarePath()}). Therefore this repository
458
   *     follows the sub-folder structure {@code «repository»/«tool»/«edition»/«version»/}. So multiple versions of the same tool exist here as different
459
   *     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
460
   *     of the scope of this folders.
461
   */
462
  Path getSoftwareRepositoryPath();
463

464
  /**
465
   * @return the {@link Path} to the {@link #FOLDER_PLUGINS plugins folder} inside {@link #getIdeHome() IDE_HOME}. All plugins of the IDE instance will be
466
   *     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.
467
   */
468
  Path getPluginsPath();
469

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

479
  /**
480
   * @return the {@link Path} to the users home directory. Typically initialized via the {@link System#getProperty(String) system property} "user.home".
481
   * @see com.devonfw.tools.ide.variable.IdeVariables#HOME
482
   */
483
  Path getUserHome();
484

485
  /**
486
   * @return the {@link Path} to the ".ide" subfolder in the {@link #getUserHome() users home directory}.
487
   */
488
  Path getUserHomeIde();
489

490
  /**
491
   * @return the {@link Path} to the {@link #FOLDER_SETTINGS settings} folder with the cloned git repository containing the project configuration.
492
   */
493
  Path getSettingsPath();
494

495
  /**
496
   * @return the {@link Path} to the {@link #FOLDER_REPOSITORIES repositories} folder with legacy fallback if not present or {@code null} if not found.
497
   */
498
  default Path getRepositoriesPath() {
499

500
    Path settingsPath = getSettingsPath();
3✔
501
    if (settingsPath == null) {
2!
502
      return null;
×
503
    }
504
    Path repositoriesPath = settingsPath.resolve(IdeContext.FOLDER_REPOSITORIES);
4✔
505
    if (Files.isDirectory(repositoriesPath)) {
5✔
506
      return repositoriesPath;
2✔
507
    }
508
    Path legacyRepositoriesPath = settingsPath.resolve(IdeContext.FOLDER_LEGACY_REPOSITORIES);
4✔
509
    if (Files.isDirectory(legacyRepositoriesPath)) {
5!
510
      return legacyRepositoriesPath;
×
511
    }
512
    return null;
2✔
513
  }
514

515
  /**
516
   * @return the {@link Path} to the {@code settings} folder with the cloned git repository containing the project configuration only if the settings repository
517
   *     is in fact a git repository.
518
   */
519
  Path getSettingsGitRepository();
520

521
  /**
522
   * @return {@code true} if the settings repository is a symlink or a junction.
523
   */
524
  boolean isSettingsRepositorySymlinkOrJunction();
525

526
  /**
527
   * @return the {@link Path} to the file containing the last tracked commit Id of the settings repository.
528
   */
529
  Path getSettingsCommitIdPath();
530

531
  /**
532
   * @return the {@link Path} to the templates folder inside the {@link #getSettingsPath() settings}. The relative directory structure in this templates folder
533
   *     is to be applied to {@link #getIdeHome() IDE_HOME} when the project is set up.
534
   */
535
  default Path getSettingsTemplatePath() {
536
    Path settingsFolder = getSettingsPath();
3✔
537
    Path templatesFolder = settingsFolder.resolve(IdeContext.FOLDER_TEMPLATES);
4✔
538
    if (!Files.isDirectory(templatesFolder)) {
5✔
539
      Path templatesFolderLegacy = settingsFolder.resolve(IdeContext.FOLDER_LEGACY_TEMPLATES);
4✔
540
      if (Files.isDirectory(templatesFolderLegacy)) {
5!
541
        templatesFolder = templatesFolderLegacy;
×
542
      } else {
543
        AbstractIdeContext.LOG.warn("No templates found in settings git repo neither in {} nor in {} - configuration broken", templatesFolder,
5✔
544
            templatesFolderLegacy);
545
        return null;
2✔
546
      }
547
    }
548
    return templatesFolder;
2✔
549
  }
550

551
  /**
552
   * @return the {@link Path} to the {@code conf} folder with instance specific tool configurations and the
553
   *     {@link EnvironmentVariablesType#CONF user specific project configuration}.
554
   */
555
  Path getConfPath();
556

557
  /**
558
   * @return the {@link Path} to the workspaces base folder containing the individual {@link #getWorkspacePath(String) workspaces}.
559
   * @see #getWorkspacePath(String)
560
   */
561
  Path getWorkspacesBasePath();
562

563
  /**
564
   * @return the {@link Path} to the workspace.
565
   * @see #getWorkspaceName()
566
   */
567
  Path getWorkspacePath();
568

569
  /**
570
   * @param workspace the specific workspace name.
571
   * @return the {@link Path} to the specified workspace.
572
   */
573
  Path getWorkspacePath(String workspace);
574

575
  /**
576
   * @return the name of the workspace. Defaults to {@link #WORKSPACE_MAIN}.
577
   */
578
  String getWorkspaceName();
579

580
  /**
581
   * @return the value of the system {@link IdeVariables#PATH PATH} variable. It is automatically extended according to the tools available in
582
   *     {@link #getSoftwarePath() software path} unless {@link #getIdeHome() IDE_HOME} was not found.
583
   */
584
  SystemPath getPath();
585

586
  /**
587
   * @return a new {@link ProcessContext} to {@link ProcessContext#run() run} external commands.
588
   */
589
  ProcessContext newProcess();
590

591
  /**
592
   * @param title the {@link IdeProgressBar#getTitle() title}.
593
   * @param size the {@link IdeProgressBar#getMaxSize() expected maximum size}.
594
   * @param unitName the {@link IdeProgressBar#getUnitName() unit name}.
595
   * @param unitSize the {@link IdeProgressBar#getUnitSize() unit size}.
596
   * @return the new {@link IdeProgressBar} to use.
597
   */
598
  IdeProgressBar newProgressBar(String title, long size, String unitName, long unitSize);
599

600
  /**
601
   * @param title the {@link IdeProgressBar#getTitle() title}.
602
   * @param size the {@link IdeProgressBar#getMaxSize() expected maximum size} in bytes.
603
   * @return the new {@link IdeProgressBar} to use.
604
   */
605
  default IdeProgressBar newProgressBarInMib(String title, long size) {
606

607
    if ((size > 0) && (size < 1024)) {
8✔
608
      return new IdeProgressBarNone(title, size, IdeProgressBar.UNIT_NAME_MB, IdeProgressBar.UNIT_SIZE_MB);
8✔
609
    }
610
    return newProgressBar(title, size, IdeProgressBar.UNIT_NAME_MB, IdeProgressBar.UNIT_SIZE_MB);
7✔
611
  }
612

613
  /**
614
   * @param size the {@link IdeProgressBar#getMaxSize() expected maximum size} in bytes.
615
   * @return the new {@link IdeProgressBar} for copy.
616
   */
617
  default IdeProgressBar newProgressBarForDownload(long size) {
618

619
    return newProgressBarInMib(IdeProgressBar.TITLE_DOWNLOADING, size);
5✔
620
  }
621

622
  /**
623
   * @param size the {@link IdeProgressBar#getMaxSize() expected maximum size} in bytes.
624
   * @return the new {@link IdeProgressBar} for extracting.
625
   */
626
  default IdeProgressBar newProgressbarForExtracting(long size) {
627

628
    return newProgressBarInMib(IdeProgressBar.TITLE_EXTRACTING, size);
5✔
629
  }
630

631
  /**
632
   * @param size the {@link IdeProgressBar#getMaxSize() expected maximum size} in bytes.
633
   * @return the new {@link IdeProgressBar} for copy.
634
   */
635
  default IdeProgressBar newProgressbarForCopying(long size) {
636

637
    return newProgressBarInMib(IdeProgressBar.TITLE_COPYING, size);
5✔
638
  }
639

640
  /**
641
   * @param size the {@link IdeProgressBar#getMaxSize() expected maximum} plugin count.
642
   * @return the new {@link IdeProgressBar} to use.
643
   */
644
  default IdeProgressBar newProgressBarForPlugins(long size) {
645
    return newProgressBar(IdeProgressBar.TITLE_INSTALL_PLUGIN, size, IdeProgressBar.UNIT_NAME_PLUGIN, IdeProgressBar.UNIT_SIZE_PLUGIN);
7✔
646
  }
647

648
  /**
649
   * @return the {@link DirectoryMerger} used to configure and merge the workspace for an {@link com.devonfw.tools.ide.tool.ide.IdeToolCommandlet IDE}.
650
   */
651
  DirectoryMerger getWorkspaceMerger();
652

653
  /**
654
   * @return the {@link Path} to the working directory from where the command is executed.
655
   */
656
  Path getDefaultExecutionDirectory();
657

658
  /**
659
   * @return the {@link IdeSystem} instance wrapping {@link System}.
660
   */
661
  IdeSystem getSystem();
662

663
  /**
664
   * @return the {@link GitContext} used to run several git commands.
665
   */
666
  GitContext getGitContext();
667

668
  /**
669
   * @return the String value for the variable MAVEN_ARGS, or null if called outside an IDEasy installation.
670
   */
671
  default String getMavenArgs() {
672

673
    if (getIdeHome() == null) {
3✔
674
      return null;
2✔
675
    }
676
    Mvn mvn = getCommandletManager().getCommandlet(Mvn.class);
6✔
677
    return mvn.getMavenArgs();
3✔
678
  }
679

680
  /**
681
   * @return the path for the variable GRADLE_USER_HOME, or null if called outside an IDEasy installation.
682
   */
683
  default Path getGradleUserHome() {
684

685
    if (getIdeHome() == null) {
3✔
686
      return null;
2✔
687
    }
688
    Gradle gradle = getCommandletManager().getCommandlet(Gradle.class);
6✔
689
    return gradle.getOrCreateGradleConfFolder();
3✔
690
  }
691

692
  /**
693
   * @return the {@link Path} pointing to the maven configuration directory (where "settings.xml" or "settings-security.xml" are located).
694
   */
695
  default Path getMavenConfigurationFolder() {
696

697
    if (getIdeHome() == null) {
3✔
698
      // fallback to USER_HOME/.m2 folder if called outside an IDEasy project
699
      return getUserHome().resolve(Mvn.MVN_CONFIG_LEGACY_FOLDER);
5✔
700
    }
701
    Mvn mvn = getCommandletManager().getCommandlet(Mvn.class);
6✔
702
    return mvn.getMavenConfigurationFolder();
3✔
703
  }
704

705
  /**
706
   * Updates the current working directory (CWD) and configures the environment paths according to the specified parameters. This method is central to changing
707
   * the IDE's notion of where it operates, affecting where configurations, workspaces, settings, and other resources are located or loaded from.
708
   *
709
   * @return the current {@link Step} of processing.
710
   */
711
  Step getCurrentStep();
712

713
  /**
714
   * @param name the {@link Step#getName() name} of the new {@link Step}.
715
   * @return the new {@link Step} that has been created and started.
716
   */
717
  default Step newStep(String name) {
718

719
    return newStep(name, Step.NO_PARAMS);
5✔
720
  }
721

722
  /**
723
   * @param name the {@link Step#getName() name} of the new {@link Step}.
724
   * @param parameters the {@link Step#getParameter(int) parameters} of the {@link Step}.
725
   * @return the new {@link Step} that has been created and started.
726
   */
727
  default Step newStep(String name, Object... parameters) {
728

729
    return newStep(false, name, parameters);
6✔
730
  }
731

732
  /**
733
   * @param silent the {@link Step#isSilent() silent flag}.
734
   * @param name the {@link Step#getName() name} of the new {@link Step}.
735
   * @param parameters the {@link Step#getParameter(int) parameters} of the {@link Step}.
736
   * @return the new {@link Step} that has been created and started.
737
   */
738
  Step newStep(boolean silent, String name, Object... parameters);
739

740
  /**
741
   * @param lambda the {@link Runnable} to {@link Runnable#run() run} while the {@link com.devonfw.tools.ide.log.IdeLogger logging} is entirely disabled.
742
   *     After this the logging will be enabled again. Collected log messages will then be logged at the end.
743
   */
744
  default void runWithoutLogging(Runnable lambda) {
745

746
    runWithoutLogging(lambda, IdeLogLevel.TRACE);
4✔
747
  }
1✔
748

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

758
  /**
759
   * Updates the current working directory (CWD) and configures the environment paths according to the specified parameters. This method is central to changing
760
   * the IDE's notion of where it operates, affecting where configurations, workspaces, settings, and other resources are located or loaded from.
761
   *
762
   * @param ideHome The path to the IDE home directory.
763
   */
764
  default void setIdeHome(Path ideHome) {
765

766
    setCwd(ideHome, WORKSPACE_MAIN, ideHome);
5✔
767
  }
1✔
768

769
  /**
770
   * Updates the current working directory (CWD) and configures the environment paths according to the specified parameters. This method is central to changing
771
   * the IDE's notion of where it operates, affecting where configurations, workspaces, settings, and other resources are located or loaded from.
772
   *
773
   * @param userDir The path to set as the current working directory.
774
   * @param workspace The name of the workspace within the IDE's environment.
775
   * @param ideHome The path to the IDE home directory.
776
   */
777
  void setCwd(Path userDir, String workspace, Path ideHome);
778

779
  /**
780
   * Finds the path to the Bash executable.
781
   *
782
   * @return the {@link Path} to the Bash executable, or {@code null} if Bash is not found.
783
   */
784
  Path findBash();
785

786
  /**
787
   * Finds the path to the Bash executable.
788
   *
789
   * @return the {@link Path} to the Bash executable. Throws a {@link CliException} if no bash was found.
790
   */
791
  default Path findBashRequired() {
792
    Path bash = findBash();
3✔
793
    if (bash == null) {
2!
794
      String message = "Bash " + IS_NOT_INSTALLED_BUT_REQUIRED;
×
795
      if (getSystemInfo().isWindows()) {
×
796
        message += " " + PLEASE_DOWNLOAD_AND_INSTALL_GIT + ":\n " + WINDOWS_GIT_DOWNLOAD_URL;
×
797
        throw new CliException(message);
×
798
      }
799
      bash = Path.of("bash");
×
800
    }
801

802
    return bash;
2✔
803
  }
804

805
  /**
806
   * @return the {@link WindowsPathSyntax} used for {@link Path} conversion or {@code null} for no such conversion (typically if not on Windows).
807
   */
808
  WindowsPathSyntax getPathSyntax();
809

810
  /**
811
   * logs the status of {@link #getIdeHome() IDE_HOME} and {@link #getIdeRoot() IDE_ROOT}.
812
   */
813
  void logIdeHomeAndRootStatus();
814

815
  /**
816
   * @param version the {@link VersionIdentifier} to write.
817
   * @param installationPath the {@link Path directory} where to write the version to a {@link #FILE_SOFTWARE_VERSION version file}.
818
   */
819
  void writeVersionFile(VersionIdentifier version, Path installationPath);
820

821
  /**
822
   * Verifies that current {@link IdeVersion} satisfies {@link IdeVariables#IDE_MIN_VERSION}.
823
   *
824
   * @param throwException whether to throw a {@link CliException} or just log a warning.
825
   */
826
  void verifyIdeMinVersion(boolean throwException);
827

828
  /**
829
   * @return the path for the variable COREPACK_HOME, or null if called outside an IDEasy installation.
830
   */
831
  default Path getCorePackHome() {
832
    if (getIdeHome() == null) {
×
833
      return null;
×
834
    }
835
    Corepack corepack = getCommandletManager().getCommandlet(Corepack.class);
×
836
    return corepack.getOrCreateCorepackHomeFolder();
×
837
  }
838

839
  /**
840
   * @return the path for the variable NPM_CONFIG_USERCONFIG, or null if called outside an IDEasy installation.
841
   */
842
  default Path getNpmConfigUserConfig() {
843
    if (getIdeHome() == null) {
3✔
844
      return null;
2✔
845
    }
846
    Npm npm = getCommandletManager().getCommandlet(Npm.class);
6✔
847
    return npm.getOrCreateNpmConfigUserConfig();
3✔
848
  }
849

850
}
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