stephencelis-ghi 0.0.1 → 0.0.2
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/History.rdoc +8 -0
- data/lib/ghi.rb +1 -1
- data/lib/ghi/api.rb +35 -23
- data/lib/ghi/cli.rb +70 -47
- metadata +2 -2
data/History.rdoc
CHANGED
data/lib/ghi.rb
CHANGED
data/lib/ghi/api.rb
CHANGED
@@ -17,54 +17,66 @@ class GHI::API
|
|
17
17
|
@user, @repo = user, repo
|
18
18
|
end
|
19
19
|
|
20
|
+
def search(term, state = :open)
|
21
|
+
get(:search, state, term)["issues"].map { |attrs| GHI::Issue.new(attrs) }
|
22
|
+
end
|
23
|
+
|
20
24
|
def list(state = :open)
|
21
|
-
|
22
|
-
raise ResponseError, res if res["issues"].nil?
|
23
|
-
res["issues"].map { |attrs| GHI::Issue.new(attrs) }
|
25
|
+
get(:list, state)["issues"].map { |attrs| GHI::Issue.new(attrs) }
|
24
26
|
end
|
25
27
|
|
26
28
|
def show(number)
|
27
|
-
|
28
|
-
raise ResponseError, res if res["issue"].nil?
|
29
|
-
GHI::Issue.new res["issue"]
|
29
|
+
GHI::Issue.new get(:show, number)["issue"]
|
30
30
|
end
|
31
31
|
|
32
32
|
def open(title, body)
|
33
|
-
|
34
|
-
raise ResponseError, res if res["issue"].nil?
|
35
|
-
GHI::Issue.new res["issue"]
|
33
|
+
GHI::Issue.new post(:open, :title => title, :body => body)["issue"]
|
36
34
|
end
|
37
35
|
|
38
36
|
def edit(number, title, body)
|
39
|
-
res = post
|
40
|
-
raise ResponseError, res if res["issue"].nil?
|
37
|
+
res = post :edit, number, :title => title, :body => body
|
41
38
|
GHI::Issue.new res["issue"]
|
42
39
|
end
|
43
40
|
|
44
41
|
def close(number)
|
45
|
-
|
46
|
-
raise ResponseError, res if res["issue"].nil?
|
47
|
-
GHI::Issue.new res["issue"]
|
42
|
+
GHI::Issue.new post(:close, number)["issue"]
|
48
43
|
end
|
49
44
|
|
50
45
|
def reopen(number)
|
51
|
-
|
52
|
-
|
53
|
-
|
46
|
+
GHI::Issue.new post(:reopen, number)
|
47
|
+
end
|
48
|
+
|
49
|
+
def add_label(label, number)
|
50
|
+
post "label/add", label, number
|
51
|
+
p res
|
52
|
+
end
|
53
|
+
|
54
|
+
def remove_label(label, number)
|
55
|
+
post "label/remove", label, number
|
56
|
+
end
|
57
|
+
|
58
|
+
def comment(number, comment)
|
59
|
+
post(:comment, number, comment)["comment"]
|
54
60
|
end
|
55
61
|
|
56
62
|
private
|
57
63
|
|
58
64
|
def get(*args)
|
59
|
-
res = Net::HTTP.get
|
60
|
-
|
65
|
+
res = YAML.load Net::HTTP.get(URI.parse(url(*args) + auth(true)))
|
66
|
+
raise ResponseError, errors(res) if res["error"]
|
67
|
+
res
|
61
68
|
end
|
62
69
|
|
63
70
|
def post(*args)
|
64
71
|
params = args.last.is_a?(Hash) ? args.pop : {}
|
65
72
|
params.update auth
|
66
|
-
res = Net::HTTP.post_form
|
67
|
-
|
73
|
+
res = YAML.load Net::HTTP.post_form(URI.parse(url(*args)), params).body
|
74
|
+
raise ResponseError, errors(res) if res["error"]
|
75
|
+
res
|
76
|
+
end
|
77
|
+
|
78
|
+
def errors(response)
|
79
|
+
[*response["error"]].map { |e| e["error"] } * ", "
|
68
80
|
end
|
69
81
|
|
70
82
|
def auth(query = false)
|
@@ -75,10 +87,10 @@ class GHI::API
|
|
75
87
|
end
|
76
88
|
end
|
77
89
|
|
78
|
-
def url(action,
|
90
|
+
def url(action, *args)
|
79
91
|
@url ||= API_URL.sub(":user", user).sub(":repo", repo)
|
80
92
|
uri = @url.sub ":action", action.to_s
|
81
|
-
uri += "/#{
|
93
|
+
uri += "/#{args.join("/")}" unless args.empty?
|
82
94
|
uri
|
83
95
|
end
|
84
96
|
end
|
data/lib/ghi/cli.rb
CHANGED
@@ -5,73 +5,80 @@ require "ghi/api"
|
|
5
5
|
require "ghi/issue"
|
6
6
|
|
7
7
|
class GHI::CLI
|
8
|
-
|
9
|
-
|
10
|
-
@api = GHI::API.new *(@user, @repo = $1, $2)
|
8
|
+
attr_reader :user, :repo, :api, :action, :state, :number, :title,
|
9
|
+
:search_term
|
11
10
|
|
11
|
+
def initialize
|
12
12
|
option_parser.parse!(ARGV)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
13
|
+
|
14
|
+
`git config --get remote.origin.url`.match %r{([^:/]+)/([^/]+).git$}
|
15
|
+
@user ||= $1
|
16
|
+
@repo ||= $2
|
17
|
+
@api = GHI::API.new user, repo
|
18
|
+
|
19
|
+
case action
|
20
|
+
when :search then search search_term, state
|
21
|
+
when :list then list state
|
22
|
+
when :show then show number
|
23
|
+
when :open then open title
|
24
|
+
when :edit then edit number
|
25
|
+
when :close then close number
|
26
|
+
when :reopen then reopen number
|
20
27
|
else puts option_parser
|
21
28
|
end
|
22
29
|
rescue GHI::API::InvalidConnection
|
23
30
|
warn "#{File.basename $0}: not a GitHub repo"
|
31
|
+
rescue GHI::API::ResponseError => e
|
32
|
+
warn "#{File.basename $0}: #{e.message} (#{user}/#{repo})"
|
24
33
|
rescue OptionParser::InvalidOption, OptionParser::MissingArgument => e
|
25
34
|
warn "#{File.basename $0}: #{e.message}"
|
26
35
|
end
|
27
36
|
|
28
37
|
private
|
29
38
|
|
30
|
-
def options
|
31
|
-
@options ||= {}
|
32
|
-
end
|
33
|
-
|
34
39
|
def option_parser
|
35
40
|
@option_parser ||= OptionParser.new { |opts|
|
36
41
|
opts.banner = "Usage: #{File.basename $0} [options]"
|
37
42
|
|
38
|
-
opts.on("-l", "--list", "--show [number]") do |v|
|
39
|
-
|
43
|
+
opts.on("-l", "--list", "--search", "--show [state|term|number]") do |v|
|
44
|
+
@action = :list
|
40
45
|
case v
|
41
|
-
when nil, /^o
|
42
|
-
|
46
|
+
when nil, /^o$/
|
47
|
+
@state = :open
|
43
48
|
when /^\d+$/
|
44
|
-
|
45
|
-
|
46
|
-
when /^c
|
47
|
-
|
49
|
+
@action = :show
|
50
|
+
@number = v.to_i
|
51
|
+
when /^c$/
|
52
|
+
@state = :closed
|
48
53
|
else
|
49
|
-
|
54
|
+
@action = :search
|
55
|
+
@state ||= :open
|
56
|
+
@search_term = v
|
50
57
|
end
|
51
58
|
end
|
52
59
|
|
53
60
|
opts.on("-o", "--open", "--reopen [number]") do |v|
|
54
|
-
|
61
|
+
@action = :open
|
55
62
|
case v
|
56
63
|
when /^\d+$/
|
57
|
-
|
58
|
-
|
59
|
-
when /^l
|
60
|
-
|
61
|
-
|
64
|
+
@action = :reopen
|
65
|
+
@number = v.to_i
|
66
|
+
when /^l/, nil
|
67
|
+
@action = :list
|
68
|
+
@state = :open
|
62
69
|
else
|
63
|
-
|
70
|
+
@title = v
|
64
71
|
end
|
65
72
|
end
|
66
73
|
|
67
74
|
opts.on("-c", "--closed", "--close [number]") do |v|
|
68
75
|
case v
|
69
76
|
when /^\d+$/
|
70
|
-
|
71
|
-
|
72
|
-
when /^l
|
73
|
-
|
74
|
-
|
77
|
+
@action = :close
|
78
|
+
@number = v.to_i
|
79
|
+
when /^l/, nil
|
80
|
+
@action = :list
|
81
|
+
@state = :closed
|
75
82
|
else
|
76
83
|
raise OptionParser::InvalidOption
|
77
84
|
end
|
@@ -80,14 +87,20 @@ class GHI::CLI
|
|
80
87
|
opts.on("-e", "--edit [number]") do |v|
|
81
88
|
case v
|
82
89
|
when /^\d+$/
|
83
|
-
|
84
|
-
|
85
|
-
|
90
|
+
@action = :edit
|
91
|
+
@state = :closed
|
92
|
+
@number = v.to_i
|
86
93
|
else
|
87
94
|
raise OptionParser::MissingArgument
|
88
95
|
end
|
89
96
|
end
|
90
97
|
|
98
|
+
opts.on("-r", "--repo", "--repository [name]") do |v|
|
99
|
+
repo = v.split "/"
|
100
|
+
repo.unshift GHI.login if repo.length == 1
|
101
|
+
@user, @repo = repo
|
102
|
+
end
|
103
|
+
|
91
104
|
opts.on("-V", "--version") do
|
92
105
|
puts "#{File.basename($0)}: v#{GHI::VERSION}"
|
93
106
|
exit
|
@@ -100,9 +113,19 @@ class GHI::CLI
|
|
100
113
|
}
|
101
114
|
end
|
102
115
|
|
116
|
+
def search(term, state)
|
117
|
+
issues = api.search term, state
|
118
|
+
puts "# #{state.to_s.capitalize} #{term.inspect} issues on #{user}/#{repo}"
|
119
|
+
if issues.empty?
|
120
|
+
puts "none"
|
121
|
+
else
|
122
|
+
puts issues.map { |i| " #{i.number.to_s.rjust(3)}: #{i.title[0,72]}" }
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
103
126
|
def list(state)
|
104
|
-
issues =
|
105
|
-
puts "# #{state.to_s.capitalize} issues on
|
127
|
+
issues = api.list state
|
128
|
+
puts "# #{state.to_s.capitalize} issues on #{user}/#{repo}"
|
106
129
|
if issues.empty?
|
107
130
|
puts "none"
|
108
131
|
else
|
@@ -111,7 +134,7 @@ class GHI::CLI
|
|
111
134
|
end
|
112
135
|
|
113
136
|
def show(number)
|
114
|
-
issue =
|
137
|
+
issue = api.show number
|
115
138
|
puts <<-BODY
|
116
139
|
#{issue.number}: #{issue.title} [#{issue.state}]
|
117
140
|
|
@@ -136,7 +159,7 @@ BODY
|
|
136
159
|
#
|
137
160
|
# http://github.github.com/github-flavored-markdown
|
138
161
|
#
|
139
|
-
# On
|
162
|
+
# On #{user}/#{repo}:
|
140
163
|
#
|
141
164
|
# user: #{GHI.login}
|
142
165
|
BODY
|
@@ -150,7 +173,7 @@ BODY
|
|
150
173
|
else
|
151
174
|
title = lines.shift.strip
|
152
175
|
body = lines.join.sub(/\b\n\b/, " ").strip
|
153
|
-
issue =
|
176
|
+
issue = api.open title, body
|
154
177
|
puts " Opened issue #{issue.number}: #{issue.title[0,58]}"
|
155
178
|
end
|
156
179
|
end
|
@@ -159,7 +182,7 @@ BODY
|
|
159
182
|
edit = ENV["VISUAL"] || ENV["EDITOR"] || "vi"
|
160
183
|
begin
|
161
184
|
temp = Tempfile.open("open-issue-")
|
162
|
-
issue =
|
185
|
+
issue = api.show number
|
163
186
|
temp.write <<-BODY
|
164
187
|
#{issue.title}#{"\n\n" + issue.body unless issue.body.to_s.strip == ""}
|
165
188
|
# Please explain the issue. The first line will be used as the title.
|
@@ -193,7 +216,7 @@ BODY
|
|
193
216
|
else
|
194
217
|
title = lines.shift.strip
|
195
218
|
body = lines.join.sub(/\b\n\b/, " ").strip
|
196
|
-
issue =
|
219
|
+
issue = api.edit number, title, body
|
197
220
|
puts " Updated issue #{issue.number}: #{issue.title[0,58]}"
|
198
221
|
end
|
199
222
|
end
|
@@ -203,12 +226,12 @@ BODY
|
|
203
226
|
end
|
204
227
|
|
205
228
|
def close(number)
|
206
|
-
issue =
|
229
|
+
issue = api.close number
|
207
230
|
puts " Closed issue #{issue.number}: #{issue.title[0,58]}"
|
208
231
|
end
|
209
232
|
|
210
233
|
def reopen(number)
|
211
|
-
issue =
|
234
|
+
issue = api.reopen number
|
212
235
|
puts " Reopened issue #{issue.number}: #{issue.title[0,56]}"
|
213
236
|
end
|
214
237
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stephencelis-ghi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stephen Celis
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-04-
|
12
|
+
date: 2009-04-21 00:00:00 -07:00
|
13
13
|
default_executable: ghi
|
14
14
|
dependencies: []
|
15
15
|
|