Skip to content
2 changes: 2 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ This file documents all notable changes to https://github.com/devonfw/IDEasy[IDE

Release with new features and bugfixes:

* https://github.com/devonfw/IDEasy/issues/2286[#2286]: Fix SystemPath.findBinary to search extraPathEntries


The full list of changes for this release can be found in https://github.com/devonfw/IDEasy/milestone/49?closed=1[milestone 2026.08.002].

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,12 @@ public Path findBinary(Path toolPath, Predicate<Path> filter) {
String fileName = toolPath.getFileName().toString();

if (parent == null) {
for (Path path : this.extraPathEntries) {
Path binaryPath = findBinaryInOrder(path, fileName);
if (binaryPath != null && filter.test(binaryPath)) {
return binaryPath;
}
}
for (Path path : this.tool2pathMap.values()) {
Path binaryPath = findBinaryInOrder(path, fileName);
if (binaryPath != null && filter.test(binaryPath)) {
Expand Down
48 changes: 48 additions & 0 deletions cli/src/test/java/com/devonfw/tools/ide/common/SystemPathTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.devonfw.tools.ide.common;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -143,6 +145,52 @@ void testFindBinaryFindsNothingWithoutFilter() {
assertThat(result).isEqualTo(test);
}

@Test
void testFindBinaryFindsBinaryInExtraPathEntries() throws IOException {
// arrange
IdeTestContext context = newContext(PROJECT_BASIC);
Path binDir = context.getIdeHome().resolve("scratch-bin");
Files.createDirectories(binDir);
// create a plain binary name (no extension) so it works on both Linux and Windows
Path fakeToolFile = binDir.resolve("faketool");
Files.writeString(fakeToolFile, "@echo hi");

// empty PATH and no software folder, so tool2pathMap and paths stay empty
SystemPath base = new SystemPath(context, "", null, null, ';', List.of());
SystemPath merged = base.withPath(null, List.of(binDir));

// assert
assertThat(merged.toString()).contains(binDir.toString());
Path resolved = merged.findBinary(Path.of("faketool"));
Comment thread
krystynaShatkovska marked this conversation as resolved.
assertThat(resolved).isNotEqualTo(Path.of("faketool"));
assertThat(resolved).isEqualTo(fakeToolFile);
}

@Test
void testFindBinaryExtraPathEntriesWinsOverTool2pathMap() throws IOException {
// arrange - create two directories, both with a binary named "mytool"
// tool2pathMap collects subdirectories of softwarePath, so mytool must be a subdirectory
IdeTestContext context = newContext(PROJECT_BASIC);
Path toolDir = context.getIdeHome().resolve("software-tool");
Files.createDirectories(toolDir);
Path mytoolInToolDir = toolDir.resolve("mytool");
Files.createDirectories(mytoolInToolDir);
Files.writeString(mytoolInToolDir.resolve("mytool"), "tool-version");

Path extraDir = context.getIdeHome().resolve("extra-path");
Files.createDirectories(extraDir);
Files.writeString(extraDir.resolve("mytool"), "extra-version");

// tool2pathMap has "software-tool" (mytool is a subdirectory → registered), extraPathEntries has "extraDir"
SystemPath base = new SystemPath(context, "", null, toolDir, ';', List.of());
SystemPath merged = base.withPath(null, List.of(extraDir));

// assert - findBinary should return the one from extraPathEntries, NOT from tool2pathMap
Path resolved = merged.findBinary(Path.of("mytool"));
assertThat(resolved).isEqualTo(extraDir.resolve("mytool"));
assertThat(resolved).isNotEqualTo(mytoolInToolDir.resolve("mytool"));
}

@Test
void testConstructorNormalizesPathEntryWithControlCharactersAndKeepsIt() {
// arrange
Expand Down