gemirro 1.6.0 → 2.0.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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Gemfile.lock +2 -2
- data/MANIFEST +0 -3
- data/lib/gemirro/cli/index.rb +4 -3
- data/lib/gemirro/cli/init.rb +0 -5
- data/lib/gemirro/cli.rb +3 -1
- data/lib/gemirro/configuration.rb +3 -11
- data/lib/gemirro/gems_fetcher.rb +2 -0
- data/lib/gemirro/indexer.rb +32 -231
- data/lib/gemirro/server.rb +10 -42
- data/lib/gemirro/source.rb +2 -15
- data/lib/gemirro/utils.rb +22 -12
- data/lib/gemirro/version.rb +1 -1
- data/lib/gemirro/versions_fetcher.rb +7 -12
- data/lib/gemirro/versions_file.rb +26 -24
- data/spec/gemirro/configuration_spec.rb +9 -2
- data/spec/gemirro/gems_fetcher_spec.rb +1 -1
- data/spec/gemirro/indexer_spec.rb +5 -5
- data/spec/gemirro/server_spec.rb +29 -52
- data/spec/gemirro/source_spec.rb +1 -10
- data/spec/gemirro/versions_fetcher_spec.rb +3 -4
- data/spec/gemirro/versions_file_spec.rb +8 -32
- data/template/config.rb +1 -1
- metadata +2 -5
- 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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e54b02e5575feb8b7a4fcbb40f5fd91764fb0f589368e4a9207f6a5074fe2f05
|
4
|
+
data.tar.gz: 14449b2b15d5477216adaecea6e36aff26dae8b30104e3db627bdcdbdf7c6b7d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ba26ee7c502dd1bbfc02fd55e1263097dedad78670281d8f775bd9c5940be1c46032130cd76be02fbdee3b8a4c2f24504f39b38c7e5901497c7eff28d13a0307
|
7
|
+
data.tar.gz: ce425c173bcfc46ea6298cc0911ddec8a838f321749f9ec782da8323afdaf3268f6071d629be5fa6b129fbe29d2198e930b6202225d23f17ac582fac71fc1533
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
gemirro (
|
4
|
+
gemirro (2.0.0)
|
5
5
|
addressable (~> 2.8)
|
6
6
|
builder (~> 3.2)
|
7
7
|
compact_index (~> 0.15)
|
@@ -50,7 +50,7 @@ GEM
|
|
50
50
|
racc
|
51
51
|
public_suffix (6.0.1)
|
52
52
|
racc (1.8.1)
|
53
|
-
rack (2.2.
|
53
|
+
rack (2.2.14)
|
54
54
|
rack-protection (3.2.0)
|
55
55
|
base64 (>= 0.1.0)
|
56
56
|
rack (~> 2.2, >= 2.2.4)
|
data/MANIFEST
CHANGED
@@ -55,9 +55,6 @@ template/config.rb
|
|
55
55
|
template/logs/.gitkeep
|
56
56
|
template/public/dist/css/gemirro.css
|
57
57
|
template/public/gems/.gitkeep
|
58
|
-
template/public/latest_specs.4.8
|
59
|
-
template/public/prerelease_specs.4.8
|
60
|
-
template/public/specs.4.8
|
61
58
|
views/gem.erb
|
62
59
|
views/index.erb
|
63
60
|
views/layout.erb
|
data/lib/gemirro/cli/index.rb
CHANGED
@@ -19,10 +19,11 @@ Gemirro::CLI.options.command 'index' do
|
|
19
19
|
abort
|
20
20
|
end
|
21
21
|
|
22
|
-
indexer = Gemirro::Indexer.new
|
22
|
+
indexer = Gemirro::Indexer.new
|
23
23
|
indexer.ui = Gem::SilentUI.new
|
24
24
|
|
25
|
-
if File.exist?(File.join(config.
|
25
|
+
if File.exist?(File.join(config.versions_file))
|
26
|
+
indexer.download_source_versions
|
26
27
|
if opts[:u]
|
27
28
|
config.logger.info('Generating index updates')
|
28
29
|
indexer.update_index
|
@@ -31,7 +32,7 @@ Gemirro::CLI.options.command 'index' do
|
|
31
32
|
indexer.generate_index
|
32
33
|
end
|
33
34
|
else
|
34
|
-
config.logger.error("
|
35
|
+
config.logger.error("#{File.basename(config.versions_file)} file is missing.")
|
35
36
|
config.logger.error('Run "gemirro update" before running index.')
|
36
37
|
end
|
37
38
|
end
|
data/lib/gemirro/cli/init.rb
CHANGED
@@ -26,11 +26,6 @@ Gemirro::CLI.options.command 'init' do
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
# make sure index updates blank local specs
|
30
|
-
['specs.4.8', 'latest_specs.4.8', 'prerelease_specs.4.8'].each do |s|
|
31
|
-
File.utime(Time.at(0), Time.at(0), File.join(directory, 'public', s))
|
32
|
-
end
|
33
|
-
|
34
29
|
puts "Initialized empty mirror in #{directory}"
|
35
30
|
end
|
36
31
|
end
|
data/lib/gemirro/cli.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require File.expand_path('../version', __FILE__)
|
4
|
+
|
3
5
|
module Gemirro
|
4
6
|
# CLI mode
|
5
7
|
module CLI
|
@@ -58,7 +60,7 @@ module Gemirro
|
|
58
60
|
# @return [String]
|
59
61
|
#
|
60
62
|
def self.version_information
|
61
|
-
"gemirro v#{VERSION} on #{RUBY_DESCRIPTION}"
|
63
|
+
"gemirro v#{Gemirro::VERSION} on #{RUBY_DESCRIPTION}"
|
62
64
|
end
|
63
65
|
end
|
64
66
|
end
|
@@ -99,18 +99,10 @@ module Gemirro
|
|
99
99
|
#
|
100
100
|
# @return [String]
|
101
101
|
#
|
102
|
-
def
|
103
|
-
|
104
|
-
end
|
102
|
+
def versions_file
|
103
|
+
return unless @source
|
105
104
|
|
106
|
-
|
107
|
-
# Returns the name of the file that contains an index
|
108
|
-
# of all the prerelease versions.
|
109
|
-
#
|
110
|
-
# @return [String]
|
111
|
-
#
|
112
|
-
def self.prerelease_versions_file
|
113
|
-
"prerelease_specs.#{marshal_version}.gz"
|
105
|
+
File.expand_path("#{URI.parse(@source.host).host.gsub('.', '_')}_versions", destination.to_s)
|
114
106
|
end
|
115
107
|
|
116
108
|
##
|
data/lib/gemirro/gems_fetcher.rb
CHANGED
data/lib/gemirro/indexer.rb
CHANGED
@@ -35,19 +35,16 @@ module Gemirro
|
|
35
35
|
# @param [Hash] options Indexer options
|
36
36
|
# @return [Array]
|
37
37
|
##
|
38
|
-
def initialize(
|
38
|
+
def initialize(options = {})
|
39
39
|
require 'fileutils'
|
40
40
|
require 'tmpdir'
|
41
41
|
require 'zlib'
|
42
42
|
require 'builder/xchar'
|
43
43
|
require 'compact_index'
|
44
44
|
|
45
|
-
options.merge!({ build_modern:
|
45
|
+
options.merge!({ build_modern: false })
|
46
46
|
|
47
|
-
@
|
48
|
-
@build_compact = options[:build_compact]
|
49
|
-
|
50
|
-
@dest_directory = directory
|
47
|
+
@dest_directory = Gemirro.configuration.destination
|
51
48
|
@directory =
|
52
49
|
File.join(Dir.tmpdir, "gem_generate_index_#{rand(1_000_000_000)}")
|
53
50
|
|
@@ -69,22 +66,12 @@ module Gemirro
|
|
69
66
|
@latest_index =
|
70
67
|
File.join(@quick_dir, 'latest_index')
|
71
68
|
|
72
|
-
@specs_index =
|
73
|
-
File.join(@directory, "specs.#{::Gem.marshal_version}")
|
74
69
|
@latest_specs_index =
|
75
70
|
File.join(@directory, "latest_specs.#{::Gem.marshal_version}")
|
76
|
-
@prerelease_specs_index =
|
77
|
-
File.join(@directory, "prerelease_specs.#{::Gem.marshal_version}")
|
78
|
-
@dest_specs_index =
|
79
|
-
File.join(@dest_directory, "specs.#{::Gem.marshal_version}")
|
80
71
|
@dest_latest_specs_index =
|
81
72
|
File.join(@dest_directory, "latest_specs.#{::Gem.marshal_version}")
|
82
|
-
@dest_prerelease_specs_index =
|
83
|
-
File.join(@dest_directory, "prerelease_specs.#{::Gem.marshal_version}")
|
84
73
|
@infos_dir =
|
85
74
|
File.join(@dest_directory, 'info')
|
86
|
-
@api_v1_dependencies_dir =
|
87
|
-
File.join(@dest_directory, 'api', 'v1', 'dependencies')
|
88
75
|
|
89
76
|
@files = []
|
90
77
|
end
|
@@ -92,16 +79,9 @@ module Gemirro
|
|
92
79
|
##
|
93
80
|
# Generate indices on the destination directory
|
94
81
|
#
|
95
|
-
def install_indices
|
96
|
-
install_indicies
|
97
|
-
end
|
98
|
-
|
99
|
-
##
|
100
|
-
# Generate indicies on the destination directory
|
101
|
-
#
|
102
82
|
# @return [Array]
|
103
83
|
#
|
104
|
-
def
|
84
|
+
def install_indices
|
105
85
|
Utils.logger
|
106
86
|
.debug("Downloading index into production dir #{@dest_directory}")
|
107
87
|
|
@@ -111,24 +91,19 @@ module Gemirro
|
|
111
91
|
if files.include?(@quick_marshal_dir) && !files.include?(@quick_dir)
|
112
92
|
files.delete @quick_marshal_dir
|
113
93
|
FileUtils.mkdir_p(File.dirname(@quick_marshal_dir_base), verbose: verbose)
|
114
|
-
|
94
|
+
if @quick_marshal_dir_base && File.exist?(@quick_marshal_dir_base)
|
95
|
+
FileUtils.rm_rf(@quick_marshal_dir_base, verbose: verbose)
|
96
|
+
end
|
115
97
|
FileUtils.mv(@quick_marshal_dir, @quick_marshal_dir_base, verbose: verbose, force: true)
|
116
98
|
end
|
117
99
|
|
118
100
|
files.each do |path|
|
119
101
|
file = path.sub(%r{^#{Regexp.escape @directory}/?}, '')
|
120
102
|
|
121
|
-
|
122
|
-
|
123
|
-
"#{@prerelease_specs_index}.gz"].include?(path)
|
124
|
-
res = build_zlib_file(file, File.join(@directory, file), File.join(@dest_directory, file), true)
|
125
|
-
next unless res
|
126
|
-
else
|
127
|
-
source_content = download_from_source(file)
|
128
|
-
next if source_content.nil?
|
103
|
+
source_content = download_from_source(file)
|
104
|
+
next if source_content.nil?
|
129
105
|
|
130
|
-
|
131
|
-
end
|
106
|
+
MirrorFile.new(File.join(@dest_directory, file)).write(source_content)
|
132
107
|
|
133
108
|
FileUtils.rm_rf(path)
|
134
109
|
end
|
@@ -142,7 +117,7 @@ module Gemirro
|
|
142
117
|
#
|
143
118
|
def download_from_source(file)
|
144
119
|
source_host = Gemirro.configuration.source.host
|
145
|
-
Utils.logger.info("Download from source
|
120
|
+
Utils.logger.info("Download from source #{source_host}/#{file}")
|
146
121
|
resp = Http.get("#{source_host}/#{File.basename(file)}")
|
147
122
|
return unless resp.code == 200
|
148
123
|
|
@@ -155,104 +130,18 @@ module Gemirro
|
|
155
130
|
# @return [Array]
|
156
131
|
#
|
157
132
|
def build_indices
|
158
|
-
build_indicies
|
159
|
-
end
|
160
|
-
|
161
|
-
##
|
162
|
-
# Build indicies
|
163
|
-
#
|
164
|
-
# @return [Array]
|
165
|
-
#
|
166
|
-
def build_indicies
|
167
133
|
specs = *map_gems_to_specs(gem_file_list)
|
168
134
|
specs.select! { |s| s.instance_of?(::Gem::Specification) }
|
169
135
|
::Gem::Specification.dirs = []
|
170
136
|
::Gem::Specification.all = specs
|
171
137
|
|
172
|
-
|
173
|
-
build_marshal_gemspecs(specs)
|
174
|
-
build_modern_indices(specs) if @build_modern
|
175
|
-
compress_indices
|
176
|
-
else
|
177
|
-
build_marshal_gemspecs
|
178
|
-
build_modern_indicies if @build_modern
|
179
|
-
compress_indicies
|
180
|
-
end
|
181
|
-
|
182
|
-
build_api_v1_dependencies(specs)
|
183
|
-
|
184
|
-
return unless @build_compact
|
138
|
+
build_marshal_gemspecs(specs)
|
185
139
|
|
186
140
|
build_compact_index_names
|
187
141
|
build_compact_index_infos(specs)
|
188
142
|
build_compact_index_versions(specs)
|
189
143
|
end
|
190
144
|
|
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
145
|
##
|
257
146
|
# Cache compact_index endpoint /names
|
258
147
|
# Report all gems with versions available. Does not require opening spec files.
|
@@ -323,7 +212,7 @@ module Gemirro
|
|
323
212
|
end
|
324
213
|
|
325
214
|
Tempfile.create('versions.list') do |f|
|
326
|
-
previous_versions_file = Dir.glob(File.join(@dest_directory, 'versions
|
215
|
+
previous_versions_file = Dir.glob(File.join(@dest_directory, 'versions.*.*.list')).last
|
327
216
|
|
328
217
|
if partial && previous_versions_file
|
329
218
|
versions_file = CompactIndex::VersionsFile.new(previous_versions_file)
|
@@ -336,7 +225,7 @@ module Gemirro
|
|
336
225
|
f.write CompactIndex.versions(versions_file, cg)
|
337
226
|
f.rewind
|
338
227
|
|
339
|
-
FileUtils.rm_rf(Dir.glob(File.join(@dest_directory, 'versions
|
228
|
+
FileUtils.rm_rf(Dir.glob(File.join(@dest_directory, 'versions.*.*.list')))
|
340
229
|
|
341
230
|
FileUtils.cp(
|
342
231
|
f.path,
|
@@ -359,7 +248,7 @@ module Gemirro
|
|
359
248
|
# @return nil
|
360
249
|
#
|
361
250
|
def build_compact_index_infos(specs, partial = false)
|
362
|
-
FileUtils.mkdir_p(@infos_dir)
|
251
|
+
FileUtils.mkdir_p(@infos_dir, verbose: verbose)
|
363
252
|
|
364
253
|
if partial
|
365
254
|
specs.collect(&:name).uniq do |name|
|
@@ -468,13 +357,8 @@ module Gemirro
|
|
468
357
|
next
|
469
358
|
end
|
470
359
|
|
471
|
-
|
472
|
-
|
473
|
-
spec.sanitize
|
474
|
-
else
|
475
|
-
abbreviate(spec)
|
476
|
-
sanitize(spec)
|
477
|
-
end
|
360
|
+
spec.abbreviate
|
361
|
+
spec.sanitize
|
478
362
|
|
479
363
|
spec
|
480
364
|
rescue SignalException
|
@@ -507,14 +391,15 @@ module Gemirro
|
|
507
391
|
indexed_gemfiles = Dir.glob('*.gemspec.rz', base: @quick_marshal_dir_base).collect { |x| x.gsub(/spec.rz$/, '') }
|
508
392
|
|
509
393
|
@updated_gems = []
|
394
|
+
|
510
395
|
# detect files manually added to public/gems
|
511
396
|
@updated_gems += (present_gemfiles - indexed_gemfiles).collect { |x| File.join(@dest_directory, 'gems', x) }
|
512
397
|
# detect files manually deleted from public/gems
|
513
398
|
@updated_gems += (indexed_gemfiles - present_gemfiles).collect { |x| File.join(@dest_directory, 'gems', x) }
|
514
399
|
|
515
|
-
|
400
|
+
versions_mtime =
|
516
401
|
begin
|
517
|
-
File.stat(@
|
402
|
+
File.stat(Dir.glob(File.join(@dest_directory, 'versions*.list')).last).mtime
|
518
403
|
rescue StandardError
|
519
404
|
Time.at(0)
|
520
405
|
end
|
@@ -525,7 +410,7 @@ module Gemirro
|
|
525
410
|
gem_file_list.select do |gem|
|
526
411
|
gem_mtime = File.stat(gem).mtime
|
527
412
|
newest_mtime = gem_mtime if gem_mtime > newest_mtime
|
528
|
-
gem_mtime >
|
413
|
+
gem_mtime > versions_mtime
|
529
414
|
end
|
530
415
|
|
531
416
|
@updated_gems.uniq!
|
@@ -538,7 +423,7 @@ module Gemirro
|
|
538
423
|
specs = map_gems_to_specs(@updated_gems)
|
539
424
|
|
540
425
|
# specs only includes latest discovered files.
|
541
|
-
# /info/[gemname]
|
426
|
+
# /info/[gemname] can not be rebuilt
|
542
427
|
# incrementally, so retrive specs for all versions of these gems.
|
543
428
|
gem_name_updates = specs.collect(&:name).uniq
|
544
429
|
u2 =
|
@@ -549,108 +434,24 @@ module Gemirro
|
|
549
434
|
Utils.logger.info('Reloading for /info/[gemname]')
|
550
435
|
version_specs = map_gems_to_specs(u2)
|
551
436
|
|
552
|
-
prerelease, released = specs.partition { |s| s.version.prerelease? }
|
553
|
-
|
554
437
|
::Gem::Specification.dirs = []
|
555
438
|
::Gem::Specification.all = *specs
|
556
|
-
|
557
|
-
if ::Gem::VERSION >= '2.5.0'
|
558
|
-
build_marshal_gemspecs specs
|
559
|
-
else
|
560
|
-
build_marshal_gemspecs
|
561
|
-
end
|
562
|
-
|
563
|
-
::Gem.time('Updated indexes') do
|
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
|
-
)
|
579
|
-
end
|
580
|
-
|
581
|
-
if ::Gem::VERSION >= '2.5.0'
|
582
|
-
compress_indices
|
583
|
-
else
|
584
|
-
compress_indicies
|
585
|
-
end
|
439
|
+
build_marshal_gemspecs specs
|
586
440
|
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
build_compact_index_names
|
591
|
-
build_compact_index_infos(version_specs, true)
|
592
|
-
build_compact_index_versions(specs, true)
|
593
|
-
end
|
594
|
-
|
595
|
-
Utils.logger.info("Updating production dir #{@dest_directory}") if verbose
|
596
|
-
files << @specs_index
|
597
|
-
files << "#{@specs_index}.gz"
|
598
|
-
files << @latest_specs_index
|
599
|
-
files << "#{@latest_specs_index}.gz"
|
600
|
-
files << @prerelease_specs_index
|
601
|
-
files << "#{@prerelease_specs_index}.gz"
|
602
|
-
|
603
|
-
files.each do |path|
|
604
|
-
file = path.sub(%r{^#{Regexp.escape @directory}/?}, '')
|
605
|
-
|
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))
|
608
|
-
next unless res
|
609
|
-
else
|
610
|
-
FileUtils.mv(
|
611
|
-
File.join(@directory, file),
|
612
|
-
File.join(@dest_directory, file),
|
613
|
-
verbose: verbose,
|
614
|
-
force: true
|
615
|
-
)
|
616
|
-
end
|
617
|
-
|
618
|
-
File.utime(newest_mtime, newest_mtime, File.join(@dest_directory, file))
|
619
|
-
end
|
620
|
-
end
|
621
|
-
|
622
|
-
def build_zlib_file(file, src_name, dst_name, from_source = false)
|
623
|
-
content = Marshal.load(Zlib::GzipReader.open(src_name).read)
|
624
|
-
create_zlib_file("#{dst_name}.local", content)
|
625
|
-
|
626
|
-
return false if @only_origin
|
627
|
-
|
628
|
-
if from_source
|
629
|
-
source_content = download_from_source(file)
|
630
|
-
source_content = Marshal.load(
|
631
|
-
Zlib::GzipReader.new(
|
632
|
-
StringIO.new(source_content)
|
633
|
-
).read
|
634
|
-
)
|
635
|
-
else
|
636
|
-
source_content = Marshal.load(Zlib::GzipReader.open(dst_name).read)
|
637
|
-
end
|
638
|
-
|
639
|
-
return false if source_content.nil?
|
640
|
-
|
641
|
-
new_content = source_content.concat(content).uniq
|
642
|
-
create_zlib_file(dst_name, new_content)
|
441
|
+
build_compact_index_infos(version_specs, true)
|
442
|
+
build_compact_index_versions(specs, true)
|
443
|
+
build_compact_index_names
|
643
444
|
end
|
644
445
|
|
645
|
-
def
|
646
|
-
Tempfile.create(File.basename(
|
647
|
-
|
648
|
-
|
649
|
-
gzf.close
|
446
|
+
def download_source_versions
|
447
|
+
Tempfile.create(File.basename(Gemirro.configuration.versions_file)) do |f|
|
448
|
+
f.write(download_from_source('versions'))
|
449
|
+
f.close
|
650
450
|
|
451
|
+
FileUtils.rm(Gemirro.configuration.versions_file, verbose: verbose)
|
651
452
|
FileUtils.cp(
|
652
453
|
f.path,
|
653
|
-
|
454
|
+
Gemirro.configuration.versions_file,
|
654
455
|
verbose: verbose
|
655
456
|
)
|
656
457
|
end
|
data/lib/gemirro/server.rb
CHANGED
@@ -4,6 +4,7 @@ require 'sinatra/base'
|
|
4
4
|
require 'thin'
|
5
5
|
require 'uri'
|
6
6
|
require 'addressable/uri'
|
7
|
+
require 'base64'
|
7
8
|
|
8
9
|
module Gemirro
|
9
10
|
##
|
@@ -78,39 +79,6 @@ module Gemirro
|
|
78
79
|
erb(:index, {}, gems: Utils.gems_collection)
|
79
80
|
end
|
80
81
|
|
81
|
-
##
|
82
|
-
# Return gem dependencies as marshaled binary
|
83
|
-
#
|
84
|
-
# @return [nil]
|
85
|
-
#
|
86
|
-
get '/api/v1/dependencies' do
|
87
|
-
content_type 'application/octet-stream'
|
88
|
-
if params[:gems].to_s != '' && params[:gems].to_s.split(',').any?
|
89
|
-
Marshal.dump(dependencies_loader(params[:gems].to_s.split(',')))
|
90
|
-
else
|
91
|
-
200
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
##
|
96
|
-
# Return gem dependencies as json
|
97
|
-
#
|
98
|
-
# @return [nil]
|
99
|
-
#
|
100
|
-
get '/api/v1/dependencies.json' do
|
101
|
-
content_type 'application/json'
|
102
|
-
|
103
|
-
return '[]' unless params[:gems]
|
104
|
-
|
105
|
-
gem_names = params[:gems].to_s
|
106
|
-
.split(',')
|
107
|
-
.map(&:strip)
|
108
|
-
.reject(&:empty?)
|
109
|
-
return '[]' if gem_names.empty?
|
110
|
-
|
111
|
-
JSON.dump(dependencies_loader(gem_names))
|
112
|
-
end
|
113
|
-
|
114
82
|
##
|
115
83
|
# compact_index, Return list of available gem names
|
116
84
|
#
|
@@ -120,10 +88,10 @@ module Gemirro
|
|
120
88
|
content_type 'text/plain'
|
121
89
|
|
122
90
|
content_path = Dir.glob(File.join(Gemirro.configuration.destination, 'names.*.*.list')).last
|
123
|
-
_, etag, repr_digest, _ = content_path.split('.'
|
91
|
+
_, etag, repr_digest, _ = File.basename(content_path).split('.')
|
124
92
|
|
125
|
-
headers 'etag' => etag
|
126
|
-
headers 'repr-digest' => %(sha-256
|
93
|
+
headers 'etag' => %("#{etag}")
|
94
|
+
headers 'repr-digest' => %(sha-256=#{Base64.strict_encode64([repr_digest].pack('H*'))})
|
127
95
|
send_file content_path
|
128
96
|
end
|
129
97
|
|
@@ -136,10 +104,10 @@ module Gemirro
|
|
136
104
|
content_type 'text/plain'
|
137
105
|
|
138
106
|
content_path = Dir.glob(File.join(Utils.configuration.destination, 'versions.*.*.list')).last
|
139
|
-
_, etag, repr_digest, _ = content_path.split('.'
|
107
|
+
_, etag, repr_digest, _ = File.basename(content_path).split('.')
|
140
108
|
|
141
|
-
headers 'etag' => etag
|
142
|
-
headers 'repr-digest' => %(sha-256
|
109
|
+
headers 'etag' => %("#{etag}")
|
110
|
+
headers 'repr-digest' => %(sha-256=#{Base64.strict_encode64([repr_digest].pack('H*'))})
|
143
111
|
send_file content_path
|
144
112
|
end
|
145
113
|
|
@@ -155,10 +123,10 @@ module Gemirro
|
|
155
123
|
content_type 'text/plain'
|
156
124
|
|
157
125
|
content_path = Dir.glob(File.join(Utils.configuration.destination, 'info', "#{params[:gemname]}.*.*.list")).last
|
158
|
-
_, etag, repr_digest, _ = content_path.split('.'
|
126
|
+
_, etag, repr_digest, _ = File.basename(content_path).split('.')
|
159
127
|
|
160
|
-
headers 'etag' => etag
|
161
|
-
headers 'repr-digest' => %(sha-256
|
128
|
+
headers 'etag' => %("#{etag}")
|
129
|
+
headers 'repr-digest' => %(sha-256=#{Base64.strict_encode64([repr_digest].pack('H*'))})
|
162
130
|
send_file content_path
|
163
131
|
end
|
164
132
|
|
data/lib/gemirro/source.rb
CHANGED
@@ -33,23 +33,10 @@ module Gemirro
|
|
33
33
|
#
|
34
34
|
def fetch_versions
|
35
35
|
Utils.logger.info(
|
36
|
-
"Fetching
|
36
|
+
"Fetching versions on #{@name} (#{@host})"
|
37
37
|
)
|
38
38
|
|
39
|
-
Http.get("#{host}
|
40
|
-
end
|
41
|
-
|
42
|
-
##
|
43
|
-
# Fetches a list of all the available Gems and their versions.
|
44
|
-
#
|
45
|
-
# @return [String]
|
46
|
-
#
|
47
|
-
def fetch_prerelease_versions
|
48
|
-
Utils.logger.info(
|
49
|
-
"Fetching #{Configuration.prerelease_versions_file} " \
|
50
|
-
"on #{@name} (#{@host})"
|
51
|
-
)
|
52
|
-
Http.get("#{host}/#{Configuration.prerelease_versions_file}").body
|
39
|
+
Http.get("#{host}/versions").body
|
53
40
|
end
|
54
41
|
|
55
42
|
##
|
data/lib/gemirro/utils.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'gemirro/gem_version'
|
4
|
+
|
3
5
|
module Gemirro
|
4
6
|
##
|
5
7
|
# The Utils class is responsible for executing specific traitments
|
@@ -33,12 +35,10 @@ module Gemirro
|
|
33
35
|
@gems_collection ||= { files: {}, values: nil }
|
34
36
|
|
35
37
|
file_paths =
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
)
|
41
|
-
end
|
38
|
+
Dir.glob(File.join(
|
39
|
+
Gemirro.configuration.destination,
|
40
|
+
'versions.*.*.list'
|
41
|
+
))
|
42
42
|
|
43
43
|
has_file_changed =
|
44
44
|
@gems_collection[:files] != file_paths.each_with_object({}) do |f, r|
|
@@ -50,12 +50,22 @@ module Gemirro
|
|
50
50
|
|
51
51
|
gems = []
|
52
52
|
|
53
|
-
|
54
|
-
|
55
|
-
|
53
|
+
CompactIndex::VersionsFile.new(file_paths.last).contents.each_line.with_index do |line, index|
|
54
|
+
next if index < 2
|
55
|
+
|
56
|
+
gem_name = line.split[0]
|
57
|
+
versions = line.split[1..-2].collect { |x| x.split(',') }.flatten # All except first and last
|
56
58
|
|
57
|
-
|
58
|
-
|
59
|
+
versions.each do |ver|
|
60
|
+
version, platform =
|
61
|
+
if ver.include?('-')
|
62
|
+
ver.split('-', 2)
|
63
|
+
else
|
64
|
+
[ver, 'ruby']
|
65
|
+
end
|
66
|
+
|
67
|
+
gems << Gemirro::GemVersion.new(gem_name, version, platform)
|
68
|
+
end
|
59
69
|
end
|
60
70
|
|
61
71
|
@gems_collection[:values] = GemVersionCollection.new(gems)
|
@@ -187,7 +197,7 @@ module Gemirro
|
|
187
197
|
# @return [Indexer]
|
188
198
|
#
|
189
199
|
def self.update_indexes
|
190
|
-
indexer = Gemirro::Indexer.new
|
200
|
+
indexer = Gemirro::Indexer.new
|
191
201
|
indexer.only_origin = true
|
192
202
|
indexer.ui = ::Gem::SilentUI.new
|
193
203
|
|
data/lib/gemirro/version.rb
CHANGED
@@ -22,29 +22,24 @@ module Gemirro
|
|
22
22
|
# @return [Gemirro::VersionsFile]
|
23
23
|
#
|
24
24
|
def fetch
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
)
|
25
|
+
return unless Gemirro.configuration.versions_file
|
26
|
+
|
27
|
+
VersionsFile.new(read_file(Gemirro.configuration.versions_file))
|
29
28
|
end
|
30
29
|
|
31
30
|
##
|
32
31
|
# Read file if exists otherwise download its from source
|
33
32
|
#
|
34
33
|
# @param [String] file name
|
35
|
-
# @param [TrueClass|FalseClass] prerelease Is prerelease or not
|
36
34
|
#
|
37
|
-
def read_file(file
|
38
|
-
|
39
|
-
file_dst = File.join(destination, file)
|
40
|
-
unless File.exist?(file_dst)
|
35
|
+
def read_file(file)
|
36
|
+
unless File.exist?(file)
|
41
37
|
throw 'No source defined' unless @source
|
42
38
|
|
43
|
-
File.write(
|
44
|
-
File.write(file_dst, @source.fetch_prerelease_versions) if prerelease
|
39
|
+
File.write(file, @source.fetch_versions)
|
45
40
|
end
|
46
41
|
|
47
|
-
File.read(
|
42
|
+
File.read(file)
|
48
43
|
end
|
49
44
|
end
|
50
45
|
end
|
@@ -11,36 +11,24 @@ module Gemirro
|
|
11
11
|
# @return [Hash]
|
12
12
|
#
|
13
13
|
class VersionsFile
|
14
|
-
attr_reader :
|
14
|
+
attr_reader :versions_string, :versions_hash
|
15
15
|
|
16
16
|
##
|
17
17
|
# Reads the versions file from the specified String.
|
18
18
|
#
|
19
|
-
# @param [String]
|
20
|
-
# @param [String] prerelease_content
|
19
|
+
# @param [String] versions_content
|
21
20
|
# @return [Gemirro::VersionsFile]
|
22
21
|
#
|
23
|
-
def self.load(spec_content, prerelease_content)
|
24
|
-
buffer = StringIO.new(spec_content)
|
25
|
-
reader = Zlib::GzipReader.new(buffer)
|
26
|
-
versions = Marshal.load(reader.read)
|
27
|
-
|
28
|
-
buffer = StringIO.new(prerelease_content)
|
29
|
-
reader = Zlib::GzipReader.new(buffer)
|
30
|
-
versions.concat(Marshal.load(reader.read))
|
31
|
-
|
32
|
-
instance = new(versions)
|
33
|
-
|
34
|
-
reader.close
|
35
|
-
|
36
|
-
instance
|
37
|
-
end
|
38
22
|
|
39
23
|
##
|
40
|
-
# @param [
|
24
|
+
# @param [String] versions
|
41
25
|
#
|
42
|
-
def initialize(
|
43
|
-
|
26
|
+
def initialize(versions_string)
|
27
|
+
unless versions_string.is_a? String
|
28
|
+
throw "#{versions_string.class} is wrong format, expect String; #{versions_string.inspect}"
|
29
|
+
end
|
30
|
+
|
31
|
+
@versions_string = versions_string
|
44
32
|
@versions_hash = create_versions_hash
|
45
33
|
end
|
46
34
|
|
@@ -53,10 +41,24 @@ module Gemirro
|
|
53
41
|
def create_versions_hash
|
54
42
|
hash = Hash.new { |h, k| h[k] = [] }
|
55
43
|
|
56
|
-
|
57
|
-
|
58
|
-
end
|
44
|
+
versions_string.each_line.with_index do |line, index|
|
45
|
+
next if index < 2
|
59
46
|
|
47
|
+
parts = line.split
|
48
|
+
gem_name = parts[0]
|
49
|
+
parts[-1]
|
50
|
+
versions = parts[1..-2].collect { |x| x.split(',') }.flatten # All except first and last
|
51
|
+
|
52
|
+
versions.each do |ver|
|
53
|
+
version, platform =
|
54
|
+
if ver.include?('-')
|
55
|
+
ver.split('-', 2)
|
56
|
+
else
|
57
|
+
[ver, 'ruby']
|
58
|
+
end
|
59
|
+
hash[gem_name] << [gem_name, ::Gem::Version.new(version), platform]
|
60
|
+
end
|
61
|
+
end
|
60
62
|
hash
|
61
63
|
end
|
62
64
|
|
@@ -39,8 +39,8 @@ module Gemirro
|
|
39
39
|
expect(Configuration.marshal_identifier).to match(/Marshal\.(\d+)\.(\d+)/)
|
40
40
|
end
|
41
41
|
|
42
|
-
it 'should
|
43
|
-
expect(
|
42
|
+
it 'should error on version since no source is defined' do
|
43
|
+
expect(Gemirro.configuration.versions_file).to match(nil)
|
44
44
|
end
|
45
45
|
|
46
46
|
it 'should return marshal file' do
|
@@ -84,5 +84,12 @@ module Gemirro
|
|
84
84
|
expect(result.host).to eq('https://rubygems.org')
|
85
85
|
expect(result.name).to eq('rubygems')
|
86
86
|
end
|
87
|
+
|
88
|
+
|
89
|
+
it 'should return versions file with source' do
|
90
|
+
result = @config.define_source('RubyGems', 'https://rubygems.org') do
|
91
|
+
end
|
92
|
+
expect(@config.versions_file).to match(/rubygems_org_versions$/)
|
93
|
+
end
|
87
94
|
end
|
88
95
|
end
|
@@ -12,7 +12,7 @@ module Gemirro
|
|
12
12
|
|
13
13
|
before(:each) do
|
14
14
|
@source = Source.new('RubyGems', 'https://rubygems.org')
|
15
|
-
@versions_file = VersionsFile.new(
|
15
|
+
@versions_file = VersionsFile.new(%(created_at: 2025-04-24T03:46:59Z\n---\nrack 3.0.0,3.0.1 d545a45462d63b1b4865bbb89a109366))
|
16
16
|
@fetcher = GemsFetcher.new(@source, @versions_file)
|
17
17
|
Gemirro.configuration.ignored_gems.clear
|
18
18
|
end
|
@@ -24,7 +24,7 @@ module Gemirro
|
|
24
24
|
|
25
25
|
dir = MirrorDirectory.new('/tmp')
|
26
26
|
dir.add_directory('test')
|
27
|
-
indexer = Indexer.new
|
27
|
+
indexer = Indexer.new
|
28
28
|
|
29
29
|
Struct.new('HttpGet', :code, :body)
|
30
30
|
http_get = Struct::HttpGet.new(200, 'bad')
|
@@ -43,7 +43,7 @@ module Gemirro
|
|
43
43
|
allow(::Gem.configuration).to receive(:really_verbose)
|
44
44
|
.once.and_return(true)
|
45
45
|
|
46
|
-
indexer = Indexer.new
|
46
|
+
indexer = Indexer.new
|
47
47
|
indexer.quick_marshal_dir = '/tmp/gem_generate_index/quick/Marshal.4.8'
|
48
48
|
indexer.dest_directory = '/tmp/test'
|
49
49
|
indexer.directory = '/tmp/gem_generate_index'
|
@@ -97,7 +97,7 @@ module Gemirro
|
|
97
97
|
end
|
98
98
|
|
99
99
|
it 'should build indices' do
|
100
|
-
indexer = Indexer.new
|
100
|
+
indexer = Indexer.new
|
101
101
|
dir = MirrorDirectory.new('/')
|
102
102
|
dir.add_directory('gems')
|
103
103
|
dir.add_directory('quick')
|
@@ -140,7 +140,7 @@ module Gemirro
|
|
140
140
|
end
|
141
141
|
|
142
142
|
it 'should update index and exit ruby gems' do
|
143
|
-
indexer = Indexer.new
|
143
|
+
indexer = Indexer.new
|
144
144
|
MirrorDirectory.new('/')
|
145
145
|
MirrorFile.new('/specs.4.8').write('')
|
146
146
|
expect { indexer.update_index }.to raise_error(::Gem::SystemExitException)
|
@@ -152,7 +152,7 @@ module Gemirro
|
|
152
152
|
dir.add_directory('test/gems')
|
153
153
|
dir.add_directory('test/quick')
|
154
154
|
|
155
|
-
indexer = Indexer.new
|
155
|
+
indexer = Indexer.new
|
156
156
|
indexer.quick_marshal_dir = '/tmp/gem_generate_index/quick/Marshal.4.8'
|
157
157
|
indexer.dest_directory = '/tmp/test'
|
158
158
|
indexer.directory = '/tmp/gem_generate_index'
|
data/spec/gemirro/server_spec.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
require 'rack/test'
|
2
2
|
require 'json'
|
3
3
|
require 'parallel'
|
4
|
+
require 'sinatra/base'
|
5
|
+
require 'thin'
|
6
|
+
require 'base64'
|
4
7
|
require 'gemirro/utils'
|
5
8
|
require 'gemirro/mirror_directory'
|
6
9
|
require 'gemirro/mirror_file'
|
@@ -37,7 +40,6 @@ module Gemirro
|
|
37
40
|
Utils.instance_eval('@gems_source_collection = nil')
|
38
41
|
FakeFS::FileSystem.clone(Gemirro::Configuration.views_directory)
|
39
42
|
allow_any_instance_of(Indexer).to receive(:compress_indices)
|
40
|
-
allow_any_instance_of(Indexer).to receive(:compress_indicies)
|
41
43
|
allow_any_instance_of(Indexer).to receive(:rand).and_return('0')
|
42
44
|
|
43
45
|
source = Source.new('Rubygems', 'https://rubygems.org')
|
@@ -51,6 +53,9 @@ module Gemirro
|
|
51
53
|
.and_return(nil)
|
52
54
|
.and_yield(@fake_logger)
|
53
55
|
|
56
|
+
|
57
|
+
MirrorFile.new('/var/www/gemirro/versions.md5.aaa256.list').write('created_at: 2025-01-01T00:00:00Z\n---\nvolay 0.1.0\n')
|
58
|
+
|
54
59
|
get '/'
|
55
60
|
expect(last_response).to be_ok
|
56
61
|
end
|
@@ -68,14 +73,7 @@ module Gemirro
|
|
68
73
|
end
|
69
74
|
|
70
75
|
it 'should display gem specifications' do
|
71
|
-
|
72
|
-
::Gem::Version.create('0.1.0'),
|
73
|
-
'ruby']])
|
74
|
-
|
75
|
-
MirrorFile.new('/var/www/gemirro/specs.4.8.gz.local').write(Marshal.dump({}))
|
76
|
-
|
77
|
-
|
78
|
-
allow(Zlib::GzipReader).to receive(:open).and_return(double(read: marshal_dump))
|
76
|
+
MirrorFile.new('/var/www/gemirro/versions.md5.aaa256.list').write(%(created_at: 2025-01-01T00:00:00Z\n---\nvolay 0.1.0 checksum))
|
79
77
|
|
80
78
|
get '/gem/volay'
|
81
79
|
|
@@ -84,48 +82,41 @@ module Gemirro
|
|
84
82
|
end
|
85
83
|
|
86
84
|
it 'responds to compact_index /names' do
|
87
|
-
MirrorFile.new('/var/www/gemirro/names.md5.
|
85
|
+
MirrorFile.new('/var/www/gemirro/names.md5.aaa256.list').write(%(---\nvolay))
|
88
86
|
|
89
87
|
get '/names'
|
90
88
|
expect(last_response.status).to eq(200)
|
91
89
|
expect(last_response).to be_ok
|
92
|
-
|
93
|
-
|
94
|
-
expect(last_response.
|
90
|
+
|
91
|
+
|
92
|
+
expect(last_response.body).to eq(%(---\nvolay))
|
93
|
+
expect(last_response.headers['etag']).to eq('"md5"')
|
94
|
+
expect(last_response.headers['repr-digest']).to eq(%(sha-256=#{Base64.strict_encode64(['aaa256'].pack('H*'))}))
|
95
95
|
end
|
96
96
|
|
97
97
|
it 'responds to compact_index /info/[gemname]' do
|
98
|
-
marshal_dump = Marshal.dump([['volay',
|
99
|
-
::Gem::Version.create('0.1.0'),
|
100
|
-
'ruby']])
|
101
|
-
|
102
|
-
MirrorFile.new('/var/www/gemirro/specs.4.8.gz.local').write(Marshal.dump({}))
|
103
|
-
|
104
|
-
allow(Zlib::GzipReader).to receive(:open).and_return(double(read: marshal_dump))
|
105
|
-
|
106
|
-
|
107
98
|
MirrorDirectory.new('/var/www/gemirro/info')
|
108
|
-
MirrorFile.new('/var/www/gemirro/info/volay.md5.
|
99
|
+
MirrorFile.new('/var/www/gemirro/info/volay.md5.aaa256.list').write('---\n 0.1.0 |checksum:sha256\n')
|
109
100
|
|
110
101
|
|
111
102
|
get '/info/volay'
|
112
103
|
expect(last_response.status).to eq(200)
|
113
104
|
expect(last_response).to be_ok
|
114
105
|
expect(last_response.body).to eq('---\n 0.1.0 |checksum:sha256\n')
|
115
|
-
expect(last_response.headers['etag']).to eq("md5")
|
116
|
-
expect(last_response.headers['repr-digest']).to eq(
|
106
|
+
expect(last_response.headers['etag']).to eq('"md5"')
|
107
|
+
expect(last_response.headers['repr-digest']).to eq(%(sha-256=#{Base64.strict_encode64(['aaa256'].pack('H*'))}))
|
117
108
|
end
|
118
109
|
|
119
110
|
|
120
111
|
it 'responds to compact_index /versions' do
|
121
|
-
MirrorFile.new('/var/www/gemirro/versions.md5.
|
112
|
+
MirrorFile.new('/var/www/gemirro/versions.md5.aaa256.list').write(%(created_at: 2025-01-01T00:00:00Z\n---\nvolay 0.1.0))
|
122
113
|
|
123
114
|
get '/versions'
|
124
115
|
expect(last_response.status).to eq(200)
|
125
116
|
expect(last_response).to be_ok
|
126
|
-
expect(last_response.body).to eq(
|
127
|
-
expect(last_response.headers['etag']).to eq("md5")
|
128
|
-
expect(last_response.headers['repr-digest']).to eq(
|
117
|
+
expect(last_response.body).to eq(%(created_at: 2025-01-01T00:00:00Z\n---\nvolay 0.1.0))
|
118
|
+
expect(last_response.headers['etag']).to eq('"md5"')
|
119
|
+
expect(last_response.headers['repr-digest']).to eq(%(sha-256=#{Base64.strict_encode64(['aaa256'].pack('H*'))}))
|
129
120
|
end
|
130
121
|
|
131
122
|
|
@@ -214,31 +205,20 @@ module Gemirro
|
|
214
205
|
end
|
215
206
|
|
216
207
|
context 'dependencies' do
|
217
|
-
it 'should retrieve nothing' do
|
208
|
+
it 'should retrieve nothing and give 404' do
|
218
209
|
get '/api/v1/dependencies'
|
219
|
-
expect(last_response.
|
220
|
-
|
221
|
-
expect(last_response.body).to eq('')
|
222
|
-
expect(last_response).to be_ok
|
210
|
+
expect(last_response.status).to eq(404)
|
211
|
+
expect(last_response).to_not be_ok
|
223
212
|
end
|
224
213
|
|
225
|
-
it 'should retrieve empty json' do
|
226
|
-
get '/api/v1/dependencies.json'
|
227
|
-
expect(last_response.headers['Content-Type'])
|
228
|
-
.to eq('application/json')
|
229
|
-
expect(last_response.body).to eq('[]')
|
230
|
-
expect(last_response).to be_ok
|
231
|
-
end
|
232
214
|
|
233
|
-
it 'should retrieve
|
215
|
+
it 'should retrieve nothing and give 404' do
|
234
216
|
get '/api/v1/dependencies.json?gems=gemirro'
|
235
|
-
expect(last_response.
|
236
|
-
|
237
|
-
expect(last_response.body).to eq('[]')
|
238
|
-
expect(last_response).to be_ok
|
217
|
+
expect(last_response.status).to eq(404)
|
218
|
+
expect(last_response).to_not be_ok
|
239
219
|
end
|
240
220
|
|
241
|
-
it 'should retrieve
|
221
|
+
it 'should retrieve nothing and give 404' do
|
242
222
|
MirrorDirectory.new('/var/www/gemirro')
|
243
223
|
.add_directory('quick/Marshal.4.8')
|
244
224
|
# rubocop:disable Metrics/LineLength
|
@@ -295,11 +275,8 @@ module Gemirro
|
|
295
275
|
allow(Utils).to receive(:gems_collection)
|
296
276
|
.and_return(collection)
|
297
277
|
get '/api/v1/dependencies.json?gems=volay'
|
298
|
-
expect(last_response.
|
299
|
-
|
300
|
-
|
301
|
-
expect(last_response.body).to match(/"name":"volay"/)
|
302
|
-
expect(last_response).to be_ok
|
278
|
+
expect(last_response.status).to eq(404)
|
279
|
+
expect(last_response).to_not be_ok
|
303
280
|
end
|
304
281
|
end
|
305
282
|
end
|
data/spec/gemirro/source_spec.rb
CHANGED
@@ -21,20 +21,11 @@ module Gemirro
|
|
21
21
|
Struct.new('FetchVersions', :body)
|
22
22
|
result = Struct::FetchVersions.new(true)
|
23
23
|
allow(Http).to receive(:get).once.with(
|
24
|
-
"https://rubygems.org
|
24
|
+
"https://rubygems.org/versions"
|
25
25
|
).and_return(result)
|
26
26
|
expect(@source.fetch_versions).to be_truthy
|
27
27
|
end
|
28
28
|
|
29
|
-
it 'should fetch prereleases versions' do
|
30
|
-
Struct.new('FetchPrereleaseVersions', :body)
|
31
|
-
result = Struct::FetchPrereleaseVersions.new(true)
|
32
|
-
allow(Http).to receive(:get).once.with(
|
33
|
-
"https://rubygems.org/#{Configuration.prerelease_versions_file}"
|
34
|
-
).and_return(result)
|
35
|
-
expect(@source.fetch_prerelease_versions).to be_truthy
|
36
|
-
end
|
37
|
-
|
38
29
|
it 'should fetch gem' do
|
39
30
|
Struct.new('FetchGem', :body)
|
40
31
|
result = Struct::FetchGem.new(true)
|
@@ -17,10 +17,9 @@ module Gemirro
|
|
17
17
|
|
18
18
|
it 'should fetch versions' do
|
19
19
|
allow(@source).to receive(:fetch_versions).once.and_return([])
|
20
|
-
allow(
|
21
|
-
allow(
|
22
|
-
allow(File).to receive(:
|
23
|
-
allow(File).to receive(:read).twice.and_return('nothing')
|
20
|
+
allow(VersionsFile).to receive(:load).with('nothing')
|
21
|
+
allow(File).to receive(:write).once
|
22
|
+
allow(File).to receive(:read).once.and_return('nothing')
|
24
23
|
expect(@fetcher.fetch).to be_nil
|
25
24
|
end
|
26
25
|
end
|
@@ -7,44 +7,20 @@ module Gemirro
|
|
7
7
|
describe 'VersionsFile' do
|
8
8
|
include FakeFS::SpecHelpers
|
9
9
|
|
10
|
-
it 'should be initialized' do
|
11
|
-
@versions_file = VersionsFile.new([['gemirro', '0.0.1'],
|
12
|
-
['gemirro', '0.0.2']])
|
13
|
-
expect(@versions_file.versions).to eq([['gemirro', '0.0.1'],
|
14
|
-
['gemirro', '0.0.2']])
|
15
|
-
expect(@versions_file.versions_hash).to eq(
|
16
|
-
'gemirro' => [
|
17
|
-
['gemirro', '0.0.1'],
|
18
|
-
['gemirro', '0.0.2']
|
19
|
-
]
|
20
|
-
)
|
21
|
-
end
|
22
|
-
|
23
10
|
it 'should load versions file' do
|
24
|
-
spec =
|
25
|
-
w_gz = Zlib::GzipWriter.new(spec)
|
26
|
-
w_gz.write(Marshal.dump([['gemirro', '0.0.1'],
|
27
|
-
['gemirro', '0.0.2']]))
|
28
|
-
w_gz.close
|
29
|
-
prerelease = StringIO.new('w')
|
30
|
-
w_gz = Zlib::GzipWriter.new(prerelease)
|
31
|
-
w_gz.write(Marshal.dump([['gemirro', '0.0.1.alpha1'],
|
32
|
-
['gemirro', '0.0.2.alpha2']]))
|
33
|
-
w_gz.close
|
11
|
+
spec = %(created_at: 2025-01-01T00:00:00Z\n---\ngemirro 0.0.1.alpha1,0.0.1,0.0.2.alpha2,0.0.2 checksum)
|
34
12
|
|
35
|
-
result = VersionsFile.
|
13
|
+
result = VersionsFile.new(spec)
|
36
14
|
expect(result).to be_a(VersionsFile)
|
37
15
|
|
38
|
-
expect(result.
|
39
|
-
|
40
|
-
['gemirro', '0.0.1.alpha1'],
|
41
|
-
['gemirro', '0.0.2.alpha2']])
|
16
|
+
expect(result.versions_string).to eq(%(created_at: 2025-01-01T00:00:00Z\n---\ngemirro 0.0.1.alpha1,0.0.1,0.0.2.alpha2,0.0.2 checksum))
|
17
|
+
|
42
18
|
expect(result.versions_hash).to eq(
|
43
19
|
'gemirro' => [
|
44
|
-
['gemirro', '0.0.1'],
|
45
|
-
['gemirro', '0.0.
|
46
|
-
['gemirro', '0.0.
|
47
|
-
['gemirro', '0.0.2
|
20
|
+
['gemirro', ::Gem::Version.new('0.0.1.alpha1'), 'ruby'],
|
21
|
+
['gemirro', ::Gem::Version.new('0.0.1'), 'ruby'],
|
22
|
+
['gemirro', ::Gem::Version.new('0.0.2.alpha2'), 'ruby'],
|
23
|
+
['gemirro', ::Gem::Version.new('0.0.2'), 'ruby']
|
48
24
|
]
|
49
25
|
)
|
50
26
|
end
|
data/template/config.rb
CHANGED
@@ -60,6 +60,6 @@ Gemirro.configuration.configure do
|
|
60
60
|
# All gem in the block will be downloaded with the update command.
|
61
61
|
# Other gems will be downloaded with the server.
|
62
62
|
define_source 'rubygems', 'https://rubygems.org' do
|
63
|
-
gem 'rack', '>=
|
63
|
+
gem 'rack', '>= 3.0.0'
|
64
64
|
end
|
65
65
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gemirro
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pierre Rambaud
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-05-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|
@@ -290,9 +290,6 @@ files:
|
|
290
290
|
- template/logs/.gitkeep
|
291
291
|
- template/public/dist/css/gemirro.css
|
292
292
|
- template/public/gems/.gitkeep
|
293
|
-
- template/public/latest_specs.4.8
|
294
|
-
- template/public/prerelease_specs.4.8
|
295
|
-
- template/public/specs.4.8
|
296
293
|
- views/gem.erb
|
297
294
|
- views/index.erb
|
298
295
|
- views/layout.erb
|
Binary file
|
Binary file
|
data/template/public/specs.4.8
DELETED
Binary file
|