schacon-grit 0.9.1 → 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
data/Manifest.txt CHANGED
@@ -3,7 +3,6 @@ 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
@@ -11,12 +10,26 @@ lib/grit/commit_stats.rb
11
10
  lib/grit/config.rb
12
11
  lib/grit/diff.rb
13
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
14
23
  lib/grit/git.rb
24
+ lib/grit/head.rb
15
25
  lib/grit/index.rb
16
26
  lib/grit/lazy.rb
17
27
  lib/grit/ref.rb
18
28
  lib/grit/repo.rb
29
+ lib/grit/status.rb
30
+ lib/grit/tag.rb
19
31
  lib/grit/tree.rb
32
+ lib/grit.rb
20
33
  test/fixtures/blame
21
34
  test/fixtures/cat_file_blob
22
35
  test/fixtures/cat_file_blob_size
data/grit.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "grit"
3
- s.version = "0.9.1"
3
+ s.version = "0.9.3"
4
4
  s.date = "2008-04-24"
5
5
  s.summary = "Object model interface to a git repo"
6
6
  s.email = "tom@rubyisawesome.com"
@@ -56,5 +56,7 @@ Gem::Specification.new do |s|
56
56
  "test/test_tree.rb"]
57
57
  s.rdoc_options = ["--main", "README.txt"]
58
58
  s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt"]
59
+ s.add_dependency("diff-lcs", ["> 0.0.0"])
59
60
  s.add_dependency("mime-types", ["> 0.0.0"])
61
+ s.add_dependency("open4", ["> 0.0.0"])
60
62
  end
data/lib/grit/commit.rb CHANGED
@@ -182,6 +182,14 @@ module Grit
182
182
  def to_s
183
183
  @id
184
184
  end
185
+
186
+ def sha
187
+ @id
188
+ end
189
+
190
+ def date
191
+ @committed_date
192
+ end
185
193
 
186
194
  # Pretty object inspection
187
195
  def inspect
data/lib/grit/git-ruby.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  require 'grit/git-ruby/repository'
2
2
  require 'grit/git-ruby/file_index'
3
- require 'grit/git-ruby/commit_db'
4
3
 
5
4
  module Grit
6
5
 
@@ -11,6 +10,14 @@ module Grit
11
10
 
12
11
  attr_accessor :ruby_git_repo, :git_file_index
13
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
+
14
21
  def cat_file(options, ref)
15
22
  if options[:t]
16
23
  file_type(ref)
@@ -172,4 +179,4 @@ module Grit
172
179
  # git log --pretty='raw' --max-count='1' 'master' -- 'test'
173
180
 
174
181
  end
175
- end
182
+ end
@@ -9,17 +9,18 @@
9
9
  # provides native ruby access to git objects and pack files
10
10
  #
11
11
 
12
- begin
13
- require 'mmap'
14
- rescue LoadError
15
-
16
12
  module Grit
17
13
  module GitRuby
18
14
  module Internal
19
15
  class Mmap
20
- def initialize(file)
16
+ def initialize(file, version = 1)
21
17
  @file = file
22
18
  @offset = nil
19
+ if version == 2
20
+ @global_offset = 8
21
+ else
22
+ @global_offset = 0
23
+ end
23
24
  end
24
25
 
25
26
  def unmap
@@ -41,7 +42,7 @@ module Grit
41
42
  raise RuntimeError, "invalid index param: #{idx.class}"
42
43
  end
43
44
  if @offset != offset
44
- @file.seek(offset)
45
+ @file.seek(offset + @global_offset)
45
46
  end
46
47
  @offset = offset + len ? len : 1
47
48
  if not len
@@ -55,5 +56,3 @@ module Grit
55
56
  end
56
57
  end
57
58
 
58
- end # rescue LoadError
59
-
@@ -13,6 +13,9 @@ require 'zlib'
13
13
  require 'grit/git-ruby/internal/raw_object'
14
14
  require 'grit/git-ruby/internal/mmap'
15
15
 
16
+ PACK_SIGNATURE = "PACK"
17
+ PACK_IDX_SIGNATURE = "\377tOc"
18
+
16
19
  module Grit
17
20
  module GitRuby
18
21
  module Internal
@@ -27,30 +30,19 @@ module Grit
27
30
  SHA1Size = 20
28
31
  IdxOffsetSize = 4
29
32
  OffsetSize = 4
33
+ CrcSize = 4
30
34
  OffsetStart = FanOutCount * IdxOffsetSize
31
35
  SHA1Start = OffsetStart + OffsetSize
32
36
  EntrySize = OffsetSize + SHA1Size
37
+ EntrySizeV2 = SHA1Size + CrcSize + OffsetSize
33
38
 
34
39
  def initialize(file)
35
40
  if file =~ /\.idx$/
36
41
  file = file[0...-3] + 'pack'
37
42
  end
38
-
39
- @cache = {}
40
43
  @name = file
41
-
42
- with_idx do |idx|
43
- @offsets = [0]
44
- FanOutCount.times do |i|
45
- pos = idx[i * IdxOffsetSize,IdxOffsetSize].unpack('N')[0]
46
- if pos < @offsets[i]
47
- raise PackFormatError, "pack #@name has discontinuous index #{i}"
48
- end
49
- @offsets << pos
50
- end
51
-
52
- @size = @offsets[-1]
53
- end
44
+ @cache = {}
45
+ init_pack
54
46
  end
55
47
 
56
48
  def with_idx(index_file = nil)
@@ -60,7 +52,21 @@ module Grit
60
52
  else
61
53
  idxfile = File.open(index_file)
62
54
  end
63
- idx = Mmap.new(idxfile)
55
+
56
+ # read header
57
+ sig = idxfile.read(4)
58
+ ver = idxfile.read(4).unpack("N")[0]
59
+
60
+ if sig == PACK_IDX_SIGNATURE
61
+ if(ver != 2)
62
+ raise PackFormatError, "pack #@name has unknown pack file version #{ver}"
63
+ end
64
+ @version = 2
65
+ else
66
+ @version = 1
67
+ end
68
+
69
+ idx = Mmap.new(idxfile, @version)
64
70
  yield idx
65
71
  idx.unmap
66
72
  idxfile.close
@@ -72,31 +78,6 @@ module Grit
72
78
  packfile.close
73
79
  end
74
80
 
75
- # given an index file, list out the shas that it's packfile contains
76
- def self.get_shas(index_file)
77
- with_idx(index_file) do |idx|
78
- @offsets = [0]
79
- FanOutCount.times do |i|
80
- pos = idx[i * IdxOffsetSize,IdxOffsetSize].unpack('N')[0]
81
- if pos < @offsets[i]
82
- raise PackFormatError, "pack #@name has discontinuous index #{i}"
83
- end
84
- @offsets << pos
85
- end
86
-
87
- @size = @offsets[-1]
88
- shas = []
89
-
90
- pos = SHA1Start
91
- @size.times do
92
- sha1 = idx[pos,SHA1Size]
93
- pos += EntrySize
94
- shas << sha1.unpack("H*").first
95
- end
96
- shas
97
- end
98
- end
99
-
100
81
  def cache_objects
101
82
  @cache = {}
102
83
  with_packfile do |packfile|
@@ -117,6 +98,13 @@ module Grit
117
98
  # shouldnt be anything open now
118
99
  end
119
100
 
101
+ # given an index file, list out the shas that it's packfile contains
102
+ def get_shas
103
+ shas = []
104
+ each_sha1 { |sha| shas << sha.unpack("H*")[0] }
105
+ shas
106
+ end
107
+
120
108
  def [](sha1)
121
109
  if obj = @cache[sha1]
122
110
  return obj
@@ -128,39 +116,77 @@ module Grit
128
116
  return obj
129
117
  end
130
118
 
131
- def each_entry
119
+ def init_pack
132
120
  with_idx do |idx|
133
- pos = OffsetStart
134
- @size.times do
135
- offset = idx[pos,OffsetSize].unpack('N')[0]
136
- sha1 = idx[pos+OffsetSize,SHA1Size]
137
- pos += EntrySize
138
- yield sha1, offset
121
+ @offsets = [0]
122
+ FanOutCount.times do |i|
123
+ pos = idx[i * IdxOffsetSize,IdxOffsetSize].unpack('N')[0]
124
+ if pos < @offsets[i]
125
+ raise PackFormatError, "pack #@name has discontinuous index #{i}"
126
+ end
127
+ @offsets << pos
139
128
  end
129
+ @size = @offsets[-1]
140
130
  end
141
131
  end
142
-
143
- def each_sha1
132
+
133
+ def each_entry
144
134
  with_idx do |idx|
145
- # unpacking the offset is quite expensive, so
146
- # we avoid using #each
147
- pos = SHA1Start
148
- @size.times do
149
- sha1 = idx[pos,SHA1Size]
150
- pos += EntrySize
151
- yield sha1
135
+ if @version == 2
136
+ data = read_data_v2(idx)
137
+ data.each do |sha1, crc, offset|
138
+ yield sha1, offset
139
+ end
140
+ else
141
+ pos = OffsetStart
142
+ @size.times do
143
+ offset = idx[pos,OffsetSize].unpack('N')[0]
144
+ sha1 = idx[pos+OffsetSize,SHA1Size]
145
+ pos += EntrySize
146
+ yield sha1, offset
147
+ end
152
148
  end
153
149
  end
154
150
  end
155
-
156
- def find_object(sha1)
157
- obj = nil
151
+
152
+ def read_data_v2(idx)
153
+ data = []
154
+ pos = OffsetStart
155
+ @size.times do |i|
156
+ data[i] = [idx[pos,SHA1Size], 0, 0]
157
+ pos += SHA1Size
158
+ end
159
+ @size.times do |i|
160
+ crc = idx[pos,CrcSize]
161
+ data[i][1] = crc
162
+ pos += CrcSize
163
+ end
164
+ @size.times do |i|
165
+ offset = idx[pos,OffsetSize].unpack('N')[0]
166
+ data[i][2] = offset
167
+ pos += OffsetSize
168
+ end
169
+ data
170
+ end
171
+ private :read_data_v2
172
+
173
+ def each_sha1
158
174
  with_idx do |idx|
159
- obj = find_object_in_index(idx, sha1)
175
+ if @version == 2
176
+ data = read_data_v2(idx)
177
+ data.each do |sha1, crc, offset|
178
+ yield sha1
179
+ end
180
+ else
181
+ pos = SHA1Start
182
+ @size.times do
183
+ sha1 = idx[pos,SHA1Size]
184
+ pos += EntrySize
185
+ yield sha1
186
+ end
187
+ end
160
188
  end
161
- obj
162
- end
163
- private :find_object
189
+ end
164
190
 
165
191
  def find_object_in_index(idx, sha1)
166
192
  slot = sha1[0]
@@ -168,22 +194,46 @@ module Grit
168
194
  first, last = @offsets[slot,2]
169
195
  while first < last
170
196
  mid = (first + last) / 2
171
- midsha1 = idx[SHA1Start + mid * EntrySize,SHA1Size]
172
- cmp = midsha1 <=> sha1
197
+ if @version == 2
198
+ midsha1 = idx[OffsetStart + (mid * SHA1Size), SHA1Size]
199
+ cmp = midsha1 <=> sha1
173
200
 
174
- if cmp < 0
175
- first = mid + 1
176
- elsif cmp > 0
177
- last = mid
201
+ if cmp < 0
202
+ first = mid + 1
203
+ elsif cmp > 0
204
+ last = mid
205
+ else
206
+ pos = OffsetStart + (@size * (SHA1Size + CrcSize)) + (mid * OffsetSize)
207
+ offset = idx[pos, OffsetSize].unpack('N')[0]
208
+ return offset
209
+ end
178
210
  else
179
- pos = OffsetStart + mid * EntrySize
180
- offset = idx[pos,OffsetSize].unpack('N')[0]
181
- return offset
211
+ midsha1 = idx[SHA1Start + mid * EntrySize,SHA1Size]
212
+ cmp = midsha1 <=> sha1
213
+
214
+ if cmp < 0
215
+ first = mid + 1
216
+ elsif cmp > 0
217
+ last = mid
218
+ else
219
+ pos = OffsetStart + mid * EntrySize
220
+ offset = idx[pos,OffsetSize].unpack('N')[0]
221
+ return offset
222
+ end
182
223
  end
183
224
  end
184
225
  nil
185
226
  end
186
-
227
+
228
+ def find_object(sha1)
229
+ obj = nil
230
+ with_idx do |idx|
231
+ obj = find_object_in_index(idx, sha1)
232
+ end
233
+ obj
234
+ end
235
+ private :find_object
236
+
187
237
  def parse_object(offset)
188
238
  obj = nil
189
239
  with_packfile do |packfile|
@@ -37,6 +37,7 @@ module Grit
37
37
  def initialize(git_dir, options = {})
38
38
  @git_dir = git_dir
39
39
  @options = options
40
+ @packs = []
40
41
  end
41
42
 
42
43
  # returns the loose objects object lazily
@@ -599,6 +600,53 @@ module Grit
599
600
  found_data
600
601
  end
601
602
 
603
+ # initialize a git repository
604
+ def self.init(dir, bare = false)
605
+
606
+ FileUtils.mkdir_p(dir) if !File.exists?(dir)
607
+
608
+ FileUtils.cd(dir) do
609
+ if(File.exists?('objects'))
610
+ return false # already initialized
611
+ else
612
+ # initialize directory
613
+ create_initial_config(bare)
614
+ FileUtils.mkdir_p('refs/heads')
615
+ FileUtils.mkdir_p('refs/tags')
616
+ FileUtils.mkdir_p('objects/info')
617
+ FileUtils.mkdir_p('objects/pack')
618
+ FileUtils.mkdir_p('branches')
619
+ add_file('description', 'Unnamed repository; edit this file to name it for gitweb.')
620
+ add_file('HEAD', "ref: refs/heads/master\n")
621
+ FileUtils.mkdir_p('hooks')
622
+ FileUtils.cd('hooks') do
623
+ add_file('applypatch-msg', '# add shell script and make executable to enable')
624
+ add_file('post-commit', '# add shell script and make executable to enable')
625
+ add_file('post-receive', '# add shell script and make executable to enable')
626
+ add_file('post-update', '# add shell script and make executable to enable')
627
+ add_file('pre-applypatch', '# add shell script and make executable to enable')
628
+ add_file('pre-commit', '# add shell script and make executable to enable')
629
+ add_file('pre-rebase', '# add shell script and make executable to enable')
630
+ add_file('update', '# add shell script and make executable to enable')
631
+ end
632
+ FileUtils.mkdir_p('info')
633
+ add_file('info/exclude', "# *.[oa]\n# *~")
634
+ end
635
+ end
636
+ end
637
+
638
+ def self.create_initial_config(bare = false)
639
+ bare ? bare_status = 'true' : bare_status = 'false'
640
+ config = "[core]\n\trepositoryformatversion = 0\n\tfilemode = true\n\tbare = #{bare_status}\n\tlogallrefupdates = true"
641
+ add_file('config', config)
642
+ end
643
+
644
+ def self.add_file(name, contents)
645
+ File.open(name, 'w') do |f|
646
+ f.write contents
647
+ end
648
+ end
649
+
602
650
  def close
603
651
  @packs.each do |pack|
604
652
  pack.close
@@ -625,6 +673,9 @@ module Grit
625
673
  alt = File.join(path, 'info/alternates')
626
674
  if File.exists?(alt)
627
675
  File.readlines(alt).each do |line|
676
+ if line[0, 2] == '..'
677
+ line = File.expand_path(File.join(@git_dir, line))
678
+ end
628
679
  load_loose(line.chomp)
629
680
  load_alternate_loose(line.chomp)
630
681
  end
@@ -648,6 +699,9 @@ module Grit
648
699
  alt = File.join(path, 'info/alternates')
649
700
  if File.exists?(alt)
650
701
  File.readlines(alt).each do |line|
702
+ if line[0, 2] == '..'
703
+ line = File.expand_path(File.join(@git_dir, line))
704
+ end
651
705
  full_pack = File.join(line.chomp, 'pack')
652
706
  load_packs(full_pack)
653
707
  load_alternate_packs(File.join(line.chomp))
data/lib/grit/index.rb CHANGED
@@ -1,11 +1,12 @@
1
1
  module Grit
2
2
 
3
3
  class Index
4
- attr_accessor :repo, :tree
4
+ attr_accessor :repo, :tree, :current_tree
5
5
 
6
6
  def initialize(repo)
7
7
  self.repo = repo
8
8
  self.tree = {}
9
+ self.current_tree = nil
9
10
  end
10
11
 
11
12
  # Add a file to the index
@@ -28,12 +29,16 @@ module Grit
28
29
  current[filename] = data
29
30
  end
30
31
 
32
+ def read_tree(tree)
33
+ self.current_tree = self.repo.tree(tree)
34
+ end
35
+
31
36
  # Commit the contents of the index
32
37
  # +message+ is the commit message
33
38
  #
34
39
  # Returns a String of the SHA1 of the commit
35
- def commit(message, parents = nil, actor = nil, last_tree = nil)
36
- tree_sha1 = write_tree(self.tree)
40
+ def commit(message, parents = nil, actor = nil, last_tree = nil, head = 'master')
41
+ tree_sha1 = write_tree(self.tree, self.current_tree)
37
42
  return false if tree_sha1 == last_tree # don't write identical commits
38
43
 
39
44
  contents = []
@@ -60,7 +65,7 @@ module Grit
60
65
  commit_sha1 = self.repo.git.ruby_git.put_raw_object(contents.join("\n"), 'commit')
61
66
 
62
67
  # self.repo.git.update_ref({}, 'HEAD', commit_sha1)
63
- File.open(File.join(self.repo.path, 'refs', 'heads', 'master'), 'w') do |f|
68
+ File.open(File.join(self.repo.path, 'refs', 'heads', head), 'w') do |f|
64
69
  f.write(commit_sha1)
65
70
  end if commit_sha1
66
71
 
@@ -71,23 +76,35 @@ module Grit
71
76
  # +tree+ is the tree
72
77
  #
73
78
  # Returns the SHA1 String of the tree
74
- def write_tree(tree)
75
- tree_contents = ''
79
+ def write_tree(tree, now_tree = nil)
80
+ tree_contents = {}
81
+
82
+ # fill in original tree
83
+ now_tree.contents.each do |obj|
84
+ sha = [obj.id].pack("H*")
85
+ k = obj.name
86
+ k += '/' if (obj.class == Grit::Tree)
87
+ tree_contents[k] = "%s %s\0%s" % [obj.mode.to_s, obj.name, sha]
88
+ end if now_tree
89
+
90
+ # overwrite with new tree contents
76
91
  tree.each do |k, v|
77
92
  case v
78
93
  when String:
79
94
  sha = write_blob(v)
80
95
  sha = [sha].pack("H*")
81
96
  str = "%s %s\0%s" % ['100644', k, sha]
82
- tree_contents += str
97
+ tree_contents[k] = str
83
98
  when Hash:
84
- sha = write_tree(v)
99
+ ctree = now_tree/k if now_tree
100
+ sha = write_tree(v, ctree)
85
101
  sha = [sha].pack("H*")
86
102
  str = "%s %s\0%s" % ['040000', k, sha]
87
- tree_contents += str
103
+ tree_contents[k + '/'] = str
88
104
  end
89
105
  end
90
- self.repo.git.ruby_git.put_raw_object(tree_contents, 'tree')
106
+ tr = tree_contents.sort.map { |k, v| v }.join('')
107
+ self.repo.git.ruby_git.put_raw_object(tr, 'tree')
91
108
  end
92
109
 
93
110
  # Write the blob to the index
data/lib/grit/repo.rb CHANGED
@@ -5,6 +5,7 @@ module Grit
5
5
 
6
6
  # The path of the git repo as a String
7
7
  attr_accessor :path
8
+ attr_accessor :working_dir
8
9
  attr_reader :bare
9
10
 
10
11
  # The git command line interface object
@@ -22,6 +23,7 @@ module Grit
22
23
  epath = File.expand_path(path)
23
24
 
24
25
  if File.exist?(File.join(epath, '.git'))
26
+ self.working_dir = epath
25
27
  self.path = File.join(epath, '.git')
26
28
  @bare = false
27
29
  elsif File.exist?(epath) && (epath =~ /\.git$/ || options[:is_bare])
@@ -60,6 +62,10 @@ module Grit
60
62
 
61
63
  alias_method :branches, :heads
62
64
 
65
+ def is_head?(head_name)
66
+ heads.find { |h| h.name == head_name }
67
+ end
68
+
63
69
  # Object reprsenting the current repo head.
64
70
  #
65
71
  # Returns Grit::Head (baked)
data/lib/grit/status.rb CHANGED
@@ -88,25 +88,27 @@ module Grit
88
88
  def construct_status
89
89
  @files = ls_files
90
90
 
91
- # find untracked in working dir
92
- Dir.glob('**/*') do |file|
93
- if !@files[file]
94
- @files[file] = {:path => file, :untracked => true} if !File.directory?(file)
91
+ Dir.chdir(@base.working_dir) do
92
+ # find untracked in working dir
93
+ Dir.glob('**/*') do |file|
94
+ if !@files[file]
95
+ @files[file] = {:path => file, :untracked => true} if !File.directory?(file)
96
+ end
95
97
  end
96
- end
97
98
 
98
- # find modified in tree
99
- diff_files.each do |path, data|
100
- @files[path] ? @files[path].merge!(data) : @files[path] = data
101
- end
99
+ # find modified in tree
100
+ diff_files.each do |path, data|
101
+ @files[path] ? @files[path].merge!(data) : @files[path] = data
102
+ end
102
103
 
103
- # find added but not committed - new files
104
- diff_index('HEAD').each do |path, data|
105
- @files[path] ? @files[path].merge!(data) : @files[path] = data
106
- end
104
+ # find added but not committed - new files
105
+ diff_index('HEAD').each do |path, data|
106
+ @files[path] ? @files[path].merge!(data) : @files[path] = data
107
+ end
107
108
 
108
- @files.each do |k, file_hash|
109
- @files[k] = StatusFile.new(@base, file_hash)
109
+ @files.each do |k, file_hash|
110
+ @files[k] = StatusFile.new(@base, file_hash)
111
+ end
110
112
  end
111
113
  end
112
114
 
data/test/test_head.rb CHANGED
@@ -28,6 +28,12 @@ class TestHead < Test::Unit::TestCase
28
28
  head = @r.heads[2]
29
29
  assert_equal %Q{#<Grit::Head "test/chacon">}, head.inspect
30
30
  end
31
+
32
+ def test_is_head
33
+ assert @r.is_head?('master')
34
+ assert @r.is_head?('test/chacon')
35
+ assert !@r.is_head?('masterblah')
36
+ end
31
37
 
32
38
  def test_head_count
33
39
  assert_equal 5, @r.heads.size
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: schacon-grit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.1
4
+ version: 0.9.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Preston-Werner
@@ -13,6 +13,15 @@ cert_chain: []
13
13
  date: 2008-04-24 00:00:00 -07:00
14
14
  default_executable:
15
15
  dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: diff-lcs
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
16
25
  - !ruby/object:Gem::Dependency
17
26
  name: mime-types
18
27
  version_requirement:
@@ -22,6 +31,15 @@ dependencies:
22
31
  - !ruby/object:Gem::Version
23
32
  version: 0.0.0
24
33
  version:
34
+ - !ruby/object:Gem::Dependency
35
+ name: open4
36
+ version_requirement:
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">"
40
+ - !ruby/object:Gem::Version
41
+ version: 0.0.0
42
+ version:
25
43
  description: Grit is a Ruby library for extracting information from a git repository in and object oriented manner.
26
44
  email: tom@rubyisawesome.com
27
45
  executables: []