ghi 0.9.2 → 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/ghi/authorization.rb +16 -2
- data/lib/ghi/client.rb +1 -1
- data/lib/ghi/commands/command.rb +10 -2
- data/lib/ghi/commands/comment.rb +40 -2
- data/lib/ghi/commands/edit.rb +1 -1
- data/lib/ghi/commands/label.rb +42 -7
- data/lib/ghi/commands/list.rb +7 -3
- data/lib/ghi/commands/open.rb +1 -1
- data/lib/ghi/commands/show.rb +16 -0
- data/lib/ghi/commands/version.rb +1 -1
- data/lib/ghi/formatting.rb +54 -16
- data/lib/ghi/formatting/colors.rb +62 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 542fd93fc503609bf5d4cc5a258356d35ee0313c
|
4
|
+
data.tar.gz: 03e5dc1531dd7a57fe02e36e265f54d94c799546
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f2984c9e741d600f119935ff9afb7b7a228839987d56caf40311aaaa43358ca000b5fdab2eba6cdea1f551ac0ce5b1d71e8c1cda7d2f43dea3e26b23b126cd30
|
7
|
+
data.tar.gz: 7e0e12147f1c5fc7f6a2cf6563076fa01e4e9648e0e0b9f0a0403627d95fcf405c399b3ce75400d14f489e747126617cf24ad820f56e31f373ae4348ab9999e7
|
data/lib/ghi/authorization.rb
CHANGED
@@ -18,12 +18,15 @@ module GHI
|
|
18
18
|
return false unless user && pass
|
19
19
|
code ||= nil # 2fa
|
20
20
|
args = code ? [] : [54, "✔\r"]
|
21
|
+
note = %w[ghi]
|
22
|
+
note << "(#{GHI.repo})" if local
|
23
|
+
note << "on #{Socket.gethostname}"
|
21
24
|
res = throb(*args) {
|
22
25
|
headers = {}
|
23
26
|
headers['X-GitHub-OTP'] = code if code
|
24
27
|
body = {
|
25
28
|
:scopes => %w(public_repo repo),
|
26
|
-
:note => '
|
29
|
+
:note => note.join(' '),
|
27
30
|
:note_url => 'https://github.com/stephencelis/ghi'
|
28
31
|
}
|
29
32
|
Client.new(user, pass).post(
|
@@ -47,7 +50,18 @@ module GHI
|
|
47
50
|
retry
|
48
51
|
end
|
49
52
|
|
50
|
-
|
53
|
+
if e.errors.any? { |err| err['code'] == 'already_exists' }
|
54
|
+
message = <<EOF.chomp
|
55
|
+
A ghi token already exists!
|
56
|
+
|
57
|
+
Please revoke all previously-generated ghi personal access tokens here:
|
58
|
+
|
59
|
+
https://github.com/settings/applications
|
60
|
+
EOF
|
61
|
+
else
|
62
|
+
message = e.message
|
63
|
+
end
|
64
|
+
abort "#{message}#{CURSOR[:column][0]}"
|
51
65
|
end
|
52
66
|
|
53
67
|
def username
|
data/lib/ghi/client.rb
CHANGED
data/lib/ghi/commands/command.rb
CHANGED
@@ -88,8 +88,7 @@ module GHI
|
|
88
88
|
if index = args.index { |arg| /^\d+$/ === arg }
|
89
89
|
@issue = args.delete_at index
|
90
90
|
else
|
91
|
-
|
92
|
-
warn "(Inferring issue from branch prefix: ##@issue)" if @issue
|
91
|
+
infer_issue_from_branch_prefix
|
93
92
|
end
|
94
93
|
@issue
|
95
94
|
end
|
@@ -97,6 +96,11 @@ module GHI
|
|
97
96
|
alias milestone issue
|
98
97
|
alias extract_milestone issue
|
99
98
|
|
99
|
+
def infer_issue_from_branch_prefix
|
100
|
+
@issue = `git symbolic-ref --short HEAD 2>/dev/null`[/^\d+/];
|
101
|
+
warn "(Inferring issue from branch prefix: ##@issue)" if @issue
|
102
|
+
end
|
103
|
+
|
100
104
|
def require_issue
|
101
105
|
raise MissingArgument, 'Issue required.' unless issue
|
102
106
|
end
|
@@ -109,6 +113,10 @@ module GHI
|
|
109
113
|
def any_or_none_or input
|
110
114
|
input ? input : { nil => '*', false => 'none' }[input]
|
111
115
|
end
|
116
|
+
|
117
|
+
def sort_by_creation(arr)
|
118
|
+
arr.sort_by { |el| el['created_at'] }
|
119
|
+
end
|
112
120
|
end
|
113
121
|
end
|
114
122
|
end
|
data/lib/ghi/commands/comment.rb
CHANGED
@@ -45,9 +45,11 @@ EOF
|
|
45
45
|
|
46
46
|
case action
|
47
47
|
when 'list'
|
48
|
+
get_requests(:index, :events)
|
48
49
|
res = index
|
49
50
|
page do
|
50
|
-
|
51
|
+
elements = sort_by_creation(res.body + paged_events(events, res))
|
52
|
+
puts format_comments_and_events(elements)
|
51
53
|
break unless res.next_page
|
52
54
|
res = throb { api.get res.next_page }
|
53
55
|
end
|
@@ -76,7 +78,7 @@ EOF
|
|
76
78
|
protected
|
77
79
|
|
78
80
|
def index
|
79
|
-
throb { api.get uri, :per_page => 100 }
|
81
|
+
@index ||= throb { api.get uri, :per_page => 100 }
|
80
82
|
end
|
81
83
|
|
82
84
|
def create message = 'Commented.'
|
@@ -96,8 +98,28 @@ EOF
|
|
96
98
|
puts 'Comment deleted.'
|
97
99
|
end
|
98
100
|
|
101
|
+
def events
|
102
|
+
@events ||= begin
|
103
|
+
events = []
|
104
|
+
res = api.get(event_uri, :per_page => 100)
|
105
|
+
loop do
|
106
|
+
events += res.body
|
107
|
+
break unless res.next_page
|
108
|
+
res = api.get res.next_page
|
109
|
+
end
|
110
|
+
events
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
99
114
|
private
|
100
115
|
|
116
|
+
def get_requests(*methods)
|
117
|
+
threads = methods.map do |method|
|
118
|
+
Thread.new { send(method) }
|
119
|
+
end
|
120
|
+
threads.each { |t| t.join }
|
121
|
+
end
|
122
|
+
|
101
123
|
def uri
|
102
124
|
if comment
|
103
125
|
comment['url']
|
@@ -106,6 +128,10 @@ EOF
|
|
106
128
|
end
|
107
129
|
end
|
108
130
|
|
131
|
+
def event_uri
|
132
|
+
"/repos/#{repo}/issues/#{issue}/events"
|
133
|
+
end
|
134
|
+
|
109
135
|
def require_body
|
110
136
|
assigns[:body] = args.join ' ' unless args.empty?
|
111
137
|
return if assigns[:body]
|
@@ -125,6 +151,18 @@ EOF
|
|
125
151
|
assigns[:body] = message if message
|
126
152
|
e
|
127
153
|
end
|
154
|
+
|
155
|
+
def paged_events(events, comments_res)
|
156
|
+
if comments_res.next_page
|
157
|
+
last_comment_creation = comments_res.body.last['created_at']
|
158
|
+
events_for_this_page, @events = events.partition do |event|
|
159
|
+
event['created_at'] < last_comment_creation
|
160
|
+
end
|
161
|
+
events_for_this_page
|
162
|
+
else
|
163
|
+
events
|
164
|
+
end
|
165
|
+
end
|
128
166
|
end
|
129
167
|
end
|
130
168
|
end
|
data/lib/ghi/commands/edit.rb
CHANGED
data/lib/ghi/commands/label.rb
CHANGED
@@ -15,7 +15,7 @@ module GHI
|
|
15
15
|
opts.banner = <<EOF
|
16
16
|
usage: ghi label <labelname> [-c <color>] [-r <newname>]
|
17
17
|
or: ghi label -D <labelname>
|
18
|
-
or: ghi label <issueno> [-a] [-d] [-f]
|
18
|
+
or: ghi label <issueno(s)> [-a] [-d] [-f] <label>
|
19
19
|
or: ghi label -l [<issueno>]
|
20
20
|
EOF
|
21
21
|
opts.separator ''
|
@@ -41,13 +41,13 @@ EOF
|
|
41
41
|
opts.separator ''
|
42
42
|
opts.separator 'Issue modification options'
|
43
43
|
opts.on '-a', '--add', 'add labels to issue' do
|
44
|
-
self.action =
|
44
|
+
self.action = issues_present? ? 'add' : 'create'
|
45
45
|
end
|
46
46
|
opts.on '-d', '--delete', 'remove labels from issue' do
|
47
|
-
self.action =
|
47
|
+
self.action = issues_present? ? 'remove' : 'destroy'
|
48
48
|
end
|
49
49
|
opts.on '-f', '--force', 'replace existing labels' do
|
50
|
-
self.action =
|
50
|
+
self.action = issues_present? ? 'replace' : 'update'
|
51
51
|
end
|
52
52
|
opts.separator ''
|
53
53
|
end
|
@@ -58,16 +58,16 @@ EOF
|
|
58
58
|
require_repo
|
59
59
|
options.parse! args.empty? ? %w(-l) : args
|
60
60
|
|
61
|
-
if
|
61
|
+
if issues_present?
|
62
62
|
self.action ||= 'add'
|
63
63
|
self.name = args.shift.to_s.split ','
|
64
64
|
self.name.concat args
|
65
|
+
multi_action(action)
|
65
66
|
else
|
66
67
|
self.action ||= 'create'
|
67
68
|
self.name ||= args.shift
|
69
|
+
send action
|
68
70
|
end
|
69
|
-
|
70
|
-
send action
|
71
71
|
end
|
72
72
|
|
73
73
|
protected
|
@@ -156,6 +156,41 @@ EOF
|
|
156
156
|
def base_uri
|
157
157
|
"/repos/#{repo}/#{issue ? "issues/#{issue}/labels" : 'labels'}"
|
158
158
|
end
|
159
|
+
|
160
|
+
# This method is usually inherited from Command and extracts a single issue
|
161
|
+
# from args - we override it to handle multiple issues at once.
|
162
|
+
def extract_issue
|
163
|
+
@issues = []
|
164
|
+
args.delete_if do |arg|
|
165
|
+
arg.match(/^\d+$/) ? @issues << arg : break
|
166
|
+
end
|
167
|
+
infer_issue_from_branch_prefix unless @issues.any?
|
168
|
+
end
|
169
|
+
|
170
|
+
def issues_present?
|
171
|
+
@issues.any? || @issue
|
172
|
+
end
|
173
|
+
|
174
|
+
def multi_action(action)
|
175
|
+
if @issues.any?
|
176
|
+
override_issue_reader
|
177
|
+
threads = @issues.map do |issue|
|
178
|
+
Thread.new do
|
179
|
+
Thread.current[:issue] = issue
|
180
|
+
send action
|
181
|
+
end
|
182
|
+
end
|
183
|
+
threads.each(&:join)
|
184
|
+
else
|
185
|
+
send action
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def override_issue_reader
|
190
|
+
def issue
|
191
|
+
Thread.current[:issue]
|
192
|
+
end
|
193
|
+
end
|
159
194
|
end
|
160
195
|
end
|
161
196
|
end
|
data/lib/ghi/commands/list.rb
CHANGED
@@ -7,6 +7,7 @@ module GHI
|
|
7
7
|
attr_accessor :reverse
|
8
8
|
attr_accessor :quiet
|
9
9
|
attr_accessor :exclude_pull_requests
|
10
|
+
attr_accessor :pull_requests_only
|
10
11
|
|
11
12
|
def options
|
12
13
|
OptionParser.new do |opts|
|
@@ -42,7 +43,8 @@ module GHI
|
|
42
43
|
opts.on '--reverse', 'reverse (ascending) sort order' do
|
43
44
|
self.reverse = !reverse
|
44
45
|
end
|
45
|
-
opts.on('-p', '--
|
46
|
+
opts.on('-p', '--pulls','list only pull requests') { self.pull_requests_only = true }
|
47
|
+
opts.on('-P', '--no-pulls','exclude pull requests') { self.exclude_pull_requests = true }
|
46
48
|
opts.on(
|
47
49
|
'--since <date>', 'issues more recent than',
|
48
50
|
"e.g., '2011-04-30'"
|
@@ -136,8 +138,10 @@ module GHI
|
|
136
138
|
print "\r#{CURSOR[:up][1]}" if header && paginate?
|
137
139
|
page header do
|
138
140
|
issues = res.body
|
139
|
-
|
140
|
-
|
141
|
+
|
142
|
+
if exclude_pull_requests || pull_requests_only
|
143
|
+
prs, issues = issues.partition { |i| i['pull_request'].values.any? }
|
144
|
+
issues = prs if pull_requests_only
|
141
145
|
end
|
142
146
|
if assigns[:exclude_labels]
|
143
147
|
issues = issues.reject do |i|
|
data/lib/ghi/commands/open.rb
CHANGED
data/lib/ghi/commands/show.rb
CHANGED
@@ -32,6 +32,7 @@ module GHI
|
|
32
32
|
end
|
33
33
|
else
|
34
34
|
i = throb { api.get "/repos/#{repo}/issues/#{issue}" }.body
|
35
|
+
determine_merge_status(i) if pull_request?(i)
|
35
36
|
page do
|
36
37
|
puts format_issue(i)
|
37
38
|
n = i['comments']
|
@@ -44,6 +45,21 @@ module GHI
|
|
44
45
|
end
|
45
46
|
end
|
46
47
|
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def pull_request?(issue)
|
52
|
+
issue['pull_request']['html_url']
|
53
|
+
end
|
54
|
+
|
55
|
+
def determine_merge_status(pr)
|
56
|
+
pr['merged'] = true if pr['state'] == 'closed' && merged?
|
57
|
+
end
|
58
|
+
|
59
|
+
def merged?
|
60
|
+
# API returns with a Not Found error when the PR is not merged
|
61
|
+
api.get "/repos/#{repo}/pulls/#{issue}/merge" rescue false
|
62
|
+
end
|
47
63
|
end
|
48
64
|
end
|
49
65
|
end
|
data/lib/ghi/commands/version.rb
CHANGED
data/lib/ghi/formatting.rb
CHANGED
@@ -33,7 +33,7 @@ module GHI
|
|
33
33
|
|
34
34
|
def puts *strings
|
35
35
|
strings = strings.flatten.map { |s|
|
36
|
-
s.gsub(/(^| )
|
36
|
+
s.gsub(/(^| *)@(\w+)/) {
|
37
37
|
if $2 == Authorization.username
|
38
38
|
bright { fg(:yellow) { "#$1@#$2" } }
|
39
39
|
else
|
@@ -117,7 +117,7 @@ module GHI
|
|
117
117
|
end
|
118
118
|
|
119
119
|
def format_issues_header
|
120
|
-
state = assigns[:state]
|
120
|
+
state = assigns[:state] ||= 'open'
|
121
121
|
header = "# #{repo || 'Global,'} #{state} issues"
|
122
122
|
if repo
|
123
123
|
if milestone = assigns[:milestone]
|
@@ -210,6 +210,7 @@ module GHI
|
|
210
210
|
*i.values_at('number', 'title')], 0, width } } %>
|
211
211
|
@<%= i['user']['login'] %> opened this <%= p ? 'pull request' : 'issue' %> \
|
212
212
|
<%= format_date DateTime.parse(i['created_at']) %>. \
|
213
|
+
<% if i['merged'] %><%= format_state 'merged', format_tag('merged'), :bg %><% end %> \
|
213
214
|
<%= format_state i['state'], format_tag(i['state']), :bg %> \
|
214
215
|
<% unless i['comments'] == 0 %>\
|
215
216
|
<%= fg('aaaaaa'){
|
@@ -233,9 +234,15 @@ Milestone #<%= i['milestone']['number'] %>: <%= i['milestone']['title'] %>\
|
|
233
234
|
EOF
|
234
235
|
end
|
235
236
|
|
236
|
-
def
|
237
|
-
return 'None.' if
|
238
|
-
|
237
|
+
def format_comments_and_events elements
|
238
|
+
return 'None.' if elements.empty?
|
239
|
+
elements.map do |element|
|
240
|
+
if event = element['event']
|
241
|
+
format_event(element) unless unimportant_event?(event)
|
242
|
+
else
|
243
|
+
format_comment(element)
|
244
|
+
end
|
245
|
+
end.compact
|
239
246
|
end
|
240
247
|
|
241
248
|
def format_comment c, width = columns
|
@@ -245,6 +252,16 @@ EOF
|
|
245
252
|
#{indent c['body'], 4, width}
|
246
253
|
|
247
254
|
|
255
|
+
EOF
|
256
|
+
end
|
257
|
+
|
258
|
+
def format_event e, width = columns
|
259
|
+
reference = e['commit_id']
|
260
|
+
<<EOF
|
261
|
+
#{bright { '⁕' }} #{format_event_type(e['event'])} by @#{e['actor']['login']}\
|
262
|
+
#{" through #{underline { reference[0..6] }}" if reference} \
|
263
|
+
#{format_date DateTime.parse(e['created_at'])}
|
264
|
+
|
248
265
|
EOF
|
249
266
|
end
|
250
267
|
|
@@ -306,7 +323,12 @@ EOF
|
|
306
323
|
end
|
307
324
|
|
308
325
|
def format_state state, string = state, layer = :fg
|
309
|
-
|
326
|
+
color_codes = {
|
327
|
+
'closed' => 'ff0000',
|
328
|
+
'open' => '2cc200',
|
329
|
+
'merged' => '511c7d',
|
330
|
+
}
|
331
|
+
send(layer, color_codes[state]) { string }
|
310
332
|
end
|
311
333
|
|
312
334
|
def format_labels labels
|
@@ -318,6 +340,17 @@ EOF
|
|
318
340
|
(colorize? ? ' %s ' : '[%s]') % tag
|
319
341
|
end
|
320
342
|
|
343
|
+
def format_event_type(event)
|
344
|
+
color_codes = {
|
345
|
+
'reopened' => '2cc200',
|
346
|
+
'closed' => 'ff0000',
|
347
|
+
'merged' => '9677b1',
|
348
|
+
'assigned' => 'e1811d',
|
349
|
+
'referenced' => 'aaaaaa'
|
350
|
+
}
|
351
|
+
fg(color_codes[event]) { event }
|
352
|
+
end
|
353
|
+
|
321
354
|
#--
|
322
355
|
# Helpers:
|
323
356
|
#++
|
@@ -416,16 +449,15 @@ EOF
|
|
416
449
|
%r{\b(<)?(https?://\S+|[^@\s]+@[^@\s]+)(>)?\b},
|
417
450
|
fg(c){'\1' + underline{'\2'} + '\3'}
|
418
451
|
)
|
419
|
-
|
420
|
-
#
|
421
|
-
|
422
|
-
|
423
|
-
#
|
424
|
-
#
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
# }
|
452
|
+
|
453
|
+
# Inline code
|
454
|
+
string.gsub!(/`([^`].+?)`(?=[^`])/, inverse { ' \1 ' })
|
455
|
+
|
456
|
+
# Code blocks
|
457
|
+
string.gsub!(/(?<indent>^\ {#{indent}})(```)\s*(?<lang>\w*$)(\n)(?<code>.+?)(\n)(^\ {#{indent}}```$)/m) do |m|
|
458
|
+
highlight(Regexp.last_match)
|
459
|
+
end
|
460
|
+
|
429
461
|
string
|
430
462
|
end
|
431
463
|
|
@@ -471,5 +503,11 @@ EOF
|
|
471
503
|
puts "\r#{CURSOR[:column][position]}#{redraw}#{CURSOR[:show]}"
|
472
504
|
end
|
473
505
|
end
|
506
|
+
|
507
|
+
private
|
508
|
+
|
509
|
+
def unimportant_event?(event)
|
510
|
+
%w{ subscribed unsubscribed mentioned }.include?(event)
|
511
|
+
end
|
474
512
|
end
|
475
513
|
end
|
@@ -37,6 +37,11 @@ module GHI
|
|
37
37
|
escape :inverse, &block
|
38
38
|
end
|
39
39
|
|
40
|
+
def highlight(code_block)
|
41
|
+
return code_block unless colorize?
|
42
|
+
highlighter.highlight(code_block)
|
43
|
+
end
|
44
|
+
|
40
45
|
def no_color
|
41
46
|
old_colorize, Colors.colorize = colorize?, false
|
42
47
|
yield
|
@@ -228,7 +233,11 @@ module GHI
|
|
228
233
|
end
|
229
234
|
|
230
235
|
def escape_256 color
|
231
|
-
"8;5;#{to_256(*to_rgb(color))}" if
|
236
|
+
"8;5;#{to_256(*to_rgb(color))}" if supports_256_colors?
|
237
|
+
end
|
238
|
+
|
239
|
+
def supports_256_colors?
|
240
|
+
`tput colors` =~ /256/
|
232
241
|
end
|
233
242
|
|
234
243
|
def to_256 r, g, b
|
@@ -294,6 +303,58 @@ module GHI
|
|
294
303
|
return m1 + (m2 - m1) * (2.0/3 - h) * 6 if h * 3 < 2
|
295
304
|
return m1
|
296
305
|
end
|
306
|
+
|
307
|
+
def highlighter
|
308
|
+
@highlighter ||= begin
|
309
|
+
raise unless supports_256_colors?
|
310
|
+
require 'pygments'
|
311
|
+
Pygmentizer.new
|
312
|
+
rescue
|
313
|
+
FakePygmentizer.new
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
class FakePygmentizer
|
318
|
+
def highlight(code_block)
|
319
|
+
code_block
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
class Pygmentizer
|
324
|
+
def initialize
|
325
|
+
@style = GHI.config('ghi.highlight.style') || 'monokai'
|
326
|
+
end
|
327
|
+
|
328
|
+
def highlight(code_block)
|
329
|
+
begin
|
330
|
+
indent = code_block['indent']
|
331
|
+
lang = code_block['lang']
|
332
|
+
code = code_block['code']
|
333
|
+
|
334
|
+
output = pygmentize(lang, code)
|
335
|
+
with_indentation(output, indent)
|
336
|
+
rescue
|
337
|
+
code_block
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
private
|
342
|
+
|
343
|
+
def pygmentize(lang, code)
|
344
|
+
Pygments.highlight(unescape(code), :formatter => '256', :lexer => lang,
|
345
|
+
:options => { :style => @style })
|
346
|
+
end
|
347
|
+
|
348
|
+
def unescape(str)
|
349
|
+
str.gsub(/\e\[[^m]*m/, '')
|
350
|
+
end
|
351
|
+
|
352
|
+
def with_indentation(string, indent)
|
353
|
+
string.each_line.map do |line|
|
354
|
+
"#{indent}#{line}"
|
355
|
+
end.join
|
356
|
+
end
|
357
|
+
end
|
297
358
|
end
|
298
359
|
end
|
299
360
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ghi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stephen Celis
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-03-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -88,7 +88,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
88
88
|
version: '0'
|
89
89
|
requirements: []
|
90
90
|
rubyforge_project:
|
91
|
-
rubygems_version: 2.2.
|
91
|
+
rubygems_version: 2.2.2
|
92
92
|
signing_key:
|
93
93
|
specification_version: 4
|
94
94
|
summary: GitHub Issues command line interface
|