├── .gemtest ├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── Gemfile ├── MIT-LICENSE ├── README.md ├── Rakefile ├── gemcutter.gemspec ├── lib ├── gemcutter │ └── version.rb ├── rubygems │ └── commands │ │ ├── migrate_command.rb │ │ ├── tumble_command.rb │ │ ├── webhook_command.rb │ │ └── yank_command.rb └── rubygems_plugin.rb └── test ├── helper.rb ├── webhook_command_test.rb └── yank_command_test.rb /.gemtest: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubygems/gemcutter/b67e8dd866880c91f86d6104c7744612cff42f5a/.gemtest -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | *.sw[a-p] 4 | *.tmproj 5 | *.tmproject 6 | *.un~ 7 | *~ 8 | .DS_Store 9 | .Spotlight-V100 10 | .Trashes 11 | ._* 12 | .bundle 13 | .config 14 | .directory 15 | .elc 16 | .emacs.desktop 17 | .emacs.desktop.lock 18 | .redcar 19 | .yardoc 20 | Desktop.ini 21 | Gemfile.lock 22 | Icon? 23 | InstalledFiles 24 | Session.vim 25 | Thumbs.db 26 | \#*\# 27 | _yardoc 28 | auto-save-list 29 | coverage 30 | doc 31 | lib/bundler/man 32 | pkg 33 | pkg/* 34 | rdoc 35 | spec/reports 36 | test/tmp 37 | test/version_tmp 38 | tmp 39 | tmtags 40 | tramp 41 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | rvm: 2 | - 1.8.7 3 | - 1.9.2 4 | - 1.9.3 5 | - 2.0.0 6 | - 2.1.1 7 | - rbx-2 8 | - ree 9 | - jruby 10 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing 2 | In the spirit of [free software][free-sw], **everyone** is encouraged to help improve 3 | this project. 4 | 5 | [free-sw]: http://www.fsf.org/licensing/essays/free-sw.html 6 | 7 | Here are some ways *you* can contribute: 8 | 9 | * by using alpha, beta, and prerelease versions 10 | * by reporting bugs 11 | * by suggesting new features 12 | * by writing or editing documentation 13 | * by writing specifications 14 | * by writing code (**no patch is too small**: fix typos, add comments, clean up inconsistent whitespace) 15 | * by refactoring code 16 | * by closing [issues][] 17 | * by reviewing patches 18 | 19 | [issues]: https://github.com/rubygems/gemcutter/issues 20 | 21 | ## Submitting an Issue 22 | We use the [GitHub issue tracker][issues] to track bugs and features. Before 23 | submitting a bug report or feature request, check to make sure it hasn't 24 | already been submitted. You can indicate support for an existing issue by 25 | voting it up. When submitting a bug report, please include a [gist][] that 26 | includes a stack trace and any details that may be necessary to reproduce the 27 | bug, including your gem version, Ruby version, and operating system. Ideally, a 28 | bug report should include a pull request with failing specs. 29 | 30 | [gist]: https://gist.github.com/ 31 | 32 | ## Submitting a Pull Request 33 | 1. Fork the project. 34 | 2. Create a topic branch. 35 | 3. Implement your feature or bug fix. 36 | 4. Add tests for your feature or bug fix. 37 | 5. Run `bundle exec rake test`. If your changes are not 100% covered, go back 38 | to step 4. 39 | 6. Commit and push your changes. 40 | 7. Submit a pull request. Please do not include changes to the gemspec or 41 | version. (If you want to create your own version for some reason, please do 42 | so in a separate commit.) 43 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | platforms :jruby do 4 | gem 'jruby-openssl', '~> 0.7' 5 | end 6 | 7 | gemspec 8 | 9 | # Backwards compatibilities 10 | gem 'activesupport', '~> 3.2.18' if RUBY_VERSION < '1.9.3' 11 | gem 'shoulda-matchers', '~> 2.0.0' if RUBY_VERSION < '1.9.2' 12 | -------------------------------------------------------------------------------- /MIT-LICENSE: -------------------------------------------------------------------------------- 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. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gemcutter 2 | [![Build Status](https://secure.travis-ci.org/rubygems/gemcutter.png?branch=master)][travis] 3 | [![Dependency Status](https://gemnasium.com/rubygems/gemcutter.png?travis)][gemnasium] 4 | [![Code Climate](https://codeclimate.com/badge.png)][codeclimate] 5 | 6 | This repository now contains only the `gemcutter` gem, which provides `gem 7 | yank` and `gem webhook`. The Rails app has moved to 8 | [rubygems/rubygems.org][rubygems]. Please update your links and remotes! 9 | 10 | [travis]: http://travis-ci.org/rubygems/gemcutter 11 | [gemnasium]: https://gemnasium.com/rubygems/gemcutter 12 | [codeclimate]: https://codeclimate.com/github/rubygems/gemcutter 13 | [rubygems]: https://github.com/rubygems/rubygems.org 14 | 15 | ## Installation 16 | gem install gemcutter 17 | 18 | ## Supported Ruby Versions 19 | This library aims to support and is [tested against][travis] the following Ruby 20 | implementations: 21 | 22 | * Ruby 1.8.7 23 | * Ruby 1.9.2 24 | * Ruby 1.9.3 25 | * Ruby 2.0.0 26 | * Ruby 2.1.1 27 | * [JRuby][] 28 | * [Rubinius][] 29 | * [Ruby Enterprise Edition][ree] 30 | 31 | [jruby]: http://www.jruby.org/ 32 | [rubinius]: http://rubini.us/ 33 | [ree]: http://www.rubyenterpriseedition.com/ 34 | 35 | If something doesn't work on one of these interpreters, it should be considered 36 | a bug. 37 | 38 | This library may inadvertently work (or seem to work) on other Ruby 39 | implementations, however support will only be provided for the versions listed 40 | above. 41 | 42 | If you would like this library to support another Ruby version, you may 43 | volunteer to be a maintainer. Being a maintainer entails making sure all tests 44 | run and pass on that implementation. When something breaks on your 45 | implementation, you will be personally responsible for providing patches in a 46 | timely fashion. If critical issues for a particular implementation exist at the 47 | time of a major release, support for that Ruby version may be dropped. 48 | 49 | ## License 50 | 51 | Gemcutter is released under the MIT license. Please check the [LICENSE][] file 52 | for more details. 53 | 54 | [license]: https://github.com/rubygems/gemcutter/blob/master/MIT-LICENSE 55 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env rake 2 | 3 | require 'bundler' 4 | Bundler::GemHelper.install_tasks 5 | 6 | task :default => :test 7 | 8 | require 'rake/testtask' 9 | Rake::TestTask.new(:test) do |t| 10 | t.libs << "test" 11 | t.test_files = FileList['test/*_test.rb'] 12 | t.verbose = true 13 | end 14 | -------------------------------------------------------------------------------- /gemcutter.gemspec: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | require File.expand_path('../lib/gemcutter/version', __FILE__) 3 | 4 | Gem::Specification.new do |gem| 5 | gem.add_development_dependency 'activesupport' 6 | gem.add_development_dependency 'i18n' 7 | gem.add_development_dependency 'rake' 8 | gem.add_development_dependency 'rr' 9 | gem.add_development_dependency 'shoulda' 10 | gem.add_development_dependency 'webmock' 11 | gem.authors = ["Nick Quaranto"] 12 | gem.description = %q{Provides the `gem yank` and `gem webhook` commands to RubyGems.} 13 | gem.email = ['nick@quaran.to'] 14 | gem.files = Dir['Gemfile', 'MIT-LICENSE', 'README.md', 'Rakefile', 'lib/**/*', 'test/**/*'] 15 | gem.homepage = 'http://rubygems.org' 16 | gem.name = 'gemcutter' 17 | gem.post_install_message =< error 103 | say "There was a problem parsing the data:" 104 | say error.to_s 105 | terminate_interaction 106 | end 107 | end 108 | end 109 | 110 | def make_webhook_request(method, name, url, api = "api/v1/web_hooks") 111 | response = rubygems_api_request(method, api) do |request| 112 | request.set_form_data("gem_name" => name, "url" => url) 113 | request.add_field("Authorization", Gem.configuration.rubygems_api_key) 114 | end 115 | 116 | with_response(response) 117 | end 118 | end 119 | -------------------------------------------------------------------------------- /lib/rubygems/commands/yank_command.rb: -------------------------------------------------------------------------------- 1 | require 'rubygems/local_remote_options' 2 | require 'rubygems/version_option' 3 | require 'rubygems/gemcutter_utilities' 4 | require 'rubygems/command' 5 | 6 | class Gem::Commands::YankCommand < Gem::Command 7 | include Gem::LocalRemoteOptions 8 | include Gem::VersionOption 9 | include Gem::GemcutterUtilities 10 | 11 | def description 12 | 'Remove a specific gem version release from RubyGems.org' 13 | end 14 | 15 | def arguments 16 | "GEM name of gem" 17 | end 18 | 19 | def usage 20 | "#{program_name} GEM -v VERSION [-p PLATFORM] [--undo] [--key KEY_NAME]" 21 | end 22 | 23 | def initialize 24 | super 'yank', description 25 | add_version_option("remove") 26 | add_platform_option("remove") 27 | add_option('--undo') do |value, options| 28 | options[:undo] = true 29 | end 30 | 31 | add_option('-k', '--key KEY_NAME', 32 | 'Use API key from your gem credentials file') do |value, options| 33 | options[:key] = value 34 | end 35 | end 36 | 37 | def execute 38 | sign_in 39 | version = get_version_from_requirements(options[:version]) 40 | platform = get_platform_from_requirements(options) 41 | api_key = Gem.configuration.rubygems_api_key 42 | api_key = Gem.configuration.api_keys[options[:key].to_sym] if options[:key] 43 | 44 | if !version.nil? 45 | if options[:undo] 46 | unyank_gem(version, platform, api_key) 47 | else 48 | yank_gem(version, platform, api_key) 49 | end 50 | else 51 | say "A version argument is required: #{usage}" 52 | terminate_interaction 53 | end 54 | end 55 | 56 | def yank_gem(version, platform, api_key) 57 | say "Yanking gem from RubyGems.org..." 58 | yank_api_request(:delete, version, platform, "api/v1/gems/yank", api_key) 59 | end 60 | 61 | def unyank_gem(version, platform, api_key) 62 | say "Unyanking gem from RubyGems.org..." 63 | yank_api_request(:put, version, platform, "api/v1/gems/unyank", api_key) 64 | end 65 | 66 | private 67 | def yank_api_request(method, version, platform, api, api_key) 68 | name = get_one_gem_name 69 | response = rubygems_api_request(method, api) do |request| 70 | request.add_field("Authorization", api_key) 71 | request.set_form_data({'gem_name' => name, 'version' => version, 'platform' => platform}) 72 | end 73 | say response.body 74 | end 75 | 76 | def get_version_from_requirements(requirements) 77 | begin 78 | requirements.requirements.first[1].version 79 | rescue 80 | nil 81 | end 82 | end 83 | 84 | def get_platform_from_requirements(requirements) 85 | Gem.platforms[1].to_s if requirements.key? :added_platform 86 | end 87 | end 88 | -------------------------------------------------------------------------------- /lib/rubygems_plugin.rb: -------------------------------------------------------------------------------- 1 | require 'rubygems/command_manager' 2 | 3 | if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.3.6') 4 | %w[migrate tumble webhook yank].each do |command| 5 | Gem::CommandManager.instance.register_command command.to_sym 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /test/helper.rb: -------------------------------------------------------------------------------- 1 | require 'rubygems/commands/webhook_command' 2 | require 'rubygems/commands/yank_command' 3 | require 'shoulda' 4 | require 'active_support' 5 | require 'active_support/test_case' 6 | require 'webmock' 7 | require 'rr' 8 | 9 | # Backwards compatability for older versions of ActiveSupport 10 | defined?(Minitest) ? (require 'minitest/autorun') : (require 'test/unit') 11 | 12 | WebMock.disable_net_connect! 13 | 14 | class CommandTest < ActiveSupport::TestCase 15 | include RR::Adapters::TestUnit unless include?(RR::Adapters::TestUnit) 16 | include WebMock::API 17 | 18 | def teardown 19 | WebMock.reset! 20 | end 21 | end 22 | 23 | def stub_api_key(api_key) 24 | file = Gem::ConfigFile.new({}) 25 | stub(file).rubygems_api_key { api_key } 26 | yield file if block_given? 27 | stub(Gem).configuration { file } 28 | end 29 | 30 | def assert_said(command, what) 31 | assert_received(command) do |command| 32 | command.say(what) 33 | end 34 | end 35 | 36 | def assert_never_said(command, what) 37 | assert_received(command) do |command| 38 | command.say(what).never 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /test/webhook_command_test.rb: -------------------------------------------------------------------------------- 1 | require 'helper' 2 | 3 | class WebhookCommandTest < CommandTest 4 | context "webhooking" do 5 | setup do 6 | @gem = "foo" 7 | @api = "https://rubygems.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_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_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_api_key("key") 74 | stub_request(:get, "#{@api}.yaml").to_return :body => < 1) 123 | assert_requested(:get, "#{@api}.yaml", 124 | :headers => { 'Authorization' => 'key' }) 125 | end 126 | end 127 | 128 | context "listing hooks with none available" do 129 | setup do 130 | stub_api_key("key") 131 | stub_request(:get, "#{@api}.yaml").to_return(:body => "{}") 132 | @command.handle_options([]) 133 | @command.execute 134 | end 135 | 136 | should "list hooks" do 137 | assert_received(@command) do |command| 138 | command.say("You haven't added any webhooks yet.") 139 | end 140 | end 141 | end 142 | 143 | context "listing hooks with a json error" do 144 | setup do 145 | stub(@command).terminate_interaction 146 | stub_api_key("key") 147 | stub_request(:get, "#{@api}.yaml").to_return(:body => "fubar") 148 | @command.handle_options([]) 149 | @command.execute 150 | end 151 | 152 | should "dump out with error message" do 153 | assert_received(@command) do |command| 154 | command.say("There was a problem parsing the data:") 155 | end 156 | end 157 | 158 | should "terminate interaction" do 159 | assert_received(@command) do |command| 160 | command.terminate_interaction 161 | end 162 | end 163 | end 164 | 165 | context "removing specific hooks" do 166 | setup do 167 | stub_api_key("key") 168 | stub_request(:delete, "#{@api}/remove").to_return(:body => "Success!") 169 | 170 | @command.handle_options([@gem, "-r", @url]) 171 | @command.execute 172 | end 173 | 174 | should "say hook was removed" do 175 | assert_received(@command) do |command| 176 | command.say("Removing webhook...") 177 | command.say("Success!") 178 | end 179 | end 180 | 181 | should "send delete to api" do 182 | # webmock doesn't pass body params on correctly :[ 183 | assert_requested(:delete, "#{@api}/remove", 184 | :times => 1) 185 | assert_requested(:delete, "#{@api}/remove", 186 | :headers => { 'Authorization' => 'key' }) 187 | end 188 | end 189 | 190 | context "removing global hooks" do 191 | setup do 192 | stub_api_key("key") 193 | stub_request(:delete, "#{@api}/remove").to_return(:body => "Success!") 194 | 195 | @command.handle_options(["-g", "-r", @url]) 196 | @command.execute 197 | end 198 | 199 | should "say hook was removed" do 200 | assert_received(@command) do |command| 201 | command.say("Removing webhook...") 202 | command.say("Success!") 203 | end 204 | end 205 | 206 | should "send delete to api" do 207 | # webmock doesn't pass body params on correctly :[ 208 | assert_requested(:delete, "#{@api}/remove", 209 | :times => 1) 210 | assert_requested(:delete, "#{@api}/remove", 211 | :headers => { 'Authorization' => 'key' }) 212 | end 213 | end 214 | 215 | context "test firing hooks" do 216 | setup do 217 | stub_api_key("key") 218 | stub_request(:post, "#{@api}/fire").to_return(:body => "Success!") 219 | 220 | @command.handle_options([@gem, "-f", @url]) 221 | @command.execute 222 | end 223 | 224 | should "say hook was fired" do 225 | assert_received(@command) do |command| 226 | command.say("Test firing webhook...") 227 | command.say("Success!") 228 | end 229 | end 230 | 231 | should "send post to api" do 232 | # webmock doesn't pass body params on correctly :[ 233 | assert_requested(:post, "#{@api}/fire", 234 | :times => 1) 235 | assert_requested(:post, "#{@api}/fire", 236 | :headers => { 'Authorization' => 'key' }) 237 | end 238 | end 239 | end 240 | end 241 | -------------------------------------------------------------------------------- /test/yank_command_test.rb: -------------------------------------------------------------------------------- 1 | require 'helper' 2 | 3 | class YankCommandTest < CommandTest 4 | context "yanking" do 5 | setup do 6 | @gem = "MyGem" 7 | @version = '0.1.0' 8 | @platform = nil 9 | @command = Gem::Commands::YankCommand.new 10 | stub(@command).say 11 | end 12 | 13 | %w[-v --version -p --platform].each do |option| 14 | should "raise an error with no version with #{option}" do 15 | assert_raise OptionParser::MissingArgument do 16 | @command.handle_options([@gem, option]) 17 | end 18 | end 19 | end 20 | 21 | context 'yanking a gem' do 22 | setup do 23 | @api_key = "key" 24 | stub_api_key(@api_key) 25 | @api = "https://rubygems.org/api/v1/gems/yank" 26 | stub_request(:delete, @api).to_return(:body => "Successfully yanked") 27 | @command.handle_options([@gem, "-v", @version]) 28 | end 29 | 30 | should 'say gem was yanked' do 31 | @command.execute 32 | assert_received(@command) do |command| 33 | command.say("Yanking gem from Gemcutter...") 34 | command.say("Successfully yanked") 35 | end 36 | end 37 | 38 | should 'invoke yank_gem' do 39 | stub(@command).yank_gem(@version, @platform, @api_key) 40 | @command.execute 41 | assert_received(@command) do |command| 42 | command.yank_gem(@version, @platform, @api_key) 43 | end 44 | end 45 | 46 | should 'delete to api' do 47 | @command.execute 48 | assert_requested(:delete, @api, 49 | :times => 1) 50 | assert_requested(:delete, @api, 51 | :headers => { 'Authorization' => 'key' }) 52 | end 53 | 54 | should 'use given API key' do 55 | other_key = 'another_key' 56 | 57 | stub_api_key('key') {|config| stub(config).api_keys {{:another_name => other_key}}} 58 | 59 | @command.handle_options([@gem, "-v", @version, "-k", "another_name"]) 60 | @command.execute 61 | assert_requested(:delete, @api, 62 | :times => 1) 63 | assert_requested(:delete, @api, 64 | :headers => { 'Authorization' => other_key }) 65 | end 66 | 67 | context 'with a platform specified' do 68 | setup do 69 | stub_api_key("key") 70 | @api = "https://rubygems.org/api/v1/gems/yank" 71 | @platform = "x86-darwin-10" 72 | stub_request(:delete, @api).to_return(:body => "Successfully yanked") 73 | @command.handle_options([@gem, "-v", @version, "-p", @platform]) 74 | end 75 | 76 | should 'say gem was yanked' do 77 | @command.execute 78 | assert_received(@command) do |command| 79 | command.say("Yanking gem from Gemcutter...") 80 | command.say("Successfully yanked") 81 | end 82 | end 83 | 84 | should 'invoke yank_gem' do 85 | stub(@command).yank_gem(@version, @platform, @api_key) 86 | @command.execute 87 | assert_received(@command) do |command| 88 | command.yank_gem(@version, @platform, @api_key) 89 | end 90 | end 91 | end 92 | 93 | end 94 | 95 | context 'unyanking a gem' do 96 | setup do 97 | @api_key = "key" 98 | stub_api_key(@api_key) 99 | @api = "https://rubygems.org/api/v1/gems/unyank" 100 | stub_request(:put, @api).to_return(:body => "Successfully unyanked") 101 | @command.handle_options([@gem, "-v", @version, "--undo"]) 102 | end 103 | 104 | should 'say gem was unyanked' do 105 | @command.execute 106 | assert_received(@command) do |command| 107 | command.say("Re-indexing gem") 108 | command.say("Successfully unyanked") 109 | end 110 | end 111 | 112 | should 'invoke unyank_gem' do 113 | stub(@command).unyank_gem(@version, @platform, @api_key) 114 | @command.execute 115 | assert_received(@command) do |command| 116 | command.unyank_gem(@version, @platform, @api_key) 117 | end 118 | end 119 | 120 | should 'put to api' do 121 | @command.execute 122 | assert_requested(:put, @api, :times => 1) 123 | assert_requested(:put, @api, :headers => { 'Authorization' => 'key' }) 124 | end 125 | end 126 | 127 | 128 | context 'with a platform specified' do 129 | setup do 130 | @api_key = 'key' 131 | stub_api_key(@api_key) 132 | @api = "https://rubygems.org/api/v1/gems/unyank" 133 | @platform = "x86-darwin-10" 134 | stub_request(:put, @api).to_return(:body => "Successfully unyanked") 135 | @command.handle_options([@gem, "-v", @version, "-p", @platform, "--undo"]) 136 | end 137 | 138 | should 'say gem was unyanked' do 139 | @command.execute 140 | assert_received(@command) do |command| 141 | command.say("Re-indexing gem") 142 | command.say("Successfully unyanked") 143 | end 144 | end 145 | 146 | should 'invoke unyank_gem' do 147 | stub(@command).unyank_gem(@version, @platform, @api_key) 148 | @command.execute 149 | assert_received(@command) do |command| 150 | command.unyank_gem(@version, @platform, @api_key) 151 | end 152 | end 153 | end 154 | 155 | end 156 | 157 | end 158 | --------------------------------------------------------------------------------