bump-revision: add --remove-bottle-block option

This removes a bottle block for the specified formulae
while bumping the revision.
This commit is contained in:
Steve Peters 2021-12-22 11:36:06 -08:00
parent d1a819986f
commit d53dab62c9
No known key found for this signature in database
GPG Key ID: FEE8781DA266BCA6
4 changed files with 240 additions and 0 deletions

View File

@ -3,6 +3,9 @@
module Homebrew
module CLI
class Args < OpenStruct
sig { returns(T::Boolean) }
def remove_bottle_block?; end
sig { returns(T::Boolean) }
def strict?; end

View File

@ -18,6 +18,8 @@ module Homebrew
EOS
switch "-n", "--dry-run",
description: "Print what would be done rather than doing it."
switch "--remove-bottle-block",
description: "Remove the bottle block in addition to bumping the revision."
switch "--write-only",
description: "Make the expected file modifications without taking any Git actions."
flag "--message=",
@ -60,6 +62,7 @@ module Homebrew
else
formula_ast.replace_stanza(:revision, new_revision)
end
formula_ast.remove_stanza(:bottle) if args.remove_bottle_block?
formula.path.atomic_write(formula_ast.process)
end

View File

@ -46,6 +46,207 @@ describe Utils::AST::FormulaAST do
end
end
describe "#remove_stanza" do
context "when stanza to be removed is a single line followed by a blank line" do
subject(:formula_ast) do
described_class.new <<~RUBY.chomp
class Foo < Formula
url "https://brew.sh/foo-1.0.tar.gz"
license :cannot_represent
bottle do
sha256 "f7b1fc772c79c20fddf621ccc791090bc1085fcef4da6cca03399424c66e06ca" => :sierra
end
end
RUBY
end
let(:new_contents) do
<<~RUBY.chomp
class Foo < Formula
url "https://brew.sh/foo-1.0.tar.gz"
bottle do
sha256 "f7b1fc772c79c20fddf621ccc791090bc1085fcef4da6cca03399424c66e06ca" => :sierra
end
end
RUBY
end
it "removes the line containing the stanza" do
formula_ast.remove_stanza(:license)
expect(formula_ast.process).to eq(new_contents)
end
end
context "when stanza to be removed is a multiline block followed by a blank line" do
subject(:formula_ast) do
described_class.new <<~RUBY.chomp
class Foo < Formula
url "https://brew.sh/foo-1.0.tar.gz"
license all_of: [
:public_domain,
"MIT",
"GPL-3.0-or-later" => { with: "Autoconf-exception-3.0" },
]
bottle do
sha256 "f7b1fc772c79c20fddf621ccc791090bc1085fcef4da6cca03399424c66e06ca" => :sierra
end
end
RUBY
end
let(:new_contents) do
<<~RUBY.chomp
class Foo < Formula
url "https://brew.sh/foo-1.0.tar.gz"
bottle do
sha256 "f7b1fc772c79c20fddf621ccc791090bc1085fcef4da6cca03399424c66e06ca" => :sierra
end
end
RUBY
end
it "removes the lines containing the stanza" do
formula_ast.remove_stanza(:license)
expect(formula_ast.process).to eq(new_contents)
end
end
context "when stanza to be removed has a comment on the same line" do
subject(:formula_ast) do
described_class.new <<~RUBY.chomp
class Foo < Formula
url "https://brew.sh/foo-1.0.tar.gz"
license :cannot_represent # comment
bottle do
sha256 "f7b1fc772c79c20fddf621ccc791090bc1085fcef4da6cca03399424c66e06ca" => :sierra
end
end
RUBY
end
let(:new_contents) do
<<~RUBY.chomp
class Foo < Formula
url "https://brew.sh/foo-1.0.tar.gz"
# comment
bottle do
sha256 "f7b1fc772c79c20fddf621ccc791090bc1085fcef4da6cca03399424c66e06ca" => :sierra
end
end
RUBY
end
it "removes the stanza but keeps the comment and its whitespace" do
formula_ast.remove_stanza(:license)
expect(formula_ast.process).to eq(new_contents)
end
end
context "when stanza to be removed has a comment on the next line" do
subject(:formula_ast) do
described_class.new <<~RUBY.chomp
class Foo < Formula
url "https://brew.sh/foo-1.0.tar.gz"
license :cannot_represent
# comment
bottle do
sha256 "f7b1fc772c79c20fddf621ccc791090bc1085fcef4da6cca03399424c66e06ca" => :sierra
end
end
RUBY
end
let(:new_contents) do
<<~RUBY.chomp
class Foo < Formula
url "https://brew.sh/foo-1.0.tar.gz"
# comment
bottle do
sha256 "f7b1fc772c79c20fddf621ccc791090bc1085fcef4da6cca03399424c66e06ca" => :sierra
end
end
RUBY
end
it "removes the stanza but keeps the comment" do
formula_ast.remove_stanza(:license)
expect(formula_ast.process).to eq(new_contents)
end
end
context "when stanza to be removed has newlines before and after" do
subject(:formula_ast) do
described_class.new <<~RUBY.chomp
class Foo < Formula
url "https://brew.sh/foo-1.0.tar.gz"
bottle do
sha256 "f7b1fc772c79c20fddf621ccc791090bc1085fcef4da6cca03399424c66e06ca" => :sierra
end
head do
url "https://brew.sh/foo.git"
end
end
RUBY
end
let(:new_contents) do
<<~RUBY.chomp
class Foo < Formula
url "https://brew.sh/foo-1.0.tar.gz"
head do
url "https://brew.sh/foo.git"
end
end
RUBY
end
it "removes the stanza and preceding newline" do
formula_ast.remove_stanza(:bottle)
expect(formula_ast.process).to eq(new_contents)
end
end
context "when stanza to be removed is at the end of the formula" do
subject(:formula_ast) do
described_class.new <<~RUBY.chomp
class Foo < Formula
url "https://brew.sh/foo-1.0.tar.gz"
license :cannot_represent
bottle do
sha256 "f7b1fc772c79c20fddf621ccc791090bc1085fcef4da6cca03399424c66e06ca" => :sierra
end
end
RUBY
end
let(:new_contents) do
<<~RUBY.chomp
class Foo < Formula
url "https://brew.sh/foo-1.0.tar.gz"
license :cannot_represent
end
RUBY
end
it "removes the stanza and preceding newline" do
formula_ast.remove_stanza(:bottle)
expect(formula_ast.process).to eq(new_contents)
end
end
end
describe "#add_bottle_block" do
let(:bottle_output) do
<<~RUBY.chomp.indent(2)

View File

@ -114,6 +114,39 @@ module Utils
add_stanza(:bottle, "\n#{bottle_output.chomp}", type: :block_call)
end
sig { params(name: Symbol, type: T.nilable(Symbol)).void }
def remove_stanza(name, type: nil)
stanza_node = stanza(name, type: type)
raise "Could not find '#{name}' stanza!" if stanza_node.blank?
# stanza is probably followed by a newline character
# try to delete it if so
stanza_range = stanza_node.source_range
trailing_range = stanza_range.with(begin_pos: stanza_range.end_pos,
end_pos: stanza_range.end_pos + 1)
if trailing_range.source.chomp.empty?
stanza_range = stanza_range.adjust(end_pos: 1)
# stanza_node is probably indented
# since a trailing newline has been removed,
# try to delete leading whitespace on line
leading_range = stanza_range.with(begin_pos: stanza_range.begin_pos - stanza_range.column,
end_pos: stanza_range.begin_pos)
if leading_range.source.strip.empty?
stanza_range = stanza_range.adjust(begin_pos: -stanza_range.column)
# if the stanza was preceded by a blank line, it should be removed
# that is, if the two previous characters are newlines,
# then delete one of them
leading_range = stanza_range.with(begin_pos: stanza_range.begin_pos - 2,
end_pos: stanza_range.begin_pos)
stanza_range = stanza_range.adjust(begin_pos: -1) if leading_range.source.chomp.chomp.empty?
end
end
tree_rewriter.remove(stanza_range)
end
sig { params(name: Symbol, replacement: T.any(Numeric, String, Symbol), type: T.nilable(Symbol)).void }
def replace_stanza(name, replacement, type: nil)
stanza_node = stanza(name, type: type)