gash 0.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.
- data/CHANGELOG +1 -0
- data/Manifest +5 -0
- data/README +3 -0
- data/Rakefile +18 -0
- data/gash.gemspec +79 -0
- data/lib/gash.rb +401 -0
- metadata +78 -0
data/CHANGELOG
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
v0.1. First version.
|
data/Manifest
ADDED
data/README
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'echoe'
|
2
|
+
require 'hanna/rdoctask'
|
3
|
+
|
4
|
+
Echoe.new('gash') do |p|
|
5
|
+
p.project = "dojo"
|
6
|
+
p.author = "Magnus Holm"
|
7
|
+
p.email = "judofyr@gmail.com"
|
8
|
+
p.summary = "Git + Hash"
|
9
|
+
p.url = "http://dojo.rubyforge.org/gash/"
|
10
|
+
p.rdoc_options += ["--main", "Gash", "--title", "Gash"]
|
11
|
+
end
|
12
|
+
|
13
|
+
Rake::Task[:publish_docs].instance_eval do
|
14
|
+
@actions.clear
|
15
|
+
enhance do
|
16
|
+
sh("rsync -avc --delete doc/* judofyr@rubyforge.org:/var/www/gforge-projects/dojo/gash/")
|
17
|
+
end
|
18
|
+
end
|
data/gash.gemspec
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
|
2
|
+
# Gem::Specification for Gash-0.1
|
3
|
+
# Originally generated by Echoe
|
4
|
+
|
5
|
+
--- !ruby/object:Gem::Specification
|
6
|
+
name: gash
|
7
|
+
version: !ruby/object:Gem::Version
|
8
|
+
version: "0.1"
|
9
|
+
platform: ruby
|
10
|
+
authors:
|
11
|
+
- Magnus Holm
|
12
|
+
autorequire:
|
13
|
+
bindir: bin
|
14
|
+
|
15
|
+
date: 2008-09-04 00:00:00 +02:00
|
16
|
+
default_executable:
|
17
|
+
dependencies:
|
18
|
+
- !ruby/object:Gem::Dependency
|
19
|
+
name: echoe
|
20
|
+
type: :development
|
21
|
+
version_requirement:
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: "0"
|
27
|
+
version:
|
28
|
+
description: Git + Hash
|
29
|
+
email: judofyr@gmail.com
|
30
|
+
executables: []
|
31
|
+
|
32
|
+
extensions: []
|
33
|
+
|
34
|
+
extra_rdoc_files:
|
35
|
+
- CHANGELOG
|
36
|
+
- lib/gash.rb
|
37
|
+
- README
|
38
|
+
files:
|
39
|
+
- CHANGELOG
|
40
|
+
- lib/gash.rb
|
41
|
+
- Rakefile
|
42
|
+
- README
|
43
|
+
- Manifest
|
44
|
+
- gash.gemspec
|
45
|
+
has_rdoc: true
|
46
|
+
homepage: http://dojo.rubyforge.org/gash/
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options:
|
49
|
+
- --line-numbers
|
50
|
+
- --inline-source
|
51
|
+
- --title
|
52
|
+
- Gash
|
53
|
+
- --main
|
54
|
+
- README
|
55
|
+
- --main
|
56
|
+
- Gash
|
57
|
+
- --title
|
58
|
+
- Gash
|
59
|
+
require_paths:
|
60
|
+
- lib
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: "0"
|
66
|
+
version:
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - "="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: "1.2"
|
72
|
+
version:
|
73
|
+
requirements: []
|
74
|
+
|
75
|
+
rubyforge_project: dojo
|
76
|
+
rubygems_version: 1.2.0
|
77
|
+
specification_version: 2
|
78
|
+
summary: Git + Hash
|
79
|
+
test_files: []
|
data/lib/gash.rb
ADDED
@@ -0,0 +1,401 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
3
|
+
# == What is Gash?
|
4
|
+
#
|
5
|
+
# * Gash lets you access a Git-repo as a Hash.
|
6
|
+
# * Gash only cares about the data, not the commits.
|
7
|
+
# * Gash only cares about the _latest_ data.
|
8
|
+
# * Gash can commit.
|
9
|
+
# * Gash doesn't touch your working directory
|
10
|
+
# * Gash will automatically create branches if they don't exists.
|
11
|
+
# * Gash only loads what it needs, so it handles large repos well.
|
12
|
+
#
|
13
|
+
# == How do you use it?
|
14
|
+
#
|
15
|
+
# gash = Gash.new
|
16
|
+
# gash["README"] = "new content"
|
17
|
+
# gash.commit("Some changes...")
|
18
|
+
#
|
19
|
+
# It's also important to remember that a Gash is simply a Tree, so you can
|
20
|
+
# also call those methods.
|
21
|
+
#
|
22
|
+
# <strong>See also</strong>: #new, #commit, Tree
|
23
|
+
#
|
24
|
+
# == Limitation
|
25
|
+
#
|
26
|
+
# The only Hash-like features which currently works is #[] and #[]=,
|
27
|
+
# so don't try #merge or something like that.
|
28
|
+
class Gash < SimpleDelegator
|
29
|
+
module Errors
|
30
|
+
# This error is raised when the Git-command fails.
|
31
|
+
class Git < StandardError; end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Some common methods used by both Tree and Blob.
|
35
|
+
module Helpers
|
36
|
+
attr_accessor :sha1, :mode, :parent
|
37
|
+
|
38
|
+
# Sets the accessors using a Hash:
|
39
|
+
#
|
40
|
+
# tree = Gash::Tree.new(:sha1 => "some thing", :mode => "some thing",
|
41
|
+
# :parent => "some parent")
|
42
|
+
# tree.sha1 == "some thing"
|
43
|
+
# tree.mode == "some thing"
|
44
|
+
# tree.parent == "some parent"
|
45
|
+
def initialize(opts = {})
|
46
|
+
opts.each do |key, value|
|
47
|
+
send("#{key}=", value)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Checks if this is a Blob.
|
52
|
+
def blob?; self.class == Gash::Blob end
|
53
|
+
# Checks if this is a Tree.
|
54
|
+
def tree?; self.class == Gash::Tree end
|
55
|
+
# Checks if this object has been changed (since last commit).
|
56
|
+
def changed?; !@sha1 end
|
57
|
+
# Mark this, and all parents as changed.
|
58
|
+
def changed!; @sha1 = nil;parent.changed! end
|
59
|
+
# Returns the Gash-object (top-parent).
|
60
|
+
def gash; parent.gash end
|
61
|
+
end
|
62
|
+
|
63
|
+
# A Tree is a Hash which can store other instances of Tree and Blob.
|
64
|
+
#
|
65
|
+
# <strong>See also</strong>: Helpers, Blob
|
66
|
+
class Tree < Hash
|
67
|
+
include Helpers
|
68
|
+
|
69
|
+
# Retrieves the _value_ stored as +key+:
|
70
|
+
#
|
71
|
+
# tree["FILE"] == the file
|
72
|
+
# tree["DIR/FILE"] == tree["DIR"]["FILE"] = another file
|
73
|
+
#
|
74
|
+
# It will automatically call the +load!+-method in order to load
|
75
|
+
# it from the repo. Set +lazy+ to +true+ if this is not what you want:
|
76
|
+
#
|
77
|
+
# blob = tree["FILE", true] == #<Blob:1234...>
|
78
|
+
# # do some other stuff...
|
79
|
+
# blob.laod! # Load it now!
|
80
|
+
def [](key, lazy = nil)
|
81
|
+
ret = if key.include?("/")
|
82
|
+
key, rest = key.split("/", 2)
|
83
|
+
value = super(key)
|
84
|
+
return if value.nil?
|
85
|
+
value[rest]
|
86
|
+
else
|
87
|
+
super(key)
|
88
|
+
end
|
89
|
+
ensure
|
90
|
+
ret.load! if ret.respond_to?(:load!) && !lazy
|
91
|
+
end
|
92
|
+
alias / []
|
93
|
+
|
94
|
+
# Stores the given _value_:
|
95
|
+
#
|
96
|
+
# tree["FILE"] = "Content"
|
97
|
+
#
|
98
|
+
# Unless it's already a Tree or a Blob, it will be converted to a Blob,
|
99
|
+
# and the parent will _always_ be set to +self+.
|
100
|
+
#
|
101
|
+
# tree["FILE"] = "Content"
|
102
|
+
# # is the same as:
|
103
|
+
# tree["FILE"] = Gash::Blob.new(:content => "Content", :parent => tree)
|
104
|
+
#
|
105
|
+
# It will also mark the object as changed (using <code>Helpers#changed!</code>).
|
106
|
+
# Set +not_changed+ to +true+ if this is not what you want.
|
107
|
+
#
|
108
|
+
# (If you give it three arguments, then the second one will act as
|
109
|
+
# +not_changed+, not the third):
|
110
|
+
#
|
111
|
+
# tree["FILE", true] = "Test"
|
112
|
+
# tree["FILE"].changed? # => false
|
113
|
+
def []=(key, value, not_changed = nil)
|
114
|
+
key, value, not_changed = if not_changed.nil?
|
115
|
+
[key, value]
|
116
|
+
else
|
117
|
+
[key, not_changed, value]
|
118
|
+
end
|
119
|
+
|
120
|
+
if key.include?("/")
|
121
|
+
keys = key.split("/")
|
122
|
+
name = keys.pop
|
123
|
+
keys.inject(self) do |memo, i|
|
124
|
+
memo[i] = Tree.new(:parent => self) unless memo.include?(i)
|
125
|
+
memo[i, true]
|
126
|
+
end[name, not_changed] = value
|
127
|
+
else
|
128
|
+
value = case value
|
129
|
+
when Tree, Blob
|
130
|
+
value
|
131
|
+
else
|
132
|
+
Blob.new(:content => value.to_s)
|
133
|
+
end
|
134
|
+
value.parent = self
|
135
|
+
super(key, value)
|
136
|
+
end
|
137
|
+
ensure
|
138
|
+
self.changed! unless not_changed
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# A Blob represent a string:
|
143
|
+
#
|
144
|
+
# blob = Gash::Blob.new(:content => "Some content")
|
145
|
+
# blob # => "Some content"
|
146
|
+
#
|
147
|
+
# == Using SHA1
|
148
|
+
#
|
149
|
+
# However, if you provide a SHA1 (and have a parent which is connected to
|
150
|
+
# a Gash-object) it will then load the content from the repo when needed:
|
151
|
+
#
|
152
|
+
# blob = Gash::Blob.new(:sha1 => "1234" * 10, :parent => gash_OR_tree_connected_to_gash)
|
153
|
+
# blob # => #<Blob:1234123412341234123412341234123412341234>
|
154
|
+
# blob.upcase # It's loaded when needed
|
155
|
+
# #blob.load! # or forced with #load!
|
156
|
+
# blob # => "Content of the blob"
|
157
|
+
#
|
158
|
+
# Tree#[]= automatically sets the parent to itself, so you don't need to
|
159
|
+
# provide it then:
|
160
|
+
#
|
161
|
+
# tree["FILE"] = Gash::Blob.new(:sha1 => a_sha1)
|
162
|
+
#
|
163
|
+
# <strong>See also</strong>: Helpers, Tree
|
164
|
+
class Blob < Delegator
|
165
|
+
include Helpers
|
166
|
+
attr_accessor :content
|
167
|
+
|
168
|
+
# Loads the file from Git, unless it's already been loaded.
|
169
|
+
def load!
|
170
|
+
@content ||= gash.send(:cat_file, @sha1)
|
171
|
+
end
|
172
|
+
|
173
|
+
def inspect #:nodoc:
|
174
|
+
@content ? @content.inspect : (@sha1 ? "#<Blob:#{@sha1}>" : to_s.inspect)
|
175
|
+
end
|
176
|
+
|
177
|
+
def __getobj__ #:nodoc:
|
178
|
+
@content ||= @sha1 ? load! : ''
|
179
|
+
end
|
180
|
+
alias_method :to_s, :__getobj__
|
181
|
+
end
|
182
|
+
|
183
|
+
attr_accessor :branch, :repository
|
184
|
+
|
185
|
+
# Opens the +repo+ with the specified +branch+.
|
186
|
+
#
|
187
|
+
# <strong>Please note:</strong> The +repo+ must link to the actual repo,
|
188
|
+
# not the working directory!
|
189
|
+
def initialize(branch = "master", repo = ".git")
|
190
|
+
@branch = branch
|
191
|
+
@repository = File.expand_path(repo)
|
192
|
+
__setobj__(Tree.new(:parent => self))
|
193
|
+
update!
|
194
|
+
end
|
195
|
+
|
196
|
+
def gash #:nodoc:
|
197
|
+
self
|
198
|
+
end
|
199
|
+
|
200
|
+
def changed! #:nodoc:
|
201
|
+
@sha1 = nil
|
202
|
+
end
|
203
|
+
|
204
|
+
# Fetch the latest data from Git; you can use this as a +clear+-method.
|
205
|
+
def update!
|
206
|
+
clear
|
207
|
+
self.sha1 = git_tree_sha1
|
208
|
+
git_tree do |line|
|
209
|
+
line.strip!
|
210
|
+
mode = line[0, 6]
|
211
|
+
type = line[7]
|
212
|
+
sha1 = line[12, 40]
|
213
|
+
name = line[53..-1]
|
214
|
+
if name[0] == ?" && name[-1] == ?"
|
215
|
+
name = eval(name)
|
216
|
+
end
|
217
|
+
name = name[/[^\/]+$/]
|
218
|
+
parent = if $`.empty?
|
219
|
+
self
|
220
|
+
else
|
221
|
+
self[$`.chomp("/")]
|
222
|
+
end
|
223
|
+
parent[name, true] = case type
|
224
|
+
when ?b
|
225
|
+
Blob.new(:sha1 => sha1, :mode => mode)
|
226
|
+
when ?t
|
227
|
+
Tree.new(:sha1 => sha1, :mode => mode)
|
228
|
+
end
|
229
|
+
end
|
230
|
+
self
|
231
|
+
end
|
232
|
+
|
233
|
+
# Commit the current changes and returns the commit-hash.
|
234
|
+
#
|
235
|
+
# Returns +nil+ if nothing has changed.
|
236
|
+
def commit(msg)
|
237
|
+
return unless changed?
|
238
|
+
commit = commit_tree(to_tree!, msg)
|
239
|
+
@sha1 = git_tree_sha1
|
240
|
+
commit
|
241
|
+
end
|
242
|
+
|
243
|
+
# Checks if the current branch exists
|
244
|
+
def branch_exists?
|
245
|
+
git('rev-parse', @branch, '2>&1')
|
246
|
+
true
|
247
|
+
rescue Errors::Git
|
248
|
+
false
|
249
|
+
end
|
250
|
+
|
251
|
+
def inspect #:nodoc:
|
252
|
+
__getobj__.inspect
|
253
|
+
end
|
254
|
+
|
255
|
+
private
|
256
|
+
|
257
|
+
def cat_file(blob)
|
258
|
+
git('cat-file', 'blob', blob)
|
259
|
+
end
|
260
|
+
|
261
|
+
def to_tree!(from = self)
|
262
|
+
input = []
|
263
|
+
from.each do |key, value|
|
264
|
+
key = key.inspect
|
265
|
+
if value.tree?
|
266
|
+
value.sha1 ||= to_tree!(value)
|
267
|
+
value.mode ||= "040000"
|
268
|
+
input << "#{value.mode} tree #{value.sha1}\t#{key}\n"
|
269
|
+
else
|
270
|
+
value.sha1 ||= git('hash-object', '-w', '--stdin', :input => value.to_s)
|
271
|
+
value.mode ||= "100644"
|
272
|
+
input << "#{value.mode} blob #{value.sha1}\t#{key}\n"
|
273
|
+
end
|
274
|
+
end
|
275
|
+
git('mktree', :input => input)
|
276
|
+
end
|
277
|
+
|
278
|
+
def update_head(new_head)
|
279
|
+
git('update-ref', 'refs/heads/%s' % @branch, new_head)
|
280
|
+
end
|
281
|
+
|
282
|
+
def commit_tree(tree, msg)
|
283
|
+
if branch_exists?
|
284
|
+
commit = git('commit-tree', tree, '-p', @branch, :input => msg)
|
285
|
+
update_head(commit)
|
286
|
+
else
|
287
|
+
commit = git('commit-tree', tree, :input => msg)
|
288
|
+
git('branch', @branch, commit)
|
289
|
+
end
|
290
|
+
commit
|
291
|
+
end
|
292
|
+
|
293
|
+
def git_tree(&blk)
|
294
|
+
git('ls-tree', '-r', '-t', @branch, '2>&1') do |f|
|
295
|
+
f.each_line(&blk)
|
296
|
+
end
|
297
|
+
rescue Errors::Git
|
298
|
+
""
|
299
|
+
end
|
300
|
+
|
301
|
+
def git_tree_sha1(from = @branch)
|
302
|
+
git('rev-parse', @branch + '^{tree}', '2>&1')
|
303
|
+
rescue Errors::Git
|
304
|
+
end
|
305
|
+
|
306
|
+
def method_missing(meth, *args, &blk)
|
307
|
+
target = self.__getobj__
|
308
|
+
unless target.respond_to?(meth)
|
309
|
+
Object.instance_method(:method_missing).bind(self).call(meth, *args, &blk)
|
310
|
+
end
|
311
|
+
target.__send__(meth, *args, &blk)
|
312
|
+
end
|
313
|
+
|
314
|
+
# passes the command over to git
|
315
|
+
#
|
316
|
+
# ==== Parameters
|
317
|
+
# cmd<String>:: the git command to execute
|
318
|
+
# *rest:: any number of String arguments to the command, followed by an options hash
|
319
|
+
# &block:: if you supply a block, you can communicate with git throught a pipe. NEVER even think about closing the stream!
|
320
|
+
#
|
321
|
+
# ==== Options
|
322
|
+
# :strip<Boolean>:: true to strip the output String#strip, false not to to it
|
323
|
+
#
|
324
|
+
# ==== Raises
|
325
|
+
# Errors::Git:: if git returns non-null, an Exception is raised
|
326
|
+
#
|
327
|
+
# ==== Returns
|
328
|
+
# String:: if you didn't supply a block, the things git said on STDOUT, otherwise noting
|
329
|
+
def git(cmd, *rest, &block)
|
330
|
+
result, status = run_git(cmd, *rest, &block)
|
331
|
+
|
332
|
+
if status != 0
|
333
|
+
raise Errors::Git.new("Error: #{cmd} returned #{status}. Result: #{result}")
|
334
|
+
end
|
335
|
+
result
|
336
|
+
end
|
337
|
+
|
338
|
+
|
339
|
+
# passes the command over to git and returns its status ($?)
|
340
|
+
#
|
341
|
+
# ==== Parameters
|
342
|
+
# cmd<String>:: the git command to execute
|
343
|
+
# *rest:: any number of String arguments to the command, followed by an options hash
|
344
|
+
# &block:: if you supply a block, you can communicate with git throught a pipe. NEVER even think about closing the stream!
|
345
|
+
#
|
346
|
+
# ==== Returns
|
347
|
+
# Integer:: the return status of git
|
348
|
+
def git_status(cmd, *rest, &block)
|
349
|
+
run_git(cmd, *rest, &block)[1]
|
350
|
+
end
|
351
|
+
|
352
|
+
# passes the command over to git (you should not call this directly)
|
353
|
+
#
|
354
|
+
# ==== Parameters
|
355
|
+
# cmd<String>:: the git command to execute
|
356
|
+
# *rest:: any number of String arguments to the command, followed by an options hash
|
357
|
+
# &block:: if you supply a block, you can communicate with git throught a pipe. NEVER even think about closing the stream!
|
358
|
+
#
|
359
|
+
# ==== Options
|
360
|
+
# :strip<Boolean>:: true to strip the output String#strip, false not to to it
|
361
|
+
#
|
362
|
+
# ==== Raises
|
363
|
+
# Errors::Git:: if git returns non-null, an Exception is raised
|
364
|
+
#
|
365
|
+
# ==== Returns
|
366
|
+
# Array[String, Integer]:: the first item is the STDOUT of git, the second is the return-status
|
367
|
+
def run_git(cmd, *args, &block)
|
368
|
+
options = if args.last.kind_of?(Hash)
|
369
|
+
args.pop
|
370
|
+
else
|
371
|
+
{}
|
372
|
+
end
|
373
|
+
|
374
|
+
options[:strip] = true unless options.key?(:strip)
|
375
|
+
|
376
|
+
ENV["GIT_DIR"] = @repository
|
377
|
+
cmd = "git #{cmd} #{args.join(' ')}"
|
378
|
+
|
379
|
+
result = ""
|
380
|
+
IO.popen(cmd, "w+") do |f|
|
381
|
+
if input = options.delete(:input)
|
382
|
+
f.write(input)
|
383
|
+
f.close_write
|
384
|
+
elsif block_given?
|
385
|
+
yield f
|
386
|
+
f.close_write
|
387
|
+
end
|
388
|
+
|
389
|
+
result = ""
|
390
|
+
|
391
|
+
while !f.eof
|
392
|
+
result << f.read
|
393
|
+
end
|
394
|
+
end
|
395
|
+
status = $?
|
396
|
+
|
397
|
+
result.strip! if options[:strip] == true
|
398
|
+
|
399
|
+
[result, status]
|
400
|
+
end
|
401
|
+
end
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gash
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "0.1"
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Magnus Holm
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-09-04 00:00:00 +02:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: echoe
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
description: Git + Hash
|
26
|
+
email: judofyr@gmail.com
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- CHANGELOG
|
33
|
+
- lib/gash.rb
|
34
|
+
- README
|
35
|
+
files:
|
36
|
+
- CHANGELOG
|
37
|
+
- lib/gash.rb
|
38
|
+
- Rakefile
|
39
|
+
- README
|
40
|
+
- Manifest
|
41
|
+
- gash.gemspec
|
42
|
+
has_rdoc: true
|
43
|
+
homepage: http://dojo.rubyforge.org/gash/
|
44
|
+
post_install_message:
|
45
|
+
rdoc_options:
|
46
|
+
- --line-numbers
|
47
|
+
- --inline-source
|
48
|
+
- --title
|
49
|
+
- Gash
|
50
|
+
- --main
|
51
|
+
- README
|
52
|
+
- --main
|
53
|
+
- Gash
|
54
|
+
- --title
|
55
|
+
- Gash
|
56
|
+
require_paths:
|
57
|
+
- lib
|
58
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: "0"
|
63
|
+
version:
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: "1.2"
|
69
|
+
version:
|
70
|
+
requirements: []
|
71
|
+
|
72
|
+
rubyforge_project: dojo
|
73
|
+
rubygems_version: 1.2.0
|
74
|
+
signing_key:
|
75
|
+
specification_version: 2
|
76
|
+
summary: Git + Hash
|
77
|
+
test_files: []
|
78
|
+
|