stickler 0.1.1 → 2.0.0a
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY.rdoc +5 -2
- data/Rakefile +31 -0
- data/examples/config.ru +9 -0
- data/examples/gemcutter_repo.ru +19 -0
- data/examples/index_repo.ru +15 -0
- data/examples/local_repo.ru +14 -0
- data/examples/mirror_repo.ru +16 -0
- data/examples/not_found.ru +8 -0
- data/lib/stickler/error.rb +3 -0
- data/lib/stickler/middleware/compression.rb +30 -0
- data/lib/stickler/middleware/gemcutter.rb +62 -0
- data/lib/stickler/middleware/helpers.rb +84 -0
- data/lib/stickler/middleware/index.rb +137 -0
- data/lib/stickler/middleware/local.rb +38 -0
- data/lib/stickler/middleware/mirror.rb +60 -0
- data/lib/stickler/middleware/not_found.rb +62 -0
- data/lib/stickler/middleware.rb +4 -0
- data/lib/stickler/repository/api.rb +167 -0
- data/lib/stickler/repository/index.rb +97 -0
- data/lib/stickler/repository/local.rb +251 -0
- data/lib/stickler/repository/mirror.rb +48 -0
- data/lib/stickler/repository/null.rb +58 -0
- data/lib/stickler/repository/remote.rb +235 -0
- data/lib/stickler/repository.rb +7 -499
- data/lib/stickler/spec_lite.rb +60 -14
- data/lib/stickler/version.rb +6 -6
- data/lib/stickler/web.rb +19 -0
- data/spec/data/gems/bar-1.0.0.gem +0 -0
- data/spec/data/gems/foo-1.0.0.gem +0 -0
- data/spec/data/specifications/bar-1.0.0.gemspec +31 -0
- data/spec/data/specifications/foo-1.0.0.gemspec +31 -0
- data/spec/middleware/common_gem_server_helpers.rb +67 -0
- data/spec/middleware/index_spec.rb +26 -0
- data/spec/middleware/legacy_gem_server_behavior.rb +33 -0
- data/spec/middleware/local_spec.rb +25 -0
- data/spec/middleware/modern_gem_server_behavior.rb +20 -0
- data/spec/middleware/not_found_spec.rb +25 -0
- data/spec/repository/api_behavior.rb +162 -0
- data/spec/repository/api_spec.rb +38 -0
- data/spec/repository/index_spec.rb +32 -0
- data/spec/repository/local_spec.rb +36 -0
- data/spec/repository/null_spec.rb +17 -0
- data/spec/repository/remote_spec.rb +49 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +15 -3
- data/spec/spec_lite_spec.rb +62 -0
- data/stickler.gemspec +60 -0
- data/views/index.erb +19 -0
- data/views/layout.erb +39 -0
- metadata +93 -63
- data/COPYING +0 -339
- data/bin/stickler +0 -58
- data/data/stickler.yml +0 -14
- data/gemspec.rb +0 -62
- data/lib/stickler/cli.rb +0 -302
- data/lib/stickler/configuration.rb +0 -74
- data/lib/stickler/console.rb +0 -72
- data/lib/stickler/paths.rb +0 -62
- data/lib/stickler/source.rb +0 -75
- data/lib/stickler/source_group.rb +0 -365
- data/lib/stickler.rb +0 -19
- data/spec/configuration_spec.rb +0 -68
- data/spec/paths_spec.rb +0 -25
- data/spec/repository_spec.rb +0 -55
- data/spec/version_spec.rb +0 -17
- data/tasks/announce.rake +0 -39
- data/tasks/config.rb +0 -107
- data/tasks/distribution.rake +0 -45
- data/tasks/documentation.rake +0 -31
- data/tasks/rspec.rake +0 -29
- data/tasks/rubyforge.rake +0 -51
- data/tasks/utils.rb +0 -80
data/lib/stickler/repository.rb
CHANGED
@@ -1,502 +1,10 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
#++
|
6
|
-
|
7
|
-
require 'stickler'
|
8
|
-
require 'fileutils'
|
9
|
-
require 'ostruct'
|
10
|
-
require 'highline'
|
11
|
-
require 'stickler/configuration'
|
12
|
-
require 'stickler/source_group'
|
1
|
+
require 'stickler/error'
|
2
|
+
require 'rubygems/format'
|
3
|
+
require 'rubygems/platform'
|
4
|
+
require 'rubygems/dependency'
|
13
5
|
|
14
6
|
module Stickler
|
15
|
-
|
16
|
-
|
17
|
-
# is very similar to a GEM_HOME directory. The layout is as follows, this is
|
18
|
-
# all assumed to be under STICKLER_HOME.
|
19
|
-
#
|
20
|
-
# stickler.yml - the Stickler configuration file for this repository.
|
21
|
-
# The existence of this file indicates this is the root
|
22
|
-
# of a stickler repository
|
23
|
-
# gems/ - storage of the actual gem files
|
24
|
-
# cache/ - cache of gem files downloaded from upstream sources
|
25
|
-
# managed by the rubygems fetcher classes
|
26
|
-
# specifications/ - ruby gemspec files
|
27
|
-
# log/ - directory holding rotating logs files for stickler
|
28
|
-
# dist/ - directory holding the distributable gem index location,
|
29
|
-
# rsync this to your webserver, or serve from it directly.
|
30
|
-
#
|
31
|
-
#
|
32
|
-
class Repository
|
33
|
-
class Error < ::StandardError ; end
|
34
|
-
|
35
|
-
# The repository directory. the directory containing the stickler.yml file
|
36
|
-
attr_reader :directory
|
37
|
-
|
38
|
-
# The configuration
|
39
|
-
attr_reader :configuration
|
40
|
-
|
41
|
-
# Are requrements satisfied in a minimal or maximal approach
|
42
|
-
attr_reader :requirement_satisfaction_behavior
|
43
|
-
|
44
|
-
class << self
|
45
|
-
def other_dir_names
|
46
|
-
%w[ gems_dir log_dir specification_dir dist_dir cache_dir ]
|
47
|
-
end
|
48
|
-
|
49
|
-
def config_file_basename
|
50
|
-
"stickler.yml"
|
51
|
-
end
|
52
|
-
|
53
|
-
def basedir
|
54
|
-
"stickler"
|
55
|
-
end
|
56
|
-
|
57
|
-
#
|
58
|
-
# What should the default stickler directory be, this is one of two
|
59
|
-
# things. If there is a stickler.yml file in the current directory, then
|
60
|
-
# the default directory is the current directory, otherwise, it is the
|
61
|
-
# _stickler_ directory below the current_directory
|
62
|
-
#
|
63
|
-
def default_directory
|
64
|
-
defaults = [ File.join( Dir.pwd, config_file_basename ), File.join( Dir.pwd, basedir ) ]
|
65
|
-
defaults.each do |def_dir|
|
66
|
-
if File.exist?( def_dir ) then
|
67
|
-
return File.dirname( def_dir ) if File.file?( def_dir )
|
68
|
-
return def_dir
|
69
|
-
end
|
70
|
-
end
|
71
|
-
return defaults.last
|
72
|
-
end
|
73
|
-
|
74
|
-
#
|
75
|
-
# gem requirement information
|
76
|
-
#
|
77
|
-
def requirement_meta
|
78
|
-
[ [ "=" , "Equals version" ],
|
79
|
-
[ "!=" , "Not equal to version" ],
|
80
|
-
[ ">" , "Greater than version" ],
|
81
|
-
[ "<" , "Less than version" ],
|
82
|
-
[ ">=" , "Greater than or equal to" ],
|
83
|
-
[ "<=" , "Less than or equal to" ],
|
84
|
-
[ "~>" , "Approximately greater than" ]]
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
#
|
89
|
-
# Initialize a stickler repository
|
90
|
-
#
|
91
|
-
def initialize( opts )
|
92
|
-
|
93
|
-
@directory = File.expand_path( opts['directory'] )
|
94
|
-
@requirement_satisfaction_behavior = ( opts['requirements'] || "maximum" ).to_sym
|
95
|
-
enhance_logging( opts ) if File.directory?( log_dir )
|
96
|
-
@overwrite = opts['force']
|
97
|
-
|
98
|
-
@configuration = nil
|
99
|
-
load_configuration if File.exist?( config_file )
|
100
|
-
|
101
|
-
end
|
102
|
-
|
103
|
-
def configuration_loaded?
|
104
|
-
@configuration.nil?
|
105
|
-
end
|
106
|
-
|
107
|
-
#
|
108
|
-
# should existing items be overwritten
|
109
|
-
#
|
110
|
-
def overwrite?
|
111
|
-
@overwrite
|
112
|
-
end
|
113
|
-
|
114
|
-
#
|
115
|
-
# update logging by turning on a log file in the repository directory, and
|
116
|
-
# possibly turning off the stdout logger that is the default.
|
117
|
-
#
|
118
|
-
def enhance_logging( opts )
|
119
|
-
|
120
|
-
layout = ::Logging::Layouts::Pattern.new(
|
121
|
-
:pattern => "[%d] %c %6p %5l : %m\n",
|
122
|
-
:date_pattern => "%Y-%m-%d %H:%M:%S"
|
123
|
-
)
|
124
|
-
Logging::Logger.root.add_appenders ::Logging::Appenders::RollingFile.new( 'stickler_rolling_logfile',
|
125
|
-
{ :filename => log_file,
|
126
|
-
:layout => layout,
|
127
|
-
# at 5MB roll the log
|
128
|
-
:size => 5 * (1024**2),
|
129
|
-
:keep => 5,
|
130
|
-
:safe => true,
|
131
|
-
:level => :debug
|
132
|
-
})
|
133
|
-
end
|
134
|
-
|
135
|
-
#
|
136
|
-
# return a handle to the repository configuration found in stickler.yml.
|
137
|
-
#
|
138
|
-
def load_configuration
|
139
|
-
begin
|
140
|
-
@configuration = Configuration.new( config_file )
|
141
|
-
source_group # force load
|
142
|
-
rescue => e
|
143
|
-
logger.error "Failure to load configuration #{e}"
|
144
|
-
exit 1
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
#
|
149
|
-
# The configuration file for the repository
|
150
|
-
#
|
151
|
-
def config_file
|
152
|
-
@config_file ||= File.join( directory, Repository.config_file_basename )
|
153
|
-
end
|
154
|
-
|
155
|
-
#
|
156
|
-
# The log directory
|
157
|
-
#
|
158
|
-
def log_dir
|
159
|
-
@log_dir ||= File.join( directory, 'log' )
|
160
|
-
end
|
161
|
-
|
162
|
-
#
|
163
|
-
# The log file
|
164
|
-
#
|
165
|
-
def log_file
|
166
|
-
@log_file ||= File.join( log_dir, 'stickler.log' )
|
167
|
-
end
|
168
|
-
|
169
|
-
#
|
170
|
-
# The gem storage directory.
|
171
|
-
#
|
172
|
-
# This holds the raw gem files downloaded from the sources. This is
|
173
|
-
# equivalent to a gem installations 'gems' directory.
|
174
|
-
#
|
175
|
-
def gems_dir
|
176
|
-
@gems_dir ||= File.join( directory, 'gems' )
|
177
|
-
end
|
178
|
-
|
179
|
-
#
|
180
|
-
# The Gem specification directory
|
181
|
-
#
|
182
|
-
def specification_dir
|
183
|
-
@specification_dir ||= File.join( directory, 'specifications' )
|
184
|
-
end
|
185
|
-
|
186
|
-
#
|
187
|
-
# The cache dir for the downloads
|
188
|
-
#
|
189
|
-
def cache_dir
|
190
|
-
@cache_dir ||= File.join( directory, 'cache' )
|
191
|
-
end
|
192
|
-
|
193
|
-
#
|
194
|
-
# The Distribution directory
|
195
|
-
#
|
196
|
-
# this is the document root for the webserver that will serve your rubygems.
|
197
|
-
# Or they can be served directly from this location
|
198
|
-
#
|
199
|
-
def dist_dir
|
200
|
-
@dist_dir ||= File.join( directory, 'dist' )
|
201
|
-
end
|
202
|
-
|
203
|
-
#
|
204
|
-
# logging handler
|
205
|
-
#
|
206
|
-
def logger
|
207
|
-
@logger ||= ::Logging::Logger[self]
|
208
|
-
end
|
209
|
-
|
210
|
-
#
|
211
|
-
# The SourceGroup containing all of the sources for this repository
|
212
|
-
#
|
213
|
-
def source_group
|
214
|
-
unless @source_group
|
215
|
-
sg = SourceGroup.new( self )
|
216
|
-
Console.info "Setting up sources"
|
217
|
-
configuration.sources.each do |source_uri|
|
218
|
-
sg.add_source( source_uri )
|
219
|
-
end
|
220
|
-
@source_group = sg
|
221
|
-
end
|
222
|
-
return @source_group
|
223
|
-
end
|
224
|
-
|
225
|
-
#
|
226
|
-
# Is the repository valid?
|
227
|
-
#
|
228
|
-
def valid?
|
229
|
-
if @valid.nil? then
|
230
|
-
begin
|
231
|
-
valid!
|
232
|
-
@valid = true
|
233
|
-
rescue StandardError => e
|
234
|
-
logger.error "Repository is not valid : #{e}"
|
235
|
-
@valid = false
|
236
|
-
end
|
237
|
-
end
|
238
|
-
return @valid
|
239
|
-
end
|
240
|
-
|
241
|
-
#
|
242
|
-
# raise an error if the repository is not valid
|
243
|
-
#
|
244
|
-
def valid!
|
245
|
-
raise Error, "#{directory} does not exist" unless File.exist?( directory )
|
246
|
-
raise Error, "#{directory} is not writable" unless File.writable?( directory )
|
247
|
-
|
248
|
-
raise Error, "#{config_file} does not exist" unless File.exist?( config_file )
|
249
|
-
raise Error, "#{config_file} is not loaded" unless configuration
|
250
|
-
|
251
|
-
Repository.other_dir_names.each do |method|
|
252
|
-
other_dir = self.send( method )
|
253
|
-
raise Error, "#{other_dir} does not exist" unless File.exist?( other_dir )
|
254
|
-
raise Error, "#{other_dir} is not writeable" unless File.writable?( other_dir )
|
255
|
-
end
|
256
|
-
|
257
|
-
if File.exist?( log_file ) then
|
258
|
-
raise Error, "#{log_file} is not writable" unless File.writable?( log_file )
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
|
-
#
|
263
|
-
# Setup the repository.
|
264
|
-
#
|
265
|
-
# This is executed with the 'setup' mode on the command line. Only those
|
266
|
-
# files and directories that do not already exist are created. Nothing is
|
267
|
-
# destroyed.
|
268
|
-
#
|
269
|
-
def setup
|
270
|
-
if File.exist?( directory ) then
|
271
|
-
Console.info "repository root already exists #{directory}"
|
272
|
-
else
|
273
|
-
FileUtils.mkdir_p( directory )
|
274
|
-
Console.info "created repository root #{directory}"
|
275
|
-
end
|
276
|
-
|
277
|
-
Repository.other_dir_names.each do |method|
|
278
|
-
d = self.send( method )
|
279
|
-
if File.exist?( d ) then
|
280
|
-
Console.info "directory #{d} already exists"
|
281
|
-
else
|
282
|
-
FileUtils.mkdir_p( d )
|
283
|
-
Console.info "created directory #{d}"
|
284
|
-
end
|
285
|
-
end
|
286
|
-
|
287
|
-
if overwrite? or not File.exist?( config_file ) then
|
288
|
-
FileUtils.cp Stickler::Paths.data_path( Repository.config_file_basename ), config_file
|
289
|
-
Console.info "copied in default configuration to #{config_file}"
|
290
|
-
else
|
291
|
-
Console.info "configuration file #{config_file} already exists"
|
292
|
-
end
|
293
|
-
|
294
|
-
# load the configuration for the repo
|
295
|
-
load_configuration
|
296
|
-
|
297
|
-
rescue => e
|
298
|
-
$stderr.puts "Unable to setup the respository"
|
299
|
-
$stderr.puts e
|
300
|
-
$stderr.puts e.backtrace.join("\n")
|
301
|
-
exit 1
|
302
|
-
end
|
303
|
-
|
304
|
-
#
|
305
|
-
# Report information about the repository. This is what is called from the
|
306
|
-
# 'info' mode on the commandline
|
307
|
-
#
|
308
|
-
def info
|
309
|
-
return unless valid?
|
310
|
-
|
311
|
-
Console.info ""
|
312
|
-
Console.info "Upstream Sources"
|
313
|
-
Console.info "----------------"
|
314
|
-
Console.info ""
|
315
|
-
|
316
|
-
max_width = configuration.sources.collect { |s| s.length }.max
|
317
|
-
source_group.sources.each do |source|
|
318
|
-
Console.info " #{source.uri.to_s.rjust( max_width )} : #{source.source_specs.size} gems available"
|
319
|
-
Console.info " #{" ".rjust( max_width )} : #{source_group.existing_specs_for_source_uri( source.uri ).size} gems existing"
|
320
|
-
end
|
321
|
-
|
322
|
-
|
323
|
-
Console.info ""
|
324
|
-
Console.info "Configured gems (in stickler.yml)"
|
325
|
-
Console.info "---------------------------------"
|
326
|
-
Console.info ""
|
327
|
-
configuration.gem_dependencies.sort.each do |dep|
|
328
|
-
Console.info "#{dep.name} : #{dep.version_requirements}"
|
329
|
-
end
|
330
|
-
|
331
|
-
Console.info ""
|
332
|
-
Console.info "Existing gems"
|
333
|
-
Console.info "-------------"
|
334
|
-
Console.info ""
|
335
|
-
|
336
|
-
source_group.gems.keys.sort.each do |g|
|
337
|
-
puts g
|
338
|
-
end
|
339
|
-
|
340
|
-
|
341
|
-
end
|
342
|
-
|
343
|
-
#
|
344
|
-
# Add a source to the repository
|
345
|
-
#
|
346
|
-
def add_source( source_uri )
|
347
|
-
load_configuration unless configuration_loaded?
|
348
|
-
if configuration.sources.include?( source_uri ) then
|
349
|
-
Console.info "#{source_uri} already in sources"
|
350
|
-
else
|
351
|
-
source_group.add_source( source_uri )
|
352
|
-
configuration.sources << source_uri
|
353
|
-
configuration.write
|
354
|
-
Console.info "#{source_uri} added to sources"
|
355
|
-
end
|
356
|
-
end
|
357
|
-
|
358
|
-
#
|
359
|
-
# Remove a source from the repository
|
360
|
-
#
|
361
|
-
def remove_source( source_uri )
|
362
|
-
load_configuration unless configuration_loaded?
|
363
|
-
uri = ::URI.parse source_uri
|
364
|
-
if configuration.sources.delete( source_uri ) then
|
365
|
-
source_group.remove_source( source_uri )
|
366
|
-
configuration.write
|
367
|
-
Console.info "#{source_uri} removed from sources"
|
368
|
-
else
|
369
|
-
Console.info "#{source_uri} is not one of your sources"
|
370
|
-
Console.info "Your sources are:"
|
371
|
-
configuration.sources.each do |src|
|
372
|
-
Console.info " #{src}"
|
373
|
-
end
|
374
|
-
end
|
375
|
-
end
|
376
|
-
|
377
|
-
#
|
378
|
-
# Add a gem to the repository
|
379
|
-
#
|
380
|
-
def add_gem( gem_name, version )
|
381
|
-
|
382
|
-
Console.info ""
|
383
|
-
|
384
|
-
::HighLine.track_eof = false
|
385
|
-
hl = ::HighLine.new( STDIN, STDOUT, :auto)
|
386
|
-
hl.say("You need to pick the #{gem_name} Requirement to configure Stickler.")
|
387
|
-
hl.say("This involves picking one of the following Requirement operators")
|
388
|
-
hl.say('See http://docs.rubygems.org/read/chapter/16#page74 for operator info.')
|
389
|
-
hl.say("\nYou need to (1) pick an operator and (2) pick a requirement.")
|
390
|
-
hl.say("The most common operators are >=, > and ~>")
|
391
|
-
|
392
|
-
op = hl.choose(*Repository.requirement_meta.collect { |k,v| "#{k.ljust(3)}#{v}" } ) do |m|
|
393
|
-
m.prompt = "(1) Pick an operator ? "
|
394
|
-
end
|
395
|
-
|
396
|
-
op = op.split.first # get only the operator, not the trailing text
|
397
|
-
|
398
|
-
version = ::Gem::Requirement.default if version == :latest
|
399
|
-
search_pattern = ::Gem::Dependency.new( gem_name, version )
|
400
|
-
choices = []
|
401
|
-
source_group.search( search_pattern ).each do |spec|
|
402
|
-
choices << "#{op} #{spec.version.to_s}"
|
403
|
-
end
|
404
|
-
choices = choices.sort.reverse
|
405
|
-
|
406
|
-
hl.say("\nNow to pick a requirement. Based upon your chosen operator '#{op}',")
|
407
|
-
hl.say("These are the available version of the #{gem_name} gem.")
|
408
|
-
requirement = hl.choose do |m|
|
409
|
-
m.flow = :columns_down
|
410
|
-
m.prompt = "(2) Pick a requirement ? "
|
411
|
-
m.choices( *choices )
|
412
|
-
end
|
413
|
-
|
414
|
-
Console.info ""
|
415
|
-
|
416
|
-
dep = ::Gem::Dependency.new( gem_name, requirement )
|
417
|
-
if configuration.gem_dependencies.include?( dep ) then
|
418
|
-
Console.info "#{dep} is already in your list of gems"
|
419
|
-
else
|
420
|
-
source_group.add_from_dependency( dep )
|
421
|
-
configuration.gem_dependencies << dep
|
422
|
-
configuration.write
|
423
|
-
end
|
424
|
-
end
|
425
|
-
|
426
|
-
#
|
427
|
-
# Remove a gem from the repository
|
428
|
-
#
|
429
|
-
def remove_gem( gem_name, version )
|
430
|
-
Console.info ""
|
431
|
-
version = ::Gem::Requirement.default if version == :all
|
432
|
-
search_pattern = ::Gem::Dependency.new( gem_name, version )
|
433
|
-
ulist = source_group.search_existing( search_pattern )
|
434
|
-
source_group.search_existing( search_pattern ).each do |spec|
|
435
|
-
source_group.remove( spec )
|
436
|
-
configuration.gem_dependencies.reject! { |d| d.name == spec.name }
|
437
|
-
end
|
438
|
-
configuration.write
|
439
|
-
end
|
440
|
-
|
441
|
-
#
|
442
|
-
# Sync the repository
|
443
|
-
#
|
444
|
-
def sync( rebuild = false )
|
445
|
-
Console.info ""
|
446
|
-
Console.info "Making sure that all gems listed in configuration are available"
|
447
|
-
Console.info ""
|
448
|
-
|
449
|
-
if rebuild then
|
450
|
-
Console.info "Removing existing gems and specifications ... "
|
451
|
-
Dir[ File.join( gems_dir, "*.gem" ) ].each { |g| FileUtils.rm_f g }
|
452
|
-
Dir[ File.join( specification_dir , "*.gemspec" ) ].each { |s| FileUtils.rm_f s }
|
453
|
-
end
|
454
|
-
configuration.gem_dependencies.each do |dep|
|
455
|
-
source_group.add_from_dependency( dep )
|
456
|
-
end
|
457
|
-
end
|
458
|
-
|
459
|
-
#
|
460
|
-
# generate the system configuration to be used by rubygem clients of the
|
461
|
-
# repository that stickler managers
|
462
|
-
#
|
463
|
-
def generate_sysconfig( to = $stdout )
|
464
|
-
Console.info "Generating configuration to stdout"
|
465
|
-
txt = <<-cfg
|
466
|
-
#
|
467
|
-
# This is the system wide configuration to be used by
|
468
|
-
# rubygem clients that install gems from the repository
|
469
|
-
# located at :
|
470
|
-
#
|
471
|
-
# #{configuration.downstream_source}
|
472
|
-
#
|
473
|
-
# On Unix like machines install in
|
474
|
-
#
|
475
|
-
# /etc/gemrc
|
476
|
-
#
|
477
|
-
# On Windows machines install in
|
478
|
-
#
|
479
|
-
# C:\\Documents and Settings\\All Users\\Application Data\\gemrc
|
480
|
-
#
|
481
|
-
---
|
482
|
-
:sources:
|
483
|
-
- #{configuration.downstream_source}
|
484
|
-
cfg
|
485
|
-
to.puts txt
|
486
|
-
end
|
487
|
-
|
488
|
-
#
|
489
|
-
# Generate the gem index that can be rsynced to another location
|
490
|
-
#
|
491
|
-
#
|
492
|
-
def generate_index
|
493
|
-
require 'rubygems/indexer'
|
494
|
-
Console.info "Generating rubygems index in #{dist_dir}"
|
495
|
-
FileUtils.rm_rf dist_dir
|
496
|
-
FileUtils.mkdir_p dist_dir
|
497
|
-
FileUtils.cp_r gems_dir, dist_dir
|
498
|
-
indexer = ::Gem::Indexer.new dist_dir
|
499
|
-
indexer.generate_index
|
500
|
-
end
|
7
|
+
module Repository
|
8
|
+
class Error < ::Stickler::Error ; end
|
501
9
|
end
|
502
|
-
end
|
10
|
+
end
|
data/lib/stickler/spec_lite.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'rubygems/platform'
|
2
|
+
require 'rubygems/version'
|
3
|
+
|
1
4
|
module Stickler
|
2
5
|
#
|
3
6
|
# A lightweight version of a gemspec that only responds to name, version,
|
@@ -6,43 +9,86 @@ module Stickler
|
|
6
9
|
# encapsulates that.
|
7
10
|
#
|
8
11
|
class SpecLite
|
12
|
+
include Comparable
|
13
|
+
|
9
14
|
attr_reader :name
|
10
15
|
attr_reader :version
|
11
16
|
attr_reader :platform
|
12
17
|
|
13
|
-
def initialize( name, version, platform )
|
18
|
+
def initialize( name, version, platform = Gem::Platform::RUBY )
|
14
19
|
@name = name
|
15
|
-
@version = version
|
16
|
-
@
|
17
|
-
@platform = platform
|
20
|
+
@version = Gem::Version.new( version )
|
21
|
+
@platform = Gem::Platform.new( platform )
|
18
22
|
end
|
19
23
|
|
20
24
|
def full_name
|
21
25
|
if platform == Gem::Platform::RUBY or platform.nil? then
|
22
|
-
|
26
|
+
name_version
|
23
27
|
else
|
24
|
-
"#{
|
28
|
+
"#{name_version}-#{platform}"
|
25
29
|
end
|
26
30
|
end
|
31
|
+
alias :to_s :full_name
|
32
|
+
|
33
|
+
def file_name
|
34
|
+
full_name + ".gem"
|
35
|
+
end
|
36
|
+
|
37
|
+
def spec_file_name
|
38
|
+
full_name + ".gemspec"
|
39
|
+
end
|
27
40
|
|
28
41
|
def name_version
|
29
42
|
"#{name}-#{version}"
|
30
43
|
end
|
31
44
|
|
32
45
|
def to_a
|
46
|
+
[ name, version.to_s, platform.to_s ]
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
# Convert to the array format used by rubygems itself
|
51
|
+
#
|
52
|
+
def to_rubygems_a
|
33
53
|
[ name, version, platform.to_s ]
|
34
54
|
end
|
35
55
|
|
36
|
-
|
37
|
-
|
56
|
+
#
|
57
|
+
# Lets be comparable!
|
58
|
+
#
|
59
|
+
def <=>(other)
|
60
|
+
return 0 if other.object_id == self.object_id
|
61
|
+
other = coerce( other )
|
62
|
+
[ :name, :version, :platform ].each do |method|
|
63
|
+
result = ( self.send( method ).<=>( other.send( method ) ) )
|
64
|
+
return result unless 0 == result
|
65
|
+
end
|
66
|
+
return 0
|
67
|
+
end
|
68
|
+
|
69
|
+
#
|
70
|
+
# See if another Spec is the same as this spec
|
71
|
+
#
|
72
|
+
def =~(other)
|
73
|
+
other = coerce( other )
|
74
|
+
return (other and
|
75
|
+
self.name == other.name and
|
76
|
+
self.version.to_s == other.version.to_s and
|
77
|
+
self.platform == other.platform )
|
38
78
|
end
|
39
|
-
end
|
40
|
-
end
|
41
79
|
|
42
|
-
|
43
|
-
|
44
|
-
def
|
45
|
-
|
80
|
+
private
|
81
|
+
|
82
|
+
def coerce( other )
|
83
|
+
if self.class === other then
|
84
|
+
other
|
85
|
+
elsif other.respond_to?( :name ) and
|
86
|
+
other.respond_to?( :version ) and
|
87
|
+
other.respond_to?( :platform ) then
|
88
|
+
SpecLite.new( other.name, other.version, other.platform )
|
89
|
+
else
|
90
|
+
return false
|
91
|
+
end
|
46
92
|
end
|
47
93
|
end
|
48
94
|
end
|
data/lib/stickler/version.rb
CHANGED
@@ -3,16 +3,16 @@
|
|
3
3
|
# All rights reserved. Licensed under the same terms as Ruby. No warranty is
|
4
4
|
# provided. See LICENSE and COPYING for details.
|
5
5
|
#++
|
6
|
-
|
6
|
+
|
7
7
|
module Stickler
|
8
8
|
|
9
9
|
# Version access in every possibly way that people might want to get it.
|
10
10
|
#
|
11
11
|
module Version
|
12
12
|
|
13
|
-
MAJOR =
|
14
|
-
MINOR =
|
15
|
-
BUILD =
|
13
|
+
MAJOR = 2
|
14
|
+
MINOR = 0
|
15
|
+
BUILD = 0
|
16
16
|
|
17
17
|
def self.to_ary
|
18
18
|
[ MAJOR, MINOR, BUILD ]
|
@@ -27,10 +27,10 @@ module Stickler
|
|
27
27
|
end
|
28
28
|
|
29
29
|
# Version string constant
|
30
|
-
STRING = Version.to_s
|
30
|
+
STRING = Version.to_s
|
31
31
|
|
32
32
|
end
|
33
33
|
|
34
34
|
# Version string constant
|
35
|
-
VERSION = Version.to_s
|
35
|
+
VERSION = Version.to_s
|
36
36
|
end
|
data/lib/stickler/web.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'stickler/middleware/compression'
|
2
|
+
require 'stickler/middleware/gemcutter'
|
3
|
+
require 'stickler/middleware/mirror'
|
4
|
+
require 'stickler/middleware/index'
|
5
|
+
require 'rack/cascade'
|
6
|
+
|
7
|
+
module Stickler
|
8
|
+
class Web < ::Sinatra::Base
|
9
|
+
|
10
|
+
disable :sessions
|
11
|
+
enable :logging, :dump_errors, :clean_trace
|
12
|
+
|
13
|
+
use Stickler::Middleware::Compression
|
14
|
+
use Stickler::Middleware::Gemcutter, :serve_indexes => false
|
15
|
+
use Stickler::Middleware::Mirror, :serve_indexes => false
|
16
|
+
use Stickler::Middleware::Index, :serve_indexes => true
|
17
|
+
run Stickler::Middleware::NotFound
|
18
|
+
end
|
19
|
+
end
|
Binary file
|
Binary file
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{bar}
|
5
|
+
s.version = "1.0.0"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Jeremy Hinegardner"]
|
9
|
+
s.date = %q{2010-06-23}
|
10
|
+
s.description = %q{bar gem}
|
11
|
+
s.email = %q{jeremy@hinegardner.org}
|
12
|
+
s.files = ["README.rdoc", "lib/bar.rb", "bin/bar", "Rakefile", "bar.gemspec"]
|
13
|
+
s.homepage = %q{http://github.com/copiousfreetime/stickler}
|
14
|
+
s.require_paths = ["lib"]
|
15
|
+
s.rubygems_version = %q{1.3.5}
|
16
|
+
s.summary = %q{bar gem}
|
17
|
+
|
18
|
+
if s.respond_to? :specification_version then
|
19
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
20
|
+
s.specification_version = 3
|
21
|
+
|
22
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
23
|
+
s.add_runtime_dependency(%q<rake>, [">= 0"])
|
24
|
+
else
|
25
|
+
s.add_dependency(%q<rake>, [">= 0"])
|
26
|
+
end
|
27
|
+
else
|
28
|
+
s.add_dependency(%q<rake>, [">= 0"])
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|