botanicus-gemcutter 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,115 @@
1
+ require 'rubygems/local_remote_options'
2
+
3
+ class Gem::AbstractCommand < Gem::Command
4
+ include Gem::LocalRemoteOptions
5
+
6
+ URL = "http://gemcutter.org"
7
+
8
+ def gemcutter_url
9
+ ENV['GEMCUTTER_URL'] || 'https://gemcutter.org'
10
+ end
11
+
12
+ def setup
13
+ use_proxy! if http_proxy
14
+ sign_in unless api_key
15
+ end
16
+
17
+ def sign_in
18
+ say "Enter your Gemcutter credentials. Don't have an account yet? Create one at #{URL}/sign_up"
19
+
20
+ email = ask("Email: ")
21
+ password = ask_for_password("Password: ")
22
+
23
+ response = make_request(:get, "api_key") do |request|
24
+ request.basic_auth email, password
25
+ end
26
+
27
+ case response
28
+ when Net::HTTPSuccess
29
+ self.api_key = response.body
30
+ say "Signed in. Your api key has been stored in ~/.gem/credentials"
31
+ else
32
+ say response.body
33
+ terminate_interaction
34
+ end
35
+ end
36
+
37
+ def credentials_path
38
+ File.join(Gem.user_home, '.gem', 'credentials')
39
+ end
40
+
41
+ def api_key
42
+ Gem.configuration.load_file(credentials_path)[:rubygems_api_key]
43
+ end
44
+
45
+ def api_key=(api_key)
46
+ config = Gem.configuration.load_file(credentials_path).merge(:rubygems_api_key => api_key)
47
+
48
+ dirname = File.dirname(credentials_path)
49
+ Dir.mkdir(dirname) unless File.exists?(dirname)
50
+
51
+ File.open(credentials_path, 'w') do |f|
52
+ f.write config.to_yaml
53
+ end
54
+
55
+ @rubygems_api_key = api_key
56
+ end
57
+
58
+ def make_request(method, path)
59
+ require 'net/http'
60
+
61
+ url = URI.parse("#{gemcutter_url}/api/v1/#{path}")
62
+
63
+ http = proxy_class.new(url.host, url.port)
64
+
65
+ if url.scheme == 'https'
66
+ require 'net/https'
67
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
68
+ http.use_ssl = true
69
+ end
70
+
71
+ request_method =
72
+ case method
73
+ when :get
74
+ proxy_class::Get
75
+ when :post
76
+ proxy_class::Post
77
+ when :put
78
+ proxy_class::Put
79
+ when :delete
80
+ proxy_class::Delete
81
+ else
82
+ raise ArgumentError
83
+ end
84
+
85
+ request = request_method.new(url.path)
86
+ request.add_field "User-Agent", "Gemcutter/0.2.0"
87
+
88
+ yield request if block_given?
89
+ http.request(request)
90
+ end
91
+
92
+ def use_proxy!
93
+ proxy_uri = http_proxy
94
+ @proxy_class = Net::HTTP::Proxy(proxy_uri.host, proxy_uri.port, proxy_uri.user, proxy_uri.password)
95
+ end
96
+
97
+ def proxy_class
98
+ @proxy_class || Net::HTTP
99
+ end
100
+
101
+ # @return [URI, nil] the HTTP-proxy as a URI if set; +nil+ otherwise
102
+ def http_proxy
103
+ proxy = Gem.configuration[:http_proxy] || ENV['http_proxy'] || ENV['HTTP_PROXY']
104
+ return nil if proxy.nil? || proxy == :no_proxy
105
+ URI.parse(proxy)
106
+ end
107
+
108
+ def ask_for_password(message)
109
+ system "stty -echo"
110
+ password = ask(message)
111
+ system "stty echo"
112
+ ui.say("\n")
113
+ password
114
+ end
115
+ end
@@ -0,0 +1,14 @@
1
+ class Gem::Commands::MigrateCommand < Gem::AbstractCommand
2
+ def description
3
+ 'Deprecate method for migrating a gem you own from Rubyforge to Gemcutter.'
4
+ end
5
+
6
+ def initialize
7
+ super 'migrate', description
8
+ end
9
+
10
+ def execute
11
+ say "This command is deprecated, RubyForge accounts/ownerships have been transferred to Gemcutter."
12
+ say "Please see http://gemcutter.org/pages/migrate for more information"
13
+ end
14
+ end
@@ -0,0 +1,89 @@
1
+ class Gem::Commands::OwnerCommand < Gem::AbstractCommand
2
+ def description
3
+ 'Manage gem owners on Gemcutter.'
4
+ end
5
+
6
+ def initialize
7
+ super 'owner', description
8
+ defaults.merge!(:add => [], :remove => [])
9
+
10
+ add_option('-a', '--add EMAIL', 'Add an owner') do |value, options|
11
+ options[:add] << value
12
+ end
13
+
14
+ add_option('-r', '--remove EMAIL', 'Remove an owner') do |value, options|
15
+ options[:remove] << value
16
+ end
17
+ end
18
+
19
+ def execute
20
+ setup
21
+ name = get_one_gem_name
22
+
23
+ add_owners name, options[:add]
24
+ remove_owners name, options[:remove]
25
+ show_owners name
26
+ end
27
+
28
+ def add_owners(name, owners)
29
+ owners.each do |owner|
30
+ response = make_request(:post, "gems/#{name}/owners.json") do |request|
31
+ request.set_form_data("email" => owner)
32
+ request.add_field("Authorization", api_key)
33
+ end
34
+
35
+ case response
36
+ when Net::HTTPSuccess
37
+ say "Added owner: #{owner}"
38
+ else
39
+ say "Error adding owner: #{owner}"
40
+ end
41
+ end
42
+ end
43
+
44
+ def remove_owners(name, owners)
45
+ owners.each do |owner|
46
+ response = make_request(:delete, "gems/#{name}/owners.json") do |request|
47
+ request.set_form_data(:email => owner)
48
+ request.add_field("Authorization", api_key)
49
+ end
50
+
51
+ case response
52
+ when Net::HTTPSuccess
53
+ say "Removed owner: #{owner}"
54
+ else
55
+ say "Error removing owner: #{owner}"
56
+ end
57
+ end end
58
+
59
+ def show_owners(name)
60
+ require 'json/pure'
61
+ response = make_request(:get, "gems/#{name}/owners.json") do |request|
62
+ request.add_field("Authorization", api_key)
63
+ end
64
+
65
+ case response
66
+ when Net::HTTPSuccess
67
+ begin
68
+ owners = JSON.parse(response.body)
69
+
70
+ say "Owners for gem: #{name}"
71
+ owners.each do |owner|
72
+ say "- #{owner['email']}"
73
+ end
74
+ rescue JSON::ParserError => json_error
75
+ say "There was a problem parsing the data: #{json_error}"
76
+ terminate_interaction
77
+ end
78
+ when Net::HTTPNotFound
79
+ say "This gem is currently not hosted on Gemcutter."
80
+ terminate_interaction
81
+ when Net::HTTPUnauthorized
82
+ say "You do not have permission to manage this gem."
83
+ terminate_interaction
84
+ else
85
+ say "There was a problem processing your request."
86
+ terminate_interaction
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,39 @@
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
+ name = get_one_gem_name
29
+ response = make_request(:post, "gems") do |request|
30
+ request.body = File.open(name, 'rb'){|io| io.read }
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
+
39
+ end
@@ -0,0 +1,13 @@
1
+ class Gem::Commands::TumbleCommand < Gem::AbstractCommand
2
+ def description
3
+ "Deprecated method of upgrading to Gemcutter.org for gem downloads"
4
+ end
5
+
6
+ def initialize
7
+ super 'tumble', description
8
+ end
9
+
10
+ def execute
11
+ say "This command is deprecated, Gemcutter.org is the primary source for gems."
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ $:.unshift File.dirname(__FILE__) # For use/testing when no gem is installed
2
+
3
+ require 'rubygems/command_manager'
4
+ require 'commands/abstract_command'
5
+
6
+ %w[migrate owner push tumble].each do |command|
7
+ require "commands/#{command}"
8
+ Gem::CommandManager.instance.register_command command.to_sym
9
+ end
@@ -0,0 +1,30 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+
4
+ require "#{File.dirname(__FILE__)}/../../vendor/bundler_gems/environment"
5
+
6
+ require 'shoulda'
7
+ begin
8
+ require 'redgreen'
9
+ rescue LoadError
10
+ end
11
+ require 'active_support'
12
+ require 'active_support/test_case'
13
+ require 'fakeweb'
14
+ require 'rr'
15
+
16
+ FakeWeb.allow_net_connect = false
17
+
18
+ $:.unshift File.expand_path(File.join(File.dirname(__FILE__), ".."))
19
+
20
+ require "rubygems_plugin"
21
+
22
+ class CommandTest < ActiveSupport::TestCase
23
+ include RR::Adapters::TestUnit unless include?(RR::Adapters::TestUnit)
24
+ end
25
+
26
+ def stub_config(config)
27
+ file = Gem::ConfigFile.new({})
28
+ config.each { |key, value| file[key] = value }
29
+ stub(Gem).configuration { file }
30
+ end
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: botanicus-gemcutter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
+ platform: ruby
6
+ authors:
7
+ - Nick Quaranto
8
+ - Jakub Stastny
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2009-12-10 00:00:00 +00:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: json_pure
18
+ type: :runtime
19
+ version_requirement:
20
+ version_requirements: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: "0"
25
+ version:
26
+ description: Adds several commands for using gemcutter.org, such as pushing new gems, migrating gems from RubyForge, and more.
27
+ email: nick@quaran.to
28
+ executables: []
29
+
30
+ extensions: []
31
+
32
+ extra_rdoc_files: []
33
+
34
+ files:
35
+ - lib/commands/abstract_command.rb
36
+ - lib/commands/migrate.rb
37
+ - lib/commands/owner.rb
38
+ - lib/commands/push.rb
39
+ - lib/commands/tumble.rb
40
+ - lib/rubygems_plugin.rb
41
+ has_rdoc: true
42
+ homepage: http://github.com/qrush/gemcutter
43
+ licenses: []
44
+
45
+ post_install_message: |+
46
+
47
+ ========================================================================
48
+
49
+ Thanks for installing Gemcutter! You can now run:
50
+
51
+ gem push publish your gems for the world to use and enjoy
52
+ gem owner allow/disallow others to push to your gems
53
+
54
+ ========================================================================
55
+
56
+ rdoc_options:
57
+ - --charset=UTF-8
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: "0"
65
+ version:
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: 1.3.5
71
+ version:
72
+ requirements: []
73
+
74
+ rubyforge_project: gemcutter
75
+ rubygems_version: 1.3.5
76
+ signing_key:
77
+ specification_version: 3
78
+ summary: Commands to interact with gemcutter.org
79
+ test_files:
80
+ - test/command_helper.rb