stickler 2.0.2 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/.gitignore +1 -0
  2. data/HISTORY.asciidoc +17 -8
  3. data/LICENSE +13 -54
  4. data/README.asciidoc +29 -5
  5. data/Rakefile +11 -10
  6. data/TODO.asciidoc +6 -0
  7. data/bin/stickler +5 -2
  8. data/examples/fetch-a-gem +6 -0
  9. data/examples/gemcutter_repo.ru +1 -1
  10. data/lib/stickler.rb +1 -1
  11. data/lib/stickler/client.rb +1 -0
  12. data/lib/stickler/client/list.rb +30 -0
  13. data/lib/stickler/client/mirror.rb +5 -5
  14. data/lib/stickler/client/push.rb +1 -1
  15. data/lib/stickler/middleware/gemcutter.rb +2 -2
  16. data/lib/stickler/middleware/helpers.rb +37 -42
  17. data/lib/stickler/middleware/index.rb +51 -19
  18. data/lib/stickler/repository/index.rb +46 -9
  19. data/lib/stickler/repository/local.rb +75 -20
  20. data/lib/stickler/repository/null.rb +0 -2
  21. data/lib/stickler/repository/remote.rb +81 -64
  22. data/lib/stickler/repository/rubygems_authenticator.rb +3 -8
  23. data/lib/stickler/server.rb +1 -1
  24. data/lib/stickler/spec_lite.rb +13 -10
  25. data/lib/stickler/version.rb +2 -2
  26. data/man/stickler.asciidoc +3 -1
  27. data/spec/data/gems/foo-2.0.0a.gem +0 -0
  28. data/spec/index_spec_helpers.rb +71 -0
  29. data/spec/middleware/local_spec.rb +58 -10
  30. data/spec/middleware/not_found_spec.rb +1 -0
  31. data/spec/repository/index_spec.rb +15 -0
  32. data/spec/repository/local_spec.rb +20 -5
  33. data/spec/repository/remote_spec.rb +2 -3
  34. data/spec/spec.opts +1 -1
  35. data/spec/spec_helper.rb +8 -6
  36. data/spec/spec_lite_spec.rb +19 -6
  37. data/tasks/man.rake +1 -1
  38. metadata +74 -40
  39. data/spec/middleware/common_gem_server_helpers.rb +0 -69
  40. data/spec/middleware/index_spec.rb +0 -26
  41. data/spec/middleware/legacy_gem_server_behavior.rb +0 -31
  42. 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 can_handle?( request )
23
- request_uri = Addressable::URI.parse(request.uri)
24
- return (request_uri.host == rubygems_uri.host ) &&
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
@@ -20,7 +20,7 @@ module Stickler
20
20
 
21
21
  def app
22
22
  root = self.stickler_root
23
- Rack::Builder.new do
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" )
@@ -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}-#{platform}"
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, platform.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, platform.to_s ]
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, :platform ].each do |method|
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.platform == other.platform )
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?( :platform ) then
98
- SpecLite.new( other.name, other.version, other.platform )
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
@@ -11,8 +11,8 @@ module Stickler
11
11
  module Version
12
12
 
13
13
  MAJOR = 2
14
- MINOR = 0
15
- BUILD = 2
14
+ MINOR = 1
15
+ BUILD = 0
16
16
 
17
17
  def self.to_ary
18
18
  [ MAJOR, MINOR, BUILD ]
@@ -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 third_party --version 0.4.2 --upstream http://rubygems.org/ --server http://stickler.example.com/
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
 
@@ -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.join( File.dirname(__FILE__), "..", "spec_helper.rb" ) )
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 ::Stickler::Middleware::Local do
6
+ describe Stickler::Middleware::Local do
7
+
8
+ include IndexSpecHelpers
9
+ include Rack::Test::Methods
10
+
9
11
  def app
10
- repo_root = @sinatra_gem_dir
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
- before do
19
- @sinatra_gem_dir = @webrick_gem_dir = @gem_root
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
- it_should_behave_like "modern gem server indexes"
23
- # it_should_behave_like "legacy gem server indexes"
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
- end
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
@@ -2,6 +2,7 @@ require File.expand_path( File.join( File.dirname(__FILE__), "..", "spec_helper.
2
2
  require 'stickler/middleware/not_found'
3
3
 
4
4
  describe ::Stickler::Middleware::NotFound do
5
+ include Rack::Test::Methods
5
6
  def app
6
7
  ::Stickler::Middleware::NotFound.new
7
8
  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
- @repo_dir = File.join( @spec_dir, "tmp" )
10
- @repo = ::Stickler::Repository::Local.new( @repo_dir )
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
- FileUtils.rm_rf( @repo_dir )
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 == 2
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
- @acc.resource( @repo_uri + "specs.#{Gem.marshal_version}.gz" ).get
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
@@ -1,2 +1,2 @@
1
- --format specdoc
1
+ --format documentation
2
2
  --colour
@@ -1,8 +1,9 @@
1
- require 'spec'
2
- require 'rack/test'
1
+ require 'rspec'
2
+ require 'index_spec_helpers'
3
3
 
4
- Spec::Runner.configure do |config|
5
- config.include Rack::Test::Methods
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
-
@@ -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 :platform" do
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 :platform" do
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 :platform
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.platform = @specs[:ruby].platform
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