add link_overwrite DSL
Sometimes we accidentally install files outside prefix. After we fix that, users will get nasty link conflict error. So we create a whitelist here to allow overwriting certain files. e.g. link_overwrite "bin/foo", "lib/bar" link_overwrite "share/man/man1/baz-*" During FormulaInstaller#link, the whitelist conflict files will be backup into HOMEBREW_CACHE/Backup
This commit is contained in:
parent
6362b5fdba
commit
09c810c7f4
@ -11,6 +11,7 @@ require "install_renamed"
|
|||||||
require "pkg_version"
|
require "pkg_version"
|
||||||
require "tap"
|
require "tap"
|
||||||
require "formula_renames"
|
require "formula_renames"
|
||||||
|
require "keg"
|
||||||
|
|
||||||
# A formula provides instructions and metadata for Homebrew to install a piece
|
# A formula provides instructions and metadata for Homebrew to install a piece
|
||||||
# of software. Every Homebrew formula is a {Formula}.
|
# of software. Every Homebrew formula is a {Formula}.
|
||||||
@ -330,7 +331,6 @@ class Formula
|
|||||||
# The currently installed version for this formula. Will raise an exception
|
# The currently installed version for this formula. Will raise an exception
|
||||||
# if the formula is not installed.
|
# if the formula is not installed.
|
||||||
def installed_version
|
def installed_version
|
||||||
require "keg"
|
|
||||||
Keg.new(installed_prefix).version
|
Keg.new(installed_prefix).version
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -657,6 +657,30 @@ class Formula
|
|||||||
self.class.skip_clean_paths.include? to_check
|
self.class.skip_clean_paths.include? to_check
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Sometimes we accidentally install files outside prefix. After we fix that,
|
||||||
|
# users will get nasty link conflict error. So we create a whitelist here to
|
||||||
|
# allow overwriting certain files. e.g.
|
||||||
|
# link_overwrite "bin/foo", "lib/bar"
|
||||||
|
# link_overwrite "share/man/man1/baz-*"
|
||||||
|
def link_overwrite?(path)
|
||||||
|
# Don't overwrite files not created by Homebrew.
|
||||||
|
return false unless path.stat.uid == File.stat(HOMEBREW_BREW_FILE).uid
|
||||||
|
# Don't overwrite files belong to other keg.
|
||||||
|
begin
|
||||||
|
Keg.for(path)
|
||||||
|
rescue NotAKegError, Errno::ENOENT
|
||||||
|
# file doesn't belong to any keg.
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
to_check = path.relative_path_from(HOMEBREW_PREFIX).to_s
|
||||||
|
self.class.link_overwrite_paths.any? do |p|
|
||||||
|
p == to_check ||
|
||||||
|
to_check.start_with?(p.chomp("/") + "/") ||
|
||||||
|
/^#{Regexp.escape(p).gsub('\*', ".*?")}$/ === to_check
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def skip_cxxstdlib_check?
|
def skip_cxxstdlib_check?
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
@ -1351,5 +1375,14 @@ class Formula
|
|||||||
def test(&block)
|
def test(&block)
|
||||||
define_method(:test, &block)
|
define_method(:test, &block)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def link_overwrite(*paths)
|
||||||
|
paths.flatten!
|
||||||
|
link_overwrite_paths.merge(paths)
|
||||||
|
end
|
||||||
|
|
||||||
|
def link_overwrite_paths
|
||||||
|
@link_overwrite_paths ||= Set.new
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -589,9 +589,20 @@ class FormulaInstaller
|
|||||||
keg.remove_linked_keg_record
|
keg.remove_linked_keg_record
|
||||||
end
|
end
|
||||||
|
|
||||||
|
link_overwrite_backup = {} # dict: conflict file -> backup file
|
||||||
|
backup_dir = HOMEBREW_CACHE/"Backup"
|
||||||
|
|
||||||
begin
|
begin
|
||||||
keg.link
|
keg.link
|
||||||
rescue Keg::ConflictError => e
|
rescue Keg::ConflictError => e
|
||||||
|
conflict_file = e.dst
|
||||||
|
if formula.link_overwrite?(conflict_file) && !link_overwrite_backup.key?(conflict_file)
|
||||||
|
backup_file = backup_dir/conflict_file.relative_path_from(HOMEBREW_PREFIX).to_s
|
||||||
|
backup_file.parent.mkpath
|
||||||
|
conflict_file.rename backup_file
|
||||||
|
link_overwrite_backup[conflict_file] = backup_file
|
||||||
|
retry
|
||||||
|
end
|
||||||
onoe "The `brew link` step did not complete successfully"
|
onoe "The `brew link` step did not complete successfully"
|
||||||
puts "The formula built, but is not symlinked into #{HOMEBREW_PREFIX}"
|
puts "The formula built, but is not symlinked into #{HOMEBREW_PREFIX}"
|
||||||
puts e
|
puts e
|
||||||
@ -616,10 +627,24 @@ class FormulaInstaller
|
|||||||
puts e
|
puts e
|
||||||
puts e.backtrace if debug?
|
puts e.backtrace if debug?
|
||||||
@show_summary_heading = true
|
@show_summary_heading = true
|
||||||
ignore_interrupts { keg.unlink }
|
ignore_interrupts do
|
||||||
|
keg.unlink
|
||||||
|
link_overwrite_backup.each do |conflict_file, backup_file|
|
||||||
|
conflict_file.parent.mkpath
|
||||||
|
backup_file.rename conflict_file
|
||||||
|
end
|
||||||
|
end
|
||||||
Homebrew.failed = true
|
Homebrew.failed = true
|
||||||
raise
|
raise
|
||||||
end
|
end
|
||||||
|
|
||||||
|
unless link_overwrite_backup.empty?
|
||||||
|
opoo "These files were overwritten during `brew link` step:"
|
||||||
|
puts link_overwrite_backup.keys
|
||||||
|
puts
|
||||||
|
puts "They are backup in #{backup_dir}"
|
||||||
|
@show_summary_heading = true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def install_plist
|
def install_plist
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user