Merge branch 'master' into license
This commit is contained in:
commit
5f6917ae7c
@ -91,7 +91,7 @@ GEM
|
||||
rubocop-ast (>= 0.0.3, < 1.0)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (>= 1.4.0, < 2.0)
|
||||
rubocop-ast (0.0.3)
|
||||
rubocop-ast (0.1.0)
|
||||
parser (>= 2.7.0.1)
|
||||
rubocop-performance (1.6.1)
|
||||
rubocop (>= 0.71.0)
|
||||
|
@ -22,9 +22,9 @@ module Homebrew
|
||||
switch "--force-bottle",
|
||||
description: "Show the cache file used when pouring a bottle."
|
||||
switch "--formula",
|
||||
description: "Show cache files for only formulae"
|
||||
description: "Only show cache files for formulae."
|
||||
switch "--cask",
|
||||
description: "Show cache files for only casks"
|
||||
description: "Only show cache files for casks."
|
||||
conflicts "--build-from-source", "--force-bottle"
|
||||
conflicts "--formula", "--cask"
|
||||
end
|
||||
|
@ -267,6 +267,7 @@ module Homebrew
|
||||
# Need to rescue before `FormulaUnavailableError` (superclass of this)
|
||||
# is handled, as searching for a formula doesn't make sense here (the
|
||||
# formula was found, but there's a problem with its implementation).
|
||||
$stderr.puts e.backtrace if Homebrew::EnvConfig.developer?
|
||||
ofail e.message
|
||||
rescue FormulaUnavailableError => e
|
||||
if e.name == "updog"
|
||||
|
@ -172,14 +172,6 @@ module Homebrew
|
||||
@text.split("\n__END__").first
|
||||
end
|
||||
|
||||
def data?
|
||||
/^[^#]*\bDATA\b/ =~ @text
|
||||
end
|
||||
|
||||
def end?
|
||||
/^__END__$/ =~ @text
|
||||
end
|
||||
|
||||
def trailing_newline?
|
||||
/\Z\n/ =~ @text
|
||||
end
|
||||
@ -239,12 +231,6 @@ module Homebrew
|
||||
end
|
||||
|
||||
def audit_file
|
||||
# TODO: check could be in RuboCop
|
||||
problem "'DATA' was found, but no '__END__'" if text.data? && !text.end?
|
||||
|
||||
# TODO: check could be in RuboCop
|
||||
problem "'__END__' was found, but 'DATA' is not used" if text.end? && !text.data?
|
||||
|
||||
# TODO: check could be in RuboCop
|
||||
if text.to_s.match?(/inreplace [^\n]* do [^\n]*\n[^\n]*\.gsub![^\n]*\n\ *end/m)
|
||||
problem "'inreplace ... do' was used for a single substitution (use the non-block form instead)."
|
||||
|
@ -23,6 +23,8 @@ module Homebrew
|
||||
description: "Create a basic template for an Autotools-style build."
|
||||
switch "--cmake",
|
||||
description: "Create a basic template for a CMake-style build."
|
||||
switch "--crystal",
|
||||
description: "Create a basic template for a Crystal build."
|
||||
switch "--go",
|
||||
description: "Create a basic template for a Go build."
|
||||
switch "--meson",
|
||||
@ -52,7 +54,7 @@ module Homebrew
|
||||
switch :force
|
||||
switch :verbose
|
||||
switch :debug
|
||||
conflicts "--autotools", "--cmake", "--go", "--meson", "--perl", "--python", "--rust"
|
||||
conflicts "--autotools", "--cmake", "--crystal", "--go", "--meson", "--perl", "--python", "--rust"
|
||||
named 1
|
||||
end
|
||||
end
|
||||
@ -86,6 +88,8 @@ module Homebrew
|
||||
:autotools
|
||||
elsif args.meson?
|
||||
:meson
|
||||
elsif args.crystal?
|
||||
:crystal
|
||||
elsif args.go?
|
||||
:go
|
||||
elsif args.perl?
|
||||
|
@ -14,9 +14,9 @@ module Homebrew
|
||||
Reupload the stable URL of a formula to Bintray for use as a mirror.
|
||||
EOS
|
||||
flag "--bintray-org=",
|
||||
description: "Upload to the specified Bintray organisation (default: homebrew)."
|
||||
description: "Upload to the specified Bintray organisation (default: `homebrew`)."
|
||||
flag "--bintray-repo=",
|
||||
description: "Upload to the specified Bintray repository (default: mirror)."
|
||||
description: "Upload to the specified Bintray repository (default: `mirror`)."
|
||||
switch "--no-publish",
|
||||
description: "Upload to Bintray, but don't publish."
|
||||
switch :verbose
|
||||
|
@ -34,18 +34,18 @@ module Homebrew
|
||||
description: "When a patch fails to apply, leave in progress and allow user to resolve, "\
|
||||
"instead of aborting."
|
||||
flag "--workflow=",
|
||||
description: "Retrieve artifacts from the specified workflow (default: tests.yml)."
|
||||
description: "Retrieve artifacts from the specified workflow (default: `tests.yml`)."
|
||||
flag "--artifact=",
|
||||
description: "Download artifacts with the specified name (default: bottles)."
|
||||
description: "Download artifacts with the specified name (default: `bottles`)."
|
||||
flag "--bintray-org=",
|
||||
description: "Upload to the specified Bintray organisation (default: homebrew)."
|
||||
description: "Upload to the specified Bintray organisation (default: `homebrew`)."
|
||||
flag "--tap=",
|
||||
description: "Target tap repository (default: homebrew/core)."
|
||||
description: "Target tap repository (default: `homebrew/core`)."
|
||||
flag "--root-url=",
|
||||
description: "Use the specified <URL> as the root of the bottle's URL instead of Homebrew's default."
|
||||
flag "--bintray-mirror=",
|
||||
description: "Use the specified Bintray repository to automatically mirror stable URLs "\
|
||||
"defined in the formulae (default: mirror)"
|
||||
"defined in the formulae (default: `mirror`)."
|
||||
switch :verbose
|
||||
switch :debug
|
||||
min_named 1
|
||||
|
@ -15,10 +15,10 @@ module Homebrew
|
||||
EOS
|
||||
switch "--no-publish",
|
||||
description: "Apply the bottle commit and upload the bottles, but don't publish them."
|
||||
switch "--dry-run", "-n",
|
||||
switch "-n", "--dry-run",
|
||||
description: "Print what would be done rather than doing it."
|
||||
flag "--bintray-org=",
|
||||
description: "Upload to the specified Bintray organisation (default: homebrew)."
|
||||
description: "Upload to the specified Bintray organisation (default: `homebrew`)."
|
||||
flag "--root-url=",
|
||||
description: "Use the specified <URL> as the root of the bottle's URL instead of Homebrew's default."
|
||||
switch :verbose
|
||||
|
@ -27,6 +27,7 @@ class Keg
|
||||
# patchelf requires that the ELF file have a .dynstr section.
|
||||
# Skip ELF files that do not have a .dynstr section.
|
||||
return if ["cannot find section .dynstr", "strange: no string table"].include?(old_rpath)
|
||||
|
||||
unless $CHILD_STATUS.success?
|
||||
raise ErrorDuringExecution.new(cmd_rpath, status: $CHILD_STATUS, output: [[:stderr, old_rpath]])
|
||||
end
|
||||
@ -41,15 +42,15 @@ class Keg
|
||||
new_rpath = rpath.join(":")
|
||||
cmd = [patchelf, "--force-rpath", "--set-rpath", new_rpath]
|
||||
|
||||
if file.with_interpreter?
|
||||
old_interpreter = Utils.safe_popen_read(patchelf, "--print-interpreter", file).strip
|
||||
new_interpreter = if File.readable? "#{new_prefix}/lib/ld.so"
|
||||
old_interpreter = file.interpreter
|
||||
new_interpreter = if old_interpreter.nil?
|
||||
nil
|
||||
elsif File.readable? "#{new_prefix}/lib/ld.so"
|
||||
"#{new_prefix}/lib/ld.so"
|
||||
else
|
||||
old_interpreter.sub old_prefix, new_prefix
|
||||
end
|
||||
cmd << "--set-interpreter" << new_interpreter if old_interpreter != new_interpreter
|
||||
end
|
||||
|
||||
return if old_rpath == new_rpath && old_interpreter == new_interpreter
|
||||
|
||||
|
@ -104,6 +104,8 @@ module Homebrew
|
||||
|
||||
<% if mode == :cmake %>
|
||||
depends_on "cmake" => :build
|
||||
<% elsif mode == :crystal %>
|
||||
depends_on "crystal" => :build
|
||||
<% elsif mode == :go %>
|
||||
depends_on "go" => :build
|
||||
<% elsif mode == :meson %>
|
||||
@ -139,6 +141,9 @@ module Homebrew
|
||||
"--disable-dependency-tracking",
|
||||
"--disable-silent-rules",
|
||||
"--prefix=\#{prefix}"
|
||||
<% elsif mode == :crystal %>
|
||||
system "shards", "build", "--release"
|
||||
bin.install "bin/#{name}"
|
||||
<% elsif mode == :go %>
|
||||
system "go", "build", *std_go_args
|
||||
<% elsif mode == :meson %>
|
||||
|
@ -35,6 +35,7 @@ module Formulary
|
||||
begin
|
||||
mod.module_eval(contents, path)
|
||||
rescue NameError, ArgumentError, ScriptError => e
|
||||
$stderr.puts e.backtrace if Homebrew::EnvConfig.developer?
|
||||
raise FormulaUnreadableError.new(name, e)
|
||||
end
|
||||
class_name = class_s(name)
|
||||
|
@ -103,7 +103,7 @@ module Homebrew
|
||||
help_lines = command_help_lines(path)
|
||||
return if help_lines.blank?
|
||||
|
||||
Formatter.wrap(help_lines.join.delete_prefix(" "), COMMAND_DESC_WIDTH)
|
||||
Formatter.wrap(help_lines.join, COMMAND_DESC_WIDTH)
|
||||
.sub("@hide_from_man_page ", "")
|
||||
.sub(/^\* /, "#{Tty.bold}Usage: brew#{Tty.reset} ")
|
||||
.gsub(/`(.*?)`/m, "#{Tty.bold}\\1#{Tty.reset}")
|
||||
|
@ -68,28 +68,24 @@ module ELFShim
|
||||
elf_type == :executable
|
||||
end
|
||||
|
||||
def with_interpreter?
|
||||
return @with_interpreter if defined? @with_interpreter
|
||||
def interpreter
|
||||
return @interpreter if defined? @interpreter
|
||||
|
||||
@with_interpreter = if binary_executable?
|
||||
true
|
||||
elsif dylib?
|
||||
if HOMEBREW_PATCHELF_RB
|
||||
@interpreter = if HOMEBREW_PATCHELF_RB
|
||||
begin
|
||||
patchelf_patcher.interpreter.present?
|
||||
patchelf_patcher.interpreter
|
||||
rescue PatchELF::PatchError => e
|
||||
opoo e unless e.to_s.start_with? "No interpreter found"
|
||||
false
|
||||
nil
|
||||
end
|
||||
elsif which "readelf"
|
||||
Utils.popen_read("readelf", "-l", to_path).include?(" INTERP ")
|
||||
elsif which "file"
|
||||
Utils.popen_read("file", "-L", "-b", to_path).include?(" interpreter ")
|
||||
elsif (patchelf = DevelopmentTools.locate "patchelf")
|
||||
interp = Utils.popen_read(patchelf, "--print-interpreter", to_s, err: :out).strip
|
||||
$CHILD_STATUS.success? ? interp : nil
|
||||
elsif (file = DevelopmentTools.locate("file"))
|
||||
output = Utils.popen_read(file, "-L", "-b", to_s, err: :out).strip
|
||||
output[/^ELF.*, interpreter (.+?), /, 1]
|
||||
else
|
||||
raise "Please install either readelf (from binutils) or file."
|
||||
end
|
||||
else
|
||||
false
|
||||
raise "Please install either patchelf or file."
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -22,5 +22,6 @@ require "rubocops/uses_from_macos"
|
||||
require "rubocops/files"
|
||||
require "rubocops/keg_only"
|
||||
require "rubocops/version"
|
||||
require "rubocops/deprecate"
|
||||
|
||||
require "rubocops/rubocop-cask"
|
||||
|
35
Library/Homebrew/rubocops/deprecate.rb
Normal file
35
Library/Homebrew/rubocops/deprecate.rb
Normal file
@ -0,0 +1,35 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "rubocops/extend/formula"
|
||||
|
||||
module RuboCop
|
||||
module Cop
|
||||
module FormulaAudit
|
||||
# This cop audits deprecate!
|
||||
class Deprecate < FormulaCop
|
||||
def audit_formula(_node, _class_node, _parent_class_node, body_node)
|
||||
deprecate_node = find_node_method_by_name(body_node, :deprecate!)
|
||||
|
||||
return if deprecate_node.nil? || deprecate_node.children.length < 3
|
||||
|
||||
date_node = find_strings(deprecate_node).first
|
||||
|
||||
begin
|
||||
Date.iso8601(string_content(date_node))
|
||||
rescue ArgumentError
|
||||
fixed_date_string = Date.parse(string_content(date_node)).iso8601
|
||||
offending_node(date_node)
|
||||
problem "Use `#{fixed_date_string}` to comply with ISO 8601"
|
||||
end
|
||||
end
|
||||
|
||||
def autocorrect(node)
|
||||
lambda do |corrector|
|
||||
fixed_fixed_date_string = Date.parse(string_content(node)).iso8601
|
||||
corrector.replace(node.source_range, "\"#{fixed_fixed_date_string}\"")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -495,7 +495,15 @@ module RuboCop
|
||||
when :str
|
||||
node.str_content
|
||||
when :dstr
|
||||
node.each_child_node(:str).map(&:str_content).join
|
||||
content = ""
|
||||
node.each_child_node(:str, :begin) do |child|
|
||||
content += if child.begin_type?
|
||||
child.source
|
||||
else
|
||||
child.str_content
|
||||
end
|
||||
end
|
||||
content
|
||||
when :const
|
||||
node.const_name
|
||||
when :sym
|
||||
|
@ -195,7 +195,7 @@ module RuboCop
|
||||
end
|
||||
end
|
||||
|
||||
class ShellCmd < FormulaCop
|
||||
class SafePopenCommands < FormulaCop
|
||||
def audit_formula(_node, _class_node, _parent_class_node, body_node)
|
||||
test = find_block(body_node, :test)
|
||||
|
||||
@ -223,6 +223,35 @@ module RuboCop
|
||||
end
|
||||
end
|
||||
|
||||
class ShellVariables < FormulaCop
|
||||
def audit_formula(_node, _class_node, _parent_class_node, body_node)
|
||||
popen_commands = [
|
||||
:popen,
|
||||
:popen_read,
|
||||
:safe_popen_read,
|
||||
:popen_write,
|
||||
:safe_popen_write,
|
||||
]
|
||||
|
||||
popen_commands.each do |command|
|
||||
find_instance_method_call(body_node, "Utils", command) do |method|
|
||||
next unless match = regex_match_group(parameters(method).first, /^([^"' ]+)=([^"' ]+)(?: (.*))?$/)
|
||||
|
||||
good_args = "Utils.#{command}({ \"#{match[1]}\" => \"#{match[2]}\" }, \"#{match[3]}\")"
|
||||
|
||||
problem "Use `#{good_args}` instead of `#{method.source}`"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def autocorrect(node)
|
||||
lambda do |corrector|
|
||||
match = regex_match_group(node, /^([^"' ]+)=([^"' ]+)(?: (.*))?$/)
|
||||
corrector.replace(node.source_range, "{ \"#{match[1]}\" => \"#{match[2]}\" }, \"#{match[3]}\"")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Miscellaneous < FormulaCop
|
||||
def audit_formula(_node, _class_node, _parent_class_node, body_node)
|
||||
# FileUtils is included in Formula
|
||||
|
@ -8,7 +8,9 @@ module RuboCop
|
||||
module FormulaAudit
|
||||
# This cop audits patches in Formulae.
|
||||
class Patches < FormulaCop
|
||||
def audit_formula(_node, _class_node, _parent_class_node, body)
|
||||
def audit_formula(node, _class_node, _parent_class_node, body)
|
||||
@full_source_content = source_buffer(node).source
|
||||
|
||||
external_patches = find_all_blocks(body, :patch)
|
||||
external_patches.each do |patch_block|
|
||||
url_node = find_every_method_call_by_name(patch_block, :url).first
|
||||
@ -16,6 +18,14 @@ module RuboCop
|
||||
patch_problems(url_string)
|
||||
end
|
||||
|
||||
inline_patches = find_every_method_call_by_name(body, :patch)
|
||||
inline_patches.each { |patch| inline_patch_problems(patch) }
|
||||
|
||||
if inline_patches.empty? && patch_end?
|
||||
offending_patch_end_node(node)
|
||||
problem "patch is missing 'DATA'"
|
||||
end
|
||||
|
||||
patches_node = find_method_def(body, :patches)
|
||||
return if patches_node.nil?
|
||||
|
||||
@ -84,6 +94,30 @@ module RuboCop
|
||||
#{patch_url}
|
||||
EOS
|
||||
end
|
||||
|
||||
def inline_patch_problems(patch)
|
||||
return unless patch_data?(patch) && !patch_end?
|
||||
|
||||
offending_node(patch)
|
||||
problem "patch is missing '__END__'"
|
||||
end
|
||||
|
||||
def_node_search :patch_data?, <<~AST
|
||||
(send nil? :patch (:sym :DATA))
|
||||
AST
|
||||
|
||||
def patch_end?
|
||||
/^__END__$/.match?(@full_source_content)
|
||||
end
|
||||
|
||||
def offending_patch_end_node(node)
|
||||
@offensive_node = node
|
||||
@source_buf = source_buffer(node)
|
||||
@line_no = node.loc.last_line + 1
|
||||
@column = 0
|
||||
@length = 7 # "__END__".size
|
||||
@offense_source_range = source_range(@source_buf, @line_no, @column, @length)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -41,8 +41,6 @@ module Homebrew
|
||||
url "https://www.brew.sh/valid-1.0.tar.gz"
|
||||
RUBY
|
||||
|
||||
expect(ft).not_to have_data
|
||||
expect(ft).not_to have_end
|
||||
expect(ft).to have_trailing_newline
|
||||
|
||||
expect(ft =~ /\burl\b/).to be_truthy
|
||||
@ -55,20 +53,6 @@ module Homebrew
|
||||
ft = formula_text "newline"
|
||||
expect(ft).to have_trailing_newline
|
||||
end
|
||||
|
||||
specify "#data?" do
|
||||
ft = formula_text "data", <<~RUBY
|
||||
patch :DATA
|
||||
RUBY
|
||||
|
||||
expect(ft).to have_data
|
||||
end
|
||||
|
||||
specify "#end?" do
|
||||
ft = formula_text "end", "", patch: "__END__\na patch here"
|
||||
expect(ft).to have_end
|
||||
expect(ft.without_patch).to eq("class End < Formula\n \nend")
|
||||
end
|
||||
end
|
||||
|
||||
describe FormulaAuditor do
|
||||
@ -186,31 +170,6 @@ module Homebrew
|
||||
end
|
||||
|
||||
describe "#audit_file" do
|
||||
specify "DATA but no __END__" do
|
||||
fa = formula_auditor "foo", <<~RUBY
|
||||
class Foo < Formula
|
||||
url "https://brew.sh/foo-1.0.tgz"
|
||||
patch :DATA
|
||||
end
|
||||
RUBY
|
||||
|
||||
fa.audit_file
|
||||
expect(fa.problems).to eq(["'DATA' was found, but no '__END__'"])
|
||||
end
|
||||
|
||||
specify "__END__ but no DATA" do
|
||||
fa = formula_auditor "foo", <<~RUBY
|
||||
class Foo < Formula
|
||||
url "https://brew.sh/foo-1.0.tgz"
|
||||
end
|
||||
__END__
|
||||
a patch goes here
|
||||
RUBY
|
||||
|
||||
fa.audit_file
|
||||
expect(fa.problems).to eq(["'__END__' was found, but 'DATA' is not used"])
|
||||
end
|
||||
|
||||
specify "no issue" do
|
||||
fa = formula_auditor "foo", <<~RUBY
|
||||
class Foo < Formula
|
||||
|
56
Library/Homebrew/test/rubocops/deprecate_spec.rb
Normal file
56
Library/Homebrew/test/rubocops/deprecate_spec.rb
Normal file
@ -0,0 +1,56 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "rubocops/deprecate"
|
||||
|
||||
describe RuboCop::Cop::FormulaAudit::Deprecate do
|
||||
subject(:cop) { described_class.new }
|
||||
|
||||
context "When auditing formula for deprecate!" do
|
||||
it "deprecation date is not ISO 8601 compliant" do
|
||||
expect_offense(<<~RUBY)
|
||||
class Foo < Formula
|
||||
url 'https://brew.sh/foo-1.0.tgz'
|
||||
deprecate! :date => "June 25, 2020"
|
||||
^^^^^^^^^^^^^^^ Use `2020-06-25` to comply with ISO 8601
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "deprecation date is ISO 8601 compliant" do
|
||||
expect_no_offenses(<<~RUBY)
|
||||
class Foo < Formula
|
||||
url 'https://brew.sh/foo-1.0.tgz'
|
||||
deprecate! :date => "2020-06-25"
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "no deprecation date" do
|
||||
expect_no_offenses(<<~RUBY)
|
||||
class Foo < Formula
|
||||
url 'https://brew.sh/foo-1.0.tgz'
|
||||
deprecate!
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "auto corrects to ISO 8601 format" do
|
||||
source = <<~RUBY
|
||||
class Foo < Formula
|
||||
url 'https://brew.sh/foo-1.0.tgz'
|
||||
deprecate! :date => "June 25, 2020"
|
||||
end
|
||||
RUBY
|
||||
|
||||
corrected_source = <<~RUBY
|
||||
class Foo < Formula
|
||||
url 'https://brew.sh/foo-1.0.tgz'
|
||||
deprecate! :date => "2020-06-25"
|
||||
end
|
||||
RUBY
|
||||
|
||||
new_source = autocorrect_source(source)
|
||||
expect(new_source).to eq(corrected_source)
|
||||
end
|
||||
end
|
||||
end
|
@ -345,10 +345,10 @@ describe RuboCop::Cop::FormulaAudit::MpiCheck do
|
||||
end
|
||||
end
|
||||
|
||||
describe RuboCop::Cop::FormulaAudit::ShellCmd do
|
||||
describe RuboCop::Cop::FormulaAudit::SafePopenCommands do
|
||||
subject(:cop) { described_class.new }
|
||||
|
||||
context "When auditing shell commands" do
|
||||
context "When auditing popen commands" do
|
||||
it "Utils.popen_read should become Utils.safe_popen_read" do
|
||||
expect_offense(<<~RUBY)
|
||||
class Foo < Formula
|
||||
@ -440,6 +440,140 @@ describe RuboCop::Cop::FormulaAudit::ShellCmd do
|
||||
end
|
||||
end
|
||||
|
||||
describe RuboCop::Cop::FormulaAudit::ShellVariables do
|
||||
subject(:cop) { described_class.new }
|
||||
|
||||
context "When auditing shell variables" do
|
||||
it "Shell variables should be expanded in Utils.popen" do
|
||||
expect_offense(<<~RUBY)
|
||||
class Foo < Formula
|
||||
def install
|
||||
Utils.popen "SHELL=bash foo"
|
||||
^^^^^^^^^^^^^^ Use `Utils.popen({ "SHELL" => "bash" }, "foo")` instead of `Utils.popen "SHELL=bash foo"`
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "Shell variables should be expanded in Utils.safe_popen_read" do
|
||||
expect_offense(<<~RUBY)
|
||||
class Foo < Formula
|
||||
def install
|
||||
Utils.safe_popen_read "SHELL=bash foo"
|
||||
^^^^^^^^^^^^^^ Use `Utils.safe_popen_read({ "SHELL" => "bash" }, "foo")` instead of `Utils.safe_popen_read "SHELL=bash foo"`
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "Shell variables should be expanded in Utils.safe_popen_write" do
|
||||
expect_offense(<<~RUBY)
|
||||
class Foo < Formula
|
||||
def install
|
||||
Utils.safe_popen_write "SHELL=bash foo"
|
||||
^^^^^^^^^^^^^^ Use `Utils.safe_popen_write({ "SHELL" => "bash" }, "foo")` instead of `Utils.safe_popen_write "SHELL=bash foo"`
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "Shell variables should be expanded and keep inline string variables in the arguments" do
|
||||
expect_offense(<<~RUBY)
|
||||
class Foo < Formula
|
||||
def install
|
||||
Utils.popen "SHELL=bash \#{bin}/foo"
|
||||
^^^^^^^^^^^^^^^^^^^^^ Use `Utils.popen({ "SHELL" => "bash" }, "\#{bin}/foo")` instead of `Utils.popen "SHELL=bash \#{bin}/foo"`
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "corrects shell variables in Utils.popen" do
|
||||
source = <<~RUBY
|
||||
class Foo < Formula
|
||||
def install
|
||||
Utils.popen("SHELL=bash foo")
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
|
||||
corrected_source = <<~RUBY
|
||||
class Foo < Formula
|
||||
def install
|
||||
Utils.popen({ "SHELL" => "bash" }, "foo")
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
|
||||
new_source = autocorrect_source(source)
|
||||
expect(new_source).to eq(corrected_source)
|
||||
end
|
||||
|
||||
it "corrects shell variables in Utils.safe_popen_read" do
|
||||
source = <<~RUBY
|
||||
class Foo < Formula
|
||||
def install
|
||||
Utils.safe_popen_read("SHELL=bash foo")
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
|
||||
corrected_source = <<~RUBY
|
||||
class Foo < Formula
|
||||
def install
|
||||
Utils.safe_popen_read({ "SHELL" => "bash" }, "foo")
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
|
||||
new_source = autocorrect_source(source)
|
||||
expect(new_source).to eq(corrected_source)
|
||||
end
|
||||
|
||||
it "corrects shell variables in Utils.safe_popen_write" do
|
||||
source = <<~RUBY
|
||||
class Foo < Formula
|
||||
def install
|
||||
Utils.safe_popen_write("SHELL=bash foo")
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
|
||||
corrected_source = <<~RUBY
|
||||
class Foo < Formula
|
||||
def install
|
||||
Utils.safe_popen_write({ "SHELL" => "bash" }, "foo")
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
|
||||
new_source = autocorrect_source(source)
|
||||
expect(new_source).to eq(corrected_source)
|
||||
end
|
||||
|
||||
it "corrects shell variables with inline string variable in arguments" do
|
||||
source = <<~RUBY
|
||||
class Foo < Formula
|
||||
def install
|
||||
Utils.popen("SHELL=bash \#{bin}/foo")
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
|
||||
corrected_source = <<~RUBY
|
||||
class Foo < Formula
|
||||
def install
|
||||
Utils.popen({ "SHELL" => "bash" }, "\#{bin}/foo")
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
|
||||
new_source = autocorrect_source(source)
|
||||
expect(new_source).to eq(corrected_source)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe RuboCop::Cop::FormulaAudit::Miscellaneous do
|
||||
subject(:cop) { described_class.new }
|
||||
|
||||
|
@ -163,6 +163,53 @@ describe RuboCop::Cop::FormulaAudit::Patches do
|
||||
end
|
||||
end
|
||||
|
||||
context "When auditing inline patches" do
|
||||
it "reports no offenses for valid inline patches" do
|
||||
expect_no_offenses(<<~RUBY)
|
||||
class Foo < Formula
|
||||
url 'https://brew.sh/foo-1.0.tgz'
|
||||
patch :DATA
|
||||
end
|
||||
__END__
|
||||
patch content here
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "reports no offenses for valid nested inline patches" do
|
||||
expect_no_offenses(<<~RUBY)
|
||||
class Foo < Formula
|
||||
url 'https://brew.sh/foo-1.0.tgz'
|
||||
stable do
|
||||
patch :DATA
|
||||
end
|
||||
end
|
||||
__END__
|
||||
patch content here
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "reports an offense when DATA is found with no __END__" do
|
||||
expect_offense(<<~RUBY)
|
||||
class Foo < Formula
|
||||
url 'https://brew.sh/foo-1.0.tgz'
|
||||
patch :DATA
|
||||
^^^^^^^^^^^ patch is missing '__END__'
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
|
||||
it "reports an offense when __END__ is found with no DATA" do
|
||||
expect_offense(<<~RUBY)
|
||||
class Foo < Formula
|
||||
url 'https://brew.sh/foo-1.0.tgz'
|
||||
end
|
||||
__END__
|
||||
^^^^^^^ patch is missing 'DATA'
|
||||
patch content here
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
|
||||
context "When auditing external patches" do
|
||||
it "Patch URLs" do
|
||||
patch_urls = [
|
||||
|
@ -497,7 +497,7 @@ module Kernel
|
||||
path.read
|
||||
.lines
|
||||
.grep(/^#:/)
|
||||
.map { |line| line.slice(2..-1) }
|
||||
.map { |line| line.slice(2..-1).delete_prefix(" ") }
|
||||
end
|
||||
|
||||
def redact_secrets(input, secrets)
|
||||
|
@ -162,6 +162,7 @@ _brew_create() {
|
||||
--HEAD
|
||||
--autotools
|
||||
--cmake
|
||||
--crystal
|
||||
--debug
|
||||
--force
|
||||
--go
|
||||
|
@ -45,20 +45,19 @@ __brew_completion_caching_policy() {
|
||||
tmp=( $1(mw-2N) )
|
||||
(( $#tmp )) || return 0
|
||||
|
||||
# otherwise, invalidate if latest tap index file is missing or newer than
|
||||
# cache file
|
||||
# otherwise, invalidate if latest tap index file is missing or newer than cache file
|
||||
tmp=( ${HOMEBREW_REPOSITORY:-/usr/local/Homebrew}/Library/Taps/*/*/.git/index(om[1]N) )
|
||||
[[ -z $tmp || $tmp -nt $1 ]]
|
||||
}
|
||||
|
||||
__brew_formulae() {
|
||||
local -a formulae
|
||||
local -a list
|
||||
local comp_cachename=brew_formulae
|
||||
if _cache_invalid $comp_cachename || ! _retrieve_cache $comp_cachename; then
|
||||
formulae=($(brew search))
|
||||
_store_cache $comp_cachename formulae
|
||||
if ! _retrieve_cache $comp_cachename; then
|
||||
list=( $(brew search) )
|
||||
_store_cache $comp_cachename list
|
||||
fi
|
||||
_describe -t formulae 'all formulae' formulae
|
||||
_describe -t formulae 'all formulae' list
|
||||
}
|
||||
|
||||
__brew_installed_formulae() {
|
||||
@ -145,18 +144,17 @@ __brew_common_commands() {
|
||||
}
|
||||
|
||||
__brew_all_commands() {
|
||||
local -a commands
|
||||
local -a list
|
||||
local comp_cachename=brew_all_commands
|
||||
if _cache_invalid $comp_cachename || ! _retrieve_cache $comp_cachename; then
|
||||
HOMEBREW_CACHE=$(brew --cache)
|
||||
HOMEBREW_REPOSITORY=$(brew --repo)
|
||||
[[ -f "$HOMEBREW_CACHE/all_commands_list.txt" ]] &&
|
||||
commands=($(cat "$HOMEBREW_CACHE/all_commands_list.txt")) ||
|
||||
commands=($(cat "$HOMEBREW_REPOSITORY/completions/internal_commands_list.txt"))
|
||||
commands=(${commands:#*instal}) # Exclude instal, uninstal, etc.
|
||||
_store_cache $comp_cachename commands
|
||||
if ! _retrieve_cache $comp_cachename; then
|
||||
local cache_dir=$(brew --cache)
|
||||
[[ -f $cache_dir/all_commands_list.txt ]] &&
|
||||
list=( $(<$cache_dir/all_commands_list.txt) ) ||
|
||||
list=( $(<$(brew --repo)/completions/internal_commands_list.txt) )
|
||||
list=( ${list:#*instal} ) # Exclude instal, uninstal, etc.
|
||||
_store_cache $comp_cachename list
|
||||
fi
|
||||
_describe -t all-commands 'all commands' commands
|
||||
_describe -t all-commands 'all commands' list
|
||||
}
|
||||
|
||||
__brew_commands() {
|
||||
@ -857,10 +855,10 @@ _brew() {
|
||||
case "$state" in
|
||||
command)
|
||||
# set default cache policy
|
||||
zstyle -s ":completion:${curcontext%:*}:*" cache-policy tmp
|
||||
[[ -n $tmp ]] ||
|
||||
zstyle ":completion:${curcontext%:*}:*" cache-policy \
|
||||
__brew_completion_caching_policy
|
||||
zstyle -s ":completion:${curcontext%:*}:*" cache-policy tmp ||
|
||||
zstyle ":completion:${curcontext%:*}:*" cache-policy __brew_completion_caching_policy
|
||||
zstyle -s ":completion:${curcontext%:*}:*" use-cache tmp ||
|
||||
zstyle ":completion:${curcontext%:*}:*" use-cache true
|
||||
|
||||
__brew_commands && return 0
|
||||
;;
|
||||
@ -878,10 +876,10 @@ _brew() {
|
||||
|
||||
# set default cache policy (we repeat this dance because the context
|
||||
# service differs from above)
|
||||
zstyle -s ":completion:${curcontext%:*}:*" cache-policy tmp
|
||||
[[ -n $tmp ]] ||
|
||||
zstyle ":completion:${curcontext%:*}:*" cache-policy \
|
||||
__brew_completion_caching_policy
|
||||
zstyle -s ":completion:${curcontext%:*}:*" cache-policy tmp ||
|
||||
zstyle ":completion:${curcontext%:*}:*" cache-policy __brew_completion_caching_policy
|
||||
zstyle -s ":completion:${curcontext%:*}:*" use-cache tmp ||
|
||||
zstyle ":completion:${curcontext%:*}:*" use-cache true
|
||||
|
||||
# call completion for named command e.g. _brew_list
|
||||
local completion_func="_brew_${command//-/_}"
|
||||
|
@ -21,7 +21,7 @@ __brew_all_casks() {
|
||||
local expl
|
||||
local comp_cachename=brew_casks
|
||||
|
||||
if _cache_invalid $comp_cachename || ! _retrieve_cache $comp_cachename; then
|
||||
if ! _retrieve_cache $comp_cachename; then
|
||||
list=( $(brew search --casks) )
|
||||
_store_cache $comp_cachename list
|
||||
fi
|
||||
|
@ -8,7 +8,7 @@ If a bottle is available and usable it will be downloaded and poured automatical
|
||||
Bottles will not be used if the user requests it (see above), if the formula requests it (with `pour_bottle?`), if any options are specified during installation (bottles are all compiled with default options), if the bottle is not up to date (e.g. lacking a checksum) or if the bottle's `cellar` is not `:any` nor equal to the current `HOMEBREW_CELLAR`.
|
||||
|
||||
## Creation
|
||||
Bottles are created using the [Brew Test Bot](Brew-Test-Bot.md). This happens mostly when people submit pull requests to Homebrew and the `bottle do` block is updated by maintainers when they `brew pr-publish` or `brew pr-pull` the contents of a pull request. For the Homebrew organisations' taps they are uploaded to and downloaded from [Bintray](https://bintray.com/homebrew).
|
||||
Bottles are created using the [Brew Test Bot](Brew-Test-Bot.md), usually when people submit pull requests to Homebrew. The `bottle do` block is updated by maintainers when they merge a pull request. For the Homebrew organisations' taps they are uploaded to and downloaded from [Bintray](https://bintray.com/homebrew).
|
||||
|
||||
By default, bottles will be built for the oldest CPU supported by the OS/architecture you're building for (Core 2 for 64-bit OSs). This ensures that bottles are compatible with all computers you might distribute them to. If you *really* want your bottles to be optimised for something else, you can pass the `--bottle-arch=` option to build for another architecture; for example, `brew install foo --build-bottle --bottle-arch=penryn`. Just remember that if you build for a newer architecture some of your users might get binaries they can't run and that would be sad!
|
||||
|
||||
|
@ -8,6 +8,7 @@ If a pull request is correct and doesn't need any modifications to commit messag
|
||||
|
||||
1. Ensure the job has already completed successfully.
|
||||
2. Run `brew pr-publish 12345` where `12345` is the pull request number (or URL).
|
||||
- Approving a PR for an existing formula will automatically publish the bottles and close the PR, taking care of this step.
|
||||
3. Watch the [actions queue](https://github.com/Homebrew/homebrew-core/actions) to ensure your job finishes. BrewTestBot will usually notify you of failures with a ping as well.
|
||||
|
||||
If a pull request needs changes to the commit messages:
|
||||
|
@ -54,7 +54,7 @@ Check for:
|
||||
- if CI is green and...
|
||||
- formula `bottle :unneeded`, you can merge it through GitHub UI
|
||||
- bottles need to be pulled, and...
|
||||
- the commits are correct and don't need changes, use: `brew pr-publish $PR_ID`
|
||||
- the commits are correct and don't need changes, approve the PR to trigger an automatic merge (use `brew pr-publish $PR_ID` to trigger manually in case of a new formula)
|
||||
- the commits need to be amended, use `brew pr-pull $PR_ID`, make changes, and `git push`
|
||||
- don't forget to thank the contributor
|
||||
- celebrate the first-time contributors
|
||||
|
@ -588,9 +588,9 @@ If *`formula`* is provided, display the file or directory used to cache *`formul
|
||||
* `--force-bottle`:
|
||||
Show the cache file used when pouring a bottle.
|
||||
* `--formula`:
|
||||
Show cache files for only formulae
|
||||
Only show cache files for formulae.
|
||||
* `--cask`:
|
||||
Show cache files for only casks
|
||||
Only show cache files for casks.
|
||||
|
||||
### `--cellar` [*`formula`*]
|
||||
|
||||
@ -769,6 +769,8 @@ a simple example. For the complete API, see:
|
||||
Create a basic template for an Autotools-style build.
|
||||
* `--cmake`:
|
||||
Create a basic template for a CMake-style build.
|
||||
* `--crystal`:
|
||||
Create a basic template for a Crystal build.
|
||||
* `--go`:
|
||||
Create a basic template for a Go build.
|
||||
* `--meson`:
|
||||
@ -900,17 +902,17 @@ repository.
|
||||
* `--resolve`:
|
||||
When a patch fails to apply, leave in progress and allow user to resolve, instead of aborting.
|
||||
* `--workflow`:
|
||||
Retrieve artifacts from the specified workflow (default: tests.yml).
|
||||
Retrieve artifacts from the specified workflow (default: `tests.yml`).
|
||||
* `--artifact`:
|
||||
Download artifacts with the specified name (default: bottles).
|
||||
Download artifacts with the specified name (default: `bottles`).
|
||||
* `--bintray-org`:
|
||||
Upload to the specified Bintray organisation (default: homebrew).
|
||||
Upload to the specified Bintray organisation (default: `homebrew`).
|
||||
* `--tap`:
|
||||
Target tap repository (default: homebrew/core).
|
||||
Target tap repository (default: `homebrew/core`).
|
||||
* `--root-url`:
|
||||
Use the specified *`URL`* as the root of the bottle's URL instead of Homebrew's default.
|
||||
* `--bintray-mirror`:
|
||||
Use the specified Bintray repository to automatically mirror stable URLs defined in the formulae (default: mirror)
|
||||
Use the specified Bintray repository to automatically mirror stable URLs defined in the formulae (default: `mirror`).
|
||||
|
||||
### `pr-upload` [*`options`*]
|
||||
|
||||
@ -921,7 +923,7 @@ Apply the bottle commit and publish bottles to Bintray.
|
||||
* `-n`, `--dry-run`:
|
||||
Print what would be done rather than doing it.
|
||||
* `--bintray-org`:
|
||||
Upload to the specified Bintray organisation (default: homebrew).
|
||||
Upload to the specified Bintray organisation (default: `homebrew`).
|
||||
* `--root-url`:
|
||||
Use the specified *`URL`* as the root of the bottle's URL instead of Homebrew's default.
|
||||
|
||||
|
@ -33,9 +33,10 @@ A few requests:
|
||||
- In Homebrew/brew, close pull requests using GitHub's "Merge pull request"
|
||||
button in "Create a merge commit" mode.
|
||||
- In Homebrew/homebrew-core, use `brew pr-publish` to close pull requests
|
||||
that require new bottles or change multiple formulae. If commits need to
|
||||
be amended use `brew pr-pull` instead. Let these commands auto-close
|
||||
issues whenever possible (it may take up to 5 minutes). If in doubt,
|
||||
that require new bottles or change multiple formulae. Note that an approving
|
||||
review on a pull request for an existing formula will trigger this automatically.
|
||||
If commits need to be amended use `brew pr-pull` instead. Let these commands
|
||||
auto-close issues whenever possible (it may take up to 5 minutes). If in doubt,
|
||||
check with e.g. Fork.app that you've not accidentally added merge commits.
|
||||
If bottles are unnecessary, use GitHub's "Merge pull request" button in
|
||||
"Squash and merge" mode for a single formula change.
|
||||
|
@ -765,11 +765,11 @@ Show the cache file used when pouring a bottle\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-formula\fR
|
||||
Show cache files for only formulae
|
||||
Only show cache files for formulae\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-cask\fR
|
||||
Show cache files for only casks
|
||||
Only show cache files for casks\.
|
||||
.
|
||||
.SS "\fB\-\-cellar\fR [\fIformula\fR]"
|
||||
Display Homebrew\'s Cellar path\. \fIDefault:\fR \fB$(brew \-\-prefix)/Cellar\fR, or if that directory doesn\'t exist, \fB$(brew \-\-repository)/Cellar\fR\.
|
||||
@ -999,6 +999,10 @@ Create a basic template for an Autotools\-style build\.
|
||||
Create a basic template for a CMake\-style build\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-crystal\fR
|
||||
Create a basic template for a Crystal build\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-go\fR
|
||||
Create a basic template for a Go build\.
|
||||
.
|
||||
@ -1169,19 +1173,19 @@ When a patch fails to apply, leave in progress and allow user to resolve, instea
|
||||
.
|
||||
.TP
|
||||
\fB\-\-workflow\fR
|
||||
Retrieve artifacts from the specified workflow (default: tests\.yml)\.
|
||||
Retrieve artifacts from the specified workflow (default: \fBtests\.yml\fR)\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-artifact\fR
|
||||
Download artifacts with the specified name (default: bottles)\.
|
||||
Download artifacts with the specified name (default: \fBbottles\fR)\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-bintray\-org\fR
|
||||
Upload to the specified Bintray organisation (default: homebrew)\.
|
||||
Upload to the specified Bintray organisation (default: \fBhomebrew\fR)\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-tap\fR
|
||||
Target tap repository (default: homebrew/core)\.
|
||||
Target tap repository (default: \fBhomebrew/core\fR)\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-root\-url\fR
|
||||
@ -1189,7 +1193,7 @@ Use the specified \fIURL\fR as the root of the bottle\'s URL instead of Homebrew
|
||||
.
|
||||
.TP
|
||||
\fB\-\-bintray\-mirror\fR
|
||||
Use the specified Bintray repository to automatically mirror stable URLs defined in the formulae (default: mirror)
|
||||
Use the specified Bintray repository to automatically mirror stable URLs defined in the formulae (default: \fBmirror\fR)\.
|
||||
.
|
||||
.SS "\fBpr\-upload\fR [\fIoptions\fR]"
|
||||
Apply the bottle commit and publish bottles to Bintray\.
|
||||
@ -1204,7 +1208,7 @@ Print what would be done rather than doing it\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-bintray\-org\fR
|
||||
Upload to the specified Bintray organisation (default: homebrew)\.
|
||||
Upload to the specified Bintray organisation (default: \fBhomebrew\fR)\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-root\-url\fR
|
||||
|
Loading…
x
Reference in New Issue
Block a user