From d402eb3d80ad89644b407bbed82d3aa205fea3a8 Mon Sep 17 00:00:00 2001 From: crschnick Date: Sat, 18 Oct 2025 10:24:33 +0000 Subject: [PATCH] Various fixes --- .../impl/compress/CompressMenuProvider.java | 5 ++--- .../app/prefs/ExternalApplicationType.java | 9 ++++++--- .../io/xpipe/app/process/CommandSupport.java | 19 ++----------------- .../xpipe/app/process/ShellControlCache.java | 2 +- .../xpipe/app/terminal/KittyTerminalType.java | 2 +- .../terminal/TerminalLaunchConfiguration.java | 3 +-- .../xpipe/app/terminal/WaveTerminalType.java | 7 +++---- .../xpipe/app/terminal/WezTerminalType.java | 8 ++++---- .../io/xpipe/app/util/SshLocalBridge.java | 2 +- 9 files changed, 21 insertions(+), 36 deletions(-) diff --git a/app/src/main/java/io/xpipe/app/browser/menu/impl/compress/CompressMenuProvider.java b/app/src/main/java/io/xpipe/app/browser/menu/impl/compress/CompressMenuProvider.java index 548ec5f1d..1991ce5fe 100644 --- a/app/src/main/java/io/xpipe/app/browser/menu/impl/compress/CompressMenuProvider.java +++ b/app/src/main/java/io/xpipe/app/browser/menu/impl/compress/CompressMenuProvider.java @@ -7,7 +7,6 @@ import io.xpipe.app.comp.Comp; import io.xpipe.app.comp.base.ModalOverlay; import io.xpipe.app.core.AppI18n; import io.xpipe.app.platform.LabelGraphic; -import io.xpipe.app.process.CommandSupport; import io.xpipe.app.ext.FileKind; import io.xpipe.core.OsType; @@ -27,11 +26,11 @@ public class CompressMenuProvider implements BrowserMenuBranchProvider { var sc = model.getFileSystem().getShell().orElseThrow(); - var foundTar = CommandSupport.findProgram(sc, "tar"); + var foundTar = sc.view().findProgram("tar"); model.getCache().getInstalledApplications().put("tar", foundTar.isPresent()); if (sc.getOsType() != OsType.WINDOWS) { - var found = CommandSupport.findProgram(sc, "zip"); + var found = sc.view().findProgram("zip"); model.getCache().getInstalledApplications().put("zip", found.isPresent()); } } diff --git a/app/src/main/java/io/xpipe/app/prefs/ExternalApplicationType.java b/app/src/main/java/io/xpipe/app/prefs/ExternalApplicationType.java index 86ea20f8d..1fc3ad17a 100644 --- a/app/src/main/java/io/xpipe/app/prefs/ExternalApplicationType.java +++ b/app/src/main/java/io/xpipe/app/prefs/ExternalApplicationType.java @@ -94,7 +94,8 @@ public interface ExternalApplicationType extends PrefsValue { default boolean isAvailable() { try (ShellControl pc = LocalShell.getShell()) { - return CommandSupport.findProgram(pc, getExecutable()).isPresent(); + String name = getExecutable(); + return pc.view().findProgram(name).isPresent(); } catch (Exception e) { ErrorEventFactory.fromThrowable(e).omit().handle(); return false; @@ -103,7 +104,8 @@ public interface ExternalApplicationType extends PrefsValue { default void launch(CommandBuilder args) throws Exception { try (ShellControl pc = LocalShell.getShell()) { - if (!CommandSupport.isInPath(pc, getExecutable())) { + String executable = getExecutable(); + if (!pc.view().findProgram(executable).isPresent()) { throw ErrorEventFactory.expected(new IOException("Executable " + getExecutable() + " not found in PATH. Either add it to the PATH and refresh the environment by restarting XPipe, or specify an absolute " + "executable path using the custom terminal setting.")); @@ -152,7 +154,8 @@ public interface ExternalApplicationType extends PrefsValue { default Optional determineFromPath() { // Try to locate if it is in the Path try (var sc = LocalShell.getShell().start()) { - var out = CommandSupport.findProgram(sc, getExecutable()); + String name = getExecutable(); + var out = sc.view().findProgram(name); if (out.isPresent()) { return out.map(filePath -> Path.of(filePath.toString())); } diff --git a/app/src/main/java/io/xpipe/app/process/CommandSupport.java b/app/src/main/java/io/xpipe/app/process/CommandSupport.java index 821ba8786..550c9cfb4 100644 --- a/app/src/main/java/io/xpipe/app/process/CommandSupport.java +++ b/app/src/main/java/io/xpipe/app/process/CommandSupport.java @@ -4,25 +4,11 @@ import io.xpipe.app.issue.ErrorEventFactory; import io.xpipe.app.storage.DataStorage; import io.xpipe.app.storage.DataStoreEntry; import io.xpipe.core.FailableSupplier; -import io.xpipe.core.FilePath; import java.io.IOException; -import java.util.Optional; public class CommandSupport { - public static Optional findProgram(ShellControl processControl, String name) throws Exception { - var out = processControl - .command(processControl.getShellDialect().getWhichCommand(name)) - .readStdoutIfPossible(); - return out.flatMap(s -> s.lines().findFirst()).map(String::trim).map(FilePath::of); - } - - public static boolean isInPath(ShellControl processControl, String executable) throws Exception { - return processControl.executeSimpleBooleanCommand( - processControl.getShellDialect().getWhichCommand(executable)); - } - public static void isInPathOrThrow(ShellControl processControl, String executable) throws Exception { isInPathOrThrow(processControl, executable, null); } @@ -43,7 +29,7 @@ public class CommandSupport { public static void isInPathOrThrow( ShellControl processControl, String executable, String displayName, DataStoreEntry connection) throws Exception { - if (!isInPath(processControl, executable)) { + if (!processControl.view().findProgram(executable).isPresent()) { var prefix = displayName != null ? displayName + " executable " + executable : executable + " executable"; throw ErrorEventFactory.expected(new IOException( prefix + " not found in PATH" + (connection != null ? " on system " + connection.getName() : ""))); @@ -60,8 +46,7 @@ public class CommandSupport { public static boolean isInLocalPath(String executable) throws Exception { try (var sc = LocalShell.getShell().start()) { - var r = sc.command(sc.getShellDialect().getWhichCommand(executable)).executeAndCheck(); - return r; + return sc.view().findProgram(executable).isPresent(); } } diff --git a/app/src/main/java/io/xpipe/app/process/ShellControlCache.java b/app/src/main/java/io/xpipe/app/process/ShellControlCache.java index c64abe331..0f49d9815 100644 --- a/app/src/main/java/io/xpipe/app/process/ShellControlCache.java +++ b/app/src/main/java/io/xpipe/app/process/ShellControlCache.java @@ -18,7 +18,7 @@ public class ShellControlCache { public boolean isApplicationInPath(String app) { if (!installedApplications.containsKey(app)) { try { - var b = CommandSupport.isInPath(shellControl, app); + var b = shellControl.view().findProgram(app).isPresent(); installedApplications.put(app, b); } catch (Exception e) { installedApplications.put(app, false); diff --git a/app/src/main/java/io/xpipe/app/terminal/KittyTerminalType.java b/app/src/main/java/io/xpipe/app/terminal/KittyTerminalType.java index 20e8f18d9..6721ff352 100644 --- a/app/src/main/java/io/xpipe/app/terminal/KittyTerminalType.java +++ b/app/src/main/java/io/xpipe/app/terminal/KittyTerminalType.java @@ -108,7 +108,7 @@ public interface KittyTerminalType extends ExternalTerminalType, TrackableTermin public boolean isAvailable() { try (ShellControl pc = LocalShell.getShell()) { - return CommandSupport.findProgram(pc, "kitty").isPresent(); + return pc.view().findProgram("kitty").isPresent(); } catch (Exception e) { ErrorEventFactory.fromThrowable(e).omit().handle(); return false; diff --git a/app/src/main/java/io/xpipe/app/terminal/TerminalLaunchConfiguration.java b/app/src/main/java/io/xpipe/app/terminal/TerminalLaunchConfiguration.java index 5277f0a9f..e8af39e55 100644 --- a/app/src/main/java/io/xpipe/app/terminal/TerminalLaunchConfiguration.java +++ b/app/src/main/java/io/xpipe/app/terminal/TerminalLaunchConfiguration.java @@ -101,8 +101,7 @@ public class TerminalLaunchConfiguration { ShellDialects.POWERSHELL); return config; } else { - var found = - sc.command(sc.getShellDialect().getWhichCommand("script")).executeAndCheck(); + var found = sc.view().findProgram("script").isPresent(); if (!found) { var suffix = sc.getOsType() == OsType.MACOS ? "This command is available in the util-linux package which can be installed via homebrew." diff --git a/app/src/main/java/io/xpipe/app/terminal/WaveTerminalType.java b/app/src/main/java/io/xpipe/app/terminal/WaveTerminalType.java index fc8f85b4f..25d5f7d4a 100644 --- a/app/src/main/java/io/xpipe/app/terminal/WaveTerminalType.java +++ b/app/src/main/java/io/xpipe/app/terminal/WaveTerminalType.java @@ -3,7 +3,6 @@ package io.xpipe.app.terminal; import io.xpipe.app.core.AppInstallation; import io.xpipe.app.issue.ErrorEventFactory; import io.xpipe.app.process.CommandBuilder; -import io.xpipe.app.process.CommandSupport; import io.xpipe.app.process.LocalShell; public interface WaveTerminalType extends ExternalTerminalType, TrackableTerminalType { @@ -15,7 +14,7 @@ public interface WaveTerminalType extends ExternalTerminalType, TrackableTermina @Override default boolean isAvailable() { try (var sc = LocalShell.getShell().start()) { - var wsh = CommandSupport.findProgram(sc, "wsh"); + var wsh = sc.view().findProgram("wsh"); return wsh.isPresent(); } catch (Exception ex) { ErrorEventFactory.fromThrowable(ex).handle(); @@ -46,10 +45,10 @@ public interface WaveTerminalType extends ExternalTerminalType, TrackableTermina @Override default void launch(TerminalLaunchConfiguration configuration) throws Exception { try (var sc = LocalShell.getShell().start()) { - var wsh = CommandSupport.findProgram(sc, "wsh"); + var wsh = sc.view().findProgram("wsh"); var env = sc.view().getEnvironmentVariable("WAVETERM_JWT"); if (wsh.isEmpty() || env.isEmpty()) { - var inPath = CommandSupport.findProgram(sc, "xpipe").isPresent(); + var inPath = sc.view().findProgram("xpipe").isPresent(); var msg = """ The Wave integration requires XPipe to be launched from Wave itself to have access to its environment variables. Otherwise, XPipe does not have access to the token to control Wave. diff --git a/app/src/main/java/io/xpipe/app/terminal/WezTerminalType.java b/app/src/main/java/io/xpipe/app/terminal/WezTerminalType.java index 948af87d1..7a0e8dc88 100644 --- a/app/src/main/java/io/xpipe/app/terminal/WezTerminalType.java +++ b/app/src/main/java/io/xpipe/app/terminal/WezTerminalType.java @@ -4,6 +4,7 @@ import io.xpipe.app.issue.ErrorEventFactory; import io.xpipe.app.prefs.ExternalApplicationHelper; import io.xpipe.app.prefs.ExternalApplicationType; import io.xpipe.app.process.CommandBuilder; +import io.xpipe.app.process.CommandSupport; import io.xpipe.app.process.ShellControl; import io.xpipe.app.process.LocalShell; import io.xpipe.app.util.WindowsRegistry; @@ -75,8 +76,8 @@ public interface WezTerminalType extends ExternalTerminalType, TrackableTerminal ErrorEventFactory.fromThrowable(ex).omit().handle(); } - try (ShellControl pc = LocalShell.getShell()) { - if (pc.executeSimpleBooleanCommand(pc.getShellDialect().getWhichCommand("wezterm-gui"))) { + try { + if (CommandSupport.isInLocalPath("wezterm")) { return Optional.of(Path.of("wezterm-gui")); } } catch (Exception e) { @@ -119,8 +120,7 @@ public interface WezTerminalType extends ExternalTerminalType, TrackableTerminal public boolean isAvailable() { try (ShellControl pc = LocalShell.getShell()) { - return pc.executeSimpleBooleanCommand(pc.getShellDialect().getWhichCommand("wezterm")) - && pc.executeSimpleBooleanCommand(pc.getShellDialect().getWhichCommand("wezterm-gui")); + return CommandSupport.isInLocalPath("wezterm") && CommandSupport.isInLocalPath("wezterm-gui"); } catch (Exception e) { ErrorEventFactory.fromThrowable(e).omit().handle(); return false; diff --git a/app/src/main/java/io/xpipe/app/util/SshLocalBridge.java b/app/src/main/java/io/xpipe/app/util/SshLocalBridge.java index 61633d1b5..d949e4d1f 100644 --- a/app/src/main/java/io/xpipe/app/util/SshLocalBridge.java +++ b/app/src/main/java/io/xpipe/app/util/SshLocalBridge.java @@ -143,7 +143,7 @@ public class SshLocalBridge { } private static FilePath getSshd(ShellControl sc) throws Exception { - var exec = CommandSupport.findProgram(sc, "sshd"); + var exec = sc.view().findProgram("sshd"); if (exec.isEmpty()) { throw ErrorEventFactory.expected( new IllegalStateException(