diff options
29 files changed, 316 insertions, 49 deletions
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 287e95b03..cfa55d26e 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,10 +1,10 @@ **Please note we will close your issue without comment if you delete, do not read or do not fill out the issue checklist below and provide ALL the requested information. If you repeatedly fail to use the issue template, we will block you from ever submitting issues to Homebrew again.** -# Please always follow these steps: -- [ ] Confirmed this is a problem with running a `brew` command and not `brew install`ing or the post-install behaviour of one or more formulae? If it's a formulae-specific problem please file this issue at the relevant tap e.g. for Homebrew/homebrew-core https://github.com/Homebrew/homebrew-core/issues/new -- [ ] Ran `brew update` and retried your prior step? -- [ ] Ran `brew doctor`, fixed all issues and retried your prior step? -- [ ] Ran `brew config` and `brew doctor` and included their output with your issue? +- [ ] are reporting a bug others will be able to reproduce and not asking a question. If you're not sure or want to ask a question do so on our Discourse: https://discourse.brew.sh +- [ ] ran a `brew` command and reproduced the problem with multiple formulae? If it's a problem with a single, official formula (not cask) please file this issue at Homebrew/homebrew-core: https://github.com/Homebrew/homebrew-core/issues/new. If it's a `brew cask` problem please file this issue at https://github.com/caskroom/homebrew-cask/issues/new. If it's a tap (e.g. Homebrew/homebrew-php) problem please file this issue at the tap. +- [ ] ran `brew update` and can still reproduce the problem? +- [ ] ran `brew doctor`, fixed all issues and can still reproduce the problem? +- [ ] ran `brew config` and `brew doctor` and included their output with your issue? To help us debug your issue please explain: - What you were trying to do (and why) @@ -16,7 +16,7 @@ To help us debug your issue please explain: Please replace this section with: - a detailed description of your proposed feature - the motivation for the feature -- how the feature would be relevant to at least 90% of Homebrew users +- how the feature would be relevant to at least 90% of Homebrew users (if it's not: do not open a feature request) - what alternatives to the feature you have considered -We will close this issue or ask you to create a pull-request if it's something we're not actively planning to work on. +We will close this issue or ask you to create a pull-request if it's something the maintainers are not actively planning to work on. diff --git a/Library/Homebrew/cask/lib/hbc/cli/doctor.rb b/Library/Homebrew/cask/lib/hbc/cli/doctor.rb index 5aef2c420..32b927218 100644 --- a/Library/Homebrew/cask/lib/hbc/cli/doctor.rb +++ b/Library/Homebrew/cask/lib/hbc/cli/doctor.rb @@ -1,25 +1,116 @@ require "system_config" +require "hbc/checkable" module Hbc class CLI class Doctor < AbstractCommand + include Checkable + def initialize(*) super return if args.empty? raise ArgumentError, "#{self.class.command_name} does not take arguments." end + def success? + !(errors? || warnings?) + end + + def summary_header + "Cask's Doctor Checkup" + end + def run + check_software_versions + check_install_location + check_staging_location + check_cached_downloads + check_taps + check_load_path + check_environment_variables + + puts summary unless success? + raise CaskError, "There are some problems with your setup." unless success? + end + + def check_software_versions ohai "Homebrew-Cask Version", Hbc.full_version ohai "macOS", MacOS.full_version ohai "SIP", self.class.check_sip ohai "Java", SystemConfig.describe_java - ohai "Homebrew-Cask Install Location", self.class.render_install_location - ohai "Homebrew-Cask Staging Location", self.class.render_staging_location(Hbc.caskroom) - ohai "Homebrew-Cask Cached Downloads", self.class.render_cached_downloads + end + + # This could be done by calling into Homebrew, but the situation + # where "doctor" is needed is precisely the situation where such + # things are less dependable. + def check_install_location + ohai "Homebrew-Cask Install Location" + + locations = Dir.glob(HOMEBREW_CELLAR.join("brew-cask", "*")).reverse + if locations.empty? + puts self.class.none_string + else + locations.collect do |l| + add_error "Legacy install at #{l}. Run \"brew uninstall --force brew-cask\"." + puts l + end + end + end + + def check_staging_location + ohai "Homebrew-Cask Staging Location" + + path = Pathname.new(user_tilde(Hbc.caskroom.to_s)) + + if !path.exist? + add_error "The staging path #{path} does not exist." + elsif !path.writable? + add_error "The staging path #{path} is not writable by the current user." + end + + puts path + end + + def check_cached_downloads + ohai "Homebrew-Cask Cached Downloads" + + cleanup = CLI::Cleanup.new + count = cleanup.cache_files.count + size = cleanup.disk_cleanup_size + msg = user_tilde(Hbc.cache.to_s) + msg << " (#{number_readable(count)} files, #{disk_usage_readable(size)})" unless count.zero? + puts msg + end + + def check_taps ohai "Homebrew-Cask Taps:" - puts self.class.render_taps(Hbc.default_tap, *self.class.alt_taps) - ohai "Contents of $LOAD_PATH", self.class.render_load_path($LOAD_PATH) + + default_tap = [Hbc.default_tap] + + alt_taps = Tap.select { |t| t.cask_dir.exist? && t != Hbc.default_tap } + + (default_tap + alt_taps).each do |tap| + if tap.path.nil? || tap.path.to_s.empty? + puts none_string + else + puts "#{tap.path} (#{cask_count_for_tap(tap)})" + end + end + end + + def check_load_path + ohai "Contents of $LOAD_PATH" + paths = $LOAD_PATH.map(&method(:user_tilde)) + + if paths.empty? + puts none_string + add_error "$LOAD_PATH is empty" + else + puts paths + end + end + + def check_environment_variables ohai "Environment Variables" environment_variables = %w[ @@ -35,7 +126,25 @@ module Hbc SHELL ] - (self.class.locale_variables + environment_variables).sort.each(&self.class.method(:render_env_var)) + locale_variables = ENV.keys.grep(/^(?:LC_\S+|LANG|LANGUAGE)\Z/).sort + + (locale_variables + environment_variables).sort.each(&method(:render_env_var)) + end + + def user_tilde(path) + self.class.user_tilde(path) + end + + def cask_count_for_tap(tap) + self.class.cask_count_for_tap(tap) + end + + def none_string + self.class.none_string + end + + def render_env_var(var) + self.class.render_env_var(var) end def self.check_sip @@ -71,7 +180,8 @@ module Hbc def self.cask_count_for_tap(tap) Formatter.pluralize(tap.cask_files.count, "cask") rescue StandardError - "0 #{error_string "error reading #{tap.path}"}" + add_error "Unable to read from Tap: #{tap.path}" + "0" end def self.render_taps(*taps) diff --git a/Library/Homebrew/cask/lib/hbc/installer.rb b/Library/Homebrew/cask/lib/hbc/installer.rb index 8520f154d..a2833e8f9 100644 --- a/Library/Homebrew/cask/lib/hbc/installer.rb +++ b/Library/Homebrew/cask/lib/hbc/installer.rb @@ -75,7 +75,7 @@ module Hbc fetch uninstall_existing_cask if @reinstall - oh1 "Installing Cask #{@cask}" + oh1 "Installing Cask #{Formatter.identifier(@cask)}" stage install_artifacts enable_accessibility_access @@ -348,7 +348,7 @@ module Hbc end def uninstall - oh1 "Uninstalling Cask #{@cask}" + oh1 "Uninstalling Cask #{Formatter.identifier(@cask)}" disable_accessibility_access uninstall_artifacts(clear: true) purge_versioned_files @@ -356,7 +356,7 @@ module Hbc end def start_upgrade - oh1 "Starting upgrade for Cask #{@cask}" + oh1 "Starting upgrade for Cask #{Formatter.identifier(@cask)}" disable_accessibility_access uninstall_artifacts diff --git a/Library/Homebrew/cmd/reinstall.rb b/Library/Homebrew/cmd/reinstall.rb index 53c923d91..7c62d8092 100644 --- a/Library/Homebrew/cmd/reinstall.rb +++ b/Library/Homebrew/cmd/reinstall.rb @@ -42,7 +42,7 @@ module Homebrew fi.link_keg ||= keg_was_linked if keg_had_linked_opt fi.prelude - oh1 "Reinstalling #{f.full_name} #{options.to_a.join " "}" + oh1 "Reinstalling #{Formatter.identifier(f.full_name)} #{options.to_a.join " "}" fi.install fi.finish diff --git a/Library/Homebrew/cmd/unpack.rb b/Library/Homebrew/cmd/unpack.rb index 51c2b59f0..aee4ea2eb 100644 --- a/Library/Homebrew/cmd/unpack.rb +++ b/Library/Homebrew/cmd/unpack.rb @@ -36,7 +36,7 @@ module Homebrew rm_rf stage_dir end - oh1 "Unpacking #{f.full_name} to: #{stage_dir}" + oh1 "Unpacking #{Formatter.identifier(f.full_name)} to: #{stage_dir}" ENV["VERBOSE"] = "1" # show messages about tar f.brew do diff --git a/Library/Homebrew/cmd/upgrade.rb b/Library/Homebrew/cmd/upgrade.rb index 401a02e67..debd5eea2 100644 --- a/Library/Homebrew/cmd/upgrade.rb +++ b/Library/Homebrew/cmd/upgrade.rb @@ -127,7 +127,7 @@ module Homebrew end fi.prelude - oh1 "Upgrading #{f.full_specified_name} #{fi.options.to_a.join " "}" + oh1 "Upgrading #{Formatter.identifier(f.full_specified_name)} #{fi.options.to_a.join " "}" # first we unlink the currently active keg for this formula otherwise it is # possible for the existing build to interfere with the build we are about to diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index 657487f3c..e3fb3a580 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -196,6 +196,8 @@ class FormulaAuditor @online = options[:online] # Accept precomputed style offense results, for efficiency @style_offenses = options[:style_offenses] + # Allow the actual official-ness of a formula to be overridden, for testing purposes + @official_tap = formula.tap&.official? || options[:official_tap] @problems = [] @text = FormulaText.new(formula.path) @specs = %w[stable devel head].map { |s| formula.send(s) }.compact @@ -302,7 +304,7 @@ class FormulaAuditor def audit_formula_name return unless @strict # skip for non-official taps - return unless formula.tap&.official? + return unless @official_tap name = formula.name @@ -716,7 +718,7 @@ class FormulaAuditor return unless @strict - if formula.tap&.official? && line.include?("env :std") + if @official_tap && line.include?("env :std") problem "`env :std` in official tap formulae is deprecated" end @@ -745,7 +747,7 @@ class FormulaAuditor def audit_reverse_migration # Only enforce for new formula being re-added to core and official taps return unless @strict - return unless formula.tap&.official? + return unless @official_tap return unless formula.tap.tap_migrations.key?(formula.name) problem <<~EOS @@ -766,6 +768,18 @@ class FormulaAuditor EOS end + def audit_url_is_not_binary + return unless @official_tap + + urls = @specs.map(&:url) + + urls.each do |url| + if url =~ /darwin/i && (url =~ /x86_64/i || url =~ /amd64/i) + problem "#{url} looks like a binary package, not a source archive. Official taps are source-only." + end + end + end + def quote_dep(dep) dep.is_a?(Symbol) ? dep.inspect : "'#{dep}'" end diff --git a/Library/Homebrew/diagnostic.rb b/Library/Homebrew/diagnostic.rb index 46750c24f..8cbf124e6 100644 --- a/Library/Homebrew/diagnostic.rb +++ b/Library/Homebrew/diagnostic.rb @@ -788,7 +788,7 @@ module Homebrew EOS end - return if ENV["CI"] || ENV["JENKINS_HOME"] + return if ENV["CI"] branch = coretap_path.git_branch return if branch.nil? || branch =~ /master/ diff --git a/Library/Homebrew/download_strategy.rb b/Library/Homebrew/download_strategy.rb index feb518057..e85661d76 100644 --- a/Library/Homebrew/download_strategy.rb +++ b/Library/Homebrew/download_strategy.rb @@ -303,7 +303,11 @@ class AbstractFileDownloadStrategy < AbstractDownloadStrategy # We can't use basename_without_params, because given a URL like # https://example.com/download.php?file=foo-1.0.tar.gz # the extension we want is ".tar.gz", not ".php". - Pathname.new(@url).extname[/[^?]+/] + Pathname.new(@url).ascend do |path| + ext = path.extname[/[^?]+/] + return ext if ext + end + nil end end diff --git a/Library/Homebrew/extend/pathname.rb b/Library/Homebrew/extend/pathname.rb index b4311f13f..baf47b276 100644 --- a/Library/Homebrew/extend/pathname.rb +++ b/Library/Homebrew/extend/pathname.rb @@ -436,11 +436,14 @@ class Pathname end # Writes an exec script that invokes a java jar - def write_jar_script(target_jar, script_name, java_opts = "") + def write_jar_script(target_jar, script_name, java_opts = "", java_version: nil) mkpath + java_home = if java_version + "JAVA_HOME=\"$(#{Language::Java.java_home_cmd(java_version)})\" " + end join(script_name).write <<~EOS #!/bin/bash - exec java #{java_opts} -jar #{target_jar} "$@" + #{java_home}exec java #{java_opts} -jar #{target_jar} "$@" EOS end diff --git a/Library/Homebrew/manpages/brew.1.md.erb b/Library/Homebrew/manpages/brew.1.md.erb index 508c90f2d..fbe6fca94 100644 --- a/Library/Homebrew/manpages/brew.1.md.erb +++ b/Library/Homebrew/manpages/brew.1.md.erb @@ -199,6 +199,9 @@ can take several different forms: If set, Homebrew will not auto-update before running `brew install`, `brew upgrade` or `brew tap`. + * `HOMEBREW_NO_COLOR`: + If set, Homebrew will not print text with color added. + * `HOMEBREW_NO_EMOJI`: If set, Homebrew will not print the `HOMEBREW_INSTALL_BADGE` on a successful build. diff --git a/Library/Homebrew/os/mac/linkage_checker.rb b/Library/Homebrew/os/mac/linkage_checker.rb index e1709d1b4..cf6c12f22 100644 --- a/Library/Homebrew/os/mac/linkage_checker.rb +++ b/Library/Homebrew/os/mac/linkage_checker.rb @@ -14,6 +14,7 @@ class LinkageChecker @system_dylibs = Set.new @broken_dylibs = Set.new @variable_dylibs = Set.new + @indirect_deps = [] @undeclared_deps = [] @reverse_links = Hash.new { |h, k| h[k] = Set.new } @unnecessary_deps = [] @@ -52,7 +53,7 @@ class LinkageChecker end end - @undeclared_deps, @unnecessary_deps = check_undeclared_deps if formula + @indirect_deps, @undeclared_deps, @unnecessary_deps = check_undeclared_deps if formula end def check_undeclared_deps @@ -62,13 +63,31 @@ class LinkageChecker formula.build.without?(dep) end declared_deps = formula.deps.reject { |dep| filter_out.call(dep) }.map(&:name) + recursive_deps = keg.to_formula.runtime_dependencies.map { |dep| dep.to_formula.full_name } declared_dep_names = declared_deps.map { |dep| dep.split("/").last } - undeclared_deps = @brewed_dylibs.keys.reject do |full_name| + indirect_deps = [] + undeclared_deps = [] + @brewed_dylibs.each_key do |full_name| name = full_name.split("/").last - next true if name == formula.name - declared_dep_names.include?(name) + next if name == formula.name + if recursive_deps.include?(name) + indirect_deps << full_name unless declared_dep_names.include?(name) + else + undeclared_deps << full_name + end + end + sort_by_formula_full_name!(indirect_deps) + sort_by_formula_full_name!(undeclared_deps) + unnecessary_deps = declared_dep_names.reject do |full_name| + name = full_name.split("/").last + next true if Formula[name].bin.directory? + @brewed_dylibs.keys.map { |x| x.split("/").last }.include?(name) end - undeclared_deps.sort do |a, b| + [indirect_deps, undeclared_deps, unnecessary_deps] + end + + def sort_by_formula_full_name!(arr) + arr.sort! do |a, b| if a.include?("/") && !b.include?("/") 1 elsif !a.include?("/") && b.include?("/") @@ -77,17 +96,12 @@ class LinkageChecker a <=> b end end - unnecessary_deps = declared_dep_names.reject do |full_name| - name = full_name.split("/").last - next true if Formula[name].bin.directory? - @brewed_dylibs.keys.map { |x| x.split("/").last }.include?(name) - end - [undeclared_deps, unnecessary_deps] end def display_normal_output display_items "System libraries", @system_dylibs display_items "Homebrew libraries", @brewed_dylibs + display_items "Indirect dependencies with linkage", @indirect_deps display_items "Variable-referenced libraries", @variable_dylibs display_items "Missing libraries", @broken_dylibs display_items "Undeclared dependencies with linkage", @undeclared_deps diff --git a/Library/Homebrew/requirements/xcode_requirement.rb b/Library/Homebrew/requirements/xcode_requirement.rb index 9396b0df7..6cb7d45d7 100644 --- a/Library/Homebrew/requirements/xcode_requirement.rb +++ b/Library/Homebrew/requirements/xcode_requirement.rb @@ -22,7 +22,7 @@ class XcodeRequirement < Requirement A full installation of Xcode.app#{version} is required to compile this software. Installing just the Command Line Tools is not sufficient. EOS - if Version.new(MacOS::Xcode.latest_version) < Version.new(@version) + if @version && Version.new(MacOS::Xcode.latest_version) < Version.new(@version) message + <<~EOS Xcode#{version} cannot be installed on macOS #{MacOS.version}. You must upgrade your version of macOS. diff --git a/Library/Homebrew/test/Gemfile b/Library/Homebrew/test/Gemfile index b6d1405ff..34ba794a8 100644 --- a/Library/Homebrew/test/Gemfile +++ b/Library/Homebrew/test/Gemfile @@ -5,6 +5,7 @@ require_relative "../constants" gem "parallel_tests" gem "rspec" gem "rspec-its", require: false +gem "rspec-retry", require: false gem "rspec-wait", require: false gem "rubocop", HOMEBREW_RUBOCOP_VERSION diff --git a/Library/Homebrew/test/Gemfile.lock b/Library/Homebrew/test/Gemfile.lock index 47f51e56b..a3f9c4c47 100644 --- a/Library/Homebrew/test/Gemfile.lock +++ b/Library/Homebrew/test/Gemfile.lock @@ -31,6 +31,8 @@ GEM rspec-mocks (3.6.0) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.6.0) + rspec-retry (0.5.6) + rspec-core (> 3.3, < 3.8) rspec-support (3.6.0) rspec-wait (0.0.9) rspec (>= 3, < 4) @@ -58,9 +60,10 @@ DEPENDENCIES parallel_tests rspec rspec-its + rspec-retry rspec-wait rubocop (= 0.52.1) simplecov BUNDLED WITH - 1.16.0 + 1.16.1 diff --git a/Library/Homebrew/test/cask/dsl_spec.rb b/Library/Homebrew/test/cask/dsl_spec.rb index d3bb46264..993c03bac 100644 --- a/Library/Homebrew/test/cask/dsl_spec.rb +++ b/Library/Homebrew/test/cask/dsl_spec.rb @@ -75,6 +75,7 @@ describe Hbc::DSL, :cask do it "may use deprecated DSL version hash syntax" do allow(ENV).to receive(:[]).with("HOMEBREW_DEVELOPER").and_return(nil) + allow(ENV).to receive(:[]).with("HOMEBREW_NO_COLOR").and_return(nil) expect(cask.token).to eq("with-dsl-version") expect(cask.url.to_s).to eq("http://example.com/TestCask.dmg") diff --git a/Library/Homebrew/test/cmd/search_spec.rb b/Library/Homebrew/test/cmd/search_spec.rb index 36ddde3e1..aec23ae4c 100644 --- a/Library/Homebrew/test/cmd/search_spec.rb +++ b/Library/Homebrew/test/cmd/search_spec.rb @@ -25,7 +25,7 @@ describe "brew search", :integration_test do .and be_a_success end - it "falls back to a GitHub tap search when no formula is found", :needs_network do + it "falls back to a GitHub tap search when no formula is found", :needs_network, retry: 3 do expect { brew "search", "caskroom/cask/firefox" } .to output(/firefox/).to_stdout .and output(/Searching/).to_stderr diff --git a/Library/Homebrew/test/cmd/services_spec.rb b/Library/Homebrew/test/cmd/services_spec.rb index 669e84e5f..fb40ce0b2 100644 --- a/Library/Homebrew/test/cmd/services_spec.rb +++ b/Library/Homebrew/test/cmd/services_spec.rb @@ -1,4 +1,4 @@ -describe "brew services", :integration_test, :needs_macos, :needs_network do +describe "brew services", :integration_test, :needs_macos, :needs_network, retry: 3 do it "allows controlling services" do setup_remote_tap "homebrew/services" diff --git a/Library/Homebrew/test/dev-cmd/audit_spec.rb b/Library/Homebrew/test/dev-cmd/audit_spec.rb index 2381ff1f5..38884222d 100644 --- a/Library/Homebrew/test/dev-cmd/audit_spec.rb +++ b/Library/Homebrew/test/dev-cmd/audit_spec.rb @@ -522,4 +522,82 @@ describe FormulaAuditor do end end end + + describe "#audit_url_is_not_binary" do + specify "it detects a url containing darwin and x86_64" do + fa = formula_auditor "foo", <<~EOS, official_tap: true + class Foo < Formula + url "https://example.com/example-darwin.x86_64.tar.gz" + end + EOS + + fa.audit_url_is_not_binary + + expect(fa.problems.first) + .to match("looks like a binary package, not a source archive. Official taps are source-only.") + end + + specify "it detects a url containing darwin and amd64" do + fa = formula_auditor "foo", <<~EOS, official_tap: true + class Foo < Formula + url "https://example.com/example-darwin.amd64.tar.gz" + end + EOS + + fa.audit_url_is_not_binary + + expect(fa.problems.first) + .to match("looks like a binary package, not a source archive. Official taps are source-only.") + end + + specify "it works on the devel spec" do + fa = formula_auditor "foo", <<~EOS, official_tap: true + class Foo < Formula + url "https://example.com/valid-1.0.tar.gz" + + devel do + url "https://example.com/example-darwin.x86_64.tar.gz" + end + end + EOS + + fa.audit_url_is_not_binary + + expect(fa.problems.first) + .to match("looks like a binary package, not a source archive. Official taps are source-only.") + end + + specify "it works on the head spec" do + fa = formula_auditor "foo", <<~EOS, official_tap: true + class Foo < Formula + url "https://example.com/valid-1.0.tar.gz" + + head do + url "https://example.com/example-darwin.x86_64.tar.gz" + end + end + EOS + + fa.audit_url_is_not_binary + + expect(fa.problems.first) + .to match("looks like a binary package, not a source archive. Official taps are source-only.") + end + + specify "it ignores resource urls" do + fa = formula_auditor "foo", <<~EOS, official_tap: true + class Foo < Formula + url "https://example.com/valid-1.0.tar.gz" + + resource "binary_res" do + url "https://example.com/example-darwin.x86_64.tar.gz" + end + end + EOS + + fa.audit_url_is_not_binary + + expect(fa.problems).to eq([]) + end + end end diff --git a/Library/Homebrew/test/dev-cmd/pull_spec.rb b/Library/Homebrew/test/dev-cmd/pull_spec.rb index 984ac0843..cc66df783 100644 --- a/Library/Homebrew/test/dev-cmd/pull_spec.rb +++ b/Library/Homebrew/test/dev-cmd/pull_spec.rb @@ -6,7 +6,7 @@ describe "brew pull", :integration_test do .and be_a_failure end - it "fetches a patch from a GitHub commit or pull request and applies it", :needs_network do + it "fetches a patch from a GitHub commit or pull request and applies it", :needs_network, retry: 3 do CoreTap.instance.path.cd do system "git", "init" system "git", "checkout", "-b", "new-branch" diff --git a/Library/Homebrew/test/download_strategies_spec.rb b/Library/Homebrew/test/download_strategies_spec.rb index 06d6fa855..7ad070fc4 100644 --- a/Library/Homebrew/test/download_strategies_spec.rb +++ b/Library/Homebrew/test/download_strategies_spec.rb @@ -209,6 +209,19 @@ describe CurlDownloadStrategy do it "parses the opts and sets the corresponding args" do expect(subject.send(:_curl_opts)).to eq(["--user", "download:123456"]) end + + describe "#tarball_path" do + subject { described_class.new(name, resource).tarball_path } + + context "when URL ends with file" do + it { is_expected.to eq(HOMEBREW_CACHE/"foo-.tar.gz") } + end + + context "when URL file is in middle" do + let(:url) { "http://example.com/foo.tar.gz/from/this/mirror" } + it { is_expected.to eq(HOMEBREW_CACHE/"foo-.tar.gz") } + end + end end describe DownloadStrategyDetector do diff --git a/Library/Homebrew/test/spec_helper.rb b/Library/Homebrew/test/spec_helper.rb index be184b6e0..865342ddf 100644 --- a/Library/Homebrew/test/spec_helper.rb +++ b/Library/Homebrew/test/spec_helper.rb @@ -2,6 +2,7 @@ require "find" require "pathname" require "rspec/its" require "rspec/wait" +require "rspec/retry" require "rubocop" require "rubocop/rspec/support" require "set" diff --git a/Library/Homebrew/test/utils/tty_spec.rb b/Library/Homebrew/test/utils/tty_spec.rb index 3ba89b6fd..e6c9168f3 100644 --- a/Library/Homebrew/test/utils/tty_spec.rb +++ b/Library/Homebrew/test/utils/tty_spec.rb @@ -53,7 +53,7 @@ describe Tty do allow($stdout).to receive(:tty?).and_return(true) end - it "returns an empty string for all colors" do + it "returns ANSI escape codes for colors" do expect(subject.to_s).to eq("") expect(subject.red.to_s).to eq("\033[31m") expect(subject.green.to_s).to eq("\033[32m") @@ -63,5 +63,17 @@ describe Tty do expect(subject.cyan.to_s).to eq("\033[36m") expect(subject.default.to_s).to eq("\033[39m") end + + it "returns an empty string for all colors when HOMEBREW_NO_COLOR is set" do + ENV["HOMEBREW_NO_COLOR"] = "1" + expect(subject.to_s).to eq("") + expect(subject.red.to_s).to eq("") + expect(subject.green.to_s).to eq("") + expect(subject.yellow.to_s).to eq("") + expect(subject.blue.to_s).to eq("") + expect(subject.magenta.to_s).to eq("") + expect(subject.cyan.to_s).to eq("") + expect(subject.default.to_s).to eq("") + end end end diff --git a/Library/Homebrew/utils.rb b/Library/Homebrew/utils.rb index 989f05b45..03924dcef 100644 --- a/Library/Homebrew/utils.rb +++ b/Library/Homebrew/utils.rb @@ -200,6 +200,7 @@ module Homebrew def install_gem_setup_path!(name, version = nil, executable = name) # Match where our bundler gems are. ENV["GEM_HOME"] = "#{ENV["HOMEBREW_LIBRARY"]}/Homebrew/vendor/bundle/ruby/#{RbConfig::CONFIG["ruby_version"]}" + ENV["GEM_PATH"] = ENV["GEM_HOME"] # Make rubygems notice env changes. Gem.clear_paths diff --git a/Library/Homebrew/utils/git.rb b/Library/Homebrew/utils/git.rb index f1113af66..ac17967c5 100644 --- a/Library/Homebrew/utils/git.rb +++ b/Library/Homebrew/utils/git.rb @@ -50,7 +50,7 @@ module Utils # we cannot install brewed git if homebrew/core is unavailable. if CoreTap.instance.installed? begin - oh1 "Installing git" + oh1 "Installing #{Formatter.identifier("git")}" safe_system HOMEBREW_BREW_FILE, "install", "git" rescue raise "Git is unavailable" diff --git a/Library/Homebrew/utils/tty.rb b/Library/Homebrew/utils/tty.rb index e872e6460..81d5f00d7 100644 --- a/Library/Homebrew/utils/tty.rb +++ b/Library/Homebrew/utils/tty.rb @@ -59,7 +59,9 @@ module Tty end def to_s - return "" unless $stdout.tty? + if ENV["HOMEBREW_NO_COLOR"] || !$stdout.tty? + return "" + end current_escape_sequence ensure reset_escape_sequence! @@ -47,7 +47,7 @@ HOMEBREW_LIBRARY="$HOMEBREW_REPOSITORY/Library" # Whitelist and copy to HOMEBREW_* all variables previously mentioned in # manpage or used elsewhere by Homebrew. for VAR in AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY BINTRAY_USER BINTRAY_KEY \ - BROWSER EDITOR GIT PATH VISUAL \ + BROWSER EDITOR GIT NO_COLOR PATH VISUAL \ GITHUB_USER GITHUB_PASSWORD GITHUB_TOKEN do # Skip if variable value is empty. @@ -66,9 +66,9 @@ then FILTERED_ENV=() # Filter all but the specific variables. - for VAR in HOME SHELL PATH TERM LOGNAME USER CI TRAVIS SSH_AUTH_SOCK SUDO_ASKPASS \ + for VAR in HOME SHELL PATH TERM LOGNAME USER CI TRAVIS TRAVIS_SUDO SSH_AUTH_SOCK SUDO_ASKPASS \ http_proxy https_proxy ftp_proxy no_proxy all_proxy HTTPS_PROXY FTP_PROXY ALL_PROXY \ - "${!HOMEBREW_@}" "${!TRAVIS_@}" "${!JENKINS_@}" + "${!HOMEBREW_@}" do # Skip if variable value is empty. [[ -z "${!VAR}" ]] && continue diff --git a/docs/Manpage.md b/docs/Manpage.md index 920518376..e4f189490 100644 --- a/docs/Manpage.md +++ b/docs/Manpage.md @@ -1037,6 +1037,9 @@ can take several different forms: If set, Homebrew will not auto-update before running `brew install`, `brew upgrade` or `brew tap`. + * `HOMEBREW_NO_COLOR`: + If set, Homebrew will not print text with color added. + * `HOMEBREW_NO_EMOJI`: If set, Homebrew will not print the `HOMEBREW_INSTALL_BADGE` on a successful build. diff --git a/manpages/brew.1 b/manpages/brew.1 index 56581bfc0..4f373558c 100644 --- a/manpages/brew.1 +++ b/manpages/brew.1 @@ -1059,6 +1059,10 @@ If set, Homebrew will not send analytics\. See: \fIhttps://docs\.brew\.sh/Analyt If set, Homebrew will not auto\-update before running \fBbrew install\fR, \fBbrew upgrade\fR or \fBbrew tap\fR\. . .TP +\fBHOMEBREW_NO_COLOR\fR +If set, Homebrew will not print text with color added\. +. +.TP \fBHOMEBREW_NO_EMOJI\fR If set, Homebrew will not print the \fBHOMEBREW_INSTALL_BADGE\fR on a successful build\. . |
