stickler 2.3.0 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +15 -0
  2. data/CONTRIBUTING.md +5 -4
  3. data/HISTORY.md +16 -9
  4. data/LICENSE +1 -1
  5. data/Manifest.txt +34 -20
  6. data/README.md +128 -0
  7. data/Rakefile +10 -9
  8. data/bin/stickler +9 -6
  9. data/bin/stickler-passenger-config +8 -8
  10. data/bin/stickler-server +12 -12
  11. data/examples/as_middleware.ru +14 -0
  12. data/examples/auth_repo.ru +1 -1
  13. data/examples/gemcutter_repo.ru +1 -1
  14. data/examples/local_repo.ru +1 -1
  15. data/lib/stickler.rb +3 -1
  16. data/lib/stickler/client.rb +2 -1
  17. data/lib/stickler/client/delete.rb +1 -1
  18. data/lib/stickler/client/latest-version.rb +40 -0
  19. data/lib/stickler/client/mirror.rb +47 -15
  20. data/lib/stickler/client/push.rb +1 -1
  21. data/lib/stickler/client/unyank.rb +1 -1
  22. data/lib/stickler/client/yank.rb +1 -1
  23. data/lib/stickler/gem_container.rb +40 -0
  24. data/lib/stickler/gemfile_lock_parser.rb +47 -0
  25. data/lib/stickler/middleware.rb +1 -0
  26. data/lib/stickler/middleware/server.rb +37 -0
  27. data/lib/stickler/repository/api.rb +16 -0
  28. data/lib/stickler/repository/index.rb +0 -3
  29. data/lib/stickler/repository/local.rb +6 -8
  30. data/lib/stickler/repository/remote.rb +29 -7
  31. data/lib/stickler/server.rb +2 -6
  32. data/man/stickler-passenger-config.1 +2 -22
  33. data/man/stickler-server.1 +9 -99
  34. data/man/stickler.1 +15 -173
  35. data/man/stickler.1.ronn +6 -0
  36. data/tasks/default.rake +16 -18
  37. data/tasks/man.rake +7 -0
  38. data/tasks/this.rb +5 -5
  39. data/test/data/Gemfile.lock.example +56 -0
  40. data/{spec → test}/data/gemcutter/gems/foo-1.0.0.gem +0 -0
  41. data/{spec → test}/data/gems/bar-1.0.0.gem +0 -0
  42. data/{spec → test}/data/gems/baz-3.1.4-java.gem +0 -0
  43. data/{spec → test}/data/gems/baz-3.1.4.gem +0 -0
  44. data/{spec → test}/data/gems/foo-1.0.0.gem +0 -0
  45. data/{spec → test}/data/gems/foo-2.0.0a.gem +0 -0
  46. data/test/data/specifications/bar-1.0.0.gemspec +31 -0
  47. data/test/data/specifications/baz-3.1.4-java.gemspec +32 -0
  48. data/test/data/specifications/baz-3.1.4.gemspec +31 -0
  49. data/test/data/specifications/foo-1.0.0.gemspec +31 -0
  50. data/test/data/specifications/foo-2.0.0a.gemspec +32 -0
  51. data/test/index_test_helpers.rb +75 -0
  52. data/test/middleware/test_local.rb +75 -0
  53. data/test/middleware/test_not_found.rb +26 -0
  54. data/test/repository/test_api.rb +49 -0
  55. data/test/repository/test_api_behavior.rb +208 -0
  56. data/test/repository/test_index.rb +48 -0
  57. data/test/repository/test_local.rb +59 -0
  58. data/test/repository/test_null.rb +15 -0
  59. data/test/repository/test_remote.rb +26 -0
  60. data/test/repository/test_remote_authenticated.rb +39 -0
  61. data/test/stickler_test_server.rb +35 -0
  62. data/test/test_gemfile_lock_parser.rb +28 -0
  63. data/test/test_paths.rb +22 -0
  64. data/test/test_spec_lite.rb +90 -0
  65. data/test/test_stickler.rb +49 -0
  66. metadata +58 -85
  67. data/README.rdoc +0 -156
  68. data/spec/index_spec_helpers.rb +0 -73
  69. data/spec/middleware/local_spec.rb +0 -72
  70. data/spec/middleware/not_found_spec.rb +0 -25
  71. data/spec/paths_spec.rb +0 -11
  72. data/spec/repository/api_behavior.rb +0 -192
  73. data/spec/repository/api_spec.rb +0 -37
  74. data/spec/repository/index_spec.rb +0 -46
  75. data/spec/repository/local_spec.rb +0 -49
  76. data/spec/repository/null_spec.rb +0 -14
  77. data/spec/repository/remote_spec.rb +0 -86
  78. data/spec/spec.opts +0 -2
  79. data/spec/spec_helper.rb +0 -24
  80. data/spec/spec_lite_spec.rb +0 -96
@@ -0,0 +1,75 @@
1
+ require 'test_stickler'
2
+
3
+ module Stickler
4
+ class MiddlewareLocalTest < Test
5
+ include IndexTestHelpers
6
+ include Rack::Test::Methods
7
+
8
+ def app
9
+ repo_root = @idx_test_datadir
10
+ ::Rack::Builder.new do
11
+ use ::Stickler::Middleware::Compression
12
+ use ::Stickler::Middleware::Local, :repo_root => repo_root
13
+ run ::Sinatra::Base
14
+ end
15
+ end
16
+ end
17
+
18
+ class MiddlewareLocalModernTest < MiddlewareLocalTest
19
+ def setup
20
+ mirror_spec_gemdir
21
+ make_modern_index
22
+ end
23
+
24
+ def teardown
25
+ destroy_scratch_dir
26
+ end
27
+
28
+ def test_returns_the_same_bytes_as_gem_indexer
29
+ [
30
+ "/specs.#{Gem.marshal_version}",
31
+ "/specs.#{Gem.marshal_version}.gz",
32
+ "/latest_specs.#{Gem.marshal_version}",
33
+ "/latest_specs.#{Gem.marshal_version}.gz",
34
+ "/prerelease_specs.#{Gem.marshal_version}",
35
+ "/prerelease_specs.#{Gem.marshal_version}.gz",
36
+ "/quick/Marshal.#{Gem.marshal_version}/foo-1.0.0.gemspec.rz",
37
+ "/quick/Marshal.#{Gem.marshal_version}/bar-1.0.0.gemspec.rz",
38
+ "/quick/Marshal.#{Gem.marshal_version}/foo-2.0.0a.gemspec.rz",
39
+ "/quick/Marshal.#{Gem.marshal_version}/baz-3.1.4-java.gemspec.rz",
40
+ "/quick/Marshal.#{Gem.marshal_version}/baz-3.1.4.gemspec.rz",
41
+ ].each do |path|
42
+ response = get( path )
43
+ need, got = validate_contents( response.body,
44
+ IO.read( File.join(@scratch_datadir, path) ),
45
+ response.content_type )
46
+ assert_equal need, got, "Match failure for #{path}"
47
+ end
48
+ end
49
+ end
50
+
51
+ class MiddlewareLocalLegacyTest < MiddlewareLocalTest
52
+ def setup
53
+ mirror_spec_gemdir
54
+ make_legacy_index
55
+ end
56
+
57
+ def teardown
58
+ destroy_scratch_dir
59
+ end
60
+
61
+ def test_returns_the_same_bytes_as_gem_indexer
62
+ [
63
+ "/Marshal.#{Gem.marshal_version}",
64
+ "/Marshal.#{Gem.marshal_version}.Z",
65
+ ].each do |path|
66
+ skip "Not testing legacy indexes at the moment"
67
+ response = get( path )
68
+ need, got = validate_contents( response.body,
69
+ IO.read( File.join(@scratch_datadir, path) ),
70
+ response.content_type )
71
+ assert_equal need, got, "Match failure for #{path}"
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,26 @@
1
+ require 'test_stickler'
2
+
3
+ module Stickler
4
+ class MiddlewareNotFound < Test
5
+ include Rack::Test::Methods
6
+ def app
7
+ ::Stickler::Middleware::NotFound.new
8
+ end
9
+
10
+ def setup
11
+ get "/"
12
+ end
13
+
14
+ def test_responds_with_404_to_everything
15
+ assert_equal 404, last_response.status
16
+ end
17
+
18
+ def test_resturns_html_page
19
+ assert_equal 'text/html', last_response.content_type
20
+ end
21
+
22
+ def test_body_says_look_elsewhere
23
+ assert_match( /Not Found/, last_response.body)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,49 @@
1
+ require 'test_stickler'
2
+ require 'digest/sha1'
3
+
4
+ module Stickler
5
+ module RepositoryApiTests
6
+ def test_implements_all_the_api_methods
7
+ Stickler::Repository::Api.api_methods.each do |method|
8
+ assert_respond_to repo, method
9
+ end
10
+ end
11
+ end
12
+
13
+ # Stub class for testing
14
+ module Repository
15
+ class Stub
16
+ include Stickler::Repository::Api
17
+ end
18
+ end
19
+
20
+ class RepositoryApiModuleTest < Test
21
+ include RepositoryApiTests
22
+
23
+ def repo
24
+ @repo ||= Stickler::Repository::Stub.new
25
+ end
26
+
27
+ def setup
28
+ @spec = Stickler::SpecLite.new( "foo", "1.0.0" )
29
+ end
30
+
31
+ def test_raising_error_on_unimplemented_methods
32
+ %w[ uri gems_uri ].each do |method|
33
+ assert_raises( NotImplementedError ) { repo.send( method ) }
34
+ end
35
+ end
36
+
37
+ def test_raising_error_on_unimplemented_methods_taking_a_spec
38
+ %w[ uri_for_gem search_for delete yank get open ].each do |method|
39
+ assert_raises( NotImplementedError ) { repo.send( method, @spec ) }
40
+ end
41
+ end
42
+
43
+ def test_raising_error_on_implemented_methods_taking_an_object
44
+ %w[ push ].each do |method|
45
+ assert_raises( NotImplementedError ) { repo.send( method, Object.new ) }
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,208 @@
1
+ require 'test_stickler'
2
+ require 'digest/sha1'
3
+ require 'repository/test_api'
4
+
5
+ module Stickler
6
+ module RepositoryApiBehaviorTests
7
+ include RepositoryApiTests
8
+ def setup
9
+ super
10
+ @foo_gem_local_path = File.join( gems_dir, "foo-1.0.0.gem" )
11
+ @foo_spec = Stickler::SpecLite.new( 'foo', '1.0.0' )
12
+ assert File.readable?( @foo_gem_local_path ), "#{@foo_gem_local_path} is missing"
13
+ @foo_digest = Digest::SHA1.hexdigest( IO.read( @foo_gem_local_path ) )
14
+ @missing_spec = Stickler::SpecLite.new( "does_not_exist", "0.1.0" )
15
+ end
16
+
17
+ #####
18
+ # URI
19
+ #####
20
+
21
+ def test_uri
22
+ result = repo.uri
23
+ assert_includes [ ::URI, ::Addressable::URI ], result.class
24
+ end
25
+
26
+ def test_gems_uri
27
+ result = repo.gems_uri
28
+ assert_includes [ ::URI, ::Addressable::URI ], result.class
29
+ end
30
+
31
+ def test_uri_for_gem
32
+ repo.push( @foo_gem_local_path )
33
+ result = repo.uri_for_gem( @foo_spec )
34
+ assert_includes [ ::URI, ::Addressable::URI ], result.class
35
+ assert_nil repo.uri_for_gem( @missing_spec )
36
+ end
37
+
38
+ #######
39
+ # Push
40
+ #######
41
+
42
+ def test_pushes_a_gem_file
43
+ repo.push( @foo_gem_local_path )
44
+ result = repo.search_for( Stickler::SpecLite.new( "foo", "1.0.0" ) )
45
+ assert_instance_of Array, result
46
+ assert_equal 1, result.size
47
+ end
48
+
49
+ def test_raising_error_when_pushing_already_existing_gem
50
+ repo.push( @foo_gem_local_path )
51
+ assert_raises_kind_of( Stickler::Repository::Error ) do
52
+ repo.push( @foo_gem_local_path )
53
+ end
54
+ end
55
+
56
+ ########
57
+ # Delete
58
+ ########
59
+
60
+ def test_delete_existing_gem
61
+ assert_empty repo.search_for( @foo_spec )
62
+ repo.push( @foo_gem_local_path )
63
+
64
+ assert_equal 1, repo.search_for( @foo_spec ).size
65
+
66
+ assert repo.delete( @foo_spec )
67
+ assert_empty repo.search_for( @foo_spec )
68
+ end
69
+
70
+ def test_delete_non_existing_gem
71
+ assert_empty repo.search_for( @foo_spec )
72
+ refute repo.delete( @foo_spec )
73
+ end
74
+
75
+ ######
76
+ # yank
77
+ ######
78
+
79
+ def test_yank_returns_the_uri_of_the_gem
80
+ assert_empty repo.search_for( @foo_spec )
81
+ repo.push( @foo_gem_local_path )
82
+ @response_uri = repo.yank( @foo_spec )
83
+ assert_includes [ ::URI, ::Addressable::URI ], @response_uri.class
84
+ end
85
+
86
+ def test_yank_returns_nil_for_non_existent_gem
87
+ assert_nil repo.yank( @missing_spec )
88
+ end
89
+
90
+ def test_yanked_gem_does_not_appear_in_search
91
+ assert_empty repo.search_for( @foo_spec )
92
+ repo.push( @foo_gem_local_path )
93
+ @response_uri = repo.yank( @foo_spec )
94
+ assert_empty repo.search_for( @foo_spec )
95
+ end
96
+
97
+ def test_yanked_gem_does_still_have_a_uri
98
+ assert_empty repo.search_for( @foo_spec )
99
+ repo.push( @foo_gem_local_path )
100
+ @response_uri = repo.yank( @foo_spec )
101
+ assert_equal @response_uri, repo.uri_for_gem( @foo_spec )
102
+ end
103
+
104
+ def test_yanked_gem_may_still_be_retrieved
105
+ assert_empty repo.search_for( @foo_spec )
106
+ repo.push( @foo_gem_local_path )
107
+ data = repo.get( @foo_spec )
108
+ sha1 = Digest::SHA1.hexdigest( data )
109
+ assert_equal @foo_digest, sha1
110
+ end
111
+
112
+ ########
113
+ # unyank
114
+ ########
115
+
116
+ def test_unyank_returns_nil_for_non_existent_gem
117
+ assert_empty repo.search_for( @foo_spec )
118
+ repo.push( @foo_gem_local_path )
119
+ non_existing_gem = @missing_spec
120
+ assert_nil repo.unyank( non_existing_gem )
121
+ end
122
+
123
+
124
+ # Do we even care about this?
125
+ def test_unyank_returns_nil_for_not_yet_yanked_gem
126
+ assert_empty repo.search_for( @foo_spec )
127
+ repo.push( @foo_gem_local_path )
128
+ assert_equal 1, repo.search_for( @foo_spec ).size
129
+ assert_nil repo.unyank( @foo_spec )
130
+ end
131
+
132
+ def test_unyank_returns_true_on_success
133
+ assert_empty repo.search_for( @foo_spec )
134
+ repo.push( @foo_gem_local_path )
135
+ repo.yank( @foo_spec )
136
+ assert repo.unyank( @foo_spec ), "Expected true"
137
+ end
138
+
139
+ def test_unyank_returns_gem_to_searchability
140
+ assert_empty repo.search_for( @foo_spec )
141
+ repo.push( @foo_gem_local_path )
142
+ repo.yank( @foo_spec )
143
+ repo.unyank( @foo_spec )
144
+ assert_equal 1, repo.search_for( @foo_spec ).size
145
+ end
146
+
147
+ ############
148
+ # Search For
149
+ ############
150
+
151
+ def test_search_for_returns_found_items
152
+ repo.push( @foo_gem_local_path )
153
+ refute_empty repo.search_for( @foo_spec )
154
+ end
155
+
156
+ def test_search_for_returns_empty_array_when_nothing_found
157
+ assert_empty repo.search_for( @missing_spec )
158
+ end
159
+
160
+
161
+ #####
162
+ # GET
163
+ #####
164
+
165
+ def test_get_returns_the_bytes_of_a_gem_that_exists
166
+ repo.push( @foo_gem_local_path )
167
+ data = repo.get( @foo_spec )
168
+ sha1 = Digest::SHA1.hexdigest( data )
169
+ assert_equal @foo_digest, sha1
170
+ end
171
+
172
+ def test_get_returns_nil_for_non_existent_gem
173
+ assert_nil repo.get( @missing_spec )
174
+ end
175
+
176
+ ######
177
+ # open
178
+ ######
179
+
180
+ def test_open_reads_a_gem_via_the_returned_output_stream
181
+ repo.push( @foo_gem_local_path )
182
+ io = repo.open( @foo_spec )
183
+ sha1 = Digest::SHA1.hexdigest( io.read )
184
+ assert_equal @foo_digest, sha1
185
+ end
186
+
187
+ def test_open_may_be_called_with_a_block
188
+ repo.push( @foo_gem_local_path )
189
+ sha1 = Digest::SHA1.new
190
+ repo.open( @foo_spec ) do |io|
191
+ sha1 << io.read
192
+ end
193
+ assert_equal @foo_digest, sha1.hexdigest
194
+ end
195
+
196
+ def test_open_returns_nil_for_non_existent_gem
197
+ assert_nil repo.open( @missing_spec )
198
+ end
199
+
200
+ def test_open_does_not_call_block_for_non_existent_gem
201
+ called = false
202
+ repo.open( @missing_spec ) do |io|
203
+ called = true
204
+ end
205
+ refute called
206
+ end
207
+ end
208
+ end
@@ -0,0 +1,48 @@
1
+ require 'test_stickler'
2
+
3
+ module Stickler
4
+ class TestIndexRepository < Test
5
+ def setup
6
+ @index_me = File.join( test_dir, "tmp" )
7
+ FileUtils.mkdir_p( @index_me )
8
+
9
+ @specifications = Dir.glob( File.join( specifications_dir, "*.gemspec" ) )
10
+ @specifications.each do |s|
11
+ FileUtils.cp( s, @index_me )
12
+ end
13
+ @index = ::Stickler::Repository::Index.new( @index_me )
14
+ end
15
+
16
+ def teardown
17
+ FileUtils.rm_rf( @index_me )
18
+ end
19
+
20
+ def test_all_gemspec_files_in_a_directory_are_indexed
21
+ assert_equal @specifications.size, @index.specs.size
22
+ end
23
+
24
+ def test_notice_changes_in_the_index
25
+ assert_equal @specifications.size, @index.specs.size
26
+ FileUtils.rm( File.join( @index_me, "foo-1.0.0.gemspec" ) )
27
+ assert_equal @specifications.size-1, @index.specs.size
28
+ end
29
+
30
+ def test_latest_specs
31
+ assert_equal( @specifications.size - 1, @index.latest_specs.size )
32
+ expected = %w[ bar-1.0.0 baz-3.1.4 baz-3.1.4-java foo-1.0.0 ]
33
+ assert_equal expected, @index.latest_specs.collect { |s| s.full_name }.sort
34
+ end
35
+
36
+ def test_pre_release_specs
37
+ assert_equal 1, @index.prerelease_specs.size
38
+ assert_equal "foo-2.0.0a",@index.prerelease_specs.first.full_name
39
+ end
40
+
41
+ def test_released_specs
42
+ assert_equal 4, @index.released_specs.size
43
+ expected = %w[ bar-1.0.0 baz-3.1.4 baz-3.1.4-java foo-1.0.0 ]
44
+ assert_equal expected, @index.released_specs.collect { |s| s.full_name }.sort
45
+ end
46
+ end
47
+ end
48
+
@@ -0,0 +1,59 @@
1
+ require 'test_stickler'
2
+ require 'repository/test_api_behavior'
3
+
4
+ module Stickler
5
+ class LocalRepositoryTest < Test
6
+ include RepositoryApiBehaviorTests
7
+
8
+ def repos_dir
9
+ File.join( test_dir, "repos" )
10
+ end
11
+
12
+ def repo_dir
13
+ File.join( repos_dir, "1" )
14
+ end
15
+
16
+ def repo
17
+ @repo ||= ::Stickler::Repository::Local.new( repo_dir )
18
+ end
19
+
20
+ def teardown
21
+ super
22
+ FileUtils.rm_rf( repos_dir )
23
+ end
24
+
25
+ def test_creates_gems_directory
26
+ repo.gems_dir
27
+ new_dir = File.join( repo_dir , 'gems') + File::SEPARATOR
28
+ assert File.directory?( new_dir ), "#{new_dir} must be a directory"
29
+ assert_equal new_dir, repo.gems_dir
30
+ end
31
+
32
+ def test_creates_specifications_directory
33
+ repo.specifications_dir
34
+ new_dir = File.join( repo_dir , 'specifications' ) + File::SEPARATOR
35
+ assert File.directory?( new_dir ), "#{new_dir} must be a directory"
36
+ assert_equal new_dir, repo.specifications_dir
37
+ end
38
+
39
+ def test_lists_all_specs_in_the_repo
40
+ Dir.glob( File.join( gems_dir, "*.gem" ) ).each do |gem|
41
+ repo.push( gem )
42
+ end
43
+ assert_equal 5, repo.specs.size
44
+ end
45
+
46
+ def test_two_instances_with_the_same_repo_dir_are_the_same_object
47
+ repo2 = ::Stickler::Repository::Local.new( File.join( repos_dir, '1') )
48
+ assert_equal repo.object_id, repo2.object_id
49
+ assert_equal 1, ::Stickler::Repository::Local.repos.size
50
+ end
51
+
52
+ def test_tracks_all_repository_instances
53
+ ::Stickler::Repository::Local.new( File.join( repos_dir, "2" ) )
54
+ ::Stickler::Repository::Local.new( File.join( repos_dir, "3" ) )
55
+ assert_equal 2, ::Stickler::Repository::Local.repos.size
56
+ end
57
+ end
58
+ end
59
+