Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't remove cask directories when upgrading. #15138

Merged
merged 13 commits into from
May 4, 2023

Conversation

JBYoshi
Copy link
Contributor

@JBYoshi JBYoshi commented Apr 3, 2023

  • Have you followed the guidelines in our Contributing document?
  • Have you checked to ensure there aren't other open Pull Requests for the same change?
  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your changes? Here's an example.
  • Have you successfully run brew style with your changes locally?
  • Have you successfully run brew typecheck with your changes locally?
  • Have you successfully run brew tests with your changes locally?

When updating casks, Homebrew deletes the old version of the application before moving the new one in its place. This causes macOS to think that the application was uninstalled, and so it may get removed from places like notification settings and Launchpad. This PR changes the move behavior for cask directories so the app directory itself is retained during the upgrade, while the contents are replaced.

Fixes Homebrew/homebrew-cask#102721.

@reitermarkus reitermarkus added the cask Homebrew Cask label Apr 4, 2023
@reitermarkus
Copy link
Member

Okay, so instead of essentially rm -r App.app, we only rm -r App.app/* and then replace the contents?

Do you have an example cask that breaks if you remove it completely to test this?

@JBYoshi JBYoshi marked this pull request as ready for review April 4, 2023 01:22
@JBYoshi
Copy link
Contributor Author

JBYoshi commented Apr 4, 2023

That's the gist of it.

I haven't figured out an automated test case yet since I don't know of any APIs that Apple exposes for the dock / Launchpad. However, I have been manually testing using the 1password cask. Here's my current procedure:

  • Add a sleep(10) call to the end of Cask::Artifact::Moved::delete(). (This accounts for the timing sensitivity discussed in the original issue.)
  • Install an old version of the 1password cask (I used 8.10.1).
  • Pin the 1Password app to the dock and/or add it to a folder in Launchpad.
  • Change the cask file to a newer version (I used 8.10.3).
  • Run brew upgrade.

With the original code, the 1Password app will disappear from the dock and will be moved out of the folder in Launchpad. With this code, the app remains in the dock and the Launchpad folder.

One possible automated test case could be making sure the inode number stays the same before and after the upgrade. That wouldn't check Launchpad or the dock directly but it will ensure the directory isn't deleted.

@reitermarkus
Copy link
Member

Is copying xattrs crucial for this to work? Do we care about any xattrs apart from the quarantine attribute?

@reitermarkus reitermarkus requested a review from a team April 4, 2023 01:46
Copy link
Member

@MikeMcQuaid MikeMcQuaid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code seems reasonable to me but will wait for another @Homebrew/cask 👍🏻/✅ first.

If this stops the "multiple VSCode icons in my toolbar" issues: I will be very grateful.

@bevanjkay
Copy link
Member

@MikeMcQuaid Unfortunately this won't solve the issue with Visual Studio Code. There's something with the architecture that allows multiple instances of the app to be running, and when two different versions of the app are open, two icons are present in dock. I have checked out this branch and will see how it goes over the next day or so with these changes and report back.

@bevanjkay
Copy link
Member

I can confirm that this is working as expected with a cask that is known to have this issue (Spotify).

A couple of questions;

  1. Should the same logic apply with brew reinstall <token>?
  2. Should the xattr be copied across? Should the user only be notified about the source when they are opening and upgraded app for the first time? My assumption is that we should expect the notification whenever the binary/version changes for security purposes?
“Spotify” is an app downloaded from the internet. Are you sure you want to open it?

@JBYoshi
Copy link
Contributor Author

JBYoshi commented Apr 4, 2023

For the xattrs part, the original behavior includes copying xattrs (link), so I kept that for consistency.

brew reinstall might be a good idea to support as well. I'll look into that later today.

Copy link
Member

@p-linnane p-linnane left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would love if this resolves our long standing issue. Thanks @JBYoshi!

@JBYoshi
Copy link
Contributor Author

JBYoshi commented Apr 4, 2023

I've changed the upgrade parameter on artifacts to upgrade_or_reinstall so this behavior should also apply to reinstalls. I'll note that the upgrade parameter was also used for login item uninstallation, but I think it would also make sense to use this behavior for login item reinstalls, so I've pulled that completely into the upgrade_or_reinstall behavior.

Copy link
Member

@reitermarkus reitermarkus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there is an edge case that still needs to be handled here:

If an app is renamed, will this leave an empty directory for the old app name?

@SMillerDev
Copy link
Member

Does this work with codesigning too? Otherwise it'll disable any upgraded app on ARM.

@bevanjkay
Copy link
Member

@SMillerDev I have been using this branch on my ARM MacBook for the last couple of days and all seems to be well.

@JBYoshi
Copy link
Contributor Author

JBYoshi commented Apr 8, 2023

I think there is an edge case that still needs to be handled here:

If an app is renamed, will this leave an empty directory for the old app name?

Good point. I've added some behavior to handle that by passing in the old and new versions of the casks to the artifact installation and uninstallation steps.

@apainintheneck
Copy link
Contributor

Looks like this needs to be updated to reflect the changes made to cask/reinstall in #15184.

@JBYoshi
Copy link
Contributor Author

JBYoshi commented Apr 16, 2023

Updated to fix the merge conflicts.

@MikeMcQuaid
Copy link
Member

Fine with this when @reitermarkus is.

@JBYoshi
Copy link
Contributor Author

JBYoshi commented Apr 23, 2023

Any updates on this?

Copy link
Member

@reitermarkus reitermarkus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some small suggestions, but should be ready to merge after that.

Maybe the artifacts.any? part can also be moved into a helper method since it's the same for move and delete.

ohai "Removing #{self.class.english_name} '#{target}'"
raise CaskError, "Cannot remove undeletable #{self.class.english_name}." if MacOS.undeletable?(target)

return unless Utils.path_occupied?(target)

if target.parent.writable? && !force
if !successor.nil? && target.directory? && successor.artifacts.any? do |a|
a.class.dsl_key == self.class.dsl_key && a.target == self.target
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
a.class.dsl_key == self.class.dsl_key && a.target == self.target
a.class == self.class && a.target == self.target

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated, with one caveats from the style checker. It doesn't like an equality test on the classes, so I used a two-way instance_of? check that has the same behavior.

Copy link
Member

@reitermarkus reitermarkus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One small change still needed, otherwise looks ready to merge.

@JBYoshi
Copy link
Contributor Author

JBYoshi commented Apr 30, 2023

Updated for that feedback.

Copy link
Member

@carlocab carlocab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that there's a new release tag, we should get this in ASAP so this has time to bake.

@MikeMcQuaid MikeMcQuaid requested a review from reitermarkus May 1, 2023 14:35
@reitermarkus reitermarkus requested a review from MikeMcQuaid May 2, 2023 22:12
Copy link
Member

@MikeMcQuaid MikeMcQuaid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Some style suggestions.

@JBYoshi
Copy link
Contributor Author

JBYoshi commented May 3, 2023

@MikeMcQuaid Done.

@MikeMcQuaid MikeMcQuaid merged commit 0e387fe into Homebrew:master May 4, 2023
@MikeMcQuaid
Copy link
Member

Thanks so much for your first, great contribution (hopefully of many)! Without people like you submitting PRs we couldn't run this project. You rock, @JBYoshi!

@JBYoshi JBYoshi deleted the cask-move-contents branch May 4, 2023 15:46
@SMillerDev
Copy link
Member

Could this be causing https://github.com/orgs/Homebrew/discussions/4498?

@timfallmk
Copy link

Could this be causing https://github.com/orgs/Homebrew/discussions/4498?

This is very likely related. I ran into the same problem when running a standard upgrade of chrome and chrome canary a day ago, but didn't see any reports of it at the time.

I'll see if I can dig some relevant logs back out.

@Bo98
Copy link
Member

Bo98 commented May 10, 2023

I've merged #15399 which will improve the errors a bit (the stack trace will actually be useful now), but yeah will need to track down the source.

Apparently the issues might be Ventura-specific. I'm running Monterey at the moment.

@SMillerDev
Copy link
Member

I'm running the beta, let me know if I can test something

@xkia
Copy link

xkia commented May 18, 2023

On the Ventura, it is not possible to upgrade the application of cash normally

@maxim-badarau-m10
Copy link

Any updates on the issue, it happen for me today

@JBYoshi
Copy link
Contributor Author

JBYoshi commented May 24, 2023

I think these issues might have to do with the new "App Management" permissions in macOS Ventura. More info here: Homebrew/homebrew-cask#147383 (comment)

@github-actions github-actions bot added the outdated PR was locked due to age label Jun 24, 2023
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jun 24, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
cask Homebrew Cask outdated PR was locked due to age
Projects
None yet
Development

Successfully merging this pull request may close these issues.

upgrade/reinstall induce time-dependent dock and launchpad behavior