stickler 0.1.1 → 2.0.0a

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 (72) hide show
  1. data/HISTORY.rdoc +5 -2
  2. data/Rakefile +31 -0
  3. data/examples/config.ru +9 -0
  4. data/examples/gemcutter_repo.ru +19 -0
  5. data/examples/index_repo.ru +15 -0
  6. data/examples/local_repo.ru +14 -0
  7. data/examples/mirror_repo.ru +16 -0
  8. data/examples/not_found.ru +8 -0
  9. data/lib/stickler/error.rb +3 -0
  10. data/lib/stickler/middleware/compression.rb +30 -0
  11. data/lib/stickler/middleware/gemcutter.rb +62 -0
  12. data/lib/stickler/middleware/helpers.rb +84 -0
  13. data/lib/stickler/middleware/index.rb +137 -0
  14. data/lib/stickler/middleware/local.rb +38 -0
  15. data/lib/stickler/middleware/mirror.rb +60 -0
  16. data/lib/stickler/middleware/not_found.rb +62 -0
  17. data/lib/stickler/middleware.rb +4 -0
  18. data/lib/stickler/repository/api.rb +167 -0
  19. data/lib/stickler/repository/index.rb +97 -0
  20. data/lib/stickler/repository/local.rb +251 -0
  21. data/lib/stickler/repository/mirror.rb +48 -0
  22. data/lib/stickler/repository/null.rb +58 -0
  23. data/lib/stickler/repository/remote.rb +235 -0
  24. data/lib/stickler/repository.rb +7 -499
  25. data/lib/stickler/spec_lite.rb +60 -14
  26. data/lib/stickler/version.rb +6 -6
  27. data/lib/stickler/web.rb +19 -0
  28. data/spec/data/gems/bar-1.0.0.gem +0 -0
  29. data/spec/data/gems/foo-1.0.0.gem +0 -0
  30. data/spec/data/specifications/bar-1.0.0.gemspec +31 -0
  31. data/spec/data/specifications/foo-1.0.0.gemspec +31 -0
  32. data/spec/middleware/common_gem_server_helpers.rb +67 -0
  33. data/spec/middleware/index_spec.rb +26 -0
  34. data/spec/middleware/legacy_gem_server_behavior.rb +33 -0
  35. data/spec/middleware/local_spec.rb +25 -0
  36. data/spec/middleware/modern_gem_server_behavior.rb +20 -0
  37. data/spec/middleware/not_found_spec.rb +25 -0
  38. data/spec/repository/api_behavior.rb +162 -0
  39. data/spec/repository/api_spec.rb +38 -0
  40. data/spec/repository/index_spec.rb +32 -0
  41. data/spec/repository/local_spec.rb +36 -0
  42. data/spec/repository/null_spec.rb +17 -0
  43. data/spec/repository/remote_spec.rb +49 -0
  44. data/spec/spec.opts +2 -0
  45. data/spec/spec_helper.rb +15 -3
  46. data/spec/spec_lite_spec.rb +62 -0
  47. data/stickler.gemspec +60 -0
  48. data/views/index.erb +19 -0
  49. data/views/layout.erb +39 -0
  50. metadata +93 -63
  51. data/COPYING +0 -339
  52. data/bin/stickler +0 -58
  53. data/data/stickler.yml +0 -14
  54. data/gemspec.rb +0 -62
  55. data/lib/stickler/cli.rb +0 -302
  56. data/lib/stickler/configuration.rb +0 -74
  57. data/lib/stickler/console.rb +0 -72
  58. data/lib/stickler/paths.rb +0 -62
  59. data/lib/stickler/source.rb +0 -75
  60. data/lib/stickler/source_group.rb +0 -365
  61. data/lib/stickler.rb +0 -19
  62. data/spec/configuration_spec.rb +0 -68
  63. data/spec/paths_spec.rb +0 -25
  64. data/spec/repository_spec.rb +0 -55
  65. data/spec/version_spec.rb +0 -17
  66. data/tasks/announce.rake +0 -39
  67. data/tasks/config.rb +0 -107
  68. data/tasks/distribution.rake +0 -45
  69. data/tasks/documentation.rake +0 -31
  70. data/tasks/rspec.rake +0 -29
  71. data/tasks/rubyforge.rake +0 -51
  72. data/tasks/utils.rb +0 -80
@@ -0,0 +1,235 @@
1
+ require 'resourceful'
2
+ require 'stickler/repository'
3
+ require 'stickler/repository/api'
4
+ require 'stringio'
5
+
6
+ module ::Stickler::Repository
7
+ #
8
+ # A Repository::Api implementation that retrieves all is data from an HTTP
9
+ # based remote location. It utilizes the Modern gem server api and the gem
10
+ # cutter api (push/yank/unyank). The legacy gem server api is not utilized.
11
+ #
12
+ class Remote
13
+ # the http client
14
+ attr_reader :http
15
+
16
+ def initialize( repo_uri )
17
+ @uri = Addressable::URI.parse( ensure_http( ensure_trailing_slash( repo_uri ) ) )
18
+ @http = Resourceful::HttpAccessor.new( :cache_manager => Resourceful::InMemoryCacheManager.new )
19
+ # :logger => Resourceful::StdOutLogger.new )
20
+ @specs_list = nil
21
+ end
22
+
23
+ #
24
+ # See Api#uri
25
+ def uri
26
+ @uri
27
+ end
28
+
29
+ #
30
+ # See Api#gems_uri
31
+ #
32
+ def gems_uri
33
+ @gems_uri ||= self.uri.join( "gems/" )
34
+ end
35
+
36
+ #
37
+ # See Api#uri_from_gem
38
+ #
39
+ def uri_for_gem( spec )
40
+ return nil unless remote_gem_file_exist?( spec )
41
+ return self.gems_uri.join( spec.file_name )
42
+ end
43
+
44
+ #
45
+ # The array of specs from upstream
46
+ #
47
+ def specs_list
48
+ Marshal.load( download_specs_list )
49
+ end
50
+
51
+ #
52
+ # See Api#search_for
53
+ #
54
+ def search_for( spec )
55
+ found = []
56
+ specs_list.each do |name, version, platform|
57
+ up_spec = Stickler::SpecLite.new( name, version, platform )
58
+ found << up_spec if spec =~ up_spec
59
+ end
60
+ return found
61
+ end
62
+
63
+ #
64
+ # See Api#get
65
+ #
66
+ def get( spec )
67
+ return download_gem( spec ) if remote_gem_file_exist?( spec )
68
+ return nil
69
+ end
70
+
71
+ #
72
+ # See Api#push
73
+ #
74
+ def push( path )
75
+ spec = speclite_from_gem_file( path )
76
+ raise Stickler::Repository::Error, "gem #{spec.full_name} already exists in remote repository" if remote_gem_file_exist?( spec )
77
+ begin
78
+ resp = push_resource.post( IO.read( path ) )
79
+ rescue Resourceful::UnsuccessfulHttpRequestError => e
80
+ msg = "Failure pushing #{path} to remote repository : response code => #{e.http_response.code}, response message => '#{e.http_response.body}'"
81
+ raise Stickler::Repository::Error, msg
82
+ end
83
+ return spec
84
+ end
85
+
86
+ #
87
+ # See Api#yank
88
+ #
89
+ def yank( spec )
90
+ return nil unless remote_gem_file_exist?( spec )
91
+ begin
92
+ form_data = Resourceful::UrlencodedFormData.new
93
+ form_data.add( "gem_name", spec.name )
94
+ form_data.add( "version", spec.version.to_s )
95
+ yank_resource.request( :delete, form_data.read, {'Content-Type' => form_data.content_type } )
96
+ return full_uri_to_gem( spec )
97
+ rescue Resourceful::UnsuccessfulHttpRequestError => e
98
+ raise Stickler::Repository::Error, "Failure yanking: #{e.inspect}"
99
+ end
100
+ end
101
+
102
+ #
103
+ # See Api#delete
104
+ #
105
+ def delete( spec )
106
+ return false unless remote_gem_file_exist?( spec )
107
+ begin
108
+ gem_resource( spec ).delete
109
+ return true
110
+ rescue Resourceful::UnsuccessfulHttpRequestError => e
111
+ return false
112
+ end
113
+ end
114
+
115
+ #
116
+ # See Api#open
117
+ #
118
+ def open( spec, &block )
119
+ return nil unless remote_gem_file_exist?( spec )
120
+ begin
121
+ data = download_resource( gem_resource( spec ) )
122
+ io = StringIO.new( data , "rb" )
123
+ if block_given? then
124
+ begin
125
+ yield io
126
+ ensure
127
+ io.close
128
+ end
129
+ else
130
+ return io
131
+ end
132
+ rescue Resourceful::UnsuccessfulHttpRequestError => e
133
+ return nil
134
+ end
135
+ nil
136
+ end
137
+
138
+ private
139
+
140
+ def ensure_trailing_slash( uri )
141
+ uri += '/' unless uri =~ %r{/\Z}
142
+ return uri
143
+ end
144
+
145
+ def ensure_http( uri )
146
+ uri = "http://#{uri}" unless uri =~ %r{\Ahttp(s)?://}
147
+ return uri
148
+ end
149
+
150
+ def full_uri_to_gem( spec )
151
+ gems_uri.join( spec.file_name )
152
+ end
153
+
154
+ def specs_list_uri
155
+ Addressable::URI.join( uri, "specs.#{Gem.marshal_version}.gz" )
156
+ end
157
+
158
+ def specs_list_resource
159
+ @specs_list_resource ||= @http.resource( specs_list_uri )
160
+ end
161
+
162
+ def push_uri
163
+ Addressable::URI.join( uri, "api/v1/gems" )
164
+ end
165
+
166
+ def push_resource
167
+ @push_resource ||= @http.resource( push_uri, { 'Content-Type', 'application/octet-stream' } )
168
+ end
169
+
170
+ def yank_uri
171
+ Addressable::URI.join( uri, "api/v1/gems/yank" )
172
+ end
173
+
174
+ def yank_resource
175
+ @yank_resource ||= @http.resource( yank_uri )
176
+ end
177
+
178
+ def gem_resource( spec )
179
+ @http.resource( full_uri_to_gem( spec ) )
180
+ end
181
+
182
+ def download_specs_list
183
+ download_gzipped_resource( specs_list_resource )
184
+ end
185
+
186
+ def download_gzipped_resource( resource )
187
+ Gem.gunzip( download_resource( resource ) )
188
+ end
189
+
190
+ def download_gem( spec )
191
+ download_uri( full_uri_to_gem( spec ) )
192
+ end
193
+
194
+ def download_uri( uri )
195
+ download_resource( http.resource( uri ) )
196
+ end
197
+
198
+ def download_resource( resource )
199
+ begin
200
+ resource.get.body
201
+ rescue Resourceful::UnsuccessfulHttpRequestError => e
202
+ return false
203
+ end
204
+ end
205
+
206
+ def remote_gem_file_exist?( spec )
207
+ gem_uri = full_uri_to_gem( spec )
208
+ remote_uri_exist?( gem_uri )
209
+ end
210
+
211
+ def remote_uri_exist?( uri )
212
+ begin
213
+ # FIXME: bug in Resourceful that uses cached HEAD responses
214
+ # to satisfy later GET requests.
215
+ rc = http.resource( uri ).head( 'Cache-Control' => 'no-store' ).successful?
216
+ return rc
217
+ rescue Resourceful::UnsuccessfulHttpRequestError => e
218
+ return false
219
+ end
220
+ end
221
+
222
+ def speclite_from_gem_file( path )
223
+ speclite_from_specification( specification_from_gem_file( path ) )
224
+ end
225
+
226
+ def specification_from_gem_file( path )
227
+ format = Gem::Format.from_file_by_path( path )
228
+ return format.spec
229
+ end
230
+
231
+ def speclite_from_specification( spec )
232
+ Stickler::SpecLite.new( spec.name, spec.version.to_s, spec.platform )
233
+ end
234
+ end
235
+ end