diff options
| author | Max Howell | 2012-03-06 02:23:01 +0000 |
|---|---|---|
| committer | Max Howell | 2012-03-16 21:06:16 +0000 |
| commit | 2e86a41e6162caec5c6922b04746c45c2686a5b1 (patch) | |
| tree | 3034b2185534724502c54b4753a66e1cb699ae1a /Library/Homebrew/cmd/update.rb | |
| parent | 31188c7df34a355bc761b5ff83023192b358a5f3 (diff) | |
| download | homebrew-2e86a41e6162caec5c6922b04746c45c2686a5b1.tar.bz2 | |
`brew update` will update taps
Diffstat (limited to 'Library/Homebrew/cmd/update.rb')
| -rw-r--r-- | Library/Homebrew/cmd/update.rb | 244 |
1 files changed, 95 insertions, 149 deletions
diff --git a/Library/Homebrew/cmd/update.rb b/Library/Homebrew/cmd/update.rb index 7e4157a03..3d7713784 100644 --- a/Library/Homebrew/cmd/update.rb +++ b/Library/Homebrew/cmd/update.rb @@ -1,192 +1,138 @@ module Homebrew extend self + def update abort "Please `brew install git' first." unless system "/usr/bin/which -s git" - updater = RefreshBrew.new - if updater.update_from_masterbrew! - updater.report - else - puts "Already up-to-date." - end - end -end - -class RefreshBrew - REPOSITORY_URL = "https://github.com/mxcl/homebrew.git" - FORMULA_DIR = 'Library/Formula/' - EXAMPLE_DIR = 'Library/Contributions/examples/' - - attr_reader :added_formulae, :updated_formulae, :deleted_formulae, :installed_formulae - attr_reader :added_examples, :deleted_examples - attr_reader :initial_revision, :current_revision - - def initialize - @added_formulae, @updated_formulae, @deleted_formulae, @installed_formulae = [], [], [], [] - @added_examples, @deleted_examples = [], [], [] - @initial_revision, @current_revision = nil - end - - # Performs an update of the homebrew source. Returns +true+ if a newer - # version was available, +false+ if already up-to-date. - def update_from_masterbrew! # ensure GIT_CONFIG is unset as we need to operate on .git/config ENV.delete('GIT_CONFIG') - HOMEBREW_REPOSITORY.cd do - if git_repo? - safe_system "git checkout -q master" - @initial_revision = read_revision - # originally we fetched by URL but then we decided that we should - # use origin so that it's easier for forks to operate seamlessly - unless `git remote`.split.include? 'origin' - safe_system "git remote add origin #{REPOSITORY_URL}" - end - else - begin - safe_system "git init" - safe_system "git config core.autocrlf false" - safe_system "git remote add origin #{REPOSITORY_URL}" - safe_system "git fetch origin" - safe_system "git reset --hard origin/master" - rescue Exception - safe_system "/bin/rm -rf .git" - raise - end - end + cd HOMEBREW_REPOSITORY + git_init_if_necessary - # ensure we don't munge line endings on checkout - safe_system "git config core.autocrlf false" - # specify a refspec so that 'origin/master' gets updated - refspec = "refs/heads/master:refs/remotes/origin/master" - rebase = "--rebase" if ARGV.include? "--rebase" - execute "git pull #{rebase} origin #{refspec}" - @current_revision = read_revision - end - - if initial_revision && initial_revision != current_revision - # hash with status characters for keys: - # Added (A), Copied (C), Deleted (D), Modified (M), Renamed (R) - @changes_map = Hash.new {|h,k| h[k] = [] } - - changes = HOMEBREW_REPOSITORY.cd do - execute("git diff-tree -r --name-status -z #{initial_revision} #{current_revision}").split("\0") - end + report = Report.new + master_updater = Updater.new + master_updater.pull! + report.merge!(master_updater.report) - while status = changes.shift - file = changes.shift - @changes_map[status] << file + Dir["Library/Taps/*"].each do |tapd| + cd tapd do + updater = Updater.new + updater.pull! + report.merge!(updater.report) do |key, oldval, newval| + oldval.concat(newval) + end end + end - if @changes_map.any? - @added_formulae = changed_items('A', FORMULA_DIR) - @deleted_formulae = changed_items('D', FORMULA_DIR) - @updated_formulae = changed_items('M', FORMULA_DIR) - @added_examples = changed_items('A', EXAMPLE_DIR) - @deleted_examples = changed_items('D', EXAMPLE_DIR) - @added_internal_commands = changed_items('A', "Library/Homebrew/cmd") - @deleted_internal_commands = changed_items('D', "Library/Homebrew/cmd") + 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 - @installed_formulae = HOMEBREW_CELLAR.children. - select{ |pn| pn.directory? }. - map{ |pn| pn.basename.to_s }.sort if HOMEBREW_CELLAR.directory? + private - return true - end + 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 - # assume nothing was updated - return false + rescue Exception + FileUtils.rm_rf ".git" + raise end - def git_repo? - Dir['.git/*'].length > 0 - end +end - def pending_formulae_changes? - !@updated_formulae.empty? - end +class Updater + attr_reader :initial_revision, :current_revision - def pending_new_formulae? - !@added_formulae.empty? - end + def pull! + safe_system "git checkout -q master" - def deleted_formulae? - !@deleted_formulae.empty? - end + @initial_revision = read_current_revision - def pending_examples_changes? - !@updated_examples.empty? - end + # ensure we don't munge line endings on checkout + safe_system "git config core.autocrlf false" - def pending_new_examples? - !@added_examples.empty? - end + 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 - def deleted_examples? - !@deleted_examples.empty? + @current_revision = read_current_revision end def report - puts "Updated Homebrew from #{initial_revision[0,8]} to #{current_revision[0,8]}." - if pending_new_formulae? - ohai "New formulae" - puts_columns added_formulae - end - if deleted_formulae? - ohai "Removed formulae" - puts_columns deleted_formulae, installed_formulae - end - if pending_formulae_changes? - ohai "Updated formulae" - puts_columns updated_formulae, installed_formulae - end + map = Hash.new{ |h,k| h[k] = [] } - unless @added_internal_commands.empty? - ohai "New commands" - puts_columns @added_internal_commands - end - unless @deleted_internal_commands.empty? - ohai "Removed commands" - puts_columns @deleted_internal_commands + if initial_revision && initial_revision != current_revision + changes = `git diff-tree -r --name-status -z #{initial_revision} #{current_revision}`.split("\0") + changes.each_slice(2) do |status, file| + file = Pathname.pwd.join(file).relative_path_from(HOMEBREW_REPOSITORY) + map[status.to_sym] << file.to_s + end end - # external commands aren't generally documented but the distinction - # is loose. They are less "supported" and more "playful". - if pending_new_examples? - ohai "New external commands" - puts_columns added_examples - end - if deleted_examples? - ohai "Removed external commands" - puts_columns deleted_examples - end + map end private - def read_revision - execute("git rev-parse HEAD").chomp + def read_current_revision + `git rev-parse HEAD`.chomp end - def filter_by_directory(files, dir) - files.select { |f| f.index(dir) == 0 } + 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 +end + + +class Report < Hash - def basenames(files) - files.map { |f| File.basename(f, '.rb') } + def dump + # Key Legend: Added (A), Copied (C), Deleted (D), Modified (M), Renamed (R) + + dump_formula_report :A, "New Formula" + dump_formula_report :M, "Updated Formula" + dump_formula_report :D, "Deleted Formula" + dump_formula_report :R, "Renamed Formula" +# dump_new_commands +# dump_deleted_commands end - # extracts items by status from @changes_map - def changed_items(status, dir) - basenames(filter_by_directory(@changes_map[status], dir)).sort + 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+)/(.*)} + "#$1/#$2/#{File.basename(path, '.rb')}" + end + end.compact.sort end - def execute(cmd) - out = `#{cmd}` - if $? && !$?.success? - $stderr.puts out - raise "Failed while executing #{cmd}" + def dump_formula_report key, title + formula = select_formula(key) + unless formula.empty? + ohai title + puts_columns formula end - ohai(cmd, out) if ARGV.verbose? - out end + end |
