mojombo-grit 0.8.1 → 0.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. data/History.txt +7 -0
  2. data/Manifest.txt +18 -1
  3. data/grit.gemspec +56 -10
  4. data/lib/{mojombo-grit.rb → grit.rb} +20 -4
  5. data/lib/grit/commit.rb +32 -11
  6. data/lib/grit/commit_stats.rb +104 -0
  7. data/lib/grit/git-ruby.rb +182 -0
  8. data/lib/grit/git-ruby/commit_db.rb +52 -0
  9. data/lib/grit/git-ruby/file_index.rb +186 -0
  10. data/lib/grit/git-ruby/git_object.rb +344 -0
  11. data/lib/grit/git-ruby/internal/loose.rb +136 -0
  12. data/lib/grit/git-ruby/internal/mmap.rb +58 -0
  13. data/lib/grit/git-ruby/internal/pack.rb +382 -0
  14. data/lib/grit/git-ruby/internal/raw_object.rb +37 -0
  15. data/lib/grit/git-ruby/object.rb +319 -0
  16. data/lib/grit/git-ruby/repository.rb +729 -0
  17. data/lib/grit/git.rb +33 -15
  18. data/lib/grit/head.rb +6 -15
  19. data/lib/grit/index.rb +121 -0
  20. data/lib/grit/ref.rb +95 -0
  21. data/lib/grit/repo.rb +95 -6
  22. data/lib/grit/status.rb +151 -0
  23. data/lib/grit/tree.rb +3 -2
  24. data/test/test_blob.rb +5 -0
  25. data/test/test_commit.rb +7 -5
  26. data/test/test_diff.rb +1 -1
  27. data/test/test_git.rb +20 -2
  28. data/test/test_grit.rb +32 -0
  29. data/test/test_head.rb +30 -5
  30. data/test/test_real.rb +8 -6
  31. data/test/test_remote.rb +14 -0
  32. data/test/test_repo.rb +86 -79
  33. data/test/test_tag.rb +2 -6
  34. data/test/test_tree.rb +5 -0
  35. metadata +40 -40
  36. data/test/fixtures/blame +0 -131
  37. data/test/fixtures/cat_file_blob +0 -1
  38. data/test/fixtures/cat_file_blob_size +0 -1
  39. data/test/fixtures/diff_2 +0 -54
  40. data/test/fixtures/diff_2f +0 -19
  41. data/test/fixtures/diff_f +0 -15
  42. data/test/fixtures/diff_i +0 -201
  43. data/test/fixtures/diff_mode_only +0 -1152
  44. data/test/fixtures/diff_new_mode +0 -17
  45. data/test/fixtures/diff_p +0 -610
  46. data/test/fixtures/for_each_ref +0 -0
  47. data/test/fixtures/for_each_ref_tags +0 -0
  48. data/test/fixtures/ls_tree_a +0 -7
  49. data/test/fixtures/ls_tree_b +0 -2
  50. data/test/fixtures/ls_tree_commit +0 -3
  51. data/test/fixtures/rev_list +0 -26
  52. data/test/fixtures/rev_list_count +0 -655
  53. data/test/fixtures/rev_list_single +0 -7
  54. data/test/fixtures/rev_parse +0 -1
  55. data/test/fixtures/show_empty_commit +0 -6
  56. data/test/fixtures/simple_config +0 -2
  57. data/test/helper.rb +0 -17
  58. data/test/profile.rb +0 -21
  59. data/test/suite.rb +0 -6
data/History.txt CHANGED
@@ -1,6 +1,13 @@
1
+ == 0.8.3 / 2008-07-07
2
+ * Capture stderr and log if debug is true (rsanheim)
3
+
4
+ == 0.8.2 / 2008-06-27
5
+ * Allow user provided logger (rsanheim)
6
+
1
7
  == 0.8.0 / 2008-04-24
2
8
  * Lots of fixes and additions
3
9
 
4
10
  == 0.7.0 / 2008-01-07
5
11
  * First public release!
6
12
 
13
+
data/Manifest.txt CHANGED
@@ -3,19 +3,33 @@ Manifest.txt
3
3
  README.txt
4
4
  Rakefile
5
5
  grit.gemspec
6
- lib/grit.rb
7
6
  lib/grit/actor.rb
8
7
  lib/grit/blob.rb
9
8
  lib/grit/commit.rb
9
+ lib/grit/commit_stats.rb
10
10
  lib/grit/config.rb
11
11
  lib/grit/diff.rb
12
12
  lib/grit/errors.rb
13
+ lib/grit/git-ruby/commit_db.rb
14
+ lib/grit/git-ruby/file_index.rb
15
+ lib/grit/git-ruby/git_object.rb
16
+ lib/grit/git-ruby/internal/loose.rb
17
+ lib/grit/git-ruby/internal/mmap.rb
18
+ lib/grit/git-ruby/internal/pack.rb
19
+ lib/grit/git-ruby/internal/raw_object.rb
20
+ lib/grit/git-ruby/object.rb
21
+ lib/grit/git-ruby/repository.rb
22
+ lib/grit/git-ruby.rb
13
23
  lib/grit/git.rb
14
24
  lib/grit/head.rb
25
+ lib/grit/index.rb
15
26
  lib/grit/lazy.rb
27
+ lib/grit/ref.rb
16
28
  lib/grit/repo.rb
29
+ lib/grit/status.rb
17
30
  lib/grit/tag.rb
18
31
  lib/grit/tree.rb
32
+ lib/grit.rb
19
33
  test/fixtures/blame
20
34
  test/fixtures/cat_file_blob
21
35
  test/fixtures/cat_file_blob_size
@@ -27,6 +41,7 @@ test/fixtures/diff_mode_only
27
41
  test/fixtures/diff_new_mode
28
42
  test/fixtures/diff_p
29
43
  test/fixtures/for_each_ref
44
+ test/fixtures/for_each_ref_remotes
30
45
  test/fixtures/for_each_ref_tags
31
46
  test/fixtures/ls_tree_a
32
47
  test/fixtures/ls_tree_b
@@ -46,8 +61,10 @@ test/test_commit.rb
46
61
  test/test_config.rb
47
62
  test/test_diff.rb
48
63
  test/test_git.rb
64
+ test/test_grit.rb
49
65
  test/test_head.rb
50
66
  test/test_reality.rb
67
+ test/test_remote.rb
51
68
  test/test_repo.rb
52
69
  test/test_tag.rb
53
70
  test/test_tree.rb
data/grit.gemspec CHANGED
@@ -1,16 +1,62 @@
1
1
  Gem::Specification.new do |s|
2
- s.name = "grit"
3
- s.version = "0.8.1"
4
- s.date = "2008-04-24"
5
- s.summary = "Object model interface to a git repo"
6
- s.email = "tom@rubyisawesome.com"
7
- s.homepage = "http://github.com/mojombo/grit"
2
+ s.name = "grit"
3
+ s.version = "0.9.3"
4
+ s.date = "2008-04-24"
5
+ s.summary = "Object model interface to a git repo"
6
+ s.email = "tom@rubyisawesome.com"
7
+ s.homepage = "http://github.com/schacon/grit"
8
8
  s.description = "Grit is a Ruby library for extracting information from a git repository in and object oriented manner."
9
9
  s.has_rdoc = true
10
- s.authors = ["Tom Preston-Werner"]
11
- s.files = ["History.txt", "Manifest.txt", "README.txt", "Rakefile", "grit.gemspec", "lib/grit.rb", "lib/grit/actor.rb", "lib/grit/blob.rb", "lib/grit/commit.rb", "lib/grit/config.rb", "lib/grit/diff.rb", "lib/grit/errors.rb", "lib/grit/git.rb", "lib/grit/head.rb", "lib/grit/lazy.rb", "lib/grit/repo.rb", "lib/grit/tag.rb", "lib/grit/tree.rb", "test/fixtures/blame", "test/fixtures/cat_file_blob", "test/fixtures/cat_file_blob_size", "test/fixtures/diff_2", "test/fixtures/diff_2f", "test/fixtures/diff_f", "test/fixtures/diff_i", "test/fixtures/diff_mode_only", "test/fixtures/diff_new_mode", "test/fixtures/diff_p", "test/fixtures/for_each_ref", "test/fixtures/for_each_ref_tags", "test/fixtures/ls_tree_a", "test/fixtures/ls_tree_b", "test/fixtures/ls_tree_commit", "test/fixtures/rev_list", "test/fixtures/rev_list_count", "test/fixtures/rev_list_single", "test/fixtures/rev_parse", "test/fixtures/show_empty_commit", "test/fixtures/simple_config", "test/helper.rb", "test/profile.rb", "test/suite.rb", "test/test_actor.rb", "test/test_blob.rb", "test/test_commit.rb", "test/test_config.rb", "test/test_diff.rb", "test/test_git.rb", "test/test_head.rb", "test/test_reality.rb", "test/test_repo.rb", "test/test_tag.rb", "test/test_tree.rb", "test/test_real.rb"]
12
- s.test_files = ["test/test_actor.rb", "test/test_blob.rb", "test/test_commit.rb", "test/test_config.rb", "test/test_diff.rb", "test/test_git.rb", "test/test_head.rb", "test/test_real.rb", "test/test_reality.rb", "test/test_repo.rb", "test/test_tag.rb", "test/test_tree.rb"]
10
+ s.authors = ["Tom Preston-Werner", "Scott Chacon"]
11
+ s.files = ["History.txt",
12
+ "Manifest.txt",
13
+ "README.txt",
14
+ "Rakefile",
15
+ "grit.gemspec",
16
+ "lib/grit/actor.rb",
17
+ "lib/grit/blob.rb",
18
+ "lib/grit/commit.rb",
19
+ "lib/grit/commit_stats.rb",
20
+ "lib/grit/config.rb",
21
+ "lib/grit/diff.rb",
22
+ "lib/grit/errors.rb",
23
+ "lib/grit/git-ruby/commit_db.rb",
24
+ "lib/grit/git-ruby/file_index.rb",
25
+ "lib/grit/git-ruby/git_object.rb",
26
+ "lib/grit/git-ruby/internal",
27
+ "lib/grit/git-ruby/internal/loose.rb",
28
+ "lib/grit/git-ruby/internal/mmap.rb",
29
+ "lib/grit/git-ruby/internal/pack.rb",
30
+ "lib/grit/git-ruby/internal/raw_object.rb",
31
+ "lib/grit/git-ruby/object.rb",
32
+ "lib/grit/git-ruby/repository.rb",
33
+ "lib/grit/git-ruby.rb",
34
+ "lib/grit/git.rb",
35
+ "lib/grit/head.rb",
36
+ "lib/grit/index.rb",
37
+ "lib/grit/lazy.rb",
38
+ "lib/grit/ref.rb",
39
+ "lib/grit/repo.rb",
40
+ "lib/grit/status.rb",
41
+ "lib/grit/tag.rb",
42
+ "lib/grit/tree.rb",
43
+ "lib/grit.rb"]
44
+ s.test_files = ["test/test_actor.rb",
45
+ "test/test_blob.rb", "test/test_commit.rb",
46
+ "test/test_config.rb",
47
+ "test/test_diff.rb",
48
+ "test/test_git.rb",
49
+ "test/test_grit.rb",
50
+ "test/test_head.rb",
51
+ "test/test_real.rb",
52
+ "test/test_reality.rb",
53
+ "test/test_remote.rb",
54
+ "test/test_repo.rb",
55
+ "test/test_tag.rb",
56
+ "test/test_tree.rb"]
13
57
  s.rdoc_options = ["--main", "README.txt"]
14
58
  s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt"]
59
+ s.add_dependency("diff-lcs", ["> 0.0.0"])
15
60
  s.add_dependency("mime-types", ["> 0.0.0"])
16
- end
61
+ s.add_dependency("open4", ["> 0.0.0"])
62
+ end
@@ -6,32 +6,48 @@ require 'time'
6
6
 
7
7
  # stdlib
8
8
  require 'timeout'
9
+ require 'logger'
9
10
 
10
11
  # third party
11
12
  require 'rubygems'
12
13
  require 'mime/types'
13
14
  require 'open4'
15
+ require 'digest/sha1'
14
16
 
15
17
  # internal requires
16
18
  require 'grit/lazy'
17
19
  require 'grit/errors'
20
+ require 'grit/git-ruby'
18
21
  require 'grit/git'
19
- require 'grit/head'
20
- require 'grit/tag'
22
+ require 'grit/ref'
21
23
  require 'grit/commit'
24
+ require 'grit/commit_stats'
22
25
  require 'grit/tree'
23
26
  require 'grit/blob'
24
27
  require 'grit/actor'
25
28
  require 'grit/diff'
26
29
  require 'grit/config'
27
30
  require 'grit/repo'
31
+ require 'grit/index'
32
+ require 'grit/status'
33
+
28
34
 
29
35
  module Grit
36
+
30
37
  class << self
38
+ # Set +debug+ to true to log all git calls and responses
31
39
  attr_accessor :debug
40
+ attr_accessor :use_git_ruby
41
+ # The standard +logger+ for debugging git calls - this defaults to a plain STDOUT logger
42
+ attr_accessor :logger
43
+ def log(str)
44
+ logger.debug { str }
45
+ end
32
46
  end
33
-
34
47
  self.debug = false
48
+ self.use_git_ruby = true
49
+
50
+ @logger ||= ::Logger.new(STDOUT)
35
51
 
36
- VERSION = '0.8.1'
52
+ VERSION = '0.9.1'
37
53
  end
data/lib/grit/commit.rb CHANGED
@@ -36,7 +36,7 @@ module Grit
36
36
  end
37
37
 
38
38
  def id_abbrev
39
- @id_abbrev ||= @repo.git.rev_parse({:short => true}, self.id).chomp
39
+ @id_abbrev ||= @repo.git.rev_parse({}, self.id).chomp[0, 7]
40
40
  end
41
41
 
42
42
  # Create an unbaked Commit containing just the specified attributes
@@ -84,7 +84,7 @@ module Grit
84
84
  # Returns Grit::Commit[] (baked)
85
85
  def self.find_all(repo, ref, options = {})
86
86
  allowed_options = [:max_count, :skip, :since]
87
-
87
+
88
88
  default_options = {:pretty => "raw"}
89
89
  actual_options = default_options.merge(options)
90
90
 
@@ -93,8 +93,10 @@ module Grit
93
93
  else
94
94
  output = repo.git.rev_list(actual_options.merge(:all => true))
95
95
  end
96
-
96
+
97
97
  self.list_from_string(repo, output)
98
+ rescue Grit::GitRuby::Repository::NoSuchShaFound
99
+ []
98
100
  end
99
101
 
100
102
  # Parse out commit information into an array of baked Commit objects
@@ -102,11 +104,15 @@ module Grit
102
104
  # +text+ is the text output from the git command (raw format)
103
105
  #
104
106
  # Returns Grit::Commit[] (baked)
107
+ #
108
+ # really should re-write this to be more accepting of non-standard commit messages
109
+ # - it broke when 'encoding' was introduced - not sure what else might show up
110
+ #
105
111
  def self.list_from_string(repo, text)
106
112
  lines = text.split("\n")
107
113
 
108
114
  commits = []
109
-
115
+
110
116
  while !lines.empty?
111
117
  id = lines.shift.split.last
112
118
  tree = lines.shift.split.last
@@ -117,6 +123,9 @@ module Grit
117
123
  author, authored_date = self.actor(lines.shift)
118
124
  committer, committed_date = self.actor(lines.shift)
119
125
 
126
+ # not doing anything with this yet, but it's sometimes there
127
+ encoding = lines.shift.split.last if lines.first =~ /^encoding/
128
+
120
129
  lines.shift
121
130
 
122
131
  message_lines = []
@@ -151,15 +160,19 @@ module Grit
151
160
  Diff.list_from_string(repo, text)
152
161
  end
153
162
 
163
+ def show
164
+ diff = @repo.git.show({:full_index => true, :pretty => 'raw'}, @id)
165
+ if diff =~ /diff --git a/
166
+ diff = diff.sub(/.+?(diff --git a)/m, '\1')
167
+ else
168
+ diff = ''
169
+ end
170
+ Diff.list_from_string(@repo, diff)
171
+ end
172
+
154
173
  def diffs
155
174
  if parents.empty?
156
- diff = @repo.git.show({:full_index => true, :pretty => 'raw'}, @id)
157
- if diff =~ /diff --git a/
158
- diff = diff.sub(/.+?(diff --git a)/m, '\1')
159
- else
160
- diff = ''
161
- end
162
- Diff.list_from_string(@repo, diff)
175
+ show
163
176
  else
164
177
  self.class.diff(@repo, parents.first.id, @id)
165
178
  end
@@ -169,6 +182,14 @@ module Grit
169
182
  def to_s
170
183
  @id
171
184
  end
185
+
186
+ def sha
187
+ @id
188
+ end
189
+
190
+ def date
191
+ @committed_date
192
+ end
172
193
 
173
194
  # Pretty object inspection
174
195
  def inspect
@@ -0,0 +1,104 @@
1
+ module Grit
2
+
3
+ class CommitStats
4
+
5
+ attr_reader :id, :files, :additions, :deletions, :total
6
+
7
+ # Instantiate a new CommitStats
8
+ # +id+ is the id of the commit
9
+ # +files+ is an array of :
10
+ # [ [filename, adds, deletes, total],
11
+ # [filename, adds, deletes, total],
12
+ # [filename, adds, deletes, total] ]
13
+ #
14
+ # Returns Grit::CommitStats (baked)
15
+ def initialize(repo, id, files)
16
+ @repo = repo
17
+ @id = id
18
+ @files = files
19
+ @additions = files.inject(0) { |total, a| total += a[1] }
20
+ @deletions = files.inject(0) { |total, a| total += a[2] }
21
+ @total = files.inject(0) { |total, a| total += a[3] }
22
+ end
23
+
24
+ # Find all commit stats matching the given criteria.
25
+ # +repo+ is the Repo
26
+ # +ref+ is the ref from which to begin (SHA1 or name) or nil for --all
27
+ # +options+ is a Hash of optional arguments to git
28
+ # :max_count is the maximum number of commits to fetch
29
+ # :skip is the number of commits to skip
30
+ #
31
+ # Returns assoc array [sha, Grit::Commit[] (baked)]
32
+ def self.find_all(repo, ref, options = {})
33
+ allowed_options = [:max_count, :skip, :since]
34
+
35
+ default_options = {:numstat => true}
36
+ actual_options = default_options.merge(options)
37
+
38
+ if ref
39
+ output = repo.git.log(actual_options, ref)
40
+ else
41
+ output = repo.git.log(actual_options.merge(:all => true))
42
+ end
43
+
44
+ self.list_from_string(repo, output)
45
+ end
46
+
47
+ # Parse out commit information into an array of baked Commit objects
48
+ # +repo+ is the Repo
49
+ # +text+ is the text output from the git command (raw format)
50
+ #
51
+ # Returns assoc array [sha, Grit::Commit[] (baked)]
52
+ def self.list_from_string(repo, text)
53
+ lines = text.split("\n")
54
+
55
+ commits = []
56
+
57
+ while !lines.empty?
58
+ id = lines.shift.split.last
59
+
60
+ lines.shift
61
+ lines.shift
62
+ lines.shift
63
+
64
+ message_lines = []
65
+ message_lines << lines.shift[4..-1] while lines.first =~ /^ {4}/
66
+
67
+ lines.shift while lines.first && lines.first.empty?
68
+
69
+ files = []
70
+ while lines.first =~ /^(\d+)\s+(\d+)\s+(.+)/
71
+ (additions, deletions, filename) = lines.shift.split
72
+ additions = additions.to_i
73
+ deletions = deletions.to_i
74
+ total = additions + deletions
75
+ files << [filename, additions, deletions, total]
76
+ end
77
+
78
+ lines.shift while lines.first && lines.first.empty?
79
+
80
+ commits << [id, CommitStats.new(repo, id, files)]
81
+ end
82
+
83
+ commits
84
+ end
85
+
86
+ # Pretty object inspection
87
+ def inspect
88
+ %Q{#<Grit::CommitStats "#{@id}">}
89
+ end
90
+
91
+ # private
92
+
93
+ def to_hash
94
+ {
95
+ 'id' => id,
96
+ 'files' => files,
97
+ 'additions' => additions,
98
+ 'deletions' => deletions,
99
+ 'total' => total
100
+ }
101
+ end
102
+ end # CommitStats
103
+
104
+ end # Grit
@@ -0,0 +1,182 @@
1
+ require 'grit/git-ruby/repository'
2
+ require 'grit/git-ruby/file_index'
3
+
4
+ module Grit
5
+
6
+ # the functions in this module intercept the calls to git binary
7
+ # made buy the grit objects and attempts to run them in pure ruby
8
+ # if it will be faster, or if the git binary is not available (!!TODO!!)
9
+ module GitRuby
10
+
11
+ attr_accessor :ruby_git_repo, :git_file_index
12
+
13
+ def init(options)
14
+ if options.size == 0
15
+ Grit::GitRuby::Repository.init(@git_dir)
16
+ else
17
+ method_missing('init', options)
18
+ end
19
+ end
20
+
21
+ def cat_file(options, ref)
22
+ if options[:t]
23
+ file_type(ref)
24
+ elsif options[:s]
25
+ file_size(ref)
26
+ elsif options[:p]
27
+ try_run { ruby_git.cat_file(ref) }
28
+ end
29
+ rescue Grit::GitRuby::Repository::NoSuchShaFound
30
+ ''
31
+ end
32
+
33
+ # lib/grit/tree.rb:16: output = repo.git.ls_tree({}, treeish, *paths)
34
+ def ls_tree(options, treeish, *paths)
35
+ sha = rev_parse({}, treeish)
36
+ ruby_git.ls_tree(sha, paths.flatten)
37
+ rescue Grit::GitRuby::Repository::NoSuchShaFound
38
+ ''
39
+ end
40
+
41
+ # git diff --full-index 'ec037431382e83c3e95d4f2b3d145afbac8ea55d' 'f1ec1aea10986159456846b8a05615b87828d6c6'
42
+ def diff(options, sha1, sha2)
43
+ try_run { ruby_git.diff(sha1, sha2, options) }
44
+ end
45
+
46
+ def rev_list(options, ref = 'master')
47
+ options.delete(:skip) if options[:skip].to_i == 0
48
+ allowed_options = [:max_count, :since, :until, :pretty] # this is all I can do right now
49
+ if ((options.keys - allowed_options).size > 0)
50
+ return method_missing('rev-list', options, ref)
51
+ elsif (options.size == 0)
52
+ # pure rev-list
53
+ begin
54
+ return file_index.commits_from(rev_parse({}, ref)).join("\n")
55
+ rescue
56
+ return method_missing('rev-list', options, ref)
57
+ end
58
+ else
59
+ aref = rev_parse({}, ref)
60
+ if aref.is_a? Array
61
+ return method_missing('rev-list', options, ref)
62
+ else
63
+ return try_run { ruby_git.rev_list(aref, options) }
64
+ end
65
+ end
66
+ end
67
+
68
+ def rev_parse(options, string)
69
+ if string =~ /\.\./
70
+ (sha1, sha2) = string.split('..')
71
+ return [rev_parse({}, sha1), rev_parse({}, sha2)]
72
+ end
73
+
74
+ if /\w{40}/.match(string) # passing in a sha - just no-op it
75
+ return string.chomp
76
+ end
77
+
78
+ head = File.join(@git_dir, 'refs', 'heads', string)
79
+ return File.read(head).chomp if File.file?(head)
80
+
81
+ head = File.join(@git_dir, 'refs', 'remotes', string)
82
+ return File.read(head).chomp if File.file?(head)
83
+
84
+ head = File.join(@git_dir, 'refs', 'tags', string)
85
+ return File.read(head).chomp if File.file?(head)
86
+
87
+ ## check packed-refs file, too
88
+ packref = File.join(@git_dir, 'packed-refs')
89
+ if File.file?(packref)
90
+ File.readlines(packref).each do |line|
91
+ if m = /^(\w{40}) refs\/.+?\/(.*?)$/.match(line)
92
+ next if !Regexp.new(string + '$').match(m[3])
93
+ return m[1].chomp
94
+ end
95
+ end
96
+ end
97
+
98
+ ## !! more - partials and such !!
99
+
100
+ # revert to calling git - grr
101
+ return method_missing('rev-parse', {}, string).chomp
102
+ end
103
+
104
+ def file_size(ref)
105
+ try_run { ruby_git.cat_file_size(ref).to_s }
106
+ end
107
+
108
+ def file_type(ref)
109
+ try_run { ruby_git.cat_file_type(ref).to_s }
110
+ end
111
+
112
+ def blame_tree(commit, path = nil)
113
+ begin
114
+ commits = file_index.last_commits(rev_parse({}, commit), looking_for(commit, path))
115
+ clean_paths(commits)
116
+ rescue FileIndex::IndexFileNotFound
117
+ {}
118
+ end
119
+ end
120
+
121
+ def file_index
122
+ @git_file_index ||= FileIndex.new(@git_dir)
123
+ end
124
+
125
+ def ruby_git
126
+ @ruby_git_repo ||= Repository.new(@git_dir)
127
+ end
128
+
129
+ private
130
+
131
+ def try_run
132
+ ret = ''
133
+ Timeout.timeout(self.class.git_timeout) do
134
+ ret = yield
135
+ end
136
+ @bytes_read += ret.size
137
+
138
+ #if @bytes_read > 5242880 # 5.megabytes
139
+ # bytes = @bytes_read
140
+ # @bytes_read = 0
141
+ # raise Grit::Git::GitTimeout.new(command, bytes)
142
+ #end
143
+
144
+ ret
145
+ rescue Timeout::Error => e
146
+ bytes = @bytes_read
147
+ @bytes_read = 0
148
+ raise Grit::Git::GitTimeout.new(command, bytes)
149
+ end
150
+
151
+ def looking_for(commit, path = nil)
152
+ tree_sha = ruby_git.get_subtree(rev_parse({}, commit), path)
153
+
154
+ looking_for = []
155
+ ruby_git.get_object_by_sha1(tree_sha).entry.each do |e|
156
+ if path && !(path == '' || path == '.' || path == './')
157
+ file = File.join(path, e.name)
158
+ else
159
+ file = e.name
160
+ end
161
+ file += '/' if e.type == :directory
162
+ looking_for << file
163
+ end
164
+ looking_for
165
+ end
166
+
167
+ def clean_paths(commit_array)
168
+ new_commits = {}
169
+ commit_array.each do |file, sha|
170
+ file = file.chop if file[file.size - 1 , 1] == '/'
171
+ new_commits[file] = sha
172
+ end
173
+ new_commits
174
+ end
175
+
176
+ # TODO
177
+ # git grep -n 'foo' 'master'
178
+ # git log --pretty='raw' --max-count='1' 'master' -- 'LICENSE'
179
+ # git log --pretty='raw' --max-count='1' 'master' -- 'test'
180
+
181
+ end
182
+ end