mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-09-30 00:56:56 +13:00
Rework file paths and kitty support
This commit is contained in:
parent
c228e6ba30
commit
a8f07c3e0f
13 changed files with 130 additions and 68 deletions
|
@ -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")
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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) {
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue