Update readme

This commit is contained in:
crschnick 2023-02-28 14:22:49 +00:00
parent 1bde4c8909
commit d5a7e2fb64
17 changed files with 91 additions and 47 deletions

View file

@ -1,12 +1,12 @@
<img src="https://user-images.githubusercontent.com/72509152/213873342-7638e830-8a95-4b5d-ad3e-5a9a0b4bf538.png" alt="drawing" width="300"/>
### Next level remote data workflows for everyone
### A smart connection manager and remote file explorer
X-Pipe is a connection manager, remote file explorer, and more in an early alpha.
The core approach is to utilize and integrate well with other tools and workflows,
X-Pipe takes a fresh spin on the established concept of connection managers.
The central idea is to utilize and integrate well with your existing tools and workflows,
focusing on augmenting them rather than replacing them.
X-Pipe is built around existing tools and tries to outsource tasks to them,
such that you can always use your favorite tools to work with X-Pipe, e.g.
X-Pipe outsources as many tasks as possible such
that you can always use your favorite tools to work with X-Pipe, e.g.
text/code editors, terminals, shells, command-line tools and more.
The X-Pipe platform is open source and designed to be extensible, allowing anyone
to implement custom functionality through custom extensions.

View file

@ -39,7 +39,8 @@ public class OpenFileSystemComp extends SimpleComp {
var path = new SimpleStringProperty(model.getCurrentPath().get());
var pathBar = new TextFieldComp(path, true).createRegion();
path.addListener((observable, oldValue, newValue) -> {
model.cd(newValue);
var changed = model.cd(newValue);
changed.ifPresent(path::set);
});
model.getCurrentPath().addListener((observable, oldValue, newValue) -> {
path.set(newValue);

View file

@ -6,6 +6,7 @@ import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.util.BusyProperty;
import io.xpipe.app.util.TerminalHelper;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.core.impl.LocalStore;
import io.xpipe.core.store.ConnectionFileSystem;
import io.xpipe.core.store.FileSystem;
import io.xpipe.core.store.FileSystemStore;
@ -18,6 +19,7 @@ import java.nio.file.Path;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@Getter
@ -51,25 +53,27 @@ final class OpenFileSystemModel {
return new FileSystem.FileEntry(fileSystem, currentPath.get(), Instant.now(), true, false, false, 0);
}
public void cd(String path) {
public Optional<String> cd(String path) {
var newPath = FileSystemHelper.normalizeDirectoryPath(this, path);
if (!path.equals(newPath)) {
return Optional.of(newPath);
}
ThreadHelper.runFailableAsync(() -> {
try (var ignored = new BusyProperty(busy)) {
cdSync(path);
}
});
return Optional.empty();
}
private boolean cdSync(String path) {
private void cdSync(String path) {
path = FileSystemHelper.normalizeDirectoryPath(this, path);
if (!navigateToSync(path)) {
return false;
}
navigateToSync(path);
filter.setValue(null);
currentPath.set(path);
history.cd(path);
return true;
}
private boolean navigateToSync(String dir) {
@ -85,6 +89,7 @@ final class OpenFileSystemModel {
fileList.setAll(newList);
return true;
} catch (Exception e) {
fileList.setAll(List.of());
ErrorEvent.fromThrowable(e).handle();
return false;
}
@ -171,7 +176,7 @@ final class OpenFileSystemModel {
fs.open();
this.fileSystem = fs;
var current = fs instanceof ConnectionFileSystem connectionFileSystem
var current = !(fileSystem instanceof LocalStore) && fs instanceof ConnectionFileSystem connectionFileSystem
? connectionFileSystem
.getShellProcessControl()
.executeStringSimpleCommand(connectionFileSystem

View file

@ -66,7 +66,8 @@ public class AppGreetings {
}
public static void showIfNeeded() {
if (!AppProperties.get().isImage()) {
//TODO
if (!AppProperties.get().isImage() || true) {
return;
}

View file

@ -66,7 +66,11 @@ public class SentryErrorHandler {
s.setTag("terminal", Boolean.toString(ee.isTerminal()));
s.setTag("omitted", Boolean.toString(ee.isOmitted()));
ee.getTrackEvents().forEach(t -> s.addBreadcrumb(toBreadcrumb(t)));
/*
TODO: Ignore breadcrumbs for now
*/
// ee.getTrackEvents().forEach(t -> s.addBreadcrumb(toBreadcrumb(t)));
if (ee.getThrowable() != null) {
if (ee.getDescription() != null

View file

@ -5,7 +5,6 @@ import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.core.impl.LocalStore;
import io.xpipe.core.process.OsType;
import io.xpipe.core.process.ShellProcessControl;
import io.xpipe.core.store.ShellStore;
import java.nio.file.Files;
import java.nio.file.Path;
@ -38,7 +37,7 @@ public abstract class ExternalApplicationType implements PrefsChoiceValue {
}
protected Optional<Path> getApplicationPath() {
try (ShellProcessControl pc = ShellStore.createLocal().create().start()) {
try (ShellProcessControl pc = LocalStore.getShell().start()) {
try (var c = pc.command(String.format(
"/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister "
+ "-dump | grep -o \"/.*%s.app\" | grep -v -E \"Caches|TimeMachine|Temporary|/Volumes/%s\" | uniq",

View file

@ -2,7 +2,6 @@ package io.xpipe.app.util;
import io.xpipe.core.impl.LocalStore;
import io.xpipe.core.process.OsType;
import io.xpipe.core.store.ShellStore;
import io.xpipe.core.util.XPipeInstallation;
import java.nio.file.Files;
@ -21,7 +20,7 @@ public class DesktopShortcuts {
%%PWS%% -Command "$ws = New-Object -ComObject WScript.Shell; $s = $ws.CreateShortcut('%%SHORTCUT%%'); $S.IconLocation='%s'; $S.TargetPath = '%%TARGET%%'; $S.Save()"
""",
target, name, icon.toString());
ShellStore.createLocal().create().executeSimpleCommand(content);
LocalStore.getShell().executeSimpleCommand(content);
}
private static void createLinuxShortcut(String target, String name) throws Exception {

View file

@ -3,9 +3,9 @@ package io.xpipe.app.util;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.core.impl.FileNames;
import io.xpipe.core.impl.LocalStore;
import io.xpipe.core.process.OsType;
import io.xpipe.core.store.FileSystem;
import io.xpipe.core.store.ShellStore;
import org.apache.commons.io.FilenameUtils;
import java.nio.file.Path;
@ -65,7 +65,7 @@ public class FileOpener {
}
public static void openInDefaultApplication(String file) {
try (var pc = ShellStore.createLocal().create().start()) {
try (var pc = LocalStore.getShell().start()) {
if (pc.getOsType().equals(OsType.WINDOWS)) {
pc.executeSimpleCommand("\"" + file + "\"");
} else if (pc.getOsType().equals(OsType.LINUX)) {

View file

@ -2,7 +2,7 @@ package io.xpipe.app.util;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.core.AppWindowHelper;
import io.xpipe.core.store.ShellStore;
import io.xpipe.core.impl.LocalStore;
import javafx.application.Platform;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.scene.control.Alert;
@ -14,7 +14,7 @@ public class MacOsPermissions {
public static boolean waitForAccessibilityPermissions() throws Exception {
AtomicReference<Alert> alert = new AtomicReference<>();
var state = new SimpleBooleanProperty(true);
try (var pc = ShellStore.createLocal().create().start()) {
try (var pc = LocalStore.getShell().start()) {
while (state.get()) {
var success = pc.executeBooleanSimpleCommand(
"osascript -e 'tell application \"System Events\" to keystroke \"t\"'");

View file

@ -2,11 +2,11 @@ package io.xpipe.app.util;
import io.xpipe.app.issue.TrackEvent;
import io.xpipe.core.impl.FileNames;
import io.xpipe.core.impl.LocalStore;
import io.xpipe.core.process.OsType;
import io.xpipe.core.process.ShellProcessControl;
import io.xpipe.core.process.ShellDialect;
import io.xpipe.core.process.ShellDialects;
import io.xpipe.core.store.ShellStore;
import io.xpipe.core.process.ShellProcessControl;
import io.xpipe.core.util.SecretValue;
import lombok.SneakyThrows;
@ -42,7 +42,7 @@ public class ScriptHelper {
@SneakyThrows
public static String createLocalExecScript(String content) {
try (var l = ShellStore.createLocal().create().start()) {
try (var l = LocalStore.getShell().start()) {
return createExecScript(l, content);
}
}
@ -167,6 +167,19 @@ public class ScriptHelper {
return t.getInitFileOpenCommand(initFile);
}
@SneakyThrows
public static String getExecScriptFile(ShellProcessControl processControl) {
return getExecScriptFile(processControl, processControl.getShellDialect().getScriptFileEnding());
}
@SneakyThrows
public static String getExecScriptFile(ShellProcessControl processControl, String fileEnding) {
var fileName = "exec-" + getScriptId();
var temp = processControl.getTemporaryDirectory();
var file = FileNames.join(temp, fileName + "." + fileEnding);
return file;
}
@SneakyThrows
public static String createExecScript(ShellProcessControl processControl, String content) {
var fileName = "exec-" + getScriptId();

View file

@ -18,11 +18,19 @@ public class FileNames {
}
public static String getFileName(String file) {
if (file.isEmpty()) {
return "";
}
var split = file.split("[\\\\/]");
if (split.length == 0) {
return "";
}
var components = Arrays.stream(split).filter(s -> !s.isEmpty()).toList();
if (components.size() == 0) {
return "";
}
return components.get(components.size() - 1);
}

View file

@ -4,12 +4,12 @@ import com.fasterxml.jackson.annotation.JsonTypeName;
import io.xpipe.core.process.ProcessControlProvider;
import io.xpipe.core.process.ShellDialects;
import io.xpipe.core.process.ShellProcessControl;
import io.xpipe.core.store.*;
import io.xpipe.core.store.ConnectionFileSystem;
import io.xpipe.core.store.FileSystem;
import io.xpipe.core.store.FileSystemStore;
import io.xpipe.core.store.ShellStore;
import io.xpipe.core.util.JacksonizedValue;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
@JsonTypeName("local")
@ -43,17 +43,6 @@ public class LocalStore extends JacksonizedValue implements ShellStore {
return LocalStore.this;
}
@Override
public InputStream openInput(String file) throws Exception {
var p = wrap(file);
return Files.newInputStream(p);
}
@Override
public OutputStream openOutput(String file) throws Exception {
var p = wrap(file);
return Files.newOutputStream(p);
}
private Path wrap(String file) {
for (var e : System.getenv().entrySet()) {

View file

@ -49,10 +49,16 @@ public interface CommandProcessControl extends ProcessControl {
public String readOrThrow() throws Exception;
public default boolean discardAndCheckExit() {
public default boolean discardAndCheckExit() throws ProcessOutputException {
try {
discardOrThrow();
return true;
} catch (ProcessOutputException ex) {
if (ex.isTimeOut()) {
throw ex;
}
return false;
} catch (Exception ex) {
return false;
}

View file

@ -25,4 +25,8 @@ public class ProcessOutputException extends Exception {
this.exitCode = exitCode;
this.output = output;
}
public boolean isTimeOut() {
return exitCode == -1;
}
}

View file

@ -17,6 +17,14 @@ public interface ShellDialect {
return "cd \"" + directory + "\"";
}
default String getPushdCommand(String directory){
return "pushd \"" + directory + "\"";
}
default String getPopdCommand(){
return "popd";
}
String getScriptFileEnding();
String addInlineVariablesToCommand(Map<String, String> variables, String command);
@ -39,8 +47,6 @@ public interface ShellDialect {
.collect(Collectors.joining(" "));
}
void disableHistory(ShellProcessControl pc) throws Exception;
default String getExitCommand() {
return "exit";
}

View file

@ -0,0 +1,10 @@
package io.xpipe.core.process;
import lombok.Value;
@Value
public class ShellProperties {
ShellDialect dialect;
boolean tty;
}

View file

@ -8,7 +8,6 @@ import io.xpipe.app.util.XPipeDaemon;
import io.xpipe.core.impl.LocalStore;
import io.xpipe.core.process.OsType;
import io.xpipe.core.store.DataStore;
import io.xpipe.core.store.ShellStore;
import java.util.List;
import java.util.UUID;
@ -17,7 +16,7 @@ public class LocalStoreProvider implements DataStoreProvider {
@Override
public String queryInformationString(DataStore store, int length) throws Exception {
try (var pc = ShellStore.createLocal().create().start()) {
try (var pc = LocalStore.getShell().start()) {
return OsType.getLocal().determineOperatingSystemName(pc);
}
}