refactor update command to use git diff instead of parsing pull output

This fixes reporting of which formulae changed in git versions where `pull`
output is not compatible.

Signed-off-by: Adam Vandenberg <flangy@gmail.com>
This commit is contained in:
Mislav Marohnić 2011-06-12 17:07:59 +02:00 committed by Adam Vandenberg
parent 5fdb145e76
commit 8c521ca3d0
3 changed files with 138 additions and 123 deletions

View File

@ -16,69 +16,71 @@ class RefreshBrew
INIT_COMMAND = "git init" INIT_COMMAND = "git init"
CHECKOUT_COMMAND = "git checkout -q master" CHECKOUT_COMMAND = "git checkout -q master"
UPDATE_COMMAND = "git pull #{REPOSITORY_URL} master" UPDATE_COMMAND = "git pull #{REPOSITORY_URL} master"
REVISION_COMMAND = "git log -l -1 --pretty=format:%H 2> /dev/null" REVISION_COMMAND = "git rev-parse HEAD"
GIT_UP_TO_DATE = "Already up-to-date." DIFF_COMMAND = "git diff-tree -r --name-status -z %s %s"
formula_regexp = 'Library/Formula/(.+?)\.rb' FORMULA_DIR = 'Library/Formula/'
ADDED_FORMULA = %r{^\s+create mode \d+ #{formula_regexp}$} EXAMPLE_DIR = 'Library/Contributions/examples/'
UPDATED_FORMULA = %r{^\s+#{formula_regexp}\s}
DELETED_FORMULA = %r{^\s+delete mode \d+ #{formula_regexp}$}
example_regexp = 'Library/Contributions/examples/([^.\s]+).*'
ADDED_EXAMPLE = %r{^\s+create mode \d+ #{example_regexp}$}
UPDATED_EXAMPLE = %r{^\s+#{example_regexp}}
DELETED_EXAMPLE = %r{^\s+delete mode \d+ #{example_regexp}$}
attr_reader :added_formulae, :updated_formulae, :deleted_formulae, :installed_formulae attr_reader :added_formulae, :updated_formulae, :deleted_formulae, :installed_formulae
attr_reader :added_examples, :updated_examples, :deleted_examples attr_reader :added_examples, :updated_examples, :deleted_examples
attr_reader :initial_revision attr_reader :initial_revision, :current_revision
def initialize def initialize
@added_formulae, @updated_formulae, @deleted_formulae, @installed_formulae = [], [], [], [] @added_formulae, @updated_formulae, @deleted_formulae, @installed_formulae = [], [], [], []
@added_examples, @updated_examples, @deleted_examples = [], [], [] @added_examples, @updated_examples, @deleted_examples = [], [], []
@initial_revision = self.current_revision @initial_revision, @current_revision = nil
end end
# Performs an update of the homebrew source. Returns +true+ if a newer # Performs an update of the homebrew source. Returns +true+ if a newer
# version was available, +false+ if already up-to-date. # version was available, +false+ if already up-to-date.
def update_from_masterbrew! def update_from_masterbrew!
output = ''
HOMEBREW_REPOSITORY.cd do HOMEBREW_REPOSITORY.cd do
if File.directory? '.git' if git_repo?
safe_system CHECKOUT_COMMAND safe_system CHECKOUT_COMMAND
@initial_revision = read_revision
else else
safe_system INIT_COMMAND safe_system INIT_COMMAND
end end
output = execute(UPDATE_COMMAND) execute(UPDATE_COMMAND)
@current_revision = read_revision
end end
output.split("\n").reverse.each do |line| if initial_revision && initial_revision != current_revision
case line # hash with status characters for keys:
when ADDED_FORMULA # Added (A), Copied (C), Deleted (D), Modified (M), Renamed (R)
@added_formulae << $1 @changes_map = Hash.new {|h,k| h[k] = [] }
when DELETED_FORMULA
@deleted_formulae << $1 changes = HOMEBREW_REPOSITORY.cd do
when UPDATED_FORMULA execute(DIFF_COMMAND % [initial_revision, current_revision]).split("\0")
@updated_formulae << $1 unless @added_formulae.include?($1) or @deleted_formulae.include?($1) end
when ADDED_EXAMPLE
@added_examples << $1 while status = changes.shift
when DELETED_EXAMPLE file = changes.shift
@deleted_examples << $1 @changes_map[status] << file
when UPDATED_EXAMPLE end
@updated_examples << $1 unless @added_examples.include?($1) or @deleted_examples.include?($1)
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)
@updated_examples = changed_items('M', EXAMPLE_DIR)
@installed_formulae = HOMEBREW_CELLAR.children.
select{ |pn| pn.directory? }.
map{ |pn| pn.basename.to_s }.sort
return true
end end
end end
@added_formulae.sort! # assume nothing was updated
@updated_formulae.sort! return false
@deleted_formulae.sort! end
@added_examples.sort!
@updated_examples.sort!
@deleted_examples.sort!
@installed_formulae = HOMEBREW_CELLAR.children.
select{ |pn| pn.directory? }.
map{ |pn| pn.basename.to_s }.sort
output.strip != GIT_UP_TO_DATE def git_repo?
File.directory? '.git'
end end
def pending_formulae_changes? def pending_formulae_changes?
@ -105,12 +107,6 @@ class RefreshBrew
!@deleted_examples.empty? !@deleted_examples.empty?
end end
def current_revision
HOMEBREW_REPOSITORY.cd { execute(REVISION_COMMAND).strip }
rescue
'TAIL'
end
def report def report
puts "Updated Homebrew from #{initial_revision[0,8]} to #{current_revision[0,8]}." puts "Updated Homebrew from #{initial_revision[0,8]} to #{current_revision[0,8]}."
## New Formulae ## New Formulae
@ -151,10 +147,27 @@ class RefreshBrew
private private
def read_revision
execute(REVISION_COMMAND).chomp
end
def filter_by_directory(files, dir)
files.select { |f| f.index(dir) == 0 }
end
def basenames(files)
files.map { |f| File.basename(f, '.rb') }
end
# extracts items by status from @changes_map
def changed_items(status, dir)
basenames(filter_by_directory(@changes_map[status], dir)).sort
end
def execute(cmd) def execute(cmd)
out = `#{cmd}` out = `#{cmd}`
if $? && !$?.success? if $? && !$?.success?
puts out $stderr.puts out
raise "Failed while executing #{cmd}" raise "Failed while executing #{cmd}"
end end
ohai(cmd, out) if ARGV.verbose? ohai(cmd, out) if ARGV.verbose?

View File

@ -1,53 +1,26 @@
update_git_pull_output_without_formulae_changes: | update_git_diff_output_without_formulae_changes: |
remote: counting objects: 58, done. M Library/Homebrew/ARGV+yeast.rb
remote: Compressing objects: 100% (35/35), done. A Library/Homebrew/beer_events.rb
remote: Total 39 (delta 20), reused 0 (delta 0) A Library/Homebrew/hardware.rb
Unpacking objects: 100% (39/39), done. D Library/Homebrew/hw.model.c
From git://github.com/mxcl/homebrew M README
* branch master -> FETCH_HEAD M bin/brew
Updating 14ef7f9..f414bc8 update_git_diff_output_with_formulae_changes: |
Fast forward M Library/Contributions/brew_bash_completion.sh
Library/Homebrew/ARGV+yeast.rb | 35 ++-- A Library/Formula/antiword.rb
Library/Homebrew/beer_events.rb | 181 +++++++++++++ A Library/Formula/bash-completion.rb
Library/Homebrew/hardware.rb | 71 ++++++ M Library/Formula/xar.rb
Library/Homebrew/hw.model.c | 17 -- M Library/Formula/yajl.rb
README | 337 +++++++++++++------------ M Library/Homebrew/ARGV+yeast.rb
bin/brew | 137 ++++++++--- M Library/Homebrew/pathname+yeast.rb
40 files changed, 1107 insertions(+), 426 deletions(-) M Library/Homebrew/unittest.rb
create mode 100644 Library/Homebrew/beer_events.rb M Library/Homebrew/utils.rb
create mode 100644 Library/Homebrew/hardware.rb M README
delete mode 100644 Library/Homebrew/hw.model.c M bin/brew
delete mode 100644 Library/Homebrew/hw.model.rb A Library/Formula/ddrescue.rb
update_git_pull_output_with_formulae_changes: | A Library/Formula/dict.rb
remote: counting objects: 58, done. A Library/Formula/lua.rb
remote: Compressing objects: 100% (35/35), done. A Library/Homebrew/beer_events.rb
remote: Total 39 (delta 20), reused 0 (delta 0) A Library/Homebrew/hardware.rb
Unpacking objects: 100% (39/39), done. D Library/Homebrew/hw.model.c
From git://github.com/mxcl/homebrew D Library/Homebrew/hw.model.rb
* branch master -> FETCH_HEAD
Updating 14ef7f9..f414bc8
Fast forward
Library/Contributions/brew_bash_completion.sh | 6 +-
Library/Formula/antiword.rb | 13 +
Library/Formula/bash-completion.rb | 25 ++
Library/Formula/xar.rb | 19 ++
Library/Formula/yajl.rb | 2 +-
Library/Homebrew/ARGV+yeast.rb | 35 ++--
Library/Homebrew/beer_events.rb | 181 +++++++++++++
Library/Homebrew/hardware.rb | 71 ++++++
Library/Homebrew/hw.model.c | 17 --
Library/Homebrew/pathname+yeast.rb | 28 ++-
Library/Homebrew/unittest.rb | 106 ++++++++-
Library/Homebrew/utils.rb | 36 ++-
README | 337 +++++++++++++------------
bin/brew | 137 ++++++++---
40 files changed, 1107 insertions(+), 426 deletions(-)
create mode 100644 Library/Formula/antiword.rb
create mode 100644 Library/Formula/bash-completion.rb
create mode 100644 Library/Formula/ddrescue.rb
create mode 100644 Library/Formula/dict.rb
create mode 100644 Library/Formula/lua.rb
create mode 100644 Library/Homebrew/beer_events.rb
create mode 100644 Library/Homebrew/hardware.rb
delete mode 100644 Library/Homebrew/hw.model.c
delete mode 100644 Library/Homebrew/hw.model.rb

View File

@ -11,15 +11,23 @@ require 'utils'
require 'cmd/update' require 'cmd/update'
class RefreshBrewMock < RefreshBrew class RefreshBrewMock < RefreshBrew
def in_prefix_expect(expect, returns = '') def git_repo?
@expect ||= {} @git_repo
@expect[expect] = returns end
attr_writer :git_repo
def in_prefix_expect(cmd, output = '')
@outputs ||= Hash.new { |h,k| h[k] = [] }
@expected ||= []
@expected << cmd
@outputs[cmd] << output
end end
def `(cmd) def `(cmd)
if Dir.pwd == HOMEBREW_PREFIX.to_s and @expect.has_key?(cmd) if Dir.pwd == HOMEBREW_PREFIX.to_s and @expected.include?(cmd) and !@outputs[cmd].empty?
(@called ||= []) << cmd @called ||= []
@expect[cmd] @called << cmd
@outputs[cmd].shift
else else
raise "#{inspect} Unexpectedly called backticks in pwd `#{HOMEBREW_PREFIX}' and command `#{cmd}'" raise "#{inspect} Unexpectedly called backticks in pwd `#{HOMEBREW_PREFIX}' and command `#{cmd}'"
end end
@ -28,7 +36,7 @@ class RefreshBrewMock < RefreshBrew
alias safe_system ` alias safe_system `
def expectations_met? def expectations_met?
@expect.keys.sort == @called.sort @expected == @called
end end
def inspect def inspect
@ -54,11 +62,30 @@ class UpdaterTests < Test::Unit::TestCase
@fixture_data @fixture_data
end end
def test_init_homebrew
outside_prefix do
updater = RefreshBrewMock.new
updater.git_repo = false
updater.in_prefix_expect("git init")
updater.in_prefix_expect("git pull #{RefreshBrewMock::REPOSITORY_URL} master")
updater.in_prefix_expect("git rev-parse HEAD", "1234abcd")
assert_equal false, updater.update_from_masterbrew!
assert updater.expectations_met?
assert updater.updated_formulae.empty?
assert updater.added_formulae.empty?
end
end
def test_update_homebrew_without_any_changes def test_update_homebrew_without_any_changes
outside_prefix do outside_prefix do
updater = RefreshBrewMock.new updater = RefreshBrewMock.new
updater.in_prefix_expect(RefreshBrew::INIT_COMMAND) updater.git_repo = true
updater.in_prefix_expect(RefreshBrew::UPDATE_COMMAND, "Already up-to-date.\n") updater.in_prefix_expect("git checkout -q master")
updater.in_prefix_expect("git rev-parse HEAD", "1234abcd")
updater.in_prefix_expect("git pull #{RefreshBrewMock::REPOSITORY_URL} master")
updater.in_prefix_expect("git rev-parse HEAD", "3456cdef")
updater.in_prefix_expect("git diff-tree -r --name-status -z 1234abcd 3456cdef", "")
assert_equal false, updater.update_from_masterbrew! assert_equal false, updater.update_from_masterbrew!
assert updater.expectations_met? assert updater.expectations_met?
@ -70,9 +97,14 @@ class UpdaterTests < Test::Unit::TestCase
def test_update_homebrew_without_formulae_changes def test_update_homebrew_without_formulae_changes
outside_prefix do outside_prefix do
updater = RefreshBrewMock.new updater = RefreshBrewMock.new
updater.in_prefix_expect(RefreshBrew::INIT_COMMAND) updater.git_repo = true
output = fixture('update_git_pull_output_without_formulae_changes') diff_output = fixture('update_git_diff_output_without_formulae_changes')
updater.in_prefix_expect(RefreshBrew::UPDATE_COMMAND, output)
updater.in_prefix_expect("git checkout -q master")
updater.in_prefix_expect("git rev-parse HEAD", "1234abcd")
updater.in_prefix_expect("git pull #{RefreshBrewMock::REPOSITORY_URL} master")
updater.in_prefix_expect("git rev-parse HEAD", "3456cdef")
updater.in_prefix_expect("git diff-tree -r --name-status -z 1234abcd 3456cdef", diff_output.gsub(/\s+/, "\0"))
assert_equal true, updater.update_from_masterbrew! assert_equal true, updater.update_from_masterbrew!
assert !updater.pending_formulae_changes? assert !updater.pending_formulae_changes?
@ -84,9 +116,14 @@ class UpdaterTests < Test::Unit::TestCase
def test_update_homebrew_with_formulae_changes def test_update_homebrew_with_formulae_changes
outside_prefix do outside_prefix do
updater = RefreshBrewMock.new updater = RefreshBrewMock.new
updater.in_prefix_expect(RefreshBrew::INIT_COMMAND) updater.git_repo = true
output = fixture('update_git_pull_output_with_formulae_changes') diff_output = fixture('update_git_diff_output_with_formulae_changes')
updater.in_prefix_expect(RefreshBrew::UPDATE_COMMAND, output)
updater.in_prefix_expect("git checkout -q master")
updater.in_prefix_expect("git rev-parse HEAD", "1234abcd")
updater.in_prefix_expect("git pull #{RefreshBrewMock::REPOSITORY_URL} master")
updater.in_prefix_expect("git rev-parse HEAD", "3456cdef")
updater.in_prefix_expect("git diff-tree -r --name-status -z 1234abcd 3456cdef", diff_output.gsub(/\s+/, "\0"))
assert_equal true, updater.update_from_masterbrew! assert_equal true, updater.update_from_masterbrew!
assert updater.pending_formulae_changes? assert updater.pending_formulae_changes?
@ -94,12 +131,4 @@ class UpdaterTests < Test::Unit::TestCase
assert_equal %w{ antiword bash-completion ddrescue dict lua }, updater.added_formulae assert_equal %w{ antiword bash-completion ddrescue dict lua }, updater.added_formulae
end end
end end
def test_updater_returns_current_revision
outside_prefix do
updater = RefreshBrewMock.new
updater.in_prefix_expect(RefreshBrew::REVISION_COMMAND, 'the-revision-hash')
assert_equal 'the-revision-hash', updater.current_revision
end
end
end end