Make inreplace errors fatal

Closes Homebrew/homebrew#32649.
Closes Homebrew/homebrew#32703.
This commit is contained in:
Jack Nagel 2014-09-28 01:08:31 -05:00
parent 1c71fb4287
commit aaaab946ec
3 changed files with 54 additions and 17 deletions

View File

@ -56,10 +56,16 @@ end
# used by the inreplace function (in utils.rb)
module StringInreplaceExtension
attr_accessor :errors
def self.extended(str)
str.errors = []
end
def sub! before, after
result = super
unless result
opoo "inreplace: replacement of '#{before}' with '#{after}' failed"
errors << "expected replacement of #{before.inspect} with #{after.inspect}"
end
result
end
@ -68,7 +74,7 @@ module StringInreplaceExtension
def gsub! before, after, audit_result=true
result = super(before, after)
if audit_result && result.nil?
opoo "inreplace: replacement of '#{before}' with '#{after}' failed"
errors << "expected replacement of #{before.inspect} with #{after.inspect}"
end
result
end
@ -76,9 +82,8 @@ module StringInreplaceExtension
# Looks for Makefile style variable defintions and replaces the
# value with "new_value", or removes the definition entirely.
def change_make_var! flag, new_value
new_value = "#{flag}=#{new_value}"
unless gsub!(/^#{Regexp.escape(flag)}[ \t]*=[ \t]*(.*)$/, new_value, false)
opoo "inreplace: changing '#{flag}' to '#{new_value}' failed"
unless gsub!(/^#{Regexp.escape(flag)}[ \t]*=[ \t]*(.*)$/, "#{flag}=#{new_value}", false)
errors << "expected to change #{flag.inspect} to #{new_value.inspect}"
end
end
@ -87,7 +92,7 @@ module StringInreplaceExtension
Array(flags).each do |flag|
# Also remove trailing \n, if present.
unless gsub!(/^#{Regexp.escape(flag)}[ \t]*=.*$\n?/, "", false)
opoo "inreplace: removing '#{flag}' failed"
errors << "expected to remove #{flag.inspect}"
end
end
end

View File

@ -1,5 +1,6 @@
require 'testing_env'
require 'extend/string'
require "testing_env"
require "extend/string"
require "utils/inreplace"
class InreplaceTest < Homebrew::TestCase
def test_change_make_var
@ -87,4 +88,27 @@ class InreplaceTest < Homebrew::TestCase
s.gsub!("o", "e")
assert_equal "bee", s
end
def test_inreplace_errors
extend(Utils::Inreplace)
open("test", "w") { |f| f.write "a\nb\nc\n" }
assert_raises(Utils::InreplaceError) {
inreplace "test", "d", "f"
}
assert_raises(Utils::InreplaceError) {
inreplace("test") { |s| s.gsub! "d", "f" }
}
assert_raises(Utils::InreplaceError) {
inreplace("test") { |s|
s.change_make_var! "VAR", "value"
s.remove_make_var! "VAR2"
}
}
ensure
File.unlink("test")
end
end

View File

@ -1,24 +1,32 @@
module Utils
class InreplaceError < RuntimeError
def initialize(errors)
super errors.inject("inreplace failed\n") { |s, (path, errs)|
s << "#{path}:\n" << errs.map { |e| " #{e}\n" }.join
}
end
end
module Inreplace
def inreplace paths, before=nil, after=nil
errors = {}
Array(paths).each do |path|
s = File.open(path, "rb", &:read)
s = File.open(path, "rb", &:read).extend(StringInreplaceExtension)
if before.nil? && after.nil?
yield s.extend(StringInreplaceExtension)
yield s
else
after = after.to_s if Symbol === after
unless s.gsub!(before, after)
message = <<-EOS.undent
inreplace in '#{path}' failed
Expected replacement of '#{before}' with '#{after}'
EOS
ARGV.homebrew_developer? ? odie(message) : opoo(message)
end
s.gsub!(before, after)
end
errors[path] = s.errors if s.errors.any?
Pathname(path).atomic_write(s)
end
raise InreplaceError.new(errors) if errors.any?
end
module_function :inreplace
end