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

devonfw / IDEasy / 25490918517

07 May 2026 10:40AM UTC coverage: 70.765% (+0.02%) from 70.741%
25490918517

Pull #1900

github

web-flow
Merge 8446e0ac8 into fd215c395
Pull Request #1900: #1886 fix npm based commandlet shows wrong tool version

4408 of 6878 branches covered (64.09%)

Branch coverage included in aggregate %.

11357 of 15400 relevant lines covered (73.75%)

3.12 hits per line

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

84.62
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.Files;
4
import java.nio.file.Path;
5
import java.util.List;
6
import java.util.Set;
7

8
import org.slf4j.Logger;
9
import org.slf4j.LoggerFactory;
10

11
import com.devonfw.tools.ide.common.Tag;
12
import com.devonfw.tools.ide.context.IdeContext;
13
import com.devonfw.tools.ide.process.ProcessContext;
14
import com.devonfw.tools.ide.process.ProcessErrorHandling;
15
import com.devonfw.tools.ide.process.ProcessMode;
16
import com.devonfw.tools.ide.process.ProcessResult;
17
import com.devonfw.tools.ide.tool.LocalToolCommandlet;
18
import com.devonfw.tools.ide.tool.PackageManagerRequest;
19
import com.devonfw.tools.ide.tool.node.NodeBasedCommandlet;
20
import com.devonfw.tools.ide.tool.repository.ToolRepository;
21
import com.devonfw.tools.ide.version.VersionIdentifier;
22

23
/**
24
 * {@link LocalToolCommandlet} for tools based on <a href="https://www.npmjs.com/">npm</a>.
25
 */
26
public abstract class NpmBasedCommandlet extends NodeBasedCommandlet<Npm> {
27

28
  private static final Logger LOG = LoggerFactory.getLogger(NpmBasedCommandlet.class);
4✔
29

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

39
    super(context, tool, tags);
5✔
40
  }
1✔
41

42
  @Override
43
  protected Class<Npm> getPackageManagerClass() {
44

45
    return Npm.class;
2✔
46
  }
47

48
  @Override
49
  public ToolRepository getToolRepository() {
50

51
    return this.context.getNpmRepository();
4✔
52
  }
53

54
  /**
55
   * Override to ignore the toolPath parameter and use npm package manager to detect the actual installed version of the tool.
56
   *
57
   * @param toolPath the installation {@link Path} where to find the version file.
58
   * @return the installed version or null if not installed.
59
   */
60
  @Override
61
  protected VersionIdentifier getInstalledVersion(Path toolPath) {
62
    return computeInstalledVersion();
3✔
63
  }
64

65
  @Override
66
  protected VersionIdentifier computeInstalledVersion() {
67
    return runPackageManagerGetInstalledVersion(getPackageName());
5✔
68
  }
69

70
  private VersionIdentifier runPackageManagerGetInstalledVersion(String npmPackage) {
71
    if (!Files.isDirectory(this.context.getSoftwarePath().resolve("node"))) {
9✔
72
      LOG.trace("Since node is not installed, also package {} for tool {} cannot be installed.", npmPackage, this.tool);
6✔
73
      return null;
2✔
74
    }
75
    PackageManagerRequest request = new PackageManagerRequest("list", npmPackage).addArg("list").addArg("-g").addArg(npmPackage).addArg("--depth=0")
14✔
76
        .setProcessMode(ProcessMode.DEFAULT_CAPTURE);
2✔
77
    ProcessContext pc = this.context.newProcess().errorHandling(ProcessErrorHandling.THROW_CLI)
6✔
78
        .withExitCodeAcceptor(rc -> true); // if the tool is not installed npm list will end with exit code 1
4✔
79
    request.setProcessContext(pc);
4✔
80
    ProcessResult result = runPackageManager(request);
4✔
81
    if (result.isSuccessful()) {
3!
82
      List<String> versions = result.getOut();
3✔
83
      String parsedVersion = null;
2✔
84
      for (String version : versions) {
10!
85
        if (version.contains(npmPackage)) {
4✔
86
          parsedVersion = version.replaceAll(".*" + npmPackage + "@", "");
6✔
87
          break;
1✔
88
        }
89
      }
1✔
90
      if (parsedVersion != null) {
2!
91
        return VersionIdentifier.of(parsedVersion);
3✔
92
      }
93
    } else {
×
94
      LOG.debug("The npm package {} for tool {} is not installed.", npmPackage, this.tool);
×
95
    }
96
    return null;
×
97
  }
98

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