Refactor commands and error handling

This commit is contained in:
crschnick 2023-06-05 11:12:44 +00:00
parent e92ded1c71
commit 271e2c8013
11 changed files with 29 additions and 22 deletions

View file

@ -75,7 +75,7 @@ public class FileSystemHelper {
var normalized = shell.get()
.getShellDialect()
.normalizeDirectory(shell.get(), path)
.readOrThrow();
.readStdoutOrThrow();
if (!model.getFileSystem().directoryExists(normalized)) {
throw new IllegalArgumentException(String.format("Directory %s does not exist", normalized));

View file

@ -139,7 +139,7 @@ public final class OpenFileSystemModel {
.getShell()
.get()
.command(normalizedPath)
.workingDirectory(directory)
.withWorkingDirectory(directory)
.prepareTerminalOpen(name);
TerminalHelper.open(normalizedPath, cmd);
}

View file

@ -14,7 +14,7 @@ public abstract class ExecuteApplicationAction implements LeafAction, Applicatio
ShellControl sc = model.getFileSystem().getShell().orElseThrow();
for (BrowserEntry entry : entries) {
var command = detach() ? ScriptHelper.createDetachCommand(sc, createCommand(model, entry)) : createCommand(model, entry);
try (var cc = sc.command(command).workingDirectory(model.getCurrentDirectory().getPath()).start()) {
try (var cc = sc.command(command).withWorkingDirectory(model.getCurrentDirectory().getPath()).start()) {
cc.discardOrThrow();
}
}

View file

@ -30,7 +30,7 @@ public abstract class MultiExecuteAction implements BranchAction {
pc -> {
for (BrowserEntry entry : entries) {
var cmd = pc.command(createCommand(pc, model, entry))
.workingDirectory(model.getCurrentDirectory()
.withWorkingDirectory(model.getCurrentDirectory()
.getPath())
.prepareTerminalOpen(FileNames.getFileName(
entry.getRawFileEntry().getPath()));
@ -58,7 +58,7 @@ public abstract class MultiExecuteAction implements BranchAction {
var cmd = ScriptHelper.createDetachCommand(
pc, createCommand(pc, model, entry));
pc.command(cmd)
.workingDirectory(model.getCurrentDirectory()
.withWorkingDirectory(model.getCurrentDirectory()
.getPath())
.execute();
}
@ -79,7 +79,7 @@ public abstract class MultiExecuteAction implements BranchAction {
pc -> {
for (BrowserEntry entry : entries) {
pc.command(createCommand(pc, model, entry))
.workingDirectory(model.getCurrentDirectory()
.withWorkingDirectory(model.getCurrentDirectory()
.getPath())
.execute();
}

View file

@ -14,7 +14,7 @@ public abstract class ToFileCommandAction implements LeafAction, ApplicationPath
ShellControl sc = model.getFileSystem().getShell().orElseThrow();
for (BrowserEntry entry : entries) {
var command = createCommand(model, entry);
try (var cc = sc.command(command).workingDirectory(model.getCurrentDirectory().getPath()).start()) {
try (var cc = sc.command(command).withWorkingDirectory(model.getCurrentDirectory().getPath()).start()) {
cc.discardErr();
FileOpener.openCommandOutput(entry.getFileName(), entry, cc);
}

View file

@ -34,7 +34,7 @@ public interface CommandControl extends ProcessControl {
CommandControl notComplex();
CommandControl workingDirectory(String directory);
CommandControl withWorkingDirectory(String directory);
default void execute() throws Exception {
try (var c = start()) {
@ -56,7 +56,7 @@ public interface CommandControl extends ProcessControl {
public boolean waitFor();
CommandControl customCharset(Charset charset);
CommandControl withCustomCharset(Charset charset);
int getExitCode();
@ -82,7 +82,7 @@ public interface CommandControl extends ProcessControl {
public byte[] readRawBytesOrThrow() throws Exception;
public String readOrThrow() throws Exception;
public String readStdoutOrThrow() throws Exception;
public default boolean discardAndCheckExit() throws ProcessOutputException {
try {

View file

@ -84,7 +84,7 @@ public sealed interface OsType permits OsType.Windows, OsType.Linux, OsType.MacO
@Override
public Map<String, String> getProperties(ShellControl pc) throws Exception {
try (CommandControl c = pc.command("systeminfo").start()) {
var text = c.readOrThrow();
var text = c.readStdoutOrThrow();
return PropertiesFormatsParser.parse(text, ":");
}
}
@ -228,7 +228,7 @@ public sealed interface OsType permits OsType.Windows, OsType.Linux, OsType.MacO
public Map<String, String> getProperties(ShellControl pc) throws Exception {
try (CommandControl c =
pc.subShell(ShellDialects.BASH).command("sw_vers").start()) {
var text = c.readOrThrow();
var text = c.readStdoutOrThrow();
return PropertiesFormatsParser.parse(text, ":");
}
}

View file

@ -2,6 +2,9 @@ package io.xpipe.core.process;
import lombok.Getter;
import java.util.Arrays;
import java.util.stream.Collectors;
@Getter
public class ProcessOutputException extends Exception {
@ -11,16 +14,20 @@ public class ProcessOutputException extends Exception {
return new ProcessOutputException(message, ex.getExitCode(), ex.getOutput());
}
public static ProcessOutputException of(int exitCode, String stdout, String stderr) {
var combinedError = (stdout != null && !stdout.isBlank() ? stdout.strip() + "\n\n" : "")
+ (stderr != null && !stderr.isBlank() ? stderr.strip() : "");
public static ProcessOutputException of(int exitCode, String... messages) {
var combinedError = Arrays.stream(messages)
.filter(s -> s != null && !s.isBlank())
.map(s -> s.strip())
.collect(Collectors.joining("\n\n"))
.replaceAll("\r\n", "\n");
var hasMessage = !combinedError.isBlank();
var errorSuffix = hasMessage ? ": " + combinedError : "";
var errorSuffix = hasMessage ? ":\n" + combinedError : "";
var message =
switch (exitCode) {
case CommandControl.START_FAILED_EXIT_CODE -> "Process did not start up properly and had to be killed" + errorSuffix;
case CommandControl.EXIT_TIMEOUT_EXIT_CODE -> "Wait for process exit timed out"
case CommandControl
.START_FAILED_EXIT_CODE -> "Process did not start up properly and had to be killed"
+ errorSuffix;
case CommandControl.EXIT_TIMEOUT_EXIT_CODE -> "Wait for process exit timed out" + errorSuffix;
default -> "Process returned exit code " + exitCode + errorSuffix;
};
return new ProcessOutputException(message, exitCode, combinedError);

View file

@ -56,7 +56,7 @@ public interface ShellControl extends ProcessControl {
default String executeSimpleStringCommand(String command) throws Exception {
try (CommandControl c = command(command).start()) {
return c.readOrThrow();
return c.readStdoutOrThrow();
}
}

View file

@ -156,7 +156,7 @@ public class XPipeInstallation {
public static String queryInstallationVersion(ShellControl p, String exec) throws Exception {
try (CommandControl c = p.command(List.of(exec, "version")).start()) {
return c.readOrThrow();
return c.readStdoutOrThrow();
} catch (ProcessOutputException ex) {
return "?";
}

View file

@ -72,7 +72,7 @@ public class SampleAction implements ActionProvider {
"""
).start()) {
// Reads stdout, stashes stderr. If the exit code is not 0, it will throw an exception with the stderr contents.
var output = cc.readOrThrow();
var output = cc.readStdoutOrThrow();
}
// More customization options
@ -80,7 +80,7 @@ public class SampleAction implements ActionProvider {
// sudo and the optional sudo password automatically provided by XPipe
// by using the information from the connection store.
// You can also set a custom working directory.
try (CommandControl cc = sc.command("kill <pid>").elevated("kill").workingDirectory("/").start()) {
try (CommandControl cc = sc.command("kill <pid>").elevated("kill").withWorkingDirectory("/").start()) {
// Discard any output but throw an exception with the stderr contents if the exit code is not 0
cc.discardOrThrow();
}