grit 2.0.0 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of grit might be problematic. Click here for more details.
- data/History.txt +21 -0
- data/PURE_TODO +35 -0
- data/Rakefile +149 -0
- data/{test/bench/benchmarks.rb → benchmarks.rb} +6 -3
- data/benchmarks.txt +21 -0
- data/examples/ex_index.rb +7 -0
- data/grit.gemspec +76 -0
- data/lib/grit.rb +7 -5
- data/lib/grit/commit.rb +26 -12
- data/lib/grit/diff.rb +22 -13
- data/lib/grit/errors.rb +4 -1
- data/lib/grit/git-ruby.rb +12 -7
- data/lib/grit/git-ruby/git_object.rb +2 -2
- data/lib/grit/git-ruby/internal/loose.rb +1 -1
- data/lib/grit/git-ruby/internal/pack.rb +2 -0
- data/lib/grit/git-ruby/repository.rb +33 -6
- data/lib/grit/git.rb +9 -4
- data/lib/grit/index.rb +1 -1
- data/lib/{open3_detach.rb → grit/open3_detach.rb} +0 -0
- data/lib/grit/ref.rb +3 -1
- data/lib/grit/repo.rb +81 -1
- data/lib/grit/tag.rb +57 -4
- data/lib/grit/tree.rb +1 -1
- metadata +30 -46
- data/VERSION.yml +0 -4
- data/test/helper.rb +0 -18
- data/test/profile.rb +0 -21
- data/test/suite.rb +0 -6
- data/test/test_actor.rb +0 -35
- data/test/test_blame.rb +0 -32
- data/test/test_blame_tree.rb +0 -33
- data/test/test_blob.rb +0 -83
- data/test/test_commit.rb +0 -207
- data/test/test_commit_stats.rb +0 -33
- data/test/test_commit_write.rb +0 -20
- data/test/test_config.rb +0 -58
- data/test/test_diff.rb +0 -18
- data/test/test_file_index.rb +0 -56
- data/test/test_git.rb +0 -105
- data/test/test_grit.rb +0 -32
- data/test/test_head.rb +0 -47
- data/test/test_index_status.rb +0 -40
- data/test/test_merge.rb +0 -17
- data/test/test_raw.rb +0 -16
- data/test/test_real.rb +0 -19
- data/test/test_reality.rb +0 -17
- data/test/test_remote.rb +0 -14
- data/test/test_repo.rb +0 -349
- data/test/test_rubygit.rb +0 -192
- data/test/test_rubygit_alt.rb +0 -40
- data/test/test_rubygit_index.rb +0 -76
- data/test/test_rubygit_iv2.rb +0 -28
- data/test/test_submodule.rb +0 -69
- data/test/test_tag.rb +0 -67
- data/test/test_tree.rb +0 -101
data/lib/grit/diff.rb
CHANGED
@@ -4,20 +4,23 @@ module Grit
|
|
4
4
|
attr_reader :a_path, :b_path
|
5
5
|
attr_reader :a_blob, :b_blob
|
6
6
|
attr_reader :a_mode, :b_mode
|
7
|
-
attr_reader :new_file, :deleted_file
|
8
|
-
attr_reader :
|
7
|
+
attr_reader :new_file, :deleted_file, :renamed_file
|
8
|
+
attr_reader :similarity_index
|
9
|
+
attr_accessor :diff
|
9
10
|
|
10
|
-
def initialize(repo, a_path, b_path, a_blob, b_blob, a_mode, b_mode, new_file, deleted_file, diff)
|
11
|
-
@repo
|
11
|
+
def initialize(repo, a_path, b_path, a_blob, b_blob, a_mode, b_mode, new_file, deleted_file, diff, renamed_file = false, similarity_index = 0)
|
12
|
+
@repo = repo
|
12
13
|
@a_path = a_path
|
13
14
|
@b_path = b_path
|
14
15
|
@a_blob = a_blob =~ /^0{40}$/ ? nil : Blob.create(repo, :id => a_blob)
|
15
16
|
@b_blob = b_blob =~ /^0{40}$/ ? nil : Blob.create(repo, :id => b_blob)
|
16
17
|
@a_mode = a_mode
|
17
18
|
@b_mode = b_mode
|
18
|
-
@new_file
|
19
|
-
@deleted_file
|
20
|
-
@
|
19
|
+
@new_file = new_file || @a_blob.nil?
|
20
|
+
@deleted_file = deleted_file || @b_blob.nil?
|
21
|
+
@renamed_file = renamed_file
|
22
|
+
@similarity_index = similarity_index.to_i
|
23
|
+
@diff = diff
|
21
24
|
end
|
22
25
|
|
23
26
|
def self.list_from_string(repo, text)
|
@@ -38,17 +41,23 @@ module Grit
|
|
38
41
|
next
|
39
42
|
end
|
40
43
|
|
41
|
-
|
44
|
+
sim_index = 0
|
45
|
+
new_file = false
|
42
46
|
deleted_file = false
|
47
|
+
renamed_file = false
|
43
48
|
|
44
49
|
if lines.first =~ /^new file/
|
45
50
|
m, b_mode = lines.shift.match(/^new file mode (.+)$/)
|
46
|
-
a_mode
|
47
|
-
new_file
|
51
|
+
a_mode = nil
|
52
|
+
new_file = true
|
48
53
|
elsif lines.first =~ /^deleted file/
|
49
|
-
m, a_mode
|
50
|
-
b_mode
|
54
|
+
m, a_mode = lines.shift.match(/^deleted file mode (.+)$/)
|
55
|
+
b_mode = nil
|
51
56
|
deleted_file = true
|
57
|
+
elsif lines.first =~ /^similarity index (\d+)\%/
|
58
|
+
sim_index = $1.to_i
|
59
|
+
renamed_file = true
|
60
|
+
2.times { lines.shift } # shift away the 2 `rename from/to ...` lines
|
52
61
|
end
|
53
62
|
|
54
63
|
m, a_blob, b_blob, b_mode = *lines.shift.match(%r{^index ([0-9A-Fa-f]+)\.\.([0-9A-Fa-f]+) ?(.+)?$})
|
@@ -60,7 +69,7 @@ module Grit
|
|
60
69
|
end
|
61
70
|
diff = diff_lines.join("\n")
|
62
71
|
|
63
|
-
diffs << Diff.new(repo, a_path, b_path, a_blob, b_blob, a_mode, b_mode, new_file, deleted_file, diff)
|
72
|
+
diffs << Diff.new(repo, a_path, b_path, a_blob, b_blob, a_mode, b_mode, new_file, deleted_file, diff, renamed_file, sim_index)
|
64
73
|
end
|
65
74
|
|
66
75
|
diffs
|
data/lib/grit/errors.rb
CHANGED
data/lib/grit/git-ruby.rb
CHANGED
@@ -18,28 +18,33 @@ module Grit
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
def cat_file(options,
|
21
|
+
def cat_file(options, sha)
|
22
22
|
if options[:t]
|
23
|
-
file_type(
|
23
|
+
file_type(sha)
|
24
24
|
elsif options[:s]
|
25
|
-
file_size(
|
25
|
+
file_size(sha)
|
26
26
|
elsif options[:p]
|
27
|
-
try_run { ruby_git.cat_file(
|
27
|
+
try_run { ruby_git.cat_file(sha) }
|
28
28
|
end
|
29
29
|
rescue Grit::GitRuby::Repository::NoSuchShaFound
|
30
30
|
''
|
31
31
|
end
|
32
32
|
|
33
|
+
def cat_ref(options, ref)
|
34
|
+
sha = rev_parse({}, ref)
|
35
|
+
cat_file(options, sha)
|
36
|
+
end
|
37
|
+
|
33
38
|
# lib/grit/tree.rb:16: output = repo.git.ls_tree({}, treeish, *paths)
|
34
39
|
def ls_tree(options, treeish, *paths)
|
35
40
|
sha = rev_parse({}, treeish)
|
36
|
-
ruby_git.ls_tree(sha, paths.flatten)
|
41
|
+
ruby_git.ls_tree(sha, paths.flatten, options.delete(:r))
|
37
42
|
rescue Grit::GitRuby::Repository::NoSuchShaFound
|
38
43
|
''
|
39
44
|
end
|
40
45
|
|
41
46
|
# git diff --full-index 'ec037431382e83c3e95d4f2b3d145afbac8ea55d' 'f1ec1aea10986159456846b8a05615b87828d6c6'
|
42
|
-
def diff(options, sha1, sha2)
|
47
|
+
def diff(options, sha1, sha2 = nil)
|
43
48
|
try_run { ruby_git.diff(sha1, sha2, options) }
|
44
49
|
end
|
45
50
|
|
@@ -100,7 +105,7 @@ module Grit
|
|
100
105
|
## !! more - partials and such !!
|
101
106
|
|
102
107
|
# revert to calling git - grr
|
103
|
-
return method_missing('rev-parse',
|
108
|
+
return method_missing('rev-parse', options, string).chomp
|
104
109
|
end
|
105
110
|
|
106
111
|
def refs(options, prefix)
|
@@ -337,8 +337,8 @@ module Grit
|
|
337
337
|
end
|
338
338
|
|
339
339
|
def raw_content
|
340
|
-
"object %s\ntype %s\ntag %s\ntagger %s\n\n" % \
|
341
|
-
[@object, @type, @tag, @tagger] + @message
|
340
|
+
("object %s\ntype %s\ntag %s\ntagger %s\n\n" % \
|
341
|
+
[@object, @type, @tag, @tagger]) + @message.to_s
|
342
342
|
end
|
343
343
|
|
344
344
|
def type
|
@@ -169,7 +169,8 @@ module Grit
|
|
169
169
|
# returns the raw (cat-file) output for a tree
|
170
170
|
# if given a commit sha, it will print the tree of that commit
|
171
171
|
# if given a path limiter array, it will limit the output to those
|
172
|
-
|
172
|
+
# if asked for recrusive trees, will traverse trees
|
173
|
+
def ls_tree(sha, paths = [], recursive = false)
|
173
174
|
if paths.size > 0
|
174
175
|
# pathing
|
175
176
|
part = []
|
@@ -178,20 +179,44 @@ module Grit
|
|
178
179
|
end
|
179
180
|
return part.join("\n")
|
180
181
|
else
|
181
|
-
get_raw_tree(sha)
|
182
|
+
get_raw_tree(sha, recursive)
|
182
183
|
end
|
183
184
|
end
|
184
185
|
|
185
|
-
def get_raw_tree(sha)
|
186
|
+
def get_raw_tree(sha, recursive = false)
|
186
187
|
o = get_raw_object_by_sha1(sha)
|
187
188
|
if o.type == :commit
|
188
|
-
|
189
|
+
tree = get_object_by_sha1(sha).tree
|
189
190
|
elsif o.type == :tag
|
190
191
|
commit_sha = get_object_by_sha1(sha).object
|
191
|
-
|
192
|
+
tree = get_object_by_sha1(commit_sha).tree
|
192
193
|
elsif o.type == :tree
|
193
|
-
|
194
|
+
tree = sha
|
195
|
+
else
|
196
|
+
return nil
|
194
197
|
end
|
198
|
+
|
199
|
+
recursive ? get_raw_trees(tree) : cat_file(tree)
|
200
|
+
end
|
201
|
+
|
202
|
+
# Grabs tree contents recursively,
|
203
|
+
# e.g. `git ls-tree -r sha`
|
204
|
+
def get_raw_trees(sha, path = '')
|
205
|
+
out = ''
|
206
|
+
cat_file(sha).split("\n").each do |line|
|
207
|
+
mode, type, sha, name = line.split(/\s/)
|
208
|
+
|
209
|
+
if type == 'tree'
|
210
|
+
full_name = path.empty? ? name : "#{path}/#{name}"
|
211
|
+
out << get_raw_trees(sha, full_name)
|
212
|
+
elsif path.empty?
|
213
|
+
out << line + "\n"
|
214
|
+
else
|
215
|
+
out << line.gsub(name, "#{path}/#{name}") + "\n"
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
out
|
195
220
|
end
|
196
221
|
|
197
222
|
# return array of tree entries
|
@@ -219,6 +244,7 @@ module Grit
|
|
219
244
|
tree
|
220
245
|
end
|
221
246
|
else
|
247
|
+
raise NoSuchPath if tree.nil?
|
222
248
|
next_path = paths.shift
|
223
249
|
dir_name = tree.split("\n").select { |p| p.split("\t")[1] == next_path }.first
|
224
250
|
raise NoSuchPath if !dir_name
|
@@ -231,6 +257,7 @@ module Grit
|
|
231
257
|
end
|
232
258
|
end
|
233
259
|
else
|
260
|
+
raise NoSuchPath if tree.nil?
|
234
261
|
tree = tree.split("\n")
|
235
262
|
tree = tree.select { |p| p.split("\t")[1] == path }
|
236
263
|
if append
|
data/lib/grit/git.rb
CHANGED
@@ -27,6 +27,12 @@ module Grit
|
|
27
27
|
ruby_git.object_exists?(object_id)
|
28
28
|
end
|
29
29
|
|
30
|
+
def select_existing_objects(object_ids)
|
31
|
+
object_ids.select do |object_id|
|
32
|
+
object_exists?(object_id)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
30
36
|
class << self
|
31
37
|
attr_accessor :git_binary, :git_timeout, :git_max_size
|
32
38
|
end
|
@@ -72,7 +78,7 @@ module Grit
|
|
72
78
|
#
|
73
79
|
# Returns the String contents of the file
|
74
80
|
def fs_read(file)
|
75
|
-
File.
|
81
|
+
File.read(File.join(self.git_dir, file))
|
76
82
|
end
|
77
83
|
|
78
84
|
# Write a normal file to the filesystem.
|
@@ -229,13 +235,12 @@ module Grit
|
|
229
235
|
opt_args = transform_options(options)
|
230
236
|
|
231
237
|
if RUBY_PLATFORM.downcase =~ /mswin(?!ce)|mingw|bccwin/
|
232
|
-
ext_args = args.reject { |a| a.empty? }.map { |a| (a == '--' || a[0].chr == '|') ? a : "\"#{e(a)}\"" }
|
238
|
+
ext_args = args.reject { |a| a.empty? }.map { |a| (a == '--' || a[0].chr == '|' || Grit.no_quote) ? a : "\"#{e(a)}\"" }
|
233
239
|
call = "#{prefix}#{Git.git_binary} --git-dir=\"#{self.git_dir}\" #{cmd.to_s.gsub(/_/, '-')} #{(opt_args + ext_args).join(' ')}#{e(postfix)}"
|
234
240
|
else
|
235
|
-
ext_args = args.reject { |a| a.empty? }.map { |a| (a == '--' || a[0].chr == '|') ? a : "'#{e(a)}'" }
|
241
|
+
ext_args = args.reject { |a| a.empty? }.map { |a| (a == '--' || a[0].chr == '|' || Grit.no_quote) ? a : "'#{e(a)}'" }
|
236
242
|
call = "#{prefix}#{Git.git_binary} --git-dir='#{self.git_dir}' #{cmd.to_s.gsub(/_/, '-')} #{(opt_args + ext_args).join(' ')}#{e(postfix)}"
|
237
243
|
end
|
238
|
-
|
239
244
|
Grit.log(call) if Grit.debug
|
240
245
|
response, err = timeout ? sh(call) : wild_sh(call)
|
241
246
|
Grit.log(response) if Grit.debug
|
data/lib/grit/index.rb
CHANGED
File without changes
|
data/lib/grit/ref.rb
CHANGED
@@ -63,7 +63,9 @@ module Grit
|
|
63
63
|
def self.current(repo, options = {})
|
64
64
|
head = repo.git.fs_read('HEAD').chomp
|
65
65
|
if /ref: refs\/heads\/(.*)/.match(head)
|
66
|
-
|
66
|
+
id = repo.git.rev_parse(options, 'HEAD')
|
67
|
+
commit = Commit.create(repo, :id => id)
|
68
|
+
self.new($1, commit)
|
67
69
|
end
|
68
70
|
end
|
69
71
|
|
data/lib/grit/repo.rb
CHANGED
@@ -132,6 +132,30 @@ module Grit
|
|
132
132
|
Tag.find_all(self)
|
133
133
|
end
|
134
134
|
|
135
|
+
# Finds the most recent annotated tag name that is reachable from a commit.
|
136
|
+
#
|
137
|
+
# @repo.recent_tag_name('master')
|
138
|
+
# # => "v1.0-0-abcdef"
|
139
|
+
#
|
140
|
+
# committish - optional commit SHA, branch, or tag name.
|
141
|
+
# options - optional hash of options to pass to git.
|
142
|
+
# Default: {:always => true}
|
143
|
+
# :tags => true # use lightweight tags too.
|
144
|
+
# :abbrev => Integer # number of hex digits to form the unique
|
145
|
+
# name. Defaults to 7.
|
146
|
+
# :long => true # always output tag + commit sha
|
147
|
+
# # see `git describe` docs for more options.
|
148
|
+
#
|
149
|
+
# Returns the String tag name, or just the commit if no tag is
|
150
|
+
# found. If there have been updates since the tag was made, a
|
151
|
+
# suffix is added with the number of commits since the tag, and
|
152
|
+
# the abbreviated object name of the most recent commit.
|
153
|
+
# Returns nil if the committish value is not found.
|
154
|
+
def recent_tag_name(committish = nil, options = {})
|
155
|
+
value = git.describe({:always => true}.update(options), committish.to_s).to_s.strip
|
156
|
+
value.size.zero? ? nil : value
|
157
|
+
end
|
158
|
+
|
135
159
|
# An array of Remote objects representing the remote branches in
|
136
160
|
# this repo
|
137
161
|
#
|
@@ -251,6 +275,46 @@ module Grit
|
|
251
275
|
end
|
252
276
|
end
|
253
277
|
|
278
|
+
def objects(refs)
|
279
|
+
Grit.no_quote = true
|
280
|
+
obj = self.git.rev_list({:objects => true, :timeout => false}, refs).split("\n").map { |a| a[0, 40] }
|
281
|
+
Grit.no_quote = false
|
282
|
+
obj
|
283
|
+
end
|
284
|
+
|
285
|
+
def commit_objects(refs)
|
286
|
+
Grit.no_quote = true
|
287
|
+
obj = self.git.rev_list({:timeout => false}, refs).split("\n").map { |a| a[0, 40] }
|
288
|
+
Grit.no_quote = false
|
289
|
+
obj
|
290
|
+
end
|
291
|
+
|
292
|
+
def objects_between(ref1, ref2 = nil)
|
293
|
+
if ref2
|
294
|
+
refs = "#{ref2}..#{ref1}"
|
295
|
+
else
|
296
|
+
refs = ref1
|
297
|
+
end
|
298
|
+
self.objects(refs)
|
299
|
+
end
|
300
|
+
|
301
|
+
def diff_objects(commit_sha, parents = true)
|
302
|
+
revs = []
|
303
|
+
Grit.no_quote = true
|
304
|
+
if parents
|
305
|
+
# PARENTS:
|
306
|
+
cmd = "-r -t -m #{commit_sha}"
|
307
|
+
revs = self.git.diff_tree({:timeout => false}, cmd).strip.split("\n").map{ |a| r = a.split(' '); r[3] if r[1] != '160000' }
|
308
|
+
else
|
309
|
+
# NO PARENTS:
|
310
|
+
cmd = "-r -t #{commit_sha}"
|
311
|
+
revs = self.git.method_missing('ls-tree', {:timeout => false}, "-r -t #{commit_sha}").split("\n").map{ |a| a.split("\t").first.split(' ')[2] }
|
312
|
+
end
|
313
|
+
revs << self.commit(commit_sha).tree.id
|
314
|
+
Grit.no_quote = false
|
315
|
+
return revs.uniq.compact
|
316
|
+
end
|
317
|
+
|
254
318
|
# The Tree object for the given treeish reference
|
255
319
|
# +treeish+ is the reference (default 'master')
|
256
320
|
# +paths+ is an optional Array of directory paths to restrict the tree (deafult [])
|
@@ -287,7 +351,14 @@ module Grit
|
|
287
351
|
# +b+ is the other commit
|
288
352
|
# +paths+ is an optional list of file paths on which to restrict the diff
|
289
353
|
def diff(a, b, *paths)
|
290
|
-
self.git.diff
|
354
|
+
diff = self.git.native('diff', {}, a, b, '--', *paths)
|
355
|
+
|
356
|
+
if diff =~ /diff --git a/
|
357
|
+
diff = diff.sub(/.+?(diff --git a)/m, '\1')
|
358
|
+
else
|
359
|
+
diff = ''
|
360
|
+
end
|
361
|
+
Diff.list_from_string(self, diff)
|
291
362
|
end
|
292
363
|
|
293
364
|
# The commit diff for the given commit
|
@@ -314,6 +385,15 @@ module Grit
|
|
314
385
|
self.new(path, repo_options)
|
315
386
|
end
|
316
387
|
|
388
|
+
def self.init_bare_or_open(path, git_options = {}, repo_options = {})
|
389
|
+
git = Git.new(path)
|
390
|
+
if !git.exist?
|
391
|
+
git.fs_mkdir(path)
|
392
|
+
git.init(git_options)
|
393
|
+
end
|
394
|
+
self.new(path, repo_options)
|
395
|
+
end
|
396
|
+
|
317
397
|
# Fork a bare git repository from this repo
|
318
398
|
# +path+ is the full path of the new repo (traditionally ends with /<name>.git)
|
319
399
|
# +options+ is any additional options to the git clone command (:bare and :shared are true by default)
|
data/lib/grit/tag.rb
CHANGED
@@ -1,15 +1,68 @@
|
|
1
1
|
module Grit
|
2
2
|
|
3
3
|
class Tag < Ref
|
4
|
+
lazy_reader :message
|
5
|
+
lazy_reader :tagger
|
6
|
+
lazy_reader :tag_date
|
7
|
+
|
4
8
|
def self.find_all(repo, options = {})
|
5
9
|
refs = repo.git.refs(options, prefix)
|
6
10
|
refs.split("\n").map do |ref|
|
7
11
|
name, id = *ref.split(' ')
|
8
|
-
|
9
|
-
raise "Unknown object type." if
|
10
|
-
commit = Commit.create(repo, :id =>
|
11
|
-
|
12
|
+
sha = repo.git.commit_from_sha(id)
|
13
|
+
raise "Unknown object type." if sha == ''
|
14
|
+
commit = Commit.create(repo, :id => sha)
|
15
|
+
new(name, commit)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Parses the results from `cat-file -p`
|
20
|
+
#
|
21
|
+
# data - String tag object data. Example:
|
22
|
+
# object 7bcc0ee821cdd133d8a53e8e7173a334fef448aa
|
23
|
+
# type commit
|
24
|
+
# tag v0.7.0
|
25
|
+
# tagger USER <EMAIL> DATE
|
26
|
+
#
|
27
|
+
# v0.7.0
|
28
|
+
#
|
29
|
+
# Returns parsed Hash. Example:
|
30
|
+
# {:message => "...", :tagger => "bob", :tag_date => ...}
|
31
|
+
def self.parse_tag_data(data)
|
32
|
+
return unless data =~ /^object/
|
33
|
+
parsed = {}
|
34
|
+
lines = data.split("\n")
|
35
|
+
lines.shift # type commit
|
36
|
+
lines.shift # tag name
|
37
|
+
lines.shift
|
38
|
+
author_line = lines.shift
|
39
|
+
parsed[:tagger], parsed[:tag_date] = Commit.actor(author_line)
|
40
|
+
if !parsed[:tagger] || !parsed[:tagger].name
|
41
|
+
parsed[:tag_date] ||= Time.utc(1970)
|
42
|
+
parsed[:tagger] = Actor.from_string(author_line.sub(/^tagger /, ''))
|
43
|
+
end
|
44
|
+
lines.shift # blank line
|
45
|
+
parsed[:message] = []
|
46
|
+
while lines.first && lines.first !~ /-----BEGIN PGP SIGNATURE-----/
|
47
|
+
parsed[:message] << lines.shift
|
48
|
+
end
|
49
|
+
parsed[:message] = parsed[:message] * "\n"
|
50
|
+
parsed
|
51
|
+
end
|
52
|
+
|
53
|
+
def lazy_source
|
54
|
+
data = commit.repo.git.cat_ref({:p => true}, name)
|
55
|
+
@message = commit.short_message
|
56
|
+
@tagger = commit.author
|
57
|
+
@tag_date = commit.authored_date
|
58
|
+
return self if data.empty?
|
59
|
+
|
60
|
+
if parsed = self.class.parse_tag_data(data)
|
61
|
+
@message = parsed[:message]
|
62
|
+
@tagger = parsed[:tagger]
|
63
|
+
@tag_date = parsed[:tag_date]
|
12
64
|
end
|
65
|
+
self
|
13
66
|
end
|
14
67
|
end
|
15
68
|
|