gemirro 1.5.0 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +29 -0
- data/.rubocop.yml +6 -3
- data/Gemfile.lock +126 -0
- data/MANIFEST +6 -10
- data/README.md +1 -1
- data/bin/gemirro +7 -1
- data/gemirro.gemspec +7 -2
- data/lib/gemirro/cli/index.rb +12 -3
- data/lib/gemirro/cli/init.rb +6 -1
- data/lib/gemirro/cli/update.rb +6 -0
- data/lib/gemirro/configuration.rb +1 -1
- data/lib/gemirro/gems_fetcher.rb +5 -10
- data/lib/gemirro/indexer.rb +396 -89
- data/lib/gemirro/mirror_file.rb +1 -0
- data/lib/gemirro/server.rb +73 -166
- data/lib/gemirro/utils.rb +123 -68
- data/lib/gemirro/version.rb +1 -1
- data/lib/gemirro/versions_fetcher.rb +6 -2
- data/lib/gemirro.rb +0 -1
- data/spec/gemirro/server_spec.rb +76 -47
- data/template/config.rb +6 -0
- data/template/public/dist/css/gemirro.css +25 -1
- data/template/public/latest_specs.4.8 +0 -0
- data/template/public/prerelease_specs.4.8 +0 -0
- data/template/public/specs.4.8 +0 -0
- data/views/gem.erb +46 -37
- data/views/index.erb +41 -33
- data/views/layout.erb +4 -17
- data/views/not_found.erb +4 -4
- metadata +82 -16
- data/lib/gemirro/cache.rb +0 -115
- data/spec/gemirro/cache_spec.rb +0 -32
- data/template/public/dist/css/bootstrap.min.css +0 -7
- data/template/public/dist/fonts/glyphicons-halflings-regular.eot +0 -0
- data/template/public/dist/fonts/glyphicons-halflings-regular.svg +0 -288
- data/template/public/dist/fonts/glyphicons-halflings-regular.ttf +0 -0
- data/template/public/dist/fonts/glyphicons-halflings-regular.woff +0 -0
- data/template/public/dist/fonts/glyphicons-halflings-regular.woff2 +0 -0
- data/template/public/dist/js/bootstrap.min.js +0 -7
data/lib/gemirro/indexer.rb
CHANGED
@@ -19,12 +19,14 @@ module Gemirro
|
|
19
19
|
# @return [Array]
|
20
20
|
#
|
21
21
|
class Indexer < ::Gem::Indexer
|
22
|
-
attr_accessor(
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
22
|
+
attr_accessor(
|
23
|
+
:files,
|
24
|
+
:quick_marshal_dir,
|
25
|
+
:directory,
|
26
|
+
:dest_directory,
|
27
|
+
:only_origin,
|
28
|
+
:updated_gems
|
29
|
+
)
|
28
30
|
|
29
31
|
##
|
30
32
|
# Create an indexer that will index the gems in +directory+.
|
@@ -37,34 +39,38 @@ module Gemirro
|
|
37
39
|
require 'fileutils'
|
38
40
|
require 'tmpdir'
|
39
41
|
require 'zlib'
|
42
|
+
require 'builder/xchar'
|
43
|
+
require 'compact_index'
|
40
44
|
|
41
|
-
|
42
|
-
raise 'Gem::Indexer requires that the XML Builder ' \
|
43
|
-
'library be installed:' \
|
44
|
-
"\n\tgem install builder"
|
45
|
-
end
|
46
|
-
|
47
|
-
options = { build_modern: true }.merge options
|
45
|
+
options.merge!({ build_modern: true, build_compact: true })
|
48
46
|
|
49
47
|
@build_modern = options[:build_modern]
|
48
|
+
@build_compact = options[:build_compact]
|
50
49
|
|
51
50
|
@dest_directory = directory
|
52
|
-
@directory =
|
53
|
-
|
51
|
+
@directory =
|
52
|
+
File.join(Dir.tmpdir, "gem_generate_index_#{rand(1_000_000_000)}")
|
54
53
|
|
55
54
|
marshal_name = "Marshal.#{::Gem.marshal_version}"
|
56
55
|
|
57
|
-
@master_index =
|
58
|
-
|
56
|
+
@master_index =
|
57
|
+
File.join(@directory, 'yaml')
|
58
|
+
@marshal_index =
|
59
|
+
File.join(@directory, marshal_name)
|
59
60
|
|
60
|
-
@quick_dir = File.join
|
61
|
-
@quick_marshal_dir =
|
62
|
-
|
61
|
+
@quick_dir = File.join(@directory, 'quick')
|
62
|
+
@quick_marshal_dir =
|
63
|
+
File.join(@quick_dir, marshal_name)
|
64
|
+
@quick_marshal_dir_base =
|
65
|
+
File.join(@dest_directory, 'quick', marshal_name) # FIX: UGH
|
63
66
|
|
64
|
-
@quick_index =
|
65
|
-
|
67
|
+
@quick_index =
|
68
|
+
File.join(@quick_dir, 'index')
|
69
|
+
@latest_index =
|
70
|
+
File.join(@quick_dir, 'latest_index')
|
66
71
|
|
67
|
-
@specs_index =
|
72
|
+
@specs_index =
|
73
|
+
File.join(@directory, "specs.#{::Gem.marshal_version}")
|
68
74
|
@latest_specs_index =
|
69
75
|
File.join(@directory, "latest_specs.#{::Gem.marshal_version}")
|
70
76
|
@prerelease_specs_index =
|
@@ -75,6 +81,10 @@ module Gemirro
|
|
75
81
|
File.join(@dest_directory, "latest_specs.#{::Gem.marshal_version}")
|
76
82
|
@dest_prerelease_specs_index =
|
77
83
|
File.join(@dest_directory, "prerelease_specs.#{::Gem.marshal_version}")
|
84
|
+
@infos_dir =
|
85
|
+
File.join(@dest_directory, 'info')
|
86
|
+
@api_v1_dependencies_dir =
|
87
|
+
File.join(@dest_directory, 'api', 'v1', 'dependencies')
|
78
88
|
|
79
89
|
@files = []
|
80
90
|
end
|
@@ -100,28 +110,24 @@ module Gemirro
|
|
100
110
|
|
101
111
|
if files.include?(@quick_marshal_dir) && !files.include?(@quick_dir)
|
102
112
|
files.delete @quick_marshal_dir
|
103
|
-
|
104
|
-
FileUtils.
|
105
|
-
FileUtils.
|
106
|
-
FileUtils.mv(@quick_marshal_dir, dst_name,
|
107
|
-
verbose: verbose, force: true)
|
113
|
+
FileUtils.mkdir_p(File.dirname(@quick_marshal_dir_base), verbose: verbose)
|
114
|
+
FileUtils.rm_rf(@quick_marshal_dir_base, verbose: verbose)
|
115
|
+
FileUtils.mv(@quick_marshal_dir, @quick_marshal_dir_base, verbose: verbose, force: true)
|
108
116
|
end
|
109
117
|
|
110
118
|
files.each do |path|
|
111
119
|
file = path.sub(%r{^#{Regexp.escape @directory}/?}, '')
|
112
|
-
src_name = File.join(@directory, file)
|
113
|
-
dst_name = File.join(@dest_directory, file)
|
114
120
|
|
115
121
|
if ["#{@specs_index}.gz",
|
116
122
|
"#{@latest_specs_index}.gz",
|
117
123
|
"#{@prerelease_specs_index}.gz"].include?(path)
|
118
|
-
res = build_zlib_file(file,
|
124
|
+
res = build_zlib_file(file, File.join(@directory, file), File.join(@dest_directory, file), true)
|
119
125
|
next unless res
|
120
126
|
else
|
121
127
|
source_content = download_from_source(file)
|
122
128
|
next if source_content.nil?
|
123
129
|
|
124
|
-
MirrorFile.new(
|
130
|
+
MirrorFile.new(File.join(@dest_directory, file)).write(source_content)
|
125
131
|
end
|
126
132
|
|
127
133
|
FileUtils.rm_rf(path)
|
@@ -129,7 +135,7 @@ module Gemirro
|
|
129
135
|
end
|
130
136
|
|
131
137
|
##
|
132
|
-
# Download file from source
|
138
|
+
# Download file from source (example: rubygems.org)
|
133
139
|
#
|
134
140
|
# @param [String] file File path
|
135
141
|
# @return [String]
|
@@ -164,14 +170,255 @@ module Gemirro
|
|
164
170
|
::Gem::Specification.all = specs
|
165
171
|
|
166
172
|
if ::Gem::VERSION >= '2.5.0'
|
167
|
-
build_marshal_gemspecs
|
168
|
-
build_modern_indices
|
173
|
+
build_marshal_gemspecs(specs)
|
174
|
+
build_modern_indices(specs) if @build_modern
|
169
175
|
compress_indices
|
170
176
|
else
|
171
177
|
build_marshal_gemspecs
|
172
178
|
build_modern_indicies if @build_modern
|
173
179
|
compress_indicies
|
174
180
|
end
|
181
|
+
|
182
|
+
build_api_v1_dependencies(specs)
|
183
|
+
|
184
|
+
return unless @build_compact
|
185
|
+
|
186
|
+
build_compact_index_names
|
187
|
+
build_compact_index_infos(specs)
|
188
|
+
build_compact_index_versions(specs)
|
189
|
+
end
|
190
|
+
|
191
|
+
##
|
192
|
+
# Cache Modern Index endpoints /api/v1/dependencies?gems= and /api/v1/dependencies.json?gems=
|
193
|
+
# This single request may include many fragments. server.rb determines which are required per request.
|
194
|
+
#
|
195
|
+
# @return nil
|
196
|
+
#
|
197
|
+
def build_api_v1_dependencies(specs, partial = false)
|
198
|
+
FileUtils.mkdir_p(@api_v1_dependencies_dir)
|
199
|
+
|
200
|
+
if partial
|
201
|
+
specs.collect(&:name).uniq do |name|
|
202
|
+
FileUtils.rm_rf(Dir.glob(File.join(@api_v1_dependencies_dir, "#{name}.*.*.list")))
|
203
|
+
end
|
204
|
+
else
|
205
|
+
FileUtils.rm_rf(Dir.glob(File.join(@api_v1_dependencies_dir, '*.list')))
|
206
|
+
end
|
207
|
+
|
208
|
+
grouped_specs = specs.sort_by(&:name).group_by(&:name)
|
209
|
+
grouped_specs.each_with_index do |(name, gem_versions), index|
|
210
|
+
Utils.logger.info("[#{index + 1}/#{grouped_specs.size}]: Caching /api/v1/dependencies/#{name}")
|
211
|
+
|
212
|
+
gem_versions =
|
213
|
+
gem_versions.sort do |a, b|
|
214
|
+
a.version <=> b.version
|
215
|
+
end
|
216
|
+
|
217
|
+
cg = []
|
218
|
+
Parallel.each_with_index(
|
219
|
+
gem_versions,
|
220
|
+
in_threads: Utils.configuration.update_thread_count
|
221
|
+
) do |spec, index2|
|
222
|
+
next if spec.nil?
|
223
|
+
|
224
|
+
dependencies = spec.dependencies.select do |d|
|
225
|
+
d.type == :runtime
|
226
|
+
end
|
227
|
+
|
228
|
+
dependencies = dependencies.collect do |d|
|
229
|
+
[d.name.is_a?(Array) ? d.name.first : d.name, d.requirement.to_s]
|
230
|
+
end
|
231
|
+
|
232
|
+
cg[index2] =
|
233
|
+
{
|
234
|
+
name: spec.name,
|
235
|
+
number: spec.version.to_s,
|
236
|
+
platform: spec.platform,
|
237
|
+
dependencies: dependencies
|
238
|
+
}
|
239
|
+
end
|
240
|
+
|
241
|
+
Tempfile.create("api_v1_dependencies_#{name}.list") do |f|
|
242
|
+
f.write Marshal.dump(cg)
|
243
|
+
f.rewind
|
244
|
+
|
245
|
+
FileUtils.cp(
|
246
|
+
f.path,
|
247
|
+
File.join(
|
248
|
+
@api_v1_dependencies_dir,
|
249
|
+
"#{name}.#{Digest::MD5.file(f.path).hexdigest}.#{Digest::SHA256.file(f.path).hexdigest}.list"
|
250
|
+
)
|
251
|
+
)
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
##
|
257
|
+
# Cache compact_index endpoint /names
|
258
|
+
# Report all gems with versions available. Does not require opening spec files.
|
259
|
+
#
|
260
|
+
# @return nil
|
261
|
+
#
|
262
|
+
def build_compact_index_names
|
263
|
+
Utils.logger.info('[1/1]: Caching /names')
|
264
|
+
FileUtils.rm_rf(Dir.glob(File.join(@dest_directory, 'names*.list')))
|
265
|
+
|
266
|
+
gem_name_list = Dir.glob('*.gem', base: File.join(@dest_directory, 'gems')).collect do |x|
|
267
|
+
x.sub(/-\d+(\.\d+)*(\.[a-zA-Z\d]+)*([-_a-zA-Z\d]+)?\.gem/, '')
|
268
|
+
end.uniq.sort!
|
269
|
+
|
270
|
+
Tempfile.create('names.list') do |f|
|
271
|
+
f.write CompactIndex.names(gem_name_list).to_s
|
272
|
+
f.rewind
|
273
|
+
FileUtils.cp(
|
274
|
+
f.path,
|
275
|
+
File.join(
|
276
|
+
@dest_directory,
|
277
|
+
"names.#{Digest::MD5.file(f.path).hexdigest}.#{Digest::SHA256.file(f.path).hexdigest}.list"
|
278
|
+
),
|
279
|
+
verbose: verbose
|
280
|
+
)
|
281
|
+
end
|
282
|
+
|
283
|
+
nil
|
284
|
+
end
|
285
|
+
|
286
|
+
##
|
287
|
+
# Cache compact_index endpoint /versions
|
288
|
+
#
|
289
|
+
# @param [Array] specs Gems list
|
290
|
+
# @param [Boolean] partial Is gem list an update or a full index
|
291
|
+
# @return nil
|
292
|
+
#
|
293
|
+
def build_compact_index_versions(specs, partial = false)
|
294
|
+
Utils.logger.info('[1/1]: Caching /versions')
|
295
|
+
|
296
|
+
cg =
|
297
|
+
specs
|
298
|
+
.sort_by(&:name)
|
299
|
+
.group_by(&:name)
|
300
|
+
.collect do |name, gem_versions|
|
301
|
+
gem_versions =
|
302
|
+
gem_versions.sort do |a, b|
|
303
|
+
a.version <=> b.version
|
304
|
+
end
|
305
|
+
|
306
|
+
info_file = Dir.glob(File.join(@infos_dir, "#{name}.*.*.list")).last
|
307
|
+
|
308
|
+
throw "Info file for #{name} not found" unless info_file
|
309
|
+
|
310
|
+
info_file_checksum = info_file.split('.', -4)[-3]
|
311
|
+
|
312
|
+
CompactIndex::Gem.new(
|
313
|
+
name,
|
314
|
+
gem_versions.collect do |y|
|
315
|
+
CompactIndex::GemVersion.new(
|
316
|
+
y.version.to_s,
|
317
|
+
y.platform,
|
318
|
+
nil,
|
319
|
+
info_file_checksum
|
320
|
+
)
|
321
|
+
end
|
322
|
+
)
|
323
|
+
end
|
324
|
+
|
325
|
+
Tempfile.create('versions.list') do |f|
|
326
|
+
previous_versions_file = Dir.glob(File.join(@dest_directory, 'versions*.list')).last
|
327
|
+
|
328
|
+
if partial && previous_versions_file
|
329
|
+
versions_file = CompactIndex::VersionsFile.new(previous_versions_file)
|
330
|
+
else
|
331
|
+
versions_file = CompactIndex::VersionsFile.new(f.path)
|
332
|
+
f.write format('created_at: %s', Time.now.utc.iso8601)
|
333
|
+
f.write "\n---\n"
|
334
|
+
end
|
335
|
+
|
336
|
+
f.write CompactIndex.versions(versions_file, cg)
|
337
|
+
f.rewind
|
338
|
+
|
339
|
+
FileUtils.rm_rf(Dir.glob(File.join(@dest_directory, 'versions*.list')))
|
340
|
+
|
341
|
+
FileUtils.cp(
|
342
|
+
f.path,
|
343
|
+
File.join(
|
344
|
+
@dest_directory,
|
345
|
+
"versions.#{Digest::MD5.file(f.path).hexdigest}.#{Digest::SHA256.file(f.path).hexdigest}.list"
|
346
|
+
),
|
347
|
+
verbose: verbose
|
348
|
+
)
|
349
|
+
end
|
350
|
+
|
351
|
+
nil
|
352
|
+
end
|
353
|
+
|
354
|
+
##
|
355
|
+
# Cache compact_index endpoint /info/[gemname]
|
356
|
+
#
|
357
|
+
# @param [Array] specs Gems list
|
358
|
+
# @param [Boolean] partial Is gem list an update or a full index
|
359
|
+
# @return nil
|
360
|
+
#
|
361
|
+
def build_compact_index_infos(specs, partial = false)
|
362
|
+
FileUtils.mkdir_p(@infos_dir)
|
363
|
+
|
364
|
+
if partial
|
365
|
+
specs.collect(&:name).uniq do |name|
|
366
|
+
FileUtils.rm_rf(Dir.glob(File.join(@infos_dir, "#{name}.*.*.list")))
|
367
|
+
end
|
368
|
+
else
|
369
|
+
FileUtils.rm_rf(Dir.glob(File.join(@infos_dir, '*.list')))
|
370
|
+
end
|
371
|
+
|
372
|
+
grouped_specs = specs.sort_by(&:name).group_by(&:name)
|
373
|
+
grouped_specs.each_with_index do |(name, gem_versions), index|
|
374
|
+
Utils.logger.info("[#{index + 1}/#{grouped_specs.size}]: Caching /info/#{name}")
|
375
|
+
|
376
|
+
gem_versions =
|
377
|
+
gem_versions.sort do |a, b|
|
378
|
+
a.version <=> b.version
|
379
|
+
end
|
380
|
+
|
381
|
+
versions =
|
382
|
+
Parallel.map(gem_versions, in_threads: Utils.configuration.update_thread_count) do |spec|
|
383
|
+
deps =
|
384
|
+
spec
|
385
|
+
.dependencies
|
386
|
+
.select { |d| d.type == :runtime }
|
387
|
+
.sort_by(&:name)
|
388
|
+
.collect do |dependency|
|
389
|
+
CompactIndex::Dependency.new(
|
390
|
+
dependency.name,
|
391
|
+
dependency.requirement.to_s
|
392
|
+
)
|
393
|
+
end
|
394
|
+
|
395
|
+
CompactIndex::GemVersion.new(
|
396
|
+
spec.version,
|
397
|
+
spec.platform,
|
398
|
+
Digest::SHA256.file(spec.loaded_from).hexdigest,
|
399
|
+
nil,
|
400
|
+
deps,
|
401
|
+
spec.required_ruby_version.to_s,
|
402
|
+
spec.required_rubygems_version.to_s
|
403
|
+
)
|
404
|
+
end
|
405
|
+
|
406
|
+
Tempfile.create("info_#{name}.list") do |f|
|
407
|
+
f.write CompactIndex.info(versions).to_s
|
408
|
+
f.rewind
|
409
|
+
|
410
|
+
FileUtils.cp(
|
411
|
+
f.path,
|
412
|
+
File.join(
|
413
|
+
@infos_dir,
|
414
|
+
"#{name}.#{Digest::MD5.file(f.path).hexdigest}.#{Digest::SHA256.file(f.path).hexdigest}.list"
|
415
|
+
),
|
416
|
+
verbose: verbose
|
417
|
+
)
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
nil
|
175
422
|
end
|
176
423
|
|
177
424
|
##
|
@@ -181,7 +428,9 @@ module Gemirro
|
|
181
428
|
# @return [Array]
|
182
429
|
#
|
183
430
|
def map_gems_to_specs(gems)
|
184
|
-
|
431
|
+
results = []
|
432
|
+
|
433
|
+
Parallel.each_with_index(gems, in_threads: Utils.configuration.update_thread_count) do |gemfile, index|
|
185
434
|
Utils.logger.info("[#{index + 1}/#{gems.size}]: Processing #{gemfile.split('/')[-1]}")
|
186
435
|
if File.empty?(gemfile)
|
187
436
|
Utils.logger.warn("Skipping zero-length gem: #{gemfile}")
|
@@ -190,12 +439,12 @@ module Gemirro
|
|
190
439
|
|
191
440
|
begin
|
192
441
|
begin
|
193
|
-
spec =
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
442
|
+
spec =
|
443
|
+
if ::Gem::Package.respond_to? :open
|
444
|
+
::Gem::Package.open(File.open(gemfile, 'rb'), 'r', &:metadata)
|
445
|
+
else
|
446
|
+
::Gem::Package.new(gemfile).spec
|
447
|
+
end
|
199
448
|
rescue NotImplementedError
|
200
449
|
next
|
201
450
|
end
|
@@ -213,7 +462,7 @@ module Gemirro
|
|
213
462
|
end
|
214
463
|
|
215
464
|
version = spec.version.version
|
216
|
-
unless version =~ /^\d
|
465
|
+
unless version =~ /^\d+(\.\d+)?(\.\d+)?.*/
|
217
466
|
msg = "Skipping gem #{spec.full_name} - invalid version #{version}"
|
218
467
|
Utils.logger.warn(msg)
|
219
468
|
next
|
@@ -223,8 +472,8 @@ module Gemirro
|
|
223
472
|
spec.abbreviate
|
224
473
|
spec.sanitize
|
225
474
|
else
|
226
|
-
abbreviate
|
227
|
-
sanitize
|
475
|
+
abbreviate(spec)
|
476
|
+
sanitize(spec)
|
228
477
|
end
|
229
478
|
|
230
479
|
spec
|
@@ -238,20 +487,48 @@ module Gemirro
|
|
238
487
|
"\t#{e.backtrace.join "\n\t"}"].join("\n")
|
239
488
|
Utils.logger.debug(msg)
|
240
489
|
end
|
241
|
-
|
490
|
+
|
491
|
+
results[index] = spec
|
492
|
+
end
|
493
|
+
|
494
|
+
# nils can result from insert by index
|
495
|
+
results.compact
|
242
496
|
end
|
243
497
|
|
498
|
+
##
|
499
|
+
# Handle `index --update`, detecting changed files and file lists.
|
500
|
+
#
|
501
|
+
# @return nil
|
502
|
+
#
|
244
503
|
def update_index
|
245
504
|
make_temp_directories
|
246
505
|
|
247
|
-
|
506
|
+
present_gemfiles = Dir.glob('*.gem', base: File.join(@dest_directory, 'gems'))
|
507
|
+
indexed_gemfiles = Dir.glob('*.gemspec.rz', base: @quick_marshal_dir_base).collect { |x| x.gsub(/spec.rz$/, '') }
|
508
|
+
|
509
|
+
@updated_gems = []
|
510
|
+
# detect files manually added to public/gems
|
511
|
+
@updated_gems += (present_gemfiles - indexed_gemfiles).collect { |x| File.join(@dest_directory, 'gems', x) }
|
512
|
+
# detect files manually deleted from public/gems
|
513
|
+
@updated_gems += (indexed_gemfiles - present_gemfiles).collect { |x| File.join(@dest_directory, 'gems', x) }
|
514
|
+
|
515
|
+
specs_mtime =
|
516
|
+
begin
|
517
|
+
File.stat(@dest_specs_index).mtime
|
518
|
+
rescue StandardError
|
519
|
+
Time.at(0)
|
520
|
+
end
|
248
521
|
newest_mtime = Time.at(0)
|
249
522
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
523
|
+
# files that have been replaced
|
524
|
+
@updated_gems +=
|
525
|
+
gem_file_list.select do |gem|
|
526
|
+
gem_mtime = File.stat(gem).mtime
|
527
|
+
newest_mtime = gem_mtime if gem_mtime > newest_mtime
|
528
|
+
gem_mtime > specs_mtime
|
529
|
+
end
|
530
|
+
|
531
|
+
@updated_gems.uniq!
|
255
532
|
|
256
533
|
if @updated_gems.empty?
|
257
534
|
Utils.logger.info('No new gems')
|
@@ -259,24 +536,46 @@ module Gemirro
|
|
259
536
|
end
|
260
537
|
|
261
538
|
specs = map_gems_to_specs(@updated_gems)
|
539
|
+
|
540
|
+
# specs only includes latest discovered files.
|
541
|
+
# /info/[gemname] and /api/v1/dependencies can not be rebuilt
|
542
|
+
# incrementally, so retrive specs for all versions of these gems.
|
543
|
+
gem_name_updates = specs.collect(&:name).uniq
|
544
|
+
u2 =
|
545
|
+
Dir.glob(File.join(File.join(@dest_directory, 'gems'), '*.gem')).select do |possibility|
|
546
|
+
gem_name_updates.any? { |updated| File.basename(possibility) =~ /^#{updated}-\d/ }
|
547
|
+
end
|
548
|
+
|
549
|
+
Utils.logger.info('Reloading for /info/[gemname]')
|
550
|
+
version_specs = map_gems_to_specs(u2)
|
551
|
+
|
262
552
|
prerelease, released = specs.partition { |s| s.version.prerelease? }
|
263
553
|
|
264
554
|
::Gem::Specification.dirs = []
|
265
555
|
::Gem::Specification.all = *specs
|
266
|
-
files =
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
556
|
+
files =
|
557
|
+
if ::Gem::VERSION >= '2.5.0'
|
558
|
+
build_marshal_gemspecs specs
|
559
|
+
else
|
560
|
+
build_marshal_gemspecs
|
561
|
+
end
|
271
562
|
|
272
563
|
::Gem.time('Updated indexes') do
|
273
|
-
update_specs_index(
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
564
|
+
update_specs_index(
|
565
|
+
released,
|
566
|
+
@dest_specs_index,
|
567
|
+
@specs_index
|
568
|
+
)
|
569
|
+
update_specs_index(
|
570
|
+
released,
|
571
|
+
@dest_latest_specs_index,
|
572
|
+
@latest_specs_index
|
573
|
+
)
|
574
|
+
update_specs_index(
|
575
|
+
prerelease,
|
576
|
+
@dest_prerelease_specs_index,
|
577
|
+
@prerelease_specs_index
|
578
|
+
)
|
280
579
|
end
|
281
580
|
|
282
581
|
if ::Gem::VERSION >= '2.5.0'
|
@@ -285,6 +584,14 @@ module Gemirro
|
|
285
584
|
compress_indicies
|
286
585
|
end
|
287
586
|
|
587
|
+
build_api_v1_dependencies(version_specs, true)
|
588
|
+
|
589
|
+
if @build_compact
|
590
|
+
build_compact_index_names
|
591
|
+
build_compact_index_infos(version_specs, true)
|
592
|
+
build_compact_index_versions(specs, true)
|
593
|
+
end
|
594
|
+
|
288
595
|
Utils.logger.info("Updating production dir #{@dest_directory}") if verbose
|
289
596
|
files << @specs_index
|
290
597
|
files << "#{@specs_index}.gz"
|
@@ -295,36 +602,36 @@ module Gemirro
|
|
295
602
|
|
296
603
|
files.each do |path|
|
297
604
|
file = path.sub(%r{^#{Regexp.escape @directory}/?}, '')
|
298
|
-
src_name = File.join(@directory, file)
|
299
|
-
dst_name = File.join(@dest_directory, file)
|
300
605
|
|
301
|
-
if ["#{@specs_index}.gz",
|
302
|
-
|
303
|
-
"#{@prerelease_specs_index}.gz"].include?(path)
|
304
|
-
res = build_zlib_file(file, src_name, dst_name)
|
606
|
+
if ["#{@specs_index}.gz", "#{@latest_specs_index}.gz", "#{@prerelease_specs_index}.gz"].include?(path)
|
607
|
+
res = build_zlib_file(file, File.join(@directory, file), File.join(@dest_directory, file))
|
305
608
|
next unless res
|
306
609
|
else
|
307
|
-
FileUtils.mv(
|
308
|
-
|
309
|
-
|
310
|
-
|
610
|
+
FileUtils.mv(
|
611
|
+
File.join(@directory, file),
|
612
|
+
File.join(@dest_directory, file),
|
613
|
+
verbose: verbose,
|
614
|
+
force: true
|
615
|
+
)
|
311
616
|
end
|
312
617
|
|
313
|
-
File.utime(newest_mtime, newest_mtime,
|
618
|
+
File.utime(newest_mtime, newest_mtime, File.join(@dest_directory, file))
|
314
619
|
end
|
315
620
|
end
|
316
621
|
|
317
622
|
def build_zlib_file(file, src_name, dst_name, from_source = false)
|
318
623
|
content = Marshal.load(Zlib::GzipReader.open(src_name).read)
|
319
|
-
create_zlib_file("#{dst_name}.
|
624
|
+
create_zlib_file("#{dst_name}.local", content)
|
320
625
|
|
321
626
|
return false if @only_origin
|
322
627
|
|
323
628
|
if from_source
|
324
629
|
source_content = download_from_source(file)
|
325
|
-
source_content = Marshal.load(
|
326
|
-
|
327
|
-
|
630
|
+
source_content = Marshal.load(
|
631
|
+
Zlib::GzipReader.new(
|
632
|
+
StringIO.new(source_content)
|
633
|
+
).read
|
634
|
+
)
|
328
635
|
else
|
329
636
|
source_content = Marshal.load(Zlib::GzipReader.open(dst_name).read)
|
330
637
|
end
|
@@ -336,17 +643,17 @@ module Gemirro
|
|
336
643
|
end
|
337
644
|
|
338
645
|
def create_zlib_file(dst_name, content)
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
646
|
+
Tempfile.create(File.basename(dst_name)) do |f|
|
647
|
+
gzf = Zlib::GzipWriter.new(f)
|
648
|
+
gzf.write(Marshal.dump(content))
|
649
|
+
gzf.close
|
650
|
+
|
651
|
+
FileUtils.cp(
|
652
|
+
f.path,
|
653
|
+
dst_name,
|
654
|
+
verbose: verbose
|
655
|
+
)
|
343
656
|
end
|
344
|
-
|
345
|
-
FileUtils.mv(temp_file.path,
|
346
|
-
dst_name,
|
347
|
-
verbose: verbose,
|
348
|
-
force: true)
|
349
|
-
Utils.cache.flush_key(File.basename(dst_name))
|
350
657
|
end
|
351
658
|
|
352
659
|
def verbose
|