fix: use whole-app symlinks for self-updating apps - #18
Conversation
|
Thanks a lot for your contribution! Your work actually helped identify and fix an important issue that we previously didn't fully understand. The first commit has been merged #17. However, has already been merged into main and the codebase has changed, so the second commit now has conflicts. If you'd like, feel free to update it based on the latest main branch and I’ll be happy to review it again. |
|
Follow-up after real-world repro on my machine:
I verified that restoring Cursor as a normal local app fixes the issue immediately, and the problem is consistent with self-updating apps being incompatible with the I have also refreshed this PR branch against the latest Given this repro, I still think the whole-app symlink fallback for self-updating apps is worth merging. |
|
Thanks again for the earlier feedback. I checked PR #18 again against the latest From my verification, I don’t think #17 and #18 conflict logically:
So my understanding is:
These two changes look complementary rather than mutually exclusive. I also reproduced the real issue locally with Cursor, and the breakage is consistent with self-updating apps being incompatible with the If helpful, I’m happy to further adjust the patch to match your preferred style. |
I also encountered the issue where self-updating applications stored on an external hard drive disappeared after updating. I attempted to resolve it but may not have succeeded, so in my commit I recommended moving the application back to the internal drive before updating. It's great to hear that you have a solution to this problem. |
|
Thank you so much for this contribution! This is a critical fix that significantly improves AppPorts' compatibility with self-updating apps. A quick note on the merge: Since my local develop branch was slightly out of date compared to main (which already had the 1.5.0 localization and migration features), I have manually synchronized the branches and resolved the conflicts. Status: Your fix is now successfully merged into the main branch.
|
Summary
AppPorts currently migrates native macOS apps by leaving a local
.appshell in/Applicationsand symlinking only itsContentsdirectory to the external app bundle.That works well for many apps, but it is fragile for self-updating apps such as VS Code / Cursor / other Electron apps using Squirrel, and for apps using Sparkle.
Those updaters tend to assume the bundle at
/Applications/Foo.appis a complete bundle. With a fake shell +Contentssymlink, updates can break the portal or silently de-migrate the app.This PR adds a compatibility fallback:
Squirrel.framework,Sparkle.framework,ShipIt,AutoUpdate, etc.)Contentsdeep-link strategyWhy this helps
A whole-app symlink is less pretty in Finder, but it preserves bundle-level expectations better for apps that mutate or replace themselves during update.
This is especially relevant for VS Code-like apps, where auto-update is otherwise prone to breaking the AppPorts portal.
Validation
swiftc -typecheckpassed against the project sources using the macOS SDK after stripping#Previewblocks into a temp copy (the current machine only has Command Line Tools, soxcodebuildis unavailable here)Scope
This PR intentionally keeps the change small:
If you like this direction, a follow-up could expose the selected strategy in the UI or let users choose between
Contentsmode and compatibility mode manually.