stickler 2.0.2 → 2.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/.gitignore +1 -0
- data/HISTORY.asciidoc +17 -8
- data/LICENSE +13 -54
- data/README.asciidoc +29 -5
- data/Rakefile +11 -10
- data/TODO.asciidoc +6 -0
- data/bin/stickler +5 -2
- data/examples/fetch-a-gem +6 -0
- data/examples/gemcutter_repo.ru +1 -1
- data/lib/stickler.rb +1 -1
- data/lib/stickler/client.rb +1 -0
- data/lib/stickler/client/list.rb +30 -0
- data/lib/stickler/client/mirror.rb +5 -5
- data/lib/stickler/client/push.rb +1 -1
- data/lib/stickler/middleware/gemcutter.rb +2 -2
- data/lib/stickler/middleware/helpers.rb +37 -42
- data/lib/stickler/middleware/index.rb +51 -19
- data/lib/stickler/repository/index.rb +46 -9
- data/lib/stickler/repository/local.rb +75 -20
- data/lib/stickler/repository/null.rb +0 -2
- data/lib/stickler/repository/remote.rb +81 -64
- data/lib/stickler/repository/rubygems_authenticator.rb +3 -8
- data/lib/stickler/server.rb +1 -1
- data/lib/stickler/spec_lite.rb +13 -10
- data/lib/stickler/version.rb +2 -2
- data/man/stickler.asciidoc +3 -1
- data/spec/data/gems/foo-2.0.0a.gem +0 -0
- data/spec/index_spec_helpers.rb +71 -0
- data/spec/middleware/local_spec.rb +58 -10
- data/spec/middleware/not_found_spec.rb +1 -0
- data/spec/repository/index_spec.rb +15 -0
- data/spec/repository/local_spec.rb +20 -5
- data/spec/repository/remote_spec.rb +2 -3
- data/spec/spec.opts +1 -1
- data/spec/spec_helper.rb +8 -6
- data/spec/spec_lite_spec.rb +19 -6
- data/tasks/man.rake +1 -1
- metadata +74 -40
- data/spec/middleware/common_gem_server_helpers.rb +0 -69
- data/spec/middleware/index_spec.rb +0 -26
- data/spec/middleware/legacy_gem_server_behavior.rb +0 -31
- data/spec/middleware/modern_gem_server_behavior.rb +0 -22
@@ -19,14 +19,9 @@ module Stickler::Repository
|
|
19
19
|
self.class.rubygems_uri
|
20
20
|
end
|
21
21
|
|
22
|
-
def
|
23
|
-
|
24
|
-
|
25
|
-
(request_uri.scheme == rubygems_uri.scheme)
|
26
|
-
end
|
27
|
-
|
28
|
-
def add_credentials_to(request)
|
29
|
-
request.header['Authorization'] = credentials
|
22
|
+
def handles?( scheme, host )
|
23
|
+
return ( scheme == rubygems_uri.scheme ) &&
|
24
|
+
( host == rubygems_uri.host )
|
30
25
|
end
|
31
26
|
end
|
32
27
|
end
|
data/lib/stickler/server.rb
CHANGED
@@ -20,7 +20,7 @@ module Stickler
|
|
20
20
|
|
21
21
|
def app
|
22
22
|
root = self.stickler_root
|
23
|
-
Rack::Builder.
|
23
|
+
Rack::Builder.app do
|
24
24
|
use Rack::CommonLogger
|
25
25
|
use Stickler::Middleware::Compression
|
26
26
|
use Stickler::Middleware::Gemcutter, :serve_indexes => false, :repo_root => File.join( root, "gemcutter" )
|
data/lib/stickler/spec_lite.rb
CHANGED
@@ -14,10 +14,12 @@ module Stickler
|
|
14
14
|
attr_reader :name
|
15
15
|
attr_reader :version
|
16
16
|
attr_reader :platform
|
17
|
+
attr_reader :platform_string
|
17
18
|
|
18
19
|
def initialize( name, version, platform = Gem::Platform::RUBY )
|
19
20
|
@name = name
|
20
21
|
@version = Gem::Version.new( version )
|
22
|
+
@platform_string = platform.to_s
|
21
23
|
@platform = Gem::Platform.new( platform )
|
22
24
|
end
|
23
25
|
|
@@ -42,19 +44,23 @@ module Stickler
|
|
42
44
|
if platform == Gem::Platform::RUBY or platform.nil? then
|
43
45
|
version.to_s
|
44
46
|
else
|
45
|
-
"#{version}-#{
|
47
|
+
"#{version}-#{platform_string}"
|
46
48
|
end
|
47
49
|
end
|
48
50
|
|
51
|
+
def prerelease?
|
52
|
+
version.prerelease?
|
53
|
+
end
|
54
|
+
|
49
55
|
def to_a
|
50
|
-
[ name, version.to_s,
|
56
|
+
[ name, version.to_s, platform_string ]
|
51
57
|
end
|
52
58
|
|
53
59
|
#
|
54
60
|
# Convert to the array format used by rubygems itself
|
55
61
|
#
|
56
62
|
def to_rubygems_a
|
57
|
-
[ name, version,
|
63
|
+
[ name, version, platform_string ]
|
58
64
|
end
|
59
65
|
|
60
66
|
#
|
@@ -64,11 +70,8 @@ module Stickler
|
|
64
70
|
return 0 if other.object_id == self.object_id
|
65
71
|
other = coerce( other )
|
66
72
|
|
67
|
-
[ :name, :version, :
|
73
|
+
[ :name, :version, :platform_string ].each do |method|
|
68
74
|
us, them = self.send( method ), other.send( method )
|
69
|
-
if us.instance_of?( Gem::Platform ) || them.instance_of?( Gem::Platform ) then
|
70
|
-
us, them = us.to_s, them.to_s
|
71
|
-
end
|
72
75
|
result = us.<=>( them )
|
73
76
|
return result unless 0 == result
|
74
77
|
end
|
@@ -84,7 +87,7 @@ module Stickler
|
|
84
87
|
return (other and
|
85
88
|
self.name == other.name and
|
86
89
|
self.version.to_s == other.version.to_s and
|
87
|
-
self.
|
90
|
+
self.platform_string == other.platform_string )
|
88
91
|
end
|
89
92
|
|
90
93
|
private
|
@@ -94,8 +97,8 @@ module Stickler
|
|
94
97
|
other
|
95
98
|
elsif other.respond_to?( :name ) and
|
96
99
|
other.respond_to?( :version ) and
|
97
|
-
other.respond_to?( :
|
98
|
-
SpecLite.new( other.name, other.version, other.
|
100
|
+
other.respond_to?( :platform_string ) then
|
101
|
+
SpecLite.new( other.name, other.version, other.platform_string )
|
99
102
|
else
|
100
103
|
return false
|
101
104
|
end
|
data/lib/stickler/version.rb
CHANGED
data/man/stickler.asciidoc
CHANGED
@@ -35,6 +35,8 @@ store it in a linkstick:stickler-server[1]
|
|
35
35
|
|
36
36
|
*config*:: Access or update the stickler client configuration.
|
37
37
|
|
38
|
+
*list*:: List all the gems in the remote repository
|
39
|
+
|
38
40
|
|
39
41
|
OPTIONS
|
40
42
|
-------
|
@@ -116,7 +118,7 @@ Take the +third_party+ gem, version +1.4.2+ that is on *rubygems.org* and mirror
|
|
116
118
|
on *stickler.example.com*
|
117
119
|
|
118
120
|
-----------------------------------------------------------------------------------------------------------------
|
119
|
-
stickler mirror
|
121
|
+
stickler mirror third_party_gem --gem-version 0.4.2 --upstream http://rubygems.org/ --server http://stickler.example.com/
|
120
122
|
stickler mirror --help
|
121
123
|
-----------------------------------------------------------------------------------------------------------------
|
122
124
|
|
Binary file
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'rack/test'
|
3
|
+
require 'rubygems/user_interaction'
|
4
|
+
require 'rubygems/indexer'
|
5
|
+
|
6
|
+
module IndexSpecHelpers
|
7
|
+
include Rack::Test::Methods
|
8
|
+
|
9
|
+
def define_directories
|
10
|
+
# pristine spec data location
|
11
|
+
@idx_spec_dir = File.expand_path( File.dirname( __FILE__ ) )
|
12
|
+
@idx_spec_datadir = File.join( @idx_spec_dir, "data" )
|
13
|
+
|
14
|
+
# scratch location
|
15
|
+
@scratch_dir = File.join( @idx_spec_dir, "scratch" )
|
16
|
+
@scratch_datadir = File.join( @scratch_dir, 'data' )
|
17
|
+
@scratch_specdir = File.join( @scratch_datadir, "specifications" )
|
18
|
+
@scratch_gemsdir = File.join( @scratch_datadir, "gems" )
|
19
|
+
end
|
20
|
+
|
21
|
+
# put in the before clause for setup
|
22
|
+
def mirror_spec_gemdir
|
23
|
+
define_directories
|
24
|
+
FileUtils.mkdir_p( @scratch_dir )
|
25
|
+
FileUtils.cp_r( @idx_spec_datadir, @scratch_dir )
|
26
|
+
end
|
27
|
+
|
28
|
+
# Do a legacy index of the scratch location
|
29
|
+
def make_legacy_index
|
30
|
+
indexer = Gem::Indexer.new( @scratch_datadir, :build_legacy => true, :build_modern => false )
|
31
|
+
with_quieter_rubygems { indexer.generate_index }
|
32
|
+
end
|
33
|
+
|
34
|
+
# Do a modern index of the scratch location
|
35
|
+
def make_modern_index
|
36
|
+
indexer = Gem::Indexer.new( @scratch_datadir, :build_legacy => false, :build_modern => true )
|
37
|
+
with_quieter_rubygems { indexer.generate_index }
|
38
|
+
end
|
39
|
+
|
40
|
+
# put in the after clause for cleanup
|
41
|
+
def destroy_scratch_dir
|
42
|
+
FileUtils.rm_rf( @scratch_dir )
|
43
|
+
end
|
44
|
+
|
45
|
+
def with_quieter_rubygems( &block )
|
46
|
+
previous = Gem.configuration.verbose
|
47
|
+
Gem.configuration.verbose = nil
|
48
|
+
yield
|
49
|
+
Gem.configuration.verbose = previous
|
50
|
+
end
|
51
|
+
|
52
|
+
def validate_contents( got, expected, content_type)
|
53
|
+
case content_type
|
54
|
+
when 'application/x-gzip'
|
55
|
+
response_un = Gem.gunzip( got )
|
56
|
+
expected_un = Gem.gunzip( expected )
|
57
|
+
when 'application/x-deflate'
|
58
|
+
response_un = Gem.inflate( got )
|
59
|
+
expected_un = Gem.inflate( expected )
|
60
|
+
when 'application/octet-stream'
|
61
|
+
response_un = got
|
62
|
+
expected_un = expected
|
63
|
+
else
|
64
|
+
fail "Unkonwn content type #{content_type} with data #{got}"
|
65
|
+
end
|
66
|
+
|
67
|
+
got = Marshal.load( response_un )
|
68
|
+
need = Marshal.load( expected_un )
|
69
|
+
got.should == need
|
70
|
+
end
|
71
|
+
end
|
@@ -1,13 +1,15 @@
|
|
1
|
-
require File.expand_path( File.
|
2
|
-
require File.expand_path( File.join( File.dirname(__FILE__), "modern_gem_server_behavior.rb" ) )
|
3
|
-
require File.expand_path( File.join( File.dirname(__FILE__), "legacy_gem_server_behavior.rb" ) )
|
1
|
+
require File.expand_path( "../spec_helper",File.dirname(__FILE__) )
|
4
2
|
|
5
3
|
require 'stickler/middleware/local'
|
6
4
|
require 'stickler/middleware/compression'
|
7
5
|
|
8
|
-
describe
|
6
|
+
describe Stickler::Middleware::Local do
|
7
|
+
|
8
|
+
include IndexSpecHelpers
|
9
|
+
include Rack::Test::Methods
|
10
|
+
|
9
11
|
def app
|
10
|
-
repo_root = @
|
12
|
+
repo_root = @idx_spec_datadir
|
11
13
|
::Rack::Builder.new do
|
12
14
|
use ::Stickler::Middleware::Compression
|
13
15
|
use ::Stickler::Middleware::Local, :repo_root => repo_root
|
@@ -15,11 +17,57 @@ describe ::Stickler::Middleware::Local do
|
|
15
17
|
end
|
16
18
|
end
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
+
describe "When serving a modern index" do
|
21
|
+
before( :all ) do
|
22
|
+
mirror_spec_gemdir
|
23
|
+
make_modern_index
|
24
|
+
end
|
25
|
+
|
26
|
+
after( :all ) do
|
27
|
+
destroy_scratch_dir
|
28
|
+
end
|
29
|
+
|
30
|
+
[
|
31
|
+
"/specs.#{Gem.marshal_version}",
|
32
|
+
"/specs.#{Gem.marshal_version}.gz",
|
33
|
+
"/latest_specs.#{Gem.marshal_version}",
|
34
|
+
"/latest_specs.#{Gem.marshal_version}.gz",
|
35
|
+
"/prerelease_specs.#{Gem.marshal_version}",
|
36
|
+
"/prerelease_specs.#{Gem.marshal_version}.gz",
|
37
|
+
"/quick/Marshal.#{Gem.marshal_version}/foo-1.0.0.gemspec.rz",
|
38
|
+
"/quick/Marshal.#{Gem.marshal_version}/bar-1.0.0.gemspec.rz",
|
39
|
+
"/quick/Marshal.#{Gem.marshal_version}/foo-2.0.0a.gemspec.rz",
|
40
|
+
].each do |path|
|
41
|
+
it "should return the same bytes as Gem::Indexer for '#{path}'" do
|
42
|
+
response = get( path )
|
43
|
+
validate_contents( response.body,
|
44
|
+
IO.read( File.join(@scratch_datadir, path) ),
|
45
|
+
response.content_type )
|
46
|
+
end
|
47
|
+
end
|
20
48
|
end
|
21
49
|
|
22
|
-
|
23
|
-
|
50
|
+
describe "When serving a legacy index" do
|
51
|
+
before( :all ) do
|
52
|
+
mirror_spec_gemdir
|
53
|
+
make_legacy_index
|
54
|
+
end
|
55
|
+
|
56
|
+
after( :all ) do
|
57
|
+
destroy_scratch_dir
|
58
|
+
end
|
24
59
|
|
25
|
-
|
60
|
+
[
|
61
|
+
"/Marshal.#{Gem.marshal_version}",
|
62
|
+
"/Marshal.#{Gem.marshal_version}.Z",
|
63
|
+
].each do |path|
|
64
|
+
it "should return the same bytes as Gem::Indexer for '#{path}'" do
|
65
|
+
pending
|
66
|
+
response = get( path )
|
67
|
+
validate_contents( response.body,
|
68
|
+
IO.read( File.join(@scratch_datadir, path) ),
|
69
|
+
response.content_type )
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -28,5 +28,20 @@ describe ::Stickler::Repository::Index do
|
|
28
28
|
FileUtils.rm( File.join( @index_me, "foo-1.0.0.gemspec" ) )
|
29
29
|
@index.specs.size.should == ( @specifications.size - 1 )
|
30
30
|
end
|
31
|
+
|
32
|
+
it "knows just the latest specs" do
|
33
|
+
@index.latest_specs.size.should == (@specifications.size - 1)
|
34
|
+
@index.latest_specs.collect { |s| s.full_name }.sort.should == %w[ bar-1.0.0 foo-1.0.0 ]
|
35
|
+
end
|
36
|
+
|
37
|
+
it "knows the pre-release specs" do
|
38
|
+
@index.prerelease_specs.size.should == 1
|
39
|
+
@index.prerelease_specs.first.full_name.should == "foo-2.0.0a"
|
40
|
+
end
|
41
|
+
|
42
|
+
it "knows the released specs" do
|
43
|
+
@index.released_specs.size.should == 2
|
44
|
+
@index.released_specs.collect { |s| s.full_name }.sort.should == %w[ bar-1.0.0 foo-1.0.0 ]
|
45
|
+
end
|
31
46
|
end
|
32
47
|
|
@@ -5,13 +5,15 @@ require 'stickler/repository/local'
|
|
5
5
|
|
6
6
|
describe ::Stickler::Repository::Local do
|
7
7
|
|
8
|
-
before do
|
9
|
-
@
|
10
|
-
@
|
8
|
+
before( :each ) do
|
9
|
+
@repos_dir = File.join( @spec_dir, "repos" )
|
10
|
+
@repo_dir = File.join( @repos_dir, "1" )
|
11
|
+
@repo = ::Stickler::Repository::Local.new( @repo_dir )
|
11
12
|
end
|
12
13
|
|
13
14
|
after( :each ) do
|
14
|
-
|
15
|
+
::Stickler::Repository::Local.purge
|
16
|
+
FileUtils.rm_rf( @repos_dir )
|
15
17
|
end
|
16
18
|
|
17
19
|
%w[ gems specifications ].each do |sub_dir|
|
@@ -27,7 +29,20 @@ describe ::Stickler::Repository::Local do
|
|
27
29
|
Dir.glob( File.join( @gems_dir, "*.gem" ) ).each do |gem|
|
28
30
|
@repo.push( gem )
|
29
31
|
end
|
30
|
-
@repo.specs.size.should ==
|
32
|
+
@repo.specs.size.should == 3
|
33
|
+
end
|
34
|
+
|
35
|
+
it "two instances with the same repo dir are the same object" do
|
36
|
+
repo2 = ::Stickler::Repository::Local.new( File.join(@repos_dir, '1') )
|
37
|
+
repo2.object_id.should == @repo.object_id
|
38
|
+
::Stickler::Repository::Local.repos.size.should == 1
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
it "keeps track of all the repository instances" do
|
43
|
+
repo2 = ::Stickler::Repository::Local.new( File.join(@repos_dir, "2" ) )
|
44
|
+
repo3 = ::Stickler::Repository::Local.new( File.join(@repos_dir, "3" ) )
|
45
|
+
::Stickler::Repository::Local.repos.size.should == 3
|
31
46
|
end
|
32
47
|
|
33
48
|
it_should_behave_like 'includes Repository::Api'
|
@@ -6,7 +6,7 @@ require 'stickler/repository/remote'
|
|
6
6
|
describe Stickler::Repository::Remote do
|
7
7
|
before do
|
8
8
|
@repo_uri = "http://localhost:6789/"
|
9
|
-
@repo = ::Stickler::Repository::Remote.new( @repo_uri )
|
9
|
+
@repo = ::Stickler::Repository::Remote.new( @repo_uri, :debug => true )
|
10
10
|
end
|
11
11
|
|
12
12
|
it_should_behave_like 'includes Repository::Api'
|
@@ -23,10 +23,9 @@ describe Stickler::Repository::Remote do
|
|
23
23
|
system cmd
|
24
24
|
|
25
25
|
tries = 0
|
26
|
-
@acc = ::Resourceful::HttpAccessor.new
|
27
26
|
loop do
|
28
27
|
begin
|
29
|
-
|
28
|
+
Excon.get( @repo_uri + "specs.#{Gem.marshal_version}.gz" )
|
30
29
|
#puts "rackup started with pid #{IO.read( @pid_file )}"
|
31
30
|
break
|
32
31
|
rescue => e
|
data/spec/spec.opts
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
--format
|
1
|
+
--format documentation
|
2
2
|
--colour
|
data/spec/spec_helper.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
1
|
+
require 'rspec'
|
2
|
+
require 'index_spec_helpers'
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
require 'stickler/repository/local'
|
5
|
+
|
6
|
+
RSpec.configure do |config|
|
6
7
|
|
7
8
|
config.before( :each ) do
|
8
9
|
@spec_dir = File.expand_path( File.dirname( __FILE__ ) )
|
@@ -11,7 +12,8 @@ Spec::Runner.configure do |config|
|
|
11
12
|
@gems_dir = File.join( @gem_root, "gems" )
|
12
13
|
end
|
13
14
|
|
15
|
+
config.after( :each ) do
|
16
|
+
::Stickler::Repository::Local.purge
|
17
|
+
end
|
14
18
|
|
15
19
|
end
|
16
|
-
|
17
|
-
|
data/spec/spec_lite_spec.rb
CHANGED
@@ -6,7 +6,8 @@ describe Stickler::SpecLite do
|
|
6
6
|
before do
|
7
7
|
@specs = {
|
8
8
|
:ruby => Stickler::SpecLite.new( 'foo', '0.4.2' ),
|
9
|
-
:win => Stickler::SpecLite.new( 'bar', '1.0.1', "x86-mswin32" )
|
9
|
+
:win => Stickler::SpecLite.new( 'bar', '1.0.1', "x86-mswin32" ),
|
10
|
+
:java => Stickler::SpecLite.new( 'jfoo', '0.4.2', 'jruby' )
|
10
11
|
}
|
11
12
|
end
|
12
13
|
|
@@ -18,6 +19,8 @@ describe Stickler::SpecLite do
|
|
18
19
|
[:ruby, 'spec_file_name'] => "foo-0.4.2.gemspec" ,
|
19
20
|
[:win , 'file_name'] => "bar-1.0.1-x86-mswin32.gem",
|
20
21
|
[:win , 'spec_file_name'] => "bar-1.0.1-x86-mswin32.gemspec",
|
22
|
+
[:java, 'file_name'] => 'jfoo-0.4.2-jruby.gem',
|
23
|
+
[:java, 'spec_file_name'] => 'jfoo-0.4.2-jruby.gemspec',
|
21
24
|
}.each do |params, result|
|
22
25
|
platform, method = *params
|
23
26
|
it "on a #{platform} gem ##{method} is #{result}" do
|
@@ -29,22 +32,22 @@ describe Stickler::SpecLite do
|
|
29
32
|
@specs[:win].to_a.should == [ 'bar', '1.0.1', 'x86-mswin32' ]
|
30
33
|
end
|
31
34
|
|
32
|
-
it "returns false when compared to something that does not resond to :name, :version or :
|
35
|
+
it "returns false when compared to something that does not resond to :name, :version or :platform_string" do
|
33
36
|
x = @specs[:ruby] =~ Object.new
|
34
37
|
x.should == false
|
35
38
|
end
|
36
39
|
|
37
|
-
it "can compare against anything that responds to :name, :version and :
|
40
|
+
it "can compare against anything that responds to :name, :version and :platform_string" do
|
38
41
|
class OSpec
|
39
42
|
attr_accessor :name
|
40
43
|
attr_accessor :version
|
41
|
-
attr_accessor :
|
44
|
+
attr_accessor :platform_string
|
42
45
|
end
|
43
46
|
|
44
47
|
o = OSpec.new
|
45
48
|
o.name = @specs[:ruby].name
|
46
49
|
o.version = @specs[:ruby].version
|
47
|
-
o.
|
50
|
+
o.platform_string = @specs[:ruby].platform_string
|
48
51
|
r = @specs[:ruby] =~ o
|
49
52
|
r.should == true
|
50
53
|
end
|
@@ -71,6 +74,16 @@ describe Stickler::SpecLite do
|
|
71
74
|
list = @specs.values
|
72
75
|
alib = Stickler::SpecLite.new( 'alib', '4.2' )
|
73
76
|
list << alib
|
74
|
-
list.sort.should == [ alib, @specs[:win], @specs[:ruby] ]
|
77
|
+
list.sort.should == [ alib, @specs[:win], @specs[:ruby], @specs[:java] ]
|
78
|
+
end
|
79
|
+
|
80
|
+
it "knows when it is a prerelease specification" do
|
81
|
+
spec = Stickler::SpecLite.new( 'prerelease', '1.2.3a' )
|
82
|
+
spec.should be_prerelease
|
83
|
+
end
|
84
|
+
|
85
|
+
it "knows when it is not a prerelease specification" do
|
86
|
+
spec = Stickler::SpecLite.new( 'prerelease', '1.2.3' )
|
87
|
+
spec.should_not be_prerelease
|
75
88
|
end
|
76
89
|
end
|