Skip to content

Install updates in place instead of requiring a manual drag to Applications - #10

Open
arnabbagxd wants to merge 1 commit into
mainfrom
fix/in-place-update-install
Open

Install updates in place instead of requiring a manual drag to Applications#10
arnabbagxd wants to merge 1 commit into
mainfrom
fix/in-place-update-install

Conversation

@arnabbagxd

Copy link
Copy Markdown
Owner

Summary

  • The "Update" button previously just opened the downloaded .dmg/.zip and left the user to drag the new app into /Applications and relaunch it themselves — the button implied a full update, but nothing was actually replaced.
  • AppUpdateInstaller now mounts the .dmg (or unzips a .zip via ditto), locates the .app inside it, and atomically swaps it in for the currently running app bundle with FileManager.replaceItemAt — the same technique Sparkle uses, which is safe even while the old app is still running (Unix keeps the old inode alive until the process exits).
  • After the swap it relaunches the new copy (open -n) and quits the old process.
  • If the in-place install fails for any reason (e.g. no write access to the install location), it falls back to the previous manual "open the installer" flow with a clear error, instead of failing silently.

Why

User-reported confusion: people who already had the app installed would get the update prompt, click "Update," and nothing visibly happened to their installed copy — they had to notice the mounted disk image and manually drag-replace it themselves.

Test plan

  • swift build — clean
  • swift test — 16/16 passing
  • Manually verified the core mount → find .app → copy → atomic replaceItemAt → unmount pipeline against a real built .dmg, targeting a throwaway app copy (not the live dev app): confirmed the bundle's modification date changed and the executable remained present and executable at the same path afterward
  • Manual smoke test in a real install: trigger an update prompt end-to-end and confirm relaunch lands on the new version

Notes for reviewers

  • No change to signing/notarization requirements — this works with the existing ad-hoc-signed free release path.
  • Known limitation: if the app is installed somewhere the current user can't write to without elevated privileges (uncommon on a normal single-user Mac), the in-place install fails and falls back to manual install rather than prompting for admin rights the way Sparkle's installer XPC service does.

🤖 Generated with Claude Code

…ations

Clicking "Update" previously just opened the downloaded .dmg and left the
user to drag the app into Applications themselves — confusing, since the
button implied it would just update. AppUpdateInstaller now mounts the
.dmg (or unzips a .zip), atomically swaps the new app bundle in for the
running one (the same trick Sparkle uses — safe even while the old app
is running), and relaunches. Falls back to the old manual-open flow if
the in-place install fails for any reason (e.g. no write access).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant