From d3740ec34f1ad98311a3ac606643db972d5130e9 Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Mon, 19 Sep 2016 23:00:58 +0100 Subject: tests: run in parallel --- Library/Homebrew/dev-cmd/tests.rb | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/tests.rb b/Library/Homebrew/dev-cmd/tests.rb index aa2a3bff9..aba2fa3b6 100644 --- a/Library/Homebrew/dev-cmd/tests.rb +++ b/Library/Homebrew/dev-cmd/tests.rb @@ -6,7 +6,7 @@ require "tap" module Homebrew def tests - (HOMEBREW_LIBRARY/"Homebrew/test").cd do + (HOMEBREW_LIBRARY/"Homebrew").cd do ENV["HOMEBREW_NO_ANALYTICS_THIS_RUN"] = "1" ENV["HOMEBREW_DEVELOPER"] = "1" ENV["TESTOPTS"] = "-v" if ARGV.verbose? @@ -19,9 +19,11 @@ module Homebrew if ARGV.include? "--coverage" ENV["HOMEBREW_TESTS_COVERAGE"] = "1" - FileUtils.rm_f "coverage/.resultset.json" + FileUtils.rm_f "test/coverage/.resultset.json" end + ENV["BUNDLE_GEMFILE"] = "#{Dir.pwd}/test/Gemfile" + # Override author/committer as global settings might be invalid and thus # will cause silent failure during the setup of dummy Git repositories. %w[AUTHOR COMMITTER].each do |role| @@ -37,16 +39,18 @@ module Homebrew # Make it easier to reproduce test runs. ENV["SEED"] = ARGV.next if ARGV.include? "--seed" + files = Dir["test/test_*.rb"] + files -= Dir["test/test_os_mac_*.rb"] unless OS.mac? args = [] args << "--trace" if ARGV.include? "--trace" if ARGV.value("only") ENV["HOMEBREW_TESTS_ONLY"] = "1" test_name, test_method = ARGV.value("only").split("/", 2) - args << "TEST=test_#{test_name}.rb" - args << "TESTOPTS=--name=test_#{test_method}" if test_method + files = ["test/test_#{test_name}.rb"] + args << "--name=test_#{test_method}" if test_method end args += ARGV.named.select { |v| v[/^TEST(OPTS)?=/] } - system "bundle", "exec", "rake", "test", *args + system "bundle", "exec", "parallel_test", "--", *args, "--", *files Homebrew.failed = !$?.success? -- cgit v1.2.3 From 4a9ee8154a13a0bc7b9fa3aea47108b12072ab07 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Tue, 20 Sep 2016 11:50:02 +0200 Subject: Simplify `brew man` authors. --- Library/Homebrew/dev-cmd/man.rb | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/man.rb b/Library/Homebrew/dev-cmd/man.rb index 0627241a3..871fbf46c 100644 --- a/Library/Homebrew/dev-cmd/man.rb +++ b/Library/Homebrew/dev-cmd/man.rb @@ -52,17 +52,12 @@ module Homebrew variables[:commands] = path_glob_commands("#{HOMEBREW_LIBRARY_PATH}/cmd/*.{rb,sh}") variables[:developer_commands] = path_glob_commands("#{HOMEBREW_LIBRARY_PATH}/dev-cmd/*.{rb,sh}") readme = HOMEBREW_REPOSITORY/"README.md" - variables[:lead_maintainer] = readme - .read[/Homebrew's lead maintainer is (.*)\./, 1] - .scan(/\[([^\]]*)\]/).flatten.first - variables[:maintainers] = readme - .read[/Homebrew's current maintainers are (.*)\./, 1] - .scan(/\[([^\]]*)\]/).flatten - former_maintainers = readme - .read[/Former maintainers with significant contributions include (.*)\./, 1] - .scan(/\[([^\]]*)\]/).flatten - variables[:former_maintainers] = former_maintainers[0...-1] - variables[:creator] = former_maintainers.last + variables[:lead_maintainer] = readme.read[/(Homebrew's lead maintainer .*\.)/, 1] + .gsub(/\[([^\]]+)\]\([^)]+\)/, '\1') + variables[:maintainers] = readme.read[/(Homebrew's current maintainers .*\.)/, 1] + .gsub(/\[([^\]]+)\]\([^)]+\)/, '\1') + variables[:former_maintainers] = readme.read[/(Former maintainers .*\.)/, 1] + .gsub(/\[([^\]]+)\]\([^)]+\)/, '\1') ERB.new(template, nil, ">").result(variables.instance_eval { binding }) end -- cgit v1.2.3 From 869fb0214971f3dbcccbe1915702ffc7e7d69d16 Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Tue, 20 Sep 2016 14:57:08 +0100 Subject: tests, cask-tests: serialize stdout on CI --- Library/Homebrew/dev-cmd/tests.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/tests.rb b/Library/Homebrew/dev-cmd/tests.rb index aba2fa3b6..9b15f9f3e 100644 --- a/Library/Homebrew/dev-cmd/tests.rb +++ b/Library/Homebrew/dev-cmd/tests.rb @@ -41,16 +41,24 @@ module Homebrew files = Dir["test/test_*.rb"] files -= Dir["test/test_os_mac_*.rb"] unless OS.mac? + + opts = [] + opts << "--serialize-stdout" if ENV["CI"] + args = [] args << "--trace" if ARGV.include? "--trace" + if ARGV.value("only") ENV["HOMEBREW_TESTS_ONLY"] = "1" test_name, test_method = ARGV.value("only").split("/", 2) files = ["test/test_#{test_name}.rb"] args << "--name=test_#{test_method}" if test_method end + args += ARGV.named.select { |v| v[/^TEST(OPTS)?=/] } - system "bundle", "exec", "parallel_test", "--", *args, "--", *files + + system "bundle", "exec", "parallel_test", *opts, + "--", *args, "--", *files Homebrew.failed = !$?.success? -- cgit v1.2.3 From f6fef7cdce5302ae6f3fed357612d31d1d08cd5a Mon Sep 17 00:00:00 2001 From: Mike McQuaid Date: Tue, 20 Sep 2016 19:30:27 +0100 Subject: test-bot: always update to tag for taps. --- Library/Homebrew/dev-cmd/test-bot.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/test-bot.rb b/Library/Homebrew/dev-cmd/test-bot.rb index d20711588..7a5853c48 100644 --- a/Library/Homebrew/dev-cmd/test-bot.rb +++ b/Library/Homebrew/dev-cmd/test-bot.rb @@ -1076,7 +1076,10 @@ module Homebrew # because Formula parsing and/or git commit hash lookup depends on it. # At the same time, make sure Tap is not a shallow clone. # bottle rebuild and bottle upload rely on full clone. - safe_system "brew", "tap", tap.name, "--full" if tap + if tap + ENV["HOMEBREW_UPDATE_TO_TAG"] = "1" + safe_system "brew", "tap", tap.name, "--full" + end if ARGV.include? "--ci-upload" return test_ci_upload(tap) -- cgit v1.2.3 From 5ba04b0cc6c8d3df935ab3058a91d5cbb5dc5fb7 Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Thu, 22 Sep 2016 19:26:24 +0100 Subject: docs: more accurate update-test parameter name `sha1` isn't a very accurate description of what this value can be because it can be any git commit reference. For example, `brew test-bot` uses `brew update-test --commit=HEAD`. --- Library/Homebrew/dev-cmd/update-test.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/update-test.rb b/Library/Homebrew/dev-cmd/update-test.rb index bcf8020e4..47c9046f2 100644 --- a/Library/Homebrew/dev-cmd/update-test.rb +++ b/Library/Homebrew/dev-cmd/update-test.rb @@ -1,9 +1,9 @@ -#: * `update-test` [`--commit=`] [`--before=`] [`--keep-tmp`]: +#: * `update-test` [`--commit=`] [`--before=`] [`--keep-tmp`]: #: Runs a test of `brew update` with a new repository clone. #: #: If no arguments are passed, use `origin/master` as the start commit. #: -#: If `--commit=` is passed, use `` as the start commit. +#: If `--commit=` is passed, use `` as the start commit. #: #: If `--before=` is passed, use the commit at `` as the #: start commit. -- cgit v1.2.3 From b81dcea043e2ce96371af7701f4db39b339434ee Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Thu, 22 Sep 2016 19:26:41 +0100 Subject: update-test: more accurate variable names --- Library/Homebrew/dev-cmd/update-test.rb | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/update-test.rb b/Library/Homebrew/dev-cmd/update-test.rb index 47c9046f2..18980b691 100644 --- a/Library/Homebrew/dev-cmd/update-test.rb +++ b/Library/Homebrew/dev-cmd/update-test.rb @@ -14,18 +14,18 @@ module Homebrew def update_test cd HOMEBREW_REPOSITORY - start_sha1 = if commit = ARGV.value("commit") + start_commit = if commit = ARGV.value("commit") commit elsif date = ARGV.value("before") Utils.popen_read("git", "rev-list", "-n1", "--before=#{date}", "origin/master").chomp else Utils.popen_read("git", "rev-parse", "origin/master").chomp end - start_sha1 = Utils.popen_read("git", "rev-parse", start_sha1).chomp - end_sha1 = Utils.popen_read("git", "rev-parse", "HEAD").chomp + start_commit = Utils.popen_read("git", "rev-parse", start_commit).chomp + end_commit = Utils.popen_read("git", "rev-parse", "HEAD").chomp - puts "Start commit: #{start_sha1}" - puts "End commit: #{end_sha1}" + puts "Start commit: #{start_commit}" + puts "End commit: #{end_commit}" mktemp("update-test") do |staging| staging.retain! if ARGV.keep_tmp? @@ -39,12 +39,12 @@ module Homebrew safe_system "git", "clone", "--local", "--bare", "#{HOMEBREW_REPOSITORY}/.git", "remote.git" safe_system "git", "config", "remote.origin.url", "#{curdir}/remote.git" - # force push origin to end_sha1 - safe_system "git", "checkout", "-B", "master", end_sha1 + # force push origin to end_commit + safe_system "git", "checkout", "-B", "master", end_commit safe_system "git", "push", "--force", "origin", "master" - # set test copy to start_sha1 - safe_system "git", "reset", "--hard", start_sha1 + # set test copy to start_commit + safe_system "git", "reset", "--hard", start_commit # update ENV["PATH"] ENV["PATH"] = "#{curdir}/bin:/usr/local/bin:/usr/bin:/bin" @@ -52,13 +52,13 @@ module Homebrew # run brew update oh1 "Running brew update..." safe_system "brew", "update", "--verbose" - actual_end_sha1 = Utils.popen_read("git", "rev-parse", "master").chomp - if start_sha1 != end_sha1 && start_sha1 == actual_end_sha1 + actual_end_commit = Utils.popen_read("git", "rev-parse", "master").chomp + if start_commit != end_commit && start_commit == actual_end_commit raise <<-EOS.undent brew update didn't update master! - Start commit: #{start_sha1} - Expected end commit: #{end_sha1} - Actual end commit: #{actual_end_sha1} + Start commit: #{start_commit} + Expected end commit: #{end_commit} + Actual end commit: #{actual_end_commit} EOS end end -- cgit v1.2.3 From 846a5b79b6868d6f78a1b46baedae89d74bb5142 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Thu, 22 Sep 2016 14:36:24 -0400 Subject: Remove old cctools references now that only ruby-macho is used. --- Library/Homebrew/dev-cmd/bottle.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/bottle.rb b/Library/Homebrew/dev-cmd/bottle.rb index 9676e374c..f4d6a463a 100644 --- a/Library/Homebrew/dev-cmd/bottle.rb +++ b/Library/Homebrew/dev-cmd/bottle.rb @@ -255,7 +255,7 @@ module Homebrew if prefix != prefix_check relocatable = false if keg_contain_absolute_symlink_starting_with?(prefix, keg) end - skip_relocation = relocatable && !keg.require_install_name_tool? + skip_relocation = relocatable && !keg.require_relocation? end puts if !relocatable && ARGV.verbose? rescue Interrupt -- cgit v1.2.3 From 709a20e2a0bfc8339768cd664c4ed503507908cb Mon Sep 17 00:00:00 2001 From: Bob W. Hogg Date: Thu, 22 Sep 2016 17:12:13 -0400 Subject: test: most formulae have tests now --- Library/Homebrew/dev-cmd/test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/test.rb b/Library/Homebrew/dev-cmd/test.rb index a80fa5e4f..c20edf804 100644 --- a/Library/Homebrew/dev-cmd/test.rb +++ b/Library/Homebrew/dev-cmd/test.rb @@ -1,5 +1,5 @@ #: * `test` [`--devel`|`--HEAD`] [`--debug`] [`--keep-tmp`] : -#: A few formulae provide a test method. `brew test` runs this +#: Most formulae provide a test method. `brew test` runs this #: test method. There is no standard output or return code, but it should #: generally indicate to the user if something is wrong with the installed #: formula. -- cgit v1.2.3 From 28a3cec21a259bf3a0f8e6de846fa12be6524198 Mon Sep 17 00:00:00 2001 From: Mike McQuaid Date: Fri, 23 Sep 2016 14:24:41 +0100 Subject: test-bot: cleanup Cellar/etc/var after each build. This has been causing issues when bottling files that are installed to these paths due to the diff algorithm we use for figuring out whether files installed into etc/var belong to a given bottle. Additionally, sometimes not all formulae were uninstalled which meant `brew doctor` would fail. --- Library/Homebrew/dev-cmd/test-bot.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/test-bot.rb b/Library/Homebrew/dev-cmd/test-bot.rb index 7a5853c48..e7f68d4e8 100644 --- a/Library/Homebrew/dev-cmd/test-bot.rb +++ b/Library/Homebrew/dev-cmd/test-bot.rb @@ -749,7 +749,7 @@ module Homebrew end end - def cleanup_git + def cleanup_shared git "gc", "--auto" test "git", "clean", "-ffdx", "--exclude=Library/Taps" @@ -759,8 +759,8 @@ module Homebrew safe_system "brew", "untap", tap end - Formula.installed.each do |formula| - safe_system "brew", "uninstall", "--force", formula + Dir.glob("#{HOMEBREW_PREFIX}/{Cellar,etc,var}/**/*").each do |file| + FileUtils.rm_rf file end safe_system "brew", "prune" @@ -792,7 +792,7 @@ module Homebrew git "reset", "--hard", "origin/master" end - cleanup_git + cleanup_shared pr_locks = "#{@repository}/.git/refs/remotes/*/pr/*/*.lock" Dir.glob(pr_locks) { |lock| FileUtils.rm_rf lock } @@ -813,7 +813,7 @@ module Homebrew git "stash", "pop" test "brew", "cleanup", "--prune=7" - cleanup_git + cleanup_shared if ARGV.include? "--local" FileUtils.rm_rf ENV["HOMEBREW_HOME"] -- cgit v1.2.3 From 240e49052cf113b74c0b2940531d7b6a28ab83af Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 21 Sep 2016 08:49:04 +0200 Subject: Fix Performance/FixedSize. --- Library/Homebrew/dev-cmd/audit.rb | 2 +- Library/Homebrew/dev-cmd/bottle.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index 20e9a8aff..55f545d0c 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -467,7 +467,7 @@ class FormulaAuditor # Make sure the formula name plus description is no longer than 80 characters # Note full_name includes the name of the tap, while name does not - linelength = formula.name.length + ": ".length + desc.length + linelength = "#{formula.name}: #{desc}".length if linelength > 80 problem <<-EOS.undent Description is too long. \"name: desc\" should be less than 80 characters. diff --git a/Library/Homebrew/dev-cmd/bottle.rb b/Library/Homebrew/dev-cmd/bottle.rb index f4d6a463a..fe07526f3 100644 --- a/Library/Homebrew/dev-cmd/bottle.rb +++ b/Library/Homebrew/dev-cmd/bottle.rb @@ -436,7 +436,7 @@ module Homebrew puts output update_or_add = "add" if s.include? "stable do" - indent = s.slice(/^ +stable do/).length - "stable do".length + indent = s.slice(/^( +)stable do/, 1).length string = s.sub!(/^ {#{indent}}stable do(.|\n)+?^ {#{indent}}end\n/m, '\0' + output + "\n") else string = s.sub!( -- cgit v1.2.3 From 23dacc752529bcba88248899cd5b67a66499dc40 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 21 Sep 2016 09:21:27 +0200 Subject: Fix Style/Next. --- Library/Homebrew/dev-cmd/test-bot.rb | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/test-bot.rb b/Library/Homebrew/dev-cmd/test-bot.rb index 7a5853c48..aa3a49610 100644 --- a/Library/Homebrew/dev-cmd/test-bot.rb +++ b/Library/Homebrew/dev-cmd/test-bot.rb @@ -563,11 +563,10 @@ module Homebrew (installed & dependencies).each do |installed_dependency| installed_dependency_formula = Formulary.factory(installed_dependency) - if installed_dependency_formula.installed? && - !installed_dependency_formula.keg_only? && - !installed_dependency_formula.linked_keg.exist? - test "brew", "link", installed_dependency - end + next unless installed_dependency_formula.installed? + next if installed_dependency_formula.keg_only? + next if installed_dependency_formula.linked_keg.exist? + test "brew", "link", installed_dependency end dependencies -= installed -- cgit v1.2.3 From 9ce3c8d8a4059be6187dfcfd3daddfa7ef48c656 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 21 Sep 2016 09:22:21 +0200 Subject: Fix Style/NumericLiterals. --- Library/Homebrew/dev-cmd/test-bot.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/test-bot.rb b/Library/Homebrew/dev-cmd/test-bot.rb index aa3a49610..d63f88a1c 100644 --- a/Library/Homebrew/dev-cmd/test-bot.rb +++ b/Library/Homebrew/dev-cmd/test-bot.rb @@ -185,8 +185,8 @@ module Homebrew def puts_result if ENV["TRAVIS"] - travis_start_time = @start_time.to_i*1000000000 - travis_end_time = @end_time.to_i*1000000000 + travis_start_time = @start_time.to_i * 1_000_000_000 + travis_end_time = @end_time.to_i * 1_000_000_000 travis_duration = travis_end_time - travis_start_time puts "#{Tty.white}==>#{Tty.green} PASSED#{Tty.reset}" if passed? puts "travis_time:end:#{@travis_timer_id},start=#{travis_start_time},finish=#{travis_end_time},duration=#{travis_duration}" -- cgit v1.2.3 From a5b11a6a5c7e29b9040f93fd211f52479507dd01 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Thu, 22 Sep 2016 20:12:28 +0200 Subject: Fix Style/GuardClause. --- Library/Homebrew/dev-cmd/audit.rb | 103 ++++++++++++++++++------------------- Library/Homebrew/dev-cmd/bottle.rb | 64 +++++++++++------------ 2 files changed, 82 insertions(+), 85 deletions(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index 55f545d0c..61d136daf 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -83,11 +83,11 @@ module Homebrew end end - unless problem_count.zero? - problems = "problem" + plural(problem_count) - formulae = "formula" + plural(formula_count, "e") - ofail "#{problem_count} #{problems} in #{formula_count} #{formulae}" - end + return if problem_count.zero? + + problems = "problem" + plural(problem_count) + formulae = "formula" + plural(formula_count, "e") + ofail "#{problem_count} #{problems} in #{formula_count} #{formulae}" end end @@ -279,9 +279,11 @@ class FormulaAuditor end end end + if present.include?("head") && present.include?("head block") problem "Should not have both `head` and `head do`" end + if present.include?("bottle modifier") && present.include?("bottle block") problem "Should not have `bottle :unneeded/:disable` and `bottle do`" end @@ -668,24 +670,26 @@ class FormulaAuditor end revision_map = attributes_map[:revision] - if formula.revision.nonzero? - if formula.stable - if revision_map[formula.stable.version].empty? # check stable spec - problem "'revision #{formula.revision}' should be removed" - end - else # head/devel-only formula + + return if formula.revision.zero? + + if formula.stable + if revision_map[formula.stable.version].empty? # check stable spec problem "'revision #{formula.revision}' should be removed" end + else # head/devel-only formula + problem "'revision #{formula.revision}' should be removed" end end def audit_legacy_patches return unless formula.respond_to?(:patches) legacy_patches = Patch.normalize_legacy_patches(formula.patches).grep(LegacyPatch) - unless legacy_patches.empty? - problem "Use the patch DSL instead of defining a 'patches' method" - legacy_patches.each { |p| audit_patch(p) } - end + + return if legacy_patches.empty? + + problem "Use the patch DSL instead of defining a 'patches' method" + legacy_patches.each { |p| audit_patch(p) } end def audit_patch(patch) @@ -961,61 +965,56 @@ class FormulaAuditor problem "Use Language::Node for npm install args" end - if @strict - if line =~ /system ((["'])[^"' ]*(?:\s[^"' ]*)+\2)/ - bad_system = $1 - unless %w[| < > & ; *].any? { |c| bad_system.include? c } - good_system = bad_system.gsub(" ", "\", \"") - problem "Use `system #{good_system}` instead of `system #{bad_system}` " - end - end + return unless @strict - if line =~ /(require ["']formula["'])/ - problem "`#{$1}` is now unnecessary" + if line =~ /system ((["'])[^"' ]*(?:\s[^"' ]*)+\2)/ + bad_system = $1 + unless %w[| < > & ; *].any? { |c| bad_system.include? c } + good_system = bad_system.gsub(" ", "\", \"") + problem "Use `system #{good_system}` instead of `system #{bad_system}` " end + end - if line =~ %r{#\{share\}/#{Regexp.escape(formula.name)}[/'"]} - problem "Use \#{pkgshare} instead of \#{share}/#{formula.name}" - end + if line =~ /(require ["']formula["'])/ + problem "`#{$1}` is now unnecessary" + end - if line =~ %r{share(\s*[/+]\s*)(['"])#{Regexp.escape(formula.name)}(?:\2|/)} - problem "Use pkgshare instead of (share#{$1}\"#{formula.name}\")" - end + if line =~ %r{#\{share\}/#{Regexp.escape(formula.name)}[/'"]} + problem "Use \#{pkgshare} instead of \#{share}/#{formula.name}" + end + + if line =~ %r{share(\s*[/+]\s*)(['"])#{Regexp.escape(formula.name)}(?:\2|/)} + problem "Use pkgshare instead of (share#{$1}\"#{formula.name}\")" end end def audit_caveats - caveats = formula.caveats.to_s - - if caveats.include?("setuid") - problem "Don't recommend setuid in the caveats, suggest sudo instead." - end + return unless formula.caveats.to_s.include?("setuid") + problem "Don't recommend setuid in the caveats, suggest sudo instead." end def audit_reverse_migration # Only enforce for new formula being re-added to core and official taps return unless @strict return unless formula.tap && formula.tap.official? + return unless formula.tap.tap_migrations.key?(formula.name) - if formula.tap.tap_migrations.key?(formula.name) - problem <<-EOS.undent - #{formula.name} seems to be listed in tap_migrations.json! - Please remove #{formula.name} from present tap & tap_migrations.json - before submitting it to Homebrew/homebrew-#{formula.tap.repo}. - EOS - end + problem <<-EOS.undent + #{formula.name} seems to be listed in tap_migrations.json! + Please remove #{formula.name} from present tap & tap_migrations.json + before submitting it to Homebrew/homebrew-#{formula.tap.repo}. + EOS end def audit_prefix_has_contents return unless formula.prefix.directory? + return unless Keg.new(formula.prefix).empty_installation? - if Keg.new(formula.prefix).empty_installation? - problem <<-EOS.undent - The installation seems to be empty. Please ensure the prefix - is set correctly and expected files are installed. - The prefix configure/make argument may be case-sensitive. - EOS - end + problem <<-EOS.undent + The installation seems to be empty. Please ensure the prefix + is set correctly and expected files are installed. + The prefix configure/make argument may be case-sensitive. + EOS end def audit_conditional_dep(dep, condition, line) @@ -1184,9 +1183,7 @@ class ResourceAuditor end end - using_strategy = DownloadStrategyDetector.detect("", using) - - if url_strategy == using_strategy + if url_strategy == DownloadStrategyDetector.detect("", using) problem "Redundant :using value in URL" end end diff --git a/Library/Homebrew/dev-cmd/bottle.rb b/Library/Homebrew/dev-cmd/bottle.rb index fe07526f3..797828e0e 100644 --- a/Library/Homebrew/dev-cmd/bottle.rb +++ b/Library/Homebrew/dev-cmd/bottle.rb @@ -51,10 +51,11 @@ module Homebrew end @put_filenames ||= [] - unless @put_filenames.include? filename - puts "#{Tty.red}#{filename}#{Tty.reset}" - @put_filenames << filename - end + + return if @put_filenames.include? filename + + puts "#{Tty.red}#{filename}#{Tty.reset}" + @put_filenames << filename end result = false @@ -137,11 +138,11 @@ module Homebrew tap = f.tap unless tap - if ARGV.include?("--force-core-tap") - tap = CoreTap.instance - else + unless ARGV.include?("--force-core-tap") return ofail "Formula not from core or any taps: #{f.full_name}" end + + tap = CoreTap.instance end if f.bottle_disabled? @@ -323,34 +324,33 @@ module Homebrew puts "./#{filename}" puts output - if ARGV.include? "--json" - json = { - f.full_name => { - "formula" => { - "pkg_version" => f.pkg_version.to_s, - "path" => f.path.to_s.strip_prefix("#{HOMEBREW_REPOSITORY}/"), - }, - "bottle" => { - "root_url" => bottle.root_url, - "prefix" => bottle.prefix, - "cellar" => bottle.cellar.to_s, - "rebuild" => bottle.rebuild, - "tags" => { - Utils::Bottles.tag.to_s => { - "filename" => filename.to_s, - "sha256" => sha256, - }, + return unless ARGV.include? "--json" + json = { + f.full_name => { + "formula" => { + "pkg_version" => f.pkg_version.to_s, + "path" => f.path.to_s.strip_prefix("#{HOMEBREW_REPOSITORY}/"), + }, + "bottle" => { + "root_url" => bottle.root_url, + "prefix" => bottle.prefix, + "cellar" => bottle.cellar.to_s, + "rebuild" => bottle.rebuild, + "tags" => { + Utils::Bottles.tag.to_s => { + "filename" => filename.to_s, + "sha256" => sha256, }, }, - "bintray" => { - "package" => Utils::Bottles::Bintray.package(f.name), - "repository" => Utils::Bottles::Bintray.repository(tap), - }, }, - } - File.open("#{filename.prefix}.bottle.json", "w") do |file| - file.write Utils::JSON.dump json - end + "bintray" => { + "package" => Utils::Bottles::Bintray.package(f.name), + "repository" => Utils::Bottles::Bintray.repository(tap), + }, + }, + } + File.open("#{filename.prefix}.bottle.json", "w") do |file| + file.write Utils::JSON.dump json end end -- cgit v1.2.3 From fe2d51e0b9d4d9c138e512c245b1ed8d0f1dbf53 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Fri, 23 Sep 2016 11:01:40 +0200 Subject: Fix Style/IfUnlessModifier. --- Library/Homebrew/dev-cmd/bottle.rb | 8 ++------ Library/Homebrew/dev-cmd/edit.rb | 6 +++--- Library/Homebrew/dev-cmd/mirror.rb | 4 +--- Library/Homebrew/dev-cmd/pull.rb | 12 ++++++------ Library/Homebrew/dev-cmd/test-bot.rb | 16 ++++------------ 5 files changed, 16 insertions(+), 30 deletions(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/bottle.rb b/Library/Homebrew/dev-cmd/bottle.rb index 797828e0e..b2aa3b2c5 100644 --- a/Library/Homebrew/dev-cmd/bottle.rb +++ b/Library/Homebrew/dev-cmd/bottle.rb @@ -108,9 +108,7 @@ module Homebrew absolute_symlinks_start_with_string = [] keg.find do |pn| next unless pn.symlink? && (link = pn.readlink).absolute? - if link.to_s.start_with?(string) - absolute_symlinks_start_with_string << pn - end + absolute_symlinks_start_with_string << pn if link.to_s.start_with?(string) end if ARGV.verbose? @@ -155,9 +153,7 @@ module Homebrew return ofail "Formula not installed with '--build-bottle': #{f.full_name}" end - unless f.stable - return ofail "Formula has no stable version: #{f.full_name}" - end + return ofail "Formula has no stable version: #{f.full_name}" unless f.stable if ARGV.include?("--no-rebuild") || !f.tap rebuild = 0 diff --git a/Library/Homebrew/dev-cmd/edit.rb b/Library/Homebrew/dev-cmd/edit.rb index f80d05861..2d2a5ec08 100644 --- a/Library/Homebrew/dev-cmd/edit.rb +++ b/Library/Homebrew/dev-cmd/edit.rb @@ -33,9 +33,9 @@ module Homebrew # Don't use ARGV.formulae as that will throw if the file doesn't parse paths = ARGV.named.map do |name| path = Formulary.path(name) - unless path.file? || ARGV.force? - raise FormulaUnavailableError, name - end + + raise FormulaUnavailableError, name unless path.file? || ARGV.force? + path end exec_editor(*paths) diff --git a/Library/Homebrew/dev-cmd/mirror.rb b/Library/Homebrew/dev-cmd/mirror.rb index 162008123..9966163f8 100644 --- a/Library/Homebrew/dev-cmd/mirror.rb +++ b/Library/Homebrew/dev-cmd/mirror.rb @@ -4,9 +4,7 @@ module Homebrew def mirror - if ARGV.named.empty? - odie "This command requires at least formula argument!" - end + odie "This command requires at least formula argument!" if ARGV.named.empty? bintray_user = ENV["BINTRAY_USER"] bintray_key = ENV["BINTRAY_KEY"] diff --git a/Library/Homebrew/dev-cmd/pull.rb b/Library/Homebrew/dev-cmd/pull.rb index 7f027e159..b06719fb1 100644 --- a/Library/Homebrew/dev-cmd/pull.rb +++ b/Library/Homebrew/dev-cmd/pull.rb @@ -41,12 +41,12 @@ require "pkg_version" module Homebrew def pull - if ARGV[0] == "--rebase" - odie "You meant `git pull --rebase`." - end + odie "You meant `git pull --rebase`." if ARGV[0] == "--rebase" + if ARGV.named.empty? odie "This command requires at least one argument containing a URL or pull request number" end + do_bump = ARGV.include?("--bump") && !ARGV.include?("--clean") # Formulae with affected bottles that were published @@ -429,9 +429,9 @@ module Homebrew # Returns nil if formula is absent or if there was an error reading it def self.lookup(name) json = Utils.popen_read(HOMEBREW_BREW_FILE, "info", "--json=v1", name) - unless $?.success? - return nil - end + + return nil unless $?.success? + Homebrew.force_utf8!(json) FormulaInfoFromJson.new(Utils::JSON.load(json)[0]) end diff --git a/Library/Homebrew/dev-cmd/test-bot.rb b/Library/Homebrew/dev-cmd/test-bot.rb index d63f88a1c..ba78cdb59 100644 --- a/Library/Homebrew/dev-cmd/test-bot.rb +++ b/Library/Homebrew/dev-cmd/test-bot.rb @@ -724,9 +724,7 @@ module Homebrew coverage_args = [] if ARGV.include?("--coverage") if ENV["JENKINS_HOME"] - if OS.mac? && MacOS.version == :sierra - coverage_args << "--coverage" - end + coverage_args << "--coverage" if OS.mac? && MacOS.version == :sierra else coverage_args << "--coverage" end @@ -741,9 +739,7 @@ module Homebrew test "brew", "cask-tests", *coverage_args end elsif @tap - if @tap.name == "homebrew/core" - test "brew", "style", @tap.name - end + test "brew", "style", @tap.name if @tap.name == "homebrew/core" test "brew", "readall", "--aliases", @tap.name end end @@ -1054,9 +1050,7 @@ module Homebrew ARGV << "--junit" << "--local" << "--test-default-formula" end - if ARGV.include? "--ci-master" - ARGV << "--fast" - end + ARGV << "--fast" if ARGV.include?("--ci-master") if ARGV.include? "--local" ENV["HOMEBREW_CACHE"] = "#{ENV["HOME"]}/Library/Caches/Homebrew" @@ -1080,9 +1074,7 @@ module Homebrew safe_system "brew", "tap", tap.name, "--full" end - if ARGV.include? "--ci-upload" - return test_ci_upload(tap) - end + return test_ci_upload(tap) if ARGV.include?("--ci-upload") tests = [] any_errors = false -- cgit v1.2.3 From 7c27fda11d8e6debe617734fd9dfe42baa1dc2c1 Mon Sep 17 00:00:00 2001 From: Mike McQuaid Date: Fri, 23 Sep 2016 20:29:57 +0100 Subject: test-bot: always check style of formula. --- Library/Homebrew/dev-cmd/test-bot.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/test-bot.rb b/Library/Homebrew/dev-cmd/test-bot.rb index c1a4d99b7..abf0235e5 100644 --- a/Library/Homebrew/dev-cmd/test-bot.rb +++ b/Library/Homebrew/dev-cmd/test-bot.rb @@ -634,6 +634,7 @@ module Homebrew install_passed = steps.last.passed? end end + test "brew", "style", formula_name test "brew", "audit", *audit_args if install_passed if formula.stable? && !ARGV.include?("--fast") && !ARGV.include?("--no-bottle") && !formula.bottle_disabled? -- cgit v1.2.3 From 58e36c73193befb57d351344cea2a4a33fef850d Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Fri, 23 Sep 2016 22:02:23 +0200 Subject: Fix Style/GuardClause. --- Library/Homebrew/dev-cmd/audit.rb | 46 +++++++++++++++--------------------- Library/Homebrew/dev-cmd/pull.rb | 22 ++++++++--------- Library/Homebrew/dev-cmd/test-bot.rb | 33 ++++++++++++-------------- 3 files changed, 45 insertions(+), 56 deletions(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index 61d136daf..1a6e47dbe 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -284,9 +284,8 @@ class FormulaAuditor problem "Should not have both `head` and `head do`" end - if present.include?("bottle modifier") && present.include?("bottle block") - problem "Should not have `bottle :unneeded/:disable` and `bottle do`" - end + return unless present.include?("bottle modifier") && present.include?("bottle block") + problem "Should not have `bottle :unneeded/:disable` and `bottle do`" end def audit_class @@ -350,9 +349,8 @@ class FormulaAuditor same_name_tap_formulae.delete(full_name) - unless same_name_tap_formulae.empty? - problem "Formula name conflicts with #{same_name_tap_formulae.join ", "}" - end + return if same_name_tap_formulae.empty? + problem "Formula name conflicts with #{same_name_tap_formulae.join ", "}" end def audit_deps @@ -485,9 +483,8 @@ class FormulaAuditor problem "Description shouldn't start with an indefinite article (#{$1})" end - if desc.downcase.start_with? "#{formula.name} " - problem "Description shouldn't include the formula name" - end + return unless desc.downcase.start_with? "#{formula.name} " + problem "Description shouldn't include the formula name" end def audit_homepage @@ -564,9 +561,9 @@ class FormulaAuditor end def audit_bottle_spec - if formula.bottle_disabled? && !formula.bottle_disable_reason.valid? - problem "Unrecognized bottle modifier" - end + return unless formula.bottle_disabled? + return if formula.bottle_disable_reason.valid? + problem "Unrecognized bottle modifier" end def audit_github_repository @@ -594,9 +591,8 @@ class FormulaAuditor problem "GitHub repository not notable enough (<20 forks, <20 watchers and <50 stars)" end - if Date.parse(metadata["created_at"]) > (Date.today - 30) - problem "GitHub repository too new (<30 days old)" - end + return if Date.parse(metadata["created_at"]) <= (Date.today - 30) + problem "GitHub repository too new (<30 days old)" end def audit_specs @@ -736,9 +732,8 @@ class FormulaAuditor problem "Please set plist_options when using a formula-defined plist." end - if text.include?('require "language/go"') && !text.include?("go_resource") - problem "require \"language/go\" is unnecessary unless using `go_resource`s" - end + return unless text.include?('require "language/go"') && !text.include?("go_resource") + problem "require \"language/go\" is unnecessary unless using `go_resource`s" end def audit_line(line, lineno) @@ -983,9 +978,8 @@ class FormulaAuditor problem "Use \#{pkgshare} instead of \#{share}/#{formula.name}" end - if line =~ %r{share(\s*[/+]\s*)(['"])#{Regexp.escape(formula.name)}(?:\2|/)} - problem "Use pkgshare instead of (share#{$1}\"#{formula.name}\")" - end + return unless line =~ %r{share(\s*[/+]\s*)(['"])#{Regexp.escape(formula.name)}(?:\2|/)} + problem "Use pkgshare instead of (share#{$1}\"#{formula.name}\")" end def audit_caveats @@ -1115,9 +1109,8 @@ class ResourceAuditor problem "version #{version} should not have a leading 'v'" end - if version.to_s =~ /_\d+$/ - problem "version #{version} should not end with an underline and a number" - end + return unless version.to_s =~ /_\d+$/ + problem "version #{version} should not end with an underline and a number" end def audit_checksum @@ -1183,9 +1176,8 @@ class ResourceAuditor end end - if url_strategy == DownloadStrategyDetector.detect("", using) - problem "Redundant :using value in URL" - end + return unless url_strategy == DownloadStrategyDetector.detect("", using) + problem "Redundant :using value in URL" end def audit_urls diff --git a/Library/Homebrew/dev-cmd/pull.rb b/Library/Homebrew/dev-cmd/pull.rb index b06719fb1..857c55993 100644 --- a/Library/Homebrew/dev-cmd/pull.rb +++ b/Library/Homebrew/dev-cmd/pull.rb @@ -531,19 +531,19 @@ module Homebrew req = Net::HTTP::Head.new bottle_info.url req.initialize_http_header "User-Agent" => HOMEBREW_USER_AGENT_RUBY res = http.request req - if res.is_a?(Net::HTTPSuccess) - break - elsif res.is_a?(Net::HTTPClientError) - if retry_count >= max_retries - raise "Failed to find published #{f} bottle at #{url}!" - end - print(wrote_dots ? "." : "Waiting on Bintray.") - wrote_dots = true - sleep poll_retry_delay_seconds - retry_count += 1 - else + break if res.is_a?(Net::HTTPSuccess) + + unless res.is_a?(Net::HTTPClientError) raise "Failed to find published #{f} bottle at #{url} (#{res.code} #{res.message})!" end + + if retry_count >= max_retries + raise "Failed to find published #{f} bottle at #{url}!" + end + print(wrote_dots ? "." : "Waiting on Bintray.") + wrote_dots = true + sleep poll_retry_delay_seconds + retry_count += 1 end end diff --git a/Library/Homebrew/dev-cmd/test-bot.rb b/Library/Homebrew/dev-cmd/test-bot.rb index abf0235e5..935a40731 100644 --- a/Library/Homebrew/dev-cmd/test-bot.rb +++ b/Library/Homebrew/dev-cmd/test-bot.rb @@ -123,13 +123,12 @@ module Homebrew end end - if git_url = ENV["UPSTREAM_GIT_URL"] || ENV["GIT_URL"] - # Also can get tap from Jenkins GIT_URL. - url_path = git_url.sub(%r{^https?://github\.com/}, "").chomp("/").sub(/\.git$/, "") - begin - return Tap.fetch(url_path) if url_path =~ HOMEBREW_TAP_REGEX - rescue - end + return unless git_url = ENV["UPSTREAM_GIT_URL"] || ENV["GIT_URL"] + # Also can get tap from Jenkins GIT_URL. + url_path = git_url.sub(%r{^https?://github\.com/}, "").chomp("/").sub(/\.git$/, "") + begin + return Tap.fetch(url_path) if url_path =~ HOMEBREW_TAP_REGEX + rescue end end @@ -1001,10 +1000,9 @@ module Homebrew end end - if git_tag - safe_system "git", "tag", "--force", git_tag - safe_system "git", "push", "--force", remote, "master:master", "refs/tags/#{git_tag}" - end + return unless git_tag + safe_system "git", "tag", "--force", git_tag + safe_system "git", "push", "--force", remote, "master:master", "refs/tags/#{git_tag}" end def sanitize_argv_and_env @@ -1053,13 +1051,12 @@ module Homebrew ARGV << "--fast" if ARGV.include?("--ci-master") - if ARGV.include? "--local" - ENV["HOMEBREW_CACHE"] = "#{ENV["HOME"]}/Library/Caches/Homebrew" - mkdir_p ENV["HOMEBREW_CACHE"] - ENV["HOMEBREW_HOME"] = ENV["HOME"] = "#{Dir.pwd}/home" - mkdir_p ENV["HOME"] - ENV["HOMEBREW_LOGS"] = "#{Dir.pwd}/logs" - end + return unless ARGV.include?("--local") + ENV["HOMEBREW_CACHE"] = "#{ENV["HOME"]}/Library/Caches/Homebrew" + mkdir_p ENV["HOMEBREW_CACHE"] + ENV["HOMEBREW_HOME"] = ENV["HOME"] = "#{Dir.pwd}/home" + mkdir_p ENV["HOME"] + ENV["HOMEBREW_LOGS"] = "#{Dir.pwd}/logs" end def test_bot -- cgit v1.2.3 From 6c6a4c9fa771930c882ab7819e027031fb33b018 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Sat, 24 Sep 2016 17:59:14 +0200 Subject: RuboCop: Style/AccessorMethodName --- Library/Homebrew/dev-cmd/bump-formula-pr.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/bump-formula-pr.rb b/Library/Homebrew/dev-cmd/bump-formula-pr.rb index 38c7559fb..ce10da52a 100644 --- a/Library/Homebrew/dev-cmd/bump-formula-pr.rb +++ b/Library/Homebrew/dev-cmd/bump-formula-pr.rb @@ -27,7 +27,7 @@ require "formula" module Homebrew def inreplace_pairs(path, replacement_pairs) if ARGV.dry_run? - contents = path.open("r") { |f| Formulary.set_encoding(f).read } + contents = path.open("r") { |f| Formulary.ensure_utf8_encoding(f).read } contents.extend(StringInreplaceExtension) replacement_pairs.each do |old, new| unless ARGV.flag?("--quiet") @@ -48,7 +48,7 @@ module Homebrew s.gsub!(old, new) end end - path.open("r") { |f| Formulary.set_encoding(f).read } + path.open("r") { |f| Formulary.ensure_utf8_encoding(f).read } end end -- cgit v1.2.3 From d5b403b1e9462a569cde2d0af6e5974c96a37e66 Mon Sep 17 00:00:00 2001 From: Mike McQuaid Date: Sat, 24 Sep 2016 18:55:03 +0100 Subject: test-bot: move to tap. Migrate to https://github.com/Homebrew/homebrew-test-bot to be able to work on this with a different, non-tagged workflow. --- Library/Homebrew/dev-cmd/test-bot.rb | 1164 ---------------------------------- 1 file changed, 1164 deletions(-) delete mode 100644 Library/Homebrew/dev-cmd/test-bot.rb (limited to 'Library/Homebrew/dev-cmd') diff --git a/Library/Homebrew/dev-cmd/test-bot.rb b/Library/Homebrew/dev-cmd/test-bot.rb deleted file mode 100644 index 935a40731..000000000 --- a/Library/Homebrew/dev-cmd/test-bot.rb +++ /dev/null @@ -1,1164 +0,0 @@ -#: @hide_from_man_page -#: * `test-bot` [options] : -#: Tests the full lifecycle of a formula or Homebrew/brew change. -#: -#: If `--dry-run` is passed, print what would be done rather than doing -#: it. -#: -#: If `--local` is passed, perform only local operations (i.e. don't -#: push or create PR). -#: -#: If `--keep-logs` is passed, write and keep log files under -#: `./brewbot/`. -#: -#: If `--cleanup` is passed, clean all state from the Homebrew -#: directory. Use with care! -#: -#: If `--clean-cache` is passed, remove all cached downloads. Use with -#: care! -#: -#: If `--skip-setup` is passed, don't check the local system is setup -#: correctly. -#: -#: If `--skip-homebrew` is passed, don't check Homebrew's files and -#: tests are all valid. -#: -#: If `--junit` is passed, generate a JUnit XML test results file. -#: -#: If `--no-bottle` is passed, run `brew install` without -#: `--build-bottle`. -#: -#: If `--keep-old` is passed, run `brew bottle --keep-old` to build new -#: bottles for a single platform. -#: -#: If `--skip-relocation` is passed, run -#: `brew bottle --skip-relocation` to build new bottles that don't -#: require relocation. -#: -#: If `--HEAD` is passed, run `brew install` with `--HEAD`. -#: -#: If `--local` is passed, ask Homebrew to write verbose logs under -#: `./logs/` and set `$HOME` to `./home/`. -#: -#: If `--tap=` is passed, use the `git` repository of the given -#: tap. -#: -#: If `--dry-run` is passed, just print commands, don't run them. -#: -#: If `--fail-fast` is passed, immediately exit on a failing step. -#: -#: If `--verbose` is passed, print test step output in real time. Has -#: the side effect of passing output as raw bytes instead of -#: re-encoding in UTF-8. -#: -#: If `--fast` is passed, don't install any packages, but run e.g. -#: `brew audit` anyway. -#: -#: If `--keep-tmp` is passed, keep temporary files written by main -#: installs and tests that are run. -#: -#: If `--no-pull` is passed, don't use `brew pull` when possible. -#: -#: If `--coverage` is passed, generate and uplaod a coverage report. -#: -#: If `--test-default-formula` is passed, use a default testing formula -#: when not building a tap and no other formulae are specified. -#: -#: If `--ci-master` is passed, use the Homebrew master branch CI -#: options. -#: -#: If `--ci-pr` is passed, use the Homebrew pull request CI options. -#: -#: If `--ci-testing` is passed, use the Homebrew testing CI options. -#: -#: If `--ci-auto` is passed, automatically pick one of the Homebrew CI -#: options based on the environment. -#: -#: If `--ci-upload` is passed, use the Homebrew CI bottle upload -#: options. -#: -# -#: Influential environment variables include: -#: `TRAVIS_REPO_SLUG`: same as `--tap` -#: `GIT_URL`: if set to URL of a tap remote, same as `--tap` - -require "formula" -require "utils" -require "date" -require "rexml/document" -require "rexml/xmldecl" -require "rexml/cdata" -require "tap" -require "development_tools" -require "utils/bottles" - -module Homebrew - BYTES_IN_1_MEGABYTE = 1024*1024 - MAX_STEP_OUTPUT_SIZE = BYTES_IN_1_MEGABYTE - (200*1024) # margin of safety - - HOMEBREW_TAP_REGEX = %r{^([\w-]+)/homebrew-([\w-]+)$} - - def fix_encoding!(str) - # Assume we are starting from a "mostly" UTF-8 string - str.force_encoding(Encoding::UTF_8) - return str if str.valid_encoding? - str.encode!(Encoding::UTF_16, invalid: :replace) - str.encode!(Encoding::UTF_8) - end - - def resolve_test_tap - if tap = ARGV.value("tap") - return Tap.fetch(tap) - end - - if (tap = ENV["TRAVIS_REPO_SLUG"]) && (tap =~ HOMEBREW_TAP_REGEX) - return Tap.fetch(tap) - end - - if ENV["UPSTREAM_BOT_PARAMS"] - bot_argv = ENV["UPSTREAM_BOT_PARAMS"].split " " - bot_argv.extend HomebrewArgvExtension - if tap = bot_argv.value("tap") - return Tap.fetch(tap) - end - end - - return unless git_url = ENV["UPSTREAM_GIT_URL"] || ENV["GIT_URL"] - # Also can get tap from Jenkins GIT_URL. - url_path = git_url.sub(%r{^https?://github\.com/}, "").chomp("/").sub(/\.git$/, "") - begin - return Tap.fetch(url_path) if url_path =~ HOMEBREW_TAP_REGEX - rescue - end - end - - # Wraps command invocations. Instantiated by Test#test. - # Handles logging and pretty-printing. - class Step - attr_reader :command, :name, :status, :output - - # Instantiates a Step object. - # @param test [Test] The parent Test object - # @param command [Array] Command to execute and arguments - # @param options [Hash] Recognized options are: - # :puts_output_on_success - # :repository - def initialize(test, command, options = {}) - @test = test - @category = test.category - @command = command - @puts_output_on_success = options[:puts_output_on_success] - @name = command[1].delete("-") - @status = :running - @repository = options[:repository] || HOMEBREW_REPOSITORY - end - - def log_file_path - file = "#{@category}.#{@name}.txt" - root = @test.log_root - root ? root + file : file - end - - def command_short - (@command - %w[brew --force --retry --verbose --build-bottle --json]).join(" ") - end - - def passed? - @status == :passed - end - - def failed? - @status == :failed - end - - def puts_command - if ENV["TRAVIS"] - @@travis_step_num ||= 0 - @travis_fold_id = @command.first(2).join(".") + ".#{@@travis_step_num += 1}" - @travis_timer_id = rand(2**32).to_s(16) - puts "travis_fold:start:#{@travis_fold_id}" - puts "travis_time:start:#{@travis_timer_id}" - end - puts "#{Tty.blue}==>#{Tty.white} #{@command.join(" ")}#{Tty.reset}" - end - - def puts_result - if ENV["TRAVIS"] - travis_start_time = @start_time.to_i * 1_000_000_000 - travis_end_time = @end_time.to_i * 1_000_000_000 - travis_duration = travis_end_time - travis_start_time - puts "#{Tty.white}==>#{Tty.green} PASSED#{Tty.reset}" if passed? - puts "travis_time:end:#{@travis_timer_id},start=#{travis_start_time},finish=#{travis_end_time},duration=#{travis_duration}" - puts "travis_fold:end:#{@travis_fold_id}" - end - puts "#{Tty.white}==>#{Tty.red} FAILED#{Tty.reset}" if failed? - end - - def output? - @output && !@output.empty? - end - - # The execution time of the task. - # Precondition: Step#run has been called. - # @return [Float] execution time in seconds - def time - @end_time - @start_time - end - - def run - @start_time = Time.now - - puts_command - if ARGV.include? "--dry-run" - @end_time = Time.now - @status = :passed - puts_result - return - end - - verbose = ARGV.verbose? - # Step may produce arbitrary output and we read it bytewise, so must - # buffer it as binary and convert to UTF-8 once complete - output = "".encode!("BINARY") - working_dir = Pathname.new(@command.first == "git" ? @repository : Dir.pwd) - read, write = IO.pipe - - begin - pid = fork do - read.close - $stdout.reopen(write) - $stderr.reopen(write) - write.close - working_dir.cd { exec(*@command) } - end - write.close - while buf = read.readpartial(4096) - if verbose - print buf - $stdout.flush - end - output << buf - end - rescue EOFError - ensure - read.close - end - - Process.wait(pid) - @end_time = Time.now - @status = $?.success? ? :passed : :failed - puts_result - - unless output.empty? - @output = Homebrew.fix_encoding!(output) - puts @output if (failed? || @puts_output_on_success) && !verbose - File.write(log_file_path, @output) if ARGV.include? "--keep-logs" - end - - exit 1 if ARGV.include?("--fail-fast") && failed? - end - end - - class Test - attr_reader :log_root, :category, :name, :steps - - def initialize(argument, options = {}) - @hash = nil - @url = nil - @formulae = [] - @added_formulae = [] - @modified_formula = [] - @steps = [] - @tap = options[:tap] - @repository = @tap ? @tap.path : HOMEBREW_REPOSITORY - @skip_homebrew = options.fetch(:skip_homebrew, false) - - if quiet_system "git", "-C", @repository.to_s, "rev-parse", "--verify", "-q", argument - @hash = argument - elsif url_match = argument.match(HOMEBREW_PULL_OR_COMMIT_URL_REGEX) - @url = url_match[0] - elsif canonical_formula_name = safe_formula_canonical_name(argument) - @formulae = [canonical_formula_name] - else - raise ArgumentError, "#{argument} is not a pull request URL, commit URL or formula name." - end - - @category = __method__ - @brewbot_root = Pathname.pwd + "brewbot" - FileUtils.mkdir_p @brewbot_root - end - - def no_args? - @hash == "HEAD" - end - - def safe_formula_canonical_name(formula_name) - Formulary.factory(formula_name).full_name - rescue TapFormulaUnavailableError => e - raise if e.tap.installed? - test "brew", "tap", e.tap.name - retry unless steps.last.failed? - onoe e - puts e.backtrace if ARGV.debug? - rescue FormulaUnavailableError, TapFormulaAmbiguityError, TapFormulaWithOldnameAmbiguityError => e - onoe e - puts e.backtrace if ARGV.debug? - end - - def git(*args) - @repository.cd { Utils.popen_read("git", *args) } - end - - def download - def shorten_revision(revision) - git("rev-parse", "--short", revision).strip - end - - def current_sha1 - shorten_revision "HEAD" - end - - def current_branch - git("symbolic-ref", "HEAD").gsub("refs/heads/", "").strip - end - - def single_commit?(start_revision, end_revision) - git("rev-list", "--count", "#{start_revision}..#{end_revision}").to_i == 1 - end - - def diff_formulae(start_revision, end_revision, path, filter) - return unless @tap - git( - "diff-tree", "-r", "--name-only", "--diff-filter=#{filter}", - start_revision, end_revision, "--", path - ).lines.map do |line| - file = Pathname.new line.chomp - next unless @tap.formula_file?(file) - @tap.formula_file_to_name(file) - end.compact - end - - @category = __method__ - @start_branch = current_branch - - travis_pr = ENV["TRAVIS_PULL_REQUEST"] && ENV["TRAVIS_PULL_REQUEST"] != "false" - - # Use Jenkins GitHub Pull Request Builder plugin variables for - # pull request jobs. - if ENV["ghprbPullLink"] - @url = ENV["ghprbPullLink"] - @hash = nil - test "git", "checkout", "origin/master" - elsif ENV["GIT_URL"] && ENV["GIT_BRANCH"] - git_url = ENV["GIT_URL"].chomp("/").chomp(".git") - %r{origin/pr/(\d+)/(merge|head)} =~ ENV["GIT_BRANCH"] - pr = $1 - @url = "#{git_url}/pull/#{pr}" - @hash = nil - # Use Travis CI pull-request variables for pull request jobs. - elsif travis_pr - @url = "https://github.com/#{ENV["TRAVIS_REPO_SLUG"]}/pull/#{ENV["TRAVIS_PULL_REQUEST"]}" - @hash = nil - end - - # Use Jenkins Git plugin variables for master branch jobs. - if ENV["GIT_PREVIOUS_COMMIT"] && ENV["GIT_COMMIT"] - diff_start_sha1 = ENV["GIT_PREVIOUS_COMMIT"] - diff_end_sha1 = ENV["GIT_COMMIT"] - # Use Travis CI Git variables for master or branch jobs. - elsif ENV["TRAVIS_COMMIT_RANGE"] - diff_start_sha1, diff_end_sha1 = ENV["TRAVIS_COMMIT_RANGE"].split "..." - # Otherwise just use the current SHA-1 (which may be overriden later) - else - diff_end_sha1 = diff_start_sha1 = current_sha1 - end - - diff_start_sha1 = git("merge-base", diff_start_sha1, diff_end_sha1).strip - - # Handle no arguments being passed on the command-line e.g. `brew test-bot`. - if no_args? - if diff_start_sha1 == diff_end_sha1 || \ - single_commit?(diff_start_sha1, diff_end_sha1) - @name = diff_end_sha1 - else - @name = "#{diff_start_sha1}-#{diff_end_sha1}" - end - # Handle formulae arguments being passed on the command-line e.g. `brew test-bot wget fish`. - elsif !@formulae.empty? - @name = "#{@formulae.first}-#{diff_end_sha1}" - diff_start_sha1 = diff_end_sha1 - # Handle a hash being passed on the command-line e.g. `brew test-bot 1a2b3c`. - elsif @hash - test "git", "checkout", @hash - diff_start_sha1 = "#{@hash}^" - diff_end_sha1 = @hash - @name = @hash - # Handle a URL being passed on the command-line or through Jenkins/Travis - # environment variables e.g. - # `brew test-bot https://github.com/Homebrew/homebrew-core/pull/678`. - elsif @url - # TODO: in future Travis CI may need to also use `brew pull` to e.g. push - # the right commit to BrewTestBot. - if !travis_pr && !ARGV.include?("--no-pull") - diff_start_sha1 = current_sha1 - test "brew", "pull", "--clean", @url - diff_end_sha1 = current_sha1 - end - @short_url = @url.gsub("https://github.com/", "") - if @short_url.include? "/commit/" - # 7 characters should be enough for a commit (not 40). - @short_url.gsub!(%r{(commit/\w{7}).*/}, '\1') - @name = @short_url - else - @name = "#{@short_url}-#{diff_end_sha1}" - end - else - raise "Cannot set @name: invalid command-line arguments!" - end - - @log_root = @brewbot_root + @name - FileUtils.mkdir_p @log_root - - return unless diff_start_sha1 != diff_end_sha1 - return if @url && steps.last && !steps.last.passed? - - if @tap - formula_path = @tap.formula_dir.to_s - @added_formulae += diff_formulae(diff_start_sha1, diff_end_sha1, formula_path, "A") - @modified_formula += diff_formulae(diff_start_sha1, diff_end_sha1, formula_path, "M")\ - elsif @formulae.empty? && ARGV.include?("--test-default-formula") - # Build the default test formula. - HOMEBREW_CACHE_FORMULA.mkpath - testbottest = "#{HOMEBREW_LIBRARY}/Homebrew/test/testbottest.rb" - FileUtils.cp testbottest, HOMEBREW_CACHE_FORMULA - @test_default_formula = true - @added_formulae = [testbottest] - end - - @formulae += @added_formulae + @modified_formula - end - - def skip(formula_name) - puts "#{Tty.blue}==>#{Tty.white} SKIPPING: #{formula_name}#{Tty.reset}" - end - - def satisfied_requirements?(formula, spec, dependency = nil) - requirements = formula.send(spec).requirements - - unsatisfied_requirements = requirements.reject do |requirement| - satisfied = false - satisfied ||= requirement.satisfied? - satisfied ||= requirement.optional? - if !satisfied && requirement.default_formula? - default = Formula[requirement.default_formula] - satisfied = satisfied_requirements?(default, :stable, formula.full_name) - end - satisfied - end - - if unsatisfied_requirements.empty? - true - else - name = formula.full_name - name += " (#{spec})" unless spec == :stable - name += " (#{dependency} dependency)" if dependency - skip name - puts unsatisfied_requirements.map(&:message) - false - end - end - - def setup - @category = __method__ - return if ARGV.include? "--skip-setup" - if !ENV["TRAVIS"] && HOMEBREW_PREFIX.to_s == "/usr/local" - test "brew", "doctor" - end - test "brew", "--env" - test "brew", "config" - end - - def formula(formula_name) - @category = "#{__method__}.#{formula_name}" - - test "brew", "uses", formula_name - - formula = Formulary.factory(formula_name) - - installed_gcc = false - - deps = [] - reqs = [] - - fetch_args = [formula_name] - fetch_args << "--build-bottle" if !ARGV.include?("--fast") && !ARGV.include?("--no-bottle") && !formula.bottle_disabled? - fetch_args << "--force" if ARGV.include? "--cleanup" - - audit_args = [formula_name] - audit_args << "--new-formula" if @added_formulae.include? formula_name - - if formula.stable - unless satisfied_requirements?(formula, :stable) - test "brew", "fetch", "--retry", *fetch_args - test "brew", "audit", *audit_args - return - end - - deps |= formula.stable.deps.to_a.reject(&:optional?) - reqs |= formula.stable.requirements.to_a.reject(&:optional?) - elsif formula.devel - unless satisfied_requirements?(formula, :devel) - test "brew", "fetch", "--retry", "--devel", *fetch_args - test "brew", "audit", "--devel", *audit_args - return - end - end - - if formula.devel && !ARGV.include?("--HEAD") - deps |= formula.devel.deps.to_a.reject(&:optional?) - reqs |= formula.devel.requirements.to_a.reject(&:optional?) - end - - begin - deps.each { |d| d.to_formula.recursive_dependencies } - rescue TapFormulaUnavailableError => e - raise if e.tap.installed? - safe_system "brew", "tap", e.tap.name - retry - end - - begin - deps.each do |dep| - CompilerSelector.select_for(dep.to_formula) - end - CompilerSelector.select_for(formula) - rescue CompilerSelectionError => e - unless installed_gcc - run_as_not_developer { test "brew", "install", "gcc" } - installed_gcc = true - DevelopmentTools.clear_version_cache - retry - end - skip formula_name - puts e.message - return - end - - conflicts = formula.conflicts - formula.recursive_dependencies.each do |dependency| - conflicts += dependency.to_formula.conflicts - end - - conflicts.each do |conflict| - confict_formula = Formulary.factory(conflict.name) - - if confict_formula.installed? && confict_formula.linked_keg.exist? - test "brew", "unlink", "--force", conflict.name - end - end - - installed = Utils.popen_read("brew", "list").split("\n") - dependencies = Utils.popen_read("brew", "deps", "--include-build", formula_name).split("\n") - - (installed & dependencies).each do |installed_dependency| - installed_dependency_formula = Formulary.factory(installed_dependency) - next unless installed_dependency_formula.installed? - next if installed_dependency_formula.keg_only? - next if installed_dependency_formula.linked_keg.exist? - test "brew", "link", installed_dependency - end - - dependencies -= installed - unchanged_dependencies = dependencies - @formulae - changed_dependences = dependencies - unchanged_dependencies - - runtime_dependencies = Utils.popen_read("brew", "deps", formula_name).split("\n") - build_dependencies = dependencies - runtime_dependencies - unchanged_build_dependencies = build_dependencies - @formulae - - dependents = Utils.popen_read("brew", "uses", formula_name).split("\n") - dependents -= @formulae - dependents = dependents.map { |d| Formulary.factory(d) } - - bottled_dependents = dependents.select(&:bottled?) - testable_dependents = dependents.select { |d| d.bottled? && d.test_defined? } - - if (deps | reqs).any? { |d| d.name == "mercurial" && d.build? } - run_as_not_developer { test "brew", "install", "mercurial" } - end - - test "brew", "fetch", "--retry", *unchanged_dependencies unless unchanged_dependencies.empty? - - unless changed_dependences.empty? - test "brew", "fetch", "--retry", "--build-bottle", *changed_dependences - unless ARGV.include?("--fast") - # Install changed dependencies as new bottles so we don't have checksum problems. - test "brew", "install", "--build-bottle", *changed_dependences - # Run postinstall on them because the tested formula might depend on - # this step - test "brew", "postinstall", *changed_dependences - end - end - test "brew", "fetch", "--retry", *fetch_args - test "brew", "uninstall", "--force", formula_name if formula.installed? - - # shared_*_args are applied to both the main and --devel spec - shared_install_args = ["--verbose"] - shared_install_args << "--keep-tmp" if ARGV.keep_tmp? - # install_args is just for the main (stable, or devel if in a devel-only tap) spec - install_args = [] - install_args << "--build-bottle" if !ARGV.include?("--fast") && !ARGV.include?("--no-bottle") && !formula.bottle_disabled? - install_args << "--HEAD" if ARGV.include? "--HEAD" - - # Pass --devel or --HEAD to install in the event formulae lack stable. Supports devel-only/head-only. - # head-only should not have devel, but devel-only can have head. Stable can have all three. - if devel_only_tap? formula - install_args << "--devel" - formula_bottled = false - elsif head_only_tap? formula - install_args << "--HEAD" - formula_bottled = false - else - formula_bottled = formula.bottled? - end - - install_args.concat(shared_install_args) - install_args << formula_name - # Don't care about e.g. bottle failures for dependencies. - install_passed = false - run_as_not_developer do - if !ARGV.include?("--fast") || formula_bottled || formula.bottle_unneeded? - test "brew", "install", "--only-dependencies", *install_args unless dependencies.empty? - test "brew", "install", *install_args - install_passed = steps.last.passed? - end - end - test "brew", "style", formula_name - test "brew", "audit", *audit_args - if install_passed - if formula.stable? && !ARGV.include?("--fast") && !ARGV.include?("--no-bottle") && !formula.bottle_disabled? - bottle_args = ["--verbose", "--json", formula_name] - bottle_args << "--keep-old" if ARGV.include? "--keep-old" - bottle_args << "--skip-relocation" if ARGV.include? "--skip-relocation" - bottle_args << "--force-core-tap" if @test_default_formula - test "brew", "bottle", *bottle_args - bottle_step = steps.last - if bottle_step.passed? && bottle_step.output? - bottle_filename = - bottle_step.output.gsub(%r{.*(\./\S+#{Utils::Bottles.native_regex}).*}m, '\1') - bottle_json_filename = bottle_filename.gsub(/\.(\d+\.)?tar\.gz$/, ".json") - bottle_merge_args = ["--merge", "--write", "--no-commit", bottle_json_filename] - bottle_merge_args << "--keep-old" if ARGV.include? "--keep-old" - test "brew", "bottle", *bottle_merge_args - test "brew", "uninstall", "--force", formula_name - FileUtils.ln bottle_filename, HOMEBREW_CACHE/bottle_filename, force: true - @formulae.delete(formula_name) - unless unchanged_build_dependencies.empty? - test "brew", "uninstall", "--force", *unchanged_build_dependencies - unchanged_dependencies -= unchanged_build_dependencies - end - test "brew", "install", bottle_filename - end - end - shared_test_args = ["--verbose"] - shared_test_args << "--keep-tmp" if ARGV.keep_tmp? - test "brew", "test", formula_name, *shared_test_args if formula.test_defined? - bottled_dependents.each do |dependent| - unless dependent.installed? - test "brew", "fetch", "--retry", dependent.name - next if steps.last.failed? - conflicts = dependent.conflicts.map { |c| Formulary.factory(c.name) }.select(&:installed?) - dependent.recursive_dependencies.each do |dependency| - conflicts += dependency.to_formula.conflicts.map { |c| Formulary.factory(c.name) }.select(&:installed?) - end - conflicts.each do |conflict| - test "brew", "unlink", conflict.name - end - unless ARGV.include?("--fast") - run_as_not_developer { test "brew", "install", dependent.name } - next if steps.last.failed? - end - end - next unless dependent.installed? - test "brew", "linkage", "--test", dependent.name - if testable_dependents.include? dependent - test "brew", "test", "--verbose", dependent.name - end - end - test "brew", "uninstall", "--force", formula_name - end - - if formula.devel && formula.stable? \ - && !ARGV.include?("--HEAD") && !ARGV.include?("--fast") \ - && satisfied_requirements?(formula, :devel) - test "brew", "fetch", "--retry", "--devel", *fetch_args - run_as_not_developer do - test "brew", "install", "--devel", formula_name, *shared_install_args - end - devel_install_passed = steps.last.passed? - test "brew", "audit", "--devel", *audit_args - if devel_install_passed - test "brew", "test", "--devel", formula_name, *shared_test_args if formula.test_defined? - test "brew", "uninstall", "--devel", "--force", formula_name - end - end - test "brew", "uninstall", "--force", *unchanged_dependencies unless unchanged_dependencies.empty? - end - - def homebrew - @category = __method__ - return if @skip_homebrew - - if !@tap && (@formulae.empty? || @test_default_formula) - # TODO: try to fix this on Linux at some stage. - if OS.mac? - # test update from origin/master to current commit. - test "brew", "update-test" - # test no-op update from current commit (to current commit, a no-op). - test "brew", "update-test", "--commit=HEAD" - end - - test "brew", "style" - test "brew", "readall", "--syntax" - - coverage_args = [] - if ARGV.include?("--coverage") - if ENV["JENKINS_HOME"] - coverage_args << "--coverage" if OS.mac? && MacOS.version == :sierra - else - coverage_args << "--coverage" - end - end - - test "brew", "tests", "--no-compat" - test "brew", "tests", "--generic" - test "brew", "tests", "--official-cmd-taps", *coverage_args - - if OS.mac? - run_as_not_developer { test "brew", "tap", "caskroom/cask" } - test "brew", "cask-tests", *coverage_args - end - elsif @tap - test "brew", "style", @tap.name if @tap.name == "homebrew/core" - test "brew", "readall", "--aliases", @tap.name - end - end - - def cleanup_shared - git "gc", "--auto" - test "git", "clean", "-ffdx", "--exclude=Library/Taps" - - Tap.names.each do |tap| - next if tap == "homebrew/core" - next if tap == @tap.to_s - safe_system "brew", "untap", tap - end - - Dir.glob("#{HOMEBREW_PREFIX}/{Cellar,etc,var}/**/*").each do |file| - FileUtils.rm_rf file - end - safe_system "brew", "prune" - - unless @repository == HOMEBREW_REPOSITORY - HOMEBREW_REPOSITORY.cd do - safe_system "git", "checkout", "-f", "master" - safe_system "git", "reset", "--hard", "origin/master" - safe_system "git", "clean", "-ffdx", "--exclude=Library/Taps" - end - end - - Pathname.glob("#{HOMEBREW_LIBRARY}/Taps/*/*").each do |git_repo| - next if @repository == git_repo - git_repo.cd do - safe_system "git", "checkout", "-f", "master" - safe_system "git", "reset", "--hard", "origin/master" - end - end - end - - def cleanup_before - @category = __method__ - return unless ARGV.include? "--cleanup" - git "stash" - git "am", "--abort" - git "rebase", "--abort" - unless ARGV.include? "--no-pull" - git "checkout", "-f", "master" - git "reset", "--hard", "origin/master" - end - - cleanup_shared - - pr_locks = "#{@repository}/.git/refs/remotes/*/pr/*/*.lock" - Dir.glob(pr_locks) { |lock| FileUtils.rm_rf lock } - end - - def cleanup_after - @category = __method__ - - if @start_branch && !@start_branch.empty? && \ - (ARGV.include?("--cleanup") || @url || @hash) - checkout_args = [@start_branch] - checkout_args << "-f" if ARGV.include? "--cleanup" - test "git", "checkout", *checkout_args - end - - if ARGV.include? "--cleanup" - git "reset", "--hard", "origin/master" - git "stash", "pop" - test "brew", "cleanup", "--prune=7" - - cleanup_shared - - if ARGV.include? "--local" - FileUtils.rm_rf ENV["HOMEBREW_HOME"] - FileUtils.rm_rf ENV["HOMEBREW_LOGS"] - end - end - - FileUtils.rm_rf @brewbot_root unless ARGV.include? "--keep-logs" - end - - def test(*args) - options = args.last.is_a?(Hash) ? args.pop : {} - options[:repository] = @repository - step = Step.new self, args, options - step.run - steps << step - step - end - - def check_results - steps.all? do |step| - case step.status - when :passed then true - when :running then raise - when :failed then false - end - end - end - - def formulae - changed_formulae_dependents = {} - - @formulae.each do |formula| - formula_dependencies = Utils.popen_read("brew", "deps", "--full-name", "--include-build", formula).split("\n") - unchanged_dependencies = formula_dependencies - @formulae - changed_dependences = formula_dependencies - unchanged_dependencies - changed_dependences.each do |changed_formula| - changed_formulae_dependents[changed_formula] ||= 0 - changed_formulae_dependents[changed_formula] += 1 - end - end - - changed_formulae = changed_formulae_dependents.sort do |a1, a2| - a2[1].to_i <=> a1[1].to_i - end - changed_formulae.map!(&:first) - unchanged_formulae = @formulae - changed_formulae - changed_formulae + unchanged_formulae - end - - def head_only_tap?(formula) - formula.head && formula.devel.nil? && formula.stable.nil? && formula.tap == "homebrew/homebrew-head-only" - end - - def devel_only_tap?(formula) - formula.devel && formula.stable.nil? && formula.tap == "homebrew/homebrew-devel-only" - end - - def run - cleanup_before - begin - download - setup - homebrew - formulae.each do |f| - formula(f) - end - ensure - cleanup_after - end - check_results - end - end - - def test_ci_upload(tap) - # Don't trust formulae we're uploading - ENV["HOMEBREW_DISABLE_LOAD_FORMULA"] = "1" - - bintray_user = ENV["BINTRAY_USER"] - bintray_key = ENV["BINTRAY_KEY"] - if !bintray_user || !bintray_key - raise "Missing BINTRAY_USER or BINTRAY_KEY variables!" - end - - # Don't pass keys/cookies to subprocesses - ENV["BINTRAY_KEY"] = nil - ENV["HUDSON_SERVER_COOKIE"] = nil - ENV["JENKINS_SERVER_COOKIE"] = nil - ENV["HUDSON_COOKIE"] = nil - ENV["COVERALLS_REPO_TOKEN"] = nil - - ARGV << "--verbose" - - bottles = Dir["*.bottle*.*"] - if bottles.empty? - jenkins = ENV["JENKINS_HOME"] - job = ENV["UPSTREAM_JOB_NAME"] - id = ENV["UPSTREAM_BUILD_ID"] - raise "Missing Jenkins variables!" if !jenkins || !job || !id - - bottles = Dir["#{jenkins}/jobs/#{job}/configurations/axis-version/*/builds/#{id}/archive/*.bottle*.*"] - return if bottles.empty? - - FileUtils.cp bottles, Dir.pwd, verbose: true - end - - json_files = Dir.glob("*.bottle.json") - bottles_hash = json_files.reduce({}) do |hash, json_file| - deep_merge_hashes hash, Utils::JSON.load(IO.read(json_file)) - end - - first_formula_name = bottles_hash.keys.first - tap = Tap.fetch(first_formula_name.rpartition("/").first.chuzzle || "homebrew/core") - - ENV["GIT_AUTHOR_NAME"] = ENV["GIT_COMMITTER_NAME"] = "BrewTestBot" - ENV["GIT_AUTHOR_EMAIL"] = ENV["GIT_COMMITTER_EMAIL"] = "brew-test-bot@googlegroups.com" - ENV["GIT_WORK_TREE"] = tap.path - ENV["GIT_DIR"] = "#{ENV["GIT_WORK_TREE"]}/.git" - - quiet_system "git", "am", "--abort" - quiet_system "git", "rebase", "--abort" - safe_system "git", "checkout", "-f", "master" - safe_system "git", "reset", "--hard", "origin/master" - safe_system "brew", "update" - - if (pr = ENV["UPSTREAM_PULL_REQUEST"]) - pull_pr = "https://github.com/#{tap.user}/homebrew-#{tap.repo}/pull/#{pr}" - safe_system "brew", "pull", "--clean", pull_pr - end - - if ENV["UPSTREAM_BOTTLE_KEEP_OLD"] || ENV["BOT_PARAMS"].to_s.include?("--keep-old") - system "brew", "bottle", "--merge", "--write", "--keep-old", *json_files - else - system "brew", "bottle", "--merge", "--write", *json_files - end - - remote = "git@github.com:BrewTestBot/homebrew-#{tap.repo}.git" - git_tag = if pr - "pr-#{pr}" - elsif (upstream_number = ENV["UPSTREAM_BUILD_NUMBER"]) - "testing-#{upstream_number}" - elsif (number = ENV["BUILD_NUMBER"]) - "other-#{number}" - end - if git_tag - safe_system "git", "push", "--force", remote, "master:master", ":refs/tags/#{git_tag}" - end - - formula_packaged = {} - - bottles_hash.each do |formula_name, bottle_hash| - version = bottle_hash["formula"]["pkg_version"] - bintray_package = bottle_hash["bintray"]["package"] - bintray_repo = bottle_hash["bintray"]["repository"] - bintray_repo_url = "https://api.bintray.com/packages/homebrew/#{bintray_repo}" - - bottle_hash["bottle"]["tags"].each do |_tag, tag_hash| - filename = tag_hash["filename"] - if system "curl", "-I", "--silent", "--fail", "--output", "/dev/null", - "#{BottleSpecification::DEFAULT_DOMAIN}/#{bintray_repo}/#{filename}" - raise <<-EOS.undent - #{filename} is already published. Please remove it manually from - https://bintray.com/homebrew/#{bintray_repo}/#{bintray_package}/view#files - EOS - end - - unless formula_packaged[formula_name] - package_url = "#{bintray_repo_url}/#{bintray_package}" - unless system "curl", "--silent", "--fail", "--output", "/dev/null", package_url - package_blob = <<-EOS.undent - {"name": "#{bintray_package}", - "public_download_numbers": true, - "public_stats": true} - EOS - curl "--silent", "--fail", "-u#{bintray_user}:#{bintray_key}", - "-H", "Content-Type: application/json", - "-d", package_blob, bintray_repo_url - puts - end - formula_packaged[formula_name] = true - end - - content_url = "https://api.bintray.com/content/homebrew" - content_url += "/#{bintray_repo}/#{bintray_package}/#{version}/#{filename}" - content_url += "?override=1" - curl "--silent", "--fail", "-u#{bintray_user}:#{bintray_key}", - "-T", filename, content_url - puts - end - end - - return unless git_tag - safe_system "git", "tag", "--force", git_tag - safe_system "git", "push", "--force", remote, "master:master", "refs/tags/#{git_tag}" - end - - def sanitize_argv_and_env - if Pathname.pwd == HOMEBREW_PREFIX && ARGV.include?("--cleanup") - odie "cannot use --cleanup from HOMEBREW_PREFIX as it will delete all output." - end - - ENV["HOMEBREW_DEVELOPER"] = "1" - ENV["HOMEBREW_SANDBOX"] = "1" - ENV["HOMEBREW_NO_EMOJI"] = "1" - ENV["HOMEBREW_FAIL_LOG_LINES"] = "150" - ENV["HOMEBREW_EXPERIMENTAL_FILTER_FLAGS_ON_DEPS"] = "1" - ENV["PATH"] = "#{HOMEBREW_PREFIX}/bin:#{HOMEBREW_PREFIX}/sbin:#{ENV["PATH"]}" - - travis = !ENV["TRAVIS"].nil? - if travis - ARGV << "--verbose" - ENV["HOMEBREW_VERBOSE_USING_DOTS"] = "1" - end - - # Only report coverage if build runs on macOS and this is indeed Homebrew, - # as we don't want this to be averaged with inferior Linux test coverage. - if OS.mac? && (ENV["COVERALLS_REPO_TOKEN"] || ENV["CODECOV_TOKEN"]) - ARGV << "--coverage" - end - - travis_pr = ENV["TRAVIS_PULL_REQUEST"] && ENV["TRAVIS_PULL_REQUEST"] != "false" - jenkins_pr = !ENV["ghprbPullLink"].nil? - jenkins_branch = !ENV["GIT_COMMIT"].nil? - - if ARGV.include?("--ci-auto") - if travis_pr || jenkins_pr - ARGV << "--ci-pr" - elsif travis || jenkins_branch - ARGV << "--ci-master" - else - ARGV << "--ci-testing" - end - end - - if ARGV.include?("--ci-master") || ARGV.include?("--ci-pr") \ - || ARGV.include?("--ci-testing") - ARGV << "--cleanup" if ENV["JENKINS_HOME"] - ARGV << "--junit" << "--local" << "--test-default-formula" - end - - ARGV << "--fast" if ARGV.include?("--ci-master") - - return unless ARGV.include?("--local") - ENV["HOMEBREW_CACHE"] = "#{ENV["HOME"]}/Library/Caches/Homebrew" - mkdir_p ENV["HOMEBREW_CACHE"] - ENV["HOMEBREW_HOME"] = ENV["HOME"] = "#{Dir.pwd}/home" - mkdir_p ENV["HOME"] - ENV["HOMEBREW_LOGS"] = "#{Dir.pwd}/logs" - end - - def test_bot - sanitize_argv_and_env - - tap = resolve_test_tap - # Tap repository if required, this is done before everything else - # because Formula parsing and/or git commit hash lookup depends on it. - # At the same time, make sure Tap is not a shallow clone. - # bottle rebuild and bottle upload rely on full clone. - if tap - ENV["HOMEBREW_UPDATE_TO_TAG"] = "1" - safe_system "brew", "tap", tap.name, "--full" - end - - return test_ci_upload(tap) if ARGV.include?("--ci-upload") - - tests = [] - any_errors = false - skip_homebrew = ARGV.include?("--skip-homebrew") - if ARGV.named.empty? - # With no arguments just build the most recent commit. - current_test = Test.new("HEAD", tap: tap, skip_homebrew: skip_homebrew) - any_errors = !current_test.run - tests << current_test - else - ARGV.named.each do |argument| - test_error = false - begin - current_test = Test.new(argument, tap: tap, skip_homebrew: skip_homebrew) - skip_homebrew = true - rescue ArgumentError => e - test_error = true - ofail e.message - else - test_error = !current_test.run - tests << current_test - end - any_errors ||= test_error - end - end - - if ARGV.include? "--junit" - xml_document = REXML::Document.new - xml_document << REXML::XMLDecl.new - testsuites = xml_document.add_element "testsuites" - - tests.each do |test| - testsuite = testsuites.add_element "testsuite" - testsuite.add_attribute "name", "brew-test-bot.#{Utils::Bottles.tag}" - testsuite.add_attribute "tests", test.steps.count - - test.steps.each do |step| - testcase = testsuite.add_element "testcase" - testcase.add_attribute "name", step.command_short - testcase.add_attribute "status", step.status - testcase.add_attribute "time", step.time - - next unless step.output? - output = sanitize_output_for_xml(step.output) - cdata = REXML::CData.new output - - if step.passed? - elem = testcase.add_element "system-out" - else - elem = testcase.add_element "failure" - elem.add_attribute "message", "#{step.status}: #{step.command.join(" ")}" - end - - elem << cdata - end - end - - open("brew-test-bot.xml", "w") do |xml_file| - pretty_print_indent = 2 - xml_document.write(xml_file, pretty_print_indent) - end - end - ensure - if ARGV.include? "--clean-cache" - HOMEBREW_CACHE.children.each(&:rmtree) - else - Dir.glob("*.bottle*.tar.gz") do |bottle_file| - FileUtils.rm_f HOMEBREW_CACHE/bottle_file - end - end - - Homebrew.failed = any_errors - end - - def sanitize_output_for_xml(output) - unless output.empty? - # Remove invalid XML CData characters from step output. - invalid_xml_pat = /[^\x09\x0A\x0D\x20-\uD7FF\uE000-\uFFFD\u{10000}-\u{10FFFF}]/ - output = output.gsub(invalid_xml_pat, "\uFFFD") - - # Truncate to 1MB to avoid hitting CI limits - if output.bytesize > MAX_STEP_OUTPUT_SIZE - output = truncate_text_to_approximate_size(output, MAX_STEP_OUTPUT_SIZE, front_weight: 0.0) - output = "truncated output to 1MB:\n" + output - end - end - output - end -end -- cgit v1.2.3