gemcutter 0.2.1 → 0.3.0.pre

Sign up to get free protection for your applications and to get access to all the features.
data/MIT-LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2009, Nick Quaranto
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,52 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+
4
+ task :default => [:test]
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << "test"
8
+ t.test_files = FileList['test/*_command_test.rb']
9
+ t.verbose = true
10
+ end
11
+
12
+ begin
13
+ require 'jeweler'
14
+ Jeweler::Tasks.new do |gem|
15
+ gem.name = "gemcutter"
16
+ gem.version = "0.3.0.pre"
17
+ gem.summary = "Commands to interact with gemcutter.org"
18
+ gem.description = "Adds several commands to RubyGems for managing gems and more on Gemcutter.org."
19
+ gem.email = "nick@quaran.to"
20
+ gem.homepage = "http://gemcutter.org"
21
+ gem.authors = ["Nick Quaranto"]
22
+ gem.files = FileList["lib/rubygems_plugin.rb",
23
+ "lib/commands/*",
24
+ "test/*_helper.rb",
25
+ "test/*_test.rb",
26
+ "MIT-LICENSE",
27
+ "Rakefile"]
28
+ gem.test_files = []
29
+ gem.executables = []
30
+ gem.add_runtime_dependency('json_pure')
31
+ %w[rake shoulda activesupport webmock rr].each do |dep|
32
+ gem.add_development_dependency(dep)
33
+ end
34
+ gem.required_rubygems_version = Gem::Requirement.new(">= 1.3.5") if gem.respond_to? :required_rubygems_version=
35
+ gem.post_install_message = <<MESSAGE
36
+
37
+ ========================================================================
38
+
39
+ Thanks for installing Gemcutter! You can now run:
40
+
41
+ gem push publish your gems for the world to use and enjoy
42
+ gem owner allow/disallow others to push to your gems
43
+ gem webhook register urls to be pinged when gems are pushed
44
+
45
+ ========================================================================
46
+
47
+ MESSAGE
48
+ end
49
+ Jeweler::RubyforgeTasks.new
50
+ rescue LoadError
51
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
52
+ end
@@ -3,8 +3,6 @@ require 'rubygems/local_remote_options'
3
3
  class Gem::AbstractCommand < Gem::Command
4
4
  include Gem::LocalRemoteOptions
5
5
 
6
- URL = "http://gemcutter.org"
7
-
8
6
  def gemcutter_url
9
7
  ENV['GEMCUTTER_URL'] || 'https://gemcutter.org'
10
8
  end
@@ -15,7 +13,7 @@ class Gem::AbstractCommand < Gem::Command
15
13
  end
16
14
 
17
15
  def sign_in
18
- say "Enter your Gemcutter credentials. Don't have an account yet? Create one at #{URL}/sign_up"
16
+ say "Enter your Gemcutter credentials. Don't have an account yet? Create one at http://gemcutter.org/sign_up"
19
17
 
20
18
  email = ask("Email: ")
21
19
  password = ask_for_password("Password: ")
@@ -1,8 +1,17 @@
1
1
  class Gem::Commands::OwnerCommand < Gem::AbstractCommand
2
+
2
3
  def description
3
4
  'Manage gem owners on Gemcutter.'
4
5
  end
5
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
+
6
15
  def initialize
7
16
  super 'owner', description
8
17
  defaults.merge!(:add => [], :remove => [])
@@ -57,7 +66,8 @@ class Gem::Commands::OwnerCommand < Gem::AbstractCommand
57
66
  end end
58
67
 
59
68
  def show_owners(name)
60
- require 'json/pure'
69
+ require 'json/pure' unless defined?(JSON::JSON_LOADED)
70
+
61
71
  response = make_request(:get, "gems/#{name}/owners.json") do |request|
62
72
  request.add_field("Authorization", api_key)
63
73
  end
data/lib/commands/push.rb CHANGED
@@ -25,9 +25,9 @@ class Gem::Commands::PushCommand < Gem::AbstractCommand
25
25
  def send_gem
26
26
  say "Pushing gem to Gemcutter..."
27
27
 
28
- name = get_one_gem_name
28
+ path = get_one_gem_name
29
29
  response = make_request(:post, "gems") do |request|
30
- request.body = File.open(name, 'rb'){|io| io.read }
30
+ request.body = Gem.read_binary(path)
31
31
  request.add_field("Content-Length", request.body.size)
32
32
  request.add_field("Content-Type", "application/octet-stream")
33
33
  request.add_field("Authorization", api_key)
@@ -35,5 +35,4 @@ class Gem::Commands::PushCommand < Gem::AbstractCommand
35
35
 
36
36
  say response.body
37
37
  end
38
-
39
38
  end
@@ -0,0 +1,126 @@
1
+ class Gem::Commands::WebhookCommand < Gem::AbstractCommand
2
+
3
+ def description
4
+ <<-EOF
5
+ Register a webhook that will be called any time a gem is updated on Gemcutter.
6
+
7
+ Webhooks can be created for either specific gems or all gems. In both cases
8
+ you'll get a POST request of the gem in JSON format at the URL you specify in
9
+ the command. You can also use this command to test fire a webhook.
10
+ EOF
11
+ end
12
+
13
+ def arguments
14
+ "GEM_NAME name of gem to register webhook for, or omit to list hooks."
15
+ end
16
+
17
+ def usage
18
+ "#{program_name} GEM_NAME"
19
+ end
20
+
21
+ def initialize
22
+ super 'webhook', description
23
+ option_text = "The URL of the webhook to"
24
+
25
+ add_option('-a', '--add URL', "#{option_text} add") do |value, options|
26
+ options[:send] = 'add'
27
+ options[:url] = value
28
+ end
29
+
30
+ add_option('-r', '--remove URL', "#{option_text} remove") do |value, options|
31
+ options[:send] = 'remove'
32
+ options[:url] = value
33
+ end
34
+
35
+ add_option('-f', '--fire URL', "#{option_text} testfire") do |value, options|
36
+ options[:send] = 'fire'
37
+ options[:url] = value
38
+ end
39
+
40
+ add_option('-g', '--global', "Apply hook globally") do |value, options|
41
+ options[:global] = true
42
+ end
43
+
44
+ add_proxy_option
45
+ end
46
+
47
+ def execute
48
+ setup
49
+
50
+ if options[:url]
51
+ name = options[:global] ? '*' : get_one_gem_name
52
+ send("#{options[:send]}_webhook", name, options[:url])
53
+ else
54
+ list_webhooks
55
+ end
56
+ end
57
+
58
+ def add_webhook(name, url)
59
+ say "Adding webhook..."
60
+ make_webhook_request(:post, name, url)
61
+ end
62
+
63
+ def remove_webhook(name, url)
64
+ say "Removing webhook..."
65
+ make_webhook_request(:delete, name, url, "web_hooks/remove")
66
+ end
67
+
68
+ def fire_webhook(name, url)
69
+ say "Test firing webhook..."
70
+ make_webhook_request(:post, name, url, "web_hooks/fire")
71
+ end
72
+
73
+ def list_webhooks
74
+ require 'json/pure' unless defined?(JSON::JSON_LOADED)
75
+
76
+ response = make_request(:get, "web_hooks") do |request|
77
+ request.add_field("Authorization", api_key)
78
+ end
79
+
80
+ case response
81
+ when Net::HTTPSuccess
82
+ begin
83
+ groups = JSON.parse(response.body)
84
+
85
+ if groups.size.zero?
86
+ say "You haven't added any webhooks yet."
87
+ else
88
+ groups.each do |group, hooks|
89
+ if options[:global]
90
+ next if group != "all gems"
91
+ elsif options[:args] && options[:args].first
92
+ next if group != options[:args].first
93
+ end
94
+
95
+ say "#{group}:"
96
+ hooks.each do |hook|
97
+ say "- #{hook['url']}"
98
+ end
99
+ end
100
+ end
101
+ rescue JSON::ParserError => json_error
102
+ say "There was a problem parsing the data:"
103
+ say json_error.to_s
104
+ terminate_interaction
105
+ end
106
+ else
107
+ say response.body
108
+ terminate_interaction
109
+ end
110
+ end
111
+
112
+ def make_webhook_request(method, name, url, api = "web_hooks")
113
+ response = make_request(method, api) do |request|
114
+ request.set_form_data("gem_name" => name, "url" => url)
115
+ request.add_field("Authorization", api_key)
116
+ end
117
+
118
+ case response
119
+ when Net::HTTPSuccess
120
+ say response.body
121
+ else
122
+ say response.body
123
+ terminate_interaction
124
+ end
125
+ end
126
+ end
@@ -3,7 +3,7 @@ $:.unshift File.dirname(__FILE__) # For use/testing when no gem is installed
3
3
  require 'rubygems/command_manager'
4
4
  require 'commands/abstract_command'
5
5
 
6
- %w[migrate owner push tumble].each do |command|
6
+ %w[migrate owner push tumble webhook].each do |command|
7
7
  require "commands/#{command}"
8
8
  Gem::CommandManager.instance.register_command command.to_sym
9
9
  end
@@ -0,0 +1,135 @@
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
@@ -1,19 +1,18 @@
1
1
  require 'rubygems'
2
2
  require 'test/unit'
3
3
 
4
- require "#{File.dirname(__FILE__)}/../../vendor/bundler_gems/environment"
5
-
6
4
  require 'shoulda'
5
+ require 'active_support'
6
+ require 'active_support/test_case'
7
+ require 'webmock'
8
+ require 'rr'
9
+
7
10
  begin
8
11
  require 'redgreen'
9
12
  rescue LoadError
10
13
  end
11
- require 'active_support'
12
- require 'active_support/test_case'
13
- require 'fakeweb'
14
- require 'rr'
15
14
 
16
- FakeWeb.allow_net_connect = false
15
+ WebMock.disable_net_connect!
17
16
 
18
17
  $:.unshift File.expand_path(File.join(File.dirname(__FILE__), ".."))
19
18
 
@@ -21,6 +20,11 @@ require "rubygems_plugin"
21
20
 
22
21
  class CommandTest < ActiveSupport::TestCase
23
22
  include RR::Adapters::TestUnit unless include?(RR::Adapters::TestUnit)
23
+ include WebMock
24
+
25
+ def teardown
26
+ reset_webmock
27
+ end
24
28
  end
25
29
 
26
30
  def stub_config(config)
@@ -28,3 +32,15 @@ def stub_config(config)
28
32
  config.each { |key, value| file[key] = value }
29
33
  stub(Gem).configuration { file }
30
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
@@ -0,0 +1,57 @@
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
+ WebMock.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
+ WebMock.assert_requested(:post, @url,
47
+ :times => 1)
48
+ WebMock.assert_requested(:post, @url,
49
+ :headers => { 'Authorization' => 'key' })
50
+ WebMock.assert_requested(:post, @url,
51
+ :headers => { 'Content-Length' => @gem_binary.size })
52
+ WebMock.assert_requested(:post, @url,
53
+ :headers => { 'Content-Type' => 'application/octet-stream' })
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,237 @@
1
+ require 'command_helper'
2
+
3
+ class WebhookCommandTest < CommandTest
4
+ context "webhooking" do
5
+ setup do
6
+ @gem = "foo"
7
+ @api = "https://gemcutter.org/api/v1/web_hooks"
8
+ @url = "http://example.com/hook"
9
+ @command = Gem::Commands::WebhookCommand.new
10
+ stub(@command).say
11
+ end
12
+
13
+ %w[-a --add -r --remove -f --fire].each do |option|
14
+ should "raise an error with no URL with #{option}" do
15
+ assert_raise OptionParser::MissingArgument do
16
+ @command.handle_options([@gem, option])
17
+ end
18
+ end
19
+ end
20
+
21
+ context "adding a specific hook" do
22
+ setup do
23
+ stub_config({ :rubygems_api_key => "key" })
24
+ stub_request(:post, @api).to_return(:body => "Success!")
25
+
26
+ @command.handle_options([@gem, "-a", @url])
27
+ @command.execute
28
+ end
29
+
30
+ should "say hook was added" do
31
+ assert_received(@command) do |command|
32
+ command.say("Adding webhook...")
33
+ command.say("Success!")
34
+ end
35
+ end
36
+
37
+ should "post to api" do
38
+ # webmock doesn't pass body params on correctly :[
39
+ assert_requested(:post, @api,
40
+ :times => 1)
41
+ assert_requested(:post, @api,
42
+ :headers => { 'Authorization' => 'key' })
43
+ end
44
+ end
45
+
46
+ context "adding a global hook" do
47
+ setup do
48
+ stub_config({ :rubygems_api_key => "key" })
49
+ stub_request(:post, @api).to_return(:body => "Success!")
50
+
51
+ @command.handle_options(["-g", "-a", @url])
52
+ @command.execute
53
+ end
54
+
55
+ should "say hook was added" do
56
+ assert_received(@command) do |command|
57
+ command.say("Adding webhook...")
58
+ command.say("Success!")
59
+ end
60
+ end
61
+
62
+ should "post to api" do
63
+ # webmock doesn't pass body params on correctly :[
64
+ assert_requested(:post, @api,
65
+ :times => 1)
66
+ assert_requested(:post, @api,
67
+ :headers => { 'Authorization' => 'key' })
68
+ end
69
+ end
70
+
71
+ context "listing hooks with some available" do
72
+ setup do
73
+ stub_config({ :rubygems_api_key => "key" })
74
+ stub_request(:get, @api).to_return :body => <<EOF
75
+ {
76
+ "foo": [{"url":"http://foogemhook.com","failure_count":0}],
77
+ "all gems":[{"url":"http://allgemshook.com","failure_count":0}]
78
+ }
79
+ EOF
80
+ end
81
+
82
+ should "list all hooks" do
83
+ @command.handle_options([])
84
+ @command.execute
85
+
86
+ assert_said(@command, "all gems:")
87
+ assert_said(@command, "- http://allgemshook.com")
88
+ assert_said(@command, "foo:")
89
+ assert_said(@command, "- http://foogemhook.com")
90
+ end
91
+
92
+ should "list only specific hooks" do
93
+ @command.handle_options(['foo'])
94
+ @command.execute
95
+
96
+ assert_said(@command, "foo:")
97
+ assert_said(@command, "- http://foogemhook.com")
98
+ assert_never_said(@command, "all gems:")
99
+ assert_never_said(@command, "- http://allgemshook.com")
100
+ end
101
+
102
+ should "list only global hooks" do
103
+ @command.handle_options(['-g'])
104
+ @command.execute
105
+
106
+ assert_said(@command, "all gems:")
107
+ assert_said(@command, "- http://allgemshook.com")
108
+ assert_never_said(@command, "foo:")
109
+ assert_never_said(@command, "- http://foogemhook.com")
110
+ end
111
+
112
+ should "send get to api" do
113
+ @command.handle_options([])
114
+ @command.execute
115
+
116
+ # webmock doesn't pass body params on correctly :[
117
+ assert_requested(:get, @api,
118
+ :times => 1)
119
+ assert_requested(:get, @api,
120
+ :headers => { 'Authorization' => 'key' })
121
+ end
122
+ end
123
+
124
+ context "listing hooks with none available" do
125
+ setup do
126
+ stub_config({ :rubygems_api_key => "key" })
127
+ stub_request(:get, @api).to_return(:body => "{}")
128
+ @command.handle_options([])
129
+ @command.execute
130
+ end
131
+
132
+ should "list hooks" do
133
+ assert_received(@command) do |command|
134
+ command.say("You haven't added any webhooks yet.")
135
+ end
136
+ end
137
+ end
138
+
139
+ context "listing hooks with a json error" do
140
+ setup do
141
+ stub(@command).terminate_interaction
142
+ stub_config({ :rubygems_api_key => "key" })
143
+ stub_request(:get, @api).to_return(:body => "fubar")
144
+ @command.handle_options([])
145
+ @command.execute
146
+ end
147
+
148
+ should "dump out with error message" do
149
+ assert_received(@command) do |command|
150
+ command.say("There was a problem parsing the data:")
151
+ command.say(/unexpected token at 'fubar'/)
152
+ end
153
+ end
154
+
155
+ should "terminate interaction" do
156
+ assert_received(@command) do |command|
157
+ command.terminate_interaction
158
+ end
159
+ end
160
+ end
161
+
162
+ context "removing specific hooks" do
163
+ setup do
164
+ stub_config({ :rubygems_api_key => "key" })
165
+ stub_request(:delete, "#{@api}/remove").to_return(:body => "Success!")
166
+
167
+ @command.handle_options([@gem, "-r", @url])
168
+ @command.execute
169
+ end
170
+
171
+ should "say hook was removed" do
172
+ assert_received(@command) do |command|
173
+ command.say("Removing webhook...")
174
+ command.say("Success!")
175
+ end
176
+ end
177
+
178
+ should "send delete to api" do
179
+ # webmock doesn't pass body params on correctly :[
180
+ assert_requested(:delete, "#{@api}/remove",
181
+ :times => 1)
182
+ assert_requested(:delete, "#{@api}/remove",
183
+ :headers => { 'Authorization' => 'key' })
184
+ end
185
+ end
186
+
187
+ context "removing global hooks" do
188
+ setup do
189
+ stub_config({ :rubygems_api_key => "key" })
190
+ stub_request(:delete, "#{@api}/remove").to_return(:body => "Success!")
191
+
192
+ @command.handle_options(["-g", "-r", @url])
193
+ @command.execute
194
+ end
195
+
196
+ should "say hook was removed" do
197
+ assert_received(@command) do |command|
198
+ command.say("Removing webhook...")
199
+ command.say("Success!")
200
+ end
201
+ end
202
+
203
+ should "send delete to api" do
204
+ # webmock doesn't pass body params on correctly :[
205
+ assert_requested(:delete, "#{@api}/remove",
206
+ :times => 1)
207
+ assert_requested(:delete, "#{@api}/remove",
208
+ :headers => { 'Authorization' => 'key' })
209
+ end
210
+ end
211
+
212
+ context "test firing hooks" do
213
+ setup do
214
+ stub_config({ :rubygems_api_key => "key" })
215
+ stub_request(:post, "#{@api}/fire").to_return(:body => "Success!")
216
+
217
+ @command.handle_options([@gem, "-f", @url])
218
+ @command.execute
219
+ end
220
+
221
+ should "say hook was fired" do
222
+ assert_received(@command) do |command|
223
+ command.say("Test firing webhook...")
224
+ command.say("Success!")
225
+ end
226
+ end
227
+
228
+ should "send post to api" do
229
+ # webmock doesn't pass body params on correctly :[
230
+ assert_requested(:post, "#{@api}/fire",
231
+ :times => 1)
232
+ assert_requested(:post, "#{@api}/fire",
233
+ :headers => { 'Authorization' => 'key' })
234
+ end
235
+ end
236
+ end
237
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gemcutter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0.pre
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Quaranto
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-12-10 00:00:00 -05:00
12
+ date: 2010-01-03 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -22,7 +22,57 @@ dependencies:
22
22
  - !ruby/object:Gem::Version
23
23
  version: "0"
24
24
  version:
25
- description: Adds several commands for using gemcutter.org, such as pushing new gems, migrating gems from RubyForge, and more.
25
+ - !ruby/object:Gem::Dependency
26
+ name: rake
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: shoulda
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: activesupport
47
+ type: :development
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "0"
54
+ version:
55
+ - !ruby/object:Gem::Dependency
56
+ name: webmock
57
+ type: :development
58
+ version_requirement:
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
65
+ - !ruby/object:Gem::Dependency
66
+ name: rr
67
+ type: :development
68
+ version_requirement:
69
+ version_requirements: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: "0"
74
+ version:
75
+ description: Adds several commands to RubyGems for managing gems and more on Gemcutter.org.
26
76
  email: nick@quaran.to
27
77
  executables: []
28
78
 
@@ -31,14 +81,21 @@ extensions: []
31
81
  extra_rdoc_files: []
32
82
 
33
83
  files:
84
+ - MIT-LICENSE
85
+ - Rakefile
34
86
  - lib/commands/abstract_command.rb
35
87
  - lib/commands/migrate.rb
36
88
  - lib/commands/owner.rb
37
89
  - lib/commands/push.rb
38
90
  - lib/commands/tumble.rb
91
+ - lib/commands/webhook.rb
39
92
  - lib/rubygems_plugin.rb
93
+ - test/abstract_command_test.rb
94
+ - test/command_helper.rb
95
+ - test/push_command_test.rb
96
+ - test/webhook_command_test.rb
40
97
  has_rdoc: true
41
- homepage: http://github.com/qrush/gemcutter
98
+ homepage: http://gemcutter.org
42
99
  licenses: []
43
100
 
44
101
  post_install_message: |+
@@ -49,6 +106,7 @@ post_install_message: |+
49
106
 
50
107
  gem push publish your gems for the world to use and enjoy
51
108
  gem owner allow/disallow others to push to your gems
109
+ gem webhook register urls to be pinged when gems are pushed
52
110
 
53
111
  ========================================================================
54
112
 
@@ -70,10 +128,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
70
128
  version:
71
129
  requirements: []
72
130
 
73
- rubyforge_project: gemcutter
131
+ rubyforge_project:
74
132
  rubygems_version: 1.3.5
75
133
  signing_key:
76
134
  specification_version: 3
77
135
  summary: Commands to interact with gemcutter.org
78
- test_files:
79
- - test/command_helper.rb
136
+ test_files: []
137
+