gemcutter 0.3.0 → 0.4.0.pre
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/Rakefile +7 -6
- data/lib/gemcutter.rb +6 -0
- data/lib/{commands → rubygems/commands}/migrate.rb +1 -1
- data/lib/{commands → rubygems/commands}/tumble.rb +1 -1
- data/lib/{commands → rubygems/commands}/webhook.rb +16 -21
- data/lib/rubygems_plugin.rb +1 -9
- data/test/webhook_command_test.rb +10 -10
- metadata +60 -41
- data/lib/commands/abstract_command.rb +0 -113
- data/lib/commands/owner.rb +0 -99
- data/lib/commands/push.rb +0 -38
- data/test/abstract_command_test.rb +0 -135
- data/test/command_helper.rb +0 -46
- data/test/push_command_test.rb +0 -57
data/Rakefile
CHANGED
@@ -5,7 +5,7 @@ task :default => [:test]
|
|
5
5
|
|
6
6
|
Rake::TestTask.new(:test) do |t|
|
7
7
|
t.libs << "test"
|
8
|
-
t.test_files = FileList['test/*
|
8
|
+
t.test_files = FileList['test/*_test.rb']
|
9
9
|
t.verbose = true
|
10
10
|
end
|
11
11
|
|
@@ -13,14 +13,15 @@ begin
|
|
13
13
|
require 'jeweler'
|
14
14
|
Jeweler::Tasks.new do |gem|
|
15
15
|
gem.name = "gemcutter"
|
16
|
-
gem.version = "0.
|
16
|
+
gem.version = "0.4.0.pre"
|
17
17
|
gem.summary = "Commands to interact with gemcutter.org"
|
18
18
|
gem.description = "Adds several commands to RubyGems for managing gems and more on Gemcutter.org."
|
19
19
|
gem.email = "nick@quaran.to"
|
20
20
|
gem.homepage = "http://gemcutter.org"
|
21
21
|
gem.authors = ["Nick Quaranto"]
|
22
22
|
gem.files = FileList["lib/rubygems_plugin.rb",
|
23
|
-
"lib/
|
23
|
+
"lib/gemcutter.rb",
|
24
|
+
"lib/rubygems/commands/*",
|
24
25
|
"test/*_helper.rb",
|
25
26
|
"test/*_test.rb",
|
26
27
|
"MIT-LICENSE",
|
@@ -31,15 +32,15 @@ begin
|
|
31
32
|
%w[rake shoulda activesupport webmock rr].each do |dep|
|
32
33
|
gem.add_development_dependency(dep)
|
33
34
|
end
|
34
|
-
gem.required_rubygems_version = Gem::Requirement.new(">= 1.3.
|
35
|
+
gem.required_rubygems_version = Gem::Requirement.new(">= 1.3.6.pre.1") if gem.respond_to? :required_rubygems_version=
|
35
36
|
gem.post_install_message = <<MESSAGE
|
36
37
|
|
37
38
|
========================================================================
|
38
39
|
|
39
40
|
Thanks for installing Gemcutter! You can now run:
|
40
41
|
|
41
|
-
gem push
|
42
|
-
gem owner
|
42
|
+
gem push merged into RubyGems 1.3.6
|
43
|
+
gem owner merged into RubyGems 1.3.6
|
43
44
|
gem webhook register urls to be pinged when gems are pushed
|
44
45
|
|
45
46
|
========================================================================
|
data/lib/gemcutter.rb
ADDED
@@ -1,4 +1,9 @@
|
|
1
|
-
|
1
|
+
require 'rubygems/local_remote_options'
|
2
|
+
require 'rubygems/gemcutter_utilities'
|
3
|
+
|
4
|
+
class Gem::Commands::WebhookCommand < Gem::Command
|
5
|
+
include Gem::LocalRemoteOptions
|
6
|
+
include Gem::GemcutterUtilities
|
2
7
|
|
3
8
|
def description
|
4
9
|
<<-EOF
|
@@ -43,7 +48,7 @@ EOF
|
|
43
48
|
end
|
44
49
|
|
45
50
|
def execute
|
46
|
-
|
51
|
+
sign_in
|
47
52
|
|
48
53
|
if options[:url]
|
49
54
|
name = options[:global] ? '*' : get_one_gem_name
|
@@ -60,23 +65,22 @@ EOF
|
|
60
65
|
|
61
66
|
def remove_webhook(name, url)
|
62
67
|
say "Removing webhook..."
|
63
|
-
make_webhook_request(:delete, name, url, "web_hooks/remove")
|
68
|
+
make_webhook_request(:delete, name, url, "api/v1/web_hooks/remove")
|
64
69
|
end
|
65
70
|
|
66
71
|
def fire_webhook(name, url)
|
67
72
|
say "Test firing webhook..."
|
68
|
-
make_webhook_request(:post, name, url, "web_hooks/fire")
|
73
|
+
make_webhook_request(:post, name, url, "api/v1/web_hooks/fire")
|
69
74
|
end
|
70
75
|
|
71
76
|
def list_webhooks
|
72
77
|
require 'json/pure' unless defined?(JSON::JSON_LOADED)
|
73
78
|
|
74
|
-
|
75
|
-
request.add_field("Authorization",
|
79
|
+
resp = rubygems_api_request(:get, "api/v1/web_hooks") do |request|
|
80
|
+
request.add_field("Authorization", Gem.configuration.rubygems_api_key)
|
76
81
|
end
|
77
82
|
|
78
|
-
|
79
|
-
when Net::HTTPSuccess
|
83
|
+
with_response(resp) do |response|
|
80
84
|
begin
|
81
85
|
groups = JSON.parse(response.body)
|
82
86
|
|
@@ -101,24 +105,15 @@ EOF
|
|
101
105
|
say json_error.to_s
|
102
106
|
terminate_interaction
|
103
107
|
end
|
104
|
-
else
|
105
|
-
say response.body
|
106
|
-
terminate_interaction
|
107
108
|
end
|
108
109
|
end
|
109
110
|
|
110
|
-
def make_webhook_request(method, name, url, api = "web_hooks")
|
111
|
-
response =
|
111
|
+
def make_webhook_request(method, name, url, api = "api/v1/web_hooks")
|
112
|
+
response = rubygems_api_request(method, api) do |request|
|
112
113
|
request.set_form_data("gem_name" => name, "url" => url)
|
113
|
-
request.add_field("Authorization",
|
114
|
+
request.add_field("Authorization", Gem.configuration.rubygems_api_key)
|
114
115
|
end
|
115
116
|
|
116
|
-
|
117
|
-
when Net::HTTPSuccess
|
118
|
-
say response.body
|
119
|
-
else
|
120
|
-
say response.body
|
121
|
-
terminate_interaction
|
122
|
-
end
|
117
|
+
with_response(response)
|
123
118
|
end
|
124
119
|
end
|
data/lib/rubygems_plugin.rb
CHANGED
@@ -1,9 +1 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require 'rubygems/command_manager'
|
4
|
-
require 'commands/abstract_command'
|
5
|
-
|
6
|
-
%w[migrate owner push tumble webhook].each do |command|
|
7
|
-
require "commands/#{command}"
|
8
|
-
Gem::CommandManager.instance.register_command command.to_sym
|
9
|
-
end
|
1
|
+
require File.join(File.dirname(__FILE__), 'gemcutter')
|
@@ -1,10 +1,10 @@
|
|
1
|
-
require '
|
1
|
+
require 'helper'
|
2
2
|
|
3
3
|
class WebhookCommandTest < CommandTest
|
4
4
|
context "webhooking" do
|
5
5
|
setup do
|
6
6
|
@gem = "foo"
|
7
|
-
@api = "https://
|
7
|
+
@api = "https://rubygems.org/api/v1/web_hooks"
|
8
8
|
@url = "http://example.com/hook"
|
9
9
|
@command = Gem::Commands::WebhookCommand.new
|
10
10
|
stub(@command).say
|
@@ -20,7 +20,7 @@ class WebhookCommandTest < CommandTest
|
|
20
20
|
|
21
21
|
context "adding a specific hook" do
|
22
22
|
setup do
|
23
|
-
|
23
|
+
stub_api_key("key")
|
24
24
|
stub_request(:post, @api).to_return(:body => "Success!")
|
25
25
|
|
26
26
|
@command.handle_options([@gem, "-a", @url])
|
@@ -45,7 +45,7 @@ class WebhookCommandTest < CommandTest
|
|
45
45
|
|
46
46
|
context "adding a global hook" do
|
47
47
|
setup do
|
48
|
-
|
48
|
+
stub_api_key("key")
|
49
49
|
stub_request(:post, @api).to_return(:body => "Success!")
|
50
50
|
|
51
51
|
@command.handle_options(["-g", "-a", @url])
|
@@ -70,7 +70,7 @@ class WebhookCommandTest < CommandTest
|
|
70
70
|
|
71
71
|
context "listing hooks with some available" do
|
72
72
|
setup do
|
73
|
-
|
73
|
+
stub_api_key("key")
|
74
74
|
stub_request(:get, @api).to_return :body => <<EOF
|
75
75
|
{
|
76
76
|
"foo": [{"url":"http://foogemhook.com","failure_count":0}],
|
@@ -123,7 +123,7 @@ EOF
|
|
123
123
|
|
124
124
|
context "listing hooks with none available" do
|
125
125
|
setup do
|
126
|
-
|
126
|
+
stub_api_key("key")
|
127
127
|
stub_request(:get, @api).to_return(:body => "{}")
|
128
128
|
@command.handle_options([])
|
129
129
|
@command.execute
|
@@ -139,7 +139,7 @@ EOF
|
|
139
139
|
context "listing hooks with a json error" do
|
140
140
|
setup do
|
141
141
|
stub(@command).terminate_interaction
|
142
|
-
|
142
|
+
stub_api_key("key")
|
143
143
|
stub_request(:get, @api).to_return(:body => "fubar")
|
144
144
|
@command.handle_options([])
|
145
145
|
@command.execute
|
@@ -160,7 +160,7 @@ EOF
|
|
160
160
|
|
161
161
|
context "removing specific hooks" do
|
162
162
|
setup do
|
163
|
-
|
163
|
+
stub_api_key("key")
|
164
164
|
stub_request(:delete, "#{@api}/remove").to_return(:body => "Success!")
|
165
165
|
|
166
166
|
@command.handle_options([@gem, "-r", @url])
|
@@ -185,7 +185,7 @@ EOF
|
|
185
185
|
|
186
186
|
context "removing global hooks" do
|
187
187
|
setup do
|
188
|
-
|
188
|
+
stub_api_key("key")
|
189
189
|
stub_request(:delete, "#{@api}/remove").to_return(:body => "Success!")
|
190
190
|
|
191
191
|
@command.handle_options(["-g", "-r", @url])
|
@@ -210,7 +210,7 @@ EOF
|
|
210
210
|
|
211
211
|
context "test firing hooks" do
|
212
212
|
setup do
|
213
|
-
|
213
|
+
stub_api_key("key")
|
214
214
|
stub_request(:post, "#{@api}/fire").to_return(:body => "Success!")
|
215
215
|
|
216
216
|
@command.handle_options([@gem, "-f", @url])
|
metadata
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gemcutter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: true
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 4
|
8
|
+
- 0
|
9
|
+
- pre
|
10
|
+
version: 0.4.0.pre
|
5
11
|
platform: ruby
|
6
12
|
authors:
|
7
13
|
- Nick Quaranto
|
@@ -9,69 +15,81 @@ autorequire:
|
|
9
15
|
bindir: bin
|
10
16
|
cert_chain: []
|
11
17
|
|
12
|
-
date: 2010-
|
18
|
+
date: 2010-02-10 00:00:00 -05:00
|
13
19
|
default_executable:
|
14
20
|
dependencies:
|
15
21
|
- !ruby/object:Gem::Dependency
|
16
22
|
name: json_pure
|
17
|
-
|
18
|
-
|
19
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
25
|
requirements:
|
21
26
|
- - ">="
|
22
27
|
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 0
|
23
30
|
version: "0"
|
24
|
-
|
31
|
+
type: :runtime
|
32
|
+
version_requirements: *id001
|
25
33
|
- !ruby/object:Gem::Dependency
|
26
34
|
name: rake
|
27
|
-
|
28
|
-
|
29
|
-
version_requirements: !ruby/object:Gem::Requirement
|
35
|
+
prerelease: false
|
36
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
37
|
requirements:
|
31
38
|
- - ">="
|
32
39
|
- !ruby/object:Gem::Version
|
40
|
+
segments:
|
41
|
+
- 0
|
33
42
|
version: "0"
|
34
|
-
|
43
|
+
type: :development
|
44
|
+
version_requirements: *id002
|
35
45
|
- !ruby/object:Gem::Dependency
|
36
46
|
name: shoulda
|
37
|
-
|
38
|
-
|
39
|
-
version_requirements: !ruby/object:Gem::Requirement
|
47
|
+
prerelease: false
|
48
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
40
49
|
requirements:
|
41
50
|
- - ">="
|
42
51
|
- !ruby/object:Gem::Version
|
52
|
+
segments:
|
53
|
+
- 0
|
43
54
|
version: "0"
|
44
|
-
|
55
|
+
type: :development
|
56
|
+
version_requirements: *id003
|
45
57
|
- !ruby/object:Gem::Dependency
|
46
58
|
name: activesupport
|
47
|
-
|
48
|
-
|
49
|
-
version_requirements: !ruby/object:Gem::Requirement
|
59
|
+
prerelease: false
|
60
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
50
61
|
requirements:
|
51
62
|
- - ">="
|
52
63
|
- !ruby/object:Gem::Version
|
64
|
+
segments:
|
65
|
+
- 0
|
53
66
|
version: "0"
|
54
|
-
|
67
|
+
type: :development
|
68
|
+
version_requirements: *id004
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: webmock
|
57
|
-
|
58
|
-
|
59
|
-
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
prerelease: false
|
72
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
60
73
|
requirements:
|
61
74
|
- - ">="
|
62
75
|
- !ruby/object:Gem::Version
|
76
|
+
segments:
|
77
|
+
- 0
|
63
78
|
version: "0"
|
64
|
-
|
79
|
+
type: :development
|
80
|
+
version_requirements: *id005
|
65
81
|
- !ruby/object:Gem::Dependency
|
66
82
|
name: rr
|
67
|
-
|
68
|
-
|
69
|
-
version_requirements: !ruby/object:Gem::Requirement
|
83
|
+
prerelease: false
|
84
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
70
85
|
requirements:
|
71
86
|
- - ">="
|
72
87
|
- !ruby/object:Gem::Version
|
88
|
+
segments:
|
89
|
+
- 0
|
73
90
|
version: "0"
|
74
|
-
|
91
|
+
type: :development
|
92
|
+
version_requirements: *id006
|
75
93
|
description: Adds several commands to RubyGems for managing gems and more on Gemcutter.org.
|
76
94
|
email: nick@quaran.to
|
77
95
|
executables: []
|
@@ -83,16 +101,11 @@ extra_rdoc_files: []
|
|
83
101
|
files:
|
84
102
|
- MIT-LICENSE
|
85
103
|
- Rakefile
|
86
|
-
- lib/
|
87
|
-
- lib/commands/migrate.rb
|
88
|
-
- lib/commands/
|
89
|
-
- lib/commands/
|
90
|
-
- lib/commands/tumble.rb
|
91
|
-
- lib/commands/webhook.rb
|
104
|
+
- lib/gemcutter.rb
|
105
|
+
- lib/rubygems/commands/migrate.rb
|
106
|
+
- lib/rubygems/commands/tumble.rb
|
107
|
+
- lib/rubygems/commands/webhook.rb
|
92
108
|
- lib/rubygems_plugin.rb
|
93
|
-
- test/abstract_command_test.rb
|
94
|
-
- test/command_helper.rb
|
95
|
-
- test/push_command_test.rb
|
96
109
|
- test/webhook_command_test.rb
|
97
110
|
has_rdoc: true
|
98
111
|
homepage: http://gemcutter.org
|
@@ -104,8 +117,8 @@ post_install_message: |+
|
|
104
117
|
|
105
118
|
Thanks for installing Gemcutter! You can now run:
|
106
119
|
|
107
|
-
gem push
|
108
|
-
gem owner
|
120
|
+
gem push merged into RubyGems 1.3.6
|
121
|
+
gem owner merged into RubyGems 1.3.6
|
109
122
|
gem webhook register urls to be pinged when gems are pushed
|
110
123
|
|
111
124
|
========================================================================
|
@@ -118,18 +131,24 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
118
131
|
requirements:
|
119
132
|
- - ">="
|
120
133
|
- !ruby/object:Gem::Version
|
134
|
+
segments:
|
135
|
+
- 0
|
121
136
|
version: "0"
|
122
|
-
version:
|
123
137
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
124
138
|
requirements:
|
125
139
|
- - ">="
|
126
140
|
- !ruby/object:Gem::Version
|
127
|
-
|
128
|
-
|
141
|
+
segments:
|
142
|
+
- 1
|
143
|
+
- 3
|
144
|
+
- 6
|
145
|
+
- pre
|
146
|
+
- 1
|
147
|
+
version: 1.3.6.pre.1
|
129
148
|
requirements: []
|
130
149
|
|
131
150
|
rubyforge_project:
|
132
|
-
rubygems_version: 1.3.
|
151
|
+
rubygems_version: 1.3.6.pre.1
|
133
152
|
signing_key:
|
134
153
|
specification_version: 3
|
135
154
|
summary: Commands to interact with gemcutter.org
|
@@ -1,113 +0,0 @@
|
|
1
|
-
require 'rubygems/local_remote_options'
|
2
|
-
|
3
|
-
class Gem::AbstractCommand < Gem::Command
|
4
|
-
include Gem::LocalRemoteOptions
|
5
|
-
|
6
|
-
def gemcutter_url
|
7
|
-
ENV['GEMCUTTER_URL'] || 'https://gemcutter.org'
|
8
|
-
end
|
9
|
-
|
10
|
-
def setup
|
11
|
-
use_proxy! if http_proxy
|
12
|
-
sign_in unless api_key
|
13
|
-
end
|
14
|
-
|
15
|
-
def sign_in
|
16
|
-
say "Enter your Gemcutter credentials. Don't have an account yet? Create one at http://gemcutter.org/sign_up"
|
17
|
-
|
18
|
-
email = ask("Email: ")
|
19
|
-
password = ask_for_password("Password: ")
|
20
|
-
|
21
|
-
response = make_request(:get, "api_key") do |request|
|
22
|
-
request.basic_auth email, password
|
23
|
-
end
|
24
|
-
|
25
|
-
case response
|
26
|
-
when Net::HTTPSuccess
|
27
|
-
self.api_key = response.body
|
28
|
-
say "Signed in. Your api key has been stored in ~/.gem/credentials"
|
29
|
-
else
|
30
|
-
say response.body
|
31
|
-
terminate_interaction
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def credentials_path
|
36
|
-
File.join(Gem.user_home, '.gem', 'credentials')
|
37
|
-
end
|
38
|
-
|
39
|
-
def api_key
|
40
|
-
Gem.configuration.load_file(credentials_path)[:rubygems_api_key]
|
41
|
-
end
|
42
|
-
|
43
|
-
def api_key=(api_key)
|
44
|
-
config = Gem.configuration.load_file(credentials_path).merge(:rubygems_api_key => api_key)
|
45
|
-
|
46
|
-
dirname = File.dirname(credentials_path)
|
47
|
-
Dir.mkdir(dirname) unless File.exists?(dirname)
|
48
|
-
|
49
|
-
File.open(credentials_path, 'w') do |f|
|
50
|
-
f.write config.to_yaml
|
51
|
-
end
|
52
|
-
|
53
|
-
@rubygems_api_key = api_key
|
54
|
-
end
|
55
|
-
|
56
|
-
def make_request(method, path)
|
57
|
-
require 'net/http'
|
58
|
-
require 'net/https'
|
59
|
-
|
60
|
-
url = URI.parse("#{gemcutter_url}/api/v1/#{path}")
|
61
|
-
|
62
|
-
http = proxy_class.new(url.host, url.port)
|
63
|
-
|
64
|
-
if url.scheme == 'https'
|
65
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
66
|
-
http.use_ssl = true
|
67
|
-
end
|
68
|
-
|
69
|
-
request_method =
|
70
|
-
case method
|
71
|
-
when :get
|
72
|
-
proxy_class::Get
|
73
|
-
when :post
|
74
|
-
proxy_class::Post
|
75
|
-
when :put
|
76
|
-
proxy_class::Put
|
77
|
-
when :delete
|
78
|
-
proxy_class::Delete
|
79
|
-
else
|
80
|
-
raise ArgumentError
|
81
|
-
end
|
82
|
-
|
83
|
-
request = request_method.new(url.path)
|
84
|
-
request.add_field "User-Agent", "Gemcutter/0.2.0"
|
85
|
-
|
86
|
-
yield request if block_given?
|
87
|
-
http.request(request)
|
88
|
-
end
|
89
|
-
|
90
|
-
def use_proxy!
|
91
|
-
proxy_uri = http_proxy
|
92
|
-
@proxy_class = Net::HTTP::Proxy(proxy_uri.host, proxy_uri.port, proxy_uri.user, proxy_uri.password)
|
93
|
-
end
|
94
|
-
|
95
|
-
def proxy_class
|
96
|
-
@proxy_class || Net::HTTP
|
97
|
-
end
|
98
|
-
|
99
|
-
# @return [URI, nil] the HTTP-proxy as a URI if set; +nil+ otherwise
|
100
|
-
def http_proxy
|
101
|
-
proxy = Gem.configuration[:http_proxy] || ENV['http_proxy'] || ENV['HTTP_PROXY']
|
102
|
-
return nil if proxy.nil? || proxy == :no_proxy
|
103
|
-
URI.parse(proxy)
|
104
|
-
end
|
105
|
-
|
106
|
-
def ask_for_password(message)
|
107
|
-
system "stty -echo"
|
108
|
-
password = ask(message)
|
109
|
-
system "stty echo"
|
110
|
-
ui.say("\n")
|
111
|
-
password
|
112
|
-
end
|
113
|
-
end
|
data/lib/commands/owner.rb
DELETED
@@ -1,99 +0,0 @@
|
|
1
|
-
class Gem::Commands::OwnerCommand < Gem::AbstractCommand
|
2
|
-
|
3
|
-
def description
|
4
|
-
'Manage gem owners on Gemcutter.'
|
5
|
-
end
|
6
|
-
|
7
|
-
def arguments
|
8
|
-
"GEM_NAME name of gem to manage owners for."
|
9
|
-
end
|
10
|
-
|
11
|
-
def usage
|
12
|
-
"#{program_name} GEM_NAME"
|
13
|
-
end
|
14
|
-
|
15
|
-
def initialize
|
16
|
-
super 'owner', description
|
17
|
-
defaults.merge!(:add => [], :remove => [])
|
18
|
-
|
19
|
-
add_option('-a', '--add EMAIL', 'Add an owner') do |value, options|
|
20
|
-
options[:add] << value
|
21
|
-
end
|
22
|
-
|
23
|
-
add_option('-r', '--remove EMAIL', 'Remove an owner') do |value, options|
|
24
|
-
options[:remove] << value
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def execute
|
29
|
-
setup
|
30
|
-
name = get_one_gem_name
|
31
|
-
|
32
|
-
add_owners name, options[:add]
|
33
|
-
remove_owners name, options[:remove]
|
34
|
-
show_owners name
|
35
|
-
end
|
36
|
-
|
37
|
-
def add_owners(name, owners)
|
38
|
-
owners.each do |owner|
|
39
|
-
response = make_request(:post, "gems/#{name}/owners.json") do |request|
|
40
|
-
request.set_form_data("email" => owner)
|
41
|
-
request.add_field("Authorization", api_key)
|
42
|
-
end
|
43
|
-
|
44
|
-
case response
|
45
|
-
when Net::HTTPSuccess
|
46
|
-
say "Added owner: #{owner}"
|
47
|
-
else
|
48
|
-
say "Error adding owner: #{owner}"
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def remove_owners(name, owners)
|
54
|
-
owners.each do |owner|
|
55
|
-
response = make_request(:delete, "gems/#{name}/owners.json") do |request|
|
56
|
-
request.set_form_data(:email => owner)
|
57
|
-
request.add_field("Authorization", api_key)
|
58
|
-
end
|
59
|
-
|
60
|
-
case response
|
61
|
-
when Net::HTTPSuccess
|
62
|
-
say "Removed owner: #{owner}"
|
63
|
-
else
|
64
|
-
say "Error removing owner: #{owner}"
|
65
|
-
end
|
66
|
-
end end
|
67
|
-
|
68
|
-
def show_owners(name)
|
69
|
-
require 'json/pure' unless defined?(JSON::JSON_LOADED)
|
70
|
-
|
71
|
-
response = make_request(:get, "gems/#{name}/owners.json") do |request|
|
72
|
-
request.add_field("Authorization", api_key)
|
73
|
-
end
|
74
|
-
|
75
|
-
case response
|
76
|
-
when Net::HTTPSuccess
|
77
|
-
begin
|
78
|
-
owners = JSON.parse(response.body)
|
79
|
-
|
80
|
-
say "Owners for gem: #{name}"
|
81
|
-
owners.each do |owner|
|
82
|
-
say "- #{owner['email']}"
|
83
|
-
end
|
84
|
-
rescue JSON::ParserError => json_error
|
85
|
-
say "There was a problem parsing the data: #{json_error}"
|
86
|
-
terminate_interaction
|
87
|
-
end
|
88
|
-
when Net::HTTPNotFound
|
89
|
-
say "This gem is currently not hosted on Gemcutter."
|
90
|
-
terminate_interaction
|
91
|
-
when Net::HTTPUnauthorized
|
92
|
-
say "You do not have permission to manage this gem."
|
93
|
-
terminate_interaction
|
94
|
-
else
|
95
|
-
say "There was a problem processing your request."
|
96
|
-
terminate_interaction
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
data/lib/commands/push.rb
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
class Gem::Commands::PushCommand < Gem::AbstractCommand
|
2
|
-
|
3
|
-
def description
|
4
|
-
'Push a gem up to Gemcutter'
|
5
|
-
end
|
6
|
-
|
7
|
-
def arguments
|
8
|
-
"GEM built gem to push up"
|
9
|
-
end
|
10
|
-
|
11
|
-
def usage
|
12
|
-
"#{program_name} GEM"
|
13
|
-
end
|
14
|
-
|
15
|
-
def initialize
|
16
|
-
super 'push', description
|
17
|
-
add_proxy_option
|
18
|
-
end
|
19
|
-
|
20
|
-
def execute
|
21
|
-
setup
|
22
|
-
send_gem
|
23
|
-
end
|
24
|
-
|
25
|
-
def send_gem
|
26
|
-
say "Pushing gem to Gemcutter..."
|
27
|
-
|
28
|
-
path = get_one_gem_name
|
29
|
-
response = make_request(:post, "gems") do |request|
|
30
|
-
request.body = Gem.read_binary(path)
|
31
|
-
request.add_field("Content-Length", request.body.size)
|
32
|
-
request.add_field("Content-Type", "application/octet-stream")
|
33
|
-
request.add_field("Authorization", api_key)
|
34
|
-
end
|
35
|
-
|
36
|
-
say response.body
|
37
|
-
end
|
38
|
-
end
|
@@ -1,135 +0,0 @@
|
|
1
|
-
require 'command_helper'
|
2
|
-
|
3
|
-
class Gem::Commands::FakeCommand < Gem::AbstractCommand
|
4
|
-
def description
|
5
|
-
'fake command'
|
6
|
-
end
|
7
|
-
|
8
|
-
def initialize
|
9
|
-
super 'fake', description
|
10
|
-
end
|
11
|
-
|
12
|
-
def execute
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
class AbstractCommandTest < CommandTest
|
17
|
-
context "with an fake command" do
|
18
|
-
setup do
|
19
|
-
@command = Gem::Commands::FakeCommand.new
|
20
|
-
stub(@command).say
|
21
|
-
ENV['http_proxy'] = nil
|
22
|
-
ENV['HTTP_PROXY'] = nil
|
23
|
-
end
|
24
|
-
|
25
|
-
context "parsing the proxy" do
|
26
|
-
should "return nil if no proxy is set" do
|
27
|
-
stub_config(:http_proxy => nil)
|
28
|
-
assert_equal nil, @command.http_proxy
|
29
|
-
end
|
30
|
-
|
31
|
-
should "return nil if the proxy is set to :no_proxy" do
|
32
|
-
stub_config(:http_proxy => :no_proxy)
|
33
|
-
assert_equal nil, @command.http_proxy
|
34
|
-
end
|
35
|
-
|
36
|
-
should "return a proxy as a URI if set" do
|
37
|
-
stub_config(:http_proxy => 'http://proxy.example.org:9192')
|
38
|
-
assert_equal 'proxy.example.org', @command.http_proxy.host
|
39
|
-
assert_equal 9192, @command.http_proxy.port
|
40
|
-
end
|
41
|
-
|
42
|
-
should "return a proxy as a URI if set by environment variable" do
|
43
|
-
ENV['http_proxy'] = "http://jack:duck@192.168.1.100:9092"
|
44
|
-
assert_equal "192.168.1.100", @command.http_proxy.host
|
45
|
-
assert_equal 9092, @command.http_proxy.port
|
46
|
-
assert_equal "jack", @command.http_proxy.user
|
47
|
-
assert_equal "duck", @command.http_proxy.password
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
should "sign in if no api key" do
|
52
|
-
stub(@command).api_key { nil }
|
53
|
-
stub(@command).sign_in
|
54
|
-
@command.setup
|
55
|
-
assert_received(@command) { |command| command.sign_in }
|
56
|
-
end
|
57
|
-
|
58
|
-
should "not sign in if api key exists" do
|
59
|
-
stub(@command).api_key { "1234567890" }
|
60
|
-
stub(@command).sign_in
|
61
|
-
@command.setup
|
62
|
-
assert_received(@command) { |command| command.sign_in.never }
|
63
|
-
end
|
64
|
-
|
65
|
-
context "using the proxy" do
|
66
|
-
setup do
|
67
|
-
stub_config(:http_proxy => "http://gilbert:sekret@proxy.example.org:8081")
|
68
|
-
@proxy_class = Object.new
|
69
|
-
mock(Net::HTTP).Proxy('proxy.example.org', 8081, 'gilbert', 'sekret') { @proxy_class }
|
70
|
-
@command.use_proxy!
|
71
|
-
end
|
72
|
-
|
73
|
-
should "replace Net::HTTP with a proxy version" do
|
74
|
-
assert_equal @proxy_class, @command.proxy_class
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
context "signing in" do
|
79
|
-
setup do
|
80
|
-
@email = "email"
|
81
|
-
@password = "password"
|
82
|
-
@key = "key"
|
83
|
-
|
84
|
-
stub(@command).say
|
85
|
-
stub(@command).ask { @email }
|
86
|
-
stub(@command).ask_for_password { @password }
|
87
|
-
stub_config(:rubygems_api_key => @key)
|
88
|
-
end
|
89
|
-
|
90
|
-
context "on a good request" do
|
91
|
-
setup do
|
92
|
-
WebMock.stub_request(:get, "https://#{@email}:#{@password}@gemcutter.org/api/v1/api_key").to_return(:body => @key)
|
93
|
-
end
|
94
|
-
|
95
|
-
should "ask for email and password" do
|
96
|
-
@command.sign_in
|
97
|
-
assert_received(@command) { |command| command.ask("Email: ") }
|
98
|
-
assert_received(@command) { |command| command.ask_for_password("Password: ") }
|
99
|
-
end
|
100
|
-
|
101
|
-
should "say that we signed in" do
|
102
|
-
@command.sign_in
|
103
|
-
assert_received(@command) { |command| command.say("Signed in. Your api key has been stored in ~/.gem/credentials") }
|
104
|
-
assert_received(@command) { |command| command.say("Enter your Gemcutter credentials. Don't have an account yet? Create one at http://gemcutter.org/sign_up") }
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
context "on a bad request" do
|
109
|
-
setup do
|
110
|
-
@problem = "Access Denied"
|
111
|
-
stub(@command).terminate_interaction
|
112
|
-
stub(@command).send(:api_key=)
|
113
|
-
WebMock.stub_request(:get, "https://#{@email}:#{@password}@gemcutter.org/api/v1/api_key").to_return(
|
114
|
-
:body => @problem,
|
115
|
-
:status => 401)
|
116
|
-
end
|
117
|
-
|
118
|
-
should "let the user know there was a problem" do
|
119
|
-
@command.sign_in
|
120
|
-
assert_received(@command) { |command| command.say(@problem) }
|
121
|
-
end
|
122
|
-
|
123
|
-
should "kill the command" do
|
124
|
-
@command.sign_in
|
125
|
-
assert_received(@command) { |command| command.terminate_interaction }
|
126
|
-
end
|
127
|
-
|
128
|
-
should "not write anything to the credentials file" do
|
129
|
-
@command.sign_in
|
130
|
-
assert_received(@command) { |command| command.send(:api_key=).never }
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
data/test/command_helper.rb
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'test/unit'
|
3
|
-
|
4
|
-
require 'shoulda'
|
5
|
-
require 'active_support'
|
6
|
-
require 'active_support/test_case'
|
7
|
-
require 'webmock'
|
8
|
-
require 'rr'
|
9
|
-
|
10
|
-
begin
|
11
|
-
require 'redgreen'
|
12
|
-
rescue LoadError
|
13
|
-
end
|
14
|
-
|
15
|
-
WebMock.disable_net_connect!
|
16
|
-
|
17
|
-
$:.unshift File.expand_path(File.join(File.dirname(__FILE__), ".."))
|
18
|
-
|
19
|
-
require "rubygems_plugin"
|
20
|
-
|
21
|
-
class CommandTest < ActiveSupport::TestCase
|
22
|
-
include RR::Adapters::TestUnit unless include?(RR::Adapters::TestUnit)
|
23
|
-
include WebMock
|
24
|
-
|
25
|
-
def teardown
|
26
|
-
reset_webmock
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def stub_config(config)
|
31
|
-
file = Gem::ConfigFile.new({})
|
32
|
-
config.each { |key, value| file[key] = value }
|
33
|
-
stub(Gem).configuration { file }
|
34
|
-
end
|
35
|
-
|
36
|
-
def assert_said(command, what)
|
37
|
-
assert_received(command) do |command|
|
38
|
-
command.say(what)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def assert_never_said(command, what)
|
43
|
-
assert_received(command) do |command|
|
44
|
-
command.say(what).never
|
45
|
-
end
|
46
|
-
end
|
data/test/push_command_test.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
require 'command_helper'
|
2
|
-
|
3
|
-
class PushCommandTest < CommandTest
|
4
|
-
context "pushing" do
|
5
|
-
setup do
|
6
|
-
@command = Gem::Commands::PushCommand.new
|
7
|
-
stub(@command).say
|
8
|
-
end
|
9
|
-
|
10
|
-
should "setup and send the gem" do
|
11
|
-
mock(@command).setup
|
12
|
-
mock(@command).send_gem
|
13
|
-
@command.execute
|
14
|
-
assert_received(@command) { |command| command.setup }
|
15
|
-
assert_received(@command) { |command| command.send_gem }
|
16
|
-
end
|
17
|
-
|
18
|
-
should "raise an error with no arguments" do
|
19
|
-
assert_raise Gem::CommandLineError do
|
20
|
-
@command.send_gem
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
context "pushing a gem" do
|
25
|
-
setup do
|
26
|
-
@url = "https://gemcutter.org/api/v1/gems"
|
27
|
-
@gem_path = "path/to/foo-0.0.0.gem"
|
28
|
-
@gem_binary = StringIO.new("gem")
|
29
|
-
|
30
|
-
stub(@command).say
|
31
|
-
stub(@command).options { {:args => [@gem_path]} }
|
32
|
-
stub(Gem).read_binary(@gem_path) { @gem_binary }
|
33
|
-
stub_config({ :rubygems_api_key => "key" })
|
34
|
-
stub_request(:post, @url).to_return(:body => "Success!")
|
35
|
-
|
36
|
-
@command.send_gem
|
37
|
-
end
|
38
|
-
|
39
|
-
should "say push was successful" do
|
40
|
-
assert_received(@command) { |command| command.say("Pushing gem to Gemcutter...") }
|
41
|
-
assert_received(@command) { |command| command.say("Success!") }
|
42
|
-
end
|
43
|
-
|
44
|
-
should "post to api" do
|
45
|
-
# webmock doesn't pass body params on correctly :[
|
46
|
-
assert_requested(:post, @url,
|
47
|
-
:times => 1)
|
48
|
-
assert_requested(:post, @url,
|
49
|
-
:headers => {'Authorization' => 'key' })
|
50
|
-
assert_requested(:post, @url,
|
51
|
-
:headers => {'Content-Length' => @gem_binary.size})
|
52
|
-
assert_requested(:post, @url,
|
53
|
-
:headers => {'Content-Type' => 'application/octet-stream'})
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|