diff --git a/Library/Homebrew/dev-cmd/bump-revision.rb b/Library/Homebrew/dev-cmd/bump-revision.rb index d2e28f2a25..ebc5143487 100644 --- a/Library/Homebrew/dev-cmd/bump-revision.rb +++ b/Library/Homebrew/dev-cmd/bump-revision.rb @@ -37,24 +37,25 @@ module Homebrew args.named.to_formulae.each do |formula| current_revision = formula.revision - text = "revision #{current_revision+1}" + new_revision = current_revision + 1 if args.dry_run? unless args.quiet? + old_text = "revision #{current_revision}" + new_text = "revision #{new_revision}" if current_revision.zero? - ohai "add #{text.inspect}" + ohai "add #{new_text.inspect}" else - old = "revision #{current_revision}" - ohai "replace #{old.inspect} with #{text.inspect}" + ohai "replace #{old_text.inspect} with #{new_text.inspect}" end end else Utils::Inreplace.inreplace(formula.path) do |s| s = s.inreplace_string if current_revision.zero? - Utils::AST.add_formula_stanza!(s, :revision, text) + Utils::AST.add_formula_stanza!(s, :revision, new_revision) else - Utils::AST.replace_formula_stanza!(s, :revision, text) + Utils::AST.replace_formula_stanza!(s, :revision, new_revision) end end end diff --git a/Library/Homebrew/test/utils/ast_spec.rb b/Library/Homebrew/test/utils/ast_spec.rb index a9f0ceb774..a49031916b 100644 --- a/Library/Homebrew/test/utils/ast_spec.rb +++ b/Library/Homebrew/test/utils/ast_spec.rb @@ -20,7 +20,7 @@ describe Utils::AST do describe ".replace_formula_stanza!" do it "replaces the specified stanza in a formula" do contents = initial_formula.dup - described_class.replace_formula_stanza!(contents, :license, "license :public_domain") + described_class.replace_formula_stanza!(contents, :license, :public_domain) expect(contents).to eq <<~RUBY class Foo < Formula url "https://brew.sh/foo-1.0.tar.gz" @@ -33,7 +33,7 @@ describe Utils::AST do describe ".add_formula_stanza!" do it "adds the specified stanza to a formula" do contents = initial_formula.dup - described_class.add_formula_stanza!(contents, :revision, "revision 1") + described_class.add_formula_stanza!(contents, :revision, 1) expect(contents).to eq <<~RUBY class Foo < Formula url "https://brew.sh/foo-1.0.tar.gz" @@ -48,6 +48,50 @@ describe Utils::AST do end end + describe ".stanza_text" do + let(:compound_license) do + <<~RUBY.chomp + license all_of: [ + :public_domain, + "MIT", + "GPL-3.0-or-later" => { with: "Autoconf-exception-3.0" }, + ] + RUBY + end + + it "accepts existing stanza text" do + expect(described_class.stanza_text(:revision, "revision 1")).to eq("revision 1") + expect(described_class.stanza_text(:license, "license :public_domain")).to eq("license :public_domain") + expect(described_class.stanza_text(:license, 'license "MIT"')).to eq('license "MIT"') + expect(described_class.stanza_text(:license, compound_license)).to eq(compound_license) + end + + it "accepts a number as the stanza value" do + expect(described_class.stanza_text(:revision, 1)).to eq("revision 1") + end + + it "accepts a symbol as the stanza value" do + expect(described_class.stanza_text(:license, :public_domain)).to eq("license :public_domain") + end + + it "accepts a string as the stanza value" do + expect(described_class.stanza_text(:license, "MIT")).to eq('license "MIT"') + end + + it "adds indent to stanza text if specified" do + expect(described_class.stanza_text(:revision, "revision 1", indent: 2)).to eq(" revision 1") + expect(described_class.stanza_text(:license, 'license "MIT"', indent: 2)).to eq(' license "MIT"') + expect(described_class.stanza_text(:license, compound_license, indent: 2)).to eq(compound_license.indent(2)) + end + + it "does not add indent if already indented" do + expect(described_class.stanza_text(:revision, " revision 1", indent: 2)).to eq(" revision 1") + expect( + described_class.stanza_text(:license, compound_license.indent(2), indent: 2), + ).to eq(compound_license.indent(2)) + end + end + describe ".add_bottle_stanza!" do let(:bottle_output) do <<~RUBY.chomp.indent(2) diff --git a/Library/Homebrew/utils/ast.rb b/Library/Homebrew/utils/ast.rb index 80fe2f6113..47c29bae6e 100644 --- a/Library/Homebrew/utils/ast.rb +++ b/Library/Homebrew/utils/ast.rb @@ -29,7 +29,7 @@ module Utils end def replace_bottle_stanza!(formula_contents, bottle_output) - replace_formula_stanza!(formula_contents, :bottle, bottle_output.strip, type: :block_call) + replace_formula_stanza!(formula_contents, :bottle, bottle_output.chomp, type: :block_call) end def add_bottle_stanza!(formula_contents, bottle_output) @@ -42,11 +42,11 @@ module Utils raise "Could not find #{name} stanza!" if stanza_node.nil? tree_rewriter = Parser::Source::TreeRewriter.new(processed_source.buffer) - tree_rewriter.replace(stanza_node.source_range, replacement) + tree_rewriter.replace(stanza_node.source_range, stanza_text(name, replacement, indent: 2).lstrip) formula_contents.replace(tree_rewriter.process) end - def add_formula_stanza!(formula_contents, name, text, type: nil) + def add_formula_stanza!(formula_contents, name, value, type: nil) processed_source, children = process_formula(formula_contents) preceding_component = if children.length > 1 @@ -80,19 +80,35 @@ module Utils end tree_rewriter = Parser::Source::TreeRewriter.new(processed_source.buffer) - tree_rewriter.insert_after(preceding_expr, "\n#{text.match?(/\A\s+/) ? text : text.indent(2)}") + tree_rewriter.insert_after(preceding_expr, "\n#{stanza_text(name, value, indent: 2)}") formula_contents.replace(tree_rewriter.process) end + sig { params(name: Symbol, value: T.any(Numeric, String, Symbol), indent: T.nilable(Integer)).returns(String) } + def stanza_text(name, value, indent: nil) + text = if value.is_a?(String) + _, node = process_source(value) + value if (node.send_type? || node.block_type?) && node.method_name == name + end + text ||= "#{name} #{value.inspect}" + text = text.indent(indent) if indent && !text.match?(/\A\n* +/) + text + end + private - def process_formula(formula_contents) + def process_source(source) Homebrew.install_bundler_gems! require "rubocop-ast" ruby_version = Version.new(HOMEBREW_REQUIRED_RUBY_VERSION).major_minor.to_f - processed_source = RuboCop::AST::ProcessedSource.new(formula_contents, ruby_version) + processed_source = RuboCop::AST::ProcessedSource.new(source, ruby_version) root_node = processed_source.ast + [processed_source, root_node] + end + + def process_formula(formula_contents) + processed_source, root_node = process_source(formula_contents) class_node = if root_node.class_type? root_node