gemcutter 0.2.1 → 0.3.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/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
+