1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
|
module Git
class GitTagNameDoesNotExist< StandardError
end
# represents a git object
class Object
class AbstractObject
attr_accessor :objectish, :size, :type, :mode
@base = nil
@contents = nil
@size = nil
@sha = nil
def initialize(base, objectish)
@base = base
@objectish = objectish.to_s
setup
end
def sha
@sha || @sha = @base.lib.revparse(@objectish)
end
def size
@size || @size = @base.lib.object_size(@objectish)
end
# caches the contents of this call in memory
def contents
@contents || @contents = @base.lib.object_contents(@objectish)
end
def contents_array
self.contents.split("\n")
end
def setup
raise NotImplementedError
end
def to_s
@objectish
end
def grep(string, path_limiter = nil, opts = {})
default = {:object => sha, :path_limiter => path_limiter}
grep_options = default.merge(opts)
@base.lib.grep(string, grep_options)
end
def diff(objectish)
Git::Diff.new(@base, @objectish, objectish)
end
def log(count = 30)
Git::Log.new(@base, count).object(@objectish)
end
# creates an archive of this object (tree)
def archive(file = nil, opts = {})
@base.lib.archive(@objectish, file, opts)
end
def tree?
@type == 'tree'
end
def blob?
@type == 'blob'
end
def commit?
@type == 'commit'
end
def tag?
@type == 'tag'
end
end
class Blob < AbstractObject
def initialize(base, sha, mode = nil)
super(base, sha)
@mode = mode
end
private
def setup
@type = 'blob'
end
end
class Tree < AbstractObject
@trees = nil
@blobs = nil
def initialize(base, sha, mode = nil)
super(base, sha)
@mode = mode
end
def children
blobs.merge(subtrees)
end
def blobs
check_tree
@blobs
end
alias_method :files, :blobs
def trees
check_tree
@trees
end
alias_method :subtrees, :trees
alias_method :subdirectories, :trees
private
def setup
@type = 'tree'
end
# actually run the git command
def check_tree
if !@trees
@trees = {}
@blobs = {}
data = @base.lib.ls_tree(@objectish)
data['tree'].each { |k, d| @trees[k] = Tree.new(@base, d[:sha], d[:mode]) }
data['blob'].each { |k, d| @blobs[k] = Blob.new(@base, d[:sha], d[:mode]) }
end
end
end
class Commit < AbstractObject
@tree = nil
@parents = nil
@author = nil
@committer = nil
@message = nil
def initialize(base, sha, init = nil)
super(base, sha)
if init
set_commit(init)
end
end
def message
check_commit
@message
end
def name
@base.lib.namerev(sha)
end
def gtree
check_commit
Tree.new(@base, @tree)
end
def parent
parents.first
end
# array of all parent commits
def parents
check_commit
@parents
end
# git author
def author
check_commit
@author
end
def author_date
author.date
end
# git author
def committer
check_commit
@committer
end
def committer_date
committer.date
end
alias_method :date, :committer_date
def diff_parent
diff(parent)
end
def set_commit(data)
if data['sha']
@sha = data['sha']
end
@committer = Git::Author.new(data['committer'])
@author = Git::Author.new(data['author'])
@tree = Tree.new(@base, data['tree'])
@parents = data['parent'].map{ |sha| Commit.new(@base, sha) }
@message = data['message'].chomp
end
private
def setup
@type = 'commit'
end
# see if this object has been initialized and do so if not
def check_commit
if !@tree
data = @base.lib.commit_data(@objectish)
set_commit(data)
end
end
end
class Tag < AbstractObject
attr_accessor :name
def initialize(base, sha, name)
super(base, sha)
@name = name
end
private
def setup
@type = 'tag'
end
end
class << self
# if we're calling this, we don't know what type it is yet
# so this is our little factory method
def new(base, objectish, type = nil, is_tag = false)
if is_tag
sha = base.lib.tag_sha(objectish)
if sha == ''
raise Git::GitTagNameDoesNotExist.new(objectish)
end
return Tag.new(base, sha, objectish)
else
if !type
type = base.lib.object_type(objectish)
end
end
klass =
case type
when /blob/: Blob
when /commit/: Commit
when /tree/: Tree
end
klass::new(base, objectish)
end
end
end
end
|