Jack Nagel 37a56fa513 FormulaInstaller: implement installation locks
FormulaInstaller now attempts to take a lock on a "foo.brewing" file for
the formula and all of its dependencies before attempting installation.

The lock is an advisory lock implemented using flock(), and as such it
only locks out other processes that attempt to take the lock. It also
means that it is never necessary to manually remove the lock file,
because the lock is not enforced by I/O.

The uninstall, link, and unlink commands all learn to respect this lock
as well, so that the installation cannot be corrupted by a concurrent
Homebrew process, and keg operations cannot occur simultaneously.
2013-01-26 12:14:45 -06:00

66 lines
1.3 KiB
Ruby

require 'ostruct'
module Homebrew extend self
def link
raise KegUnspecifiedError if ARGV.named.empty?
if Process.uid.zero? and not File.stat(HOMEBREW_BREW_FILE).uid.zero?
raise "Cowardly refusing to `sudo brew link'\n#{SUDO_BAD_ERRMSG}"
end
mode = OpenStruct.new
mode.overwrite = true if ARGV.include? '--overwrite'
mode.dry_run = true if ARGV.dry_run?
ARGV.kegs.each do |keg|
if keg.linked?
opoo "Already linked: #{keg}"
puts "To relink: brew unlink #{keg.fname} && brew link #{keg.fname}"
next
end
if mode.dry_run and mode.overwrite
print "Would remove:\n" do
keg.link(mode)
end
next
elsif mode.dry_run
print "Would link:\n" do
keg.link(mode)
end
next
end
keg.lock do
print "Linking #{keg}... " do
puts "#{keg.link(mode)} symlinks created"
end
end
end
end
private
# Allows us to ensure a puts happens before the block exits so that if say,
# an exception is thrown, its output starts on a new line.
def print str, &block
Kernel.print str
puts_capture = Class.new do
def self.puts str
$did_puts = true
Kernel.puts str
end
end
puts_capture.instance_eval &block
ensure
puts unless $did_puts
end
end