diff --git a/lib/grit/git-ruby.rb b/lib/grit/git-ruby.rb index 71221c5..3a759fb 100644 --- a/lib/grit/git-ruby.rb +++ b/lib/grit/git-ruby.rb @@ -76,15 +76,49 @@ module Grit end def blame_tree(commit, path = nil) - temp = Repository.new(@git_dir, :map_packfile => true) - temp.blame_tree(rev_parse({}, commit), path) + begin # try index file, sooooo much faster + index = FileIndex.new(@git_dir) + commits = index.last_commits(commit, looking_for(commit, path)) + clean_paths(commits, path) + rescue + temp = Repository.new(@git_dir, :map_packfile => true) + temp.blame_tree(rev_parse({}, commit), path) + end end def ruby_git @ruby_git_repo ||= Repository.new(@git_dir) end + private + def looking_for(commit, path = nil) + tree_sha = ruby_git.get_subtree(rev_parse({}, commit), path) + + looking_for = [] + ruby_git.get_object_by_sha1(tree_sha).entry.each do |e| + if path && !(path == '' || path == '.' || path == './') + file = File.join(path, e.name) + else + file = e.name + end + looking_for << file + end + looking_for + end + + def clean_paths(commit_array, path) + return commit_array if !path || (path == '' || path == '.' || path == './') + + new_commits = {} + path_match = Regexp.new(path + '/') + commit_array.each do |file, sha| + amended = file.sub(path_match, '') + new_commits[amended] = sha + end + new_commits + end + # TODO # git grep -n 'foo' 'master' # git log --pretty='raw' --max-count='1' 'master' -- 'LICENSE' diff --git a/lib/grit/git-ruby/file_index.rb b/lib/grit/git-ruby/file_index.rb index 0501f4e..e2c56fd 100644 --- a/lib/grit/git-ruby/file_index.rb +++ b/lib/grit/git-ruby/file_index.rb @@ -148,7 +148,7 @@ if __FILE__ == $0 end x.report('commit count') do i = Grit::GitRuby::FileIndex.new(repo) - puts i.count(commit) + i.count(commit) end x.report('commits list') do i = Grit::GitRuby::FileIndex.new(repo) diff --git a/lib/grit/git-ruby/repository.rb b/lib/grit/git-ruby/repository.rb index 9b9aff0..47bea4f 100644 --- a/lib/grit/git-ruby/repository.rb +++ b/lib/grit/git-ruby/repository.rb @@ -525,9 +525,7 @@ module Grit def look_for_commits(commit_sha, path, looking_for, options = {}) return [] if @already_searched[commit_sha] # to prevent rechecking branches - - puts looking_for.inspect - + @already_searched[commit_sha] = true commit = get_object_by_sha1(commit_sha) diff --git a/test/test_blame_tree.rb b/test/test_blame_tree.rb index 6bce8c2..cfd9622 100644 --- a/test/test_blame_tree.rb +++ b/test/test_blame_tree.rb @@ -25,7 +25,7 @@ class TestBlameTree < Test::Unit::TestCase commit = '2d3acf90f35989df8f262dc50beadc4ee3ae1560' tree = @git.blame_tree(commit, 'lib/grit') last_commit_sha = tree['diff.rb'] - assert_equal last_commit_sha, '28e7a1d3dd172a8e757ff777ab205a538b80385e' + assert_equal last_commit_sha, '22825175e37f22c9418d756ca69b574d75602994' end end \ No newline at end of file