From 14bcc9ea4c7ed220ef2f3f325526e368f271f97f Mon Sep 17 00:00:00 2001 From: crschnick Date: Mon, 19 Jan 2026 09:04:47 +0000 Subject: [PATCH] Rework --- .../xpipe/app/ext/ProcessControlProvider.java | 5 + .../io/xpipe/app/icon/SystemIconSource.java | 28 +---- .../xpipe/ext/base/script/ScriptSource.java | 110 ++++++++++++++++++ lang/strings/translations_en.properties | 4 + 4 files changed, 124 insertions(+), 23 deletions(-) create mode 100644 ext/base/src/main/java/io/xpipe/ext/base/script/ScriptSource.java diff --git a/app/src/main/java/io/xpipe/app/ext/ProcessControlProvider.java b/app/src/main/java/io/xpipe/app/ext/ProcessControlProvider.java index cf6f62642..d9d3da1fc 100644 --- a/app/src/main/java/io/xpipe/app/ext/ProcessControlProvider.java +++ b/app/src/main/java/io/xpipe/app/ext/ProcessControlProvider.java @@ -14,6 +14,7 @@ import io.xpipe.core.SecretValue; import javafx.beans.property.Property; +import java.nio.file.Path; import java.util.List; import java.util.ServiceLoader; @@ -71,4 +72,8 @@ public abstract class ProcessControlProvider { public abstract DataStoreEntryRef replace(DataStoreEntryRef ref); public abstract ModalOverlay createNetworkScanModal(); + + public abstract void cloneRepository(String url, Path target) throws Exception; + + public abstract void pullRepository(Path target) throws Exception; } diff --git a/app/src/main/java/io/xpipe/app/icon/SystemIconSource.java b/app/src/main/java/io/xpipe/app/icon/SystemIconSource.java index 6a8b79d9e..e3a0e868e 100644 --- a/app/src/main/java/io/xpipe/app/icon/SystemIconSource.java +++ b/app/src/main/java/io/xpipe/app/icon/SystemIconSource.java @@ -109,29 +109,11 @@ public interface SystemIconSource { @Override public void refresh() throws Exception { - try (var sc = - ProcessControlProvider.get().createLocalProcessControl(true).start()) { - var present = sc.view().findProgram("git").isPresent(); - if (!present) { - var msg = - "Git command-line tools are not available in the PATH but are required to use icons from a git repository. For more " - + "details, see https://git-scm.com/downloads."; - ErrorEventFactory.fromMessage(msg).expected().handle(); - return; - } - - var dir = SystemIconManager.getPoolPath().resolve(id); - if (!Files.exists(dir)) { - sc.command(CommandBuilder.of() - .add("git", "clone") - .addQuoted(remote) - .addFile(dir.toString())) - .execute(); - } else { - sc.command(CommandBuilder.of().add("git", "pull")) - .withWorkingDirectory(FilePath.of(dir)) - .execute(); - } + var dir = SystemIconManager.getPoolPath().resolve(id); + if (!Files.exists(dir)) { + ProcessControlProvider.get().cloneRepository(remote, dir); + } else { + ProcessControlProvider.get().pullRepository(dir); } } diff --git a/ext/base/src/main/java/io/xpipe/ext/base/script/ScriptSource.java b/ext/base/src/main/java/io/xpipe/ext/base/script/ScriptSource.java new file mode 100644 index 000000000..898c448df --- /dev/null +++ b/ext/base/src/main/java/io/xpipe/ext/base/script/ScriptSource.java @@ -0,0 +1,110 @@ +package io.xpipe.ext.base.script; + +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.annotation.JsonTypeName; +import io.xpipe.app.comp.base.ContextualFileReferenceChoiceComp; +import io.xpipe.app.core.AppCache; +import io.xpipe.app.ext.ProcessControlProvider; +import io.xpipe.app.platform.OptionsBuilder; +import io.xpipe.app.process.CommandBuilder; +import io.xpipe.app.process.ShellDialects; +import io.xpipe.app.storage.DataStorage; +import io.xpipe.core.FilePath; +import io.xpipe.core.SecretValue; +import io.xpipe.core.UuidHelper; +import javafx.beans.property.*; +import lombok.Builder; +import lombok.Value; +import lombok.extern.jackson.Jacksonized; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type") +public interface ScriptSource { + + @JsonTypeName("directory") + @Value + @Jacksonized + @Builder + class Directory implements ScriptSource { + + Path path; + + @SuppressWarnings("unused") + static OptionsBuilder createOptions(Property property) { + var path = new SimpleObjectProperty<>(property.getValue().getPath() != null ? FilePath.of(property.getValue().getPath()) : null); + return new OptionsBuilder() + .nameAndDescription("scriptDirectory") + .addComp(new ContextualFileReferenceChoiceComp(new ReadOnlyObjectWrapper<>(DataStorage.get().local().ref()), path, null, List.of(), null, true)) + .nonNull() + .bind( + () -> Directory.builder() + .path(path.get() != null ? path.get().asLocalPath() : null) + .build(), + property); + } + + @Override + public void prepare() { + + } + + @Override + public Path getLocalPath() { + return path; + } + } + + @JsonTypeName("gitRepository") + @Value + @Jacksonized + @Builder + class GitRepository implements ScriptSource { + + String url; + + @SuppressWarnings("unused") + static OptionsBuilder createOptions(Property property) { + var url = new SimpleStringProperty(property.getValue().getUrl()); + return new OptionsBuilder() + .nameAndDescription("scriptSourceUrl") + .addString(url) + .nonNull() + .bind( + () -> GitRepository.builder().url(url.get()).build(), + property); + } + + private String getName() { + var name = FilePath.of(url).getFileName(); + if (!name.isEmpty()) { + return name; + } + + return UuidHelper.generateFromObject(url).toString(); + } + + @Override + public void prepare() { + + } + + @Override + public Path getLocalPath() { + return AppCache.getBasePath().resolve("scripts").resolve(getName()); + } + } + + void prepare(); + + Path getLocalPath(); + + static List> getClasses() { + var l = new ArrayList>(); + l.add(Directory.class); + l.add(GitRepository.class); + return l; + } +} diff --git a/lang/strings/translations_en.properties b/lang/strings/translations_en.properties index 3c81ce0c5..2d223e561 100644 --- a/lang/strings/translations_en.properties +++ b/lang/strings/translations_en.properties @@ -1896,3 +1896,7 @@ identitiesAdded=Identities added syncInstantly=Sync instantly syncInstantlyDescription=Commit and push changes instantly after they have been made. In addition, regularly fetch and pull external changes from the remote.\n\nEnable this setting if you want to sync your changes regularly, e.g. with other running XPipe instances or other team members. If you don't need this, you can disable this setting and XPipe will only push changes after a while and don't check for remote changes. toggleTerminalDock=Toggle terminal dock +scriptDirectory=Directory location +scriptDirectoryDescription=The local directory containing shell script files +scriptSourceUrl=Repository URL +scriptSourceUrlDescription=The URL to a remote git repository containing shell script files