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

devonfw / IDEasy / 10162642157

30 Jul 2024 12:47PM UTC coverage: 61.662% (-0.02%) from 61.685%
10162642157

push

github

web-flow
#303: Handle null return of findbash (#486)

2041 of 3645 branches covered (55.99%)

Branch coverage included in aggregate %.

5422 of 8458 relevant lines covered (64.1%)

2.82 hits per line

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

53.13
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
import java.util.Locale;
6

7
import com.devonfw.tools.ide.cli.CliAbortException;
8
import com.devonfw.tools.ide.cli.CliException;
9
import com.devonfw.tools.ide.cli.CliOfflineException;
10
import com.devonfw.tools.ide.commandlet.CommandletManager;
11
import com.devonfw.tools.ide.common.SystemPath;
12
import com.devonfw.tools.ide.environment.EnvironmentVariables;
13
import com.devonfw.tools.ide.environment.EnvironmentVariablesType;
14
import com.devonfw.tools.ide.io.FileAccess;
15
import com.devonfw.tools.ide.io.IdeProgressBar;
16
import com.devonfw.tools.ide.log.IdeLogger;
17
import com.devonfw.tools.ide.merge.DirectoryMerger;
18
import com.devonfw.tools.ide.network.ProxyContext;
19
import com.devonfw.tools.ide.os.SystemInfo;
20
import com.devonfw.tools.ide.os.WindowsPathSyntax;
21
import com.devonfw.tools.ide.process.ProcessContext;
22
import com.devonfw.tools.ide.repo.CustomToolRepository;
23
import com.devonfw.tools.ide.repo.ToolRepository;
24
import com.devonfw.tools.ide.step.Step;
25
import com.devonfw.tools.ide.tool.mvn.Mvn;
26
import com.devonfw.tools.ide.url.model.UrlMetadata;
27
import com.devonfw.tools.ide.variable.IdeVariables;
28

29
/**
30
 * Interface for interaction with the user allowing to input and output information.
31
 */
32
public interface IdeContext extends IdeLogger {
33

34
  /**
35
   * The default settings URL.
36
   *
37
   * @see com.devonfw.tools.ide.commandlet.AbstractUpdateCommandlet
38
   */
39
  String DEFAULT_SETTINGS_REPO_URL = "https://github.com/devonfw/ide-settings.git";
40

41
  /** The name of the workspaces folder. */
42
  String FOLDER_WORKSPACES = "workspaces";
43

44
  /** The name of the settings folder. */
45
  String FOLDER_SETTINGS = "settings";
46

47
  /** The name of the software folder. */
48
  String FOLDER_SOFTWARE = "software";
49

50
  /** The name of the conf folder for project specific user configurations. */
51
  String FOLDER_CONF = "conf";
52

53
  /**
54
   * The base folder name of the IDE inside IDE_ROOT. Intentionally starting with an underscore and not a dot (to prevent effects like OS hiding, maven
55
   * filtering, .gitignore, etc.).
56
   */
57
  String FOLDER_IDE = "_ide";
58

59
  /** The name of the updates folder for temporary data and backup. */
60
  String FOLDER_UPDATES = "updates";
61

62
  /** The name of the volume folder for mounting archives like *.dmg. */
63
  String FOLDER_VOLUME = "volume";
64

65
  /** The name of the backups folder for backup. */
66
  String FOLDER_BACKUPS = "backups";
67

68
  /** The name of the downloads folder. */
69
  String FOLDER_DOWNLOADS = "Downloads";
70

71
  /** The name of the bin folder where executable files are found by default. */
72
  String FOLDER_BIN = "bin";
73

74
  /** The name of the repositories folder where properties files are stores for each repository */
75
  String FOLDER_REPOSITORIES = "repositories";
76

77
  /** The name of the repositories folder where properties files are stores for each repository */
78
  String FOLDER_LEGACY_REPOSITORIES = "projects";
79

80
  /** The name of the Contents folder inside a MacOS app. */
81
  String FOLDER_CONTENTS = "Contents";
82

83
  /** The name of the Resources folder inside a MacOS app. */
84
  String FOLDER_RESOURCES = "Resources";
85

86
  /** The name of the app folder inside a MacOS app. */
87
  String FOLDER_APP = "app";
88

89
  /** The name of the extra folder inside the software folder */
90
  String FOLDER_EXTRA = "extra";
91

92
  /**
93
   * The name of the {@link #getPluginsPath() plugins folder} and also the plugins folder inside the IDE folders of {@link #getSettingsPath() settings} (e.g.
94
   * settings/eclipse/plugins).
95
   */
96
  String FOLDER_PLUGINS = "plugins";
97

98
  /**
99
   * The name of the workspace folder inside the IDE specific {@link #FOLDER_SETTINGS settings} containing the configuration templates in #FOLDER_SETUP
100
   * #FOLDER_UPDATE.
101
   */
102
  String FOLDER_WORKSPACE = "workspace";
103

104
  /**
105
   * The name of the setup folder inside the {@link #FOLDER_WORKSPACE workspace} folder containing the templates for the configuration templates for the initial
106
   * setup of a workspace. This is closely related with the {@link #FOLDER_UPDATE update} folder.
107
   */
108
  String FOLDER_SETUP = "setup";
109

110
  /**
111
   * The name of the update folder inside the {@link #FOLDER_WORKSPACE workspace} folder containing the templates for the configuration templates for the update
112
   * 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
113
   * 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
114
   * for indentation and other code-formatting settings. If all developers in a project team use the same formatter settings, this will actively prevent
115
   * 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
116
   * 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
117
   * 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
118
   * user as needed.
119
   */
120
  String FOLDER_UPDATE = "update";
121

122
  /** The file where the installed software version is written to as plain text. */
123
  String FILE_SOFTWARE_VERSION = ".ide.software.version";
124

125
  /** The file where the installed software version is written to as plain text. */
126
  String FILE_LEGACY_SOFTWARE_VERSION = ".devon.software.version";
127

128
  /** The file extension for a {@link java.util.Properties} file. */
129
  String EXT_PROPERTIES = ".properties";
130

131
  /** The default for {@link #getWorkspaceName()}. */
132
  String WORKSPACE_MAIN = "main";
133

134
  /** The folder with the configuration template files from the settings. */
135
  String FOLDER_TEMPLATES = "templates";
136

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

140
  /**
141
   * @return {@code true} in case of quiet mode (reduced output), {@code false} otherwise.
142
   */
143
  boolean isQuietMode();
144

145
  /**
146
   * @return {@code true} in case of batch mode (no {@link #question(String) user-interaction}), {@code false} otherwise.
147
   */
148
  boolean isBatchMode();
149

150
  /**
151
   * @return {@code true} in case of force mode, {@code false} otherwise.
152
   */
153
  boolean isForceMode();
154

155
  /**
156
   * @return {@code true} if offline mode is activated (-o/--offline), {@code false} otherwise.
157
   */
158
  boolean isOfflineMode();
159

160
  /**
161
   * @return {@code true} if {@link #isOfflineMode() offline mode} is active or we are NOT {@link #isOnline() online}, {@code false} otherwise.
162
   */
163
  default boolean isOffline() {
164

165
    return isOfflineMode() || !isOnline();
10!
166
  }
167

168
  /**
169
   * @return {@code true} if we are currently online (Internet access is available), {@code false} otherwise.
170
   */
171
  boolean isOnline();
172

173
  /**
174
   * Asks the user for a single string input.
175
   *
176
   * @param message The information message to display.
177
   * @param defaultValue The default value to return when no input is provided.
178
   * @return The string input from the user, or the default value if no input is provided.
179
   */
180
  String askForInput(String message, String defaultValue);
181

182
  /**
183
   * Asks the user for a single string input.
184
   *
185
   * @param message The information message to display.
186
   * @return The string input from the user, or the default value if no input is provided.
187
   */
188
  String askForInput(String message);
189

190
  /**
191
   * @param question the question to ask.
192
   * @return {@code true} if the user answered with "yes", {@code false} otherwise ("no").
193
   */
194
  default boolean question(String question) {
195

196
    String yes = "yes";
×
197
    String option = question(question, yes, "no");
×
198
    if (yes.equals(option)) {
×
199
      return true;
×
200
    }
201
    return false;
×
202
  }
203

204
  /**
205
   * @param <O> type of the option. E.g. {@link String}.
206
   * @param question the question to ask.
207
   * @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.
208
   * @return the option selected by the user as answer.
209
   */
210
  @SuppressWarnings("unchecked")
211
  <O> O question(String question, O... options);
212

213
  /**
214
   * 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
215
   * exception is thrown to abort further processing.
216
   *
217
   * @param question the yes/no question to {@link #question(String) ask}.
218
   * @throws CliAbortException if the user answered with "no" and further processing shall be aborted.
219
   */
220
  default void askToContinue(String question) {
221

222
    boolean yesContinue = question(question);
×
223
    if (!yesContinue) {
×
224
      throw new CliAbortException();
×
225
    }
226
  }
×
227

228
  /**
229
   * @param purpose the purpose why Internet connection is required.
230
   * @throws CliException if you are {@link #isOffline() offline}.
231
   */
232
  default void requireOnline(String purpose) {
233

234
    if (isOfflineMode()) {
3!
235
      throw new CliOfflineException("You are offline but Internet access is required for " + purpose);
×
236
    }
237
  }
1✔
238

239
  /**
240
   * @return the {@link SystemInfo}.
241
   */
242
  SystemInfo getSystemInfo();
243

244
  /**
245
   * @return the {@link EnvironmentVariables} with full inheritance.
246
   */
247
  EnvironmentVariables getVariables();
248

249
  /**
250
   * @return the {@link FileAccess}.
251
   */
252
  FileAccess getFileAccess();
253

254
  /**
255
   * @return the {@link CommandletManager}.
256
   */
257
  CommandletManager getCommandletManager();
258

259
  /**
260
   * @return the default {@link ToolRepository}.
261
   */
262
  ToolRepository getDefaultToolRepository();
263

264
  /**
265
   * @return the {@link CustomToolRepository}.
266
   */
267
  CustomToolRepository getCustomToolRepository();
268

269
  /**
270
   * @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
271
   * isolated projects.
272
   * @see com.devonfw.tools.ide.variable.IdeVariables#IDE_HOME
273
   */
274
  Path getIdeHome();
275

276
  /**
277
   * @return the name of the current project.
278
   * @see com.devonfw.tools.ide.variable.IdeVariables#PROJECT_NAME
279
   */
280
  String getProjectName();
281

282
  /**
283
   * @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
284
   * sub-folder. There is a reserved ".ide" folder where central IDE data is stored such as the {@link #getUrlsPath() download metadata} and the central
285
   * software repository.
286
   * @see com.devonfw.tools.ide.variable.IdeVariables#IDE_ROOT
287
   */
288
  Path getIdeRoot();
289

290
  /**
291
   * @return the current working directory ("user.dir"). This is the directory where the user's shell was located when the IDE CLI was invoked.
292
   */
293
  Path getCwd();
294

295
  /**
296
   * @return the {@link Path} for the temporary directory to use. Will be different from the OS specific temporary directory (java.io.tmpDir).
297
   */
298
  Path getTempPath();
299

300
  /**
301
   * @return the {@link Path} for the temporary download directory to use.
302
   */
303
  Path getTempDownloadPath();
304

305
  /**
306
   * @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
307
   * download tools.
308
   * @see com.devonfw.tools.ide.url.model.folder.UrlRepository
309
   */
310
  Path getUrlsPath();
311

312
  /**
313
   * @return the {@link UrlMetadata}. Will be lazily instantiated and thereby automatically be cloned or pulled (by default).
314
   */
315
  UrlMetadata getUrls();
316

317
  /**
318
   * @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
319
   * the same artifact is requested again it will be taken from the cache to avoid downloading it again.
320
   */
321
  Path getDownloadPath();
322

323
  /**
324
   * @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
325
   * {@link #getSoftwareRepositoryPath() software repository} as sub-folder named after the according tool.
326
   */
327
  Path getSoftwarePath();
328

329
  /**
330
   * @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
331
   * here from the {@link #getSoftwareRepositoryPath() software repository} as sub-folder named after the according tool.
332
   */
333
  Path getSoftwareExtraPath();
334

335
  /**
336
   * @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
337
   * are shared among all IDE instances (see {@link #getIdeHome() IDE_HOME}) via symbolic links (see {@link #getSoftwarePath()}). Therefore this repository
338
   * follows the sub-folder structure {@code «repository»/«tool»/«edition»/«version»/}. So multiple versions of the same tool exist here as different folders.
339
   * 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 of the scope
340
   * of this folders.
341
   */
342
  Path getSoftwareRepositoryPath();
343

344
  /**
345
   * @return the {@link Path} to the {@link #FOLDER_PLUGINS plugins folder} inside {@link #getIdeHome() IDE_HOME}. All plugins of the IDE instance will be
346
   * 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.
347
   */
348
  Path getPluginsPath();
349

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

359
  /**
360
   * @return the {@link Path} to the users home directory. Typically initialized via the {@link System#getProperty(String) system property} "user.home".
361
   * @see com.devonfw.tools.ide.variable.IdeVariables#HOME
362
   */
363
  Path getUserHome();
364

365
  /**
366
   * @return the {@link Path} to the ".ide" subfolder in the {@link #getUserHome() users home directory}.
367
   */
368
  Path getUserHomeIde();
369

370
  /**
371
   * @return the {@link Path} to the {@code settings} folder with the cloned git repository containing the project configuration.
372
   */
373
  Path getSettingsPath();
374

375
  /**
376
   * @return the {@link Path} to the {@code conf} folder with instance specific tool configurations and the
377
   * {@link EnvironmentVariablesType#CONF user specific project configuration}.
378
   */
379
  Path getConfPath();
380

381
  /**
382
   * @return the {@link Path} to the workspace.
383
   * @see #getWorkspaceName()
384
   */
385
  Path getWorkspacePath();
386

387
  /**
388
   * @return the name of the workspace. Defaults to {@link #WORKSPACE_MAIN}.
389
   */
390
  String getWorkspaceName();
391

392
  /**
393
   * @return the value of the system {@link IdeVariables#PATH PATH} variable. It is automatically extended according to the tools available in
394
   * {@link #getSoftwarePath() software path} unless {@link #getIdeHome() IDE_HOME} was not found.
395
   */
396
  SystemPath getPath();
397

398
  /**
399
   * @return the current {@link Locale}. Either configured via command-line option or {@link Locale#getDefault() default}.
400
   */
401
  Locale getLocale();
402

403
  /**
404
   * @return a new {@link ProcessContext} to {@link ProcessContext#run() run} external commands.
405
   */
406
  ProcessContext newProcess();
407

408
  /**
409
   * Prepares the {@link IdeProgressBar} initializes task name and maximum size as well as the behaviour and style.
410
   *
411
   * @param taskName name of the task.
412
   * @param size of the content.
413
   * @return {@link IdeProgressBar} to use.
414
   */
415
  IdeProgressBar prepareProgressBar(String taskName, long size);
416

417
  /**
418
   * @return the {@link DirectoryMerger} used to configure and merge the workspace for an {@link com.devonfw.tools.ide.tool.ide.IdeToolCommandlet IDE}.
419
   */
420
  DirectoryMerger getWorkspaceMerger();
421

422
  /**
423
   * @return the {@link Path} to the working directory from where the command is executed.
424
   */
425
  Path getDefaultExecutionDirectory();
426

427
  ProxyContext getProxyContext();
428

429
  /**
430
   * @return the {@link GitContext} used to run several git commands.
431
   */
432
  GitContext getGitContext();
433

434
  /**
435
   * @return the String value for the variable MAVEN_ARGS, or null if called outside an IDEasy installation.
436
   */
437
  default String getMavenArgs() {
438

439
    if (getIdeHome() == null) {
3!
440
      return null;
×
441
    }
442
    Path confFolder = getConfPath();
3✔
443
    Path mvnSettingsFile = confFolder.resolve(Mvn.MVN_CONFIG_FOLDER).resolve(Mvn.SETTINGS_FILE);
6✔
444
    if (!Files.exists(mvnSettingsFile)) {
5✔
445
      mvnSettingsFile = confFolder.resolve(Mvn.MVN_CONFIG_LEGACY_FOLDER).resolve(Mvn.SETTINGS_FILE);
6✔
446
      if (!Files.exists(mvnSettingsFile)) {
5!
447
        return null;
2✔
448
      }
449
    }
450
    String settingsPath;
451
    WindowsPathSyntax pathSyntax = getPathSyntax();
3✔
452
    if (pathSyntax == null) {
2!
453
      settingsPath = mvnSettingsFile.toString();
4✔
454
    } else {
455
      settingsPath = pathSyntax.format(mvnSettingsFile);
×
456
    }
457
    return "-s " + settingsPath;
3✔
458
  }
459

460
  /**
461
   * @return the String value for the variable M2_REPO, or null if called outside an IDEasy installation.
462
   */
463
  default Path getMavenRepoEnvVariable() {
464

465
    if (getIdeHome() != null) {
3!
466
      return getConfPath().resolve(Mvn.MVN_CONFIG_LEGACY_FOLDER).resolve("repository");
7✔
467
    }
468
    return null;
×
469
  }
470

471
  /**
472
   * Updates the current working directory (CWD) and configures the environment paths according to the specified parameters. This method is central to changing
473
   * the IDE's notion of where it operates, affecting where configurations, workspaces, settings, and other resources are located or loaded from.
474
   *
475
   * @return the current {@link Step} of processing.
476
   */
477
  Step getCurrentStep();
478

479
  /**
480
   * @param name the {@link Step#getName() name} of the new {@link Step}.
481
   * @return the new {@link Step} that has been created and started.
482
   */
483
  default Step newStep(String name) {
484

485
    return newStep(name, Step.NO_PARAMS);
5✔
486
  }
487

488
  /**
489
   * @param name the {@link Step#getName() name} of the new {@link Step}.
490
   * @param parameters the {@link Step#getParameter(int) parameters} of the {@link Step}.
491
   * @return the new {@link Step} that has been created and started.
492
   */
493
  default Step newStep(String name, Object... parameters) {
494

495
    return newStep(false, name, parameters);
6✔
496
  }
497

498
  /**
499
   * @param silent the {@link Step#isSilent() silent flag}.
500
   * @param name the {@link Step#getName() name} of the new {@link Step}.
501
   * @param parameters the {@link Step#getParameter(int) parameters} of the {@link Step}.
502
   * @return the new {@link Step} that has been created and started.
503
   */
504
  Step newStep(boolean silent, String name, Object... parameters);
505

506
  /**
507
   * Updates the current working directory (CWD) and configures the environment paths according to the specified parameters. This method is central to changing
508
   * the IDE's notion of where it operates, affecting where configurations, workspaces, settings, and other resources are located or loaded from.
509
   *
510
   * @param ideHome The path to the IDE home directory.
511
   */
512
  default void setIdeHome(Path ideHome) {
513

514
    setCwd(ideHome, WORKSPACE_MAIN, ideHome);
5✔
515
  }
1✔
516

517
  /**
518
   * Updates the current working directory (CWD) and configures the environment paths according to the specified parameters. This method is central to changing
519
   * the IDE's notion of where it operates, affecting where configurations, workspaces, settings, and other resources are located or loaded from.
520
   *
521
   * @param userDir The path to set as the current working directory.
522
   * @param workspace The name of the workspace within the IDE's environment.
523
   * @param ideHome The path to the IDE home directory.
524
   */
525
  void setCwd(Path userDir, String workspace, Path ideHome);
526

527
  /**
528
   * Finds the path to the Bash executable.
529
   *
530
   * @return the {@link String} to the Bash executable, or {@code null} if Bash is not found
531
   */
532
  String findBash();
533

534
  /**
535
   * Finds the path to the Bash executable.
536
   *
537
   * @return the {@link String} to the Bash executable. Throws an {@link IllegalStateException} if no bash was found.
538
   */
539
  default String findBashRequired() {
540
    String bash = findBash();
3✔
541
    if (bash == null) {
2!
542
      String message = "Could not find bash what is a prerequisite of IDEasy.";
×
543
      if (getSystemInfo().isWindows()) {
×
544
        message = message + "\nPlease install Git for Windows and rerun.";
×
545
      }
546
      throw new IllegalStateException(message);
×
547
    }
548
    return bash;
2✔
549
  }
550

551
  /**
552
   * @return the {@link WindowsPathSyntax} used for {@link Path} conversion or {@code null} for no such conversion (typically if not on Windows).
553
   */
554
  WindowsPathSyntax getPathSyntax();
555

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