diff --git a/packaging/windows/installer.nsh b/packaging/windows/installer.nsh index 5dc1415..ddd97de 100644 --- a/packaging/windows/installer.nsh +++ b/packaging/windows/installer.nsh @@ -121,103 +121,72 @@ Var FinalInstDir ${EndIf} !macroend -; Returns 0 in $R9 when $R8 can be renamed (file unlocked / path free). -; _ID must be unique per insert so labels do not collide. -!macro tryRenameProbe _ID - StrCpy $R9 1 - ${IfNot} ${FileExists} "$R8" - StrCpy $R9 0 - Goto try_rename_probe_done_${_ID} - ${EndIf} - - ClearErrors - Rename "$R8" "$R8.updating" - ${If} ${Errors} - Goto try_rename_probe_done_${_ID} - ${EndIf} - - ; Leave the .updating name — the whole tree is about to be deleted. - StrCpy $R9 0 - try_rename_probe_done_${_ID}: -!macroend - -; Wait until the live install directory is released by the quitting app. -!macro waitForInstallDirWritable - !insertmacro progressStatus "Waiting for Farm Control to release install files..." - DetailPrint "Waiting for install directory to become writable..." - - StrCpy $R7 0 - wait_install_writable: - ; Probe the main binaries — rename fails while the process still holds them. - StrCpy $R8 "$FinalInstDir\bin\FarmControl.exe" - !insertmacro tryRenameProbe farmcontrol - ${If} $R9 != 0 - Goto wait_install_writable_retry - ${EndIf} - - StrCpy $R8 "$FinalInstDir\bin\launcher.exe" - !insertmacro tryRenameProbe launcher - ${If} $R9 != 0 - Goto wait_install_writable_retry - ${EndIf} - - ; Also probe creating a temp file in the install root. - ClearErrors - FileOpen $R8 "$FinalInstDir\.farmcontrol-write-probe" w - ${If} $R8 == "" - Goto wait_install_writable_retry - ${EndIf} - FileClose $R8 - Delete "$FinalInstDir\.farmcontrol-write-probe" - Goto wait_install_writable_done - - wait_install_writable_retry: - IntOp $R7 $R7 + 1 - ${If} $R7 < 60 - Sleep 500 - Goto wait_install_writable - ${EndIf} - !insertmacro progressFailure "Could not access the previous Farm Control installation." - Abort - - wait_install_writable_done: -!macroend - +; Swap order: Farm Control -> .old, Farm Control.new -> Farm Control, delete .old. !macro swapUpdateStaging !insertmacro progressPhase "Applying update" + !insertmacro progressStatus "Replacing Farm Control with the new version..." + DetailPrint "Replacing Farm Control with staged update..." + + ; Clear a leftover .old from a previous interrupted update. + ${If} ${FileExists} "$FinalInstDir.old" + DetailPrint "Removing leftover Farm Control.old..." + RMDir /r "$FinalInstDir.old" + ${EndIf} ${If} ${FileExists} "$FinalInstDir" - !insertmacro waitForInstallDirWritable - - !insertmacro progressStatus "Replacing Farm Control with the new version..." - DetailPrint "Replacing Farm Control with staged update..." + !insertmacro progressStatus "Waiting for Farm Control to release install files..." + DetailPrint "Waiting to rename install directory to Farm Control.old..." StrCpy $R7 0 - swap_delete_retry: - RMDir /r "$FinalInstDir" - ${If} ${FileExists} "$FinalInstDir" + swap_rename_old_retry: + ClearErrors + Rename "$FinalInstDir" "$FinalInstDir.old" + ${If} ${Errors} IntOp $R7 $R7 + 1 - ${If} $R7 < 20 + ${If} $R7 < 60 Sleep 500 - Goto swap_delete_retry + Goto swap_rename_old_retry ${EndIf} - !insertmacro progressFailure "Could not remove the previous Farm Control installation." + !insertmacro progressFailure "Could not move the previous Farm Control installation aside." Abort ${EndIf} ${EndIf} !insertmacro progressStatus "Activating new Farm Control installation..." - DetailPrint "Activating staged update..." + DetailPrint "Renaming Farm Control.new to Farm Control..." ClearErrors Rename "$INSTDIR" "$FinalInstDir" ${If} ${Errors} + ; Best-effort rollback so the previous install is usable again. + ${If} ${FileExists} "$FinalInstDir.old" + Rename "$FinalInstDir.old" "$FinalInstDir" + ${EndIf} !insertmacro progressFailure "Could not activate the new Farm Control installation." Abort ${EndIf} StrCpy $INSTDIR $FinalInstDir !insertmacro progressLog "installer:STATUS:Update files activated" + + ${If} ${FileExists} "$FinalInstDir.old" + !insertmacro progressStatus "Removing previous Farm Control installation..." + DetailPrint "Removing Farm Control.old..." + + StrCpy $R7 0 + swap_delete_old_retry: + RMDir /r "$FinalInstDir.old" + ${If} ${FileExists} "$FinalInstDir.old" + IntOp $R7 $R7 + 1 + ${If} $R7 < 20 + Sleep 500 + Goto swap_delete_old_retry + ${EndIf} + ; New version is already active; leftover .old is non-fatal. + DetailPrint "Warning: could not fully remove Farm Control.old" + !insertmacro progressLog "installer:STATUS:Warning: could not fully remove previous installation" + ${EndIf} + ${EndIf} !macroend !macro uninstallPreviousFarmControl