cask/quarantine: gate metadata operations behind a single doorway - #23628
Open
aholland wants to merge 1 commit into
Open
cask/quarantine: gate metadata operations behind a single doorway#23628aholland wants to merge 1 commit into
aholland wants to merge 1 commit into
Conversation
The operations that read or write quarantine metadata previously relied on every call site remembering to check Quarantine.available? first; two call sites forgot, crashing cask upgrades and installs where there is no quarantine support. Move those operations onto Quarantine::Metadata, a class whose only instance is constructed inside Quarantine.when_available, which performs the check once and yields it: holding the instance proves the check has happened, so a call site can no longer forget it.
MikeMcQuaid
requested changes
Aug 23, 2026
| sudo: true) | ||
| end | ||
| Quarantine.copy_xattrs(source, target, command:) if Quarantine.available? | ||
| Quarantine.when_available { it.copy_xattrs(source, target, command:) } |
Member
There was a problem hiding this comment.
This doesn't seem like a good API/improvement to me.
If anything I'd say just:
Suggested change
| Quarantine.when_available { it.copy_xattrs(source, target, command:) } | |
| Quarantine.copy_xattrs(source, target, command:) |
and make it a no-op when quarantine isn't available.
Contributor
Author
There was a problem hiding this comment.
Thanks, considering this. Will follow up but likely only over the w/e.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
@MikeMcQuaid, the current and ongoing requirement for every caller of any of the quarantine methods to be mindful of the seven that raise when eg not on macOS, and to remember to gate said calls with the likes of
return unless Quarantine.available?was bothering me. The recent PRs #23608 and #23617 were the second and third bugs due to this and #23226 was the first. This struck me as too much contract, not enough DRY. Here is a solution. That it makes the call sites simpler is a good sign. However, I recognise that the changes toCask::Quarantineare significant.The operations that read or write quarantine metadata (
detect,status,release!,propagate,inherit_user_approval!,cask!,copy_xattrs) move ontoQuarantine::Metadata, a class whose constructor is private and whose only instance is handed out by a doorway that performs the availability check once:When quarantine is unavailable the block simply doesn't run (the two multi-statement call sites in
upgrade.rbuse thedo |quarantine|form). A call site can no longer forget the check, because the check is no longer the call site's job, and since constructingMetadataanywhere else is aNoMethodError, holding the instance proves the check has happened. The methods that are already safe everywhere (available?,user_approved?,user_approved_paths,signing_identity,signing_identity_match,app_management_permissions_granted?) stay on the module, and their callers are unchanged.All seven call sites of the moved operations are converted (two each in
download.rb,audit.rbandupgrade.rb, one inmoved.rb), and each conversion deletes the guard it previously had to carry. The macOS implementations ofcask!andcopy_xattrsbecome an ordinary instance-method module prepended toMetadata. Behaviour is unchanged on every platform; this is a restructuring with no new features.Details
brewcommands to reproduce the bug?brew lgtm(style, typechecking and tests) locally?Used Claude Code (Fable 5) to investigate and draft; I directed the investigation and design choices, and reviewed the diff and every line of this PR text.