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

devonfw / IDEasy / 9808947434

05 Jul 2024 01:16PM UTC coverage: 61.755% (-0.04%) from 61.798%
9808947434

push

github

web-flow
#396: Display the tools help output on 'ide help <tool>'  (#434)

1987 of 3535 branches covered (56.21%)

Branch coverage included in aggregate %.

5276 of 8226 relevant lines covered (64.14%)

2.81 hits per line

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

67.83
cli/src/main/java/com/devonfw/tools/ide/tool/ToolCommandlet.java
1
package com.devonfw.tools.ide.tool;
2

3
import com.devonfw.tools.ide.commandlet.Commandlet;
4
import com.devonfw.tools.ide.common.Tag;
5
import com.devonfw.tools.ide.common.Tags;
6
import com.devonfw.tools.ide.context.IdeContext;
7
import com.devonfw.tools.ide.environment.EnvironmentVariables;
8
import com.devonfw.tools.ide.environment.EnvironmentVariablesType;
9
import com.devonfw.tools.ide.nls.NlsBundle;
10
import com.devonfw.tools.ide.os.MacOsHelper;
11
import com.devonfw.tools.ide.process.ProcessContext;
12
import com.devonfw.tools.ide.process.ProcessErrorHandling;
13
import com.devonfw.tools.ide.process.ProcessMode;
14
import com.devonfw.tools.ide.property.StringProperty;
15
import com.devonfw.tools.ide.version.VersionIdentifier;
16

17
import java.nio.file.Files;
18
import java.nio.file.Path;
19
import java.util.List;
20
import java.util.Set;
21

22
/**
23
 * {@link Commandlet} for a tool integrated into the IDE.
24
 */
25
public abstract class ToolCommandlet extends Commandlet implements Tags {
26

27
  /** @see #getName() */
28
  protected final String tool;
29

30
  private final Set<Tag> tags;
31

32
  /** The commandline arguments to pass to the tool. */
33
  public final StringProperty arguments;
34

35
  private MacOsHelper macOsHelper;
36

37
  /**
38
   * The constructor.
39
   *
40
   * @param context the {@link IdeContext}.
41
   * @param tool the {@link #getName() tool name}.
42
   * @param tags the {@link #getTags() tags} classifying the tool. Should be created via {@link Set#of(Object) Set.of} method.
43
   */
44
  public ToolCommandlet(IdeContext context, String tool, Set<Tag> tags) {
45

46
    super(context);
3✔
47
    this.tool = tool;
3✔
48
    this.tags = tags;
3✔
49
    addKeyword(tool);
3✔
50
    this.arguments = new StringProperty("", false, true, "args");
9✔
51
    initProperties();
2✔
52
  }
1✔
53

54
  /**
55
   * Add initial Properties to the tool
56
   */
57
  protected void initProperties() {
58

59
    add(this.arguments);
5✔
60
  }
1✔
61

62
  /**
63
   * @return the name of the tool (e.g. "java", "mvn", "npm", "node").
64
   */
65
  @Override
66
  public String getName() {
67

68
    return this.tool;
3✔
69
  }
70

71
  /**
72
   * @return the name of the binary executable for this tool.
73
   */
74
  protected String getBinaryName() {
75

76
    return this.tool;
3✔
77
  }
78

79
  @Override
80
  public final Set<Tag> getTags() {
81

82
    return this.tags;
×
83
  }
84

85
  @Override
86
  public void run() {
87

88
    runTool(ProcessMode.DEFAULT, null, this.arguments.asArray());
7✔
89
  }
1✔
90

91
  /**
92
   * Ensures the tool is installed and then runs this tool with the given arguments.
93
   *
94
   * @param processMode see {@link ProcessMode}
95
   * @param toolVersion the explicit version (pattern) to run. Typically {@code null} to ensure the configured version is installed and use that one. Otherwise,
96
   * the specified version will be installed in the software repository without touching and IDE installation and used to run.
97
   * @param args the command-line arguments to run the tool.
98
   */
99
  public void runTool(ProcessMode processMode, VersionIdentifier toolVersion, String... args) {
100

101
    Path binaryPath;
102
    Path toolPath = Path.of(getBinaryName());
×
103
    if (toolVersion == null) {
×
104
      install(true);
×
105
      binaryPath = toolPath;
×
106
    } else {
107
      throw new UnsupportedOperationException("Not yet implemented!");
×
108
    }
109
    ProcessContext pc = this.context.newProcess().errorHandling(ProcessErrorHandling.WARNING).executable(binaryPath).addArgs(args);
×
110

111
    pc.run(processMode);
×
112
  }
×
113

114
  /**
115
   * @param toolVersion the explicit {@link VersionIdentifier} of the tool to run.
116
   * @param args the command-line arguments to run the tool.
117
   * @see ToolCommandlet#runTool(ProcessMode, VersionIdentifier, String...)
118
   */
119
  public void runTool(VersionIdentifier toolVersion, String... args) {
120

121
    runTool(ProcessMode.DEFAULT, toolVersion, args);
5✔
122
  }
1✔
123

124
  /**
125
   * @return the {@link EnvironmentVariables#getToolEdition(String) tool edition}.
126
   */
127
  public String getEdition() {
128

129
    return this.context.getVariables().getToolEdition(getName());
7✔
130
  }
131

132
  /**
133
   * @return the {@link #getName() tool} with its {@link #getEdition() edition}. The edition will be omitted if same as tool.
134
   * @see #getToolWithEdition(String, String)
135
   */
136
  protected final String getToolWithEdition() {
137

138
    return getToolWithEdition(getName(), getEdition());
6✔
139
  }
140

141
  /**
142
   * @param tool the tool name.
143
   * @param edition the edition.
144
   * @return the {@link #getName() tool} with its {@link #getEdition() edition}. The edition will be omitted if same as tool.
145
   */
146
  protected final static String getToolWithEdition(String tool, String edition) {
147

148
    if (tool.equals(edition)) {
4!
149
      return tool;
2✔
150
    }
151
    return tool + "/" + edition;
×
152
  }
153

154
  /**
155
   * @return the {@link EnvironmentVariables#getToolVersion(String) tool version}.
156
   */
157
  public VersionIdentifier getConfiguredVersion() {
158

159
    return this.context.getVariables().getToolVersion(getName());
7✔
160
  }
161

162
  /**
163
   * Method to be called for {@link #install(boolean)} from dependent {@link com.devonfw.tools.ide.commandlet.Commandlet}s.
164
   *
165
   * @return {@code true} if the tool was newly installed, {@code false} if the tool was already installed before and nothing has changed.
166
   */
167
  public boolean install() {
168

169
    return install(true);
4✔
170
  }
171

172
  /**
173
   * Performs the installation of the {@link #getName() tool} managed by this {@link com.devonfw.tools.ide.commandlet.Commandlet}.
174
   *
175
   * @param silent - {@code true} if called recursively to suppress verbose logging, {@code false} otherwise.
176
   * @return {@code true} if the tool was newly installed, {@code false} if the tool was already installed before and nothing has changed.
177
   */
178
  public boolean install(boolean silent) {
179

180
    return doInstall(silent);
4✔
181
  }
182

183
  /**
184
   * Installs or updates the managed {@link #getName() tool}.
185
   *
186
   * @param silent - {@code true} if called recursively to suppress verbose logging, {@code false} otherwise.
187
   * @return {@code true} if the tool was newly installed, {@code false} if the tool was already installed before and nothing has changed.
188
   */
189
  protected abstract boolean doInstall(boolean silent);
190

191
  /**
192
   * This method is called after the tool has been newly installed or updated to a new version.
193
   */
194
  protected void postInstall() {
195

196
    // nothing to do by default
197
  }
1✔
198

199
  /**
200
   * @return {@code true} to extract (unpack) the downloaded binary file, {@code false} otherwise.
201
   */
202
  protected boolean isExtract() {
203

204
    return true;
2✔
205
  }
206

207
  /**
208
   * @return the {@link MacOsHelper} instance.
209
   */
210
  protected MacOsHelper getMacOsHelper() {
211

212
    if (this.macOsHelper == null) {
3✔
213
      this.macOsHelper = new MacOsHelper(this.context);
7✔
214
    }
215
    return this.macOsHelper;
3✔
216
  }
217

218
  /**
219
   * @return the currently installed {@link VersionIdentifier version} of this tool or {@code null} if not installed.
220
   */
221
  public abstract VersionIdentifier getInstalledVersion();
222

223
  /**
224
   * @return the installed edition of this tool or {@code null} if not installed.
225
   */
226
  public abstract String getInstalledEdition();
227

228
  /**
229
   * Uninstalls the {@link #getName() tool}.
230
   */
231
  public abstract void uninstall();
232

233
  /**
234
   * List the available editions of this tool.
235
   */
236
  public void listEditions() {
237

238
    List<String> editions = this.context.getUrls().getSortedEditions(getName());
7✔
239
    for (String edition : editions) {
10✔
240
      this.context.info(edition);
4✔
241
    }
1✔
242
  }
1✔
243

244
  /**
245
   * List the available versions of this tool.
246
   */
247
  public void listVersions() {
248

249
    List<VersionIdentifier> versions = this.context.getUrls().getSortedVersions(getName(), getEdition());
9✔
250
    for (VersionIdentifier vi : versions) {
10✔
251
      this.context.info(vi.toString());
5✔
252
    }
1✔
253
  }
1✔
254

255
  /**
256
   * Sets the tool version in the environment variable configuration file.
257
   *
258
   * @param version the version (pattern) to set.
259
   */
260
  public void setVersion(String version) {
261

262
    if ((version == null) || version.isBlank()) {
×
263
      throw new IllegalStateException("Version has to be specified!");
×
264
    }
265
    VersionIdentifier configuredVersion = VersionIdentifier.of(version);
×
266
    if (!configuredVersion.isPattern() && !configuredVersion.isValid()) {
×
267
      this.context.warning("Version {} seems to be invalid", version);
×
268
    }
269
    setVersion(configuredVersion, true);
×
270
  }
×
271

272
  /**
273
   * Sets the tool version in the environment variable configuration file.
274
   *
275
   * @param version the version to set. May also be a {@link VersionIdentifier#isPattern() version pattern}.
276
   * @param hint - {@code true} to print the installation hint, {@code false} otherwise.
277
   */
278
  public void setVersion(VersionIdentifier version, boolean hint) {
279

280
    String edition = getEdition();
3✔
281
    this.context.getUrls().getVersionFolder(tool, edition, version); // CliException is thrown if the version is not existing
9✔
282

283
    EnvironmentVariables variables = this.context.getVariables();
4✔
284
    EnvironmentVariables settingsVariables = variables.getByType(EnvironmentVariablesType.SETTINGS);
4✔
285
    String name = EnvironmentVariables.getToolVersionVariable(this.tool);
4✔
286
    VersionIdentifier resolvedVersion = this.context.getUrls().getVersion(this.tool, edition, version);
9✔
287
    if (version.isPattern()) {
3!
288
      this.context.debug("Resolved version {} to {} for tool {}/{}", version, resolvedVersion, this.tool, edition);
×
289
    }
290
    settingsVariables.set(name, resolvedVersion.toString(), false);
7✔
291
    settingsVariables.save();
2✔
292
    this.context.info("{}={} has been set in {}", name, version, settingsVariables.getSource());
19✔
293
    EnvironmentVariables declaringVariables = variables.findVariable(name);
4✔
294
    if ((declaringVariables != null) && (declaringVariables != settingsVariables)) {
5!
295
      this.context.warning("The variable {} is overridden in {}. Please remove the overridden declaration in order to make the change affect.", name,
×
296
          declaringVariables.getSource());
×
297
    }
298
    if (hint) {
2✔
299
      this.context.info("To install that version call the following command:");
4✔
300
      this.context.info("ide install {}", this.tool);
11✔
301
    }
302
  }
1✔
303

304
  /**
305
   * Sets the tool edition in the environment variable configuration file.
306
   *
307
   * @param edition the edition to set.
308
   */
309
  public void setEdition(String edition) {
310

311
    setEdition(edition, true);
4✔
312
  }
1✔
313

314
  /**
315
   * Sets the tool edition in the environment variable configuration file.
316
   *
317
   * @param edition the edition to set
318
   * @param hint - {@code true} to print the installation hint, {@code false} otherwise.
319
   */
320
  public void setEdition(String edition, boolean hint) {
321

322
    if ((edition == null) || edition.isBlank()) {
5!
323
      throw new IllegalStateException("Edition has to be specified!");
×
324
    }
325

326
    if (!Files.exists(this.context.getUrls().getEdition(getName(), edition).getPath())) {
12!
327
      this.context.warning("Edition {} seems to be invalid", edition);
10✔
328

329
    }
330
    EnvironmentVariables variables = this.context.getVariables();
4✔
331
    EnvironmentVariables settingsVariables = variables.getByType(EnvironmentVariablesType.SETTINGS);
4✔
332
    String name = EnvironmentVariables.getToolEditionVariable(this.tool);
4✔
333
    settingsVariables.set(name, edition, false);
6✔
334
    settingsVariables.save();
2✔
335

336
    this.context.info("{}={} has been set in {}", name, edition, settingsVariables.getSource());
19✔
337
    EnvironmentVariables declaringVariables = variables.findVariable(name);
4✔
338
    if ((declaringVariables != null) && (declaringVariables != settingsVariables)) {
5!
339
      this.context.warning("The variable {} is overridden in {}. Please remove the overridden declaration in order to make the change affect.", name,
×
340
          declaringVariables.getSource());
×
341
    }
342
    if (hint) {
2!
343
      this.context.info("To install that edition call the following command:");
4✔
344
      this.context.info("ide install {}", this.tool);
11✔
345
    }
346
  }
1✔
347

348
  /**
349
   * Runs the tool's help command to provide the user with usage information.
350
   */
351
  @Override
352
  public void printHelp(NlsBundle bundle) {
353

354
    super.printHelp(bundle);
3✔
355
    String toolHelpArgs = getToolHelpArguments();
3✔
356
    if (toolHelpArgs != null && getInstalledVersion() != null) {
5!
357
      ProcessContext pc = this.context.newProcess().errorHandling(ProcessErrorHandling.WARNING)
6✔
358
          .executable(Path.of(getBinaryName())).addArgs(toolHelpArgs);
13✔
359
      pc.run(ProcessMode.DEFAULT);
4✔
360
    }
361
  }
1✔
362

363
  /**
364
   * @return the tool's specific help command. Usually help, --help or -h. Return null if not applicable.
365
   */
366
  public String getToolHelpArguments() {
367

368
    return null;
×
369
  }
370
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc