From f304b660555f670c9abaa494fc3be933245d78a8 Mon Sep 17 00:00:00 2001 From: crschnick Date: Mon, 20 Feb 2023 09:49:10 +0000 Subject: [PATCH] Shell refactoring --- README.md | 17 ++++-- app/build.gradle | 2 +- .../xpipe/app/core/AppExtensionManager.java | 7 ++- .../java/io/xpipe/app/core/AppGreetings.java | 7 +++ .../java/io/xpipe/app/ext/ActionProvider.java | 2 +- .../io/xpipe/app/ext/DataSourceTarget.java | 2 +- .../java/io/xpipe/app/ext/PrefsProvider.java | 2 +- .../xpipe/app/ext/XPipeServiceProviders.java | 11 +++- .../xpipe/app/prefs/ExternalEditorType.java | 4 +- .../io/xpipe/app/update/AppInstaller.java | 12 ++-- .../io/xpipe/app/util/ApplicationHelper.java | 6 +- .../java/io/xpipe/app/util/ScriptHelper.java | 19 +++--- app/src/main/java/module-info.java | 1 + .../io/xpipe/app/resources/style/style.css | 4 ++ .../java/io/xpipe/beacon/BeaconServer.java | 6 +- .../java/io/xpipe/core/process/OsType.java | 2 +- .../io/xpipe/core/process/ProcessControl.java | 2 +- .../{ShellType.java => ShellDialect.java} | 4 +- .../io/xpipe/core/process/ShellDialects.java | 60 +++++++++++++++++++ .../core/process/ShellProcessControl.java | 4 +- .../java/io/xpipe/core/store/ShellStore.java | 8 +-- .../io/xpipe/core/util/CoreJacksonModule.java | 6 +- .../java/io/xpipe/core/util/Deobfuscator.java | 4 +- .../xpipe/core}/util/ModuleLayerLoader.java | 9 ++- core/src/main/java/module-info.java | 7 +++ ext/base/src/test/java/module-info.java | 4 +- ext/base/src/test/java/test/TextFileTest.java | 2 +- .../xpipe/ext/csv/test/CsvDetectorTest.java | 2 +- ext/csv/src/test/java/module-info.java | 2 +- ext/proc/build.gradle | 5 ++ ext/proc/src/main/java/module-info.java | 1 + gradle/gradle_scripts/extension.gradle | 1 + gradle/gradle_scripts/extension_test.gradle | 4 +- version | 2 +- 34 files changed, 165 insertions(+), 66 deletions(-) rename core/src/main/java/io/xpipe/core/process/{ShellType.java => ShellDialect.java} (98%) create mode 100644 core/src/main/java/io/xpipe/core/process/ShellDialects.java rename {app/src/main/java/io/xpipe/app => core/src/main/java/io/xpipe/core}/util/ModuleLayerLoader.java (82%) create mode 100644 ext/proc/build.gradle create mode 100644 ext/proc/src/main/java/module-info.java diff --git a/README.md b/README.md index 1913c603..10baba4b 100644 --- a/README.md +++ b/README.md @@ -76,15 +76,12 @@ https://user-images.githubusercontent.com/72509152/218265431-27bf34ad-03f8-43b7- The following for modules make up the X-Pipe API and a licensed under the MIT license: - [core](core) - Shared core classes of the X-Pipe Java API, X-Pipe extensions, and the X-Pipe daemon implementation -- [API](api) - The API that can be used to interact with X-Pipe from any JVM-based language. - For setup instructions, see the [X-Pipe Java API Usage](https://xpipe-io.readthedocs.io/en/latest/dev/api/java.html) section. - [beacon](beacon) - The X-Pipe beacon component is responsible for handling all communications between the X-Pipe daemon and the client applications, for example the various programming language APIs and the CLI -- [extension](extension) - An API to create all different kinds of extensions for the X-Pipe platform - For setup instructions, see the [X-Pipe extension development](https://xpipe-io.readthedocs.io/en/latest/dev/extensions/index.html) section. The other modules make up the X-Pipe implementation and are licensed under GPL: -- [app](app) - Contains the X-Pipe daemon implementation and the X-Pipe desktop application code +- [app](app) - Contains the X-Pipe daemon implementation, the X-Pipe desktop application, and an + API to create all different kinds of extensions for the X-Pipe platform - [dist](dist) - Tools to create a distributable package of X-Pipe - [ext](ext) - Available X-Pipe extensions. Essentially every feature is implemented as an extension @@ -92,7 +89,7 @@ The other modules make up the X-Pipe implementation and are licensed under GPL: X-Pipe utilizes an open core model, which essentially means that the main application core is open source while certain other components are not. -In this case these non open source components are planned to be future parts of a potential commercialization. +In this case these non open source components are planned to be future parts of a potential commercialization (got to make a living somehow). Furthermore, some tests and especially test environments and that run on private servers are also not included in this repository (Don't want to leak server information). Finally, scripts and workflows to create signed executables and installers @@ -119,6 +116,14 @@ many IDEs still have problems building this project properly. For example, you can't build this project in eclipse or vscode as it will complain about missing modules. The tested and recommended IDE is intellij. +### Setup + +You need to have an up-to-date version of X-Pipe installed on your local system in order to properly +run X-Pipe in a development environment. +This is due to the fact that some components are only included in the release version and not in this repository. +X-pipe is able to automatically detect your installation and fetch the required +components from it when it is run in a development environment. + ### Building and Running You can use the gradle wrapper to build and run the project: diff --git a/app/build.gradle b/app/build.gradle index 95ca73cf..2941ba4c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -132,7 +132,7 @@ application { run { systemProperty 'io.xpipe.app.mode', 'gui' - systemProperty 'io.xpipe.app.dataDir', "$projectDir/local_stage/" + systemProperty 'io.xpipe.app.dataDir', "$projectDir/local8/" systemProperty 'io.xpipe.app.writeLogs', "true" systemProperty 'io.xpipe.app.writeSysOut', "true" systemProperty 'io.xpipe.app.developerMode', "true" diff --git a/app/src/main/java/io/xpipe/app/core/AppExtensionManager.java b/app/src/main/java/io/xpipe/app/core/AppExtensionManager.java index 9722911c..650be8c9 100644 --- a/app/src/main/java/io/xpipe/app/core/AppExtensionManager.java +++ b/app/src/main/java/io/xpipe/app/core/AppExtensionManager.java @@ -72,7 +72,12 @@ public class AppExtensionManager { if (!AppProperties.get().isFullVersion()) { var localInstallation = XPipeInstallation.getLocalDefaultInstallationBasePath(true); - var extensions = XPipeInstallation.getLocalExtensionsDirectory(Path.of(localInstallation)); + Path p = Path.of(localInstallation); + if (!Files.exists(p)) { + throw new IllegalStateException("Required local X-Pipe installation not found"); + } + + var extensions = XPipeInstallation.getLocalExtensionsDirectory(p); extensionBaseDirectories.add(extensions); } diff --git a/app/src/main/java/io/xpipe/app/core/AppGreetings.java b/app/src/main/java/io/xpipe/app/core/AppGreetings.java index ba6ac798..bd72e073 100644 --- a/app/src/main/java/io/xpipe/app/core/AppGreetings.java +++ b/app/src/main/java/io/xpipe/app/core/AppGreetings.java @@ -66,6 +66,10 @@ public class AppGreetings { } public static void showIfNeeded() { + if (!AppProperties.get().isImage()) { + return; + } + boolean set = AppCache.get("legalAccepted", Boolean.class, () -> false); if (set) { return; @@ -95,8 +99,11 @@ public class AppGreetings { .createRegion(); var layout = new BorderPane(); + layout.getStyleClass().add("window-content"); layout.setCenter(accordion); layout.setBottom(acceptanceBox); + layout.setPrefWidth(700); + layout.setPrefHeight(600); alert.getDialogPane().setContent(layout); diff --git a/app/src/main/java/io/xpipe/app/ext/ActionProvider.java b/app/src/main/java/io/xpipe/app/ext/ActionProvider.java index 918261a7..e9c47fc1 100644 --- a/app/src/main/java/io/xpipe/app/ext/ActionProvider.java +++ b/app/src/main/java/io/xpipe/app/ext/ActionProvider.java @@ -1,7 +1,7 @@ package io.xpipe.app.ext; import io.xpipe.app.issue.ErrorEvent; -import io.xpipe.app.util.ModuleLayerLoader; +import io.xpipe.core.util.ModuleLayerLoader; import io.xpipe.core.source.DataSource; import io.xpipe.core.store.DataStore; import javafx.beans.value.ObservableValue; diff --git a/app/src/main/java/io/xpipe/app/ext/DataSourceTarget.java b/app/src/main/java/io/xpipe/app/ext/DataSourceTarget.java index ad26f67b..2095f2ac 100644 --- a/app/src/main/java/io/xpipe/app/ext/DataSourceTarget.java +++ b/app/src/main/java/io/xpipe/app/ext/DataSourceTarget.java @@ -1,6 +1,6 @@ package io.xpipe.app.ext; -import io.xpipe.app.util.ModuleLayerLoader; +import io.xpipe.core.util.ModuleLayerLoader; import io.xpipe.app.util.Validator; import io.xpipe.core.source.DataSource; import io.xpipe.core.source.DataSourceId; diff --git a/app/src/main/java/io/xpipe/app/ext/PrefsProvider.java b/app/src/main/java/io/xpipe/app/ext/PrefsProvider.java index fdb90810..54954cb4 100644 --- a/app/src/main/java/io/xpipe/app/ext/PrefsProvider.java +++ b/app/src/main/java/io/xpipe/app/ext/PrefsProvider.java @@ -1,7 +1,7 @@ package io.xpipe.app.ext; import com.dlsc.formsfx.model.structure.Field; -import io.xpipe.app.util.ModuleLayerLoader; +import io.xpipe.core.util.ModuleLayerLoader; import javafx.beans.value.ObservableBooleanValue; import java.util.ServiceLoader; diff --git a/app/src/main/java/io/xpipe/app/ext/XPipeServiceProviders.java b/app/src/main/java/io/xpipe/app/ext/XPipeServiceProviders.java index cbcbed0d..2c4e631e 100644 --- a/app/src/main/java/io/xpipe/app/ext/XPipeServiceProviders.java +++ b/app/src/main/java/io/xpipe/app/ext/XPipeServiceProviders.java @@ -1,8 +1,9 @@ package io.xpipe.app.ext; import com.fasterxml.jackson.databind.jsontype.NamedType; +import io.xpipe.app.issue.ErrorEvent; import io.xpipe.app.issue.TrackEvent; -import io.xpipe.app.util.ModuleLayerLoader; +import io.xpipe.core.util.ModuleLayerLoader; import io.xpipe.app.util.XPipeDaemon; import io.xpipe.core.process.ProcessControlProvider; import io.xpipe.core.util.JacksonMapper; @@ -12,7 +13,9 @@ public class XPipeServiceProviders { public static void load(ModuleLayer layer) { var hasDaemon = XPipeDaemon.getInstanceIfPresent().isPresent(); - ModuleLayerLoader.loadAll(layer, hasDaemon, true); + ModuleLayerLoader.loadAll(layer, hasDaemon, true, t -> { + ErrorEvent.fromThrowable(t).handle(); + }); ProcessControlProvider.init(layer); TrackEvent.info("Loading extension providers ..."); @@ -34,7 +37,9 @@ public class XPipeServiceProviders { }); } - ModuleLayerLoader.loadAll(layer, hasDaemon, false); + ModuleLayerLoader.loadAll(layer, hasDaemon, false, t -> { + ErrorEvent.fromThrowable(t).handle(); + }); if (hasDaemon) { ProxyFunction.init(layer); diff --git a/app/src/main/java/io/xpipe/app/prefs/ExternalEditorType.java b/app/src/main/java/io/xpipe/app/prefs/ExternalEditorType.java index 8dc3384f..b940325f 100644 --- a/app/src/main/java/io/xpipe/app/prefs/ExternalEditorType.java +++ b/app/src/main/java/io/xpipe/app/prefs/ExternalEditorType.java @@ -4,7 +4,7 @@ import io.xpipe.app.ext.PrefsChoiceValue; import io.xpipe.app.util.ApplicationHelper; import io.xpipe.app.util.WindowsRegistry; import io.xpipe.core.process.OsType; -import io.xpipe.core.process.ShellTypes; +import io.xpipe.core.process.ShellDialects; import java.io.IOException; import java.nio.file.Path; @@ -112,7 +112,7 @@ public interface ExternalEditorType extends PrefsChoiceValue { @Override public void launch(Path file) throws IOException { - var list = ShellTypes.getPlatformDefault().executeCommandListWithShell(executable + " \"" + file + "\""); + var list = ShellDialects.getPlatformDefault().executeCommandListWithShell(executable + " \"" + file + "\""); new ProcessBuilder(list).start(); } diff --git a/app/src/main/java/io/xpipe/app/update/AppInstaller.java b/app/src/main/java/io/xpipe/app/update/AppInstaller.java index cfcba943..76730f71 100644 --- a/app/src/main/java/io/xpipe/app/update/AppInstaller.java +++ b/app/src/main/java/io/xpipe/app/update/AppInstaller.java @@ -9,7 +9,7 @@ import io.xpipe.core.impl.FileNames; import io.xpipe.core.process.CommandProcessControl; import io.xpipe.core.process.OsType; import io.xpipe.core.process.ShellProcessControl; -import io.xpipe.core.process.ShellTypes; +import io.xpipe.core.process.ShellDialects; import io.xpipe.core.store.ShellStore; import io.xpipe.core.util.XPipeInstallation; import lombok.Getter; @@ -151,7 +151,7 @@ public class AppInstaller { shellProcessControl, XPipeInstallation.getDefaultInstallationBasePath(shellProcessControl, false)); var logsDir = FileNames.join(XPipeInstallation.getDataBasePath(shellProcessControl), "logs"); - var installer = ShellTypes.getPlatformDefault() + var installer = ShellDialects.getPlatformDefault() .flatten(List.of( "start", "/wait", @@ -161,7 +161,7 @@ public class AppInstaller { "/l*", FileNames.join(logsDir.toString(), "installer_" + FileNames.getFileName(file) + ".log"), "/qb")); - var start = ShellTypes.getPlatformDefault().flatten(List.of("start", "\"\"", exec)); + var start = ShellDialects.getPlatformDefault().flatten(List.of("start", "\"\"", exec)); var command = installer + "\r\n" + start; var script = ScriptHelper.createExecScript(shellProcessControl, command); shellProcessControl.executeSimpleCommand("start /min " + script); @@ -178,7 +178,7 @@ public class AppInstaller { @Override public void installRemote(ShellProcessControl shellProcessControl, String file) throws Exception { - try (var pc = shellProcessControl.subShell(ShellTypes.BASH).start()) { + try (var pc = shellProcessControl.subShell(ShellDialects.BASH).start()) { try (CommandProcessControl c = pc.command("DEBIAN_FRONTEND=noninteractive apt-get remove -qy xpipe") .elevated() .start()) { @@ -212,7 +212,7 @@ public class AppInstaller { @Override public void installRemote(ShellProcessControl shellProcessControl, String file) throws Exception { - try (var pc = shellProcessControl.subShell(ShellTypes.BASH).start()) { + try (var pc = shellProcessControl.subShell(ShellDialects.BASH).start()) { try (CommandProcessControl c = pc.command("rpm -U -v --force \"" + file + "\"") .elevated() .start()) { @@ -238,7 +238,7 @@ public class AppInstaller { @Override public void installRemote(ShellProcessControl shellProcessControl, String file) throws Exception { - try (var pc = shellProcessControl.subShell(ShellTypes.BASH).start()) { + try (var pc = shellProcessControl.subShell(ShellDialects.BASH).start()) { try (CommandProcessControl c = pc.command( "installer -verboseR -allowUntrusted -pkg \"" + file + "\" -target /") .elevated() diff --git a/app/src/main/java/io/xpipe/app/util/ApplicationHelper.java b/app/src/main/java/io/xpipe/app/util/ApplicationHelper.java index e848c1d5..9b0cbd55 100644 --- a/app/src/main/java/io/xpipe/app/util/ApplicationHelper.java +++ b/app/src/main/java/io/xpipe/app/util/ApplicationHelper.java @@ -2,7 +2,7 @@ package io.xpipe.app.util; import io.xpipe.app.issue.TrackEvent; import io.xpipe.core.process.ShellProcessControl; -import io.xpipe.core.process.ShellTypes; +import io.xpipe.core.process.ShellDialects; import io.xpipe.core.store.ShellStore; import java.io.IOException; @@ -11,7 +11,7 @@ import java.util.List; public class ApplicationHelper { public static void executeLocalApplication(String s) throws Exception { - var args = ShellTypes.getPlatformDefault().executeCommandListWithShell(s); + var args = ShellDialects.getPlatformDefault().executeCommandListWithShell(s); TrackEvent.withDebug("proc", "Executing local application") .elements(args) .handle(); @@ -21,7 +21,7 @@ public class ApplicationHelper { } public static void executeLocalApplication(List s) throws Exception { - var args = ShellTypes.getPlatformDefault().executeCommandListWithShell(s); + var args = ShellDialects.getPlatformDefault().executeCommandListWithShell(s); TrackEvent.withDebug("proc", "Executing local application") .elements(args) .handle(); diff --git a/app/src/main/java/io/xpipe/app/util/ScriptHelper.java b/app/src/main/java/io/xpipe/app/util/ScriptHelper.java index cd4d210b..32d5dcce 100644 --- a/app/src/main/java/io/xpipe/app/util/ScriptHelper.java +++ b/app/src/main/java/io/xpipe/app/util/ScriptHelper.java @@ -3,13 +3,12 @@ package io.xpipe.app.util; import io.xpipe.app.issue.TrackEvent; import io.xpipe.core.impl.FileNames; import io.xpipe.core.process.ShellProcessControl; -import io.xpipe.core.process.ShellType; -import io.xpipe.core.process.ShellTypes; +import io.xpipe.core.process.ShellDialect; +import io.xpipe.core.process.ShellDialects; import io.xpipe.core.store.ShellStore; import io.xpipe.core.util.SecretValue; import lombok.SneakyThrows; -import java.util.Arrays; import java.util.List; import java.util.Random; @@ -106,7 +105,7 @@ public class ScriptHelper { public static String constructOpenWithInitScriptCommand( ShellProcessControl processControl, List init, String toExecuteInShell) { - ShellType t = processControl.getShellType(); + ShellDialect t = processControl.getShellType(); if (init.size() == 0 && toExecuteInShell == null) { return t.getNormalOpenCommand(); } @@ -120,7 +119,7 @@ public class ScriptHelper { } // Check for special case of the command being a shell command - if (Arrays.stream(ShellTypes.getAllShellTypes()) + if (ShellDialects.ALL.stream() .anyMatch(shellType -> cmd.equals(shellType.getNormalOpenCommand()))) { return cmd; } @@ -129,7 +128,7 @@ public class ScriptHelper { String nl = t.getNewLine().getNewLineString(); var content = String.join(nl, init) + nl; - if (t.equals(ShellTypes.BASH)) { + if (t.equals(ShellDialects.BASH)) { content = "if [ -f ~/.bashrc ]; then . ~/.bashrc; fi\n" + content; } @@ -141,7 +140,7 @@ public class ScriptHelper { var initFile = createExecScript(processControl, content); - if (t.equals(ShellTypes.ZSH)) { + if (t.equals(ShellDialects.ZSH)) { var zshiFile = createExecScript(processControl, ZSHI); return t.getNormalOpenCommand() + " \"" + zshiFile + "\" \"" + initFile + "\""; } @@ -152,7 +151,7 @@ public class ScriptHelper { @SneakyThrows public static String createExecScript(ShellProcessControl processControl, String content) { var fileName = "exec-" + getScriptId(); - ShellType type = processControl.getShellType(); + ShellDialect type = processControl.getShellType(); var temp = processControl.getTemporaryDirectory(); var file = FileNames.join(temp, fileName + "." + type.getScriptFileEnding()); return createExecScript(processControl, file, content); @@ -160,7 +159,7 @@ public class ScriptHelper { @SneakyThrows private static String createExecScript(ShellProcessControl processControl, String file, String content) { - ShellType type = processControl.getShellType(); + ShellDialect type = processControl.getShellType(); content = type.prepareScriptContent(content); TrackEvent.withTrace("proc", "Writing exec script") @@ -176,7 +175,7 @@ public class ScriptHelper { } @SneakyThrows - public static String createAskPassScript(SecretValue pass, ShellProcessControl parent, ShellType type) { + public static String createAskPassScript(SecretValue pass, ShellProcessControl parent, ShellDialect type) { var content = type.getScriptEchoCommand(pass.getSecretValue()); var temp = parent.getTemporaryDirectory(); var file = FileNames.join(temp, "askpass-" + getScriptId() + "." + type.getScriptFileEnding()); diff --git a/app/src/main/java/module-info.java b/app/src/main/java/module-info.java index f2fbcc1a..e17d64e9 100644 --- a/app/src/main/java/module-info.java +++ b/app/src/main/java/module-info.java @@ -8,6 +8,7 @@ import io.xpipe.app.issue.EventHandlerImpl; import io.xpipe.app.storage.DataStateProviderImpl; import io.xpipe.app.util.*; import io.xpipe.core.util.DataStateProvider; +import io.xpipe.core.util.ModuleLayerLoader; import io.xpipe.core.util.ProxyFunction; import io.xpipe.core.util.ProxyManagerProvider; import org.slf4j.spi.SLF4JServiceProvider; diff --git a/app/src/main/resources/io/xpipe/app/resources/style/style.css b/app/src/main/resources/io/xpipe/app/resources/style/style.css index 4ab8a77d..293a66cb 100644 --- a/app/src/main/resources/io/xpipe/app/resources/style/style.css +++ b/app/src/main/resources/io/xpipe/app/resources/style/style.css @@ -11,6 +11,10 @@ -fx-border-radius: 2px; } +.radio-button { +-fx-background-color:transparent; +} + .icon-button-comp { -fx-padding: 0.05em; } diff --git a/beacon/src/main/java/io/xpipe/beacon/BeaconServer.java b/beacon/src/main/java/io/xpipe/beacon/BeaconServer.java index e462297f..9940d14f 100644 --- a/beacon/src/main/java/io/xpipe/beacon/BeaconServer.java +++ b/beacon/src/main/java/io/xpipe/beacon/BeaconServer.java @@ -3,7 +3,7 @@ package io.xpipe.beacon; import io.xpipe.beacon.exchange.StopExchange; import io.xpipe.core.impl.FileNames; import io.xpipe.core.process.OsType; -import io.xpipe.core.process.ShellTypes; +import io.xpipe.core.process.ShellDialects; import io.xpipe.core.util.XPipeDaemonMode; import io.xpipe.core.util.XPipeInstallation; @@ -28,7 +28,7 @@ public class BeaconServer { public static Process tryStartCustom() throws Exception { var custom = BeaconConfig.getCustomDaemonCommand(); if (custom != null) { - var command = ShellTypes.getPlatformDefault() + var command = ShellDialects.getPlatformDefault() .executeCommandListWithShell(custom + (BeaconConfig.getDaemonArguments() != null ? " " + BeaconConfig.getDaemonArguments() @@ -50,7 +50,7 @@ public class BeaconServer { getDaemonDebugExecutable(installationBase), BeaconConfig.getDaemonArguments(), mode); } - var fullCommand = ShellTypes.getPlatformDefault().executeCommandListWithShell(command); + var fullCommand = ShellDialects.getPlatformDefault().executeCommandListWithShell(command); Process process = new ProcessBuilder(fullCommand).start(); printDaemonOutput(process, fullCommand); return process; diff --git a/core/src/main/java/io/xpipe/core/process/OsType.java b/core/src/main/java/io/xpipe/core/process/OsType.java index 6ec2c22f..724227cf 100644 --- a/core/src/main/java/io/xpipe/core/process/OsType.java +++ b/core/src/main/java/io/xpipe/core/process/OsType.java @@ -143,7 +143,7 @@ public interface OsType { @Override public Map getProperties(ShellProcessControl pc) throws Exception { try (CommandProcessControl c = - pc.subShell(ShellTypes.BASH).command("sw_vers").start()) { + pc.subShell(ShellDialects.BASH).command("sw_vers").start()) { var text = c.readOrThrow(); return PropertiesFormatsParser.parse(text, ":"); } diff --git a/core/src/main/java/io/xpipe/core/process/ProcessControl.java b/core/src/main/java/io/xpipe/core/process/ProcessControl.java index 76d616af..c1f59a45 100644 --- a/core/src/main/java/io/xpipe/core/process/ProcessControl.java +++ b/core/src/main/java/io/xpipe/core/process/ProcessControl.java @@ -18,7 +18,7 @@ public interface ProcessControl extends Closeable, AutoCloseable { boolean isRunning(); - ShellType getShellType(); + ShellDialect getShellType(); void writeLine(String line) throws IOException; diff --git a/core/src/main/java/io/xpipe/core/process/ShellType.java b/core/src/main/java/io/xpipe/core/process/ShellDialect.java similarity index 98% rename from core/src/main/java/io/xpipe/core/process/ShellType.java rename to core/src/main/java/io/xpipe/core/process/ShellDialect.java index 4fe80f38..9c5b0127 100644 --- a/core/src/main/java/io/xpipe/core/process/ShellType.java +++ b/core/src/main/java/io/xpipe/core/process/ShellDialect.java @@ -11,7 +11,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type") -public interface ShellType { +public interface ShellDialect { default String getCdCommand(String directory){ return "cd \"" + directory + "\""; @@ -109,7 +109,7 @@ public interface ShellType { NewLine getNewLine(); - String getName(); + String getId(); String getDisplayName(); diff --git a/core/src/main/java/io/xpipe/core/process/ShellDialects.java b/core/src/main/java/io/xpipe/core/process/ShellDialects.java new file mode 100644 index 00000000..3c7a85af --- /dev/null +++ b/core/src/main/java/io/xpipe/core/process/ShellDialects.java @@ -0,0 +1,60 @@ +package io.xpipe.core.process; + +import io.xpipe.core.util.ModuleLayerLoader; + +import java.util.ArrayList; +import java.util.List; +import java.util.ServiceLoader; + +public class ShellDialects { + + public static final List ALL = new ArrayList<>(); + public static ShellDialect POWERSHELL; + public static ShellDialect CMD; + public static ShellDialect SH; + public static ShellDialect BASH; + public static ShellDialect ZSH; + + public static class Loader implements ModuleLayerLoader { + + @Override + public void init(ModuleLayer layer) { + ServiceLoader.load(layer, ShellDialect.class).stream().forEach(moduleLayerLoaderProvider -> { + ALL.add(moduleLayerLoaderProvider.get()); + }); + + CMD = byName("cmd"); + POWERSHELL = byName("powershell"); + SH = byName("sh"); + BASH = byName("bash"); + ZSH = byName("zsh"); + } + + @Override + public boolean requiresFullDaemon() { + return false; + } + + @Override + public boolean prioritizeLoading() { + return false; + } + } + + private static ShellDialect byName(String name) { + return ALL.stream() + .filter(shellType -> shellType.getId().equals(name)) + .findFirst() + .orElseThrow(); + } + + public static ShellDialect getPlatformDefault() { + if (OsType.getLocal().equals(OsType.WINDOWS)) { + return CMD; + } else if (OsType.getLocal().equals(OsType.LINUX)) { + return BASH; + } else { + return ZSH; + } + } +} diff --git a/core/src/main/java/io/xpipe/core/process/ShellProcessControl.java b/core/src/main/java/io/xpipe/core/process/ShellProcessControl.java index 6546db06..8ce1f867 100644 --- a/core/src/main/java/io/xpipe/core/process/ShellProcessControl.java +++ b/core/src/main/java/io/xpipe/core/process/ShellProcessControl.java @@ -49,7 +49,7 @@ public interface ShellProcessControl extends ProcessControl { } } - default String executeStringSimpleCommand(ShellType type, String command) throws Exception { + default String executeStringSimpleCommand(ShellDialect type, String command) throws Exception { try (var sub = subShell(type).start()) { return sub.executeStringSimpleCommand(command); } @@ -69,7 +69,7 @@ public interface ShellProcessControl extends ProcessControl { SecretValue getElevationPassword(); - default ShellProcessControl subShell(@NonNull ShellType type) { + default ShellProcessControl subShell(@NonNull ShellDialect type) { return subShell(p -> type.getNormalOpenCommand(), (shellProcessControl, s) -> { return s == null ? type.getNormalOpenCommand() : type.executeCommandWithShell(s); }) diff --git a/core/src/main/java/io/xpipe/core/store/ShellStore.java b/core/src/main/java/io/xpipe/core/store/ShellStore.java index a5945e67..55907da1 100644 --- a/core/src/main/java/io/xpipe/core/store/ShellStore.java +++ b/core/src/main/java/io/xpipe/core/store/ShellStore.java @@ -4,7 +4,7 @@ import io.xpipe.core.charsetter.Charsetter; import io.xpipe.core.impl.LocalStore; import io.xpipe.core.process.OsType; import io.xpipe.core.process.ShellProcessControl; -import io.xpipe.core.process.ShellType; +import io.xpipe.core.process.ShellDialect; import java.nio.charset.Charset; @@ -44,8 +44,8 @@ public interface ShellStore extends DataStore, StatefulDataStore, LaunchableStor return pc; } - default ShellType getShellType() { - return getState("type", ShellType.class, null); + default ShellDialect getShellType() { + return getState("type", ShellDialect.class, null); } default OsType getOsType() { @@ -58,7 +58,7 @@ public interface ShellStore extends DataStore, StatefulDataStore, LaunchableStor ShellProcessControl createControl(); - public default ShellType determineType() throws Exception { + public default ShellDialect determineType() throws Exception { try (var pc = create().start()) { return pc.getShellType(); } diff --git a/core/src/main/java/io/xpipe/core/util/CoreJacksonModule.java b/core/src/main/java/io/xpipe/core/util/CoreJacksonModule.java index 68773222..ce8bab36 100644 --- a/core/src/main/java/io/xpipe/core/util/CoreJacksonModule.java +++ b/core/src/main/java/io/xpipe/core/util/CoreJacksonModule.java @@ -23,8 +23,8 @@ import io.xpipe.core.dialog.BusyElement; import io.xpipe.core.dialog.ChoiceElement; import io.xpipe.core.dialog.HeaderElement; import io.xpipe.core.impl.*; -import io.xpipe.core.process.ShellType; -import io.xpipe.core.process.ShellTypes; +import io.xpipe.core.process.ShellDialect; +import io.xpipe.core.process.ShellDialects; import io.xpipe.core.source.DataSource; import io.xpipe.core.source.DataSourceReference; @@ -51,7 +51,7 @@ public class CoreJacksonModule extends SimpleModule { new NamedType(BusyElement.class), new NamedType(HeaderElement.class)); - for (ShellType t : ShellTypes.getAllShellTypes()) { + for (ShellDialect t : ShellDialects.ALL) { context.registerSubtypes(new NamedType(t.getClass())); } diff --git a/core/src/main/java/io/xpipe/core/util/Deobfuscator.java b/core/src/main/java/io/xpipe/core/util/Deobfuscator.java index 367501fb..606226cd 100644 --- a/core/src/main/java/io/xpipe/core/util/Deobfuscator.java +++ b/core/src/main/java/io/xpipe/core/util/Deobfuscator.java @@ -2,7 +2,7 @@ package io.xpipe.core.util; import io.xpipe.core.charsetter.NewLine; import io.xpipe.core.process.OsType; -import io.xpipe.core.process.ShellTypes; +import io.xpipe.core.process.ShellDialects; import io.xpipe.core.store.ShellStore; import java.io.PrintWriter; @@ -105,7 +105,7 @@ public class Deobfuscator { return false; } - var t = ShellTypes.getPlatformDefault(); + var t = ShellDialects.getPlatformDefault(); return ShellStore.local() .create() .executeBooleanSimpleCommand(t.getWhichCommand("retrace." + t.getScriptFileEnding())); diff --git a/app/src/main/java/io/xpipe/app/util/ModuleLayerLoader.java b/core/src/main/java/io/xpipe/core/util/ModuleLayerLoader.java similarity index 82% rename from app/src/main/java/io/xpipe/app/util/ModuleLayerLoader.java rename to core/src/main/java/io/xpipe/core/util/ModuleLayerLoader.java index b6e7cc87..8ff81ce4 100644 --- a/app/src/main/java/io/xpipe/app/util/ModuleLayerLoader.java +++ b/core/src/main/java/io/xpipe/core/util/ModuleLayerLoader.java @@ -1,13 +1,12 @@ -package io.xpipe.app.util; +package io.xpipe.core.util; -import io.xpipe.app.issue.ErrorEvent; - import java.util.ServiceLoader; +import java.util.function.Consumer; public interface ModuleLayerLoader { - public static void loadAll(ModuleLayer layer, boolean hasDaemon, boolean prioritization) { + public static void loadAll(ModuleLayer layer, boolean hasDaemon, boolean prioritization, Consumer errorHandler) { ServiceLoader.load(layer, ModuleLayerLoader.class).stream().forEach(moduleLayerLoaderProvider -> { var instance = moduleLayerLoaderProvider.get(); try { @@ -21,7 +20,7 @@ public interface ModuleLayerLoader { instance.init(layer); } catch (Throwable t) { - ErrorEvent.fromThrowable(t).handle(); + errorHandler.accept(t); } }); } diff --git a/core/src/main/java/module-info.java b/core/src/main/java/module-info.java index c7800499..c01be83e 100644 --- a/core/src/main/java/module-info.java +++ b/core/src/main/java/module-info.java @@ -1,6 +1,9 @@ import io.xpipe.core.process.ProcessControlProvider; +import io.xpipe.core.process.ShellDialect; +import io.xpipe.core.process.ShellDialects; import io.xpipe.core.source.WriteMode; import io.xpipe.core.util.CoreJacksonModule; +import io.xpipe.core.util.ModuleLayerLoader; open module io.xpipe.core { exports io.xpipe.core.store; @@ -29,6 +32,10 @@ open module io.xpipe.core { uses io.xpipe.core.util.ProxyManagerProvider; uses io.xpipe.core.util.DataStateProvider; uses io.xpipe.core.util.SecretProvider; + uses ModuleLayerLoader; + uses ShellDialect; + + provides ModuleLayerLoader with ShellDialects.Loader; provides WriteMode with WriteMode.Replace, diff --git a/ext/base/src/test/java/module-info.java b/ext/base/src/test/java/module-info.java index 32e12354..12f08018 100644 --- a/ext/base/src/test/java/module-info.java +++ b/ext/base/src/test/java/module-info.java @@ -1,10 +1,10 @@ -module io.xpipe.ext.text.test { +module io.xpipe.ext.base.test { requires io.xpipe.ext.base; requires org.junit.jupiter.api; requires org.junit.jupiter.params; requires io.xpipe.core; requires io.xpipe.api; - requires io.xpipe.extension; + requires io.xpipe.app; exports test; } diff --git a/ext/base/src/test/java/test/TextFileTest.java b/ext/base/src/test/java/test/TextFileTest.java index df719499..eed1e8b8 100644 --- a/ext/base/src/test/java/test/TextFileTest.java +++ b/ext/base/src/test/java/test/TextFileTest.java @@ -1,11 +1,11 @@ package test; import io.xpipe.api.DataSource; +import io.xpipe.app.test.DaemonExtensionTest; import io.xpipe.core.charsetter.NewLine; import io.xpipe.core.charsetter.StreamCharset; import io.xpipe.core.impl.FileStore; import io.xpipe.core.impl.TextSource; -import io.xpipe.extension.test.DaemonExtensionTest; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; diff --git a/ext/csv/src/test/java/io/xpipe/ext/csv/test/CsvDetectorTest.java b/ext/csv/src/test/java/io/xpipe/ext/csv/test/CsvDetectorTest.java index e7415d05..1be9f860 100644 --- a/ext/csv/src/test/java/io/xpipe/ext/csv/test/CsvDetectorTest.java +++ b/ext/csv/src/test/java/io/xpipe/ext/csv/test/CsvDetectorTest.java @@ -1,11 +1,11 @@ package io.xpipe.ext.csv.test; +import io.xpipe.app.test.DaemonExtensionTest; import io.xpipe.core.data.node.TupleNode; import io.xpipe.core.data.node.ValueNode; import io.xpipe.ext.csv.CsvDelimiter; import io.xpipe.ext.csv.CsvHeaderState; import io.xpipe.ext.csv.CsvSource; -import io.xpipe.extension.test.DaemonExtensionTest; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/ext/csv/src/test/java/module-info.java b/ext/csv/src/test/java/module-info.java index 191d79e6..5992c3ee 100644 --- a/ext/csv/src/test/java/module-info.java +++ b/ext/csv/src/test/java/module-info.java @@ -7,6 +7,6 @@ module io.xpipe.csv.test { requires org.junit.jupiter.api; requires org.junit.jupiter.params; requires io.xpipe.core; - requires io.xpipe.extension; + requires io.xpipe.app; requires io.xpipe.api; } diff --git a/ext/proc/build.gradle b/ext/proc/build.gradle new file mode 100644 index 00000000..ff4aadf5 --- /dev/null +++ b/ext/proc/build.gradle @@ -0,0 +1,5 @@ +plugins { id 'java' +id 'org.moditect.gradleplugin' version '1.0.0-rc3' +} +apply from: "$rootDir/gradle/gradle_scripts/java.gradle" +apply from: "$rootDir/gradle/gradle_scripts/extension.gradle" diff --git a/ext/proc/src/main/java/module-info.java b/ext/proc/src/main/java/module-info.java new file mode 100644 index 00000000..88844780 --- /dev/null +++ b/ext/proc/src/main/java/module-info.java @@ -0,0 +1 @@ +module io.xpipe.ext.proc {} diff --git a/gradle/gradle_scripts/extension.gradle b/gradle/gradle_scripts/extension.gradle index c804f1d6..4847e589 100644 --- a/gradle/gradle_scripts/extension.gradle +++ b/gradle/gradle_scripts/extension.gradle @@ -43,6 +43,7 @@ dependencies { if (project != project(':base')) { compileOnly project(':base') + testImplementation project(':base') } testImplementation project(':app') diff --git a/gradle/gradle_scripts/extension_test.gradle b/gradle/gradle_scripts/extension_test.gradle index 60da50e8..66487536 100644 --- a/gradle/gradle_scripts/extension_test.gradle +++ b/gradle/gradle_scripts/extension_test.gradle @@ -2,11 +2,10 @@ import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform apply from: "$buildscript.sourceFile/../junit.gradle" -def useExtension = System.getProperty('excludeExtensionLibrary') == null - dependencies { testImplementation project(':api') testImplementation project(':core') + testImplementation project(':app') testImplementation "org.openjfx:javafx-base:19:win" testImplementation "org.openjfx:javafx-controls:19:win" @@ -24,6 +23,7 @@ test { // Daemon properties systemProperty "io.xpipe.beacon.daemonArgs", " -Dio.xpipe.beacon.port=21723" + + " -Dio.xpipe.app.mode=tray" + " -Dio.xpipe.app.dataDir=$projectDir/local/" + " -Dio.xpipe.storage.persist=false" + " -Dio.xpipe.app.writeSysOut=true" + diff --git a/version b/version index 93b432f5..79a2734b 100644 --- a/version +++ b/version @@ -1 +1 @@ -0.4.30 \ No newline at end of file +0.5.0 \ No newline at end of file