Separate the Ruby backend from internal Homebrew dependencies
Closed this issue · 6 comments
Background
Homebrew-cask is implemented as a Homebrew external command, in the form of
brew-cask.rb
, which is require
d by the brew
command. This means that
Homebrew-cask has full access to, and is constrained by, the Ruby runtime
provided by Homebrew.
Initially it was thought that Homebrew-cask would re-use much of Homebrew's
code internally. That turned out not to be the case in practice, largely
because Homebrew's code is organized around the Formula.
Proposal
brew-cask.rb
should be re-implemented as an executable brew-cask
, which
would be invoked by Homebrew rather than require
d. brew-cask
would
then execute completely independently of Homebrew's Ruby environment.
This would be an internal-only change. The user interface would stay the
same. Commands would still be invoked via brew cask <verb>
, and we would
still piggyback on brew update
to get new Casks.
Advantages
- Stability. Homebrew does not guarantee any internal APIs.
Homebrew-cask frequently breaks due to changes within Homebrew
(#4732, #4982, #4229, many others). - Clarity. Where we do re-use Homebrew's classes (such as for
downloading), we do so only partially, with some methods overridden.
This needlessly obscures what the code is doing, making it more difficult
to diagnose bugs or develop new functionality. - Error Reporting. Both Homebrew and Homebrew-cask attempt to
rescue exceptions and direct users to the relevant issues URL. @voanhduy1512
did some good work on this problem, but it still crops up as in #5108. Every
misdirected report is a drain on maintainers (in both projects). - Cleanup. Currently
brew cask cleanup
works in a roundabout
way (using tracking symlinks) because we share a download location
with Homebrew. It would be more robust to maintain our own download
cache. - Ruby 2.0. We would have the choice to be more aggressive about
switching to Ruby 2.0 (say, 6 months after Yosemite is released). We
could require Mountain Lion and earlier to install Ruby 2.0 as a
prerequisite. This would not only gain us access to new language
features, but reduce the currently-imposed burden of maintaining
compatibility across Ruby 1.8 and 2.0. - Freedom. Currently we are constrained by Homebrew's decisions with
regard to character encodings, interpreter version, monkeypatching -- all
things that, once inherited, we cannot easily undo.
Disadvantages
- Tap Migration. We have sometimes used internal interfaces to Homebrew
which are not available externally, as with the tap migration code (#4169).
However, this also could have been accomplished by copying the relevant
logic from Homebrew. - Integration for files in /usr/local. Some Casks install files into
/usr/local
,
which causesbrew doctor
to complain as in #2350 and others. Currently
we have acaveats
warning for this, which is not really a fix. As mentioned
in #3693, we could fully resolve the problem by installing files to a Homebrew
Cellar, and then symlinking into the Cellar as with any other Homebrew
installation. Such a technique would become more difficult if we could not
call directly into Homebrew.- However, it also seems that nobody is working on that implementation.
- There are other possible approaches, such as generating an ad hoc Formula.
Places where we currently re-use Homebrew's code (incomplete)
- global methods such as
onoe
(example install.rb)- these are mostly trivial
- relevant code would have to be forked from Homebrew
- in some cases, we can simplify and/or get more desirable behavior
- monkeypatched methods on Pathname ?
- preferable to remove these where they may exist
- we at least use our own variant monkeypatch
cabv
(#2991)
- implicit tapping (#2303)
- can be replaced by invoking
brew tap <Tapname>
- can be replaced by invoking
- downloading, eg
Cask::CurlDownloadStrategy
(see comments in download_strategy.rb)- relevant code would have to be forked from Homebrew
- calculation of checksums
- would be simplified, as our project only uses one checksum type
depends_on_formula
(#2305)- can be replaced by invoking
brew install <formula>
- can be replaced by invoking
- automatic tap migration (#4169)
- this code was meant to be temporary in any case
- test suite
- we have also been discussing rearchitecting the test suite to use RSpec
Tracker
- Wait until Tap migration code can be safely removed (minimum of 90 days,
roughly 3 August.) - Convert
brew-cask.rb
to a bash-script executable shimbrew-cask
(#8089) - Update Formula
brew-cask.rb
(a different file) to support the new setup (#8089) - Fork and check in all Homebrew code needed for tests to pass (#8089)
- Refactor: integrate all needed classes & methods organically in our codebase
- #8155
- #8158
- #8188
- #8189
- #8194
- #8195
- #8196
- #8197
- #8218
- #8221
- #8225
- #8226
- #8227
- #8228
- #8229
- #8230
- #8247
- #8261
- #8263
- #8264
- #8265
- #8266
- #8268
- #8295
- #8296
- #8297
- #8298
- #8308
- #8310
- #8312
- #8314
- #8328
- #8329
- #8330
- #8331
- #8332
- #8333
- #8334
- #8335
- #8336
- #8337
- #8338
- #8339
- #8340
- #8341
- #8342
- #8361
- #8369
- #8388
- #8389
- #8390
- #8391
- #8392
- #8393
- #8402
- #8403
- #8425
- #8426
- #8427
- #8428
- #8433
- #8434
- #8435
- #8436
- #8437
- #8446
- #8447
- #8448
- #8458
- #8460
- #8461
- #8464
- #8466
- #8522
- #8539
- #8552
- #8556
- #8557
- #8559
- #8561
- #8595
- #8611
- #8612
- #8721
- #8724
- #8870
- make
Hbc::SystemCommand
safe for commands with large writes to STDERR as performed by curl - execute curl via
Hbc::SystemCommand
, migrating it out of homebrew-fork - migrate
Hbc::HbCurlDownloadStrategy
from homebrew-fork -
Hbc::HbSubversionDownloadStrategy
cleanups- remove
shell_quote
method - use
Hbc::SystemCommand
instead ofquiet_system
- use
Hbc::SystemCommand
instead of backticks
- remove
- migrate
Hbc::HbSubversionDownloadStrategy
from homebrew-fork - migrate
Hbc::HbVCSDownloadStrategy
from homebrew-fork - revise download caching
- create our own cache at
/Library/Caches/Homebrew-cask
, setting value inHbc::Locations
- remove
HOMEBREW_CACHE
constant fromglobal.rb
- remove
HOMEBREW_CACHE
constant fromtesting_env.rb
, and inject a test value for both rspec and minitest - transitional code: at startup, automatically purge all old files tracked by
/Library/Caches/Homebrew/Casks
, if seen - simplify
brew cask cleanup
(no longer needs to use subdirectory and tracking symlinks)
- create our own cache at
- delete homebrew-fork
download_strategy.rb
- delete homebrew-fork
exceptions.rb
- delete homebrew-fork
global.rb
- delete homebrew-fork
monkeypatch_pathname.rb
- delete homebrew-fork
testing_env.rb
- delete homebrew-fork
utils.rb
- delete directory
lib/vendor/homebrew-fork
Edits:
- added Disadvantage / Integration for files in
/usr/local
- added Tracker
- added Error Reporting
- renamed Plan to Tracker; filled out Tracker details
and add:
Advantages:
standalone: just install cask
without the need to install brew
just install
cask
without the need to installbrew
Not exactly. From the post:
we would still piggyback on
brew update
to get new Casks.
if brew is in stalled then piggyback on brew update
and for without brew add a cask update
cc @phinze
@jawshooah Since we now want to go in the opposite direction, should we close this, or is it still useful in some way?
No use in leaving it open.