@@ -376,6 +376,24 @@ perform_tarball_update() {
376
376
377
377
print_info " Attempting to update Pulse to version $TARGET_TAG using tarball..."
378
378
379
+ # Check if release exists before proceeding
380
+ if ! check_release_exists " $TARGET_TAG " ; then
381
+ print_warning " Release tarball not available for $TARGET_TAG , falling back to git..."
382
+ return 1
383
+ fi
384
+
385
+ # Create comprehensive backup of user data
386
+ local user_data_backup=" "
387
+ if [ -d " $PULSE_DIR " ]; then
388
+ cd " $PULSE_DIR " || { print_error " Failed to cd into $PULSE_DIR " ; return 1; }
389
+ if user_data_backup=$( backup_user_data) ; then
390
+ print_success " User data backup created for tarball update"
391
+ else
392
+ print_warning " Failed to create user data backup, proceeding anyway..."
393
+ fi
394
+ cd ..
395
+ fi
396
+
379
397
local script_backup_path=" /tmp/${SCRIPT_NAME} .bak"
380
398
if [ -n " $SCRIPT_ABS_PATH " ] && [ -f " $SCRIPT_ABS_PATH " ]; then
381
399
print_info " Backing up current installer script to $script_backup_path ..."
@@ -389,17 +407,10 @@ perform_tarball_update() {
389
407
script_backup_path=" "
390
408
fi
391
409
392
- # Check if release exists before proceeding
393
- if ! check_release_exists " $TARGET_TAG " ; then
394
- print_warning " Release tarball not available for $TARGET_TAG , falling back to git..."
395
- [ -n " $script_backup_path " ] && rm -f " $script_backup_path "
396
- return 1
397
- fi
398
-
399
- # Backup current installation directory
410
+ # Backup current installation directory (full backup as fallback)
400
411
local backup_dir=" /tmp/pulse-backup-$( date +%s) "
401
412
if [ -d " $PULSE_DIR " ]; then
402
- print_info " Backing up current installation..."
413
+ print_info " Creating full installation backup as safety measure ..."
403
414
if ! cp -r " $PULSE_DIR " " $backup_dir " ; then
404
415
print_warning " Failed to backup current installation, continuing anyway..."
405
416
fi
@@ -461,6 +472,16 @@ perform_tarball_update() {
461
472
print_info " CSS assets already present and up-to-date."
462
473
fi
463
474
475
+ # Restore user data after successful tarball extraction
476
+ if [ -n " $user_data_backup " ] && [ -d " $user_data_backup " ]; then
477
+ if restore_user_data " $user_data_backup " ; then
478
+ print_success " User configuration restored after tarball update"
479
+ else
480
+ print_warning " Failed to restore some user configuration"
481
+ fi
482
+ rm -rf " $user_data_backup "
483
+ fi
484
+
464
485
# Cleanup backup if successful
465
486
[ -d " $backup_dir " ] && rm -rf " $backup_dir "
466
487
@@ -471,16 +492,53 @@ perform_tarball_update() {
471
492
472
493
# Restore backup if available
473
494
if [ -d " $backup_dir " ]; then
474
- print_info " Restoring from backup..."
495
+ print_info " Restoring from full backup..."
475
496
rm -rf " $PULSE_DIR "
476
497
mv " $backup_dir " " $PULSE_DIR "
477
498
fi
478
499
500
+ # Cleanup failed backups
479
501
[ -n " $script_backup_path " ] && rm -f " $script_backup_path "
502
+ [ -n " $user_data_backup " ] && rm -rf " $user_data_backup "
480
503
return 1
481
504
fi
482
505
}
483
506
507
+ # Emergency recovery function for when updates fail
508
+ emergency_recovery () {
509
+ local backup_dir=" $1 "
510
+
511
+ print_error " ==================== EMERGENCY RECOVERY ===================="
512
+ print_error " Update failed catastrophically. Attempting emergency recovery..."
513
+
514
+ if [ -n " $backup_dir " ] && [ -d " $backup_dir " ]; then
515
+ print_info " Restoring from emergency backup: $backup_dir "
516
+ if [ -d " $PULSE_DIR " ]; then
517
+ rm -rf " $PULSE_DIR .failed" 2> /dev/null
518
+ mv " $PULSE_DIR " " $PULSE_DIR .failed" 2> /dev/null
519
+ fi
520
+
521
+ if mv " $backup_dir " " $PULSE_DIR " ; then
522
+ print_success " Emergency recovery successful!"
523
+ print_info " Your original configuration has been restored."
524
+ print_info " Failed installation moved to: $PULSE_DIR .failed"
525
+ return 0
526
+ else
527
+ print_error " Emergency recovery failed!"
528
+ fi
529
+ fi
530
+
531
+ print_error " ============== MANUAL RECOVERY REQUIRED ================"
532
+ print_error " Automatic recovery failed. You may need to:"
533
+ print_error " 1. Manually restore from backup if available"
534
+ print_error " 2. Re-run the installer: sudo bash install-pulse.sh"
535
+ print_error " 3. Reconfigure your .env file with Proxmox credentials"
536
+ print_error " 4. Contact support: https://github.com/rcourtman/Pulse/issues"
537
+ print_error " ======================================================="
538
+
539
+ return 1
540
+ }
541
+
484
542
perform_tarball_install () {
485
543
if [ -z " $TARGET_TAG " ]; then
486
544
print_error " Target version tag not determined. Cannot install via tarball."
@@ -999,6 +1057,100 @@ create_pulse_user() {
999
1057
}
1000
1058
1001
1059
1060
+ # Comprehensive backup of user configuration and data
1061
+ backup_user_data () {
1062
+ local backup_base_dir=" /tmp/pulse-config-backup-$( date +%s) "
1063
+ mkdir -p " $backup_base_dir " || {
1064
+ print_error " Failed to create backup directory $backup_base_dir "
1065
+ return 1
1066
+ }
1067
+
1068
+ print_info " Creating comprehensive backup of user configuration..."
1069
+
1070
+ # Files to always preserve
1071
+ local preserve_files=(
1072
+ " .env"
1073
+ " custom-config.json"
1074
+ " user-settings.json"
1075
+ )
1076
+
1077
+ # Directories to preserve (if they exist and contain user data)
1078
+ local preserve_dirs=(
1079
+ " data"
1080
+ " logs"
1081
+ " backups"
1082
+ " custom"
1083
+ )
1084
+
1085
+ local backup_success=false
1086
+
1087
+ # Backup individual files
1088
+ for file in " ${preserve_files[@]} " ; do
1089
+ if [ -f " $PULSE_DIR /$file " ]; then
1090
+ local file_backup_dir=" $backup_base_dir /$( dirname " $file " ) "
1091
+ mkdir -p " $file_backup_dir "
1092
+ if cp " $PULSE_DIR /$file " " $backup_base_dir /$file " 2> /dev/null; then
1093
+ print_success " Backed up: $file "
1094
+ backup_success=true
1095
+ else
1096
+ print_warning " Failed to backup: $file "
1097
+ fi
1098
+ fi
1099
+ done
1100
+
1101
+ # Backup directories
1102
+ for dir in " ${preserve_dirs[@]} " ; do
1103
+ if [ -d " $PULSE_DIR /$dir " ] && [ " $( ls -A " $PULSE_DIR /$dir " 2> /dev/null) " ]; then
1104
+ if cp -r " $PULSE_DIR /$dir " " $backup_base_dir /$dir " 2> /dev/null; then
1105
+ print_success " Backed up directory: $dir "
1106
+ backup_success=true
1107
+ else
1108
+ print_warning " Failed to backup directory: $dir "
1109
+ fi
1110
+ fi
1111
+ done
1112
+
1113
+ if [ " $backup_success " = true ]; then
1114
+ echo " $backup_base_dir "
1115
+ return 0
1116
+ else
1117
+ rm -rf " $backup_base_dir " 2> /dev/null
1118
+ print_warning " No user data found to backup or all backups failed"
1119
+ return 1
1120
+ fi
1121
+ }
1122
+
1123
+ # Restore user configuration and data
1124
+ restore_user_data () {
1125
+ local backup_dir=" $1 "
1126
+
1127
+ if [ -z " $backup_dir " ] || [ ! -d " $backup_dir " ]; then
1128
+ print_warning " No backup directory provided or directory doesn't exist"
1129
+ return 1
1130
+ fi
1131
+
1132
+ print_info " Restoring user configuration from backup..."
1133
+
1134
+ # Restore files and directories
1135
+ if [ -d " $backup_dir " ]; then
1136
+ if cp -r " $backup_dir " /* " $PULSE_DIR /" 2> /dev/null; then
1137
+ # Fix ownership and permissions
1138
+ chown -R " $PULSE_USER " :" $PULSE_USER " " $PULSE_DIR "
1139
+
1140
+ # Set secure permissions on sensitive files
1141
+ [ -f " $PULSE_DIR /.env" ] && chmod 600 " $PULSE_DIR /.env"
1142
+
1143
+ print_success " User configuration restored successfully"
1144
+ return 0
1145
+ else
1146
+ print_error " Failed to restore user configuration"
1147
+ return 1
1148
+ fi
1149
+ fi
1150
+
1151
+ return 1
1152
+ }
1153
+
1002
1154
perform_update () {
1003
1155
if [ -z " $TARGET_TAG " ] && [ -z " $TARGET_BRANCH " ]; then
1004
1156
print_error " Target version tag or branch not determined. Cannot update."
@@ -1009,20 +1161,30 @@ perform_update() {
1009
1161
if [ -n " $TARGET_TAG " ]; then
1010
1162
print_info " Attempting to update Pulse to version $TARGET_TAG ..."
1011
1163
1012
- # Try tarball update first
1164
+ # Try tarball update first - this is safer and preserves user data
1013
1165
if perform_tarball_update; then
1014
1166
return 0
1015
1167
fi
1016
1168
1017
- # Fall back to git update
1018
- print_info " Tarball update failed, falling back to git update..."
1169
+ # Fall back to git update only if tarball fails
1170
+ print_warning " Tarball update failed, falling back to git update..."
1171
+ print_warning " ⚠️ Git update may be more disruptive to user configuration"
1019
1172
else
1020
1173
print_info " Attempting to update Pulse to branch $TARGET_BRANCH ..."
1021
1174
print_warning " ⚠️ Branch installations are for testing only and may be unstable!"
1022
1175
fi
1023
1176
1024
1177
cd " $PULSE_DIR " || { print_error " Failed to change directory to $PULSE_DIR " ; return 1; }
1025
1178
1179
+ # Create comprehensive backup of all user data before ANY destructive operations
1180
+ local user_data_backup=" "
1181
+ if user_data_backup=$( backup_user_data) ; then
1182
+ print_success " User data backup created at: $user_data_backup "
1183
+ else
1184
+ print_warning " Failed to create comprehensive user data backup"
1185
+ print_warning " Proceeding with update but configuration may be lost"
1186
+ fi
1187
+
1026
1188
local script_backup_path=" /tmp/${SCRIPT_NAME} .bak"
1027
1189
if [ -n " $SCRIPT_ABS_PATH " ] && [ -f " $SCRIPT_ABS_PATH " ]; then
1028
1190
print_info " Backing up current installer script to $script_backup_path ..."
@@ -1039,43 +1201,47 @@ perform_update() {
1039
1201
1040
1202
git config --global --add safe.directory " $PULSE_DIR " > /dev/null 2>&1 || print_warning " Could not configure safe.directory for root user."
1041
1203
1204
+ # Check git status before destructive operations
1205
+ local has_local_changes=false
1206
+ if sudo -u " $PULSE_USER " git status --porcelain 2> /dev/null | grep -q . ; then
1207
+ has_local_changes=true
1208
+ print_warning " Local changes detected in repository"
1209
+ fi
1210
+
1042
1211
print_info " Resetting local repository to discard potential changes [running as user $PULSE_USER ]..."
1043
1212
if ! sudo -u " $PULSE_USER " git reset --hard HEAD; then
1044
1213
print_error " Failed to reset local repository. Aborting update."
1045
1214
[ -n " $script_backup_path " ] && rm -f " $script_backup_path "
1215
+ [ -n " $user_data_backup " ] && rm -rf " $user_data_backup "
1046
1216
cd ..
1047
1217
return 1
1048
1218
fi
1049
1219
1050
- # Backup .env file before cleaning to preserve user configuration
1051
- local env_backup_path=" "
1052
- if [ -f " $PULSE_DIR /.env" ]; then
1053
- env_backup_path=" /tmp/.env.backup.$$ "
1054
- print_info " Backing up .env file to preserve user configuration..."
1055
- if cp " $PULSE_DIR /.env" " $env_backup_path " ; then
1056
- print_success " .env file backed up temporarily."
1057
- else
1058
- print_warning " Failed to backup .env file. Configuration may be lost."
1059
- env_backup_path=" "
1060
- fi
1061
- fi
1062
-
1063
- print_info " Cleaning untracked files and directories..."
1064
- if ! sudo -u " $PULSE_USER " git clean -fd; then
1065
- print_warning " Failed to clean untracked files, continuing anyway."
1066
- fi
1067
-
1068
- # Restore .env file after cleaning
1069
- if [ -n " $env_backup_path " ] && [ -f " $env_backup_path " ]; then
1070
- print_info " Restoring .env file..."
1071
- if cp " $env_backup_path " " $PULSE_DIR /.env" ; then
1072
- chown " $PULSE_USER " :" $PULSE_USER " " $PULSE_DIR /.env"
1073
- chmod 600 " $PULSE_DIR /.env"
1074
- print_success " .env file restored successfully."
1075
- else
1076
- print_warning " Failed to restore .env file from backup."
1220
+ # Only clean untracked files if absolutely necessary
1221
+ # Skip git clean entirely and handle conflicts more gracefully
1222
+ if [ " $has_local_changes " = true ]; then
1223
+ print_info " Checking for untracked files that might conflict..."
1224
+ local untracked_files=$( sudo -u " $PULSE_USER " git status --porcelain 2> /dev/null | grep ' ^??' | cut -c4-)
1225
+
1226
+ if [ -n " $untracked_files " ]; then
1227
+ print_warning " Found untracked files that may conflict with update:"
1228
+ echo " $untracked_files " | while read -r file; do
1229
+ print_warning " - $file "
1230
+ done
1231
+
1232
+ # Instead of git clean, selectively handle conflicts
1233
+ print_info " Moving conflicting files to temporary backup..."
1234
+ local conflict_backup=" /tmp/pulse-conflicts-$( date +%s) "
1235
+ mkdir -p " $conflict_backup "
1236
+
1237
+ echo " $untracked_files " | while read -r file; do
1238
+ if [ -f " $file " ] || [ -d " $file " ]; then
1239
+ local file_dir=" $conflict_backup /$( dirname " $file " ) "
1240
+ mkdir -p " $file_dir "
1241
+ mv " $file " " $conflict_backup /$file " 2> /dev/null || true
1242
+ fi
1243
+ done
1077
1244
fi
1078
- rm -f " $env_backup_path "
1079
1245
fi
1080
1246
1081
1247
print_info " Fetching latest changes from git [running as user $PULSE_USER ]..."
@@ -1175,6 +1341,17 @@ perform_update() {
1175
1341
print_warning " Continuing update, but frontend may not display correctly."
1176
1342
fi
1177
1343
1344
+ # Restore user data BEFORE setting permissions
1345
+ if [ -n " $user_data_backup " ] && [ -d " $user_data_backup " ]; then
1346
+ if restore_user_data " $user_data_backup " ; then
1347
+ print_success " User configuration and data restored successfully"
1348
+ else
1349
+ print_warning " Failed to restore some user configuration"
1350
+ fi
1351
+ # Cleanup backup after restoration
1352
+ rm -rf " $user_data_backup "
1353
+ fi
1354
+
1178
1355
set_permissions
1179
1356
1180
1357
print_info " Ensuring systemd service $SERVICE_NAME is configured..."
0 commit comments