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

devonfw / IDEasy / 9818906813

06 Jul 2024 11:28AM UTC coverage: 61.598% (-0.2%) from 61.755%
9818906813

Pull #453

github

web-flow
Merge b8ff8f16e into 09abbeb67
Pull Request #453: #451: mac gatekeeper

1990 of 3551 branches covered (56.04%)

Branch coverage included in aggregate %.

5278 of 8248 relevant lines covered (63.99%)

2.8 hits per line

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

66.2
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.url.model.folder.UrlEdition;
16
import com.devonfw.tools.ide.version.VersionIdentifier;
17

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

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

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

31
  private final Set<Tag> tags;
32

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

36
  private MacOsHelper macOsHelper;
37

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

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

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

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

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

69
    return this.tool;
3✔
70
  }
71

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

77
    return this.tool;
3✔
78
  }
79

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

83
    return this.tags;
×
84
  }
85

86
  @Override
87
  public void run() {
88

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

205
    return true;
2✔
206
  }
207

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

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

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

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

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

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

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

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

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

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

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

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

281
    String edition = getEdition();
3✔
282

283
    EnvironmentVariables variables = this.context.getVariables();
4✔
284
    EnvironmentVariables settingsVariables = variables.getByType(EnvironmentVariablesType.SETTINGS);
4✔
285
    String versionVariableName = EnvironmentVariables.getToolVersionVariable(this.tool);
4✔
286
    VersionIdentifier resolvedVersion = this.context.getUrls().getResolvedVersion(this.tool, edition, version).getVersionIdentifier();
10✔
287
    if (version.isPattern()) {
3!
288
      this.context.debug("Resolved version {} to {} for tool {}/{}", version, resolvedVersion, this.tool, edition);
×
289
    }
290
    settingsVariables.set(versionVariableName, version.toString(), false);
7✔
291
    settingsVariables.save();
2✔
292
    this.context.info("{}={} has been set in {}", versionVariableName, version, settingsVariables.getSource());
19✔
293
    EnvironmentVariables declaringVariables = variables.findVariable(versionVariableName);
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.", versionVariableName,
×
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);
×
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