From 22c0aa07eef4e4e5cb58818c5794e52bbb6ac569 Mon Sep 17 00:00:00 2001 From: NeuralFault Date: Tue, 30 Dec 2025 19:56:34 -0500 Subject: [PATCH 1/3] Fix updating appimage on Linux via self-created bash script --- .../ViewModels/Dialogs/UpdateViewModel.cs | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/StabilityMatrix.Avalonia/ViewModels/Dialogs/UpdateViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/Dialogs/UpdateViewModel.cs index 40131ee0..31820bfd 100644 --- a/StabilityMatrix.Avalonia/ViewModels/Dialogs/UpdateViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/Dialogs/UpdateViewModel.cs @@ -162,6 +162,51 @@ await updateHelper.DownloadUpdate( ); } + // Handle Linux AppImage update + if (Compat.IsLinux && Environment.GetEnvironmentVariable("APPIMAGE") is { } appImage) + { + var updateScriptPath = UpdateHelper.UpdateFolder.JoinFile("update_script.sh").FullPath; + var newAppImage = UpdateHelper.ExecutablePath.FullPath; + + var scriptContent = $""" +#!/bin/bash +PID={Environment.ProcessId} +NEW_APPIMAGE="{newAppImage.Replace("\"", "\\\"")}" +OLD_APPIMAGE="{appImage.Replace("\"", "\\\"")}" + +# Wait for the process to exit +while kill -0 "$PID" 2>/dev/null; do + sleep 0.5 +done + +# Move the new AppImage over the old one +mv -f "$NEW_APPIMAGE" "$OLD_APPIMAGE" +chmod +x "$OLD_APPIMAGE" + +# Launch the new AppImage +"$OLD_APPIMAGE" & +"""; + await File.WriteAllTextAsync(updateScriptPath, scriptContent); + + File.SetUnixFileMode( + updateScriptPath, + UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute + ); + + System.Diagnostics.Process.Start( + new System.Diagnostics.ProcessStartInfo + { + FileName = "/bin/bash", + Arguments = updateScriptPath, + UseShellExecute = false, + CreateNoWindow = true, + } + ); + + App.Shutdown(); + return; + } + // Set current version for update messages settingsManager.Transaction( s => s.UpdatingFromVersion = Compat.AppVersion, From 4c4a10fe4ccf6daaea9262ee16af4befbee3bdf4 Mon Sep 17 00:00:00 2001 From: NeuralFault Date: Tue, 30 Dec 2025 22:23:30 -0500 Subject: [PATCH 2/3] Enhance Linux AppImage update process with error handling and user feedback --- .../ViewModels/Dialogs/UpdateViewModel.cs | 59 ++++++++++++------- 1 file changed, 37 insertions(+), 22 deletions(-) diff --git a/StabilityMatrix.Avalonia/ViewModels/Dialogs/UpdateViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/Dialogs/UpdateViewModel.cs index 31820bfd..f798e14d 100644 --- a/StabilityMatrix.Avalonia/ViewModels/Dialogs/UpdateViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/Dialogs/UpdateViewModel.cs @@ -165,10 +165,12 @@ await updateHelper.DownloadUpdate( // Handle Linux AppImage update if (Compat.IsLinux && Environment.GetEnvironmentVariable("APPIMAGE") is { } appImage) { - var updateScriptPath = UpdateHelper.UpdateFolder.JoinFile("update_script.sh").FullPath; - var newAppImage = UpdateHelper.ExecutablePath.FullPath; + try + { + var updateScriptPath = UpdateHelper.UpdateFolder.JoinFile("update_script.sh").FullPath; + var newAppImage = UpdateHelper.ExecutablePath.FullPath; - var scriptContent = $""" + var scriptContent = $""" #!/bin/bash PID={Environment.ProcessId} NEW_APPIMAGE="{newAppImage.Replace("\"", "\\\"")}" @@ -183,28 +185,41 @@ sleep 0.5 mv -f "$NEW_APPIMAGE" "$OLD_APPIMAGE" chmod +x "$OLD_APPIMAGE" -# Launch the new AppImage -"$OLD_APPIMAGE" & +# Launch the new AppImage detached +"$OLD_APPIMAGE" > /dev/null 2>&1 & +disown """; - await File.WriteAllTextAsync(updateScriptPath, scriptContent); + await File.WriteAllTextAsync(updateScriptPath, scriptContent); + + File.SetUnixFileMode( + updateScriptPath, + UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute + ); + + System.Diagnostics.Process.Start( + new System.Diagnostics.ProcessStartInfo + { + FileName = "/usr/bin/env", + Arguments = $"bash \"{updateScriptPath}\"", + UseShellExecute = false, + CreateNoWindow = true, + } + ); + + App.Shutdown(); + return; + } + catch (Exception ex) + { + logger.LogError(ex, "Failed to execute AppImage update script"); - File.SetUnixFileMode( - updateScriptPath, - UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute - ); + var dialog = DialogHelper.CreateMarkdownDialog( + "AppImage update script failed. \nCould not replace old AppImage with new version. Please check directory permissions. \nFalling back to standard update process. User intervention required: After program closes, \nplease move the new AppImage extracted in the '.StabilityMatrixUpdate' hidden directory to the old AppImage overwriting it. \n\nClose this dialog to continue with standard update process.", + Resources.Label_UnexpectedErrorOccurred + ); - System.Diagnostics.Process.Start( - new System.Diagnostics.ProcessStartInfo - { - FileName = "/bin/bash", - Arguments = updateScriptPath, - UseShellExecute = false, - CreateNoWindow = true, - } - ); - - App.Shutdown(); - return; + await dialog.ShowAsync(); + } } // Set current version for update messages From 84f508578675d64d16e20e32484b08bc727e48a4 Mon Sep 17 00:00:00 2001 From: NeuralFault Date: Tue, 30 Dec 2025 22:49:19 -0500 Subject: [PATCH 3/3] Refactor AppImage update script execution to improve environment variable handling and error messaging --- .../ViewModels/Dialogs/UpdateViewModel.cs | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/StabilityMatrix.Avalonia/ViewModels/Dialogs/UpdateViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/Dialogs/UpdateViewModel.cs index f798e14d..5635e75e 100644 --- a/StabilityMatrix.Avalonia/ViewModels/Dialogs/UpdateViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/Dialogs/UpdateViewModel.cs @@ -170,11 +170,9 @@ await updateHelper.DownloadUpdate( var updateScriptPath = UpdateHelper.UpdateFolder.JoinFile("update_script.sh").FullPath; var newAppImage = UpdateHelper.ExecutablePath.FullPath; - var scriptContent = $""" + var scriptContent = """ #!/bin/bash -PID={Environment.ProcessId} -NEW_APPIMAGE="{newAppImage.Replace("\"", "\\\"")}" -OLD_APPIMAGE="{appImage.Replace("\"", "\\\"")}" +set -e # Wait for the process to exit while kill -0 "$PID" 2>/dev/null; do @@ -196,15 +194,19 @@ sleep 0.5 UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute ); - System.Diagnostics.Process.Start( - new System.Diagnostics.ProcessStartInfo - { - FileName = "/usr/bin/env", - Arguments = $"bash \"{updateScriptPath}\"", - UseShellExecute = false, - CreateNoWindow = true, - } - ); + var startInfo = new System.Diagnostics.ProcessStartInfo + { + FileName = "/usr/bin/env", + Arguments = $"bash \"{updateScriptPath}\"", + UseShellExecute = false, + CreateNoWindow = true, + }; + + startInfo.EnvironmentVariables["PID"] = Environment.ProcessId.ToString(); + startInfo.EnvironmentVariables["NEW_APPIMAGE"] = newAppImage; + startInfo.EnvironmentVariables["OLD_APPIMAGE"] = appImage; + + System.Diagnostics.Process.Start(startInfo); App.Shutdown(); return; @@ -214,7 +216,7 @@ sleep 0.5 logger.LogError(ex, "Failed to execute AppImage update script"); var dialog = DialogHelper.CreateMarkdownDialog( - "AppImage update script failed. \nCould not replace old AppImage with new version. Please check directory permissions. \nFalling back to standard update process. User intervention required: After program closes, \nplease move the new AppImage extracted in the '.StabilityMatrixUpdate' hidden directory to the old AppImage overwriting it. \n\nClose this dialog to continue with standard update process.", + "AppImage update script failed. \nCould not replace old AppImage with new version. Please check directory permissions. \nFalling back to standard update process. User intervention required: \nAfter program closes, \nplease move the new AppImage extracted in the '.StabilityMatrixUpdate' hidden directory to the old AppImage overwriting it. \n\nClose this dialog to continue with standard update process.", Resources.Label_UnexpectedErrorOccurred );