rubygems-proxy_server 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README.rdoc +57 -0
- data/Rakefile +84 -0
- data/VERSION +1 -0
- data/lib/proxy_app.rb +101 -0
- data/lib/proxy_server_command.rb +70 -0
- data/lib/rubygems_plugin.rb +4 -0
- data/rubygems-proxy_server.gemspec +77 -0
- data/spec/mockgemui.rb +63 -0
- data/spec/proxy_app_spec.rb +146 -0
- data/spec/proxy_server_command_spec.rb +104 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +10 -0
- metadata +140 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Jeremy Burks
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
= rubygems-proxy-server
|
2
|
+
|
3
|
+
A gem source proxy.
|
4
|
+
|
5
|
+
Most useful in an intranet scenario. Currently, it is assumed that the localhost has
|
6
|
+
direct access to the Internet. A future version will have the ability to access the
|
7
|
+
Internet via an authenticated proxy.
|
8
|
+
|
9
|
+
As gem's are requested they are downloaded and re-indexed on the localhost. Future requests
|
10
|
+
will serve the local gem directly. A secondary gem source can be set to point to the internal
|
11
|
+
server. Most likely an internal gem server already exists for internal gem deployment. Note,
|
12
|
+
in the case of an existing internal gem server, you must have both the proxy_server and internal
|
13
|
+
gem server set as gem sources otherwise the rubygems client will not be able to find the
|
14
|
+
internal gems. Each gem source will have separate indexes.
|
15
|
+
|
16
|
+
== Usage
|
17
|
+
|
18
|
+
Usage: gem proxy_server [options]
|
19
|
+
|
20
|
+
Options:
|
21
|
+
-d, --directory BASEDIR Repository base dir containing gems subdir.
|
22
|
+
-s, --source URL The remote source for gems.
|
23
|
+
-p, --port PORT The port of the gem source.
|
24
|
+
|
25
|
+
Common Options:
|
26
|
+
-h, --help Get help on this command
|
27
|
+
-V, --[no-]verbose Set the verbose level of output
|
28
|
+
-q, --quiet Silence commands
|
29
|
+
--config-file FILE Use this config file instead of default
|
30
|
+
--backtrace Show stack backtrace on errors
|
31
|
+
--debug Turn on Ruby debugging
|
32
|
+
|
33
|
+
|
34
|
+
Summary:
|
35
|
+
Half gem source, half gem proxy.
|
36
|
+
|
37
|
+
Description:
|
38
|
+
The directory given via -d, --directory is expected to be a gem
|
39
|
+
server directory. See `gem help generate_index` for the requirements
|
40
|
+
for that directory.
|
41
|
+
|
42
|
+
$ gem proxy_server -d /var/www/gems
|
43
|
+
|
44
|
+
Defaults:
|
45
|
+
--port 3027 --source http://gemcutter.org
|
46
|
+
|
47
|
+
|
48
|
+
== TODOs
|
49
|
+
|
50
|
+
* Use HTTP_PROXY if present. Other ways to support proxies?
|
51
|
+
* Add --rack-config option that will print a config.ru to be used for deployments besides `gem proxy_server`
|
52
|
+
* Investigate the possibility of merging local gem indexes with upstream indexes. The idea being one gem source could be used for intranet and internet gems.
|
53
|
+
* Multiple upstream gem sources
|
54
|
+
|
55
|
+
== Copyright
|
56
|
+
|
57
|
+
Copyright (c) 2009 Jeremy Burks. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "rubygems-proxy_server"
|
8
|
+
gem.summary = "A gem source proxy."
|
9
|
+
gem.description = "A gem source proxy"
|
10
|
+
gem.email = "jeremy.burks@gmail.com"
|
11
|
+
gem.homepage = "http://github.com/jrun/rubygems-proxy_server"
|
12
|
+
gem.authors = ["jrun"]
|
13
|
+
gem.add_dependency 'rack', '~> 1.0.1'
|
14
|
+
gem.add_dependency "sinatra", "~> 0.9.4"
|
15
|
+
gem.add_development_dependency "rspec", "~> 1.2.9"
|
16
|
+
gem.add_development_dependency 'rack-test', '~> 0.5.2'
|
17
|
+
gem.add_development_dependency 'sham_rack', '~> 1.1.2'
|
18
|
+
gem.add_development_dependency 'yard', '~> 0.4.0'
|
19
|
+
gem.add_development_dependency 'grancher', '> 0'
|
20
|
+
gem.files = FileList['[a-zA-Z]*', 'bin/**/*', 'lib/**/*', 'spec/**/*']
|
21
|
+
|
22
|
+
desc "Install development dependencies."
|
23
|
+
task :setup do
|
24
|
+
gems = ::Gem::SourceIndex.from_installed_gems
|
25
|
+
gem.dependencies.each do |dep|
|
26
|
+
if gems.find_name(dep.name, dep.version_requirements).empty?
|
27
|
+
puts "Installing dependency: #{dep}"
|
28
|
+
system %Q|gem install #{dep.name} -v "#{dep.version_requirements}" --development|
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
desc "Build and reinstall the gem locally."
|
34
|
+
task :reinstall => :build do
|
35
|
+
version = File.read('VERSION')
|
36
|
+
if (system("gem list #{gem.name} -l") || "") =~ /#{gem.name}-#{version}/
|
37
|
+
system "gem uninstall #{gem.name}"
|
38
|
+
end
|
39
|
+
system "gem install --no-rdoc --no-ri -l pkg/#{gem.name}-#{version}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
Jeweler::GemcutterTasks.new
|
44
|
+
rescue LoadError
|
45
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
46
|
+
end
|
47
|
+
|
48
|
+
require 'spec/rake/spectask'
|
49
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
50
|
+
spec.libs << 'lib' << 'spec'
|
51
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
52
|
+
end
|
53
|
+
|
54
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
55
|
+
spec.libs << 'lib' << 'spec'
|
56
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
57
|
+
spec.rcov = true
|
58
|
+
end
|
59
|
+
|
60
|
+
task :spec => :check_dependencies
|
61
|
+
task :default => :spec
|
62
|
+
task :build => [:spec, :yard]
|
63
|
+
|
64
|
+
begin
|
65
|
+
require 'yard'
|
66
|
+
YARD::Rake::YardocTask.new
|
67
|
+
rescue LoadError
|
68
|
+
task :yard do
|
69
|
+
abort "YARD is not available. Run 'rake setup' to install all development dependencies."
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
begin
|
74
|
+
require 'grancher/task'
|
75
|
+
Grancher::Task.new do |g|
|
76
|
+
g.branch = 'gh-pages'
|
77
|
+
g.push_to = 'origin'
|
78
|
+
g.directory 'doc'
|
79
|
+
end
|
80
|
+
rescue LoadError
|
81
|
+
task :publish do
|
82
|
+
abort "grancher is not available. Run 'rake setup' to install all development dependencies."
|
83
|
+
end
|
84
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/lib/proxy_app.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'rubygems/indexer'
|
2
|
+
require 'sinatra/base'
|
3
|
+
require 'net/http'
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
class ProxyApp < Sinatra::Base
|
7
|
+
enable :run
|
8
|
+
disable :static
|
9
|
+
|
10
|
+
set :environment, :production
|
11
|
+
|
12
|
+
get '/' do
|
13
|
+
<<-EOS
|
14
|
+
directory: #{options.public}
|
15
|
+
gem_source: #{options.source}
|
16
|
+
EOS
|
17
|
+
end
|
18
|
+
|
19
|
+
get '/gems/*' do
|
20
|
+
filename = File.join params[:splat]
|
21
|
+
gemfile_path = gem_path.join filename
|
22
|
+
|
23
|
+
unless gemfile_path.exist?
|
24
|
+
download_file "#{options.source}/gems/#{filename}", gemfile_path
|
25
|
+
update_gem_index
|
26
|
+
end
|
27
|
+
|
28
|
+
send_file gemfile_path
|
29
|
+
end
|
30
|
+
|
31
|
+
get "/*" do
|
32
|
+
path = File.join params[:splat]
|
33
|
+
upstream_url = options.source + "/" + path
|
34
|
+
tmpfile = tmp_path_for path
|
35
|
+
|
36
|
+
download_file upstream_url, tmpfile
|
37
|
+
|
38
|
+
send_file tmpfile
|
39
|
+
end
|
40
|
+
|
41
|
+
not_found do
|
42
|
+
"\n"
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
def public_path
|
47
|
+
@public_path ||= Pathname.new(options.public)
|
48
|
+
end
|
49
|
+
|
50
|
+
def gem_path
|
51
|
+
@gem_path ||= public_path.join('gems')
|
52
|
+
end
|
53
|
+
|
54
|
+
def download_file(url, local_path)
|
55
|
+
Net::HTTP.get_response(URI.parse(url)) do |res|
|
56
|
+
case res
|
57
|
+
when Net::HTTPSuccess
|
58
|
+
local_path.open("wb") do |f|
|
59
|
+
res.read_body {|chunk| f.write(chunk) }
|
60
|
+
end
|
61
|
+
when Net::HTTPRedirection
|
62
|
+
download_file res['location'], local_path
|
63
|
+
else
|
64
|
+
raise Sinatra::NotFound, url
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def update_gem_index
|
70
|
+
if options.respond_to? :mock_gem_indexer
|
71
|
+
options.mock_gem_indexer
|
72
|
+
else
|
73
|
+
Gem::Indexer.new(options.public)
|
74
|
+
end.generate_index
|
75
|
+
end
|
76
|
+
|
77
|
+
def tmp_path_for(path)
|
78
|
+
tmpfile = Pathname.new File.join(tmp_path, path)
|
79
|
+
unless tmpfile.dirname.exist?
|
80
|
+
tmpfile.dirname.mkpath
|
81
|
+
end
|
82
|
+
tmpfile
|
83
|
+
end
|
84
|
+
|
85
|
+
# == Note
|
86
|
+
#
|
87
|
+
# There is a bug in JRuby [1] with regard to renaming files
|
88
|
+
# across devices. Create the tmp dir inside the public directory
|
89
|
+
# to make sure the files will be on the same device.
|
90
|
+
#
|
91
|
+
# [1] http://jira.codehaus.org/browse/JRUBY-3381
|
92
|
+
#
|
93
|
+
def tmp_path
|
94
|
+
tmpdir = File.join options.public, 'rubygems-proxy_server-cache'
|
95
|
+
Dir.mkdir tmpdir unless File.exist?(tmpdir)
|
96
|
+
ENV["TMPDIR"] = tmpdir
|
97
|
+
|
98
|
+
tmpdir
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'rubygems/local_remote_options'
|
2
|
+
require 'proxy_app'
|
3
|
+
|
4
|
+
class Gem::Commands::ProxyServerCommand < Gem::Command
|
5
|
+
include Gem::LocalRemoteOptions
|
6
|
+
|
7
|
+
PROXY_DEFAULT_GEM_SOURCE = "http://gemcutter.org"
|
8
|
+
PROXY_DEFAULT_PORT = 3027
|
9
|
+
|
10
|
+
NIL_DIR_MSG = "missing -d, --directory option"
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
super "proxy_server", summary
|
14
|
+
|
15
|
+
accept_uri_http
|
16
|
+
|
17
|
+
add_option '-d', '--directory BASEDIR',
|
18
|
+
'Repository base dir containing gems subdir.' do |dir, options|
|
19
|
+
options[:directory] = File.expand_path dir
|
20
|
+
end
|
21
|
+
|
22
|
+
add_option '-s', '--source URL', URI::HTTP,
|
23
|
+
'The remote source for gems.' do |source, options|
|
24
|
+
options[:remote_source] = source
|
25
|
+
end
|
26
|
+
|
27
|
+
add_option '-p', '--port PORT',
|
28
|
+
'The port of the gem source.' do |port, options|
|
29
|
+
options[:port] = port.to_i
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def summary
|
34
|
+
"Half gem source, half gem proxy."
|
35
|
+
end
|
36
|
+
|
37
|
+
def description # :nodoc:
|
38
|
+
<<-EOS
|
39
|
+
The directory given via -d, --directory is expected to be a gem
|
40
|
+
server directory. See `gem help generate_index` for the requirements
|
41
|
+
for that directory.
|
42
|
+
|
43
|
+
$ gem proxy_server -d /var/www/gems
|
44
|
+
|
45
|
+
EOS
|
46
|
+
end
|
47
|
+
|
48
|
+
def usage # :nodoc:
|
49
|
+
program_name
|
50
|
+
end
|
51
|
+
|
52
|
+
def defaults_str # :nodoc:
|
53
|
+
"--port #{PROXY_DEFAULT_PORT} --source #{PROXY_DEFAULT_GEM_SOURCE}"
|
54
|
+
end
|
55
|
+
|
56
|
+
def execute
|
57
|
+
dir = options[:directory]
|
58
|
+
if dir.nil?
|
59
|
+
alert_error NIL_DIR_MSG
|
60
|
+
terminate_interaction 1
|
61
|
+
elsif not File.exist?(dir) or not File.directory?(dir)
|
62
|
+
alert_error "unknown directory name #{dir}."
|
63
|
+
terminate_interaction 1
|
64
|
+
else
|
65
|
+
ProxyApp.run! :port => options[:port] || PROXY_DEFAULT_PORT,
|
66
|
+
:source => options[:remote_source] || PROXY_DEFAULT_GEM_SOURCE,
|
67
|
+
:public => dir
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{rubygems-proxy_server}
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["jrun"]
|
12
|
+
s.date = %q{2009-12-04}
|
13
|
+
s.description = %q{A gem source proxy}
|
14
|
+
s.email = %q{jeremy.burks@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
"LICENSE",
|
21
|
+
"README.rdoc",
|
22
|
+
"Rakefile",
|
23
|
+
"VERSION",
|
24
|
+
"lib/proxy_app.rb",
|
25
|
+
"lib/proxy_server_command.rb",
|
26
|
+
"lib/rubygems_plugin.rb",
|
27
|
+
"rubygems-proxy_server.gemspec",
|
28
|
+
"spec/mockgemui.rb",
|
29
|
+
"spec/proxy_app_spec.rb",
|
30
|
+
"spec/proxy_server_command_spec.rb",
|
31
|
+
"spec/spec.opts",
|
32
|
+
"spec/spec_helper.rb"
|
33
|
+
]
|
34
|
+
s.homepage = %q{http://github.com/jrun/rubygems-proxy_server}
|
35
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
36
|
+
s.require_paths = ["lib"]
|
37
|
+
s.rubygems_version = %q{1.3.5}
|
38
|
+
s.summary = %q{A gem source proxy.}
|
39
|
+
s.test_files = [
|
40
|
+
"spec/mockgemui.rb",
|
41
|
+
"spec/proxy_app_spec.rb",
|
42
|
+
"spec/proxy_server_command_spec.rb",
|
43
|
+
"spec/spec_helper.rb"
|
44
|
+
]
|
45
|
+
|
46
|
+
if s.respond_to? :specification_version then
|
47
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
48
|
+
s.specification_version = 3
|
49
|
+
|
50
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
51
|
+
s.add_runtime_dependency(%q<rack>, ["~> 1.0.1"])
|
52
|
+
s.add_runtime_dependency(%q<sinatra>, ["~> 0.9.4"])
|
53
|
+
s.add_development_dependency(%q<rspec>, ["~> 1.2.9"])
|
54
|
+
s.add_development_dependency(%q<rack-test>, ["~> 0.5.2"])
|
55
|
+
s.add_development_dependency(%q<sham_rack>, ["~> 1.1.2"])
|
56
|
+
s.add_development_dependency(%q<yard>, ["~> 0.4.0"])
|
57
|
+
s.add_development_dependency(%q<grancher>, ["> 0"])
|
58
|
+
else
|
59
|
+
s.add_dependency(%q<rack>, ["~> 1.0.1"])
|
60
|
+
s.add_dependency(%q<sinatra>, ["~> 0.9.4"])
|
61
|
+
s.add_dependency(%q<rspec>, ["~> 1.2.9"])
|
62
|
+
s.add_dependency(%q<rack-test>, ["~> 0.5.2"])
|
63
|
+
s.add_dependency(%q<sham_rack>, ["~> 1.1.2"])
|
64
|
+
s.add_dependency(%q<yard>, ["~> 0.4.0"])
|
65
|
+
s.add_dependency(%q<grancher>, ["> 0"])
|
66
|
+
end
|
67
|
+
else
|
68
|
+
s.add_dependency(%q<rack>, ["~> 1.0.1"])
|
69
|
+
s.add_dependency(%q<sinatra>, ["~> 0.9.4"])
|
70
|
+
s.add_dependency(%q<rspec>, ["~> 1.2.9"])
|
71
|
+
s.add_dependency(%q<rack-test>, ["~> 0.5.2"])
|
72
|
+
s.add_dependency(%q<sham_rack>, ["~> 1.1.2"])
|
73
|
+
s.add_dependency(%q<yard>, ["~> 0.4.0"])
|
74
|
+
s.add_dependency(%q<grancher>, ["> 0"])
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
data/spec/mockgemui.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#--
|
3
|
+
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
|
4
|
+
# All rights reserved.
|
5
|
+
# See LICENSE.txt for permissions.
|
6
|
+
#++
|
7
|
+
|
8
|
+
|
9
|
+
require 'stringio'
|
10
|
+
require 'rubygems/user_interaction'
|
11
|
+
|
12
|
+
class MockGemUi < Gem::StreamUI
|
13
|
+
class TermError < RuntimeError; end
|
14
|
+
|
15
|
+
module TTY
|
16
|
+
|
17
|
+
attr_accessor :tty
|
18
|
+
|
19
|
+
def tty?()
|
20
|
+
@tty = true unless defined?(@tty)
|
21
|
+
@tty
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize(input = "")
|
27
|
+
ins = StringIO.new input
|
28
|
+
outs = StringIO.new
|
29
|
+
errs = StringIO.new
|
30
|
+
|
31
|
+
ins.extend TTY
|
32
|
+
outs.extend TTY
|
33
|
+
errs.extend TTY
|
34
|
+
|
35
|
+
super ins, outs, errs
|
36
|
+
|
37
|
+
@terminated = false
|
38
|
+
end
|
39
|
+
|
40
|
+
def input
|
41
|
+
@ins.string
|
42
|
+
end
|
43
|
+
|
44
|
+
def output
|
45
|
+
@outs.string
|
46
|
+
end
|
47
|
+
|
48
|
+
def error
|
49
|
+
@errs.string
|
50
|
+
end
|
51
|
+
|
52
|
+
def terminated?
|
53
|
+
@terminated
|
54
|
+
end
|
55
|
+
|
56
|
+
def terminate_interaction(status=0)
|
57
|
+
@terminated = true
|
58
|
+
|
59
|
+
raise TermError unless status == 0
|
60
|
+
raise Gem::SystemExitException, status
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
require 'rack/test'
|
3
|
+
require 'sham_rack'
|
4
|
+
|
5
|
+
ProxyApp.set :environment, :test
|
6
|
+
|
7
|
+
describe ProxyApp do
|
8
|
+
include Rack::Test::Methods
|
9
|
+
|
10
|
+
def app
|
11
|
+
ProxyApp
|
12
|
+
end
|
13
|
+
|
14
|
+
before(:each) do
|
15
|
+
# HACK OSX /private/tmp, yanked from rubygems RubyGemTestCase
|
16
|
+
tmpdir = nil
|
17
|
+
Dir.chdir Dir.tmpdir do tmpdir = Dir.pwd end
|
18
|
+
|
19
|
+
@tmpdir = File.join tmpdir, "test_rubygems-proxy_server_#{$$}"
|
20
|
+
@tmpdir.untaint
|
21
|
+
@gemsdir = File.join @tmpdir, 'gems'
|
22
|
+
|
23
|
+
FileUtils.mkdir_p @gemsdir
|
24
|
+
|
25
|
+
@gem_source = 'http://www.test.host'
|
26
|
+
@gem_indexer = mock(:gem_indexer)
|
27
|
+
|
28
|
+
ProxyApp.set :source, @gem_source
|
29
|
+
ProxyApp.set :public, @tmpdir
|
30
|
+
ProxyApp.set :mock_gem_indexer, @gem_indexer
|
31
|
+
end
|
32
|
+
|
33
|
+
after(:each) do
|
34
|
+
FileUtils.rm_rf @tmpdir
|
35
|
+
end
|
36
|
+
|
37
|
+
context '/gems/*' do
|
38
|
+
before(:each) do
|
39
|
+
|
40
|
+
@gem_source = ShamRack.at('www.test.host').sinatra do
|
41
|
+
def request_count; @@request_count end
|
42
|
+
@@request_count = 0
|
43
|
+
|
44
|
+
get '/gems/not_found' do
|
45
|
+
not_found
|
46
|
+
end
|
47
|
+
|
48
|
+
get '/gems/redirect-0.1.0.gem' do
|
49
|
+
redirect 'http://www.test.host/gems/from-redirect-0.1.0.gem'
|
50
|
+
end
|
51
|
+
|
52
|
+
get '/gems/*' do
|
53
|
+
@@request_count += 1
|
54
|
+
"gem: #{File.join params[:splat]}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'should download the gem from the upstream server' do
|
61
|
+
@gem_indexer.should_receive(:generate_index)
|
62
|
+
|
63
|
+
get '/gems/test-gem-0.1.0.gem'
|
64
|
+
last_response.should be_ok
|
65
|
+
last_response.body.should == 'gem: test-gem-0.1.0.gem'
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should write the gem file to the 'gems' directory" do
|
69
|
+
@gem_indexer.should_receive(:generate_index)
|
70
|
+
|
71
|
+
get '/gems/test-gem-0.1.0.gem'
|
72
|
+
File.should exist(File.join(@tmpdir, 'gems/test-gem-0.1.0.gem'))
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should not download the gem a second time" do
|
76
|
+
@gem_indexer.should_receive(:generate_index)
|
77
|
+
|
78
|
+
get '/gems/test-gem-0.1.0.gem'
|
79
|
+
get '/gems/test-gem-0.1.0.gem'
|
80
|
+
|
81
|
+
@gem_source.request_count.should == 1
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should respond with 404 Not Found when the gem source reports the same' do
|
85
|
+
get '/gems/not_found'
|
86
|
+
|
87
|
+
last_response.should be_not_found
|
88
|
+
last_response.body.should == "\n"
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should follow a redirect" do
|
92
|
+
@gem_indexer.should_receive(:generate_index)
|
93
|
+
|
94
|
+
get '/gems/redirect-0.1.0.gem'
|
95
|
+
|
96
|
+
last_response.should be_ok
|
97
|
+
last_response.body.should == 'gem: from-redirect-0.1.0.gem'
|
98
|
+
File.should exist(File.join(@tmpdir, 'gems/redirect-0.1.0.gem'))
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context '/*' do
|
103
|
+
before(:each) do
|
104
|
+
ShamRack.at('www.test.host').sinatra do
|
105
|
+
get '/not_found' do
|
106
|
+
error 404, 'Not Found'
|
107
|
+
end
|
108
|
+
|
109
|
+
get '/*' do
|
110
|
+
"file: #{File.join params[:splat]}"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'should download the file from the upstream server' do
|
116
|
+
get '/some/random/file'
|
117
|
+
last_response.should be_ok
|
118
|
+
last_response.body.should == 'file: some/random/file'
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should write the file to the proxy's tmp directory" do
|
122
|
+
get '/some/random/file'
|
123
|
+
File.should exist(File.join(@tmpdir, 'rubygems-proxy_server-cache/some/random/file'))
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should respond with 404 Not Found when the gem source reports the same" do
|
127
|
+
get '/not_found'
|
128
|
+
|
129
|
+
last_response.should be_not_found
|
130
|
+
last_response.body.should == "\n"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context '/' do
|
135
|
+
it 'reports server info' do
|
136
|
+
get '/'
|
137
|
+
last_response.should be_ok
|
138
|
+
last_response.body.should == <<-EOS
|
139
|
+
directory: #{@tmpdir}
|
140
|
+
gem_source: #{@gem_source}
|
141
|
+
EOS
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe Gem::Commands::ProxyServerCommand do
|
4
|
+
include Gem::DefaultUserInteraction
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
ProxyApp.stub!(:run!)
|
8
|
+
@ui = MockGemUi.new
|
9
|
+
@cmd = Gem::Commands::ProxyServerCommand.new
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'short options' do
|
13
|
+
it '-d BASEDIR' do
|
14
|
+
@cmd.handle_options ['-d', '/tmp/rubygems-proxy-server/gems']
|
15
|
+
@cmd.options[:directory].should == '/tmp/rubygems-proxy-server/gems'
|
16
|
+
end
|
17
|
+
|
18
|
+
it '-s URL' do
|
19
|
+
@cmd.handle_options ['-s', 'http://test.host/gems']
|
20
|
+
@cmd.options[:remote_source].should == 'http://test.host/gems'
|
21
|
+
end
|
22
|
+
|
23
|
+
it '-p PORT' do
|
24
|
+
@cmd.handle_options ['-p', '6688']
|
25
|
+
@cmd.options[:port].should == 6688
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context '#execute' do
|
30
|
+
it "should report an error when the gems directory option is not given" do
|
31
|
+
use_ui @ui do
|
32
|
+
lambda do
|
33
|
+
@cmd.execute
|
34
|
+
end.should raise_error(MockGemUi::TermError)
|
35
|
+
end
|
36
|
+
@ui.error.should == "ERROR: #{Gem::Commands::ProxyServerCommand::NIL_DIR_MSG}\n"
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should report an error when the gems directory does not exist" do
|
40
|
+
@cmd.handle_options ['--directory', '/tmp/does/not/exist']
|
41
|
+
use_ui @ui do
|
42
|
+
lambda do
|
43
|
+
@cmd.execute
|
44
|
+
end.should raise_error(MockGemUi::TermError)
|
45
|
+
end
|
46
|
+
@ui.error.should =~ /unknown directory name/
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'with valid options' do
|
50
|
+
before(:each) do
|
51
|
+
@dir = '/tmp/rubygems-proxy-server/test'
|
52
|
+
|
53
|
+
File.stub!(:exist?).and_return(true)
|
54
|
+
File.stub!(:directory?).and_return(true)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should run the ProxyApp with defaults" do
|
58
|
+
port = Gem::Commands::ProxyServerCommand::PROXY_DEFAULT_PORT
|
59
|
+
gem_source = Gem::Commands::ProxyServerCommand::PROXY_DEFAULT_GEM_SOURCE
|
60
|
+
|
61
|
+
@cmd.handle_options ['--directory', @dir]
|
62
|
+
|
63
|
+
ProxyApp.should_receive(:run!).with(:port => port,
|
64
|
+
:source => gem_source,
|
65
|
+
:public => @dir)
|
66
|
+
|
67
|
+
use_ui @ui do
|
68
|
+
@cmd.execute
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'should run the ProxyApp with the given port' do
|
73
|
+
gem_source = Gem::Commands::ProxyServerCommand::PROXY_DEFAULT_GEM_SOURCE
|
74
|
+
|
75
|
+
@cmd.handle_options ['--directory', @dir, '--port', '7799']
|
76
|
+
|
77
|
+
ProxyApp.should_receive(:run!).with(:port => 7799,
|
78
|
+
:source => gem_source,
|
79
|
+
:public => @dir)
|
80
|
+
|
81
|
+
use_ui @ui do
|
82
|
+
@cmd.execute
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should run the ProxyApp with the given gem source' do
|
87
|
+
gem_source = 'http://test.host/gems'
|
88
|
+
|
89
|
+
@cmd.handle_options ['--directory', @dir, '--source', gem_source]
|
90
|
+
|
91
|
+
ProxyApp.should_receive(:run!).with(:port => Gem::Commands::ProxyServerCommand::PROXY_DEFAULT_PORT,
|
92
|
+
:source => gem_source,
|
93
|
+
:public => @dir)
|
94
|
+
|
95
|
+
use_ui @ui do
|
96
|
+
@cmd.execute
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
require 'rubygems'
|
4
|
+
require 'rubygems_plugin'
|
5
|
+
require 'spec'
|
6
|
+
require 'spec/autorun'
|
7
|
+
require 'mockgemui'
|
8
|
+
|
9
|
+
Spec::Runner.configure do |config|
|
10
|
+
end
|
metadata
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rubygems-proxy_server
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- jrun
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-12-04 00:00:00 -06:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rack
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ~>
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.0.1
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: sinatra
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.9.4
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: rspec
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.2.9
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: rack-test
|
47
|
+
type: :development
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.5.2
|
54
|
+
version:
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: sham_rack
|
57
|
+
type: :development
|
58
|
+
version_requirement:
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ~>
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: 1.1.2
|
64
|
+
version:
|
65
|
+
- !ruby/object:Gem::Dependency
|
66
|
+
name: yard
|
67
|
+
type: :development
|
68
|
+
version_requirement:
|
69
|
+
version_requirements: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ~>
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: 0.4.0
|
74
|
+
version:
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: grancher
|
77
|
+
type: :development
|
78
|
+
version_requirement:
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">"
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: "0"
|
84
|
+
version:
|
85
|
+
description: A gem source proxy
|
86
|
+
email: jeremy.burks@gmail.com
|
87
|
+
executables: []
|
88
|
+
|
89
|
+
extensions: []
|
90
|
+
|
91
|
+
extra_rdoc_files:
|
92
|
+
- LICENSE
|
93
|
+
- README.rdoc
|
94
|
+
files:
|
95
|
+
- LICENSE
|
96
|
+
- README.rdoc
|
97
|
+
- Rakefile
|
98
|
+
- VERSION
|
99
|
+
- lib/proxy_app.rb
|
100
|
+
- lib/proxy_server_command.rb
|
101
|
+
- lib/rubygems_plugin.rb
|
102
|
+
- rubygems-proxy_server.gemspec
|
103
|
+
- spec/mockgemui.rb
|
104
|
+
- spec/proxy_app_spec.rb
|
105
|
+
- spec/proxy_server_command_spec.rb
|
106
|
+
- spec/spec.opts
|
107
|
+
- spec/spec_helper.rb
|
108
|
+
has_rdoc: true
|
109
|
+
homepage: http://github.com/jrun/rubygems-proxy_server
|
110
|
+
licenses: []
|
111
|
+
|
112
|
+
post_install_message:
|
113
|
+
rdoc_options:
|
114
|
+
- --charset=UTF-8
|
115
|
+
require_paths:
|
116
|
+
- lib
|
117
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
118
|
+
requirements:
|
119
|
+
- - ">="
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: "0"
|
122
|
+
version:
|
123
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
124
|
+
requirements:
|
125
|
+
- - ">="
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: "0"
|
128
|
+
version:
|
129
|
+
requirements: []
|
130
|
+
|
131
|
+
rubyforge_project:
|
132
|
+
rubygems_version: 1.3.5
|
133
|
+
signing_key:
|
134
|
+
specification_version: 3
|
135
|
+
summary: A gem source proxy.
|
136
|
+
test_files:
|
137
|
+
- spec/mockgemui.rb
|
138
|
+
- spec/proxy_app_spec.rb
|
139
|
+
- spec/proxy_server_command_spec.rb
|
140
|
+
- spec/spec_helper.rb
|