
The code was sucking. To the extent that maintenance was hard. It's a lot easier to work with code that is sensibly split at sensible boundaries. So now it is more like that. But the refactor is minimal. Because we don't want you to have more merge hell than absolutely necessary. If you merge you will need to pay attention to brew.h.rb (as it is deleted) and bin/brew (as command logic is gone). It will be painful, but you will just have to help git out by moving any changes around manually. Note compatibility.rb. It ensures that any function renames or removals don't break anything. We're pretty serious about backwards compatibility. And that's because we encourage you to hack around with the innards. And we couldn't do that if we would then just make stuff disappear behind your back.
125 lines
3.5 KiB
Ruby
125 lines
3.5 KiB
Ruby
require 'extend/pathname'
|
|
|
|
class Keg <Pathname
|
|
def initialize path
|
|
super path
|
|
raise "#{to_s} is not a valid keg" unless parent.parent.realpath == HOMEBREW_CELLAR.realpath
|
|
raise "#{to_s} is not a directory" unless directory?
|
|
end
|
|
|
|
# if path is a file in a keg then this will return the containing Keg object
|
|
def self.for path
|
|
path = path.realpath
|
|
while not path.root?
|
|
return Keg.new(path) if path.parent.parent == HOMEBREW_CELLAR.realpath
|
|
path = path.parent.realpath # realpath() prevents root? failing
|
|
end
|
|
raise NotAKegError, "#{path} is not inside a keg"
|
|
end
|
|
|
|
def uninstall
|
|
chmod_R 0777 # ensure we have permission to delete
|
|
rmtree
|
|
parent.rmdir_if_possible
|
|
end
|
|
|
|
def unlink
|
|
n=0
|
|
Pathname.new(self).find do |src|
|
|
next if src == self
|
|
dst=HOMEBREW_PREFIX+src.relative_path_from(self)
|
|
next unless dst.symlink?
|
|
dst.unlink
|
|
n+=1
|
|
Find.prune if src.directory?
|
|
end
|
|
n
|
|
end
|
|
|
|
def link
|
|
$n=0
|
|
$d=0
|
|
|
|
share_mkpaths=%w[aclocal doc info locale man]+(1..8).collect{|x|"man/man#{x}"}
|
|
|
|
# yeah indeed, you have to force anything you need in the main tree into
|
|
# these dirs REMEMBER that *NOT* everything needs to be in the main tree
|
|
link_dir('etc') {:mkpath}
|
|
link_dir('bin') {:skip}
|
|
link_dir('sbin') {:link}
|
|
link_dir('include') {:link}
|
|
link_dir('share') {|path| :mkpath if share_mkpaths.include? path.to_s}
|
|
|
|
link_dir('lib') do |path|
|
|
case path.to_s
|
|
# pkg-config database gets explicitly created
|
|
when 'pkgconfig' then :mkpath
|
|
# lib/language folders also get explicitly created
|
|
when 'ghc' then :mkpath
|
|
when 'lua' then :mkpath
|
|
when 'node' then :mkpath
|
|
when 'ocaml' then :mkpath
|
|
when /^perl5/ then :mkpath
|
|
when 'php' then :mkpath
|
|
when /^python[23]\.\d$/ then :mkpath
|
|
# Everything else is symlinked to the cellar
|
|
else :link
|
|
end
|
|
end
|
|
|
|
return $n+$d
|
|
end
|
|
|
|
protected
|
|
def resolve_any_conflicts dst
|
|
# if it isn't a directory then a severe conflict is about to happen. Let
|
|
# it, and the exception that is generated will message to the user about
|
|
# the situation
|
|
if dst.symlink? and dst.directory?
|
|
src = (dst.parent+dst.readlink).cleanpath
|
|
keg = Keg.for(src)
|
|
dst.unlink
|
|
keg.link_dir(src) { :mkpath }
|
|
return true
|
|
end
|
|
rescue NotAKegError
|
|
puts "Won't resolve conflicts for symlink #{dst} as it doesn't resolve into the Cellar" if ARGV.verbose?
|
|
end
|
|
|
|
# symlinks the contents of self+foo recursively into /usr/local/foo
|
|
def link_dir foo
|
|
root = self+foo
|
|
return unless root.exist?
|
|
|
|
root.find do |src|
|
|
next if src == root
|
|
|
|
dst = HOMEBREW_PREFIX+src.relative_path_from(self)
|
|
dst.extend ObserverPathnameExtension
|
|
|
|
if src.file?
|
|
dst.make_relative_symlink src unless File.basename(src) == '.DS_Store'
|
|
elsif src.directory?
|
|
# if the dst dir already exists, then great! walk the rest of the tree tho
|
|
next if dst.directory? and not dst.symlink?
|
|
|
|
# no need to put .app bundles in the path, the user can just use
|
|
# spotlight, or the open command and actual mac apps use an equivalent
|
|
Find.prune if src.extname.to_s == '.app'
|
|
|
|
case yield src.relative_path_from(root)
|
|
when :skip
|
|
Find.prune
|
|
when :mkpath
|
|
dst.mkpath unless resolve_any_conflicts(dst)
|
|
else
|
|
unless resolve_any_conflicts(dst)
|
|
dst.make_relative_symlink(src)
|
|
Find.prune
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|