Rework file paths and kitty support

This commit is contained in:
crschnick 2024-04-01 03:43:22 +00:00
parent c228e6ba30
commit a8f07c3e0f
13 changed files with 130 additions and 68 deletions

View file

@ -60,6 +60,7 @@ public class TroubleshootCategory extends AppPrefsCategory {
"openCurrentLogFileDescription", "openCurrentLogFileDescription",
"mdmz-text_snippet", "mdmz-text_snippet",
e -> { e -> {
AppLogs.get().flush();
FileOpener.openInTextEditor(AppLogs.get() FileOpener.openInTextEditor(AppLogs.get()
.getSessionLogsDirectory() .getSessionLogsDirectory()
.resolve("xpipe.log") .resolve("xpipe.log")

View file

@ -10,6 +10,7 @@ import io.xpipe.app.util.LocalShell;
import io.xpipe.app.util.MacOsPermissions; import io.xpipe.app.util.MacOsPermissions;
import io.xpipe.app.util.WindowsRegistry; import io.xpipe.app.util.WindowsRegistry;
import io.xpipe.core.process.*; import io.xpipe.core.process.*;
import io.xpipe.core.store.FilePath;
import lombok.Getter; import lombok.Getter;
import lombok.Value; import lombok.Value;
import lombok.With; import lombok.With;
@ -131,7 +132,7 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
.add("-e") .add("-e")
.add("cmd") .add("cmd")
.add("/c") .add("/c")
.addQuoted(configuration.getScriptFile().replaceAll(" ", "^$0")); .addQuoted(configuration.getScriptFile().toString().replaceAll(" ", "^$0"));
} }
}; };
ExternalTerminalType TABBY_WINDOWS = new WindowsType("app.tabby", "Tabby") { ExternalTerminalType TABBY_WINDOWS = new WindowsType("app.tabby", "Tabby") {
@ -311,28 +312,12 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
protected CommandBuilder toCommand(LaunchConfiguration configuration) { protected CommandBuilder toCommand(LaunchConfiguration configuration) {
return CommandBuilder.of() return CommandBuilder.of()
.add("-e") .add("-e")
.addQuoted(configuration.getScriptFile()) .addFile(configuration.getScriptFile())
.add("-T") .add("-T")
.addQuoted(configuration.getColoredTitle()) .addQuoted(configuration.getColoredTitle())
.add("--new-tab"); .add("--new-tab");
} }
}; };
ExternalTerminalType KITTY_LINUX = new SimplePathType("app.kitty", "kitty") {
@Override
public boolean supportsTabs() {
return false;
}
@Override
protected CommandBuilder toCommand(LaunchConfiguration configuration) {
return CommandBuilder.of()
.add("-1")
.add("-T")
.addQuoted(configuration.getColoredTitle())
.addQuoted(configuration.getScriptFile());
}
};
ExternalTerminalType TERMINOLOGY = new SimplePathType("app.terminology", "terminology") { ExternalTerminalType TERMINOLOGY = new SimplePathType("app.terminology", "terminology") {
@Override @Override
@ -347,7 +332,7 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
.addQuoted(configuration.getColoredTitle()) .addQuoted(configuration.getColoredTitle())
.add("-2") .add("-2")
.add("-e") .add("-e")
.addQuoted(configuration.getScriptFile()); .addFile(configuration.getScriptFile());
} }
}; };
ExternalTerminalType COOL_RETRO_TERM = new SimplePathType("app.coolRetroTerm", "cool-retro-term") { ExternalTerminalType COOL_RETRO_TERM = new SimplePathType("app.coolRetroTerm", "cool-retro-term") {
@ -363,7 +348,7 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
.add("-T") .add("-T")
.addQuoted(configuration.getColoredTitle()) .addQuoted(configuration.getColoredTitle())
.add("-e") .add("-e")
.addQuoted(configuration.getScriptFile()); .addFile(configuration.getScriptFile());
} }
}; };
ExternalTerminalType GUAKE = new SimplePathType("app.guake", "guake") { ExternalTerminalType GUAKE = new SimplePathType("app.guake", "guake") {
@ -380,7 +365,7 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
.add("-r") .add("-r")
.addQuoted(configuration.getColoredTitle()) .addQuoted(configuration.getColoredTitle())
.add("-e") .add("-e")
.addQuoted(configuration.getScriptFile()); .addFile(configuration.getScriptFile());
} }
}; };
ExternalTerminalType ALACRITTY_LINUX = new SimplePathType("app.alacritty", "alacritty") { ExternalTerminalType ALACRITTY_LINUX = new SimplePathType("app.alacritty", "alacritty") {
@ -401,7 +386,7 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
.add("-t") .add("-t")
.addQuoted(configuration.getCleanTitle()) .addQuoted(configuration.getCleanTitle())
.add("-e") .add("-e")
.addQuoted(configuration.getScriptFile()); .addFile(configuration.getScriptFile());
} }
}; };
ExternalTerminalType TILDA = new SimplePathType("app.tilda", "tilda") { ExternalTerminalType TILDA = new SimplePathType("app.tilda", "tilda") {
@ -413,7 +398,7 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
@Override @Override
protected CommandBuilder toCommand(LaunchConfiguration configuration) { protected CommandBuilder toCommand(LaunchConfiguration configuration) {
return CommandBuilder.of().add("-c").addQuoted(configuration.getScriptFile()); return CommandBuilder.of().add("-c").addFile(configuration.getScriptFile());
} }
}; };
ExternalTerminalType XTERM = new SimplePathType("app.xterm", "xterm") { ExternalTerminalType XTERM = new SimplePathType("app.xterm", "xterm") {
@ -429,7 +414,7 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
.add("-title") .add("-title")
.addQuoted(configuration.getColoredTitle()) .addQuoted(configuration.getColoredTitle())
.add("-e") .add("-e")
.addQuoted(configuration.getScriptFile()); .addFile(configuration.getScriptFile());
} }
}; };
ExternalTerminalType DEEPIN_TERMINAL = new SimplePathType("app.deepinTerminal", "deepin-terminal") { ExternalTerminalType DEEPIN_TERMINAL = new SimplePathType("app.deepinTerminal", "deepin-terminal") {
@ -441,7 +426,7 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
@Override @Override
protected CommandBuilder toCommand(LaunchConfiguration configuration) { protected CommandBuilder toCommand(LaunchConfiguration configuration) {
return CommandBuilder.of().add("-C").addQuoted(configuration.getScriptFile()); return CommandBuilder.of().add("-C").addFile(configuration.getScriptFile());
} }
}; };
ExternalTerminalType Q_TERMINAL = new SimplePathType("app.qTerminal", "qterminal") { ExternalTerminalType Q_TERMINAL = new SimplePathType("app.qTerminal", "qterminal") {
@ -465,7 +450,7 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
@Override @Override
public void launch(LaunchConfiguration configuration) throws Exception { public void launch(LaunchConfiguration configuration) throws Exception {
try (ShellControl pc = LocalShell.getShell()) { try (ShellControl pc = LocalShell.getShell()) {
var suffix = "\"" + configuration.getScriptFile().replaceAll("\"", "\\\\\"") + "\""; var suffix = "\"" + configuration.getScriptFile().toString().replaceAll("\"", "\\\\\"") + "\"";
pc.osascriptCommand(String.format( pc.osascriptCommand(String.format(
""" """
activate application "Terminal" activate application "Terminal"
@ -508,7 +493,7 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
create window with default profile command "%s" create window with default profile command "%s"
end tell end tell
""", """,
a, a, a, a, configuration.getScriptFile().replaceAll("\"", "\\\\\""))) a, a, a, a, configuration.getScriptFile().toString().replaceAll("\"", "\\\\\"")))
.execute(); .execute();
} }
} }
@ -633,7 +618,7 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
end tell end tell
end tell end tell
""", """,
configuration.getScriptFile().replaceAll("\"", "\\\\\""))) configuration.getScriptFile().toString().replaceAll("\"", "\\\\\"")))
.execute(); .execute();
} }
} }
@ -656,7 +641,7 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
GNOME_TERMINAL, GNOME_TERMINAL,
TILIX, TILIX,
TERMINATOR, TERMINATOR,
KITTY_LINUX, KittyTerminalType.KITTY_LINUX,
TERMINOLOGY, TERMINOLOGY,
COOL_RETRO_TERM, COOL_RETRO_TERM,
GUAKE, GUAKE,
@ -747,12 +732,12 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
String cleanTitle; String cleanTitle;
@With @With
String scriptFile; FilePath scriptFile;
ShellDialect scriptDialect; ShellDialect scriptDialect;
public CommandBuilder getDialectLaunchCommand() { public CommandBuilder getDialectLaunchCommand() {
var open = scriptDialect.getOpenScriptCommand(scriptFile); var open = scriptDialect.getOpenScriptCommand(scriptFile.toString());
return open; return open;
} }
@ -783,7 +768,7 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
var format = custom.toLowerCase(Locale.ROOT).contains("$cmd") ? custom : custom + " $CMD"; var format = custom.toLowerCase(Locale.ROOT).contains("$cmd") ? custom : custom + " $CMD";
try (var pc = LocalShell.getShell()) { try (var pc = LocalShell.getShell()) {
var toExecute = ApplicationHelper.replaceFileArgument(format, "CMD", configuration.getScriptFile()); var toExecute = ApplicationHelper.replaceFileArgument(format, "CMD", configuration.getScriptFile().toString());
// We can't be sure whether the command is blocking or not, so always make it not blocking // We can't be sure whether the command is blocking or not, so always make it not blocking
if (pc.getOsType().equals(OsType.WINDOWS)) { if (pc.getOsType().equals(OsType.WINDOWS)) {
toExecute = "start \"" + configuration.getCleanTitle() + "\" " + toExecute; toExecute = "start \"" + configuration.getCleanTitle() + "\" " + toExecute;

View file

@ -0,0 +1,66 @@
package io.xpipe.app.terminal;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import io.xpipe.app.util.LocalShell;
import io.xpipe.core.process.CommandBuilder;
import io.xpipe.core.store.FilePath;
import io.xpipe.core.util.XPipeInstallation;
public class KittyTerminalType {
public static final ExternalTerminalType KITTY_LINUX = new ExternalTerminalType() {
@Override
public String getId() {
return "app.tabby";
}
@Override
public boolean supportsTabs() {
return true;
}
@Override
public void launch(LaunchConfiguration configuration) throws Exception {
launchInstanceIfNeeded();
open(configuration);
}
};
private static FilePath getSocket() throws Exception {
try (var sc = LocalShell.getShell().start()) {
var temp = sc.getSystemTemporaryDirectory();
return temp.join("xpipe_kitty");
}
}
private static void launchInstanceIfNeeded() throws Exception {
var socket = getSocket();
try (var sc = LocalShell.getShell().start()) {
if (sc.getShellDialect().createFileExistsCommand(sc,socket.toString()).executeAndCheck()) {
return;
}
sc.executeSimpleCommand(CommandBuilder.of().add("kitty").add("-o", "allow_remote_control=socket-only", "--listen-on", "unix:" + getSocket(), "--detach"));
}
}
private static void open(ExternalTerminalType.LaunchConfiguration configuration) throws Exception {
try (var sc = LocalShell.getShell().start()) {
var payload = JsonNodeFactory.instance.objectNode();
payload.put("args", configuration.getDialectLaunchCommand().buildString(sc));
payload.put("tab_title",configuration.getColoredTitle());
payload.put("type", "tab");
payload.put("logo_alpha", 0.01);
payload.put("logo", XPipeInstallation.getLocalDefaultInstallationIcon().toString());
var json = JsonNodeFactory.instance.objectNode();
json.put("cmd", "launch");
json.set("payload", payload);
var jsonString = json.toString();
var echoString = "'\\eP@kitty-cmd" + jsonString + "\\e\\\\'";
sc.executeSimpleCommand(CommandBuilder.of().add("echo", "-en", echoString, "|", "socat", "-").addFile(getSocket()));
}
}
}

View file

@ -75,7 +75,7 @@ public class WindowsTerminalType {
? CommandBuilder.of().addFile(configuration.getScriptFile()) ? CommandBuilder.of().addFile(configuration.getScriptFile())
: CommandBuilder.of() : CommandBuilder.of()
.add("powershell", "-ExecutionPolicy", "Bypass", "-File") .add("powershell", "-ExecutionPolicy", "Bypass", "-File")
.addQuoted(configuration.getScriptFile()); .addFile(configuration.getScriptFile());
var cmd = CommandBuilder.of().add("-w", "1", "nt"); var cmd = CommandBuilder.of().add("-w", "1", "nt");
if (configuration.getColor() != null) { if (configuration.getColor() != null) {

View file

@ -42,7 +42,7 @@ public class ApplicationHelper {
return String.format( return String.format(
"Start-Process -FilePath %s -ArgumentList \"-NoProfile\", \"-File\", %s", "Start-Process -FilePath %s -ArgumentList \"-NoProfile\", \"-File\", %s",
pc.getShellDialect().getExecutableName(), pc.getShellDialect().getExecutableName(),
pc.getShellDialect().fileArgument(script)); pc.getShellDialect().fileArgument(script.toString()));
} }
if (pc.getOsType().equals(OsType.WINDOWS)) { if (pc.getOsType().equals(OsType.WINDOWS)) {

View file

@ -2,7 +2,7 @@ package io.xpipe.app.util;
import io.xpipe.app.issue.TrackEvent; import io.xpipe.app.issue.TrackEvent;
import io.xpipe.core.process.*; import io.xpipe.core.process.*;
import io.xpipe.core.store.FileNames; import io.xpipe.core.store.FilePath;
import io.xpipe.core.util.FailableFunction; import io.xpipe.core.util.FailableFunction;
import io.xpipe.core.util.SecretValue; import io.xpipe.core.util.SecretValue;
import lombok.SneakyThrows; import lombok.SneakyThrows;
@ -21,13 +21,13 @@ public class ScriptHelper {
} }
@SneakyThrows @SneakyThrows
public static String createLocalExecScript(String content) { public static FilePath createLocalExecScript(String content) {
try (var l = LocalShell.getShell().start()) { try (var l = LocalShell.getShell().start()) {
return createExecScript(l, content); return createExecScript(l, content);
} }
} }
public static String constructTerminalInitFile( public static FilePath constructTerminalInitFile(
ShellDialect t, ShellDialect t,
ShellControl processControl, ShellControl processControl,
FailableFunction<ShellControl, String, Exception> workingDirectory, FailableFunction<ShellControl, String, Exception> workingDirectory,
@ -74,37 +74,37 @@ public class ScriptHelper {
content += nl + t.getPassthroughExitCommand() + nl; content += nl + t.getPassthroughExitCommand() + nl;
} }
return createExecScript(t, processControl, t.initFileName(processControl), content); return createExecScript(t, processControl, new FilePath(t.initFileName(processControl)), content);
} }
@SneakyThrows @SneakyThrows
public static String getExecScriptFile(ShellControl processControl) { public static FilePath getExecScriptFile(ShellControl processControl) {
return getExecScriptFile( return getExecScriptFile(
processControl, processControl.getShellDialect().getScriptFileEnding()); processControl, processControl.getShellDialect().getScriptFileEnding());
} }
@SneakyThrows @SneakyThrows
public static String getExecScriptFile(ShellControl processControl, String fileEnding) { public static FilePath getExecScriptFile(ShellControl processControl, String fileEnding) {
var fileName = "exec-" + getScriptId(); var fileName = "exec-" + getScriptId();
var temp = processControl.getSystemTemporaryDirectory(); var temp = processControl.getSystemTemporaryDirectory();
return FileNames.join(temp, fileName + "." + fileEnding); return temp.join(fileName + "." + fileEnding);
} }
@SneakyThrows @SneakyThrows
public static String createExecScript(ShellControl processControl, String content) { public static FilePath createExecScript(ShellControl processControl, String content) {
return createExecScript(processControl.getShellDialect(), processControl, content); return createExecScript(processControl.getShellDialect(), processControl, content);
} }
@SneakyThrows @SneakyThrows
public static String createExecScript(ShellDialect type, ShellControl processControl, String content) { public static FilePath createExecScript(ShellDialect type, ShellControl processControl, String content) {
var fileName = "exec-" + getScriptId(); var fileName = "exec-" + getScriptId();
var temp = processControl.getSystemTemporaryDirectory(); var temp = processControl.getSystemTemporaryDirectory();
var file = FileNames.join(temp, fileName + "." + type.getScriptFileEnding()); var file = temp.join(fileName + "." + type.getScriptFileEnding());
return createExecScript(type, processControl, file, content); return createExecScript(type, processControl, file, content);
} }
@SneakyThrows @SneakyThrows
public static String createExecScript(ShellDialect type, ShellControl processControl, String file, String content) { public static FilePath createExecScript(ShellDialect type, ShellControl processControl, FilePath file, String content) {
content = type.prepareScriptContent(content); content = type.prepareScriptContent(content);
TrackEvent.withTrace("Writing exec script") TrackEvent.withTrace("Writing exec script")
@ -114,12 +114,12 @@ public class ScriptHelper {
processControl processControl
.getShellDialect() .getShellDialect()
.createScriptTextFileWriteCommand(processControl, content, file) .createScriptTextFileWriteCommand(processControl, content, file.toString())
.execute(); .execute();
return file; return file;
} }
public static String createRemoteAskpassScript(ShellControl parent, UUID requestId, String prefix) public static FilePath createRemoteAskpassScript(ShellControl parent, UUID requestId, String prefix)
throws Exception { throws Exception {
var type = parent.getShellDialect(); var type = parent.getShellDialect();
@ -130,7 +130,7 @@ public class ScriptHelper {
var fileName = "exec-" + getScriptId() + "." + type.getScriptFileEnding(); var fileName = "exec-" + getScriptId() + "." + type.getScriptFileEnding();
var temp = parent.getSystemTemporaryDirectory(); var temp = parent.getSystemTemporaryDirectory();
var file = FileNames.join(temp, fileName); var file = temp.join(fileName);
if (type != parent.getShellDialect()) { if (type != parent.getShellDialect()) {
try (var sub = parent.subShell(type).start()) { try (var sub = parent.subShell(type).start()) {
var content = var content =
@ -144,12 +144,12 @@ public class ScriptHelper {
} }
} }
public static String createTerminalPreparedAskpassScript( public static FilePath createTerminalPreparedAskpassScript(
SecretValue pass, ShellControl parent, boolean forceExecutable) throws Exception { SecretValue pass, ShellControl parent, boolean forceExecutable) throws Exception {
return createTerminalPreparedAskpassScript(pass != null ? List.of(pass) : List.of(), parent, forceExecutable); return createTerminalPreparedAskpassScript(pass != null ? List.of(pass) : List.of(), parent, forceExecutable);
} }
public static String createTerminalPreparedAskpassScript( public static FilePath createTerminalPreparedAskpassScript(
List<SecretValue> pass, ShellControl parent, boolean forceExecutable) throws Exception { List<SecretValue> pass, ShellControl parent, boolean forceExecutable) throws Exception {
var scriptType = parent.getShellDialect(); var scriptType = parent.getShellDialect();
@ -161,18 +161,18 @@ public class ScriptHelper {
return createTerminalPreparedAskpassScript(pass, parent, scriptType); return createTerminalPreparedAskpassScript(pass, parent, scriptType);
} }
private static String createTerminalPreparedAskpassScript( private static FilePath createTerminalPreparedAskpassScript(
List<SecretValue> pass, ShellControl parent, ShellDialect type) throws Exception { List<SecretValue> pass, ShellControl parent, ShellDialect type) throws Exception {
var fileName = "exec-" + getScriptId() + "." + type.getScriptFileEnding(); var fileName = "exec-" + getScriptId() + "." + type.getScriptFileEnding();
var temp = parent.getSystemTemporaryDirectory(); var temp = parent.getSystemTemporaryDirectory();
var file = FileNames.join(temp, fileName); var file = temp.join(fileName);
if (type != parent.getShellDialect()) { if (type != parent.getShellDialect()) {
try (var sub = parent.subShell(type).start()) { try (var sub = parent.subShell(type).start()) {
var content = sub.getShellDialect() var content = sub.getShellDialect()
.getAskpass() .getAskpass()
.prepareFixedContent( .prepareFixedContent(
sub, sub,
file, file.toString(),
pass.stream() pass.stream()
.map(secretValue -> secretValue.getSecretValue()) .map(secretValue -> secretValue.getSecretValue())
.toList()); .toList());
@ -183,7 +183,7 @@ public class ScriptHelper {
.getAskpass() .getAskpass()
.prepareFixedContent( .prepareFixedContent(
parent, parent,
file, file.toString(),
pass.stream() pass.stream()
.map(secretValue -> secretValue.getSecretValue()) .map(secretValue -> secretValue.getSecretValue())
.toList()); .toList());

View file

@ -4,6 +4,7 @@ import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.core.process.OsType; import io.xpipe.core.process.OsType;
import io.xpipe.core.process.ShellControl; import io.xpipe.core.process.ShellControl;
import io.xpipe.core.store.FileNames; import io.xpipe.core.store.FileNames;
import io.xpipe.core.store.FilePath;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import java.io.IOException; import java.io.IOException;
@ -34,37 +35,37 @@ public class ShellTemp {
return temp.resolve(sub); return temp.resolve(sub);
} }
public static String getUserSpecificTempDataDirectory(ShellControl proc, String sub) throws Exception { public static FilePath getUserSpecificTempDataDirectory(ShellControl proc, String sub) throws Exception {
String base; FilePath base;
// On Windows and macOS, we already have user specific temp directories // On Windows and macOS, we already have user specific temp directories
// Even on macOS as root it is technically unique as only root will use /tmp // Even on macOS as root it is technically unique as only root will use /tmp
if (!proc.getOsType().equals(OsType.WINDOWS) && !proc.getOsType().equals(OsType.MACOS)) { if (!proc.getOsType().equals(OsType.WINDOWS) && !proc.getOsType().equals(OsType.MACOS)) {
var temp = proc.getSystemTemporaryDirectory(); var temp = proc.getSystemTemporaryDirectory();
base = FileNames.join(temp, "xpipe"); base = temp.join("xpipe");
// We have to make sure that also other users can create files here // We have to make sure that also other users can create files here
// This command should work in all shells // This command should work in all shells
proc.command("chmod 777 " + proc.getShellDialect().fileArgument(base)) proc.command("chmod 777 " + proc.getShellDialect().fileArgument(base))
.executeAndCheck(); .executeAndCheck();
var user = proc.getShellDialect().printUsernameCommand(proc).readStdoutOrThrow(); var user = proc.getShellDialect().printUsernameCommand(proc).readStdoutOrThrow();
base = FileNames.join(base, user); base = temp.join(user);
} else { } else {
var temp = proc.getSystemTemporaryDirectory(); var temp = proc.getSystemTemporaryDirectory();
base = FileNames.join(temp, "xpipe"); base = temp.join("xpipe");
} }
return FileNames.join(base, sub); return base.join(sub);
} }
public static void checkTempDirectory(ShellControl proc) throws Exception { public static void checkTempDirectory(ShellControl proc) throws Exception {
var d = proc.getShellDialect(); var d = proc.getShellDialect();
var systemTemp = proc.getSystemTemporaryDirectory(); var systemTemp = proc.getSystemTemporaryDirectory();
if (!d.directoryExists(proc, systemTemp).executeAndCheck() || !checkDirectoryPermissions(proc, systemTemp)) { if (!d.directoryExists(proc, systemTemp.toString()).executeAndCheck() || !checkDirectoryPermissions(proc, systemTemp.toString())) {
throw ErrorEvent.expected(new IOException("No permissions to access %s".formatted(systemTemp))); throw ErrorEvent.expected(new IOException("No permissions to access %s".formatted(systemTemp)));
} }
// Always delete legacy directory and do not care whether it partially fails // Always delete legacy directory and do not care whether it partially fails
// This system xpipe temp directory might contain other files on the local machine, so only clear the exec // This system xpipe temp directory might contain other files on the local machine, so only clear the exec
d.deleteFileOrDirectory(proc, FileNames.join(systemTemp, "xpipe", "exec")) d.deleteFileOrDirectory(proc, systemTemp.join("xpipe", "exec").toString())
.executeAndCheck(); .executeAndCheck();
var home = proc.getOsType().getHomeDirectory(proc); var home = proc.getOsType().getHomeDirectory(proc);
d.deleteFileOrDirectory(proc, FileNames.join(home, ".xpipe", "temp")).executeAndCheck(); d.deleteFileOrDirectory(proc, FileNames.join(home, ".xpipe", "temp")).executeAndCheck();

View file

@ -36,7 +36,7 @@ public class TerminalLauncherManager {
try { try {
var file = ScriptHelper.createLocalExecScript(processControl.prepareTerminalOpen(config, workingDirectory)); var file = ScriptHelper.createLocalExecScript(processControl.prepareTerminalOpen(config, workingDirectory));
entry.setResult(new ResultSuccess(Path.of(file))); entry.setResult(new ResultSuccess(Path.of(file.toString())));
} catch (Exception e) { } catch (Exception e) {
entry.setResult(new ResultFailure(e)); entry.setResult(new ResultFailure(e));
} }

View file

@ -1,5 +1,6 @@
package io.xpipe.core.process; package io.xpipe.core.process;
import io.xpipe.core.store.FilePath;
import io.xpipe.core.util.FailableConsumer; import io.xpipe.core.util.FailableConsumer;
import io.xpipe.core.util.FailableFunction; import io.xpipe.core.util.FailableFunction;
import lombok.Getter; import lombok.Getter;
@ -185,6 +186,10 @@ public class CommandBuilder {
return this; return this;
} }
public CommandBuilder addFile(FilePath s) {
return addFile(shellControl -> shellControl.getShellDialect().fileArgument(s));
}
public CommandBuilder addLiteral(String s) { public CommandBuilder addLiteral(String s) {
elements.add(sc -> { elements.add(sc -> {
if (s == null) { if (s == null) {

View file

@ -1,5 +1,6 @@
package io.xpipe.core.process; package io.xpipe.core.process;
import io.xpipe.core.store.FilePath;
import io.xpipe.core.store.ShellStore; import io.xpipe.core.store.ShellStore;
import io.xpipe.core.store.StatefulDataStore; import io.xpipe.core.store.StatefulDataStore;
import io.xpipe.core.util.FailableConsumer; import io.xpipe.core.util.FailableConsumer;
@ -92,7 +93,7 @@ public interface ShellControl extends ProcessControl {
FailableFunction<ShellControl, String, Exception> workingDirectory) FailableFunction<ShellControl, String, Exception> workingDirectory)
throws Exception; throws Exception;
String getSystemTemporaryDirectory(); FilePath getSystemTemporaryDirectory();
default CommandControl osascriptCommand(String script) { default CommandControl osascriptCommand(String script) {
return command(String.format( return command(String.format(

View file

@ -1,6 +1,7 @@
package io.xpipe.core.process; package io.xpipe.core.process;
import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeInfo;
import io.xpipe.core.store.FilePath;
import io.xpipe.core.store.FileSystem; import io.xpipe.core.store.FileSystem;
import io.xpipe.core.util.NewLine; import io.xpipe.core.util.NewLine;
import io.xpipe.core.util.SecretValue; import io.xpipe.core.util.SecretValue;
@ -51,6 +52,10 @@ public interface ShellDialect {
String fileArgument(String s); String fileArgument(String s);
default String fileArgument(FilePath s) {
return fileArgument(s.toString());
}
String quoteArgument(String s); String quoteArgument(String s);
String prepareTerminalEnvironmentCommands(); String prepareTerminalEnvironmentCommands();

View file

@ -114,9 +114,7 @@ public abstract class ScriptStore extends JacksonizedValue implements DataStore,
.mapToInt(value -> .mapToInt(value ->
value.get().getName().hashCode() + value.getStore().hashCode()) value.get().getName().hashCode() + value.getStore().hashCode())
.sum(); .sum();
var targetDir = FileNames.join( var targetDir = ShellTemp.getUserSpecificTempDataDirectory(proc, "scripts").join(proc.getShellDialect().getId()).toString();
ShellTemp.getUserSpecificTempDataDirectory(proc, "scripts"),
proc.getShellDialect().getId());
var hashFile = FileNames.join(targetDir, "hash"); var hashFile = FileNames.join(targetDir, "hash");
var d = proc.getShellDialect(); var d = proc.getShellDialect();
if (d.createFileExistsCommand(proc, hashFile).executeAndCheck()) { if (d.createFileExistsCommand(proc, hashFile).executeAndCheck()) {

View file

@ -39,7 +39,7 @@ public class SimpleScriptStore extends ScriptStore implements ScriptSnippet {
.collect(Collectors.joining( .collect(Collectors.joining(
shellControl.getShellDialect().getNewLine().getNewLineString())); shellControl.getShellDialect().getNewLine().getNewLineString()));
var script = ScriptHelper.createExecScript(targetType, shellControl, fixedCommands); var script = ScriptHelper.createExecScript(targetType, shellControl, fixedCommands);
return targetType.sourceScriptCommand(shellControl, script); return targetType.sourceScriptCommand(shellControl, script.toString());
} }
return null; return null;