Skip to content

Commit

Permalink
feat: add gsub_file! method
Browse files Browse the repository at this point in the history
  • Loading branch information
G-Rath committed Feb 23, 2024
1 parent e1333f5 commit 4f92183
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 0 deletions.
26 changes: 26 additions & 0 deletions lib/thor/actions/file_manipulation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,32 @@ def inject_into_module(path, module_name, *args, &block)
insert_into_file(path, *(args << config), &block)
end

# Run a regular expression replacement on a file, raising an error if the
# contents of the file are not changed.
#
# ==== Parameters
# path<String>:: path of the file to be changed
# flag<Regexp|String>:: the regexp or string to be replaced
# replacement<String>:: the replacement, can be also given as a block
# config<Hash>:: give :verbose => false to not log the status, and
# :force => true, to force the replacement regardless of runner behavior.
#
# ==== Example
#
# gsub_file 'app/controllers/application_controller.rb', /#\s*(filter_parameter_logging :password)/, '\1'
#
# gsub_file 'README', /rake/, :green do |match|
# match << " no more. Use thor!"
# end
#
def gsub_file!(path, flag, *args, &block)
config = args.last.is_a?(Hash) ? args.pop : {}

config[:error_on_no_change] = true

gsub_file(path, flag, *args, config, &block)
end

# Run a regular expression replacement on a file.
#
# ==== Parameters
Expand Down
98 changes: 98 additions & 0 deletions spec/actions/file_manipulation_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,104 @@ def file
end
end

describe "#gsub_file!" do
context "with invoke behavior" do
it "replaces the content in the file" do
action :gsub_file!, "doc/README", "__start__", "START"
expect(File.binread(file)).to eq("START\nREADME\n__end__\n")
end

it "does not replace if pretending" do
runner(pretend: true)
action :gsub_file!, "doc/README", "__start__", "START"
expect(File.binread(file)).to eq("__start__\nREADME\n__end__\n")
end

it "accepts a block" do
action(:gsub_file!, "doc/README", "__start__") { |match| match.gsub("__", "").upcase }
expect(File.binread(file)).to eq("START\nREADME\n__end__\n")
end

it "logs status" do
expect(action(:gsub_file!, "doc/README", "__start__", "START")).to eq(" gsub doc/README\n")
end

it "does not log status if required" do
expect(action(:gsub_file!, file, "__", verbose: false) { |match| match * 2 }).to be_empty
end

it "cares if the file contents did not change" do
expect do
action :gsub_file!, "doc/README", "___start___", "START"
end.to raise_error(Thor::Error)

expect(File.binread(file)).to eq("__start__\nREADME\n__end__\n")
end
end

context "with revoke behavior" do
context "and no force option" do
it "does not replace the content in the file" do
runner({}, :revoke)
action :gsub_file!, "doc/README", "__start__", "START"
expect(File.binread(file)).to eq("__start__\nREADME\n__end__\n")
end

it "does not replace if pretending" do
runner({pretend: true}, :revoke)
action :gsub_file!, "doc/README", "__start__", "START"
expect(File.binread(file)).to eq("__start__\nREADME\n__end__\n")
end

it "does not replace the content in the file when given a block" do
runner({}, :revoke)
action(:gsub_file!, "doc/README", "__start__") { |match| match.gsub("__", "").upcase }
expect(File.binread(file)).to eq("__start__\nREADME\n__end__\n")
end

it "does not log status" do
runner({}, :revoke)
expect(action(:gsub_file!, "doc/README", "__start__", "START")).to be_empty
end

it "does not log status if required" do
runner({}, :revoke)
expect(action(:gsub_file!, file, "__", verbose: false) { |match| match * 2 }).to be_empty
end
end

context "and force option" do
it "replaces the content in the file" do
runner({}, :revoke)
action :gsub_file!, "doc/README", "__start__", "START", force: true
expect(File.binread(file)).to eq("START\nREADME\n__end__\n")
end

it "does not replace if pretending" do
runner({pretend: true}, :revoke)
action :gsub_file!, "doc/README", "__start__", "START", force: true
expect(File.binread(file)).to eq("__start__\nREADME\n__end__\n")
end

it "replaces the content in the file when given a block" do
runner({}, :revoke)
action(:gsub_file!, "doc/README", "__start__", force: true) { |match| match.gsub("__", "").upcase }
expect(File.binread(file)).to eq("START\nREADME\n__end__\n")
end

it "logs status" do
runner({}, :revoke)
expect(action(:gsub_file!, "doc/README", "__start__", "START", force: true)).to eq(" gsub doc/README\n")
end

it "does not log status if required" do
runner({}, :revoke)
expect(action(:gsub_file!, file, "__", verbose: false, force: true) { |match| match * 2 }).to be_empty
end
end
end
end

describe "#gsub_file" do
context "with invoke behavior" do
it "replaces the content in the file" do
Expand Down

0 comments on commit 4f92183

Please sign in to comment.