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