From 808962f580e6e209d86855670e4db1361343fdab Mon Sep 17 00:00:00 2001 From: attiasas Date: Thu, 16 Apr 2026 13:08:05 +0300 Subject: [PATCH 1/9] Support WSL --- .../jfrog/ide/common/npm/NpmTreeBuilder.java | 78 +++++++++++++++++-- .../com/jfrog/ide/common/utils/WslUtils.java | 57 ++++++++++++++ .../ide/common/yarn/YarnComponentUpdater.java | 3 +- .../com/jfrog/ide/common/yarn/YarnDriver.java | 28 +++++-- .../ide/common/yarn/YarnTreeBuilder.java | 5 +- 5 files changed, 158 insertions(+), 13 deletions(-) create mode 100644 src/main/java/com/jfrog/ide/common/utils/WslUtils.java diff --git a/src/main/java/com/jfrog/ide/common/npm/NpmTreeBuilder.java b/src/main/java/com/jfrog/ide/common/npm/NpmTreeBuilder.java index 1bf16923..48c00655 100644 --- a/src/main/java/com/jfrog/ide/common/npm/NpmTreeBuilder.java +++ b/src/main/java/com/jfrog/ide/common/npm/NpmTreeBuilder.java @@ -2,16 +2,25 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectReader; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.collect.Lists; import com.jfrog.ide.common.deptree.DepTree; import com.jfrog.ide.common.deptree.DepTreeNode; import com.jfrog.ide.common.utils.Utils; +import com.jfrog.ide.common.utils.WslUtils; +import org.apache.commons.lang3.StringUtils; import org.jfrog.build.api.util.Log; +import org.jfrog.build.extractor.executor.CommandExecutor; +import org.jfrog.build.extractor.executor.CommandResults; import org.jfrog.build.extractor.npm.NpmDriver; import java.io.IOException; import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; /** @@ -21,14 +30,24 @@ */ public class NpmTreeBuilder { private static final ObjectMapper objectMapper = new ObjectMapper(); + private static final ObjectReader jsonReader = new ObjectMapper().reader(); private final NpmDriver npmDriver; + private final CommandExecutor wslExecutor; + private final boolean isWsl; private final Path projectDir; private final String descriptorFilePath; public NpmTreeBuilder(Path projectDir, String descriptorFilePath, Map env) { this.projectDir = projectDir; this.descriptorFilePath = descriptorFilePath; - this.npmDriver = new NpmDriver(env); + this.isWsl = WslUtils.isWslPath(projectDir); + if (isWsl) { + this.npmDriver = null; + this.wslExecutor = new CommandExecutor("wsl.exe", env); + } else { + this.npmDriver = new NpmDriver(env); + this.wslExecutor = null; + } } /** @@ -39,15 +58,16 @@ public NpmTreeBuilder(Path projectDir, String descriptorFilePath, Map nodes = new HashMap<>(); String packageId = getPackageId(prodResults); addDepTreeNodes(nodes, prodResults, packageId, "prod"); @@ -57,6 +77,54 @@ public DepTree buildTree(Log logger) throws IOException { return tree; } + /** + * Check whether npm is available, accounting for WSL projects. + * For WSL projects, npm is invoked through {@code wsl.exe}. + */ + private boolean isNpmInstalled() { + if (isWsl) { + try { + CommandResults results = wslExecutor.exeCommand(null, + Arrays.asList("--exec", "npm", "--version"), null, null); + return results.isOk() && !StringUtils.isBlank(results.getRes()); + } catch (Exception e) { + return false; + } + } + return npmDriver.isNpmInstalled(); + } + + /** + * Run {@code npm ls} and return the parsed JSON output. + * For WSL projects, the command is routed through {@code wsl.exe --cd --exec npm ...}. + */ + private JsonNode npmList(List extraArgs) throws IOException { + if (isWsl) { + String linuxPath = WslUtils.toLinuxPath(projectDir.toString()); + List args = new ArrayList<>(); + args.add("--cd"); + args.add(linuxPath); + args.add("--exec"); + args.add("npm"); + args.add("ls"); + args.add("--json"); + args.add("--all"); + args.addAll(extraArgs); + try { + CommandResults commandRes = wslExecutor.exeCommand(null, args, null, null); + String res = StringUtils.isBlank(commandRes.getRes()) ? "{}" : commandRes.getRes(); + JsonNode results = jsonReader.readTree(res); + if (!commandRes.isOk() && !results.has("problems")) { + ((ObjectNode) results).put("problems", commandRes.getErr()); + } + return results; + } catch (IOException | InterruptedException e) { + throw new IOException("npm ls failed via WSL", e); + } + } + return npmDriver.list(projectDir.toFile(), extraArgs); + } + private void addDepTreeNodes(Map nodes, JsonNode jsonDep, String depId, String scope) { DepTreeNode depNode; if (nodes.containsKey(depId)) { diff --git a/src/main/java/com/jfrog/ide/common/utils/WslUtils.java b/src/main/java/com/jfrog/ide/common/utils/WslUtils.java new file mode 100644 index 00000000..3e704fbf --- /dev/null +++ b/src/main/java/com/jfrog/ide/common/utils/WslUtils.java @@ -0,0 +1,57 @@ +package com.jfrog.ide.common.utils; + +import java.nio.file.Path; + +/** + * Utility methods for WSL (Windows Subsystem for Linux) path handling. + * On Windows, WSL filesystems are exposed as UNC paths under the wsl.localhost or wsl$ hosts. + */ +public class WslUtils { + // UNC-style prefixes used by Windows to expose WSL filesystems + private static final String WSL_LOCALHOST_PREFIX = "\\\\wsl.localhost\\"; + private static final String WSL_DOLLAR_PREFIX = "\\\\wsl$\\"; + + private WslUtils() { + } + + /** + * Returns true if the given path string refers to a WSL filesystem + * (i.e. it is a UNC path rooted at the wsl.localhost or wsl$ host). + */ + public static boolean isWslPath(String path) { + return path != null && (path.startsWith(WSL_LOCALHOST_PREFIX) || path.startsWith(WSL_DOLLAR_PREFIX)); + } + + /** + * Returns true if the given {@link Path} refers to a WSL filesystem. + */ + public static boolean isWslPath(Path path) { + return path != null && isWslPath(path.toString()); + } + + /** + * Converts a Windows-style WSL UNC path to the equivalent Linux path inside WSL. + * The distro name (first UNC component after the host) is stripped, and + * backslashes are replaced with forward slashes. + * + * @param wslWindowsPath the Windows-style WSL path + * @return the Linux path, or the original string unchanged if it is not a WSL path + */ + public static String toLinuxPath(String wslWindowsPath) { + String withoutPrefix; + if (wslWindowsPath.startsWith(WSL_LOCALHOST_PREFIX)) { + withoutPrefix = wslWindowsPath.substring(WSL_LOCALHOST_PREFIX.length()); + } else if (wslWindowsPath.startsWith(WSL_DOLLAR_PREFIX)) { + withoutPrefix = wslWindowsPath.substring(WSL_DOLLAR_PREFIX.length()); + } else { + return wslWindowsPath; + } + // withoutPrefix is now: \ + // Strip the distro name (first path component) to obtain the Linux path. + int firstBackslash = withoutPrefix.indexOf('\\'); + if (firstBackslash == -1) { + return "/"; // Path pointed at the distro root + } + return withoutPrefix.substring(firstBackslash).replace('\\', '/'); + } +} diff --git a/src/main/java/com/jfrog/ide/common/yarn/YarnComponentUpdater.java b/src/main/java/com/jfrog/ide/common/yarn/YarnComponentUpdater.java index 0bb13f54..84b8b8ba 100644 --- a/src/main/java/com/jfrog/ide/common/yarn/YarnComponentUpdater.java +++ b/src/main/java/com/jfrog/ide/common/yarn/YarnComponentUpdater.java @@ -1,6 +1,7 @@ package com.jfrog.ide.common.yarn; import com.jfrog.ide.common.updateversion.ComponentUpdater; +import com.jfrog.ide.common.utils.WslUtils; import org.jfrog.build.api.util.Log; import java.io.IOException; @@ -14,7 +15,7 @@ public class YarnComponentUpdater extends ComponentUpdater { public YarnComponentUpdater(Path projectDir, Log logger, Map env) { super(projectDir, logger); - this.yarnDriver = new YarnDriver(env); + this.yarnDriver = new YarnDriver(env, logger, WslUtils.isWslPath(projectDir)); } /** diff --git a/src/main/java/com/jfrog/ide/common/yarn/YarnDriver.java b/src/main/java/com/jfrog/ide/common/yarn/YarnDriver.java index d2d71d0d..2d269fd2 100644 --- a/src/main/java/com/jfrog/ide/common/yarn/YarnDriver.java +++ b/src/main/java/com/jfrog/ide/common/yarn/YarnDriver.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectReader; +import com.jfrog.ide.common.utils.WslUtils; import org.apache.commons.lang3.StringUtils; import org.jfrog.build.api.util.Log; import org.jfrog.build.api.util.NullLog; @@ -12,7 +13,6 @@ import java.io.File; import java.io.IOException; import java.util.*; -import java.util.stream.Collectors; import java.util.stream.Stream; /** @@ -22,13 +22,19 @@ public class YarnDriver { private static final ObjectReader jsonReader = new ObjectMapper().reader(); private final CommandExecutor commandExecutor; private final Log log; + protected final boolean useWsl; public YarnDriver(Map env) { - this(env, new NullLog()); + this(env, new NullLog(), false); } public YarnDriver(Map env, Log log) { - this.commandExecutor = new CommandExecutor("yarn", env); + this(env, log, false); + } + + public YarnDriver(Map env, Log log, boolean useWsl) { + this.useWsl = useWsl; + this.commandExecutor = useWsl ? new CommandExecutor("wsl.exe", env) : new CommandExecutor("yarn", env); this.log = log; } @@ -128,8 +134,20 @@ private CommandResults runCommand(File workingDirectory, String[] args) throws I } private CommandResults runCommand(File workingDirectory, String[] args, List extraArgs) throws IOException, InterruptedException { - List finalArgs = Stream.concat(Arrays.stream(args), extraArgs.stream()).collect(Collectors.toList()); - CommandResults commandRes = commandExecutor.exeCommand(workingDirectory, finalArgs, null, null); + List finalArgs = new ArrayList<>(); + File wdForExecutor = workingDirectory; + if (useWsl) { + // Route through wsl.exe. If a working directory is given, convert it to a Linux path via --cd. + if (workingDirectory != null) { + finalArgs.add("--cd"); + finalArgs.add(WslUtils.toLinuxPath(workingDirectory.getPath())); + } + finalArgs.add("--exec"); + finalArgs.add("yarn"); + wdForExecutor = null; // Working directory is handled by --cd above + } + Stream.concat(Arrays.stream(args), extraArgs.stream()).forEach(finalArgs::add); + CommandResults commandRes = commandExecutor.exeCommand(wdForExecutor, finalArgs, null, null); if (!commandRes.isOk()) { throw new IOException(commandRes.getErr() + commandRes.getRes()); } diff --git a/src/main/java/com/jfrog/ide/common/yarn/YarnTreeBuilder.java b/src/main/java/com/jfrog/ide/common/yarn/YarnTreeBuilder.java index 5736991a..f4fc9c84 100644 --- a/src/main/java/com/jfrog/ide/common/yarn/YarnTreeBuilder.java +++ b/src/main/java/com/jfrog/ide/common/yarn/YarnTreeBuilder.java @@ -5,6 +5,7 @@ import com.jfrog.ide.common.deptree.DepTree; import com.jfrog.ide.common.deptree.DepTreeNode; import com.jfrog.ide.common.nodes.subentities.ImpactTree; +import com.jfrog.ide.common.utils.WslUtils; import org.apache.commons.lang3.StringUtils; import org.jfrog.build.api.util.Log; @@ -29,7 +30,7 @@ public class YarnTreeBuilder { public YarnTreeBuilder(Path projectDir, String descriptorFilePath, Map env, Log log) { this.projectDir = projectDir; this.descriptorFilePath = descriptorFilePath; - this.yarnDriver = new YarnDriver(env, log); + this.yarnDriver = new YarnDriver(env, log, WslUtils.isWslPath(projectDir)); } /** @@ -40,7 +41,7 @@ public YarnTreeBuilder(Path projectDir, String descriptorFilePath, Map Date: Thu, 16 Apr 2026 13:16:42 +0300 Subject: [PATCH 2/9] Refine, add tests --- .../jfrog/ide/common/npm/NpmTreeBuilder.java | 32 +++++++---- .../com/jfrog/ide/common/utils/WslUtils.java | 13 ++++- .../ide/common/yarn/YarnComponentUpdater.java | 2 +- .../com/jfrog/ide/common/yarn/YarnDriver.java | 19 ++++++- .../ide/common/yarn/YarnTreeBuilder.java | 4 +- .../jfrog/ide/common/utils/WslUtilsTest.java | 55 +++++++++++++++++++ 6 files changed, 105 insertions(+), 20 deletions(-) create mode 100644 src/test/java/com/jfrog/ide/common/utils/WslUtilsTest.java diff --git a/src/main/java/com/jfrog/ide/common/npm/NpmTreeBuilder.java b/src/main/java/com/jfrog/ide/common/npm/NpmTreeBuilder.java index 48c00655..ea2bbf53 100644 --- a/src/main/java/com/jfrog/ide/common/npm/NpmTreeBuilder.java +++ b/src/main/java/com/jfrog/ide/common/npm/NpmTreeBuilder.java @@ -18,7 +18,6 @@ import java.io.IOException; import java.nio.file.Path; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -30,7 +29,7 @@ */ public class NpmTreeBuilder { private static final ObjectMapper objectMapper = new ObjectMapper(); - private static final ObjectReader jsonReader = new ObjectMapper().reader(); + private static final ObjectReader jsonReader = objectMapper.reader(); private final NpmDriver npmDriver; private final CommandExecutor wslExecutor; private final boolean isWsl; @@ -58,7 +57,6 @@ public NpmTreeBuilder(Path projectDir, String descriptorFilePath, Map args = wslNpmInvocationPrefix(); + args.add("--version"); + CommandResults results = wslExecutor.exeCommand(null, args, null, null); return results.isOk() && !StringUtils.isBlank(results.getRes()); } catch (Exception e) { return false; @@ -94,18 +93,27 @@ private boolean isNpmInstalled() { return npmDriver.isNpmInstalled(); } + /** + * Prefix arguments for {@code wsl.exe} so npm runs in the project directory inside WSL + * (same {@code --cd} context as {@link #npmList}). + */ + private List wslNpmInvocationPrefix() { + String linuxPath = WslUtils.toLinuxPath(projectDir.toString()); + List args = new ArrayList<>(); + args.add("--cd"); + args.add(linuxPath); + args.add("--exec"); + args.add("npm"); + return args; + } + /** * Run {@code npm ls} and return the parsed JSON output. * For WSL projects, the command is routed through {@code wsl.exe --cd --exec npm ...}. */ private JsonNode npmList(List extraArgs) throws IOException { if (isWsl) { - String linuxPath = WslUtils.toLinuxPath(projectDir.toString()); - List args = new ArrayList<>(); - args.add("--cd"); - args.add(linuxPath); - args.add("--exec"); - args.add("npm"); + List args = new ArrayList<>(wslNpmInvocationPrefix()); args.add("ls"); args.add("--json"); args.add("--all"); @@ -114,7 +122,7 @@ private JsonNode npmList(List extraArgs) throws IOException { CommandResults commandRes = wslExecutor.exeCommand(null, args, null, null); String res = StringUtils.isBlank(commandRes.getRes()) ? "{}" : commandRes.getRes(); JsonNode results = jsonReader.readTree(res); - if (!commandRes.isOk() && !results.has("problems")) { + if (!commandRes.isOk() && !results.has("problems") && results.isObject()) { ((ObjectNode) results).put("problems", commandRes.getErr()); } return results; diff --git a/src/main/java/com/jfrog/ide/common/utils/WslUtils.java b/src/main/java/com/jfrog/ide/common/utils/WslUtils.java index 3e704fbf..ab60ceac 100644 --- a/src/main/java/com/jfrog/ide/common/utils/WslUtils.java +++ b/src/main/java/com/jfrog/ide/common/utils/WslUtils.java @@ -14,12 +14,16 @@ public class WslUtils { private WslUtils() { } + private static boolean startsWithIgnoreCase(String s, String prefix) { + return s.length() >= prefix.length() && s.regionMatches(true, 0, prefix, 0, prefix.length()); + } + /** * Returns true if the given path string refers to a WSL filesystem * (i.e. it is a UNC path rooted at the wsl.localhost or wsl$ host). */ public static boolean isWslPath(String path) { - return path != null && (path.startsWith(WSL_LOCALHOST_PREFIX) || path.startsWith(WSL_DOLLAR_PREFIX)); + return path != null && (startsWithIgnoreCase(path, WSL_LOCALHOST_PREFIX) || startsWithIgnoreCase(path, WSL_DOLLAR_PREFIX)); } /** @@ -38,10 +42,13 @@ public static boolean isWslPath(Path path) { * @return the Linux path, or the original string unchanged if it is not a WSL path */ public static String toLinuxPath(String wslWindowsPath) { + if (wslWindowsPath == null) { + return null; + } String withoutPrefix; - if (wslWindowsPath.startsWith(WSL_LOCALHOST_PREFIX)) { + if (startsWithIgnoreCase(wslWindowsPath, WSL_LOCALHOST_PREFIX)) { withoutPrefix = wslWindowsPath.substring(WSL_LOCALHOST_PREFIX.length()); - } else if (wslWindowsPath.startsWith(WSL_DOLLAR_PREFIX)) { + } else if (startsWithIgnoreCase(wslWindowsPath, WSL_DOLLAR_PREFIX)) { withoutPrefix = wslWindowsPath.substring(WSL_DOLLAR_PREFIX.length()); } else { return wslWindowsPath; diff --git a/src/main/java/com/jfrog/ide/common/yarn/YarnComponentUpdater.java b/src/main/java/com/jfrog/ide/common/yarn/YarnComponentUpdater.java index 84b8b8ba..84ecce87 100644 --- a/src/main/java/com/jfrog/ide/common/yarn/YarnComponentUpdater.java +++ b/src/main/java/com/jfrog/ide/common/yarn/YarnComponentUpdater.java @@ -38,7 +38,7 @@ public String getVersionDelimiter() { @Override public boolean isDriverInstalled() { - return yarnDriver.isYarnInstalled(); + return yarnDriver.isYarnInstalled(projectDir.toFile()); } @Override diff --git a/src/main/java/com/jfrog/ide/common/yarn/YarnDriver.java b/src/main/java/com/jfrog/ide/common/yarn/YarnDriver.java index 2d269fd2..c7114b1a 100644 --- a/src/main/java/com/jfrog/ide/common/yarn/YarnDriver.java +++ b/src/main/java/com/jfrog/ide/common/yarn/YarnDriver.java @@ -22,7 +22,7 @@ public class YarnDriver { private static final ObjectReader jsonReader = new ObjectMapper().reader(); private final CommandExecutor commandExecutor; private final Log log; - protected final boolean useWsl; + private final boolean useWsl; public YarnDriver(Map env) { this(env, new NullLog(), false); @@ -38,10 +38,25 @@ public YarnDriver(Map env, Log log, boolean useWsl) { this.log = log; } + /** + * @return whether Yarn commands are executed via {@code wsl.exe} (WSL UNC project path). + */ + public boolean runsThroughWsl() { + return useWsl; + } + @SuppressWarnings("unused") public boolean isYarnInstalled() { + return isYarnInstalled(null); + } + + /** + * @param projectWorkingDirectory project root, or {@code null} for a global Yarn check (non-WSL only; + * WSL mode should pass the project directory so the check uses the same {@code --cd} as scans). + */ + public boolean isYarnInstalled(File projectWorkingDirectory) { try { - return !version(null).isEmpty(); + return !version(projectWorkingDirectory).isEmpty(); } catch (IOException | InterruptedException e) { return false; } diff --git a/src/main/java/com/jfrog/ide/common/yarn/YarnTreeBuilder.java b/src/main/java/com/jfrog/ide/common/yarn/YarnTreeBuilder.java index f4fc9c84..89c1a7d8 100644 --- a/src/main/java/com/jfrog/ide/common/yarn/YarnTreeBuilder.java +++ b/src/main/java/com/jfrog/ide/common/yarn/YarnTreeBuilder.java @@ -40,8 +40,8 @@ public YarnTreeBuilder(Path projectDir, String descriptorFilePath, Map Date: Thu, 16 Apr 2026 16:33:05 +0300 Subject: [PATCH 3/9] Improve Npm --- .../ide/common/npm/NpmComponentUpdater.java | 57 ++++++++++++++++++- .../com/jfrog/ide/common/utils/WslUtils.java | 33 +++++++++-- .../jfrog/ide/common/utils/WslUtilsTest.java | 3 + 3 files changed, 86 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/jfrog/ide/common/npm/NpmComponentUpdater.java b/src/main/java/com/jfrog/ide/common/npm/NpmComponentUpdater.java index 2e96ddf5..393b6ca1 100644 --- a/src/main/java/com/jfrog/ide/common/npm/NpmComponentUpdater.java +++ b/src/main/java/com/jfrog/ide/common/npm/NpmComponentUpdater.java @@ -1,12 +1,18 @@ package com.jfrog.ide.common.npm; import com.jfrog.ide.common.updateversion.ComponentUpdater; +import com.jfrog.ide.common.utils.WslUtils; +import org.apache.commons.lang3.StringUtils; import org.jfrog.build.api.util.Log; +import org.jfrog.build.extractor.executor.CommandExecutor; +import org.jfrog.build.extractor.executor.CommandResults; import org.jfrog.build.extractor.npm.NpmDriver; import java.io.IOException; import java.nio.file.Path; +import java.util.ArrayList; import java.util.Collections; +import java.util.List; import java.util.Map; /** @@ -19,10 +25,33 @@ public class NpmComponentUpdater extends ComponentUpdater { public static final String NPM_VERSION_DELIMITER = "@"; private final NpmDriver npmDriver; + private final CommandExecutor wslExecutor; + private final boolean isWsl; public NpmComponentUpdater(Path projectDir, Log logger, Map env) { super(projectDir, logger); - this.npmDriver = new NpmDriver(env); + this.isWsl = WslUtils.isWslPath(projectDir); + if (isWsl) { + this.npmDriver = null; + this.wslExecutor = new CommandExecutor("wsl.exe", env); + } else { + this.npmDriver = new NpmDriver(env); + this.wslExecutor = null; + } + } + + /** + * Prefix arguments for {@code wsl.exe} so npm runs in the project directory inside WSL + * (aligned with {@link NpmTreeBuilder}). + */ + private List wslNpmInvocationPrefix() { + String linuxPath = WslUtils.toLinuxPath(projectDir.toString()); + List args = new ArrayList<>(); + args.add("--cd"); + args.add(linuxPath); + args.add("--exec"); + args.add("npm"); + return args; } /** @@ -35,7 +64,21 @@ public NpmComponentUpdater(Path projectDir, Log logger, Map env) @Override public void run(String componentName, String componentVersion) throws IOException { super.run(componentName, componentVersion); - npmDriver.install(projectDir.toFile(), Collections.singletonList(this.componentFullName), this.logger); + if (isWsl) { + List args = new ArrayList<>(wslNpmInvocationPrefix()); + args.add("install"); + args.add(this.componentFullName); + try { + CommandResults res = wslExecutor.exeCommand(null, args, null, logger); + if (!res.isOk()) { + throw new IOException(StringUtils.defaultString(res.getErr()) + StringUtils.defaultString(res.getRes())); + } + } catch (IOException | InterruptedException e) { + throw new IOException("npm install failed via WSL", e); + } + } else { + npmDriver.install(projectDir.toFile(), Collections.singletonList(this.componentFullName), this.logger); + } } @Override @@ -45,6 +88,16 @@ public String getVersionDelimiter() { @Override public boolean isDriverInstalled() { + if (isWsl) { + try { + List args = new ArrayList<>(wslNpmInvocationPrefix()); + args.add("--version"); + CommandResults results = wslExecutor.exeCommand(null, args, null, null); + return results.isOk() && !StringUtils.isBlank(results.getRes()); + } catch (Exception e) { + return false; + } + } return npmDriver.isNpmInstalled(); } diff --git a/src/main/java/com/jfrog/ide/common/utils/WslUtils.java b/src/main/java/com/jfrog/ide/common/utils/WslUtils.java index ab60ceac..46eb505e 100644 --- a/src/main/java/com/jfrog/ide/common/utils/WslUtils.java +++ b/src/main/java/com/jfrog/ide/common/utils/WslUtils.java @@ -18,12 +18,34 @@ private static boolean startsWithIgnoreCase(String s, String prefix) { return s.length() >= prefix.length() && s.regionMatches(true, 0, prefix, 0, prefix.length()); } + /** + * Normalizes Windows extended-length UNC prefixes so WSL detection sees {@code \\wsl$\...} / {@code \\wsl.localhost\...}. + * Example: {@code \\?\UNC\wsl$\Ubuntu\home\...} becomes {@code \\wsl$\Ubuntu\home\...}. + */ + static String normalizePathStringForWsl(String path) { + if (path == null || path.isEmpty()) { + return path; + } + String p = path; + if (startsWithIgnoreCase(p, "\\\\?\\UNC\\")) { + return "\\\\" + p.substring("\\\\?\\UNC\\".length()); + } + if (startsWithIgnoreCase(p, "\\\\?\\")) { + return p.substring("\\\\?\\".length()); + } + return p; + } + /** * Returns true if the given path string refers to a WSL filesystem * (i.e. it is a UNC path rooted at the wsl.localhost or wsl$ host). */ public static boolean isWslPath(String path) { - return path != null && (startsWithIgnoreCase(path, WSL_LOCALHOST_PREFIX) || startsWithIgnoreCase(path, WSL_DOLLAR_PREFIX)); + if (path == null) { + return false; + } + String normalized = normalizePathStringForWsl(path); + return startsWithIgnoreCase(normalized, WSL_LOCALHOST_PREFIX) || startsWithIgnoreCase(normalized, WSL_DOLLAR_PREFIX); } /** @@ -45,11 +67,12 @@ public static String toLinuxPath(String wslWindowsPath) { if (wslWindowsPath == null) { return null; } + String p = normalizePathStringForWsl(wslWindowsPath); String withoutPrefix; - if (startsWithIgnoreCase(wslWindowsPath, WSL_LOCALHOST_PREFIX)) { - withoutPrefix = wslWindowsPath.substring(WSL_LOCALHOST_PREFIX.length()); - } else if (startsWithIgnoreCase(wslWindowsPath, WSL_DOLLAR_PREFIX)) { - withoutPrefix = wslWindowsPath.substring(WSL_DOLLAR_PREFIX.length()); + if (startsWithIgnoreCase(p, WSL_LOCALHOST_PREFIX)) { + withoutPrefix = p.substring(WSL_LOCALHOST_PREFIX.length()); + } else if (startsWithIgnoreCase(p, WSL_DOLLAR_PREFIX)) { + withoutPrefix = p.substring(WSL_DOLLAR_PREFIX.length()); } else { return wslWindowsPath; } diff --git a/src/test/java/com/jfrog/ide/common/utils/WslUtilsTest.java b/src/test/java/com/jfrog/ide/common/utils/WslUtilsTest.java index c43b18d1..3df12132 100644 --- a/src/test/java/com/jfrog/ide/common/utils/WslUtilsTest.java +++ b/src/test/java/com/jfrog/ide/common/utils/WslUtilsTest.java @@ -19,6 +19,8 @@ public Object[][] wslPathDetection() { {"\\\\WSL$\\Ubuntu\\home\\user\\repo", true}, {"\\\\wsl.localhost\\Ubuntu\\home\\user\\repo", true}, {"\\\\WSL.LOCALHOST\\Ubuntu\\home\\user\\repo", true}, + {"\\\\?\\UNC\\wsl$\\Ubuntu\\home\\user\\repo", true}, + {"\\\\?\\UNC\\WSL.LOCALHOST\\Ubuntu\\home\\user\\repo", true}, }; } @@ -45,6 +47,7 @@ public Object[][] toLinuxPathCases() { {"\\\\WSL$\\Ubuntu\\home\\user\\app", "/home/user/app"}, {"\\\\wsl.localhost\\Ubuntu\\home\\user\\app", "/home/user/app"}, {"\\\\wsl$\\Ubuntu", "/"}, + {"\\\\?\\UNC\\wsl$\\Ubuntu\\home\\user\\app", "/home/user/app"}, }; } From fb23238b5cfc1f47449ad149892ff893855b4942 Mon Sep 17 00:00:00 2001 From: attiasas Date: Sun, 19 Apr 2026 15:09:36 +0300 Subject: [PATCH 4/9] Move WSL utils to build, support go as well --- build.gradle | 3 +- .../ide/common/go/GoComponentUpdater.java | 3 +- .../ide/common/go/GoScanWorkspaceCreator.java | 23 ++++- .../jfrog/ide/common/go/GoTreeBuilder.java | 9 +- .../ide/common/npm/NpmComponentUpdater.java | 2 +- .../jfrog/ide/common/npm/NpmTreeBuilder.java | 2 +- .../com/jfrog/ide/common/utils/WslUtils.java | 87 ------------------- .../ide/common/yarn/YarnComponentUpdater.java | 2 +- .../com/jfrog/ide/common/yarn/YarnDriver.java | 2 +- .../ide/common/yarn/YarnTreeBuilder.java | 2 +- .../jfrog/ide/common/utils/WslUtilsTest.java | 58 ------------- 11 files changed, 35 insertions(+), 158 deletions(-) delete mode 100644 src/main/java/com/jfrog/ide/common/utils/WslUtils.java delete mode 100644 src/test/java/com/jfrog/ide/common/utils/WslUtilsTest.java diff --git a/build.gradle b/build.gradle index 6f0a3a9d..b03b1e85 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,8 @@ repositories { } } -def buildInfoVersion = '2.41.13' +// Keep in sync with published org.jfrog.buildinfo extractors (includes WslUtils in build-info-extractor + GoDriver WSL mode). +def buildInfoVersion = '2.43.x-SNAPSHOT' dependencies { implementation group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-yaml', version: '2.15.2' implementation group: 'org.jfrog.buildinfo', name: 'build-info-extractor-npm', version: buildInfoVersion diff --git a/src/main/java/com/jfrog/ide/common/go/GoComponentUpdater.java b/src/main/java/com/jfrog/ide/common/go/GoComponentUpdater.java index 08edfa5a..68e60892 100644 --- a/src/main/java/com/jfrog/ide/common/go/GoComponentUpdater.java +++ b/src/main/java/com/jfrog/ide/common/go/GoComponentUpdater.java @@ -3,6 +3,7 @@ import com.jfrog.ide.common.updateversion.ComponentUpdater; import org.jfrog.build.api.util.Log; import org.jfrog.build.extractor.go.GoDriver; +import org.jfrog.build.extractor.util.WslUtils; import java.io.IOException; import java.nio.file.Path; @@ -19,7 +20,7 @@ public class GoComponentUpdater extends ComponentUpdater { public GoComponentUpdater(Path projectDir, Log logger, Map env, String executablePath) { super(projectDir, logger); - this.goDriver = new GoDriver(executablePath, env, projectDir.toFile(), logger); + this.goDriver = new GoDriver(executablePath, env, projectDir.toFile(), logger, WslUtils.isWslPath(projectDir)); } /** diff --git a/src/main/java/com/jfrog/ide/common/go/GoScanWorkspaceCreator.java b/src/main/java/com/jfrog/ide/common/go/GoScanWorkspaceCreator.java index ba0e65de..d228435b 100644 --- a/src/main/java/com/jfrog/ide/common/go/GoScanWorkspaceCreator.java +++ b/src/main/java/com/jfrog/ide/common/go/GoScanWorkspaceCreator.java @@ -4,6 +4,7 @@ import org.apache.commons.lang3.exception.ExceptionUtils; import org.jfrog.build.api.util.Log; import org.jfrog.build.extractor.go.GoDriver; +import org.jfrog.build.extractor.util.WslUtils; import java.io.IOException; import java.nio.file.FileVisitResult; @@ -11,6 +12,9 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.util.Map; import java.util.stream.Stream; @@ -27,13 +31,16 @@ public class GoScanWorkspaceCreator implements FileVisitor { private final Path sourceDir; private final Path targetDir; private final Log logger; + private final boolean runGoThroughWsl; private static final String[] EXCLUDED_DIRS = new String[]{".git", ".idea", ".vscode"}; - public GoScanWorkspaceCreator(String executablePath, Path sourceDir, Path targetDir, Path goModAbsDir, Map env, Log logger) { - this.goDriver = new GoDriver(executablePath, env, goModAbsDir.toFile(), logger); + public GoScanWorkspaceCreator(String executablePath, Path sourceDir, Path targetDir, Path goModAbsDir, + Map env, Log logger, boolean runGoThroughWsl) { + this.goDriver = new GoDriver(executablePath, env, goModAbsDir.toFile(), logger, runGoThroughWsl); this.sourceDir = sourceDir; this.targetDir = targetDir; this.logger = logger; + this.runGoThroughWsl = runGoThroughWsl; } @Override @@ -73,7 +80,17 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO if (fileName.equals("go.mod")) { Path targetGoMod = targetDir.resolve(sourceDir.relativize(file)); Files.copy(file, targetGoMod); - goDriver.runCmd("run . -goModPath=" + targetGoMod.toAbsolutePath() + " -wd=" + sourceDir.toAbsolutePath(), true); + if (runGoThroughWsl) { + String goModPathArg = WslUtils.windowsLocalPathToWslMount(targetGoMod.toAbsolutePath().toString()); + String sourceAbs = sourceDir.toAbsolutePath().toString(); + String wdArg = WslUtils.isWslPath(sourceAbs) + ? WslUtils.toLinuxPath(sourceAbs) + : WslUtils.windowsLocalPathToWslMount(sourceAbs); + List args = new ArrayList<>(Arrays.asList("run", ".", "-goModPath=" + goModPathArg, "-wd=" + wdArg)); + goDriver.runCmd(args, true); + } else { + goDriver.runCmd("run . -goModPath=" + targetGoMod.toAbsolutePath() + " -wd=" + sourceDir.toAbsolutePath(), true); + } return FileVisitResult.CONTINUE; } // Files other than go.mod and *.go files are not necessary to build the dependency tree of used Go packages. diff --git a/src/main/java/com/jfrog/ide/common/go/GoTreeBuilder.java b/src/main/java/com/jfrog/ide/common/go/GoTreeBuilder.java index 4541bf41..a607ab8a 100644 --- a/src/main/java/com/jfrog/ide/common/go/GoTreeBuilder.java +++ b/src/main/java/com/jfrog/ide/common/go/GoTreeBuilder.java @@ -10,6 +10,7 @@ import org.jfrog.build.client.Version; import org.jfrog.build.extractor.executor.CommandResults; import org.jfrog.build.extractor.go.GoDriver; +import org.jfrog.build.extractor.util.WslUtils; import java.io.*; import java.nio.file.Files; @@ -126,7 +127,8 @@ private Path createGoWorkspace() throws IOException { Path goModAbsDir = null; try { goModAbsDir = prepareGoModAbs(); - GoScanWorkspaceCreator goScanWorkspaceCreator = new GoScanWorkspaceCreator(executablePath, projectDir, targetDir, goModAbsDir, env, logger); + boolean runGoThroughWsl = WslUtils.isWslPath(projectDir); + GoScanWorkspaceCreator goScanWorkspaceCreator = new GoScanWorkspaceCreator(executablePath, projectDir, targetDir, goModAbsDir, env, logger, runGoThroughWsl); Files.walkFileTree(projectDir, goScanWorkspaceCreator); } finally { if (goModAbsDir != null) { @@ -176,9 +178,10 @@ private static void populateChildren(DepTree depTree, String[] dependenciesGraph public DepTree buildTree() throws IOException { File tmpDir = createGoWorkspace().toFile(); try { - GoDriver goDriver = new GoDriver(executablePath, env, tmpDir, logger); + boolean runGoThroughWsl = WslUtils.isWslPath(projectDir); + GoDriver goDriver = new GoDriver(executablePath, env, tmpDir, logger, runGoThroughWsl); if (!goDriver.isInstalled()) { - throw new IOException("Could not scan the Go project dependencies, because the Go executable is not in the PATH."); + throw new IOException("Could not scan the Go project dependencies, because the Go executable is not in the PATH. [WSL=" + runGoThroughWsl + "]"); } CommandResults versionRes = goDriver.version(false); diff --git a/src/main/java/com/jfrog/ide/common/npm/NpmComponentUpdater.java b/src/main/java/com/jfrog/ide/common/npm/NpmComponentUpdater.java index 393b6ca1..edee56da 100644 --- a/src/main/java/com/jfrog/ide/common/npm/NpmComponentUpdater.java +++ b/src/main/java/com/jfrog/ide/common/npm/NpmComponentUpdater.java @@ -1,7 +1,7 @@ package com.jfrog.ide.common.npm; import com.jfrog.ide.common.updateversion.ComponentUpdater; -import com.jfrog.ide.common.utils.WslUtils; +import org.jfrog.build.extractor.util.WslUtils; import org.apache.commons.lang3.StringUtils; import org.jfrog.build.api.util.Log; import org.jfrog.build.extractor.executor.CommandExecutor; diff --git a/src/main/java/com/jfrog/ide/common/npm/NpmTreeBuilder.java b/src/main/java/com/jfrog/ide/common/npm/NpmTreeBuilder.java index ea2bbf53..3d80527e 100644 --- a/src/main/java/com/jfrog/ide/common/npm/NpmTreeBuilder.java +++ b/src/main/java/com/jfrog/ide/common/npm/NpmTreeBuilder.java @@ -8,7 +8,7 @@ import com.jfrog.ide.common.deptree.DepTree; import com.jfrog.ide.common.deptree.DepTreeNode; import com.jfrog.ide.common.utils.Utils; -import com.jfrog.ide.common.utils.WslUtils; +import org.jfrog.build.extractor.util.WslUtils; import org.apache.commons.lang3.StringUtils; import org.jfrog.build.api.util.Log; import org.jfrog.build.extractor.executor.CommandExecutor; diff --git a/src/main/java/com/jfrog/ide/common/utils/WslUtils.java b/src/main/java/com/jfrog/ide/common/utils/WslUtils.java deleted file mode 100644 index 46eb505e..00000000 --- a/src/main/java/com/jfrog/ide/common/utils/WslUtils.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.jfrog.ide.common.utils; - -import java.nio.file.Path; - -/** - * Utility methods for WSL (Windows Subsystem for Linux) path handling. - * On Windows, WSL filesystems are exposed as UNC paths under the wsl.localhost or wsl$ hosts. - */ -public class WslUtils { - // UNC-style prefixes used by Windows to expose WSL filesystems - private static final String WSL_LOCALHOST_PREFIX = "\\\\wsl.localhost\\"; - private static final String WSL_DOLLAR_PREFIX = "\\\\wsl$\\"; - - private WslUtils() { - } - - private static boolean startsWithIgnoreCase(String s, String prefix) { - return s.length() >= prefix.length() && s.regionMatches(true, 0, prefix, 0, prefix.length()); - } - - /** - * Normalizes Windows extended-length UNC prefixes so WSL detection sees {@code \\wsl$\...} / {@code \\wsl.localhost\...}. - * Example: {@code \\?\UNC\wsl$\Ubuntu\home\...} becomes {@code \\wsl$\Ubuntu\home\...}. - */ - static String normalizePathStringForWsl(String path) { - if (path == null || path.isEmpty()) { - return path; - } - String p = path; - if (startsWithIgnoreCase(p, "\\\\?\\UNC\\")) { - return "\\\\" + p.substring("\\\\?\\UNC\\".length()); - } - if (startsWithIgnoreCase(p, "\\\\?\\")) { - return p.substring("\\\\?\\".length()); - } - return p; - } - - /** - * Returns true if the given path string refers to a WSL filesystem - * (i.e. it is a UNC path rooted at the wsl.localhost or wsl$ host). - */ - public static boolean isWslPath(String path) { - if (path == null) { - return false; - } - String normalized = normalizePathStringForWsl(path); - return startsWithIgnoreCase(normalized, WSL_LOCALHOST_PREFIX) || startsWithIgnoreCase(normalized, WSL_DOLLAR_PREFIX); - } - - /** - * Returns true if the given {@link Path} refers to a WSL filesystem. - */ - public static boolean isWslPath(Path path) { - return path != null && isWslPath(path.toString()); - } - - /** - * Converts a Windows-style WSL UNC path to the equivalent Linux path inside WSL. - * The distro name (first UNC component after the host) is stripped, and - * backslashes are replaced with forward slashes. - * - * @param wslWindowsPath the Windows-style WSL path - * @return the Linux path, or the original string unchanged if it is not a WSL path - */ - public static String toLinuxPath(String wslWindowsPath) { - if (wslWindowsPath == null) { - return null; - } - String p = normalizePathStringForWsl(wslWindowsPath); - String withoutPrefix; - if (startsWithIgnoreCase(p, WSL_LOCALHOST_PREFIX)) { - withoutPrefix = p.substring(WSL_LOCALHOST_PREFIX.length()); - } else if (startsWithIgnoreCase(p, WSL_DOLLAR_PREFIX)) { - withoutPrefix = p.substring(WSL_DOLLAR_PREFIX.length()); - } else { - return wslWindowsPath; - } - // withoutPrefix is now: \ - // Strip the distro name (first path component) to obtain the Linux path. - int firstBackslash = withoutPrefix.indexOf('\\'); - if (firstBackslash == -1) { - return "/"; // Path pointed at the distro root - } - return withoutPrefix.substring(firstBackslash).replace('\\', '/'); - } -} diff --git a/src/main/java/com/jfrog/ide/common/yarn/YarnComponentUpdater.java b/src/main/java/com/jfrog/ide/common/yarn/YarnComponentUpdater.java index 84ecce87..7ddd8c90 100644 --- a/src/main/java/com/jfrog/ide/common/yarn/YarnComponentUpdater.java +++ b/src/main/java/com/jfrog/ide/common/yarn/YarnComponentUpdater.java @@ -1,7 +1,7 @@ package com.jfrog.ide.common.yarn; import com.jfrog.ide.common.updateversion.ComponentUpdater; -import com.jfrog.ide.common.utils.WslUtils; +import org.jfrog.build.extractor.util.WslUtils; import org.jfrog.build.api.util.Log; import java.io.IOException; diff --git a/src/main/java/com/jfrog/ide/common/yarn/YarnDriver.java b/src/main/java/com/jfrog/ide/common/yarn/YarnDriver.java index c7114b1a..68ff5859 100644 --- a/src/main/java/com/jfrog/ide/common/yarn/YarnDriver.java +++ b/src/main/java/com/jfrog/ide/common/yarn/YarnDriver.java @@ -3,7 +3,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectReader; -import com.jfrog.ide.common.utils.WslUtils; +import org.jfrog.build.extractor.util.WslUtils; import org.apache.commons.lang3.StringUtils; import org.jfrog.build.api.util.Log; import org.jfrog.build.api.util.NullLog; diff --git a/src/main/java/com/jfrog/ide/common/yarn/YarnTreeBuilder.java b/src/main/java/com/jfrog/ide/common/yarn/YarnTreeBuilder.java index 89c1a7d8..e9c032f7 100644 --- a/src/main/java/com/jfrog/ide/common/yarn/YarnTreeBuilder.java +++ b/src/main/java/com/jfrog/ide/common/yarn/YarnTreeBuilder.java @@ -5,7 +5,7 @@ import com.jfrog.ide.common.deptree.DepTree; import com.jfrog.ide.common.deptree.DepTreeNode; import com.jfrog.ide.common.nodes.subentities.ImpactTree; -import com.jfrog.ide.common.utils.WslUtils; +import org.jfrog.build.extractor.util.WslUtils; import org.apache.commons.lang3.StringUtils; import org.jfrog.build.api.util.Log; diff --git a/src/test/java/com/jfrog/ide/common/utils/WslUtilsTest.java b/src/test/java/com/jfrog/ide/common/utils/WslUtilsTest.java deleted file mode 100644 index 3df12132..00000000 --- a/src/test/java/com/jfrog/ide/common/utils/WslUtilsTest.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.jfrog.ide.common.utils; - -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -import java.nio.file.Path; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; - -public class WslUtilsTest { - - @DataProvider - public Object[][] wslPathDetection() { - return new Object[][]{ - {null, false}, - {"C:\\dev\\project", false}, - {"\\\\wsl$\\Ubuntu\\home\\user\\repo", true}, - {"\\\\WSL$\\Ubuntu\\home\\user\\repo", true}, - {"\\\\wsl.localhost\\Ubuntu\\home\\user\\repo", true}, - {"\\\\WSL.LOCALHOST\\Ubuntu\\home\\user\\repo", true}, - {"\\\\?\\UNC\\wsl$\\Ubuntu\\home\\user\\repo", true}, - {"\\\\?\\UNC\\WSL.LOCALHOST\\Ubuntu\\home\\user\\repo", true}, - }; - } - - @Test(dataProvider = "wslPathDetection") - public void testIsWslPathString(String path, boolean expected) { - assertEquals(WslUtils.isWslPath(path), expected); - } - - @Test(dataProvider = "wslPathDetection") - public void testIsWslPathPathObject(String pathString, boolean expected) { - if (pathString == null) { - assertFalse(WslUtils.isWslPath((Path) null)); - } else { - assertEquals(WslUtils.isWslPath(Path.of(pathString)), expected); - } - } - - @DataProvider - public Object[][] toLinuxPathCases() { - return new Object[][]{ - {null, null}, - {"C:\\dev", "C:\\dev"}, - {"\\\\wsl$\\Ubuntu\\home\\user\\app", "/home/user/app"}, - {"\\\\WSL$\\Ubuntu\\home\\user\\app", "/home/user/app"}, - {"\\\\wsl.localhost\\Ubuntu\\home\\user\\app", "/home/user/app"}, - {"\\\\wsl$\\Ubuntu", "/"}, - {"\\\\?\\UNC\\wsl$\\Ubuntu\\home\\user\\app", "/home/user/app"}, - }; - } - - @Test(dataProvider = "toLinuxPathCases") - public void testToLinuxPath(String input, String expected) { - assertEquals(WslUtils.toLinuxPath(input), expected); - } -} From 1bc50e3b101e72c7c064838bc8f417a072d0bcd0 Mon Sep 17 00:00:00 2001 From: attiasas Date: Thu, 30 Apr 2026 15:20:06 +0300 Subject: [PATCH 5/9] Update gradle-dep-tree versions --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b03b1e85..a238706e 100644 --- a/build.gradle +++ b/build.gradle @@ -43,7 +43,7 @@ dependencies { implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.11' implementation group: 'com.google.guava', name: 'guava', version: '32.0.1-jre' implementation group: 'commons-codec', name: 'commons-codec', version: '1.13' - implementation group: 'com.jfrog', name: 'gradle-dep-tree', version: '3.0.1' + implementation group: 'com.jfrog', name: 'gradle-dep-tree', version: '3.2.1' implementation group: 'commons-io', name: 'commons-io', version: '2.20.0' implementation(group: 'com.opencsv', name: 'opencsv', version: '5.11.1') { exclude group: 'common-collections', module: 'commons-collections' From 80178bd66e9e323889182a55a0e8f3873e8e3635 Mon Sep 17 00:00:00 2001 From: attiasas Date: Thu, 30 Apr 2026 15:20:53 +0300 Subject: [PATCH 6/9] update wsl utils location --- src/main/java/com/jfrog/ide/common/go/GoComponentUpdater.java | 2 +- .../java/com/jfrog/ide/common/go/GoScanWorkspaceCreator.java | 2 +- src/main/java/com/jfrog/ide/common/go/GoTreeBuilder.java | 2 +- src/main/java/com/jfrog/ide/common/npm/NpmComponentUpdater.java | 2 +- src/main/java/com/jfrog/ide/common/npm/NpmTreeBuilder.java | 2 +- .../java/com/jfrog/ide/common/yarn/YarnComponentUpdater.java | 2 +- src/main/java/com/jfrog/ide/common/yarn/YarnDriver.java | 2 +- src/main/java/com/jfrog/ide/common/yarn/YarnTreeBuilder.java | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/jfrog/ide/common/go/GoComponentUpdater.java b/src/main/java/com/jfrog/ide/common/go/GoComponentUpdater.java index 68e60892..8663e02d 100644 --- a/src/main/java/com/jfrog/ide/common/go/GoComponentUpdater.java +++ b/src/main/java/com/jfrog/ide/common/go/GoComponentUpdater.java @@ -3,7 +3,7 @@ import com.jfrog.ide.common.updateversion.ComponentUpdater; import org.jfrog.build.api.util.Log; import org.jfrog.build.extractor.go.GoDriver; -import org.jfrog.build.extractor.util.WslUtils; +import org.jfrog.build.extractor.WslUtils; import java.io.IOException; import java.nio.file.Path; diff --git a/src/main/java/com/jfrog/ide/common/go/GoScanWorkspaceCreator.java b/src/main/java/com/jfrog/ide/common/go/GoScanWorkspaceCreator.java index d228435b..63390580 100644 --- a/src/main/java/com/jfrog/ide/common/go/GoScanWorkspaceCreator.java +++ b/src/main/java/com/jfrog/ide/common/go/GoScanWorkspaceCreator.java @@ -4,7 +4,7 @@ import org.apache.commons.lang3.exception.ExceptionUtils; import org.jfrog.build.api.util.Log; import org.jfrog.build.extractor.go.GoDriver; -import org.jfrog.build.extractor.util.WslUtils; +import org.jfrog.build.extractor.WslUtils; import java.io.IOException; import java.nio.file.FileVisitResult; diff --git a/src/main/java/com/jfrog/ide/common/go/GoTreeBuilder.java b/src/main/java/com/jfrog/ide/common/go/GoTreeBuilder.java index a607ab8a..7bc76e64 100644 --- a/src/main/java/com/jfrog/ide/common/go/GoTreeBuilder.java +++ b/src/main/java/com/jfrog/ide/common/go/GoTreeBuilder.java @@ -10,7 +10,7 @@ import org.jfrog.build.client.Version; import org.jfrog.build.extractor.executor.CommandResults; import org.jfrog.build.extractor.go.GoDriver; -import org.jfrog.build.extractor.util.WslUtils; +import org.jfrog.build.extractor.WslUtils; import java.io.*; import java.nio.file.Files; diff --git a/src/main/java/com/jfrog/ide/common/npm/NpmComponentUpdater.java b/src/main/java/com/jfrog/ide/common/npm/NpmComponentUpdater.java index edee56da..feddf777 100644 --- a/src/main/java/com/jfrog/ide/common/npm/NpmComponentUpdater.java +++ b/src/main/java/com/jfrog/ide/common/npm/NpmComponentUpdater.java @@ -1,7 +1,7 @@ package com.jfrog.ide.common.npm; import com.jfrog.ide.common.updateversion.ComponentUpdater; -import org.jfrog.build.extractor.util.WslUtils; +import org.jfrog.build.extractor.WslUtils; import org.apache.commons.lang3.StringUtils; import org.jfrog.build.api.util.Log; import org.jfrog.build.extractor.executor.CommandExecutor; diff --git a/src/main/java/com/jfrog/ide/common/npm/NpmTreeBuilder.java b/src/main/java/com/jfrog/ide/common/npm/NpmTreeBuilder.java index 3d80527e..99274158 100644 --- a/src/main/java/com/jfrog/ide/common/npm/NpmTreeBuilder.java +++ b/src/main/java/com/jfrog/ide/common/npm/NpmTreeBuilder.java @@ -8,7 +8,7 @@ import com.jfrog.ide.common.deptree.DepTree; import com.jfrog.ide.common.deptree.DepTreeNode; import com.jfrog.ide.common.utils.Utils; -import org.jfrog.build.extractor.util.WslUtils; +import org.jfrog.build.extractor.WslUtils; import org.apache.commons.lang3.StringUtils; import org.jfrog.build.api.util.Log; import org.jfrog.build.extractor.executor.CommandExecutor; diff --git a/src/main/java/com/jfrog/ide/common/yarn/YarnComponentUpdater.java b/src/main/java/com/jfrog/ide/common/yarn/YarnComponentUpdater.java index 7ddd8c90..4abb0835 100644 --- a/src/main/java/com/jfrog/ide/common/yarn/YarnComponentUpdater.java +++ b/src/main/java/com/jfrog/ide/common/yarn/YarnComponentUpdater.java @@ -1,7 +1,7 @@ package com.jfrog.ide.common.yarn; import com.jfrog.ide.common.updateversion.ComponentUpdater; -import org.jfrog.build.extractor.util.WslUtils; +import org.jfrog.build.extractor.WslUtils; import org.jfrog.build.api.util.Log; import java.io.IOException; diff --git a/src/main/java/com/jfrog/ide/common/yarn/YarnDriver.java b/src/main/java/com/jfrog/ide/common/yarn/YarnDriver.java index 68ff5859..871bbc17 100644 --- a/src/main/java/com/jfrog/ide/common/yarn/YarnDriver.java +++ b/src/main/java/com/jfrog/ide/common/yarn/YarnDriver.java @@ -3,7 +3,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectReader; -import org.jfrog.build.extractor.util.WslUtils; +import org.jfrog.build.extractor.WslUtils; import org.apache.commons.lang3.StringUtils; import org.jfrog.build.api.util.Log; import org.jfrog.build.api.util.NullLog; diff --git a/src/main/java/com/jfrog/ide/common/yarn/YarnTreeBuilder.java b/src/main/java/com/jfrog/ide/common/yarn/YarnTreeBuilder.java index e9c032f7..03a8514a 100644 --- a/src/main/java/com/jfrog/ide/common/yarn/YarnTreeBuilder.java +++ b/src/main/java/com/jfrog/ide/common/yarn/YarnTreeBuilder.java @@ -5,7 +5,7 @@ import com.jfrog.ide.common.deptree.DepTree; import com.jfrog.ide.common.deptree.DepTreeNode; import com.jfrog.ide.common.nodes.subentities.ImpactTree; -import org.jfrog.build.extractor.util.WslUtils; +import org.jfrog.build.extractor.WslUtils; import org.apache.commons.lang3.StringUtils; import org.jfrog.build.api.util.Log; From 1f36378713eb9dfea67b3406b0fab052efe9d970 Mon Sep 17 00:00:00 2001 From: attiasas Date: Tue, 5 May 2026 10:55:24 +0300 Subject: [PATCH 7/9] fix breaking JAS issue for old logic --- .../ide/common/nodes/subentities/SourceCodeScanType.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/jfrog/ide/common/nodes/subentities/SourceCodeScanType.java b/src/main/java/com/jfrog/ide/common/nodes/subentities/SourceCodeScanType.java index 0a4183ab..0ede9461 100644 --- a/src/main/java/com/jfrog/ide/common/nodes/subentities/SourceCodeScanType.java +++ b/src/main/java/com/jfrog/ide/common/nodes/subentities/SourceCodeScanType.java @@ -5,9 +5,9 @@ public enum SourceCodeScanType { CONTEXTUAL("analyze-applicability"), - SECRETS("JFrog Secrets scanner"), - IAC("JFrog Terraform scanner"), - SAST("JFrog SAST"), + SECRETS("secrets-scan"), + IAC("iac-scan-modules"), + SAST("sast"), SCA("JFrog Xray Scanner"); private final String scannerName; From 65ae77ea78d375690abd20d662412c41b5ca3ff4 Mon Sep 17 00:00:00 2001 From: attiasas Date: Sun, 10 May 2026 09:38:55 +0300 Subject: [PATCH 8/9] Update build-info to 2.43.9 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index d660208d..dc52c8d6 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ repositories { } } -def buildInfoVersion = '2.43.x-SNAPSHOT' +def buildInfoVersion = '2.43.9' // Updated to 2.17.3 for security fixes - compatible with Java 8+ def jacksonVersion = '2.17.3' From b901c444cfc365161589f52271172c936ccc4928 Mon Sep 17 00:00:00 2001 From: attiasas Date: Sun, 10 May 2026 10:16:58 +0300 Subject: [PATCH 9/9] fix tests --- .github/workflows/test.yml | 9 +++++---- .../nodes/subentities/SourceCodeScanType.java | 13 ++++++++++++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c0bcf410..9671ea9c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -27,7 +27,7 @@ jobs: JF_CLI_TEST_URL: ${{ secrets.JFROG_CLI_TEST_URL }} JF_CLI_TEST_ACCESS_TOKEN: ${{ secrets.JFROG_CLI_TEST_ACCESS_TOKEN }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true ref: ${{ github.event.pull_request.head.sha }} @@ -35,20 +35,21 @@ jobs: - name: Unlabel 'safe to test' uses: actions-ecosystem/action-remove-labels@v1 if: ${{ github.event_name != 'push' }} + continue-on-error: true with: labels: "safe to test" # Install required tools - name: Set up Java - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: "temurin" java-version: "17" - name: Setup Gradle - uses: gradle/gradle-build-action@v2 + uses: gradle/actions/setup-gradle@v4 with: gradle-version: 7.6 - name: Setup NodeJS - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ matrix.node }} check-latest: true diff --git a/src/main/java/com/jfrog/ide/common/nodes/subentities/SourceCodeScanType.java b/src/main/java/com/jfrog/ide/common/nodes/subentities/SourceCodeScanType.java index 0ede9461..e33e3a68 100644 --- a/src/main/java/com/jfrog/ide/common/nodes/subentities/SourceCodeScanType.java +++ b/src/main/java/com/jfrog/ide/common/nodes/subentities/SourceCodeScanType.java @@ -3,6 +3,8 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; +import java.util.Locale; + public enum SourceCodeScanType { CONTEXTUAL("analyze-applicability"), SECRETS("secrets-scan"), @@ -23,11 +25,20 @@ public String getScannerName() { } public static SourceCodeScanType fromParam(String param) { + if (param == null) { + throw new IllegalArgumentException("No enum constant with param null"); + } for (SourceCodeScanType type : SourceCodeScanType.values()) { if (type.getScannerName().equals(param)) { return type; } } - throw new IllegalArgumentException("No enum constant with param " + param); + String normalized = param.toLowerCase(Locale.ROOT); + return switch (normalized) { + case "jfrog sast" -> SAST; + case "jfrog secrets scanner" -> SECRETS; + case "jfrog terraform scanner" -> IAC; + default -> throw new IllegalArgumentException("No enum constant with param " + param); + }; } }