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

devonfw / IDEasy / 17759606740

16 Sep 2025 08:24AM UTC coverage: 68.656% (-0.03%) from 68.69%
17759606740

push

github

web-flow
introduce CachedValue to prevent overhead of repeated process exectuion (#1489)

3418 of 5443 branches covered (62.8%)

Branch coverage included in aggregate %.

8914 of 12519 relevant lines covered (71.2%)

3.13 hits per line

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

62.75
cli/src/main/java/com/devonfw/tools/ide/tool/npm/NpmBasedCommandlet.java
1
package com.devonfw.tools.ide.tool.npm;
2

3
import java.nio.file.Path;
4
import java.util.List;
5
import java.util.Set;
6

7
import com.devonfw.tools.ide.cache.CachedValue;
8
import com.devonfw.tools.ide.common.Tag;
9
import com.devonfw.tools.ide.context.IdeContext;
10
import com.devonfw.tools.ide.process.ProcessContext;
11
import com.devonfw.tools.ide.process.ProcessErrorHandling;
12
import com.devonfw.tools.ide.process.ProcessMode;
13
import com.devonfw.tools.ide.process.ProcessResult;
14
import com.devonfw.tools.ide.tool.LocalToolCommandlet;
15
import com.devonfw.tools.ide.tool.repository.ToolRepository;
16
import com.devonfw.tools.ide.version.VersionIdentifier;
17

18
/**
19
 * {@link LocalToolCommandlet} for tools based on <a href="https://www.npmjs.com/">npm</a>.
20
 */
21
public abstract class NpmBasedCommandlet extends LocalToolCommandlet {
22

23
  private final CachedValue<VersionIdentifier> installedVersion;
24

25
  /**
26
   * The constructor.
27
   *
28
   * @param context the {@link IdeContext}.
29
   * @param tool the {@link #getName() tool name}.
30
   * @param tags the {@link #getTags() tags} classifying the tool. Should be created via {@link Set#of(Object) Set.of} method.
31
   */
32
  public NpmBasedCommandlet(IdeContext context, String tool, Set<Tag> tags) {
33

34
    super(context, tool, tags);
5✔
35
    this.installedVersion = new CachedValue<>(() -> runNpmGetInstalledPackageVersion(getNpmPackage()));
12✔
36
  }
1✔
37

38
  @Override
39
  protected boolean isIgnoreSoftwareRepo() {
40

41
    // node and node.js are messy - see https://github.com/devonfw/IDEasy/issues/352
42
    return true;
2✔
43
  }
44

45
  /**
46
   * @return the package of this tool from the NPM registry.
47
   */
48
  protected abstract String getNpmPackage();
49

50
  @Override
51
  public Path getToolPath() {
52

53
    Path toolPath = this.context.getSoftwarePath().resolve("node");
6✔
54
    if (!this.context.getSystemInfo().isWindows()) {
5✔
55
      toolPath = toolPath.resolve("bin");
4✔
56
    }
57
    return toolPath;
2✔
58
  }
59

60
  protected VersionIdentifier runNpmGetInstalledPackageVersion(String npmPackage) {
61
    ProcessResult result = runNpm(ProcessMode.DEFAULT_CAPTURE, ProcessErrorHandling.NONE, "list", "-g", npmPackage, "--depth=0");
23✔
62
    if (result.isSuccessful()) {
3!
63
      List<String> versions = result.getOut();
×
64
      String parsedVersion = null;
×
65
      for (String version : versions) {
×
66
        if (version.contains(npmPackage)) {
×
67
          parsedVersion = version.replaceAll(".*" + npmPackage + "@", "");
×
68
          break;
×
69
        }
70
      }
×
71
      if (parsedVersion != null) {
×
72
        return VersionIdentifier.of(parsedVersion);
×
73
      }
74
    } else {
×
75
      this.context.debug("The npm package {} for tool {} is not installed.", npmPackage, this.tool);
15✔
76
    }
77
    return null;
2✔
78
  }
79

80
  @Override
81
  public VersionIdentifier getInstalledVersion() {
82

83
    return this.installedVersion.get();
5✔
84
  }
85

86
  @Override
87
  public String getInstalledEdition() {
88

89
    if (getInstalledVersion() != null) {
3!
90
      return this.tool;
×
91
    }
92
    return null;
2✔
93
  }
94

95
  @Override
96
  protected void performToolInstallation(ToolRepository toolRepository, VersionIdentifier resolvedVersion, Path installationPath, String edition,
97
      ProcessContext processContext) {
98

99
    // runNpmUninstall(getNpmPackage()); // first uninstall a previously installed version
100
    runNpmInstall(getNpmPackage() + "@" + resolvedVersion);
8✔
101
    this.installedVersion.invalidate();
3✔
102
  }
1✔
103

104
  @Override
105
  protected void performUninstall(Path toolPath) {
106

107
    runNpmUninstall(getNpmPackage());
4✔
108
    this.installedVersion.invalidate();
3✔
109
  }
1✔
110

111
  /**
112
   * Performs a global npm uninstall.
113
   *
114
   * @param npmPackage the npm package to uninstall.
115
   */
116
  protected void runNpmUninstall(String npmPackage) {
117
    runNpm("uninstall", "-g", npmPackage).failOnError();
17✔
118
  }
1✔
119

120
  /**
121
   * Performs a global npm install.
122
   *
123
   * @param npmPackage the npm package to install.
124
   * @return the {@link ProcessResult} of the npm execution.
125
   */
126
  protected ProcessResult runNpmInstall(String npmPackage) {
127

128
    return runNpm("install", "-g", npmPackage);
17✔
129
  }
130

131
  private ProcessResult runNpm(String... args) {
132

133
    return runNpm(ProcessMode.DEFAULT, ProcessErrorHandling.THROW_CLI, args);
6✔
134
  }
135

136
  private ProcessResult runNpm(ProcessMode processMode, ProcessErrorHandling errorHandling, String... args) {
137

138
    ProcessContext pc = this.context.newProcess().errorHandling(errorHandling);
6✔
139
    Npm npm = this.context.getCommandletManager().getCommandlet(Npm.class);
7✔
140
    return npm.runTool(processMode, null, pc, args);
7✔
141
  }
142

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