From 318091cccc7d804c790718a3267c982199929ecd Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Sat, 10 Oct 2020 15:04:46 +0200 Subject: [PATCH] Move `StringInreplaceExtension` into separate file. --- Library/Homebrew/extend/string.rb | 52 +------- .../Homebrew/sorbet/rbi/utils/inreplace.rbi | 29 ----- Library/Homebrew/test/string_spec.rb | 17 --- Library/Homebrew/test/utils/inreplace_spec.rb | 56 ++++++++ .../string_inreplace_extension_spec.rb} | 120 ++++++------------ Library/Homebrew/utils/inreplace.rb | 17 ++- .../utils/string_inreplace_extension.rb | 72 +++++++++++ 7 files changed, 180 insertions(+), 183 deletions(-) delete mode 100644 Library/Homebrew/sorbet/rbi/utils/inreplace.rbi delete mode 100644 Library/Homebrew/test/string_spec.rb create mode 100644 Library/Homebrew/test/utils/inreplace_spec.rb rename Library/Homebrew/test/{inreplace_spec.rb => utils/string_inreplace_extension_spec.rb} (59%) create mode 100644 Library/Homebrew/utils/string_inreplace_extension.rb diff --git a/Library/Homebrew/extend/string.rb b/Library/Homebrew/extend/string.rb index d68d678970..21105e71f4 100644 --- a/Library/Homebrew/extend/string.rb +++ b/Library/Homebrew/extend/string.rb @@ -1,54 +1,4 @@ -# typed: false +# typed: strict # frozen_string_literal: true require "active_support/core_ext/object/blank" - -# Used by the inreplace function (in `utils.rb`). -class StringInreplaceExtension - attr_accessor :errors, :inreplace_string - - def initialize(str) - @inreplace_string = str - @errors = [] - end - - def self.extended(str) - str.errors = [] - end - - def sub!(before, after) - result = inreplace_string.sub!(before, after) - errors << "expected replacement of #{before.inspect} with #{after.inspect}" unless result - result - end - - # Warn if nothing was replaced - def gsub!(before, after, audit_result = true) # rubocop:disable Style/OptionalBooleanParameter - result = inreplace_string.gsub!(before, after) - errors << "expected replacement of #{before.inspect} with #{after.inspect}" if audit_result && result.nil? - result - end - - # Looks for Makefile style variable definitions and replaces the - # value with "new_value", or removes the definition entirely. - def change_make_var!(flag, new_value) - return if gsub!(/^#{Regexp.escape(flag)}[ \t]*[\\?+:!]?=[ \t]*((?:.*\\\n)*.*)$/, "#{flag}=#{new_value}", false) - - errors << "expected to change #{flag.inspect} to #{new_value.inspect}" - end - - # Removes variable assignments completely. - def remove_make_var!(flags) - Array(flags).each do |flag| - # Also remove trailing \n, if present. - unless gsub!(/^#{Regexp.escape(flag)}[ \t]*[\\?+:!]?=(?:.*\\\n)*.*$\n?/, "", false) - errors << "expected to remove #{flag.inspect}" - end - end - end - - # Finds the specified variable - def get_make_var(flag) - inreplace_string[/^#{Regexp.escape(flag)}[ \t]*[\\?+:!]?=[ \t]*((?:.*\\\n)*.*)$/, 1] - end -end diff --git a/Library/Homebrew/sorbet/rbi/utils/inreplace.rbi b/Library/Homebrew/sorbet/rbi/utils/inreplace.rbi deleted file mode 100644 index b6d0be9a5a..0000000000 --- a/Library/Homebrew/sorbet/rbi/utils/inreplace.rbi +++ /dev/null @@ -1,29 +0,0 @@ -# typed: strict - -module Utils::Inreplace - include Kernel - - sig { params(paths: T::Array[T.untyped], before: T.nilable(String), after: T.nilable(T.any(String, Symbol)), audit_result: T::Boolean).void } - def inreplace(paths, before = nil, after = nil, audit_result = true); end -end - -class StringInreplaceExtension - sig { params(before: String, after: String).returns(T.nilable(String)) } - def sub!(before, after) - end - - sig { params(before: T.nilable(String), after: T.nilable(String), audit_result: T::Boolean).returns(T.nilable(String)) } - def gsub!(before, after, audit_result = true); end - - sig {params(flag: String, new_value: String).void} - def change_make_var!(flag, new_value) - end - - sig {params(flags: T::Array[String]).void} - def remove_make_var!(flags) - end - - sig {params(flag: String).returns(String)} - def get_make_var(flag) - end -end diff --git a/Library/Homebrew/test/string_spec.rb b/Library/Homebrew/test/string_spec.rb deleted file mode 100644 index 0442c620a2..0000000000 --- a/Library/Homebrew/test/string_spec.rb +++ /dev/null @@ -1,17 +0,0 @@ -# typed: false -# frozen_string_literal: true - -require "extend/string" - -describe StringInreplaceExtension do - subject { described_class.new(string) } - - let(:string) { +"foobar" } - - describe "#sub!" do - it "adds an error to #errors when no replacement was made" do - subject.sub! "not here", "test" - expect(subject.errors).to eq(['expected replacement of "not here" with "test"']) - end - end -end diff --git a/Library/Homebrew/test/utils/inreplace_spec.rb b/Library/Homebrew/test/utils/inreplace_spec.rb new file mode 100644 index 0000000000..16c5bedd62 --- /dev/null +++ b/Library/Homebrew/test/utils/inreplace_spec.rb @@ -0,0 +1,56 @@ +# typed: false +# frozen_string_literal: true + +require "tempfile" +require "utils/inreplace" + +describe Utils::Inreplace do + let(:file) { Tempfile.new("test") } + + before do + file.write <<~EOS + a + b + c + EOS + end + + after { file.unlink } + + it "raises error if there are no files given to replace" do + expect { + described_class.inreplace [], "d", "f" + }.to raise_error(Utils::Inreplace::Error) + end + + it "raises error if there is nothing to replace" do + expect { + described_class.inreplace file.path, "d", "f" + }.to raise_error(Utils::Inreplace::Error) + end + + it "raises error if there is nothing to replace in block form" do + expect { + described_class.inreplace(file.path) do |s| + s.gsub!("d", "f") # rubocop:disable Performance/StringReplacement + end + }.to raise_error(Utils::Inreplace::Error) + end + + it "raises error if there is no make variables to replace" do + expect { + described_class.inreplace(file.path) do |s| + s.change_make_var! "VAR", "value" + s.remove_make_var! "VAR2" + end + }.to raise_error(Utils::Inreplace::Error) + end + + describe "#inreplace_pairs" do + it "raises error if there is no old value" do + expect { + described_class.inreplace_pairs(file.path, [[nil, "f"]]) + }.to raise_error(Utils::Inreplace::Error) + end + end +end diff --git a/Library/Homebrew/test/inreplace_spec.rb b/Library/Homebrew/test/utils/string_inreplace_extension_spec.rb similarity index 59% rename from Library/Homebrew/test/inreplace_spec.rb rename to Library/Homebrew/test/utils/string_inreplace_extension_spec.rb index aa80fddd0c..a072aafb5e 100644 --- a/Library/Homebrew/test/inreplace_spec.rb +++ b/Library/Homebrew/test/utils/string_inreplace_extension_spec.rb @@ -1,12 +1,10 @@ # typed: false # frozen_string_literal: true -require "extend/string" -require "tempfile" -require "utils/inreplace" +require "utils/string_inreplace_extension" describe StringInreplaceExtension do - subject { described_class.new(string.dup) } + subject(:string_extension) { described_class.new(string.dup) } describe "#change_make_var!" do context "flag" do @@ -20,8 +18,8 @@ describe StringInreplaceExtension do end it "is successfully replaced" do - subject.change_make_var! "FLAG", "def" - expect(subject.inreplace_string).to eq <<~EOS + string_extension.change_make_var! "FLAG", "def" + expect(string_extension.inreplace_string).to eq <<~EOS OTHER=def FLAG=def FLAG2=abc @@ -29,8 +27,8 @@ describe StringInreplaceExtension do end it "is successfully appended" do - subject.change_make_var! "FLAG", "\\1 def" - expect(subject.inreplace_string).to eq <<~EOS + string_extension.change_make_var! "FLAG", "\\1 def" + expect(string_extension.inreplace_string).to eq <<~EOS OTHER=def FLAG=abc def FLAG2=abc @@ -47,8 +45,8 @@ describe StringInreplaceExtension do end it "is successfully replaced" do - subject.change_make_var! "CFLAGS", "-O3" - expect(subject.inreplace_string).to eq <<~EOS + string_extension.change_make_var! "CFLAGS", "-O3" + expect(string_extension.inreplace_string).to eq <<~EOS CFLAGS=-O3 LDFLAGS\t=\t-lcrypto -lssl EOS @@ -65,8 +63,8 @@ describe StringInreplaceExtension do end it "is successfully replaced" do - subject.change_make_var! "CFLAGS", "-O3" - expect(subject.inreplace_string).to eq <<~EOS + string_extension.change_make_var! "CFLAGS", "-O3" + expect(string_extension.inreplace_string).to eq <<~EOS CFLAGS=-O3 LDFLAGS = -lcrypto -lssl EOS @@ -84,8 +82,8 @@ describe StringInreplaceExtension do end it "is successfully replaced" do - subject.change_make_var! "FLAG", "def" - expect(subject.inreplace_string).to eq <<~EOS + string_extension.change_make_var! "FLAG", "def" + expect(string_extension.inreplace_string).to eq <<~EOS OTHER=def FLAG=def FLAG2=abc @@ -102,8 +100,8 @@ describe StringInreplaceExtension do end it "is successfully replaced" do - subject.change_make_var! "FLAG", "def" - expect(subject.inreplace_string).to eq <<~EOS + string_extension.change_make_var! "FLAG", "def" + expect(string_extension.inreplace_string).to eq <<~EOS FLAG=def mv file_a file_b EOS @@ -120,8 +118,8 @@ describe StringInreplaceExtension do end it "is successfully replaced" do - subject.change_make_var! "FLAG", "def" - expect(subject.inreplace_string).to eq <<~EOS + string_extension.change_make_var! "FLAG", "def" + expect(string_extension.inreplace_string).to eq <<~EOS OTHER=def FLAG=def FLAG2=abc @@ -142,8 +140,8 @@ describe StringInreplaceExtension do end it "is successfully removed" do - subject.remove_make_var! "FLAG" - expect(subject.inreplace_string).to eq <<~EOS + string_extension.remove_make_var! "FLAG" + expect(string_extension.inreplace_string).to eq <<~EOS OTHER=def FLAG2 = def EOS @@ -159,8 +157,8 @@ describe StringInreplaceExtension do end it "is successfully removed" do - subject.remove_make_var! "LDFLAGS" - expect(subject.inreplace_string).to eq <<~EOS + string_extension.remove_make_var! "LDFLAGS" + expect(string_extension.inreplace_string).to eq <<~EOS CFLAGS\t=\t-Wall -O2 EOS end @@ -176,8 +174,8 @@ describe StringInreplaceExtension do end it "is successfully removed" do - subject.remove_make_var! "CFLAGS" - expect(subject.inreplace_string).to eq <<~EOS + string_extension.remove_make_var! "CFLAGS" + expect(string_extension.inreplace_string).to eq <<~EOS LDFLAGS = -lcrypto -lssl EOS end @@ -195,8 +193,8 @@ describe StringInreplaceExtension do end specify "are be successfully removed" do - subject.remove_make_var! ["FLAG", "FLAG2"] - expect(subject.inreplace_string).to eq <<~EOS + string_extension.remove_make_var! ["FLAG", "FLAG2"] + expect(string_extension.inreplace_string).to eq <<~EOS OTHER=def OTHER2=def EOS @@ -214,7 +212,7 @@ describe StringInreplaceExtension do end it "extracts the value for a given variable" do - expect(subject.get_make_var("CFLAGS")).to eq("-Wall -O2") + expect(string_extension.get_make_var("CFLAGS")).to eq("-Wall -O2") end end @@ -227,7 +225,7 @@ describe StringInreplaceExtension do end it "extracts the value for a given variable" do - expect(subject.get_make_var("CFLAGS")).to eq("-Wall -O2") + expect(string_extension.get_make_var("CFLAGS")).to eq("-Wall -O2") end end @@ -241,7 +239,7 @@ describe StringInreplaceExtension do end it "extracts the value for a given variable" do - expect(subject.get_make_var("CFLAGS")).to match(/^-Wall -O2 \\\n +-DSOME_VAR=1$/) + expect(string_extension.get_make_var("CFLAGS")).to match(/^-Wall -O2 \\\n +-DSOME_VAR=1$/) end end end @@ -250,8 +248,13 @@ describe StringInreplaceExtension do let(:string) { "foo" } it "replaces the first occurrence" do - subject.sub!("o", "e") - expect(subject.inreplace_string).to eq("feo") + string_extension.sub!("o", "e") + expect(string_extension.inreplace_string).to eq("feo") + end + + it "adds an error to #errors when no replacement was made" do + string_extension.sub! "not here", "test" + expect(string_extension.errors).to eq(['expected replacement of "not here" with "test"']) end end @@ -259,59 +262,8 @@ describe StringInreplaceExtension do let(:string) { "foo" } it "replaces all occurrences" do - subject.gsub!("o", "e") # rubocop:disable Performance/StringReplacement - expect(subject.inreplace_string).to eq("fee") - end - end -end - -describe Utils::Inreplace do - let(:file) { Tempfile.new("test") } - - before do - file.write <<~EOS - a - b - c - EOS - end - - after { file.unlink } - - it "raises error if there are no files given to replace" do - expect { - described_class.inreplace [], "d", "f" - }.to raise_error(Utils::Inreplace::Error) - end - - it "raises error if there is nothing to replace" do - expect { - described_class.inreplace file.path, "d", "f" - }.to raise_error(Utils::Inreplace::Error) - end - - it "raises error if there is nothing to replace in block form" do - expect { - described_class.inreplace(file.path) do |s| - s.gsub!("d", "f") # rubocop:disable Performance/StringReplacement - end - }.to raise_error(Utils::Inreplace::Error) - end - - it "raises error if there is no make variables to replace" do - expect { - described_class.inreplace(file.path) do |s| - s.change_make_var! "VAR", "value" - s.remove_make_var! "VAR2" - end - }.to raise_error(Utils::Inreplace::Error) - end - - describe "#inreplace_pairs" do - it "raises error if there is no old value" do - expect { - described_class.inreplace_pairs(file.path, [[nil, "f"]]) - }.to raise_error(Utils::Inreplace::Error) + string_extension.gsub!("o", "e") # rubocop:disable Performance/StringReplacement + expect(string_extension.inreplace_string).to eq("fee") end end end diff --git a/Library/Homebrew/utils/inreplace.rb b/Library/Homebrew/utils/inreplace.rb index 9d94ae0a81..f2827a8979 100644 --- a/Library/Homebrew/utils/inreplace.rb +++ b/Library/Homebrew/utils/inreplace.rb @@ -1,11 +1,16 @@ # typed: true # frozen_string_literal: true +require "utils/string_inreplace_extension" + module Utils # Helper functions for replacing text in files in-place. # # @api private module Inreplace + include Kernel + extend T::Sig + # Error during replacement. class Error < RuntimeError def initialize(errors) @@ -28,6 +33,14 @@ module Utils #
inreplace "somefile.cfg", /look[for]what?/, "replace by #{bin}/tool"
# # @api public + sig do + params( + paths: T::Array[T.untyped], + before: T.nilable(T.any(Regexp, String)), + after: T.nilable(T.any(String, Symbol)), + audit_result: T::Boolean, + ).void + end def inreplace(paths, before = nil, after = nil, audit_result = true) # rubocop:disable Style/OptionalBooleanParameter after = after.to_s if after.is_a? Symbol @@ -42,7 +55,7 @@ module Utils if before.nil? && after.nil? yield s else - s.gsub!(before, after, audit_result) + s.gsub!(T.must(before), after, audit_result) end errors[path] = s.errors unless s.errors.empty? @@ -54,7 +67,7 @@ module Utils end def inreplace_pairs(path, replacement_pairs, read_only_run: false, silent: false) - str = File.open(path, "rb", &:read) + str = File.open(path, "rb", &:read) || "" contents = StringInreplaceExtension.new(str) replacement_pairs.each do |old, new| ohai "replace #{old.inspect} with #{new.inspect}" unless silent diff --git a/Library/Homebrew/utils/string_inreplace_extension.rb b/Library/Homebrew/utils/string_inreplace_extension.rb new file mode 100644 index 0000000000..6a9aa275de --- /dev/null +++ b/Library/Homebrew/utils/string_inreplace_extension.rb @@ -0,0 +1,72 @@ +# typed: true +# frozen_string_literal: true + +# Used by the `inreplace` function (in `utils.rb`). +# +# @api private +class StringInreplaceExtension + extend T::Sig + + attr_accessor :errors, :inreplace_string + + sig { params(string: String).void } + def initialize(string) + @inreplace_string = string + @errors = [] + end + + # Same as `String#sub!`, but warns if nothing was replaced. + # + # @api public + sig { params(before: String, after: String).returns(T.nilable(String)) } + def sub!(before, after) + result = inreplace_string.sub!(before, after) + errors << "expected replacement of #{before.inspect} with #{after.inspect}" unless result + result + end + + # Same as `String#gsub!`, but warns if nothing was replaced. + # + # @api public + sig do + params(before: T.any(Regexp, String), after: T.nilable(String), audit_result: T::Boolean) + .returns(T.nilable(String)) + end + def gsub!(before, after, audit_result = true) # rubocop:disable Style/OptionalBooleanParameter + result = inreplace_string.gsub!(before, after) + errors << "expected replacement of #{before.inspect} with #{after.inspect}" if audit_result && result.nil? + result + end + + # Looks for Makefile style variable definitions and replaces the + # value with "new_value", or removes the definition entirely. + # + # @api public + sig { params(flag: String, new_value: String).void } + def change_make_var!(flag, new_value) + return if gsub!(/^#{Regexp.escape(flag)}[ \t]*[\\?+:!]?=[ \t]*((?:.*\\\n)*.*)$/, "#{flag}=#{new_value}", false) + + errors << "expected to change #{flag.inspect} to #{new_value.inspect}" + end + + # Removes variable assignments completely. + # + # @api public + sig { params(flags: T.any(String, T::Array[String])).void } + def remove_make_var!(flags) + Array(flags).each do |flag| + # Also remove trailing \n, if present. + unless gsub!(/^#{Regexp.escape(flag)}[ \t]*[\\?+:!]?=(?:.*\\\n)*.*$\n?/, "", false) + errors << "expected to remove #{flag.inspect}" + end + end + end + + # Finds the specified variable. + # + # @api public + sig { params(flag: String).returns(String) } + def get_make_var(flag) + inreplace_string[/^#{Regexp.escape(flag)}[ \t]*[\\?+:!]?=[ \t]*((?:.*\\\n)*.*)$/, 1] + end +end