ghi 0.2.4 → 0.2.5
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 +7 -0
- data/README.rdoc +6 -0
- data/lib/ghi/api.rb +33 -11
- data/lib/ghi/cli.rb +10 -2
- data/spec/ghi/api_spec.rb +82 -60
- metadata +14 -5
data/History.rdoc
CHANGED
data/README.rdoc
CHANGED
@@ -19,6 +19,7 @@ Go:
|
|
19
19
|
-l, --list [state|term|number]
|
20
20
|
--search, --show
|
21
21
|
-v, --verbose
|
22
|
+
--ssl
|
22
23
|
-o, --open [title|number]
|
23
24
|
--reopen
|
24
25
|
-c, --closed, --close [number]
|
@@ -76,11 +77,16 @@ ghi uses ANSI colors if you use them in git.
|
|
76
77
|
|
77
78
|
ghi looks for a <tt>$GHI_PAGER</tt> variable for paging.
|
78
79
|
|
80
|
+
Always favor SSL by setting it:
|
81
|
+
|
82
|
+
git config --global github.ssl true
|
83
|
+
|
79
84
|
|
80
85
|
== CONTRIBUTORS
|
81
86
|
|
82
87
|
* Jamie Macey (http://blog.tracefunc.com)
|
83
88
|
* Hiroshi Nakamura (http://github.com/nahi)
|
89
|
+
* David J. Hamilton
|
84
90
|
|
85
91
|
|
86
92
|
=== CONTRIBUTE?
|
data/lib/ghi/api.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require "net/http"
|
2
2
|
require "yaml"
|
3
|
+
require "cgi"
|
3
4
|
|
4
5
|
class GHI::API
|
5
6
|
class InvalidRequest < StandardError
|
@@ -11,13 +12,14 @@ class GHI::API
|
|
11
12
|
class ResponseError < StandardError
|
12
13
|
end
|
13
14
|
|
14
|
-
|
15
|
+
API_HOST = "github.com"
|
16
|
+
API_PATH = "/api/v2/yaml/issues/:action/:user/:repo"
|
15
17
|
|
16
18
|
attr_reader :user, :repo
|
17
19
|
|
18
|
-
def initialize(user, repo)
|
20
|
+
def initialize(user, repo, use_ssl = false)
|
19
21
|
raise InvalidConnection if user.nil? || repo.nil?
|
20
|
-
@user, @repo = user, repo
|
22
|
+
@user, @repo, @use_ssl = user, repo, use_ssl
|
21
23
|
end
|
22
24
|
|
23
25
|
def search(term, state = :open)
|
@@ -64,7 +66,19 @@ class GHI::API
|
|
64
66
|
private
|
65
67
|
|
66
68
|
def get(*args)
|
67
|
-
res =
|
69
|
+
res = nil
|
70
|
+
http = Net::HTTP.new(API_HOST, @use_ssl ? 443 : 80)
|
71
|
+
http.use_ssl = true if @use_ssl
|
72
|
+
http.start do
|
73
|
+
if @use_ssl
|
74
|
+
req = Net::HTTP::Post.new path(*args)
|
75
|
+
req.set_form_data auth
|
76
|
+
else
|
77
|
+
req = Net::HTTP::Get.new(path(*args) + auth(true))
|
78
|
+
end
|
79
|
+
res = YAML.load http.request(req).body
|
80
|
+
end
|
81
|
+
|
68
82
|
raise ResponseError, errors(res) if res["error"]
|
69
83
|
res
|
70
84
|
rescue ArgumentError, URI::InvalidURIError
|
@@ -75,8 +89,16 @@ class GHI::API
|
|
75
89
|
|
76
90
|
def post(*args)
|
77
91
|
params = args.last.is_a?(Hash) ? args.pop : {}
|
78
|
-
|
79
|
-
res =
|
92
|
+
|
93
|
+
res = nil
|
94
|
+
http = Net::HTTP.new(API_HOST, @use_ssl ? 443 : 80)
|
95
|
+
http.use_ssl = true if @use_ssl
|
96
|
+
http.start do
|
97
|
+
req = Net::HTTP::Post.new path(*args)
|
98
|
+
req.set_form_data params.merge(auth)
|
99
|
+
res = YAML.load http.request(req).body
|
100
|
+
end
|
101
|
+
|
80
102
|
raise ResponseError, errors(res) if res["error"]
|
81
103
|
res
|
82
104
|
rescue ArgumentError, URI::InvalidURIError
|
@@ -97,10 +119,10 @@ class GHI::API
|
|
97
119
|
end
|
98
120
|
end
|
99
121
|
|
100
|
-
def
|
101
|
-
@
|
102
|
-
|
103
|
-
|
104
|
-
|
122
|
+
def path(action, *args)
|
123
|
+
@path ||= API_PATH.sub(":user", user).sub(":repo", repo)
|
124
|
+
path = @path.sub ":action", action.to_s
|
125
|
+
path << "/#{args.join("/")}" unless args.empty?
|
126
|
+
path
|
105
127
|
end
|
106
128
|
end
|
data/lib/ghi/cli.rb
CHANGED
@@ -207,7 +207,8 @@ module GHI::CLI #:nodoc:
|
|
207
207
|
include FileHelper, FormattingHelper
|
208
208
|
|
209
209
|
attr_reader :message, :local_user, :local_repo, :user, :repo, :api,
|
210
|
-
:action, :search_term, :number, :title, :body, :tag, :args, :verbosity
|
210
|
+
:action, :search_term, :number, :title, :body, :tag, :args, :verbosity,
|
211
|
+
:use_ssl
|
211
212
|
|
212
213
|
def parse!(*argv)
|
213
214
|
@args, @argv = argv, argv.dup
|
@@ -241,7 +242,7 @@ module GHI::CLI #:nodoc:
|
|
241
242
|
end
|
242
243
|
|
243
244
|
def run!
|
244
|
-
@api = GHI::API.new user, repo
|
245
|
+
@api = GHI::API.new user, repo, use_ssl
|
245
246
|
|
246
247
|
case action
|
247
248
|
when :search then search
|
@@ -313,6 +314,10 @@ module GHI::CLI #:nodoc:
|
|
313
314
|
end
|
314
315
|
end
|
315
316
|
|
317
|
+
opts.on("--ssl") do |ssl|
|
318
|
+
@use_ssl = true
|
319
|
+
end
|
320
|
+
|
316
321
|
opts.on("-o", "--open", "--reopen [title|number]") do |v|
|
317
322
|
@action = :open
|
318
323
|
case v
|
@@ -607,6 +612,9 @@ module GHI::CLI #:nodoc:
|
|
607
612
|
@action = :url
|
608
613
|
@number ||= arguments.shift[/\d+/].to_i
|
609
614
|
end
|
615
|
+
|
616
|
+
@use_ssl ||= `git config github.ssl`.chomp == 'true'
|
617
|
+
|
610
618
|
if @action
|
611
619
|
@args = @argv.dup
|
612
620
|
args.delete_if { |arg| arg == command }
|
data/spec/ghi/api_spec.rb
CHANGED
@@ -65,132 +65,154 @@ describe GHI::API do
|
|
65
65
|
@api = API.new "stephencelis", "ghi"
|
66
66
|
GHI.stub!(:login).and_return "stephencelis"
|
67
67
|
GHI.stub!(:token).and_return "token"
|
68
|
+
|
69
|
+
@http = mock(Net::HTTP)
|
70
|
+
@http.stub(:start) { |l| l.call }
|
68
71
|
end
|
69
72
|
|
70
73
|
it "should substitute url tokens" do
|
71
|
-
@api.send(:
|
72
|
-
"
|
73
|
-
@api.send(:
|
74
|
-
"
|
75
|
-
@api.send(:
|
76
|
-
"
|
77
|
-
@api.send(:
|
78
|
-
"
|
74
|
+
@api.send(:path, :open).should ==
|
75
|
+
"/api/v2/yaml/issues/open/stephencelis/ghi"
|
76
|
+
@api.send(:path, :show, 1).should ==
|
77
|
+
"/api/v2/yaml/issues/show/stephencelis/ghi/1"
|
78
|
+
@api.send(:path, :search, :open, "me").should ==
|
79
|
+
"/api/v2/yaml/issues/search/stephencelis/ghi/open/me"
|
80
|
+
@api.send(:path, "label/add", "me").should ==
|
81
|
+
"/api/v2/yaml/issues/label/add/stephencelis/ghi/me"
|
79
82
|
end
|
80
83
|
|
81
84
|
it "should process gets" do
|
82
|
-
|
85
|
+
path = "/api/v2/yaml/issues/open/stephencelis/ghi"
|
83
86
|
query = "?login=stephencelis&token=token"
|
84
|
-
@api.stub!(:
|
85
|
-
|
86
|
-
Net::
|
87
|
+
@api.stub!(:path).and_return path
|
88
|
+
req = mock(Net::HTTPRequest)
|
89
|
+
res = mock(Net::HTTPResponse)
|
90
|
+
Net::HTTP.should_receive(:new).once.and_return @http
|
91
|
+
Net::HTTP::Get.should_receive(:new).once.with(path + query).
|
92
|
+
and_return req
|
93
|
+
@http.should_receive(:request).once.with(req).and_return res
|
94
|
+
res.should_receive(:body).once.and_return ISSUES_YAML
|
87
95
|
@api.list
|
88
96
|
end
|
89
97
|
|
90
98
|
it "should process posts" do
|
91
|
-
|
99
|
+
path = "/api/v2/yaml/issues/open/stephencelis/ghi"
|
92
100
|
query = { "login" => "stephencelis",
|
93
101
|
"token" => "token",
|
94
102
|
"title" => "Title",
|
95
103
|
"body" => "Body" }
|
96
|
-
@api.stub!(:
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
Net::HTTP.should_receive(:
|
104
|
+
@api.stub!(:path).and_return path
|
105
|
+
req = mock(Net::HTTPRequest)
|
106
|
+
res = mock(Net::HTTPResponse)
|
107
|
+
Net::HTTP.should_receive(:new).once.and_return @http
|
108
|
+
Net::HTTP::Post.should_receive(:new).once.with(path).and_return req
|
109
|
+
req.should_receive(:set_form_data).once
|
110
|
+
@http.should_receive(:request).once.with(req).and_return res
|
111
|
+
res.should_receive(:body).once.and_return ISSUE_YAML
|
101
112
|
@api.open "Title", "Body"
|
102
113
|
end
|
103
114
|
|
115
|
+
def expect_get_response(body)
|
116
|
+
req = mock(Net::HTTPRequest)
|
117
|
+
res = mock(Net::HTTPResponse)
|
118
|
+
Net::HTTP.should_receive(:new).once.and_return @http
|
119
|
+
Net::HTTP::Get.should_receive(:new).once.and_return req
|
120
|
+
@http.should_receive(:request).once.with(req).and_return res
|
121
|
+
res.should_receive(:body).once.and_return body
|
122
|
+
end
|
123
|
+
|
124
|
+
def expect_post_response(body)
|
125
|
+
req = mock(Net::HTTPRequest)
|
126
|
+
res = mock(Net::HTTPResponse)
|
127
|
+
Net::HTTP.should_receive(:new).once.and_return @http
|
128
|
+
Net::HTTP::Post.should_receive(:new).once.and_return req
|
129
|
+
req.should_receive(:set_form_data).once
|
130
|
+
@http.should_receive(:request).once.with(req).and_return res
|
131
|
+
res.should_receive(:body).once.and_return body
|
132
|
+
end
|
133
|
+
|
104
134
|
it "should search open by default" do
|
105
|
-
@api.should_receive(:
|
106
|
-
|
135
|
+
@api.should_receive(:path).with(:search, :open, "me").and_return "u"
|
136
|
+
expect_get_response ISSUES_YAML
|
107
137
|
issues = @api.search "me"
|
108
138
|
issues.should be_an_instance_of(Array)
|
109
139
|
issues.each { |issue| issue.should be_an_instance_of(Issue) }
|
110
140
|
end
|
111
141
|
|
112
142
|
it "should search closed" do
|
113
|
-
@api.should_receive(:
|
114
|
-
|
143
|
+
@api.should_receive(:path).with(:search, :closed, "me").and_return "u"
|
144
|
+
expect_get_response ISSUES_YAML
|
115
145
|
@api.search "me", :closed
|
116
146
|
end
|
117
147
|
|
118
148
|
it "should list open by default" do
|
119
|
-
@api.should_receive(:
|
120
|
-
|
149
|
+
@api.should_receive(:path).with(:list, :open).and_return "u"
|
150
|
+
expect_get_response ISSUES_YAML
|
121
151
|
issues = @api.list
|
122
152
|
issues.should be_an_instance_of(Array)
|
123
153
|
issues.each { |issue| issue.should be_an_instance_of(Issue) }
|
124
154
|
end
|
125
155
|
|
126
156
|
it "should list closed" do
|
127
|
-
@api.should_receive(:
|
128
|
-
|
157
|
+
@api.should_receive(:path).with(:list, :closed).and_return "u"
|
158
|
+
expect_get_response ISSUES_YAML
|
129
159
|
@api.list :closed
|
130
160
|
end
|
131
161
|
|
132
162
|
it "should show" do
|
133
|
-
@api.should_receive(:
|
134
|
-
|
163
|
+
@api.should_receive(:path).with(:show, 1).and_return "u"
|
164
|
+
expect_get_response ISSUE_YAML
|
135
165
|
@api.show(1).should be_an_instance_of(Issue)
|
136
166
|
end
|
137
167
|
|
138
168
|
it "should open" do
|
139
|
-
@api.should_receive(:
|
140
|
-
|
141
|
-
response.stub!(:body).and_return ISSUE_YAML
|
142
|
-
Net::HTTP.stub!(:post_form).and_return response
|
169
|
+
@api.should_receive(:path).with(:open).and_return "u"
|
170
|
+
expect_post_response ISSUE_YAML
|
143
171
|
@api.open("Title", "Body").should be_an_instance_of(Issue)
|
144
172
|
end
|
145
173
|
|
146
174
|
it "should edit" do
|
147
|
-
@api.should_receive(:
|
148
|
-
|
149
|
-
response.stub!(:body).and_return ISSUE_YAML
|
150
|
-
Net::HTTP.stub!(:post_form).and_return response
|
175
|
+
@api.should_receive(:path).with(:edit, 1).and_return "u"
|
176
|
+
expect_post_response ISSUE_YAML
|
151
177
|
@api.edit(1, "Title", "Body").should be_an_instance_of(Issue)
|
152
178
|
end
|
153
179
|
|
154
180
|
it "should close" do
|
155
|
-
@api.should_receive(:
|
156
|
-
|
157
|
-
response.stub!(:body).and_return ISSUE_YAML
|
158
|
-
Net::HTTP.stub!(:post_form).and_return response
|
181
|
+
@api.should_receive(:path).with(:close, 1).and_return "u"
|
182
|
+
expect_post_response ISSUE_YAML
|
159
183
|
@api.close(1).should be_an_instance_of(Issue)
|
160
184
|
end
|
161
185
|
|
162
186
|
it "should reopen" do
|
163
|
-
@api.should_receive(:
|
164
|
-
|
165
|
-
response.stub!(:body).and_return ISSUE_YAML
|
166
|
-
Net::HTTP.stub!(:post_form).and_return response
|
187
|
+
@api.should_receive(:path).with(:reopen, 1).and_return "u"
|
188
|
+
expect_post_response ISSUE_YAML
|
167
189
|
@api.reopen(1).should be_an_instance_of(Issue)
|
168
190
|
end
|
169
191
|
|
170
192
|
it "should add labels" do
|
171
|
-
@api.should_receive(:
|
172
|
-
|
173
|
-
response.stub!(:body).and_return LABELS_YAML
|
174
|
-
Net::HTTP.stub!(:post_form).and_return response
|
193
|
+
@api.should_receive(:path).with("label/add", 1, "l").and_return "u"
|
194
|
+
expect_post_response LABELS_YAML
|
175
195
|
@api.add_label(1, "l").should be_an_instance_of(Array)
|
176
196
|
end
|
177
197
|
|
178
198
|
it "should remove labels" do
|
179
|
-
@api.should_receive(:
|
180
|
-
|
181
|
-
response.stub!(:body).and_return LABELS_YAML
|
182
|
-
Net::HTTP.stub!(:post_form).and_return response
|
199
|
+
@api.should_receive(:path).with("label/remove", 1, "l").and_return "u"
|
200
|
+
expect_post_response LABELS_YAML
|
183
201
|
@api.remove_label(1, "l").should be_an_instance_of(Array)
|
184
202
|
end
|
185
203
|
|
186
|
-
it "should comment" do
|
187
|
-
@api.should_receive(:
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
Net::HTTP.should_receive(:
|
192
|
-
|
193
|
-
|
204
|
+
it "should comment, and escape values" do
|
205
|
+
@api.should_receive(:path).with(:comment, 1).and_return "u"
|
206
|
+
|
207
|
+
req = mock(Net::HTTPRequest)
|
208
|
+
res = mock(Net::HTTPResponse)
|
209
|
+
Net::HTTP.should_receive(:new).once.and_return @http
|
210
|
+
Net::HTTP::Post.should_receive(:new).once.and_return req
|
211
|
+
req.should_receive(:set_form_data).once
|
212
|
+
@http.should_receive(:request).once.with(req).and_return res
|
213
|
+
res.should_receive(:body).once.and_return COMMENT_YAML
|
214
|
+
|
215
|
+
@api.comment(1, "Comment&so").should be_an_instance_of(Hash)
|
194
216
|
end
|
195
217
|
end
|
196
218
|
end
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ghi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 2
|
8
|
+
- 5
|
9
|
+
version: 0.2.5
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Stephen Celis
|
@@ -9,7 +14,7 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date:
|
17
|
+
date: 2010-07-28 00:00:00 -05:00
|
13
18
|
default_executable: ghi
|
14
19
|
dependencies: []
|
15
20
|
|
@@ -48,21 +53,25 @@ rdoc_options:
|
|
48
53
|
require_paths:
|
49
54
|
- lib
|
50
55
|
required_ruby_version: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
51
57
|
requirements:
|
52
58
|
- - ">="
|
53
59
|
- !ruby/object:Gem::Version
|
60
|
+
segments:
|
61
|
+
- 0
|
54
62
|
version: "0"
|
55
|
-
version:
|
56
63
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
57
65
|
requirements:
|
58
66
|
- - ">="
|
59
67
|
- !ruby/object:Gem::Version
|
68
|
+
segments:
|
69
|
+
- 0
|
60
70
|
version: "0"
|
61
|
-
version:
|
62
71
|
requirements: []
|
63
72
|
|
64
73
|
rubyforge_project: ghi
|
65
|
-
rubygems_version: 1.3.
|
74
|
+
rubygems_version: 1.3.7
|
66
75
|
signing_key:
|
67
76
|
specification_version: 3
|
68
77
|
summary: GitHub Issues on the command line
|