electrobun 1.3.0-beta.3 → 1.3.0-beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/bun/core/Updater.ts +55 -50
- package/package.json +1 -1
|
@@ -34,7 +34,6 @@ export type UpdateStatusType =
|
|
|
34
34
|
| 'download-complete'
|
|
35
35
|
| 'applying'
|
|
36
36
|
| 'extracting'
|
|
37
|
-
| 'creating-backup'
|
|
38
37
|
| 'replacing-app'
|
|
39
38
|
| 'launching-new-version'
|
|
40
39
|
| 'complete'
|
|
@@ -148,6 +147,29 @@ let updateInfo: {
|
|
|
148
147
|
error: string;
|
|
149
148
|
};
|
|
150
149
|
|
|
150
|
+
function cleanupExtractionFolder(extractionFolder: string, keepTarHash: string) {
|
|
151
|
+
const keepFile = `${keepTarHash}.tar`;
|
|
152
|
+
try {
|
|
153
|
+
const entries = readdirSync(extractionFolder);
|
|
154
|
+
for (const entry of entries) {
|
|
155
|
+
if (entry === keepFile) continue;
|
|
156
|
+
const fullPath = join(extractionFolder, entry);
|
|
157
|
+
try {
|
|
158
|
+
const s = statSync(fullPath);
|
|
159
|
+
if (s.isDirectory()) {
|
|
160
|
+
rmdirSync(fullPath, { recursive: true });
|
|
161
|
+
} else {
|
|
162
|
+
unlinkSync(fullPath);
|
|
163
|
+
}
|
|
164
|
+
} catch (e) {
|
|
165
|
+
// Best effort — file may be in use on Windows
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
} catch (e) {
|
|
169
|
+
// Ignore errors in cleanup
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
151
173
|
const Updater = {
|
|
152
174
|
// workaround for some weird state stuff in this old version of bun
|
|
153
175
|
// todo: revisit after updating to the latest bun
|
|
@@ -550,12 +572,6 @@ const Updater = {
|
|
|
550
572
|
emitStatus('decompressing', 'Decompression complete');
|
|
551
573
|
|
|
552
574
|
unlinkSync(prevVersionCompressedTarballPath);
|
|
553
|
-
try {
|
|
554
|
-
unlinkSync(currentTarPath);
|
|
555
|
-
} catch (error) {
|
|
556
|
-
// Note: ignore the error. it may have already been deleted by the patching process
|
|
557
|
-
// if the patching process only got halfway
|
|
558
|
-
}
|
|
559
575
|
}
|
|
560
576
|
}
|
|
561
577
|
|
|
@@ -575,6 +591,9 @@ const Updater = {
|
|
|
575
591
|
updateInfo.error = "Failed to download latest version";
|
|
576
592
|
emitStatus('error', 'Failed to download latest version', { latestHash });
|
|
577
593
|
}
|
|
594
|
+
|
|
595
|
+
// Clean up stale files in the extraction folder (old tars, patches, backups, etc.)
|
|
596
|
+
cleanupExtractionFolder(extractionFolder, latestHash);
|
|
578
597
|
},
|
|
579
598
|
|
|
580
599
|
// todo (yoav): this should emit an event so app can cleanup or block the restart
|
|
@@ -711,29 +730,15 @@ const Updater = {
|
|
|
711
730
|
runningAppBundlePath = join(appDataFolder, 'app');
|
|
712
731
|
}
|
|
713
732
|
}
|
|
714
|
-
// Platform-specific backup handling
|
|
715
|
-
let backupPath: string;
|
|
716
|
-
if (currentOS === 'macos') {
|
|
717
|
-
// On macOS, backup in extraction folder with .app extension
|
|
718
|
-
backupPath = join(extractionFolder, "backup.app");
|
|
719
|
-
} else {
|
|
720
|
-
// On Linux/Windows, create a tar backup of the current app
|
|
721
|
-
backupPath = join(extractionFolder, "backup.tar");
|
|
722
|
-
}
|
|
723
|
-
|
|
724
733
|
try {
|
|
725
|
-
emitStatus('
|
|
734
|
+
emitStatus('replacing-app', 'Removing old version...');
|
|
726
735
|
|
|
727
736
|
if (currentOS === 'macos') {
|
|
728
|
-
//
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
rmdirSync(backupPath, { recursive: true });
|
|
737
|
+
// Remove existing app before installing the new one
|
|
738
|
+
if (statSync(runningAppBundlePath, { throwIfNoEntry: false })) {
|
|
739
|
+
rmdirSync(runningAppBundlePath, { recursive: true });
|
|
732
740
|
}
|
|
733
741
|
|
|
734
|
-
// Move current running app to backup
|
|
735
|
-
renameSync(runningAppBundlePath, backupPath);
|
|
736
|
-
|
|
737
742
|
emitStatus('replacing-app', 'Installing new version...');
|
|
738
743
|
// Move new app to running location
|
|
739
744
|
renameSync(newAppBundlePath, runningAppBundlePath);
|
|
@@ -747,35 +752,41 @@ const Updater = {
|
|
|
747
752
|
// Ignore errors - attribute may not exist
|
|
748
753
|
}
|
|
749
754
|
} else if (currentOS === 'linux') {
|
|
750
|
-
// On Linux,
|
|
751
|
-
// Remove existing backup if it exists
|
|
752
|
-
if (statSync(backupPath, { throwIfNoEntry: false })) {
|
|
753
|
-
unlinkSync(backupPath);
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
// Create backup of current AppImage (if it exists)
|
|
755
|
+
// On Linux, remove existing AppImage and replace with new one
|
|
757
756
|
if (statSync(runningAppBundlePath, { throwIfNoEntry: false })) {
|
|
758
|
-
|
|
757
|
+
unlinkSync(runningAppBundlePath);
|
|
759
758
|
}
|
|
760
|
-
|
|
759
|
+
|
|
761
760
|
// Move new AppImage to app location
|
|
762
761
|
renameSync(newAppBundlePath, runningAppBundlePath);
|
|
763
|
-
|
|
762
|
+
|
|
763
|
+
// Clean up the extracted inner directory (contains leftover icon, shortcut, metadata.json)
|
|
764
|
+
const innerDirName = localInfo.name.replace(/ /g, "");
|
|
765
|
+
const extractedInnerDir = join(extractionDir, innerDirName);
|
|
766
|
+
if (statSync(extractedInnerDir, { throwIfNoEntry: false })?.isDirectory()) {
|
|
767
|
+
rmdirSync(extractedInnerDir, { recursive: true });
|
|
768
|
+
}
|
|
769
|
+
|
|
764
770
|
// Make AppImage executable
|
|
765
771
|
execSync(`chmod +x "${runningAppBundlePath}"`);
|
|
766
772
|
|
|
767
773
|
// Create/update launcher script that points to the AppImage
|
|
768
774
|
await createLinuxAppImageLauncherScript(runningAppBundlePath);
|
|
769
|
-
}
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
// Clean up stale files in extraction folder
|
|
778
|
+
if (currentOS !== 'win') {
|
|
779
|
+
cleanupExtractionFolder(extractionFolder, latestHash);
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
if (currentOS === 'win') {
|
|
770
783
|
// On Windows, files are locked while in use, so we need a helper script
|
|
771
784
|
// that runs after the app exits to do the replacement
|
|
772
785
|
const parentDir = dirname(runningAppBundlePath);
|
|
773
786
|
const updateScriptPath = join(parentDir, 'update.bat');
|
|
774
|
-
const backupDir = join(parentDir, 'app-backup');
|
|
775
787
|
const launcherPath = join(runningAppBundlePath, 'bin', 'launcher.exe');
|
|
776
788
|
|
|
777
789
|
// Convert paths to Windows format
|
|
778
|
-
const backupDirWin = backupDir.replace(/\//g, '\\');
|
|
779
790
|
const runningAppWin = runningAppBundlePath.replace(/\//g, '\\');
|
|
780
791
|
const newAppWin = newAppBundlePath.replace(/\//g, '\\');
|
|
781
792
|
const extractionDirWin = extractionDir.replace(/\//g, '\\');
|
|
@@ -783,11 +794,10 @@ const Updater = {
|
|
|
783
794
|
|
|
784
795
|
// Create a batch script that will:
|
|
785
796
|
// 1. Wait for the current app to exit
|
|
786
|
-
// 2. Remove
|
|
787
|
-
// 3. Move
|
|
788
|
-
// 4.
|
|
789
|
-
// 5.
|
|
790
|
-
// 6. Clean up
|
|
797
|
+
// 2. Remove current app folder
|
|
798
|
+
// 3. Move new app to current location
|
|
799
|
+
// 4. Launch the new app
|
|
800
|
+
// 5. Clean up
|
|
791
801
|
const updateScript = `@echo off
|
|
792
802
|
setlocal
|
|
793
803
|
|
|
@@ -802,14 +812,9 @@ if "%ERRORLEVEL%"=="0" (
|
|
|
802
812
|
:: Small extra delay to ensure all file handles are released
|
|
803
813
|
timeout /t 2 /nobreak >nul
|
|
804
814
|
|
|
805
|
-
:: Remove
|
|
806
|
-
if exist "${backupDirWin}" (
|
|
807
|
-
rmdir /s /q "${backupDirWin}"
|
|
808
|
-
)
|
|
809
|
-
|
|
810
|
-
:: Backup current app folder
|
|
815
|
+
:: Remove current app folder
|
|
811
816
|
if exist "${runningAppWin}" (
|
|
812
|
-
|
|
817
|
+
rmdir /s /q "${runningAppWin}"
|
|
813
818
|
)
|
|
814
819
|
|
|
815
820
|
:: Move new app to current location
|
package/package.json
CHANGED