mojombo-grit 0.9.4 → 1.1.1

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 (47) hide show
  1. data/API.txt +101 -0
  2. data/History.txt +38 -2
  3. data/README.md +210 -0
  4. data/VERSION.yml +4 -0
  5. data/lib/grit.rb +13 -4
  6. data/lib/grit/blame.rb +61 -0
  7. data/lib/grit/blob.rb +11 -2
  8. data/lib/grit/commit.rb +44 -31
  9. data/lib/grit/commit_stats.rb +26 -2
  10. data/lib/grit/diff.rb +6 -6
  11. data/lib/grit/git-ruby.rb +4 -2
  12. data/lib/grit/git-ruby/file_index.rb +10 -3
  13. data/lib/grit/git-ruby/git_object.rb +9 -3
  14. data/lib/grit/git-ruby/internal/{mmap.rb → file_window.rb} +2 -2
  15. data/lib/grit/git-ruby/internal/loose.rb +6 -6
  16. data/lib/grit/git-ruby/internal/pack.rb +19 -19
  17. data/lib/grit/git-ruby/object.rb +8 -2
  18. data/lib/grit/git-ruby/repository.rb +11 -6
  19. data/lib/grit/git.rb +23 -10
  20. data/lib/grit/index.rb +12 -11
  21. data/lib/grit/merge.rb +45 -0
  22. data/lib/grit/ref.rb +20 -16
  23. data/lib/grit/repo.rb +59 -9
  24. data/lib/grit/ruby1.9.rb +7 -0
  25. data/lib/grit/submodule.rb +5 -1
  26. data/lib/grit/tag.rb +61 -66
  27. data/lib/grit/tree.rb +20 -1
  28. metadata +29 -47
  29. data/Manifest.txt +0 -71
  30. data/README.txt +0 -213
  31. data/Rakefile +0 -29
  32. data/grit.gemspec +0 -62
  33. data/lib/grit/head.rb +0 -83
  34. data/test/test_actor.rb +0 -35
  35. data/test/test_blob.rb +0 -79
  36. data/test/test_commit.rb +0 -190
  37. data/test/test_config.rb +0 -58
  38. data/test/test_diff.rb +0 -18
  39. data/test/test_git.rb +0 -64
  40. data/test/test_grit.rb +0 -32
  41. data/test/test_head.rb +0 -47
  42. data/test/test_real.rb +0 -19
  43. data/test/test_reality.rb +0 -17
  44. data/test/test_remote.rb +0 -14
  45. data/test/test_repo.rb +0 -277
  46. data/test/test_tag.rb +0 -25
  47. data/test/test_tree.rb +0 -96
@@ -104,14 +104,23 @@ module Grit
104
104
  info = nil
105
105
  end
106
106
  end
107
-
107
+
108
108
  blames
109
109
  end
110
110
 
111
+ def basename
112
+ File.basename(name)
113
+ end
114
+
111
115
  # Pretty object inspection
112
116
  def inspect
113
117
  %Q{#<Grit::Blob "#{@id}">}
114
118
  end
119
+
120
+ # Compares blobs by name
121
+ def <=>(other)
122
+ name <=> other.name
123
+ end
115
124
  end # Blob
116
-
125
+
117
126
  end # Grit
@@ -1,5 +1,5 @@
1
1
  module Grit
2
-
2
+
3
3
  class Commit
4
4
  attr_reader :id
5
5
  lazy_reader :parents
@@ -10,7 +10,8 @@ module Grit
10
10
  lazy_reader :committed_date
11
11
  lazy_reader :message
12
12
  lazy_reader :short_message
13
-
13
+ lazy_reader :author_string
14
+
14
15
  # Instantiate a new Commit
15
16
  # +id+ is the id of the commit
16
17
  # +parents+ is an array of commit ids (will be converted into Commit instances)
@@ -34,11 +35,11 @@ module Grit
34
35
  @message = message.join("\n")
35
36
  @short_message = message[0] || ''
36
37
  end
37
-
38
+
38
39
  def id_abbrev
39
40
  @id_abbrev ||= @repo.git.rev_parse({}, self.id).chomp[0, 7]
40
41
  end
41
-
42
+
42
43
  # Create an unbaked Commit containing just the specified attributes
43
44
  # +repo+ is the Repo
44
45
  # +atts+ is a Hash of instance variable data
@@ -47,7 +48,7 @@ module Grit
47
48
  def self.create(repo, atts)
48
49
  self.allocate.create_initialize(repo, atts)
49
50
  end
50
-
51
+
51
52
  # Initializer for Commit.create
52
53
  # +repo+ is the Repo
53
54
  # +atts+ is a Hash of instance variable data
@@ -60,11 +61,11 @@ module Grit
60
61
  end
61
62
  self
62
63
  end
63
-
64
+
64
65
  def lazy_source
65
66
  self.class.find_all(@repo, @id, {:max_count => 1}).first
66
67
  end
67
-
68
+
68
69
  # Count the number of commits reachable from this ref
69
70
  # +repo+ is the Repo
70
71
  # +ref+ is the ref from which to begin (SHA1 or name)
@@ -73,7 +74,7 @@ module Grit
73
74
  def self.count(repo, ref)
74
75
  repo.git.rev_list({}, ref).size / 41
75
76
  end
76
-
77
+
77
78
  # Find all commits matching the given criteria.
78
79
  # +repo+ is the Repo
79
80
  # +ref+ is the ref from which to begin (SHA1 or name) or nil for --all
@@ -84,21 +85,21 @@ module Grit
84
85
  # Returns Grit::Commit[] (baked)
85
86
  def self.find_all(repo, ref, options = {})
86
87
  allowed_options = [:max_count, :skip, :since]
87
-
88
+
88
89
  default_options = {:pretty => "raw"}
89
90
  actual_options = default_options.merge(options)
90
-
91
+
91
92
  if ref
92
93
  output = repo.git.rev_list(actual_options, ref)
93
94
  else
94
95
  output = repo.git.rev_list(actual_options.merge(:all => true))
95
96
  end
96
-
97
+
97
98
  self.list_from_string(repo, output)
98
99
  rescue Grit::GitRuby::Repository::NoSuchShaFound
99
100
  []
100
101
  end
101
-
102
+
102
103
  # Parse out commit information into an array of baked Commit objects
103
104
  # +repo+ is the Repo
104
105
  # +text+ is the text output from the git command (raw format)
@@ -110,40 +111,40 @@ module Grit
110
111
  #
111
112
  def self.list_from_string(repo, text)
112
113
  lines = text.split("\n")
113
-
114
+
114
115
  commits = []
115
-
116
+
116
117
  while !lines.empty?
117
118
  id = lines.shift.split.last
118
119
  tree = lines.shift.split.last
119
-
120
+
120
121
  parents = []
121
122
  parents << lines.shift.split.last while lines.first =~ /^parent/
122
-
123
+
123
124
  author, authored_date = self.actor(lines.shift)
124
125
  committer, committed_date = self.actor(lines.shift)
125
-
126
+
126
127
  # not doing anything with this yet, but it's sometimes there
127
128
  encoding = lines.shift.split.last if lines.first =~ /^encoding/
128
-
129
+
129
130
  lines.shift
130
-
131
+
131
132
  message_lines = []
132
133
  message_lines << lines.shift[4..-1] while lines.first =~ /^ {4}/
133
-
134
+
134
135
  lines.shift while lines.first && lines.first.empty?
135
-
136
+
136
137
  commits << Commit.new(repo, id, parents, tree, author, authored_date, committer, committed_date, message_lines)
137
138
  end
138
-
139
+
139
140
  commits
140
141
  end
141
-
142
+
142
143
  # Show diffs between two trees:
143
144
  # +repo+ is the Repo
144
145
  # +a+ is a named commit
145
- # +b+ is an optional named commit. Passing an array assumes you
146
- # wish to omit the second named commit and limit the diff to the
146
+ # +b+ is an optional named commit. Passing an array assumes you
147
+ # wish to omit the second named commit and limit the diff to the
147
148
  # given paths.
148
149
  # +paths* is an array of paths to limit the diff.
149
150
  #
@@ -174,10 +175,14 @@ module Grit
174
175
  if parents.empty?
175
176
  show
176
177
  else
177
- self.class.diff(@repo, parents.first.id, @id)
178
+ self.class.diff(@repo, parents.first.id, @id)
178
179
  end
179
180
  end
180
181
 
182
+ def stats
183
+ stats = @repo.commit_stats(self.sha, 1)[0][-1]
184
+ end
185
+
181
186
  # Convert this Commit to a String which is just the SHA1 id
182
187
  def to_s
183
188
  @id
@@ -186,18 +191,22 @@ module Grit
186
191
  def sha
187
192
  @id
188
193
  end
189
-
194
+
190
195
  def date
191
196
  @committed_date
192
197
  end
193
-
198
+
199
+ def to_patch
200
+ @repo.git.format_patch({'1' => true, :stdout => true}, to_s)
201
+ end
202
+
194
203
  # Pretty object inspection
195
204
  def inspect
196
205
  %Q{#<Grit::Commit "#{@id}">}
197
206
  end
198
-
207
+
199
208
  # private
200
-
209
+
201
210
  # Parse out the actor (author or committer) info
202
211
  #
203
212
  # Returns [String (actor name and email), Time (acted at time)]
@@ -206,6 +215,10 @@ module Grit
206
215
  [Actor.from_string(actor), Time.at(epoch.to_i)]
207
216
  end
208
217
 
218
+ def author_string
219
+ "%s <%s> %s %+05d" % [author.name, author.email, authored_date.to_i, 800]
220
+ end
221
+
209
222
  def to_hash
210
223
  {
211
224
  'id' => id,
@@ -225,5 +238,5 @@ module Grit
225
238
  }
226
239
  end
227
240
  end # Commit
228
-
241
+
229
242
  end # Grit
@@ -62,12 +62,12 @@ module Grit
62
62
  lines.shift
63
63
 
64
64
  message_lines = []
65
- message_lines << lines.shift[4..-1] while lines.first =~ /^ {4}/
65
+ message_lines << lines.shift[4..-1] while lines.first =~ /^ {4}/ || lines.first == ''
66
66
 
67
67
  lines.shift while lines.first && lines.first.empty?
68
68
 
69
69
  files = []
70
- while lines.first =~ /^(\d+)\s+(\d+)\s+(.+)/
70
+ while lines.first =~ /^([-\d]+)\s+([-\d]+)\s+(.+)/
71
71
  (additions, deletions, filename) = lines.shift.split
72
72
  additions = additions.to_i
73
73
  deletions = deletions.to_i
@@ -88,6 +88,13 @@ module Grit
88
88
  %Q{#<Grit::CommitStats "#{@id}">}
89
89
  end
90
90
 
91
+ # Convert to an easy-to-traverse structure
92
+ def to_diffstat
93
+ files.map do |metadata|
94
+ DiffStat.new(*metadata)
95
+ end
96
+ end
97
+
91
98
  # private
92
99
 
93
100
  def to_hash
@@ -99,6 +106,23 @@ module Grit
99
106
  'total' => total
100
107
  }
101
108
  end
109
+
102
110
  end # CommitStats
103
111
 
112
+ class DiffStat
113
+ attr_reader :filename, :additions, :deletions
114
+
115
+ def initialize(filename, additions, deletions, total=nil)
116
+ @filename, @additions, @deletions = filename, additions, deletions
117
+ end
118
+
119
+ def net
120
+ additions - deletions
121
+ end
122
+
123
+ def inspect
124
+ "#{filename}: +#{additions} -#{deletions}"
125
+ end
126
+ end
127
+
104
128
  end # Grit
@@ -2,17 +2,17 @@ module Grit
2
2
 
3
3
  class Diff
4
4
  attr_reader :a_path, :b_path
5
- attr_reader :a_commit, :b_commit
5
+ attr_reader :a_blob, :b_blob
6
6
  attr_reader :a_mode, :b_mode
7
7
  attr_reader :new_file, :deleted_file
8
8
  attr_reader :diff
9
9
 
10
- def initialize(repo, a_path, b_path, a_commit, b_commit, a_mode, b_mode, new_file, deleted_file, diff)
10
+ def initialize(repo, a_path, b_path, a_blob, b_blob, a_mode, b_mode, new_file, deleted_file, diff)
11
11
  @repo = repo
12
12
  @a_path = a_path
13
13
  @b_path = b_path
14
- @a_commit = a_commit =~ /^0{40}$/ ? nil : Commit.create(repo, :id => a_commit)
15
- @b_commit = b_commit =~ /^0{40}$/ ? nil : Commit.create(repo, :id => b_commit)
14
+ @a_blob = a_blob =~ /^0{40}$/ ? nil : Blob.create(repo, :id => a_blob)
15
+ @b_blob = b_blob =~ /^0{40}$/ ? nil : Blob.create(repo, :id => b_blob)
16
16
  @a_mode = a_mode
17
17
  @b_mode = b_mode
18
18
  @new_file = new_file
@@ -51,7 +51,7 @@ module Grit
51
51
  deleted_file = true
52
52
  end
53
53
 
54
- m, a_commit, b_commit, b_mode = *lines.shift.match(%r{^index ([0-9A-Fa-f]+)\.\.([0-9A-Fa-f]+) ?(.+)?$})
54
+ m, a_blob, b_blob, b_mode = *lines.shift.match(%r{^index ([0-9A-Fa-f]+)\.\.([0-9A-Fa-f]+) ?(.+)?$})
55
55
  b_mode.strip! if b_mode
56
56
 
57
57
  diff_lines = []
@@ -60,7 +60,7 @@ module Grit
60
60
  end
61
61
  diff = diff_lines.join("\n")
62
62
 
63
- diffs << Diff.new(repo, a_path, b_path, a_commit, b_commit, a_mode, b_mode, new_file, deleted_file, diff)
63
+ diffs << Diff.new(repo, a_path, b_path, a_blob, b_blob, a_mode, b_mode, new_file, deleted_file, diff)
64
64
  end
65
65
 
66
66
  diffs
@@ -72,8 +72,8 @@ module Grit
72
72
  (sha1, sha2) = string.split('..')
73
73
  return [rev_parse({}, sha1), rev_parse({}, sha2)]
74
74
  end
75
-
76
- if /\w{40}/.match(string) # passing in a sha - just no-op it
75
+
76
+ if /^[0-9a-f]{40}$/.match(string) # passing in a sha - just no-op it
77
77
  return string.chomp
78
78
  end
79
79
 
@@ -113,6 +113,8 @@ module Grit
113
113
 
114
114
  def blame_tree(commit, path = nil)
115
115
  begin
116
+ path = [path].join('/').to_s + '/' if (path && path != '')
117
+ path = '' if !path.is_a? String
116
118
  commits = file_index.last_commits(rev_parse({}, commit), looking_for(commit, path))
117
119
  clean_paths(commits)
118
120
  rescue FileIndex::IndexFileNotFound
@@ -22,12 +22,18 @@ module Grit
22
22
  class UnsupportedRef < StandardError
23
23
  end
24
24
 
25
+ class << self
26
+ attr_accessor :max_file_size
27
+ end
28
+
29
+ self.max_file_size = 10_000_000 # ~10M
30
+
25
31
  attr_reader :files
26
32
 
27
33
  # initializes index given repo_path
28
34
  def initialize(repo_path)
29
35
  @index_file = File.join(repo_path, 'file-index')
30
- if File.file?(@index_file)
36
+ if File.file?(@index_file) && (File.size(@index_file) < Grit::GitRuby::FileIndex.max_file_size)
31
37
  read_index
32
38
  else
33
39
  raise IndexFileNotFound
@@ -46,6 +52,7 @@ module Grit
46
52
  commits_from(commit_sha).size
47
53
  end
48
54
 
55
+ # builds a list of all commits reachable from a single commit
49
56
  def commits_from(commit_sha)
50
57
  raise UnsupportedRef if commit_sha.is_a? Array
51
58
 
@@ -69,7 +76,7 @@ module Grit
69
76
  end
70
77
 
71
78
  def sort_commits(sha_array)
72
- sha_array.sort { |a, b| @commit_order[b] <=> @commit_order[a] }
79
+ sha_array.sort { |a, b| @commit_order[b].to_i <=> @commit_order[a].to_i }
73
80
  end
74
81
 
75
82
  # returns files changed at commit sha
@@ -183,4 +190,4 @@ if __FILE__ == $0
183
190
  end
184
191
 
185
192
 
186
-
193
+
@@ -115,7 +115,7 @@ module Grit
115
115
  def initialize(mode, filename, sha1o)
116
116
  @mode = 0
117
117
  mode.each_byte do |i|
118
- @mode = (@mode << 3) | (i-'0'[0])
118
+ @mode = (@mode << 3) | (i-'0'.getord(0))
119
119
  end
120
120
  @name = filename
121
121
  @sha1 = sha1o
@@ -179,8 +179,14 @@ module Grit
179
179
 
180
180
  def self.read_bytes_until(io, char)
181
181
  string = ''
182
- while ((next_char = io.getc.chr) != char) && !io.eof
183
- string += next_char
182
+ if RUBY_VERSION > '1.9'
183
+ while ((next_char = io.getc) != char) && !io.eof
184
+ string += next_char
185
+ end
186
+ else
187
+ while ((next_char = io.getc.chr) != char) && !io.eof
188
+ string += next_char
189
+ end
184
190
  end
185
191
  string
186
192
  end
@@ -12,7 +12,7 @@
12
12
  module Grit
13
13
  module GitRuby
14
14
  module Internal
15
- class Mmap
15
+ class FileWindow
16
16
  def initialize(file, version = 1)
17
17
  @file = file
18
18
  @offset = nil
@@ -46,7 +46,7 @@ module Grit
46
46
  end
47
47
  @offset = offset + len ? len : 1
48
48
  if not len
49
- @file.read(1)[0]
49
+ @file.read(1).getord(0)
50
50
  else
51
51
  @file.read(len)
52
52
  end
@@ -29,7 +29,7 @@ module Grit
29
29
  begin
30
30
  return nil unless sha1[0...2] && sha1[2..39]
31
31
  path = @directory + '/' + sha1[0...2] + '/' + sha1[2..39]
32
- get_raw_object(File.read(path))
32
+ get_raw_object(File.open(path, 'rb').read)
33
33
  rescue Errno::ENOENT
34
34
  nil
35
35
  end
@@ -76,7 +76,7 @@ module Grit
76
76
  content = Zlib::Deflate.deflate(store)
77
77
 
78
78
  FileUtils.mkdir_p(@directory+'/'+sha1[0...2])
79
- File.open(path, 'w') do |f|
79
+ File.open(path, 'wb') do |f|
80
80
  f.write content
81
81
  end
82
82
  end
@@ -102,7 +102,7 @@ module Grit
102
102
  # private
103
103
  def unpack_object_header_gently(buf)
104
104
  used = 0
105
- c = buf[used]
105
+ c = buf.getord(used)
106
106
  used += 1
107
107
 
108
108
  type = (c >> 4) & 7;
@@ -112,7 +112,7 @@ module Grit
112
112
  if buf.length <= used
113
113
  raise LooseObjectError, "object file too short"
114
114
  end
115
- c = buf[used]
115
+ c = buf.getord(used)
116
116
  used += 1
117
117
 
118
118
  size += (c & 0x7f) << shift
@@ -127,8 +127,8 @@ module Grit
127
127
  private :unpack_object_header_gently
128
128
 
129
129
  def legacy_loose_object?(buf)
130
- word = (buf[0] << 8) + buf[1]
131
- buf[0] == 0x78 && word % 31 == 0
130
+ word = (buf.getord(0) << 8) + buf.getord(1)
131
+ buf.getord(0) == 0x78 && word % 31 == 0
132
132
  end
133
133
  private :legacy_loose_object?
134
134
  end