mirror of
https://github.com/xpipe-io/xpipe.git
synced 2026-05-29 16:11:03 +00:00
Rework on shells
This commit is contained in:
@@ -11,6 +11,8 @@ public interface OsType {
|
||||
Linux LINUX = new Linux();
|
||||
Mac MAC = new Mac();
|
||||
|
||||
String getScriptFileEnding();
|
||||
|
||||
String getName();
|
||||
|
||||
String getTempDirectory(ShellProcessControl pc) throws Exception;
|
||||
@@ -40,6 +42,11 @@ public interface OsType {
|
||||
|
||||
static class Windows implements OsType {
|
||||
|
||||
@Override
|
||||
public String getScriptFileEnding() {
|
||||
return "bat";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Windows";
|
||||
@@ -98,6 +105,11 @@ public interface OsType {
|
||||
return String.join("/", file.split("[\\\\/]+"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getScriptFileEnding() {
|
||||
return "sh";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Linux";
|
||||
@@ -168,6 +180,11 @@ public interface OsType {
|
||||
return String.join("/", file.split("[\\\\/]+"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getScriptFileEnding() {
|
||||
return "sh";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Mac";
|
||||
|
||||
@@ -11,6 +11,12 @@ import java.util.stream.Collectors;
|
||||
|
||||
public interface ShellProcessControl extends ProcessControl {
|
||||
|
||||
default String prepareOpen() throws Exception {
|
||||
return prepareOpen(null);
|
||||
}
|
||||
|
||||
String prepareOpen(String content) throws Exception;
|
||||
|
||||
default String executeSimpleCommand(String command) throws Exception {
|
||||
try (CommandProcessControl c = command(command).start()) {
|
||||
return c.readOrThrow();
|
||||
|
||||
@@ -10,6 +10,10 @@ import java.util.stream.Collectors;
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
|
||||
public interface ShellType {
|
||||
|
||||
String createInitFileContent(String command);
|
||||
|
||||
List<String> getOpenWithInitFileCommand(String file);
|
||||
|
||||
default String flatten(List<String> command) {
|
||||
return command.stream().map(s -> s.contains(" ") ? "\"" + s + "\"" : s).collect(Collectors.joining(" "));
|
||||
}
|
||||
@@ -65,5 +69,7 @@ public interface ShellType {
|
||||
|
||||
String getDisplayName();
|
||||
|
||||
String getExecutable();
|
||||
|
||||
boolean echoesInput();
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.xpipe.core.process;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import io.xpipe.core.charsetter.NewLine;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Value;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
@@ -17,6 +18,7 @@ public class ShellTypes {
|
||||
public static final ShellType POWERSHELL = new PowerShell();
|
||||
public static final ShellType CMD = new Cmd();
|
||||
public static final ShellType SH = new Sh();
|
||||
public static final ShellType BASH = new Bash();
|
||||
|
||||
public static ShellType getRecommendedDefault() {
|
||||
if (System.getProperty("os.name").startsWith("Windows")) {
|
||||
@@ -39,7 +41,7 @@ public class ShellTypes {
|
||||
}
|
||||
|
||||
public static ShellType[] getLinuxShells() {
|
||||
return new ShellType[] {SH};
|
||||
return new ShellType[] {BASH, SH};
|
||||
}
|
||||
|
||||
@JsonTypeName("cmd")
|
||||
@@ -79,11 +81,21 @@ public class ShellTypes {
|
||||
return "&";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getOpenWithInitFileCommand(String file) {
|
||||
return List.of(getExecutable(), "/V:on", "/K", file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escape(String input) {
|
||||
return input;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createInitFileContent(String command) {
|
||||
return "@echo off\n" + command;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void elevate(ShellProcessControl control, String command, String displayCommand) throws Exception {
|
||||
try (CommandProcessControl c = control.command("net session >NUL 2>NUL")) {
|
||||
@@ -163,6 +175,11 @@ public class ShellTypes {
|
||||
return "cmd";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExecutable() {
|
||||
return "C:\\Windows\\System32\\cmd.exe";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean echoesInput() {
|
||||
return true;
|
||||
@@ -173,6 +190,11 @@ public class ShellTypes {
|
||||
@Value
|
||||
public static class PowerShell implements ShellType {
|
||||
|
||||
@Override
|
||||
public String getExecutable() {
|
||||
return "C:\\Windows\\System32\\powershell.exe";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrintVariableCommand(String name) {
|
||||
return "echo %" + name + "%";
|
||||
@@ -205,6 +227,16 @@ public class ShellTypes {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createInitFileContent(String command) {
|
||||
return "@echo off\n" + command;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getOpenWithInitFileCommand(String file) {
|
||||
return List.of("powershell.exe", "-NoExit", "-ExecutionPolicy", "Bypass", "-File", file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escape(String input) {
|
||||
return input;
|
||||
@@ -298,9 +330,14 @@ public class ShellTypes {
|
||||
}
|
||||
}
|
||||
|
||||
@JsonTypeName("sh")
|
||||
@Value
|
||||
public static class Sh implements ShellType {
|
||||
public abstract static class PosixBase implements ShellType {
|
||||
|
||||
public abstract String getName();
|
||||
|
||||
@Override
|
||||
public String createInitFileContent(String command) {
|
||||
return "echo a\n" + command + "\necho b";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrintVariableCommand(String name) {
|
||||
@@ -317,9 +354,14 @@ public class ShellTypes {
|
||||
return ";";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getOpenWithInitFileCommand(String file) {
|
||||
return List.of(getExecutable(), "--init-file", file, "-i", "-l");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escape(String input) {
|
||||
return input.replace("$","\\$");
|
||||
return input.replace("$", "\\$");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -344,7 +386,6 @@ public class ShellTypes {
|
||||
return "echo " + s + (toErrorStream ? " 1>&2" : "");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String queryShellProcessId(ShellProcessControl control) throws Exception {
|
||||
try (CommandProcessControl c = control.command("echo $$").start()) {
|
||||
@@ -362,12 +403,12 @@ public class ShellTypes {
|
||||
|
||||
@Override
|
||||
public List<String> openCommand() {
|
||||
return List.of("sh", "-i", "-l");
|
||||
return List.of(getName(), "-i", "-l");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String switchTo(String cmd) {
|
||||
return "sh -c \"" + cmd + "\"";
|
||||
return getName() + " -c \"" + cmd + "\"";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -401,8 +442,19 @@ public class ShellTypes {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "sh";
|
||||
public boolean echoesInput() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@JsonTypeName("sh")
|
||||
@Value
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public static class Sh extends PosixBase {
|
||||
|
||||
@Override
|
||||
public String getExecutable() {
|
||||
return "/bin/sh";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -411,8 +463,29 @@ public class ShellTypes {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean echoesInput() {
|
||||
return false;
|
||||
public String getName() {
|
||||
return "sh";
|
||||
}
|
||||
}
|
||||
|
||||
@JsonTypeName("bash")
|
||||
@Value
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public static class Bash extends PosixBase {
|
||||
|
||||
@Override
|
||||
public String getExecutable() {
|
||||
return "/bin/bash";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return "/bin/bash";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "bash";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
package io.xpipe.core.store;
|
||||
|
||||
public class DataStoreFormatter {
|
||||
|
||||
public static String ellipsis(String input, int length) {
|
||||
if (input == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
var end = Math.min(input.length(), length);
|
||||
if (end < input.length()) {
|
||||
return input.substring(0, end) + "...";
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
public static String specialFormatHostName(String input) {
|
||||
if (input.contains(":")) {
|
||||
input = input.split(":")[0];
|
||||
}
|
||||
|
||||
if (input.endsWith(".rds.amazonaws.com")) {
|
||||
var split = input.split("\\.");
|
||||
var name = split[0];
|
||||
var region = split[2];
|
||||
return String.format("RDS %s @ %s", name, region);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,7 @@ public class CoreJacksonModule extends SimpleModule {
|
||||
new NamedType(WildcardType.class),
|
||||
new NamedType(ShellTypes.Cmd.class),
|
||||
new NamedType(ShellTypes.PowerShell.class),
|
||||
new NamedType(ShellTypes.Sh.class),
|
||||
new NamedType(ShellTypes.PosixBase.class),
|
||||
new NamedType(BaseQueryElement.class),
|
||||
new NamedType(ChoiceElement.class),
|
||||
new NamedType(BusyElement.class),
|
||||
|
||||
@@ -31,6 +31,10 @@ public interface DataStoreActionProvider<T extends DataStore> {
|
||||
|
||||
Class<T> getApplicableClass();
|
||||
|
||||
default boolean isMajor() {
|
||||
return false;
|
||||
}
|
||||
|
||||
default boolean isActive() throws Exception {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -30,11 +30,16 @@ public interface PrefsChoiceValue extends Translatable {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static <T extends PrefsChoiceValue> List<T> getSupported(Class<T> type) {
|
||||
static <T> List<T> getSupported(Class<T> type) {
|
||||
try {
|
||||
return (List<T>) type.getDeclaredField("SUPPORTED").get(null);
|
||||
} catch (IllegalAccessException | NoSuchFieldException e) {
|
||||
return getAll(type).stream().filter(t -> t.isSupported()).toList();
|
||||
var all = getAll(type);
|
||||
if (all == null) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
return all.stream().filter(t -> ((PrefsChoiceValue)t).isSupported()).toList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package io.xpipe.extension.util;
|
||||
|
||||
import io.xpipe.core.store.DataStore;
|
||||
import io.xpipe.core.store.ShellStore;
|
||||
import io.xpipe.extension.DataStoreProviders;
|
||||
|
||||
import java.util.function.IntFunction;
|
||||
|
||||
public class DataStoreFormatter {
|
||||
|
||||
public static String formatAtHost(IntFunction<String> func, DataStore at, int length) {
|
||||
var atString = at instanceof ShellStore shellStore && !ShellStore.isLocal(shellStore)
|
||||
? DataStoreProviders.byStore(at).toSummaryString(at, length)
|
||||
: null;
|
||||
if (atString == null) {
|
||||
return func.apply(length);
|
||||
}
|
||||
|
||||
var fileString = func.apply(length - atString.length() - 3);
|
||||
return String.format("%s @ %s", fileString, atString);
|
||||
}
|
||||
|
||||
public static String format(DataStore input, int length) {
|
||||
var named = XPipeDaemon.getInstance().getStoreName(input);
|
||||
if (named.isPresent()) {
|
||||
return cut(named.get(), length);
|
||||
}
|
||||
|
||||
return DataStoreProviders.byStore(input).toSummaryString(input, length);
|
||||
}
|
||||
|
||||
public static String cut(String input, int length) {
|
||||
if (input == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
var end = Math.min(input.length(), length);
|
||||
if (end < input.length()) {
|
||||
return input.substring(0, end) + "...";
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
public static String formatHostName(String input, int length) {
|
||||
// Remove port
|
||||
if (input.contains(":")) {
|
||||
input = input.split(":")[0];
|
||||
}
|
||||
|
||||
// Check for amazon web services
|
||||
if (input.endsWith(".rds.amazonaws.com")) {
|
||||
var split = input.split("\\.");
|
||||
var name = split[0];
|
||||
var region = split[2];
|
||||
var lengthShare = (length - 3) / 2;
|
||||
return String.format(
|
||||
"%s @ %s",
|
||||
DataStoreFormatter.cut(name, lengthShare), DataStoreFormatter.cut(region, length - lengthShare));
|
||||
}
|
||||
|
||||
return cut(input, length);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user