Move StringInreplaceExtension into separate file.

This commit is contained in:
Markus Reiter 2020-10-10 15:04:46 +02:00
parent 24ae318a3d
commit 318091cccc
7 changed files with 180 additions and 183 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
# <pre>inreplace "somefile.cfg", /look[for]what?/, "replace by #{bin}/tool"</pre>
#
# @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

View File

@ -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