nexus 0.1.0

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.
@@ -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.
@@ -0,0 +1,10 @@
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
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'bundler/monkey_patch'
4
+
5
+ load Gem.bin_path('bundler', 'bundle')
@@ -0,0 +1,21 @@
1
+ require 'bundler/fetcher'
2
+ require 'bundler/rubygems_integration'
3
+ require 'bundler/rubygems_mirror'
4
+ module Bundler
5
+ class RubygemsIntegration
6
+ def download_gem(spec, uri, path)
7
+ uri = RubygemsMirror.to_uri(uri)
8
+ Gem::RemoteFetcher.fetcher.download(spec, uri, path)
9
+ end
10
+ end
11
+ end
12
+ module Bundler
13
+ # Handles all the fetching with the rubygems server
14
+ class Fetcher
15
+ def initialize(remote_uri)
16
+ @remote_uri = RubygemsMirror.to_uri(remote_uri)
17
+ @has_api = true # will be set to false if the rubygems index is ever fetched
18
+ @@connection ||= Net::HTTP::Persistent.new nil, :ENV
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,27 @@
1
+ module Bundler
2
+ class RubygemsMirror
3
+
4
+ private
5
+
6
+ def self.mirrors
7
+ @mirrors ||= Bundler.settings.all.inject({}) do |h, k|
8
+ if k =~ /^mirror./
9
+ uri = add_slash(k.sub(/^mirror./, ''))
10
+ h[uri] = URI.parse(Bundler.settings[k])
11
+ end
12
+ h
13
+ end
14
+ end
15
+
16
+ def self.add_slash(uri)
17
+ uri = uri.to_s
18
+ uri =~ /\/$/ ? uri : uri + '/'
19
+ end
20
+
21
+ public
22
+
23
+ def self.to_uri(uri)
24
+ mirrors[add_slash(uri)] || uri
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,124 @@
1
+ require 'rubygems/local_remote_options'
2
+ begin
3
+ require 'always_verify_ssl_certificates'
4
+ rescue LoadError
5
+ warn 'skip "always_verify_ssl_certificates"'
6
+ end
7
+ require 'base64'
8
+
9
+ class Gem::AbstractCommand < Gem::Command
10
+ include Gem::LocalRemoteOptions
11
+
12
+ def url
13
+ url = config[:url]
14
+ # no leadng slash
15
+ url.sub!(/\/$/,'') if url
16
+ url
17
+ end
18
+
19
+ def configure_url
20
+ say "Enter the URL of the rubygems repository on a Nexus server"
21
+
22
+ url = ask("URL: ")
23
+
24
+ store_config(:url, url)
25
+
26
+ say "The Nexus URL has been stored in ~/.gem/nexus"
27
+ end
28
+
29
+ def setup
30
+ use_proxy! if http_proxy
31
+ configure_url unless url
32
+ sign_in unless authorization
33
+ end
34
+
35
+ def sign_in
36
+ say "Enter your Nexus credentials"
37
+ username = ask("Username: ")
38
+ password = ask_for_password("Password: ")
39
+
40
+ store_config(:authorization,
41
+ "Basic #{Base64.encode64(username + ':' + password).strip}")
42
+
43
+ say "Your Nexus credentials has been stored in ~/.gem/nexus"
44
+ end
45
+
46
+ def config_path
47
+ File.join(Gem.user_home, '.gem', 'nexus')
48
+ end
49
+
50
+ def config
51
+ @config ||= Gem.configuration.load_file(config_path)
52
+ end
53
+
54
+ def authorization
55
+ config[:authorization]
56
+ end
57
+
58
+ def store_config(key, value)
59
+ config.merge!(key => value)
60
+ dirname = File.dirname(config_path)
61
+ Dir.mkdir(dirname) unless File.exists?(dirname)
62
+
63
+ File.open(config_path, 'w') do |f|
64
+ f.write config.to_yaml
65
+ end
66
+ end
67
+
68
+ def make_request(method, path)
69
+ require 'net/http'
70
+ require 'net/https'
71
+
72
+ url = URI.parse("#{self.url}/#{path}")
73
+
74
+ http = proxy_class.new(url.host, url.port)
75
+
76
+ if url.scheme == 'https'
77
+ http.use_ssl = true
78
+ end
79
+
80
+ request_method =
81
+ case method
82
+ when :get
83
+ proxy_class::Get
84
+ when :post
85
+ proxy_class::Post
86
+ when :put
87
+ proxy_class::Put
88
+ when :delete
89
+ proxy_class::Delete
90
+ else
91
+ raise ArgumentError
92
+ end
93
+
94
+ request = request_method.new(url.path)
95
+ request.add_field "User-Agent", "Nexus Gem Command"
96
+
97
+ yield request if block_given?
98
+ http.request(request)
99
+ end
100
+
101
+ def use_proxy!
102
+ proxy_uri = http_proxy
103
+ @proxy_class = Net::HTTP::Proxy(proxy_uri.host, proxy_uri.port, proxy_uri.user, proxy_uri.password)
104
+ end
105
+
106
+ def proxy_class
107
+ @proxy_class || Net::HTTP
108
+ end
109
+
110
+ # @return [URI, nil] the HTTP-proxy as a URI if set; +nil+ otherwise
111
+ def http_proxy
112
+ proxy = Gem.configuration[:http_proxy] || ENV['http_proxy'] || ENV['HTTP_PROXY']
113
+ return nil if proxy.nil? || proxy == :no_proxy
114
+ URI.parse(proxy)
115
+ end
116
+
117
+ def ask_for_password(message)
118
+ system "stty -echo"
119
+ password = ask(message)
120
+ system "stty echo"
121
+ ui.say("\n")
122
+ password
123
+ end
124
+ end
@@ -0,0 +1,48 @@
1
+ class Gem::Commands::NexusCommand < Gem::AbstractCommand
2
+
3
+ def description
4
+ 'Push a gem up to Nexus server'
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 Nexus..."
27
+
28
+ path = get_one_gem_name
29
+
30
+ response = make_request(:post, "gems/#{File.basename(path)}") do |request|
31
+ request.body = Gem.read_binary(path)
32
+ request.add_field("Content-Length", request.body.size)
33
+ request.add_field("Content-Type", "application/octet-stream")
34
+ request.add_field("Authorization", authorization.strip)
35
+ end
36
+
37
+ case response.code
38
+ when "401"
39
+ say "Unauthorized"
40
+ when "400"
41
+ say "something went wrong - maybe (re)deployment is not allowed"
42
+ when "500"
43
+ say "something went wrong"
44
+ else
45
+ say response.message
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,6 @@
1
+ require 'rubygems/command_manager'
2
+ require 'commands/abstract_command'
3
+
4
+ require "commands/nexus"
5
+ Gem::CommandManager.instance.register_command :nexus
6
+
@@ -0,0 +1,134 @@
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 authorization and no nexus url" do
52
+ stub(@command).authorization { nil }
53
+ stub(@command).url { nil }
54
+ stub(@command).sign_in
55
+ stub(@command).configure_url
56
+ @command.setup
57
+ assert_received(@command) { |command| command.configure_url }
58
+ assert_received(@command) { |command| command.sign_in }
59
+ end
60
+
61
+ should "not sign in nor configure if authorizaton and url exists" do
62
+ stub(@command).authorization { "1234567890" }
63
+ stub(@command).url { "abc" }
64
+ stub(@command).sign_in
65
+ stub(@command).configure_url
66
+ @command.setup
67
+ assert_received(@command) { |command| command.configure_url.never }
68
+ assert_received(@command) { |command| command.sign_in.never }
69
+ end
70
+
71
+ context "using the proxy" do
72
+ setup do
73
+ stub_config(:http_proxy => "http://gilbert:sekret@proxy.example.org:8081")
74
+ @proxy_class = Object.new
75
+ mock(Net::HTTP).Proxy('proxy.example.org', 8081, 'gilbert', 'sekret') { @proxy_class }
76
+ @command.use_proxy!
77
+ end
78
+
79
+ should "replace Net::HTTP with a proxy version" do
80
+ assert_equal @proxy_class, @command.proxy_class
81
+ end
82
+ end
83
+
84
+ context "signing in" do
85
+ setup do
86
+ @username = "username"
87
+ @password = "password"
88
+ @key = "key"
89
+
90
+ stub(@command).say
91
+ stub(@command).ask { @username }
92
+ stub(@command).ask_for_password { @password }
93
+ stub(@command).store_config { {:authorization => @key} }
94
+ end
95
+
96
+ should "ask for username and password" do
97
+ @command.sign_in
98
+ assert_received(@command) { |command| command.ask("Username: ") }
99
+ assert_received(@command) { |command| command.ask_for_password("Password: ") }
100
+ assert_received(@command) { |command| command.store_config(:authorization, "Basic dXNlcm5hbWU6cGFzc3dvcmQ=") }
101
+ end
102
+
103
+ should "say that we signed in" do
104
+ @command.sign_in
105
+ assert_received(@command) { |command| command.say("Enter your Nexus credentials") }
106
+ assert_received(@command) { |command| command.say("Your Nexus credentials has been stored in ~/.gem/nexus") }
107
+ assert_received(@command) { |command| command.store_config(:authorization, "Basic dXNlcm5hbWU6cGFzc3dvcmQ=") }
108
+ end
109
+ end
110
+
111
+ context "configure nexus url" do
112
+ setup do
113
+ @url = "url"
114
+
115
+ stub(@command).say
116
+ stub(@command).ask { @url }
117
+ stub(@command).store_config { {:url => @url} }
118
+ end
119
+
120
+ should "ask for nexus url" do
121
+ @command.configure_url
122
+ assert_received(@command) { |command| command.ask("URL: ") }
123
+ assert_received(@command) { |command| command.store_config(:url, "url") }
124
+ end
125
+
126
+ should "say that we configured the url" do
127
+ @command.configure_url
128
+ assert_received(@command) { |command| command.say("Enter the URL of the rubygems repository on a Nexus server") }
129
+ assert_received(@command) { |command| command.say("The Nexus URL has been stored in ~/.gem/nexus") }
130
+ assert_received(@command) { |command| command.store_config(:url, "url") }
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,46 @@
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::API
24
+
25
+ def teardown
26
+ WebMock.reset!
27
+ end
28
+ end
29
+
30
+ def stub_config(config)
31
+ # file = Gem::ConfigFile.new({})
32
+ #xs config.each { |key, value| file[key] = value }
33
+ # stub(:config).configuration { config }
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,62 @@
1
+ require 'command_helper'
2
+
3
+ class NexusCommandTest < CommandTest
4
+ context "pushing" do
5
+ setup do
6
+ @command = Gem::Commands::NexusCommand.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
+
27
+ @gem_path = "path/to/foo-0.0.0.gem"
28
+ baseurl = 'http://localhost:8081/nexus/content/repositories/localgems'
29
+ @url = baseurl + @gem_path.sub(/.*\//, '/gems/')
30
+ @gem_binary = StringIO.new("gem")
31
+
32
+ stub(@command).say
33
+ stub(@command).options { {:args => [@gem_path]} }
34
+ stub(Gem).read_binary(@gem_path) { @gem_binary }
35
+ stub(@command).config { { :authorization => "key", :url => baseurl } }
36
+ stub_request(:post, @url).to_return(:status => 201)
37
+
38
+ @command.send_gem
39
+ end
40
+
41
+ should "say push was successful" do
42
+ assert_received(@command) { |command| command.say("Pushing gem to Nexus...") }
43
+ # due to webmock there is no status message
44
+ assert_received(@command) { |command| command.say("") }
45
+ end
46
+
47
+ should "post to api" do
48
+ # webmock doesn't pass body params on correctly :[
49
+ assert_requested(:post, @url,
50
+ :times => 1)
51
+ assert_requested(:post, @url,
52
+ :headers => {
53
+ 'Authorization' => 'key',
54
+ 'Content-Type' => 'application/octet-stream',
55
+ 'User-Agent'=>'Nexus Gem Command'
56
+ })
57
+ #assert_requested(:post, @url,
58
+ # :headers => {'Content-Length' => @gem_binary.size.to_s})
59
+ end
60
+ end
61
+ end
62
+ end
metadata ADDED
@@ -0,0 +1,135 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nexus
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.0
6
+ platform: ruby
7
+ authors:
8
+ - Nick Quaranto
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2012-08-17 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: always_verify_ssl_certificates
17
+ prerelease: false
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ~>
22
+ - !ruby/object:Gem::Version
23
+ version: 0.3.0
24
+ type: :runtime
25
+ version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
27
+ name: rake
28
+ prerelease: false
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - "="
33
+ - !ruby/object:Gem::Version
34
+ version: 0.9.2.2
35
+ type: :development
36
+ version_requirements: *id002
37
+ - !ruby/object:Gem::Dependency
38
+ name: shoulda
39
+ prerelease: false
40
+ requirement: &id003 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 3.1.1
46
+ type: :development
47
+ version_requirements: *id003
48
+ - !ruby/object:Gem::Dependency
49
+ name: webmock
50
+ prerelease: false
51
+ requirement: &id004 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ~>
55
+ - !ruby/object:Gem::Version
56
+ version: 1.8.8
57
+ type: :development
58
+ version_requirements: *id004
59
+ - !ruby/object:Gem::Dependency
60
+ name: rr
61
+ prerelease: false
62
+ requirement: &id005 !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "0"
68
+ type: :development
69
+ version_requirements: *id005
70
+ description: Adds a command to RubyGems for uploading gems to a nexus server.
71
+ email:
72
+ - nick@quaran.to
73
+ executables:
74
+ - nbundle
75
+ extensions: []
76
+
77
+ extra_rdoc_files: []
78
+
79
+ files:
80
+ - MIT-LICENSE
81
+ - Rakefile
82
+ - bin/nbundle
83
+ - lib/rubygems_plugin.rb
84
+ - lib/commands/nexus.rb
85
+ - lib/commands/abstract_command.rb
86
+ - lib/bundler/monkey_patch.rb
87
+ - lib/bundler/rubygems_mirror.rb
88
+ - test/abstract_command_test.rb
89
+ - test/command_helper.rb
90
+ - test/nexus_command_test.rb
91
+ homepage: https://github.com/sonatype/nexus-ruby-support/tree/master/nexus-gem
92
+ licenses: []
93
+
94
+ post_install_message: |+
95
+
96
+ ========================================================================
97
+
98
+ Thanks for installing Nexus gem! You can now run:
99
+
100
+ gem nexus publish your gems onto Nexus server
101
+
102
+ nbundle a bundler fork with mirror support.
103
+ just add a mirror with:
104
+
105
+ bundle config mirror.http://rubygems.org http://localhost:8081/nexus/content/repositories/rubygems.org
106
+
107
+ and use 'nbundle' instead of 'bundle'
108
+
109
+ ========================================================================
110
+
111
+ rdoc_options: []
112
+
113
+ require_paths:
114
+ - lib
115
+ required_ruby_version: !ruby/object:Gem::Requirement
116
+ none: false
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: "0"
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: "0"
127
+ requirements: []
128
+
129
+ rubyforge_project:
130
+ rubygems_version: 1.8.24
131
+ signing_key:
132
+ specification_version: 3
133
+ summary: Commands to interact with nexus server
134
+ test_files: []
135
+