-
-
Notifications
You must be signed in to change notification settings - Fork 9.4k
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
Add cask install receipts #17554
base: master
Are you sure you want to change the base?
Add cask install receipts #17554
Conversation
93f8bf2
to
a6e1592
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think in general the approach looks good. It'd be nice to be able to share logic between the formula and cask tab classes though it's possible that there isn't enough overlap to make that worth it.
There are few use cases for this that I've seen recently and I think they all seem to be covered here.
- Storing the tap that a cask was installed from.
- Useful when loading installed casks and troubleshooting installs.
- Wrong tap when listing installed casks from custom taps using
--json=v2 --installed
#17416
- Storing the cask version.
- Useful when upgrading casks to make sure they don't get accidentally downgraded.
- brew upgrade can actually downgrade casks in some configurations #17427
Do you have an example what the tab of a cask with an uninstall DSL looks like? Idea being we avoid reading the Ruby file entirely when uninstalling, except for flight blocks which the tab should have a boolean or something that indicates those are used. |
Here is the tab for {
"homebrew_version": "4.3.6-71-ge30aea5-dirty",
"loaded_from_api": true,
"installed_as_dependency": false,
"installed_on_request": true,
"time": 1719197835,
"dependencies": {
"macos": {
">=": [
"10.15"
]
}
},
"arch": "arm64",
"source": {
"path": "",
"tap": "homebrew/cask",
"tap_git_head": "f755fc333ebe7647fa3988e360d47a82120db032",
"version": "4.39.88"
},
"installed_on": {
"os": "Macintosh",
"os_version": "macOS 14",
"cpu_family": "arm_firestorm_icestorm",
"xcode": "15.4",
"clt": "15.3.0.0.1.1708646388",
"preferred_perl": "5.34"
},
"artifacts": [
{
"uninstall": [
{
"quit": "com.tinyspeck.slackmacgap"
}
]
},
{
"app": [
"Slack.app"
]
},
{
"zap": [
{
"trash": [
"~/Library/Application Scripts/com.tinyspeck.slackmacgap",
"~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.tinyspeck.slackmacgap.sfl*",
"~/Library/Application Support/Slack",
"~/Library/Caches/com.tinyspeck.slackmacgap*",
"~/Library/Containers/com.tinyspeck.slackmacgap*",
"~/Library/Cookies/com.tinyspeck.slackmacgap.binarycookies",
"~/Library/Group Containers/*.com.tinyspeck.slackmacgap",
"~/Library/Group Containers/*.slack",
"~/Library/HTTPStorages/com.tinyspeck.slackmacgap*",
"~/Library/Logs/Slack",
"~/Library/Preferences/ByHost/com.tinyspeck.slackmacgap.ShipIt.*.plist",
"~/Library/Preferences/com.tinyspeck.slackmacgap*",
"~/Library/Saved Application State/com.tinyspeck.slackmacgap.savedState",
"~/Library/WebKit/com.tinyspeck.slackmacgap"
]
}
]
}
]
}
Right now the format I'm saving the artifacts in is the same that is used in the API, so that should be possible (that's what I anticipated happening). Good note on the boolean to indicate about flight blocks, I'll add that. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good so far, great work @Rylan12!
In both of these cases: we should store the same for formulae and in the same format for both (to make parsing either easier).
My understanding is also we hope to be able to eventually deprecate these flight blocks so that only the tab is needed for uninstall. |
Yeah, though key word there is "eventually" and no one's working on it yet so still should have something in the meantime to improve the majority of cases while we work on improving the final few cases that use flight blocks. Flight block phasing out will likely require multiple distinct enhancements to the uninstall DSL. |
Agreed: just think it's worth considering with the design that we will hopefully not keep this around indefinitely. |
336fd06
to
a4ea7d8
Compare
I've pushed changes to have casks use the same I also updated the |
if uninstall_phase_only && | ||
!artifact.respond_to?(:uninstall_phase) && !artifact.respond_to?(:post_uninstall_phase) | ||
next | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: I think this should be a separate method to make the code more understandable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it needs to be a separate method, personally. I think it's fairly obvious what's going on here from the naming.
@sourcefile_path = path | ||
@path = path || CaskLoader.default_path(@token) | ||
@sourcefile_path = path || CaskLoader.default_path(@token) | ||
@path = @sourcefile_path |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes requested: This change needs more thought. The expectation in Cask::Cask
is that sourcefile_path
points to the Ruby source file and this breaks that assumption.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@apainintheneck What's the status quo here if there's no Ruby source file available?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: Ideally there would be a better separation of logic here. That could come in the form of a base class that both tabs inherit from or a mixin. As currently implemented, it involves a bunch of checks for the cask and formula versions of the tab logic and methods which are not relevant to one or the other type of tab are present at all times.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I somewhat agree. I think rather than having do_something
methods that call do_formula_something
or do_cask_something
or type: :formula
parameters, it'd be up to the caller to call the appropriate method(s).
That may remove the need for separate classes by providing sufficient separation. If not, a base tab class that's inherited as FormulaTab
or CaskTab
or something feels nicer than two mixins that are only used on a single class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work so far, thanks @Rylan12!
if uninstall_phase_only && | ||
!artifact.respond_to?(:uninstall_phase) && !artifact.respond_to?(:post_uninstall_phase) | ||
next | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it needs to be a separate method, personally. I think it's fairly obvious what's going on here from the naming.
@sourcefile_path = path | ||
@path = path || CaskLoader.default_path(@token) | ||
@sourcefile_path = path || CaskLoader.default_path(@token) | ||
@path = @sourcefile_path |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@apainintheneck What's the status quo here if there's no Ruby source file available?
def self.create(formula_or_cask, compiler = nil, stdlib = nil) | ||
return create_from_formula(formula_or_cask, compiler, stdlib) if formula_or_cask.is_a? Formula |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: this continues to only create from formulae, raises an specific exception/error message if provided a cask and we use odeprecated
to migrate all callers to use create_from_formula
or create_from_cask
directly instead.
"installed_as_dependency" => false, | ||
"installed_on_request" => false, | ||
"poured_from_bottle" => false, | ||
"loaded_from_api" => false, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like useful to maintain as a generic attribute.
"time" => Time.now.to_i, | ||
"source_modified_time" => formula.source_modified_time.to_i, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And this.
end | ||
end | ||
|
||
# Like {from_file}, but bypass the cache. | ||
def self.from_file_content(content, path) | ||
def self.from_file_content(content, path, type: :formula) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Think similarly this would be better being two methods: from_formula_file_content
or from_cask_file_content
and we odeprecate
from_file_content
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I somewhat agree. I think rather than having do_something
methods that call do_formula_something
or do_cask_something
or type: :formula
parameters, it'd be up to the caller to call the appropriate method(s).
That may remove the need for separate classes by providing sufficient separation. If not, a base tab class that's inherited as FormulaTab
or CaskTab
or something feels nicer than two mixins that are only used on a single class.
Apologies for closing @Rylan12, my bad :( |
brew style
with your changes locally?brew typecheck
with your changes locally?brew tests
with your changes locally?This PR is my first go at adding a cast install receipt (which I've called
Tab
to align for formulae) as per #17013.Here is a sample
INSTALL_RECEIPT.json
that is generated when I runbrew install --cask warp
:It doesn't quite work yet (there are some test failures and some other things still) but I wanted to push this up to start getting feedback on the strategy.