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

devonfw / IDEasy / 28362152823

29 Jun 2026 09:26AM UTC coverage: 71.277% (-0.08%) from 71.356%
28362152823

Pull #2086

github

web-flow
Merge 18cefaf47 into a98452817
Pull Request #2086: #2070: Create soapuiurlupdater

4714 of 7312 branches covered (64.47%)

Branch coverage included in aggregate %.

12173 of 16380 relevant lines covered (74.32%)

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.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 interaction with the user allowing to input and output information.
42
 */
43
public interface IdeContext extends IdeStartContext {
44

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

358
  /**
359
   * @return the {@link UvRepository}.
360
   */
361
  UvRepository getUvRepository();
362

363
  /**
364
   * @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
365
   *     isolated projects.
366
   * @see com.devonfw.tools.ide.variable.IdeVariables#IDE_HOME
367
   */
368
  Path getIdeHome();
369

370
  /**
371
   * @return the name of the current project.
372
   * @see com.devonfw.tools.ide.variable.IdeVariables#PROJECT_NAME
373
   */
374
  String getProjectName();
375

376
  /**
377
   * @return the IDEasy version the {@link #getIdeHome() current project} was created with or migrated to.
378
   */
379
  VersionIdentifier getProjectVersion();
380

381
  /**
382
   * @param version the new value of {@link #getProjectVersion()}.
383
   */
384
  void setProjectVersion(VersionIdentifier version);
385

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

394
  /**
395
   * @return the {@link Path} to the {@link #FOLDER_UNDERSCORE_IDE}.
396
   * @see #getIdeRoot()
397
   * @see #FOLDER_UNDERSCORE_IDE
398
   */
399
  Path getIdePath();
400

401
  /**
402
   * @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
403
   *     upgrade a new release is installed and the link is switched to the new release.
404
   */
405
  default Path getIdeInstallationPath() {
406

407
    Path idePath = getIdePath();
3✔
408
    if (idePath == null) {
2!
409
      return null;
×
410
    }
411
    return idePath.resolve(FOLDER_INSTALLATION);
4✔
412
  }
413

414
  /**
415
   * @return the current working directory ("user.dir"). This is the directory where the user's shell was located when the IDE CLI was invoked.
416
   */
417
  Path getCwd();
418

419
  /**
420
   * @return the {@link Path} for the temporary directory to use. Will be different from the OS specific temporary directory (java.io.tmpDir).
421
   */
422
  Path getTempPath();
423

424
  /**
425
   * @return the {@link Path} for the temporary download directory to use.
426
   */
427
  Path getTempDownloadPath();
428

429
  /**
430
   * @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
431
   *     download tools.
432
   * @see com.devonfw.tools.ide.url.model.folder.UrlRepository
433
   */
434
  Path getUrlsPath();
435

436
  /**
437
   * @return the {@link UrlMetadata}. Will be lazily instantiated and thereby automatically be cloned or pulled (by default).
438
   */
439
  UrlMetadata getUrls();
440

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

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

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

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

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

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

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

489
  /**
490
   * @return the {@link Path} to the ".ide" subfolder in the {@link #getUserHome() users home directory}.
491
   */
492
  Path getUserHomeIde();
493

494
  /**
495
   * @return the {@link Path} to the {@link #FOLDER_SETTINGS settings} folder with the cloned git repository containing the project configuration.
496
   */
497
  Path getSettingsPath();
498

499
  /**
500
   * @return the {@link Path} to the {@link #FOLDER_REPOSITORIES repositories} folder with legacy fallback if not present or {@code null} if not found.
501
   */
502
  default Path getRepositoriesPath() {
503

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

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

525
  /**
526
   * @return {@code true} if the settings repository is a symlink or a junction to a code-repository.
527
   */
528
  boolean isSettingsCodeRepository();
529

530
  /**
531
   * @return the {@link Path} to the file containing the last tracked commit Id of the settings repository.
532
   */
533
  Path getSettingsCommitIdPath();
534

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

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

561
  /**
562
   * @return the {@link Path} to the workspaces base folder containing the individual {@link #getWorkspacePath(String) workspaces}.
563
   * @see #getWorkspacePath(String)
564
   */
565
  Path getWorkspacesBasePath();
566

567
  /**
568
   * @return the {@link Path} to the workspace.
569
   * @see #getWorkspaceName()
570
   */
571
  Path getWorkspacePath();
572

573
  /**
574
   * @param workspace the specific workspace name.
575
   * @return the {@link Path} to the specified workspace.
576
   */
577
  Path getWorkspacePath(String workspace);
578

579
  /**
580
   * @return the name of the workspace. Defaults to {@link #WORKSPACE_MAIN}.
581
   */
582
  String getWorkspaceName();
583

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

590
  /**
591
   * @return a new {@link ProcessContext} to {@link ProcessContext#run() run} external commands.
592
   */
593
  ProcessContext newProcess();
594

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

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

611
    if ((size > 0) && (size < 1024)) {
8✔
612
      return new IdeProgressBarNone(title, size, IdeProgressBar.UNIT_NAME_MB, IdeProgressBar.UNIT_SIZE_MB);
8✔
613
    }
614
    return newProgressBar(title, size, IdeProgressBar.UNIT_NAME_MB, IdeProgressBar.UNIT_SIZE_MB);
7✔
615
  }
616

617
  /**
618
   * @param size the {@link IdeProgressBar#getMaxSize() expected maximum size} in bytes.
619
   * @return the new {@link IdeProgressBar} for copy.
620
   */
621
  default IdeProgressBar newProgressBarForDownload(long size) {
622

623
    return newProgressBarInMib(IdeProgressBar.TITLE_DOWNLOADING, size);
5✔
624
  }
625

626
  /**
627
   * @param size the {@link IdeProgressBar#getMaxSize() expected maximum size} in bytes.
628
   * @return the new {@link IdeProgressBar} for extracting.
629
   */
630
  default IdeProgressBar newProgressbarForExtracting(long size) {
631

632
    return newProgressBarInMib(IdeProgressBar.TITLE_EXTRACTING, size);
5✔
633
  }
634

635
  /**
636
   * @param size the {@link IdeProgressBar#getMaxSize() expected maximum size} in bytes.
637
   * @return the new {@link IdeProgressBar} for copy.
638
   */
639
  default IdeProgressBar newProgressbarForCopying(long size) {
640

641
    return newProgressBarInMib(IdeProgressBar.TITLE_COPYING, size);
5✔
642
  }
643

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

652
  /**
653
   * @return the {@link DirectoryMerger} used to configure and merge the workspace for an {@link com.devonfw.tools.ide.tool.ide.IdeToolCommandlet IDE}.
654
   */
655
  DirectoryMerger getWorkspaceMerger();
656

657
  /**
658
   * @return the {@link Path} to the working directory from where the command is executed.
659
   */
660
  Path getDefaultExecutionDirectory();
661

662
  /**
663
   * @return the {@link IdeSystem} instance wrapping {@link System}.
664
   */
665
  IdeSystem getSystem();
666

667
  /**
668
   * @return the {@link GitContext} used to run several git commands.
669
   */
670
  GitContext getGitContext();
671

672
  /**
673
   * @return the String value for the variable MAVEN_ARGS, or null if called outside an IDEasy installation.
674
   */
675
  default String getMavenArgs() {
676

677
    if (getIdeHome() == null) {
3✔
678
      return null;
2✔
679
    }
680
    Mvn mvn = getCommandletManager().getCommandlet(Mvn.class);
6✔
681
    return mvn.getMavenArgs();
3✔
682
  }
683

684
  /**
685
   * @return the path for the variable GRADLE_USER_HOME, or null if called outside an IDEasy installation.
686
   */
687
  default Path getGradleUserHome() {
688

689
    if (getIdeHome() == null) {
3✔
690
      return null;
2✔
691
    }
692
    Gradle gradle = getCommandletManager().getCommandlet(Gradle.class);
6✔
693
    return gradle.getOrCreateGradleConfFolder();
3✔
694
  }
695

696
  /**
697
   * @return the {@link Path} pointing to the maven configuration directory (where "settings.xml" or "settings-security.xml" are located).
698
   */
699
  default Path getMavenConfigurationFolder() {
700

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

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

717
  /**
718
   * @param name the {@link Step#getName() name} of the new {@link Step}.
719
   * @return the new {@link Step} that has been created and started.
720
   */
721
  default Step newStep(String name) {
722

723
    return newStep(name, Step.NO_PARAMS);
5✔
724
  }
725

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

733
    return newStep(false, name, parameters);
6✔
734
  }
735

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

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

750
    runWithoutLogging(lambda, IdeLogLevel.TRACE);
4✔
751
  }
1✔
752

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

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

770
    setCwd(ideHome, WORKSPACE_MAIN, ideHome);
5✔
771
  }
1✔
772

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

783
  /**
784
   * Finds the path to the Bash executable.
785
   *
786
   * @return the {@link Path} to the Bash executable, or {@code null} if Bash is not found.
787
   */
788
  Path findBash();
789

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

806
    return bash;
2✔
807
  }
808

809
  /**
810
   * @return the {@link WindowsPathSyntax} used for {@link Path} conversion or {@code null} for no such conversion (typically if not on Windows).
811
   */
812
  WindowsPathSyntax getPathSyntax();
813

814
  /**
815
   * logs the status of {@link #getIdeHome() IDE_HOME} and {@link #getIdeRoot() IDE_ROOT}.
816
   */
817
  void logIdeHomeAndRootStatus();
818

819
  /**
820
   * @param version the {@link VersionIdentifier} to write.
821
   * @param installationPath the {@link Path directory} where to write the version to a {@link #FILE_SOFTWARE_VERSION version file}.
822
   */
823
  void writeVersionFile(VersionIdentifier version, Path installationPath);
824

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

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

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

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