
Rationale: we warn when inreplace makes no changes; this is a similar sort of warning. We expected some list (probably via Dir) to include some files, but none were found. Either the list was wrong, or the install can now be omitted.
398 lines
9.4 KiB
Ruby
398 lines
9.4 KiB
Ruby
require 'pathname'
|
|
require 'bottles'
|
|
|
|
# we enhance pathname to make our code more readable
|
|
class Pathname
|
|
def install *sources
|
|
results = []
|
|
sources.each do |src|
|
|
case src
|
|
when Array
|
|
if src.empty?
|
|
opoo "install was passed an empty array"
|
|
return []
|
|
end
|
|
src.each {|s| results << install_p(s) }
|
|
when Hash
|
|
if src.empty?
|
|
opoo "install was passed an empty hash"
|
|
return []
|
|
end
|
|
src.each {|s, new_basename| results << install_p(s, new_basename) }
|
|
else
|
|
results << install_p(src)
|
|
end
|
|
end
|
|
return results
|
|
end
|
|
|
|
def install_p src, new_basename = nil
|
|
if new_basename
|
|
new_basename = File.basename(new_basename) # rationale: see Pathname.+
|
|
dst = self+new_basename
|
|
return_value = Pathname.new(dst)
|
|
else
|
|
dst = self
|
|
return_value = self+File.basename(src)
|
|
end
|
|
|
|
src = src.to_s
|
|
dst = dst.to_s
|
|
|
|
# if it's a symlink, don't resolve it to a file because if we are moving
|
|
# files one by one, it's likely we will break the symlink by moving what
|
|
# it points to before we move it
|
|
# and also broken symlinks are not the end of the world
|
|
raise "#{src} does not exist" unless File.symlink? src or File.exist? src
|
|
|
|
mkpath
|
|
if File.symlink? src
|
|
# we use the BSD mv command because FileUtils copies the target and
|
|
# not the link! I'm beginning to wish I'd used Python quite honestly!
|
|
raise unless Kernel.system 'mv', src, dst
|
|
else
|
|
# we mv when possible as it is faster and you should only be using
|
|
# this function when installing from the temporary build directory
|
|
FileUtils.mv src, dst
|
|
end
|
|
|
|
return return_value
|
|
end
|
|
|
|
# Creates symlinks to sources in this folder.
|
|
def install_symlink *sources
|
|
results = []
|
|
sources.each do |src|
|
|
case src
|
|
when Array
|
|
src.each {|s| results << install_symlink_p(s) }
|
|
when Hash
|
|
src.each {|s, new_basename| results << install_symlink_p(s, new_basename) }
|
|
else
|
|
results << install_symlink_p(src)
|
|
end
|
|
end
|
|
return results
|
|
end
|
|
|
|
def install_symlink_p src, new_basename = nil
|
|
if new_basename.nil?
|
|
dst = self+File.basename(src)
|
|
else
|
|
dst = self+File.basename(new_basename)
|
|
end
|
|
|
|
src = src.to_s
|
|
dst = dst.to_s
|
|
|
|
mkpath
|
|
FileUtils.ln_s src, dst
|
|
|
|
return dst
|
|
end
|
|
|
|
# we assume this pathname object is a file obviously
|
|
def write content
|
|
raise "Will not overwrite #{to_s}" if exist? and not ARGV.force?
|
|
dirname.mkpath
|
|
File.open(self, 'w') {|f| f.write content }
|
|
end
|
|
|
|
# NOTE always overwrites
|
|
def atomic_write content
|
|
require 'tempfile'
|
|
tf = Tempfile.new(self.basename.to_s)
|
|
tf.write(content)
|
|
tf.close
|
|
FileUtils.mv tf.path, self.to_s
|
|
end
|
|
|
|
def cp dst
|
|
if file?
|
|
FileUtils.cp to_s, dst
|
|
else
|
|
FileUtils.cp_r to_s, dst
|
|
end
|
|
return dst
|
|
end
|
|
|
|
# extended to support common double extensions
|
|
def extname
|
|
return $1 if to_s =~ bottle_regex
|
|
# old brew bottle style
|
|
return $1 if to_s =~ old_bottle_regex
|
|
/(\.(tar|cpio)\.(gz|bz2|xz|Z))$/.match to_s
|
|
return $1 if $1
|
|
return File.extname(to_s)
|
|
end
|
|
|
|
# for filetypes we support, basename without extension
|
|
def stem
|
|
return File.basename(to_s, extname)
|
|
end
|
|
|
|
# I don't trust the children.length == 0 check particularly, not to mention
|
|
# it is slow to enumerate the whole directory just to see if it is empty,
|
|
# instead rely on good ol' libc and the filesystem
|
|
def rmdir_if_possible
|
|
rmdir
|
|
true
|
|
rescue SystemCallError => e
|
|
raise unless e.errno == Errno::ENOTEMPTY::Errno or e.errno == Errno::EACCES::Errno
|
|
false
|
|
end
|
|
|
|
def chmod_R perms
|
|
require 'fileutils'
|
|
FileUtils.chmod_R perms, to_s
|
|
end
|
|
|
|
def abv
|
|
out=''
|
|
n=`find #{to_s} -type f ! -name .DS_Store | wc -l`.to_i
|
|
out<<"#{n} files, " if n > 1
|
|
out<<`/usr/bin/du -hd0 #{to_s} | cut -d"\t" -f1`.strip
|
|
end
|
|
|
|
# attempts to retrieve the version component of this path, so generally
|
|
# you'll call it on tarballs or extracted tarball directories, if you add
|
|
# to this please provide amend the unittest
|
|
def version
|
|
if directory?
|
|
# directories don't have extnames
|
|
stem=basename.to_s
|
|
else
|
|
# sourceforge /download
|
|
if %r[((?:sourceforge.net|sf.net)/.*)/download$].match to_s
|
|
stem=Pathname.new(dirname).stem
|
|
else
|
|
stem=self.stem
|
|
end
|
|
end
|
|
|
|
# github tarballs, like v1.2.3
|
|
%r[github.com/.*/(zip|tar)ball/v?((\d+\.)+\d+)$].match to_s
|
|
return $2 if $2
|
|
|
|
# eg. https://github.com/sam-github/libnet/tarball/libnet-1.1.4
|
|
%r[github.com/.*/(zip|tar)ball/.*-((\d+\.)+\d+)$].match to_s
|
|
return $2 if $2
|
|
|
|
# dashed version
|
|
# eg. github.com/isaacs/npm/tarball/v0.2.5-1
|
|
%r[github.com/.*/(zip|tar)ball/v?((\d+\.)+\d+-(\d+))$].match to_s
|
|
return $2 if $2
|
|
|
|
# underscore version
|
|
# eg. github.com/petdance/ack/tarball/1.93_02
|
|
%r[github.com/.*/(zip|tar)ball/v?((\d+\.)+\d+_(\d+))$].match to_s
|
|
return $2 if $2
|
|
|
|
# eg. boost_1_39_0
|
|
/((\d+_)+\d+)$/.match stem
|
|
return $1.gsub('_', '.') if $1
|
|
|
|
# eg. foobar-4.5.1-1
|
|
# eg. ruby-1.9.1-p243
|
|
/-((\d+\.)*\d\.\d+-(p|rc|RC)?\d+)$/.match stem
|
|
return $1 if $1
|
|
|
|
# eg. lame-398-1
|
|
/-((\d)+-\d)/.match stem
|
|
return $1 if $1
|
|
|
|
# eg. foobar-4.5.1
|
|
/-((\d+\.)*\d+)$/.match stem
|
|
return $1 if $1
|
|
|
|
# eg. foobar-4.5.1b
|
|
/-((\d+\.)*\d+([abc]|rc|RC)\d*)$/.match stem
|
|
return $1 if $1
|
|
|
|
# eg foobar-4.5.0-beta1, or foobar-4.50-beta
|
|
/-((\d+\.)*\d+-beta(\d+)?)$/.match stem
|
|
return $1 if $1
|
|
|
|
# eg. foobar4.5.1
|
|
/((\d+\.)*\d+)$/.match stem
|
|
return $1 if $1
|
|
|
|
# eg foobar-4.5.0-bin
|
|
/-((\d+\.)+\d+[abc]?)[-._](bin|dist|stable|src|sources?)$/.match stem
|
|
return $1 if $1
|
|
|
|
# Debian style eg dash_0.5.5.1.orig.tar.gz
|
|
/_((\d+\.)+\d+[abc]?)[.]orig$/.match stem
|
|
return $1 if $1
|
|
|
|
# eg. otp_src_R13B (this is erlang's style)
|
|
# eg. astyle_1.23_macosx.tar.gz
|
|
stem.scan(/_([^_]+)/) do |match|
|
|
return match.first if /\d/.match $1
|
|
end
|
|
|
|
# old erlang bottle style e.g. erlang-R14B03-bottle.tar.gz
|
|
/-([^-]+)/.match stem
|
|
return $1 if $1
|
|
|
|
nil
|
|
end
|
|
|
|
def incremental_hash(hasher)
|
|
incr_hash = hasher.new
|
|
self.open('r') do |f|
|
|
while(buf = f.read(1024))
|
|
incr_hash << buf
|
|
end
|
|
end
|
|
incr_hash.hexdigest
|
|
end
|
|
|
|
def md5
|
|
require 'digest/md5'
|
|
incremental_hash(Digest::MD5)
|
|
end
|
|
|
|
def sha1
|
|
require 'digest/sha1'
|
|
incremental_hash(Digest::SHA1)
|
|
end
|
|
|
|
def sha2
|
|
require 'digest/sha2'
|
|
incremental_hash(Digest::SHA2)
|
|
end
|
|
|
|
if '1.9' <= RUBY_VERSION
|
|
alias_method :to_str, :to_s
|
|
end
|
|
|
|
def cd
|
|
Dir.chdir(self){ yield }
|
|
end
|
|
|
|
def subdirs
|
|
children.select{ |child| child.directory? }
|
|
end
|
|
|
|
def resolved_path
|
|
self.symlink? ? dirname+readlink : self
|
|
end
|
|
|
|
def resolved_path_exists?
|
|
(dirname+readlink).exist?
|
|
end
|
|
|
|
# perhaps confusingly, this Pathname object becomes the symlink pointing to
|
|
# the src paramter.
|
|
def make_relative_symlink src
|
|
src = Pathname.new(src) unless src.kind_of? Pathname
|
|
|
|
self.dirname.mkpath
|
|
Dir.chdir self.dirname do
|
|
# NOTE only system ln -s will create RELATIVE symlinks
|
|
quiet_system 'ln', '-s', src.relative_path_from(self.dirname), self.basename
|
|
if not $?.success?
|
|
raise <<-EOS.undent
|
|
Could not symlink file: #{src.expand_path}
|
|
Check #{self} does not already exist.
|
|
Check #{dirname} is writable.
|
|
EOS
|
|
end
|
|
end
|
|
end
|
|
|
|
def / that
|
|
join that.to_s
|
|
end
|
|
|
|
def ensure_writable
|
|
saved_perms = nil
|
|
unless writable?
|
|
saved_perms = stat.mode
|
|
chmod 0644
|
|
end
|
|
yield
|
|
ensure
|
|
chmod saved_perms if saved_perms
|
|
end
|
|
|
|
def install_info
|
|
unless self.symlink?
|
|
raise "Cannot install info entry for unbrewed info file '#{self}'"
|
|
end
|
|
system '/usr/bin/install-info', '--quiet', self.to_s, (self.dirname+'dir').to_s
|
|
end
|
|
|
|
def uninstall_info
|
|
unless self.symlink?
|
|
raise "Cannot uninstall info entry for unbrewed info file '#{self}'"
|
|
end
|
|
system '/usr/bin/install-info', '--delete', '--quiet', self.to_s, (self.dirname+'dir').to_s
|
|
end
|
|
|
|
def all_formula pwd = self
|
|
children.map{ |child| child.relative_path_from(pwd) }.each do |pn|
|
|
yield pn if pn.to_s =~ /.rb$/
|
|
end
|
|
children.each do |child|
|
|
child.all_formula(pwd) do |pn|
|
|
yield pn
|
|
end if child.directory?
|
|
end
|
|
end
|
|
|
|
def find_formula
|
|
# remove special casing once tap is established and alt removed
|
|
if self == HOMEBREW_LIBRARY/"Taps/adamv-alt"
|
|
all_formula do |file|
|
|
yield file
|
|
end
|
|
return
|
|
end
|
|
|
|
[self/:Formula, self/:HomebrewFormula, self].each do |d|
|
|
if d.exist?
|
|
d.children.map{ |child| child.relative_path_from(self) }.each do |pn|
|
|
yield pn if pn.to_s =~ /.rb$/
|
|
end
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
# sets $n and $d so you can observe creation of stuff
|
|
module ObserverPathnameExtension
|
|
def unlink
|
|
super
|
|
puts "rm #{to_s}" if ARGV.verbose?
|
|
$n+=1
|
|
end
|
|
def rmdir
|
|
super
|
|
puts "rmdir #{to_s}" if ARGV.verbose?
|
|
$d+=1
|
|
end
|
|
def mkpath
|
|
super
|
|
puts "mkpath #{to_s}" if ARGV.verbose?
|
|
$d+=1
|
|
end
|
|
def make_relative_symlink src
|
|
super
|
|
$n+=1
|
|
end
|
|
def install_info
|
|
super
|
|
puts "info #{to_s}" if ARGV.verbose?
|
|
end
|
|
def uninstall_info
|
|
super
|
|
puts "uninfo #{to_s}" if ARGV.verbose?
|
|
end
|
|
end
|
|
|
|
$n=0
|
|
$d=0
|
|
|