commit_tracker 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ .DS_Store
2
+ .yardoc
3
+ doc
4
+ coverage
5
+ tmp
6
+ *.rbc
7
+ *~
8
+ *.gem
9
+ .bundle
10
+ Gemfile.lock
11
+ commit_tracker.tmproj
12
+
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source :rubygems
2
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,8 @@
1
+ Copyright (c) 2011 Sergey V. Kravchuk <alfss.obsd@gmail.com>. All rights reserved.
2
+
3
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
4
+
5
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
6
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
7
+
8
+ THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,56 @@
1
+ CommitTracker
2
+ =============
3
+
4
+ Simple create task/message to bug tracker.
5
+ Now support only TrackStudio
6
+
7
+ TODO:
8
+ Redmine
9
+ Jira
10
+
11
+
12
+ Example
13
+ =======
14
+
15
+ ``` ruby
16
+ require "commit_tracker"
17
+ #Message authentication
18
+ commit = CommitTracker::Message.new(:type => 'trackstudio',
19
+ :url => 'http://ts.domain.com/TrackStudio/services/',
20
+ :login => 'user',
21
+ :password => 'qwerty')
22
+
23
+ #Create Message
24
+ messageId = commit.create(:user => "user_1",
25
+ :hrs => 3*3600,
26
+ :comment => "test msg!!!!",
27
+ :task_number => 8845,
28
+ :msg_status => "Report time As",
29
+ :deadline_sec => Time.now.to_i)
30
+
31
+ #Delete Message
32
+ commit.delete(:messageId => messageId)
33
+
34
+ #Task authentication
35
+ commit = CommitTracker::Task.new(:type => 'trackstudio',
36
+ :url => 'http://ts.domain.com/TrackStudio/services/',
37
+ :login => 'user',
38
+ :password => 'qwerty')
39
+
40
+ #Create Task
41
+ taskId = commit.create(:parent_number => 4885,
42
+ :name => 'test_task',
43
+ :user => 'user_1',
44
+ :description => "test comment",
45
+ :category => 'Task',
46
+ :budget_sec => 3600)
47
+
48
+
49
+ #Delete Task
50
+ commit.delete(:task_number => 16069 )
51
+ commit.delete(:task_number => taskId )
52
+
53
+
54
+ ```
55
+
56
+ Copyright (c) 2011 Sergey V. Kravchuk <alfss.obsd@gmail.com>, released under the BSD license
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new
5
+
6
+ task :default => :spec
7
+ task :test => :spec
@@ -0,0 +1,26 @@
1
+ lib = File.expand_path("../lib", __FILE__)
2
+ $:.unshift lib unless $:.include? lib
3
+
4
+ require "commit_tracker/version"
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "commit_tracker"
8
+ s.version = CommitTracker::Version
9
+ s.authors = "Sergey V. Kravchuk"
10
+ s.email = "alfss.obsd@gmail.com"
11
+ s.homepage = "https://github.com/alfss/commit_tracker"
12
+ s.summary = "client tracking system"
13
+ s.description = "client tracking system"
14
+
15
+ s.rubyforge_project = s.name
16
+
17
+ s.add_dependency "builder", ">= 2.1.2"
18
+ s.add_dependency "savon", "~> 0.9.7"
19
+ s.add_dependency "nokogiri", ">= 1.4.0"
20
+
21
+ s.add_development_dependency "rake", "~> 0.8.7"
22
+ s.add_development_dependency "rspec", "~> 2.5.0"
23
+
24
+ s.files = `git ls-files`.split("\n")
25
+ s.require_path = "lib"
26
+ end
@@ -0,0 +1,6 @@
1
+ module CommitTracker
2
+
3
+ class ErrorCommitTask < RuntimeError
4
+ end
5
+
6
+ end
@@ -0,0 +1,33 @@
1
+ require "commit_tracker/error"
2
+ require "commit_tracker/trackstudio"
3
+
4
+ module CommitTracker
5
+ class Message
6
+ def initialize(options={})
7
+ @type = options[:type] || 'trackstudio'
8
+ @commit = nil
9
+ case @type
10
+ when 'trackstudio'
11
+ @commit = TrackStudio.new(options)
12
+ end
13
+ end
14
+
15
+ def create(options={})
16
+ case @type
17
+ when 'trackstudio'
18
+ return @commit.create_message(options)
19
+ else
20
+ raise ErrorCommitTask, "error name tracker"
21
+ end
22
+ end
23
+
24
+ def delete(options={})
25
+ case @type
26
+ when 'trackstudio'
27
+ return @commit.delete_message(options)
28
+ else
29
+ raise ErrorCommitTask, "error name tracker"
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,33 @@
1
+ require "commit_tracker/error"
2
+ require "commit_tracker/trackstudio"
3
+
4
+ module CommitTracker
5
+ class Task
6
+ def initialize(options={})
7
+ @type = options[:type] || 'trackstudio'
8
+ @commit = nil
9
+ case @type
10
+ when 'trackstudio'
11
+ @commit = TrackStudio.new(options)
12
+ end
13
+ end
14
+
15
+ def create(options={})
16
+ case @type
17
+ when 'trackstudio'
18
+ return @commit.create_task(options)
19
+ else
20
+ raise ErrorCommitTask, "error name tracker"
21
+ end
22
+ end
23
+
24
+ def delete(options={})
25
+ case @type
26
+ when 'trackstudio'
27
+ return @commit.delete_task(options)
28
+ else
29
+ raise ErrorCommitTask, "error name tracker"
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,371 @@
1
+ require "savon"
2
+ require "commit_tracker/error"
3
+
4
+ module CommitTracker
5
+ class TrackStudio
6
+
7
+ def initialize(options={})
8
+ url = options[:url] || 'http://localhost/TrackStudio/services/'
9
+ @login = options[:login] || 'login'
10
+ @password = options[:password] || 'password'
11
+
12
+ Savon.configure do |config|
13
+ config.soap_version = 2
14
+ end
15
+
16
+ @User = Savon::Client.new do
17
+ wsdl.document = url + "User?wsdl"
18
+ end
19
+
20
+ @Task = Savon::Client.new do
21
+ wsdl.document = url + "Task?wsdl"
22
+ end
23
+
24
+ @Message = Savon::Client.new do
25
+ wsdl.document = url + "Message?wsdl"
26
+ end
27
+
28
+ @Step = Savon::Client.new do
29
+ wsdl.document = url + "Step?wsdl"
30
+ end
31
+
32
+ @Acl = Savon::Client.new do
33
+ wsdl.document = url + "Acl?wsdl"
34
+ end
35
+
36
+ @Bookmark = Savon::Client.new do
37
+ wsdl.document = url + "Bookmark?wsdl"
38
+ end
39
+
40
+ @Category = Savon::Client.new do
41
+ wsdl.document = url + "Category?wsdl"
42
+ end
43
+
44
+ @Constants = Savon::Client.new do
45
+ wsdl.document = url + "Constants?wsdl"
46
+ end
47
+
48
+ @Export = Savon::Client.new do
49
+ wsdl.document = url + "Export?wsdl"
50
+ end
51
+
52
+ @Filter = Savon::Client.new do
53
+ wsdl.document = url + "Filter?wsdl"
54
+ end
55
+
56
+ @Find = Savon::Client.new do
57
+ wsdl.document = url + "Find?wsdl"
58
+ end
59
+
60
+ @Index = Savon::Client.new do
61
+ wsdl.document = url + "Index?wsdl"
62
+ end
63
+
64
+ @MailImport = Savon::Client.new do
65
+ wsdl.document = url + "MailImport?wsdl"
66
+ end
67
+
68
+ @Prstatus = Savon::Client.new do
69
+ wsdl.document = url + "Prstatus?wsdl"
70
+ end
71
+
72
+ @Registration = Savon::Client.new do
73
+ wsdl.document = url + "Registration?wsdl"
74
+ end
75
+
76
+ @Registration = Savon::Client.new do
77
+ wsdl.document = url + "Registration?wsdl"
78
+ end
79
+
80
+ @Report = Savon::Client.new do
81
+ wsdl.document = url + "Report?wsdl"
82
+ end
83
+
84
+ @SCM = Savon::Client.new do
85
+ wsdl.document = url + "SCM?wsdl"
86
+ end
87
+
88
+ @Template = Savon::Client.new do
89
+ wsdl.document = url + "Template?wsdl"
90
+ end
91
+
92
+ @Udf = Savon::Client.new do
93
+ wsdl.document = url + "Udf?wsdl"
94
+ end
95
+
96
+ @Workflow = Savon::Client.new do
97
+ wsdl.document = url + "Workflow?wsdl"
98
+ end
99
+
100
+ @sessionId = nil
101
+ begin
102
+ response = @User.request :soap,
103
+ :authenticate,
104
+ :body => { :login => @login,
105
+ :password => @password }
106
+
107
+ @sessionId = response.to_hash[:authenticate_response][:return]
108
+ rescue Savon::SOAP::Fault => e
109
+ raise ErrorCommitTask, e.to_hash[:fault][:reason][:text]
110
+ end
111
+ end
112
+
113
+ def get_task_id(task_number)
114
+ raise ErrorCommitTask, "task number is nil" if task_number.nil?
115
+ begin
116
+ response = @Task.request :soap,
117
+ :findTaskIdByQuickGo,
118
+ :body => { :sessionId => @sessionId.to_s,
119
+ :quickGo => task_number }
120
+
121
+ taskId = response.to_hash[:find_task_id_by_quick_go_response][:return]
122
+ return taskId
123
+ rescue Savon::SOAP::Fault => e
124
+ raise ErrorCommitTask, e.to_hash[:fault][:reason][:text]
125
+ end
126
+ end
127
+
128
+ def get_mstatus_id(taskId, msg_status)
129
+ raise ErrorCommitTask, "msg_status is nil" if msg_status.nil?
130
+ begin
131
+ response = @Step.request :soap,
132
+ :getAvailableMstatusList,
133
+ :body => { :sessionId => @sessionId.to_s,
134
+ :taskId => taskId }
135
+
136
+ value = response.to_hash[:get_available_mstatus_list_response][:return]
137
+
138
+ if !value.nil?
139
+ value = [value] if !value.kind_of?(Array)
140
+
141
+ value.each do |item|
142
+ return item[:id] if item[:name] == msg_status
143
+ end
144
+ end
145
+
146
+ rescue Savon::SOAP::Fault => e
147
+ raise ErrorCommitTask, e.to_hash[:fault][:reason][:text]
148
+ end
149
+ return nil
150
+ end
151
+
152
+ def get_user_id(user)
153
+ begin
154
+ find_user = user || @login
155
+ response = @User.request :soap,
156
+ :findUserIdByQuickGo,
157
+ :body => { :sessionId => @sessionId.to_s,
158
+ :quickGo => find_user }
159
+
160
+ return response.to_hash[:find_user_id_by_quick_go_response][:return]
161
+ rescue Savon::SOAP::Fault => e
162
+ raise ErrorCommitTask, e.to_hash[:fault][:reason][:text]
163
+ end
164
+ end
165
+
166
+ def get_workflow_for_task(taskId)
167
+ begin
168
+ response = @Workflow.request :soap,
169
+ :getAvailableWorkflowList,
170
+ :body => { :sessionId => @sessionId.to_s,
171
+ :taskId => taskId }
172
+
173
+ return response.to_hash[:get_available_workflow_list_response][:return]
174
+ rescue Savon::SOAP::Fault => e
175
+ raise ErrorCommitTask, e.to_hash[:fault][:reason][:text]
176
+ end
177
+ end
178
+
179
+ def get_priority_for_wokflow(workflow_id)
180
+ response = @Workflow.request :soap,
181
+ :getPriorityList,
182
+ :body => { :sessionId => @sessionId.to_s,
183
+ :workflowId => workflow_id }
184
+
185
+ value = response.to_hash[:get_priority_list_response][:return]
186
+ return value
187
+ end
188
+
189
+ def get_priority_id(taskId, priority)
190
+ begin
191
+ workflow_list = get_workflow_for_task(taskId)
192
+
193
+ workflow_list = [workflow_list] if !workflow_list.kind_of?(Array)
194
+
195
+ workflow_list.each do |workflow|
196
+ value = get_priority_for_wokflow(workflow[:id])
197
+ next if value.nil?
198
+
199
+ value = [value] if !value.kind_of?(Array)
200
+
201
+ value.each do |item|
202
+ return item[:id] if item[:name] == priority
203
+ end
204
+ end
205
+
206
+ rescue Savon::SOAP::Fault => e
207
+ raise ErrorCommitTask, e.to_hash[:fault][:reason][:text]
208
+ end
209
+ return nil
210
+ end
211
+
212
+ def get_resolution_id(mstatusId, resolution)
213
+ begin
214
+ response = @Workflow.request :soap,
215
+ :getResolutionList,
216
+ :body => { :sessionId => @sessionId.to_s,
217
+ :mstatusId => mstatusId }
218
+
219
+ value = response.to_hash[:get_resolution_list_response][:return]
220
+
221
+ if !value.nil?
222
+ value = [value] if !value.kind_of?(Array)
223
+
224
+ value.each do |item|
225
+ return item[:id] if item[:name] == resolution
226
+ end
227
+ end
228
+
229
+ rescue Savon::SOAP::Fault => e
230
+ raise ErrorCommitTask, e.to_hash[:fault][:reason][:text]
231
+ end
232
+ return nil
233
+ end
234
+
235
+ def get_category_list_for_task(taskId)
236
+ begin
237
+ response = @Category.request :soap,
238
+ :getCreatableCategoryList,
239
+ :body => { :sessionId => @sessionId.to_s,
240
+ :taskId => taskId }
241
+
242
+ value = response.to_hash[:get_creatable_category_list_response][:return]
243
+
244
+ value = [value] if !value.kind_of?(Array) and !value.nil?
245
+ return value
246
+
247
+ rescue Savon::SOAP::Fault => e
248
+ raise ErrorCommitTask, e.to_hash[:fault][:reason][:text]
249
+ end
250
+ end
251
+
252
+ def get_category_for_task(taskId, category)
253
+ begin
254
+ categories_list = get_category_list_for_task(taskId)
255
+
256
+ return nil if categories_list.nil?
257
+
258
+ categories_list.each do |item|
259
+ return item[:id] if item[:name] == category
260
+ end
261
+
262
+ rescue Savon::SOAP::Fault => e
263
+ raise ErrorCommitTask, e.to_hash[:fault][:reason][:text]
264
+ end
265
+ end
266
+
267
+ def delete_task(options={})
268
+ begin
269
+
270
+ taskId = nil
271
+ if !options[:task_number].nil? and options[:task_number].integer?
272
+ taskId = get_task_id(options[:task_number])
273
+ else
274
+ taskId = options[:task_number]
275
+ end
276
+
277
+ @Task.request :soap,
278
+ :deleteTask,
279
+ :body => { :sessionId => @sessionId.to_s,
280
+ :taskId => taskId }
281
+
282
+ rescue Savon::SOAP::Fault => e
283
+ raise ErrorCommitTask, e.to_hash[:fault][:reason][:text]
284
+ end
285
+ end
286
+
287
+ def delete_message(options={})
288
+ begin
289
+ @Message.request :soap,
290
+ :deleteMessage,
291
+ :body => { :sessionId => @sessionId.to_s,
292
+ :messageId => options[:messageId] }
293
+ rescue Savon::SOAP::Fault => e
294
+ raise ErrorCommitTask, e.to_hash[:fault][:reason][:text]
295
+ end
296
+ end
297
+
298
+ def create_task(options={})
299
+ begin
300
+ handlerUserId = get_user_id(options[:user])
301
+ parentId = get_task_id(options[:parent_number])
302
+ priorityId = get_priority_id(parentId, options[:priority]) if !options[:priority].nil?
303
+ categoryId = get_category_for_task(parentId, options[:category])
304
+
305
+ options[:deadline_sec] *= 1000 if !options[:deadline_sec].nil?
306
+
307
+ task_number = @Task.request :soap,
308
+ :createTask,
309
+ :body => { :sessionId => @sessionId.to_s,
310
+ :categoryId => categoryId,
311
+ :shortname => options[:shortname],
312
+ :name => options[:name],
313
+ :description => options[:description],
314
+ :budget => options[:budget_sec],
315
+ :deadline => options[:deadline_sec],
316
+ :priorityId => priorityId,
317
+ :parentId => parentId,
318
+ :handlerUserId => handlerUserId,
319
+ :handlerGroupId => nil,
320
+ :udfNames => options[:udf_names],
321
+ :udfValues => options[:udf_values] }
322
+
323
+ rescue Savon::SOAP::Fault => e
324
+ raise ErrorCommitTask, e.to_hash[:fault][:reason][:text]
325
+ end
326
+ end
327
+
328
+ def create_message(options={})
329
+ begin
330
+ priorityId = nil
331
+ resolutionId = nil
332
+
333
+ options[:is_notify] = false if options[:is_notify].nil?
334
+ options[:comment] = "" if options[:comment].nil?
335
+ options[:deadline_sec] *= 1000 if !options[:deadline_sec].nil?
336
+
337
+ taskId = get_task_id(options[:task_number])
338
+ mstatusId = get_mstatus_id(taskId, options[:msg_status])
339
+ handlerUserId = get_user_id(options[:user])
340
+
341
+ priorityId = get_priority_id(taskId, options[:priority]) if !options[:priority].nil?
342
+ resolutionId = get_resolution_id(mstatusId, options[:resolution]) if !options[:resolution].nil?
343
+
344
+ message_number = @Message.request :soap,
345
+ :createMessage,
346
+ :body => { :sessionId => @sessionId.to_s,
347
+ :taskId => taskId,
348
+ :mstatusId => mstatusId,
349
+ :text => options[:comment],
350
+ :hrs => options[:hrs],
351
+ :handlerUserId => handlerUserId,
352
+ :handlerGroupId => nil,
353
+ :resolutionId => resolutionId,
354
+ :priorityId => priorityId,
355
+ :deadlineLong => options[:deadline_sec],
356
+ :budget => options[:budget_sec],
357
+ :sendMail => options[:is_notify] }
358
+
359
+ rescue Savon::SOAP::Fault => e
360
+ raise ErrorCommitTask, e.to_hash[:fault][:reason][:text]
361
+ end
362
+
363
+ #if message_number == nil than retrun 0
364
+ if message_number.to_hash[:create_message_response][:return].nil?
365
+ return 0
366
+ else
367
+ return message_number.to_hash[:create_message_response][:return]
368
+ end
369
+ end
370
+ end
371
+ end
@@ -0,0 +1,5 @@
1
+ module CommitTracker
2
+
3
+ Version = "0.0.1"
4
+
5
+ end
@@ -0,0 +1,4 @@
1
+ require "commit_tracker/task"
2
+ require "commit_tracker/message"
3
+ module CommitTracker
4
+ end
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: commit_tracker
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Sergey V. Kravchuk
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-12-04 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: builder
16
+ requirement: &70252471296980 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 2.1.2
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70252471296980
25
+ - !ruby/object:Gem::Dependency
26
+ name: savon
27
+ requirement: &70252471294800 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 0.9.7
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70252471294800
36
+ - !ruby/object:Gem::Dependency
37
+ name: nokogiri
38
+ requirement: &70252471294020 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: 1.4.0
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70252471294020
47
+ - !ruby/object:Gem::Dependency
48
+ name: rake
49
+ requirement: &70252471292580 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 0.8.7
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70252471292580
58
+ - !ruby/object:Gem::Dependency
59
+ name: rspec
60
+ requirement: &70252471291840 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ version: 2.5.0
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70252471291840
69
+ description: client tracking system
70
+ email: alfss.obsd@gmail.com
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - .gitignore
76
+ - .rspec
77
+ - Gemfile
78
+ - LICENSE
79
+ - README.md
80
+ - Rakefile
81
+ - commit_tracker.gemspec
82
+ - lib/commit_tracker.rb
83
+ - lib/commit_tracker/error.rb
84
+ - lib/commit_tracker/message.rb
85
+ - lib/commit_tracker/task.rb
86
+ - lib/commit_tracker/trackstudio.rb
87
+ - lib/commit_tracker/version.rb
88
+ homepage: https://github.com/alfss/commit_tracker
89
+ licenses: []
90
+ post_install_message:
91
+ rdoc_options: []
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ! '>='
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ required_rubygems_version: !ruby/object:Gem::Requirement
101
+ none: false
102
+ requirements:
103
+ - - ! '>='
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ requirements: []
107
+ rubyforge_project: commit_tracker
108
+ rubygems_version: 1.8.10
109
+ signing_key:
110
+ specification_version: 3
111
+ summary: client tracking system
112
+ test_files: []