diff --git a/Library/Homebrew/cask.rb b/Library/Homebrew/cask.rb index f4b32a21fd..dacb4c9da3 100644 --- a/Library/Homebrew/cask.rb +++ b/Library/Homebrew/cask.rb @@ -23,4 +23,3 @@ require "cask/staged" require "cask/topological_hash" require "cask/url" require "cask/utils" -require "cask/verify" diff --git a/Library/Homebrew/cask/audit.rb b/Library/Homebrew/cask/audit.rb index a9603a50e8..1cc322e507 100644 --- a/Library/Homebrew/cask/audit.rb +++ b/Library/Homebrew/cask/audit.rb @@ -255,20 +255,20 @@ module Cask add_error "you should use sha256 :no_check when version is :latest" end - def check_sha256_actually_256(sha256: cask.sha256, stanza: "sha256") - odebug "Verifying #{stanza} string is a legal SHA-256 digest" - return unless sha256.is_a?(String) - return if sha256.length == 64 && sha256[/^[0-9a-f]+$/i] + def check_sha256_actually_256 + odebug "Verifying sha256 string is a legal SHA-256 digest" + return unless cask.sha256.is_a?(Checksum) + return if cask.sha256.length == 64 && cask.sha256[/^[0-9a-f]+$/i] - add_error "#{stanza} string must be of 64 hexadecimal characters" + add_error "sha256 string must be of 64 hexadecimal characters" end - def check_sha256_invalid(sha256: cask.sha256, stanza: "sha256") - odebug "Verifying #{stanza} is not a known invalid value" + def check_sha256_invalid + odebug "Verifying sha256 is not a known invalid value" empty_sha256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" - return unless sha256 == empty_sha256 + return unless cask.sha256 == empty_sha256 - add_error "cannot use the sha256 for an empty string in #{stanza}: #{empty_sha256}" + add_error "cannot use the sha256 for an empty string: #{empty_sha256}" end def check_latest_with_appcast @@ -428,8 +428,7 @@ module Cask return unless download && cask.url odebug "Auditing download" - downloaded_path = download.perform - Verify.all(cask, downloaded_path) + download.fetch rescue => e add_error "download not possible: #{e}" end diff --git a/Library/Homebrew/cask/cmd/fetch.rb b/Library/Homebrew/cask/cmd/fetch.rb index 7add6ae1dc..855efa7f0f 100644 --- a/Library/Homebrew/cask/cmd/fetch.rb +++ b/Library/Homebrew/cask/cmd/fetch.rb @@ -32,7 +32,6 @@ module Cask require "cask/installer" options = { - force: args.force?, quarantine: args.quarantine?, }.compact @@ -41,8 +40,9 @@ module Cask casks.each do |cask| puts Installer.caveats(cask) ohai "Downloading external files for Cask #{cask}" - downloaded_path = Download.new(cask, **options).perform - Verify.all(cask, downloaded_path) + download = Download.new(cask, **options) + download.clear_cache if args.force? + downloaded_path = download.fetch ohai "Success! Downloaded to -> #{downloaded_path}" end end diff --git a/Library/Homebrew/cask/download.rb b/Library/Homebrew/cask/download.rb index 12e8a575ff..33a643aae3 100644 --- a/Library/Homebrew/cask/download.rb +++ b/Library/Homebrew/cask/download.rb @@ -4,25 +4,32 @@ require "fileutils" require "cask/cache" require "cask/quarantine" -require "cask/verify" module Cask # A download corresponding to a {Cask}. # # @api private class Download + include Context + attr_reader :cask - def initialize(cask, force: false, quarantine: nil) + def initialize(cask, quarantine: nil) @cask = cask - @force = force @quarantine = quarantine end - def perform - clear_cache - fetch - quarantine + def fetch(verify_download_integrity: true) + downloaded_path = begin + downloader.fetch + downloader.cached_location + rescue => e + error = CaskError.new("Download failed on Cask '#{cask}' with message: #{e}") + error.set_backtrace e.backtrace + raise error + end + quarantine(downloaded_path) + self.verify_download_integrity(downloaded_path) if verify_download_integrity downloaded_path end @@ -33,32 +40,44 @@ module Cask end end + def clear_cache + downloader.clear_cache + end + + def cached_download + downloader.cached_location + end + + def verify_download_integrity(fn) + if @cask.sha256 == :no_check + opoo "No checksum defined for Cask '#{@cask}', skipping verification." + return + end + + ohai "Verifying checksum for Cask '#{@cask}'." if verbose? + + expected = @cask.sha256 + actual = fn.sha256 + + begin + fn.verify_checksum(expected) + rescue ChecksumMissingError + raise CaskSha256MissingError.new(@cask.token, expected, actual) + rescue ChecksumMismatchError + raise CaskSha256MismatchError.new(@cask.token, expected, actual, fn) + end + end + private - attr_reader :force - attr_accessor :downloaded_path - - def clear_cache - downloader.clear_cache if force - end - - def fetch - downloader.fetch - @downloaded_path = downloader.cached_location - rescue => e - error = CaskError.new("Download failed on Cask '#{cask}' with message: #{e}") - error.set_backtrace e.backtrace - raise error - end - - def quarantine + def quarantine(path) return if @quarantine.nil? return unless Quarantine.available? if @quarantine - Quarantine.cask!(cask: @cask, download_path: @downloaded_path) + Quarantine.cask!(cask: @cask, download_path: path) else - Quarantine.release!(download_path: @downloaded_path) + Quarantine.release!(download_path: path) end end end diff --git a/Library/Homebrew/cask/dsl.rb b/Library/Homebrew/cask/dsl.rb index 149fedb7de..b9f0ca2064 100644 --- a/Library/Homebrew/cask/dsl.rb +++ b/Library/Homebrew/cask/dsl.rb @@ -205,11 +205,14 @@ module Cask def sha256(arg = nil) set_unique_stanza(:sha256, arg.nil?) do - if !arg.is_a?(String) && arg != :no_check + case arg + when :no_check + arg + when String + Checksum.new(:sha256, arg) + else raise CaskInvalidError.new(cask, "invalid 'sha256' value: '#{arg.inspect}'") end - - arg end end diff --git a/Library/Homebrew/cask/installer.rb b/Library/Homebrew/cask/installer.rb index 481307d800..6da1fa5ce8 100644 --- a/Library/Homebrew/cask/installer.rb +++ b/Library/Homebrew/cask/installer.rb @@ -8,7 +8,6 @@ require "cask/topological_hash" require "cask/config" require "cask/download" require "cask/staged" -require "cask/verify" require "cask/quarantine" require "cgi" @@ -68,7 +67,6 @@ module Cask satisfy_dependencies download - verify end def stage @@ -156,7 +154,7 @@ module Cask return @downloaded_path if @downloaded_path odebug "Downloading" - @downloaded_path = Download.new(@cask, force: false, quarantine: quarantine?).perform + @downloaded_path = Download.new(@cask, quarantine: quarantine?).fetch odebug "Downloaded to -> #{@downloaded_path}" @downloaded_path end @@ -168,10 +166,6 @@ module Cask raise CaskNoShasumError, @cask.token end - def verify - Verify.all(@cask, @downloaded_path) - end - def primary_container @primary_container ||= begin download diff --git a/Library/Homebrew/cask/verify.rb b/Library/Homebrew/cask/verify.rb deleted file mode 100644 index 65f9998dee..0000000000 --- a/Library/Homebrew/cask/verify.rb +++ /dev/null @@ -1,30 +0,0 @@ -# typed: false -# frozen_string_literal: true - -module Cask - # Helper module for verifying a cask's checksum. - # - # @api private - module Verify - module_function - - def all(cask, downloaded_path) - if cask.sha256 == :no_check - ohai "No SHA-256 checksum defined for Cask '#{cask}', skipping verification." - return - end - - ohai "Verifying SHA-256 checksum for Cask '#{cask}'." - - expected = cask.sha256 - computed = downloaded_path.sha256 - - raise CaskSha256MissingError.new(cask.token, expected, computed) if expected.nil? || expected.empty? - - return if expected == computed - - ohai "Note: Running `brew update` may fix SHA-256 checksum errors." - raise CaskSha256MismatchError.new(cask.token, expected, computed, downloaded_path) - end - end -end diff --git a/Library/Homebrew/checksum.rb b/Library/Homebrew/checksum.rb index 7a3219513d..a0489972b9 100644 --- a/Library/Homebrew/checksum.rb +++ b/Library/Homebrew/checksum.rb @@ -13,12 +13,19 @@ class Checksum def initialize(hash_type, hexdigest) @hash_type = hash_type - @hexdigest = hexdigest + @hexdigest = hexdigest.downcase end - delegate [:empty?, :to_s] => :@hexdigest + delegate [:empty?, :to_s, :length, :[]] => :@hexdigest def ==(other) - hash_type == other&.hash_type && hexdigest == other.hexdigest + case other + when String + to_s == other.downcase + when Checksum + hash_type == other.hash_type && hexdigest == other.hexdigest + else + false + end end end diff --git a/Library/Homebrew/cli/args.rb b/Library/Homebrew/cli/args.rb index b12f32712b..c9bdd72ccf 100644 --- a/Library/Homebrew/cli/args.rb +++ b/Library/Homebrew/cli/args.rb @@ -113,7 +113,7 @@ module Homebrew def build_from_source_formulae if build_from_source? || build_bottle? - named.to_formulae.map(&:full_name) + named.to_formulae_and_casks.select { |f| f.is_a?(Formula) }.map(&:full_name) else [] end diff --git a/Library/Homebrew/cmd/fetch.rb b/Library/Homebrew/cmd/fetch.rb index ac03b5df07..cb39cc3680 100644 --- a/Library/Homebrew/cmd/fetch.rb +++ b/Library/Homebrew/cmd/fetch.rb @@ -4,6 +4,7 @@ require "formula" require "fetch" require "cli/parser" +require "cask/download" module Homebrew extend T::Sig @@ -18,8 +19,8 @@ module Homebrew usage_banner <<~EOS `fetch` [] - Download a bottle (if available) or source packages for . - For tarballs, also print SHA-256 checksums. + Download a bottle (if available) or source packages for e + and binaries for s. For files, also print SHA-256 checksums. EOS switch "--HEAD", description: "Fetch HEAD version instead of stable version." @@ -42,58 +43,98 @@ module Homebrew switch "--force-bottle", description: "Download a bottle if it exists for the current or newest version of macOS, "\ "even if it would not be used during installation." + switch "--[no-]quarantine", + description: "Disable/enable quarantining of downloads (default: enabled).", + env: :cask_opts_quarantine + + switch "--formula", "--formulae", + description: "Treat all named arguments as formulae." + switch "--cask", "--casks", + description: "Treat all named arguments as casks." + conflicts "--formula", "--cask" conflicts "--devel", "--HEAD" conflicts "--build-from-source", "--build-bottle", "--force-bottle" - min_named :formula + conflicts "--cask", "--HEAD" + conflicts "--cask", "--devel" + conflicts "--cask", "--deps" + conflicts "--cask", "-s" + conflicts "--cask", "--build-bottle" + conflicts "--cask", "--force-bottle" + + min_named :formula_or_cask end end def fetch args = fetch_args.parse - if args.deps? - bucket = [] - args.named.to_formulae.each do |f| - bucket << f - bucket.concat f.recursive_dependencies.map(&:to_formula) - end - bucket.uniq! - else - bucket = args.named.to_formulae - end + only = :formula if args.formula? && !args.cask? + only = :cask if args.cask? && !args.formula? - puts "Fetching: #{bucket * ", "}" if bucket.size > 1 - bucket.each do |f| - f.print_tap_action verb: "Fetching" + bucket = if args.deps? + args.named.to_formulae_and_casks.flat_map do |formula_or_cask| + case formula_or_cask + when Formula + f = formula_or_cask - fetched_bottle = false - if fetch_bottle?(f, args: args) - begin - fetch_formula(f.bottle, args: args) - rescue Interrupt - raise - rescue => e - raise if Homebrew::EnvConfig.developer? - - fetched_bottle = false - onoe e.message - opoo "Bottle fetch failed: fetching the source." + [f, *f.recursive_dependencies.map(&:to_formula)] else - fetched_bottle = true + formula_or_cask end end + else + args.named.to_formulae_and_casks(only: only) + end.uniq - next if fetched_bottle + puts "Fetching: #{bucket * ", "}" if bucket.size > 1 + bucket.each do |formula_or_cask| + case formula_or_cask + when Formula + f = formula_or_cask - fetch_formula(f, args: args) + f.print_tap_action verb: "Fetching" - f.resources.each do |r| - fetch_resource(r, args: args) - r.patches.each { |p| fetch_patch(p, args: args) if p.external? } + fetched_bottle = false + if fetch_bottle?(f, args: args) + begin + fetch_formula(f.bottle, args: args) + rescue Interrupt + raise + rescue => e + raise if Homebrew::EnvConfig.developer? + + fetched_bottle = false + onoe e.message + opoo "Bottle fetch failed: fetching the source." + else + fetched_bottle = true + end + end + + next if fetched_bottle + + fetch_formula(f, args: args) + + f.resources.each do |r| + fetch_resource(r, args: args) + r.patches.each { |p| fetch_patch(p, args: args) if p.external? } + end + + f.patchlist.each { |p| fetch_patch(p, args: args) if p.external? } + else + cask = formula_or_cask + + options = { + force: args.force?, + quarantine: args.quarantine?, + }.compact + + options[:quarantine] = true if options[:quarantine].nil? + + download = Cask::Download.new(cask, **options) + fetch_cask(download, args: args) end - - f.patchlist.each { |p| fetch_patch(p, args: args) if p.external? } end end @@ -112,6 +153,13 @@ module Homebrew opoo "Formula reports different #{e.hash_type}: #{e.expected}" end + def fetch_cask(cask_download, args:) + fetch_fetchable cask_download, args: args + rescue ChecksumMismatchError => e + retry if retry_fetch?(cask_download, args: args) + opoo "Cask reports different #{e.hash_type}: #{e.expected}" + end + def fetch_patch(p, args:) fetch_fetchable p, args: args rescue ChecksumMismatchError => e diff --git a/Library/Homebrew/test/cask/audit_spec.rb b/Library/Homebrew/test/cask/audit_spec.rb index 497780f470..285c6ec3cc 100644 --- a/Library/Homebrew/test/cask/audit_spec.rb +++ b/Library/Homebrew/test/cask/audit_spec.rb @@ -808,7 +808,6 @@ describe Cask::Audit, :cask do let(:cask_token) { "with-binary" } let(:cask) { Cask::CaskLoader.load(cask_token) } let(:download_double) { instance_double(Cask::Download) } - let(:verify) { class_double(Cask::Verify).as_stubbed_const } let(:message) { "Download Failed" } before do @@ -817,19 +816,12 @@ describe Cask::Audit, :cask do end it "when download and verification succeed it does not fail" do - expect(download_double).to receive(:perform) - expect(verify).to receive(:all) + expect(download_double).to receive(:fetch) expect(subject).to pass end it "when download fails it fails" do - expect(download_double).to receive(:perform).and_raise(StandardError.new(message)) - expect(subject).to fail_with(/#{message}/) - end - - it "when verification fails it fails" do - expect(download_double).to receive(:perform) - expect(verify).to receive(:all).and_raise(StandardError.new(message)) + expect(download_double).to receive(:fetch).and_raise(StandardError.new(message)) expect(subject).to fail_with(/#{message}/) end end diff --git a/Library/Homebrew/test/cask/cmd/fetch_spec.rb b/Library/Homebrew/test/cask/cmd/fetch_spec.rb index bc68dc9ec0..e3d12e9b83 100644 --- a/Library/Homebrew/test/cask/cmd/fetch_spec.rb +++ b/Library/Homebrew/test/cask/cmd/fetch_spec.rb @@ -36,7 +36,7 @@ describe Cask::Cmd::Fetch, :cask do end it "prevents double fetch (without nuking existing installation)" do - cached_location = Cask::Download.new(local_transmission).perform + cached_location = Cask::Download.new(local_transmission).fetch old_ctime = File.stat(cached_location).ctime @@ -47,7 +47,7 @@ describe Cask::Cmd::Fetch, :cask do end it "allows double fetch with --force" do - cached_location = Cask::Download.new(local_transmission).perform + cached_location = Cask::Download.new(local_transmission).fetch old_ctime = File.stat(cached_location).ctime sleep(1) diff --git a/Library/Homebrew/test/cask/cmd/install_spec.rb b/Library/Homebrew/test/cask/cmd/install_spec.rb index 7c051d9d1f..adb7b6da2b 100644 --- a/Library/Homebrew/test/cask/cmd/install_spec.rb +++ b/Library/Homebrew/test/cask/cmd/install_spec.rb @@ -11,7 +11,6 @@ describe Cask::Cmd::Install, :cask do it "displays the installation progress" do output = Regexp.new <<~EOS ==> Downloading file:.*caffeine.zip - ==> Verifying SHA-256 checksum for Cask 'local-caffeine'. ==> Installing Cask local-caffeine ==> Moving App 'Caffeine.app' to '.*Caffeine.app'. .*local-caffeine was successfully installed! diff --git a/Library/Homebrew/test/cask/cmd/reinstall_spec.rb b/Library/Homebrew/test/cask/cmd/reinstall_spec.rb index 8b93c92fc3..4cf73637a1 100644 --- a/Library/Homebrew/test/cask/cmd/reinstall_spec.rb +++ b/Library/Homebrew/test/cask/cmd/reinstall_spec.rb @@ -14,7 +14,6 @@ describe Cask::Cmd::Reinstall, :cask do output = Regexp.new <<~EOS ==> Downloading file:.*caffeine.zip Already downloaded: .*--caffeine.zip - ==> Verifying SHA-256 checksum for Cask 'local-caffeine'. ==> Uninstalling Cask local-caffeine ==> Backing App 'Caffeine.app' up to '.*Caffeine.app'. ==> Removing App '.*Caffeine.app'. diff --git a/Library/Homebrew/test/cask/verify_spec.rb b/Library/Homebrew/test/cask/download_spec.rb similarity index 72% rename from Library/Homebrew/test/cask/verify_spec.rb rename to Library/Homebrew/test/cask/download_spec.rb index 8acc50baef..65ba2b5ce1 100644 --- a/Library/Homebrew/test/cask/verify_spec.rb +++ b/Library/Homebrew/test/cask/download_spec.rb @@ -2,26 +2,30 @@ # frozen_string_literal: true module Cask - describe Verify, :cask do - describe "::all" do - subject(:verification) { described_class.all(cask, downloaded_path) } + describe Download, :cask do + describe "#verify_download_integrity" do + subject(:verification) { described_class.new(cask).verify_download_integrity(downloaded_path) } let(:cask) { instance_double(Cask, token: "cask", sha256: expected_sha256) } let(:cafebabe) { "cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe" } let(:deadbeef) { "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef" } let(:computed_sha256) { cafebabe } - let(:downloaded_path) { instance_double(Pathname, sha256: computed_sha256) } + let(:downloaded_path) { Pathname.new("cask.zip") } + + before do + allow(downloaded_path).to receive(:sha256).and_return(computed_sha256) + end context "when the expected checksum is :no_check" do let(:expected_sha256) { :no_check } it "skips the check" do - expect { verification }.to output(/skipping verification/).to_stdout + expect { verification }.to output(/skipping verification/).to_stderr end end context "when expected and computed checksums match" do - let(:expected_sha256) { cafebabe } + let(:expected_sha256) { Checksum.new(:sha256, cafebabe) } it "does not raise an error" do expect { verification }.not_to raise_error @@ -37,7 +41,7 @@ module Cask end context "when the expected checksum is empty" do - let(:expected_sha256) { "" } + let(:expected_sha256) { Checksum.new(:sha256, "") } it "raises an error" do expect { verification }.to raise_error(CaskSha256MissingError, /sha256 "#{computed_sha256}"/) @@ -45,7 +49,7 @@ module Cask end context "when expected and computed checksums do not match" do - let(:expected_sha256) { deadbeef } + let(:expected_sha256) { Checksum.new(:sha256, deadbeef) } it "raises an error" do expect { verification }.to raise_error CaskSha256MismatchError diff --git a/Library/Homebrew/test/cask/installer_spec.rb b/Library/Homebrew/test/cask/installer_spec.rb index b15bf205cd..688312e91c 100644 --- a/Library/Homebrew/test/cask/installer_spec.rb +++ b/Library/Homebrew/test/cask/installer_spec.rb @@ -116,7 +116,6 @@ describe Cask::Installer, :cask do }.to output( <<~EOS, ==> Downloading file://#{HOMEBREW_LIBRARY_PATH}/test/support/fixtures/cask/caffeine.zip - ==> Verifying SHA-256 checksum for Cask 'with-installer-manual'. ==> Installing Cask with-installer-manual To complete the installation of Cask with-installer-manual, you must also run the installer at: diff --git a/Library/Homebrew/test/cask/quarantine_spec.rb b/Library/Homebrew/test/cask/quarantine_spec.rb index 779c995eb3..426d7321cf 100644 --- a/Library/Homebrew/test/cask/quarantine_spec.rb +++ b/Library/Homebrew/test/cask/quarantine_spec.rb @@ -31,7 +31,7 @@ describe Cask::Quarantine, :cask do it "quarantines Cask fetches" do Cask::Cmd::Fetch.run("local-transmission") local_transmission = Cask::CaskLoader.load(cask_path("local-transmission")) - cached_location = Cask::Download.new(local_transmission).perform + cached_location = Cask::Download.new(local_transmission).fetch expect(cached_location).to be_quarantined end @@ -40,7 +40,7 @@ describe Cask::Quarantine, :cask do Cask::Cmd::Audit.run("local-transmission", "--download") local_transmission = Cask::CaskLoader.load(cask_path("local-transmission")) - cached_location = Cask::Download.new(local_transmission).perform + cached_location = Cask::Download.new(local_transmission).fetch expect(cached_location).to be_quarantined end @@ -142,7 +142,7 @@ describe Cask::Quarantine, :cask do it "does not quarantine Cask fetches" do Cask::Cmd::Fetch.run("local-transmission", "--no-quarantine") local_transmission = Cask::CaskLoader.load(cask_path("local-transmission")) - cached_location = Cask::Download.new(local_transmission).perform + cached_location = Cask::Download.new(local_transmission).fetch expect(cached_location).not_to be_quarantined end @@ -151,7 +151,7 @@ describe Cask::Quarantine, :cask do Cask::Cmd::Audit.run("local-transmission", "--download", "--no-quarantine") local_transmission = Cask::CaskLoader.load(cask_path("local-transmission")) - cached_location = Cask::Download.new(local_transmission).perform + cached_location = Cask::Download.new(local_transmission).fetch expect(cached_location).not_to be_quarantined end diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-manpage-no-section.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-manpage-no-section.rb index 32d5ee74d0..ee9743e61d 100644 --- a/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-manpage-no-section.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/invalid/invalid-manpage-no-section.rb @@ -1,6 +1,6 @@ cask "invalid-manpage-no-section" do version "1.2.3" - sha256 "67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94" + sha256 "68b7e71a2ca7585b004f52652749589941e3029ff0884e8aa3b099594e0282c0" url "file://#{TEST_FIXTURE_DIR}/cask/AppWithManpage.zip" homepage "https://brew.sh/with-generic-artifact" diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/with-autodetected-manpage-section.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-autodetected-manpage-section.rb index b330074da7..b05174b380 100644 --- a/Library/Homebrew/test/support/fixtures/cask/Casks/with-autodetected-manpage-section.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-autodetected-manpage-section.rb @@ -1,6 +1,6 @@ cask "with-autodetected-manpage-section" do version "1.2.3" - sha256 "67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94" + sha256 "68b7e71a2ca7585b004f52652749589941e3029ff0884e8aa3b099594e0282c0" url "file://#{TEST_FIXTURE_DIR}/cask/AppWithManpage.zip" homepage "https://brew.sh/with-autodetected-manpage-section" diff --git a/Library/Homebrew/test/support/fixtures/cask/Casks/with-non-executable-binary.rb b/Library/Homebrew/test/support/fixtures/cask/Casks/with-non-executable-binary.rb index 0ed70fff27..2e4886462a 100644 --- a/Library/Homebrew/test/support/fixtures/cask/Casks/with-non-executable-binary.rb +++ b/Library/Homebrew/test/support/fixtures/cask/Casks/with-non-executable-binary.rb @@ -1,6 +1,6 @@ cask "with-non-executable-binary" do version "1.2.3" - sha256 "d5b2dfbef7ea28c25f7a77cd7fa14d013d82b626db1d82e00e25822464ba19e2" + sha256 "306c6ca7407560340797866e077e053627ad409277d1b9da58106fce4cf717cb" url "file://#{TEST_FIXTURE_DIR}/cask/naked_non_executable" homepage "https://brew.sh/with-binary" diff --git a/docs/Manpage.md b/docs/Manpage.md index 9f5b14a52a..b8de5ae68a 100644 --- a/docs/Manpage.md +++ b/docs/Manpage.md @@ -199,8 +199,8 @@ an issue; just ignore this. ### `fetch` [*`options`*] *`formula`* -Download a bottle (if available) or source packages for *`formula`*. -For tarballs, also print SHA-256 checksums. +Download a bottle (if available) or source packages for *`formula`*e +and binaries for *`cask`*s. For files, also print SHA-256 checksums. * `--HEAD`: Fetch HEAD version instead of stable version. @@ -220,6 +220,12 @@ For tarballs, also print SHA-256 checksums. Download source packages (for eventual bottling) rather than a bottle. * `--force-bottle`: Download a bottle if it exists for the current or newest version of macOS, even if it would not be used during installation. +* `--[no-]quarantine`: + Disable/enable quarantining of downloads (default: enabled). +* `--formula`: + Treat all named arguments as formulae. +* `--cask`: + Treat all named arguments as casks. ### `gist-logs` [*`options`*] *`formula`* diff --git a/manpages/brew.1 b/manpages/brew.1 index d0902e08cb..478c11d8c5 100644 --- a/manpages/brew.1 +++ b/manpages/brew.1 @@ -254,7 +254,7 @@ List all audit methods, which can be run individually if provided as arguments\. Enable debugging and profiling of audit methods\. . .SS "\fBfetch\fR [\fIoptions\fR] \fIformula\fR" -Download a bottle (if available) or source packages for \fIformula\fR\. For tarballs, also print SHA\-256 checksums\. +Download a bottle (if available) or source packages for \fIformula\fRe and binaries for \fIcask\fRs\. For files, also print SHA\-256 checksums\. . .TP \fB\-\-HEAD\fR @@ -292,6 +292,18 @@ Download source packages (for eventual bottling) rather than a bottle\. \fB\-\-force\-bottle\fR Download a bottle if it exists for the current or newest version of macOS, even if it would not be used during installation\. . +.TP +\fB\-\-[no\-]quarantine\fR +Disable/enable quarantining of downloads (default: enabled)\. +. +.TP +\fB\-\-formula\fR +Treat all named arguments as formulae\. +. +.TP +\fB\-\-cask\fR +Treat all named arguments as casks\. +. .SS "\fBgist\-logs\fR [\fIoptions\fR] \fIformula\fR" Upload logs for a failed build of \fIformula\fR to a new Gist\. Presents an error message if no logs are found\. .