This commit is contained in:
crschnick 2025-04-12 22:34:00 +00:00
parent 3a10e18b06
commit 94a8f88106
10 changed files with 74 additions and 77 deletions

View file

@ -1,5 +1,6 @@
package io.xpipe.app.core;
import io.xpipe.app.core.mode.OperationMode;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.issue.TrackEvent;
import io.xpipe.app.update.*;
@ -25,19 +26,27 @@ public enum AppDistributionType implements Translatable {
PORTABLE("portable", false, () -> new PortableUpdater(true)),
NATIVE_INSTALLATION("install", true, () -> new GitHubUpdater(true)),
HOMEBREW("homebrew", true, () -> {
return new CommandUpdater(ShellScript.lines("brew upgrade --cask " + (AppProperties.get().isStaging() ? "xpipe-io/ptb/xpipe-ptb" : "xpipe-io/tap/xpipe")));
var pkg = AppProperties.get().isStaging() ? "xpipe-ptb" : "xpipe";
return new CommandUpdater(ShellScript.lines(
"brew upgrade --cask xpipe-io/tap/" + pkg,
OperationMode.getRestartCommand()
));
}),
APT_REPO("apt", true, () -> {
var pkg = AppProperties.get().isStaging() ? "xpipe-ptb" : "xpipe";
return new CommandUpdater(ShellScript.lines(
"echo \"+ sudo apt update && sudo apt install " + (AppProperties.get().isStaging() ? "xpipe-ptb" : "xpipe") + "\"",
"echo \"+ sudo apt update && sudo apt install " + pkg + "\"",
"sudo apt update",
"sudo apt install " + (AppProperties.get().isStaging() ? "xpipe-ptb" : "xpipe")
"sudo apt install " + pkg,
OperationMode.getRestartCommand()
));
}),
RPM_REPO("rpm", true, () -> {
var pkg = AppProperties.get().isStaging() ? "xpipe-ptb" : "xpipe";
return new CommandUpdater(ShellScript.lines(
"echo \"+ sudo yum upgrade " + (AppProperties.get().isStaging() ? "xpipe-ptb" : "xpipe") + " --refresh\"",
"sudo yum upgrade " + (AppProperties.get().isStaging() ? "xpipe-ptb" : "xpipe") + " --refresh"
"echo \"+ sudo yum upgrade " + pkg + " --refresh\"",
"sudo yum upgrade " + pkg + " --refresh",
OperationMode.getRestartCommand()
));
}),
WEBTOP("webtop", true, () -> new WebtopUpdater()),
@ -46,10 +55,14 @@ public enum AppDistributionType implements Translatable {
var pkg = AppProperties.get().isStaging() ? "xpipe-ptb" : "xpipe";
if (systemWide) {
return new CommandUpdater(ShellScript.lines(
"powershell -Command \"Start-Process -Verb runAs -FilePath choco -ArgumentList upgrade, " + pkg + "\""
"powershell -Command \"Start-Process -Verb runAs -FilePath choco -ArgumentList upgrade, " + pkg + "\"",
OperationMode.getRestartCommand()
));
} else {
return new CommandUpdater(ShellScript.lines("choco upgrade " + pkg));
return new CommandUpdater(ShellScript.lines(
"choco upgrade " + pkg,
OperationMode.getRestartCommand()
));
}
});
@ -168,15 +181,13 @@ public enum AppDistributionType implements Translatable {
}
}
// In theory, we can also add && !AppProperties.get().isStaging() here, but we want to replicate the
// production behavior
if (OsType.getLocal().equals(OsType.MACOS)) {
var out = LocalExec.readStdoutIfPossible("/opt/homebrew/bin/brew", "list", "--casks", "--versions");
if (out.isPresent()) {
if (out.get().lines().anyMatch(s -> {
var split = s.split(" ");
return split.length == 2
&& split[0].equals("xpipe")
&& split[0].equals(AppProperties.get().isStaging() ? "xpipe-ptb" : "xpipe")
&& split[1].equals(AppProperties.get().getVersion());
})) {
return HOMEBREW;

View file

@ -263,7 +263,7 @@ public abstract class OperationMode {
return ALL;
}
public static void startNewInstance() throws Exception {
public static String getRestartCommand() {
var loc = AppProperties.get().isDevelopmentEnvironment()
? XPipeInstallation.getLocalDefaultInstallationBasePath()
: XPipeInstallation.getCurrentInstallationBasePath().toString();
@ -275,7 +275,11 @@ public abstract class OperationMode {
"\"-Dio.xpipe.app.acceptEula=true\" \"-Dio.xpipe.app.dataDir=" + dataDir
+ "\" \"-Dio.xpipe.app.restarted=true\"",
true);
LocalShell.getShell().executeSimpleCommand(exec);
return exec;
}
public static void startNewInstance() throws Exception {
LocalShell.getShell().executeSimpleCommand(getRestartCommand());
}
public static void restart() {

View file

@ -82,7 +82,7 @@ public class ErrorHandlerComp extends SimpleComp {
}
var descriptionField = new TextArea(desc);
descriptionField.setPrefRowCount(Math.max(5, Math.min((int) desc.lines().count(), 14)));
descriptionField.setPrefRowCount(Math.max(5, Math.min((int) desc.lines().count() + 1, 14)));
descriptionField.setWrapText(true);
descriptionField.setEditable(false);
descriptionField.setPadding(Insets.EMPTY);

View file

@ -31,13 +31,13 @@ public class AboutCategory extends AppPrefsCategory {
@Override
protected Comp<?> create() {
var props = createProperties().padding(new Insets(0, 0, 0, 5));
var update = new UpdateCheckComp().grow(true, false).prefWidth(600);
return new VerticalComp(List.of(props, Comp.hspacer(8), update, Comp.hspacer(13), Comp.hseparator().padding(Insets.EMPTY)))
var update = new UpdateCheckComp().prefWidth(600);
return new VerticalComp(List.of(props, Comp.hspacer(8), update, Comp.hspacer(13), Comp.hseparator().padding(Insets.EMPTY).maxWidth(600)))
.apply(s -> s.get().setFillWidth(true))
.apply(struc -> struc.get().setSpacing(15))
.styleClass("information")
.styleClass("about-tab")
.apply(struc -> struc.get().setPrefWidth(600));
.apply(struc -> struc.get().maxWidth(600));
}
private Comp<?> createProperties() {

View file

@ -7,6 +7,7 @@ import io.xpipe.app.util.LocalShell;
import io.xpipe.app.util.WindowsRegistry;
import io.xpipe.core.process.CommandBuilder;
import io.xpipe.core.process.OsType;
import io.xpipe.core.process.ShellScript;
import java.io.IOException;
import java.nio.file.Path;
@ -179,8 +180,7 @@ public interface ExternalEditorType extends PrefsChoiceValue {
if (AppPrefs.get().customEditorCommandInTerminal().get()) {
TerminalLauncher.openDirect(
file.toString(),
sc -> command.buildFull(sc),
AppPrefs.get().terminalType.get());
sc -> new ShellScript(command.buildFull(sc)));
} else {
ExternalApplicationHelper.startAsync(command);
}

View file

@ -17,6 +17,7 @@ import io.xpipe.app.util.FileOpener;
import io.xpipe.app.util.OptionsBuilder;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.core.process.OsType;
import io.xpipe.core.process.ShellScript;
import io.xpipe.core.store.FileNames;
import io.xpipe.core.util.XPipeInstallation;
@ -58,13 +59,9 @@ public class TroubleshootCategory extends AppPrefsCategory {
XPipeInstallation.getCurrentInstallationBasePath()
.toString(),
XPipeInstallation.getDaemonDebugScriptPath(OsType.getLocal()));
// We can't use the SSH bridge
var type = ExternalTerminalType.determineFallbackTerminalToOpen(
AppPrefs.get().terminalType().getValue());
TerminalLauncher.openDirect(
TerminalLauncher.openDirectFallback(
"XPipe Debug",
sc -> sc.getShellDialect().runScriptCommand(sc, script),
type);
sc -> new ShellScript(sc.getShellDialect().runScriptCommand(sc, script)));
});
e.consume();
})

View file

@ -106,7 +106,6 @@ public class UpdateCheckComp extends SimpleComp {
refresh();
})
.styleClass("update-button")
.grow(true, false)
.disable(checking)
.createRegion();
}

View file

@ -86,28 +86,32 @@ public class TerminalLauncher {
return content;
}
public static void openDirect(String title, CommandBuilder command) throws Exception {
openDirect(
title,
sc -> command.buildFull(sc),
AppPrefs.get().terminalType().getValue());
}
public static void openDirect(String title, ShellScript command) throws Exception {
openDirect(
title, sc -> command.toString(), AppPrefs.get().terminalType().getValue());
title, sc -> command, AppPrefs.get().terminalType().getValue());
}
public static void openDirectFallback(String title, FailableFunction<ShellControl, ShellScript, Exception> command)
throws Exception {
// We can't use the SSH bridge and other stuff
var type = ExternalTerminalType.determineFallbackTerminalToOpen(
AppPrefs.get().terminalType().getValue());
openDirect(
title,
command,
type);
}
public static void openDirect(String title, FailableFunction<ShellControl, ShellScript, Exception> command)
throws Exception {
openDirect(
title,
sc -> command.apply(sc).toString(),
command,
AppPrefs.get().terminalType().getValue());
}
public static void openDirect(
String title, FailableFunction<ShellControl, String, Exception> command, ExternalTerminalType type)
String title, FailableFunction<ShellControl, ShellScript, Exception> command, ExternalTerminalType type)
throws Exception {
try (var sc = LocalShell.getShell().start()) {
var script = constructTerminalInitScript(
@ -115,7 +119,7 @@ public class TerminalLauncher {
sc,
WorkingDirectoryFunction.none(),
List.of(),
List.of(command.apply(sc)),
List.of(command.apply(sc).toString()),
new TerminalInitScriptConfig(
title,
type.shouldClear()

View file

@ -12,6 +12,7 @@ import io.xpipe.app.util.ScriptHelper;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.core.process.OsType;
import io.xpipe.core.process.ShellDialects;
import io.xpipe.core.process.ShellScript;
import io.xpipe.core.store.FileNames;
import io.xpipe.core.util.FailableRunnable;
import io.xpipe.core.util.XPipeInstallation;
@ -74,11 +75,6 @@ public class AppInstaller {
@Override
public void installLocal(Path file) throws Exception {
var restartExec = (AppProperties.get().isDevelopmentEnvironment()
? Path.of(XPipeInstallation.getLocalDefaultInstallationBasePath())
: XPipeInstallation.getCurrentInstallationBasePath())
.resolve(XPipeInstallation.getDaemonExecutablePath(OsType.getLocal()))
.toString();
var logsDir =
AppLogs.get().getSessionLogsDirectory().getParent().toString();
var logFile = FileNames.join(
@ -88,8 +84,8 @@ public class AppInstaller {
ProcessControlProvider.get().getEffectiveLocalDialect().equals(ShellDialects.CMD)
&& !systemWide;
var command = cmdScript
? getCmdCommand(file.toString(), logFile, restartExec)
: getPowershellCommand(file.toString(), logFile, restartExec, systemWide);
? getCmdCommand(file.toString(), logFile)
: getPowershellCommand(file.toString(), logFile, systemWide);
runAndClose(() -> {
try (var sc = LocalShell.getShell().start()) {
@ -121,7 +117,7 @@ public class AppInstaller {
XPipeInstallation.getCurrentInstallationBasePath().resolve("system"));
}
private String getCmdCommand(String file, String logFile, String exec) {
private String getCmdCommand(String file, String logFile) {
var args = "MSIFASTINSTALL=7 DISABLEROLLBACK=1";
return String.format(
"""
@ -129,8 +125,7 @@ public class AppInstaller {
cd /D "%%HOMEDRIVE%%%%HOMEPATH%%"
echo + msiexec /i "%s" /lv "%s" /qb %s
start "" /wait msiexec /i "%s" /lv "%s" /qb %s
echo Starting XPipe ...
start "" "%s" "-Dio.xpipe.app.dataDir=%s"
%s
""",
file,
file,
@ -139,11 +134,11 @@ public class AppInstaller {
file,
logFile,
args,
exec,
AppProperties.get().getDataDir());
OperationMode.getRestartCommand()
);
}
private String getPowershellCommand(String file, String logFile, String exec, boolean systemWide) {
private String getPowershellCommand(String file, String logFile, boolean systemWide) {
var property = "MSIFASTINSTALL=7 DISABLEROLLBACK=1" + (systemWide ? " ALLUSERS=1" : "");
var startProcessProperty = ", MSIFASTINSTALL=7, DISABLEROLLBACK=1" + (systemWide ? ", ALLUSERS=1" : "");
var runas = systemWide ? "-Verb runAs" : "";
@ -153,8 +148,7 @@ public class AppInstaller {
cd "$env:HOMEDRIVE\\$env:HOMEPATH"
echo '+ msiexec /i "%s" /lv "%s" /qb%s'
Start-Process %s -FilePath msiexec -Wait -ArgumentList "/i", "`"%s`"", "/lv", "`"%s`"", "/qb"%s
echo 'Starting XPipe ...'
& "%s" "-Dio.xpipe.app.dataDir=%s"
%s
""",
file,
file,
@ -164,8 +158,8 @@ public class AppInstaller {
file,
logFile,
startProcessProperty,
exec,
AppProperties.get().getDataDir());
OperationMode.getRestartCommand()
);
}
}
@ -182,7 +176,7 @@ public class AppInstaller {
}
var name = AppProperties.get().isStaging() ? "xpipe-ptb" : "xpipe";
var command = String.format(
var command = new ShellScript(String.format(
"""
runinstaller() {
echo "Installing downloaded .deb installer ..."
@ -194,13 +188,9 @@ public class AppInstaller {
cd ~
runinstaller || echo "Update failed ..." && read key
""",
file, file, name, AppProperties.get().getDataDir());
file, file, name, AppProperties.get().getDataDir()));
runAndClose(() -> {
// We can't use the SSH bridge
var type = ExternalTerminalType.determineFallbackTerminalToOpen(
AppPrefs.get().terminalType().getValue());
TerminalLauncher.openDirect("XPipe Updater", sc -> command, type);
TerminalLauncher.openDirectFallback("XPipe Updater", sc -> command);
});
}
@ -222,26 +212,22 @@ public class AppInstaller {
return;
}
var name = AppProperties.get().isStaging() ? "xpipe-ptb" : "xpipe";
var command = String.format(
var command = new ShellScript(String.format(
"""
runinstaller() {
echo "Installing downloaded .rpm installer ..."
echo "+ sudo rpm -U -v --force \\"%s\\""
sudo rpm -U -v --force "%s" || return 1
%s open -d "%s" || return 1
%s || return 1
}
cd ~
runinstaller || read -rsp "Update failed ..."$'\\n' -n 1 key
""",
file, file, name, AppProperties.get().getDataDir());
file, file, OperationMode.getRestartCommand()));
runAndClose(() -> {
// We can't use the SSH bridge
var type = ExternalTerminalType.determineFallbackTerminalToOpen(
AppPrefs.get().terminalType().getValue());
TerminalLauncher.openDirect("XPipe Updater", sc -> command, type);
TerminalLauncher.openDirectFallback("XPipe Updater", sc -> command);
});
}
@ -263,26 +249,22 @@ public class AppInstaller {
return;
}
var name = AppProperties.get().isStaging() ? "xpipe-ptb" : "xpipe";
var command = String.format(
var command = new ShellScript(String.format(
"""
runinstaller() {
echo "Installing downloaded .pkg installer ..."
echo "+ sudo installer -verboseR -pkg \\"%s\\" -target /"
sudo installer -verboseR -pkg "%s" -target / || return 1
%s open -d "%s" || return 1
%s || return 1
}
cd ~
runinstaller || echo "Update failed ..." && read -rs -k 1 key
""",
file, file, name, AppProperties.get().getDataDir());
file, file, OperationMode.getRestartCommand()));
runAndClose(() -> {
// We can't use the SSH bridge
var type = ExternalTerminalType.determineFallbackTerminalToOpen(
AppPrefs.get().terminalType().getValue());
TerminalLauncher.openDirect("XPipe Updater", sc -> command, type);
TerminalLauncher.openDirectFallback("XPipe Updater", sc -> command);
});
}

View file

@ -61,7 +61,7 @@ public class CommandUpdater extends PortableUpdater {
var performedUpdate = new PerformedUpdate(p.getVersion(), p.getBody(), p.getVersion());
AppCache.update("performedUpdate", performedUpdate);
OperationMode.executeAfterShutdown(() -> {
TerminalLauncher.openDirect("XPipe Updater", script);
TerminalLauncher.openDirectFallback("XPipe Updater", sc -> script);
});
} catch (Throwable t) {
ErrorEvent.fromThrowable(t).handle();