brew/Library/Homebrew/cmd/update.rb

194 lines
4.8 KiB
Ruby
Raw Normal View History

require 'cmd/tap'
require 'cmd/untap'
module Homebrew extend self
def update
unless ARGV.named.empty?
abort <<-EOS.undent
This command updates brew itself, and does not take formula names.
Use `brew upgrade <formula>`.
EOS
end
abort "Please `brew install git' first." unless which "git"
# ensure GIT_CONFIG is unset as we need to operate on .git/config
ENV.delete('GIT_CONFIG')
2012-03-06 02:23:01 +00:00
cd HOMEBREW_REPOSITORY
git_init_if_necessary
2011-09-20 02:25:50 +01:00
2012-03-06 02:23:01 +00:00
report = Report.new
master_updater = Updater.new
master_updater.pull!
report.merge!(master_updater.report)
2012-03-06 02:23:01 +00:00
Dir["Library/Taps/*"].each do |tapd|
next unless File.directory?(tapd)
2012-03-06 02:23:01 +00:00
cd tapd do
begin
updater = Updater.new
updater.pull!
report.merge!(updater.report) do |key, oldval, newval|
oldval.concat(newval)
end
rescue
tapd =~ %r{^Library/Taps/(\w+)-(\w+)}
onoe "Failed to update tap: #$1/#$2"
2012-03-06 02:23:01 +00:00
end
end
2012-03-06 02:23:01 +00:00
end
# we unlink first in case the formula has moved to another tap
Homebrew.unlink_tap_formula(report.removed_tapped_formula)
Homebrew.link_tap_formula(report.new_tapped_formula)
2012-03-06 02:23:01 +00:00
if report.empty?
puts "Already up-to-date."
else
puts "Updated Homebrew from #{master_updater.initial_revision[0,8]} to #{master_updater.current_revision[0,8]}."
report.dump
end
end
2012-03-06 02:23:01 +00:00
private
2012-03-06 02:23:01 +00:00
def git_init_if_necessary
if Dir['.git/*'].empty?
safe_system "git init"
safe_system "git config core.autocrlf false"
safe_system "git remote add origin https://github.com/mxcl/homebrew.git"
safe_system "git fetch origin"
safe_system "git reset --hard origin/master"
end
2012-03-06 02:23:01 +00:00
rescue Exception
FileUtils.rm_rf ".git"
raise
end
2012-03-06 02:23:01 +00:00
end
2012-03-06 02:23:01 +00:00
class Updater
attr_reader :initial_revision, :current_revision
2012-03-06 02:23:01 +00:00
def pull!
safe_system "git checkout -q master"
2012-03-06 02:23:01 +00:00
@initial_revision = read_current_revision
2012-03-06 02:23:01 +00:00
# ensure we don't munge line endings on checkout
safe_system "git config core.autocrlf false"
2012-03-06 02:23:01 +00:00
args = ["pull"]
args << "--rebase" if ARGV.include? "--rebase"
args << "-q" unless ARGV.verbose?
args << "origin"
# the refspec ensures that 'origin/master' gets updated
args << "refs/heads/master:refs/remotes/origin/master"
safe_system "git", *args
2012-03-06 02:23:01 +00:00
@current_revision = read_current_revision
end
# Matches raw git diff format (see `man git-diff-tree`)
DIFFTREE_RX = /^:[0-7]{6} [0-7]{6} [0-9a-fA-F]{40} [0-9a-fA-F]{40} ([ACDMR])\d{0,3}\t(.+?)(?:\t(.+))?$/
def report
2012-03-06 02:23:01 +00:00
map = Hash.new{ |h,k| h[k] = [] }
2012-03-06 02:23:01 +00:00
if initial_revision && initial_revision != current_revision
`git diff-tree -r --raw -M85% #{initial_revision} #{current_revision}`.each_line do |line|
DIFFTREE_RX.match line
path = case status = $1.to_sym
when :R then $3
else $2
end
path = Pathname.pwd.join(path).relative_path_from(HOMEBREW_REPOSITORY)
map[status] << path.to_s
2012-03-06 02:23:01 +00:00
end
end
2012-03-06 02:23:01 +00:00
map
end
private
2010-07-23 17:37:03 -07:00
2012-03-06 02:23:01 +00:00
def read_current_revision
`git rev-parse -q --verify HEAD`.chomp
end
2012-03-06 02:23:01 +00:00
def `(cmd)
out = Kernel.`(cmd) #`
if $? && !$?.success?
$stderr.puts out
raise ErrorDuringExecution, "Failure while executing: #{cmd}"
end
ohai(cmd, out) if ARGV.verbose?
out
end
2012-03-06 02:23:01 +00:00
end
class Report < Hash
2012-03-06 02:23:01 +00:00
def dump
# Key Legend: Added (A), Copied (C), Deleted (D), Modified (M), Renamed (R)
dump_formula_report :A, "New Formulae"
dump_formula_report :M, "Updated Formulae"
dump_formula_report :D, "Deleted Formulae"
dump_formula_report :R, "Renamed Formulae"
2012-03-06 02:23:01 +00:00
# dump_new_commands
# dump_deleted_commands
end
def tapped_formula_for key
fetch(key, []).map do |path|
case path when %r{^Library/Taps/(\w+-\w+/.*)}
relative_path = $1
if valid_formula_location?(relative_path)
Pathname.new(relative_path)
end
end
end.compact
end
def valid_formula_location?(relative_path)
ruby_file = /\A.*\.rb\Z/
parts = relative_path.split('/')[1..-1]
[
parts.length == 1 && parts.first =~ ruby_file,
parts.length == 2 && parts.first == 'Formula' && parts.last =~ ruby_file,
parts.length == 2 && parts.first == 'HomebrewFormula' && parts.last =~ ruby_file,
].any?
end
def new_tapped_formula
tapped_formula_for :A
end
def removed_tapped_formula
tapped_formula_for :D
end
2012-03-06 02:23:01 +00:00
def select_formula key
fetch(key, []).map do |path|
case path when %r{^Library/Formula}
File.basename(path, ".rb")
when %r{^Library/Taps/(\w+)-(\w+)/(.*)\.rb}
2012-03-06 02:23:01 +00:00
"#$1/#$2/#{File.basename(path, '.rb')}"
end
end.compact.sort
end
2012-03-06 02:23:01 +00:00
def dump_formula_report key, title
formula = select_formula(key)
unless formula.empty?
ohai title
puts_columns formula.uniq
end
end
2012-03-06 02:23:01 +00:00
2009-09-17 18:40:21 +01:00
end