rubygems-proxy_server 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.
- 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
|