gemirro 1.6.0 → 3.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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +1 -1
  3. data/.gitignore +2 -0
  4. data/.rubocop.yml +3 -1
  5. data/Gemfile +2 -1
  6. data/Gemfile.lock +73 -61
  7. data/MANIFEST +0 -3
  8. data/bin/gemirro +1 -8
  9. data/gemirro.gemspec +4 -6
  10. data/lib/gemirro/cli/index.rb +48 -27
  11. data/lib/gemirro/cli/init.rb +48 -29
  12. data/lib/gemirro/cli/list.rb +37 -17
  13. data/lib/gemirro/cli/server.rb +173 -114
  14. data/lib/gemirro/cli/update.rb +42 -17
  15. data/lib/gemirro/cli.rb +64 -21
  16. data/lib/gemirro/configuration.rb +26 -20
  17. data/lib/gemirro/gem_version.rb +1 -0
  18. data/lib/gemirro/gem_version_collection.rb +4 -4
  19. data/lib/gemirro/gems_fetcher.rb +9 -9
  20. data/lib/gemirro/http.rb +115 -41
  21. data/lib/gemirro/indexer.rb +33 -232
  22. data/lib/gemirro/mirror_file.rb +3 -10
  23. data/lib/gemirro/server.rb +12 -43
  24. data/lib/gemirro/source.rb +2 -15
  25. data/lib/gemirro/utils.rb +22 -12
  26. data/lib/gemirro/version.rb +1 -1
  27. data/lib/gemirro/versions_fetcher.rb +7 -12
  28. data/lib/gemirro/versions_file.rb +26 -24
  29. data/lib/gemirro.rb +3 -7
  30. data/spec/gemirro/cli_spec.rb +49 -15
  31. data/spec/gemirro/configuration_spec.rb +9 -2
  32. data/spec/gemirro/gems_fetcher_spec.rb +2 -2
  33. data/spec/gemirro/http_spec.rb +58 -54
  34. data/spec/gemirro/indexer_spec.rb +5 -5
  35. data/spec/gemirro/server_spec.rb +30 -52
  36. data/spec/gemirro/source_spec.rb +2 -10
  37. data/spec/gemirro/versions_fetcher_spec.rb +3 -4
  38. data/spec/gemirro/versions_file_spec.rb +8 -32
  39. data/template/config.rb +1 -1
  40. metadata +29 -69
  41. data/template/public/latest_specs.4.8 +0 -0
  42. data/template/public/prerelease_specs.4.8 +0 -0
  43. data/template/public/specs.4.8 +0 -0
@@ -1,6 +1,10 @@
1
+ require 'spec_helper'
1
2
  require 'rack/test'
2
3
  require 'json'
3
4
  require 'parallel'
5
+ require 'sinatra/base'
6
+ require 'puma'
7
+ require 'base64'
4
8
  require 'gemirro/utils'
5
9
  require 'gemirro/mirror_directory'
6
10
  require 'gemirro/mirror_file'
@@ -37,7 +41,6 @@ module Gemirro
37
41
  Utils.instance_eval('@gems_source_collection = nil')
38
42
  FakeFS::FileSystem.clone(Gemirro::Configuration.views_directory)
39
43
  allow_any_instance_of(Indexer).to receive(:compress_indices)
40
- allow_any_instance_of(Indexer).to receive(:compress_indicies)
41
44
  allow_any_instance_of(Indexer).to receive(:rand).and_return('0')
42
45
 
43
46
  source = Source.new('Rubygems', 'https://rubygems.org')
@@ -51,6 +54,9 @@ module Gemirro
51
54
  .and_return(nil)
52
55
  .and_yield(@fake_logger)
53
56
 
57
+
58
+ MirrorFile.new('/var/www/gemirro/versions.md5.aaa256.list').write('created_at: 2025-01-01T00:00:00Z\n---\nvolay 0.1.0\n')
59
+
54
60
  get '/'
55
61
  expect(last_response).to be_ok
56
62
  end
@@ -68,14 +74,7 @@ module Gemirro
68
74
  end
69
75
 
70
76
  it 'should display gem specifications' do
71
- marshal_dump = Marshal.dump([['volay',
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))
77
+ MirrorFile.new('/var/www/gemirro/versions.md5.aaa256.list').write(%(created_at: 2025-01-01T00:00:00Z\n---\nvolay 0.1.0 checksum))
79
78
 
80
79
  get '/gem/volay'
81
80
 
@@ -84,48 +83,41 @@ module Gemirro
84
83
  end
85
84
 
86
85
  it 'responds to compact_index /names' do
87
- MirrorFile.new('/var/www/gemirro/names.md5.sha256.list').write('---\n- volay\n')
86
+ MirrorFile.new('/var/www/gemirro/names.md5.aaa256.list').write(%(---\nvolay))
88
87
 
89
88
  get '/names'
90
89
  expect(last_response.status).to eq(200)
91
90
  expect(last_response).to be_ok
92
- expect(last_response.body).to eq('---\n- volay\n')
93
- expect(last_response.headers['etag']).to eq("md5")
94
- expect(last_response.headers['repr-digest']).to eq('sha-256="sha256"')
91
+
92
+
93
+ expect(last_response.body).to eq(%(---\nvolay))
94
+ expect(last_response.headers['etag']).to eq('"md5"')
95
+ expect(last_response.headers['repr-digest']).to eq(%(sha-256=#{Base64.strict_encode64(['aaa256'].pack('H*'))}))
95
96
  end
96
97
 
97
98
  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
99
  MirrorDirectory.new('/var/www/gemirro/info')
108
- MirrorFile.new('/var/www/gemirro/info/volay.md5.sha256.list').write('---\n 0.1.0 |checksum:sha256\n')
100
+ MirrorFile.new('/var/www/gemirro/info/volay.md5.aaa256.list').write('---\n 0.1.0 |checksum:sha256\n')
109
101
 
110
102
 
111
103
  get '/info/volay'
112
104
  expect(last_response.status).to eq(200)
113
105
  expect(last_response).to be_ok
114
106
  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('sha-256="sha256"')
107
+ expect(last_response.headers['etag']).to eq('"md5"')
108
+ expect(last_response.headers['repr-digest']).to eq(%(sha-256=#{Base64.strict_encode64(['aaa256'].pack('H*'))}))
117
109
  end
118
110
 
119
111
 
120
112
  it 'responds to compact_index /versions' do
121
- MirrorFile.new('/var/www/gemirro/versions.md5.sha256.list').write('created_at: 2025-01-01T00:00:00Z\m---\nvolay 0.1.0\n')
113
+ MirrorFile.new('/var/www/gemirro/versions.md5.aaa256.list').write(%(created_at: 2025-01-01T00:00:00Z\n---\nvolay 0.1.0))
122
114
 
123
115
  get '/versions'
124
116
  expect(last_response.status).to eq(200)
125
117
  expect(last_response).to be_ok
126
- expect(last_response.body).to eq('created_at: 2025-01-01T00:00:00Z\m---\nvolay 0.1.0\n')
127
- expect(last_response.headers['etag']).to eq("md5")
128
- expect(last_response.headers['repr-digest']).to eq('sha-256="sha256"')
118
+ expect(last_response.body).to eq(%(created_at: 2025-01-01T00:00:00Z\n---\nvolay 0.1.0))
119
+ expect(last_response.headers['etag']).to eq('"md5"')
120
+ expect(last_response.headers['repr-digest']).to eq(%(sha-256=#{Base64.strict_encode64(['aaa256'].pack('H*'))}))
129
121
  end
130
122
 
131
123
 
@@ -214,31 +206,20 @@ module Gemirro
214
206
  end
215
207
 
216
208
  context 'dependencies' do
217
- it 'should retrieve nothing' do
209
+ it 'should retrieve nothing and give 404' do
218
210
  get '/api/v1/dependencies'
219
- expect(last_response.headers['Content-Type'])
220
- .to eq('application/octet-stream')
221
- expect(last_response.body).to eq('')
222
- expect(last_response).to be_ok
211
+ expect(last_response.status).to eq(404)
212
+ expect(last_response).to_not be_ok
223
213
  end
224
214
 
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
215
 
233
- it 'should retrieve empty json when gem was not found' do
216
+ it 'should retrieve nothing and give 404' do
234
217
  get '/api/v1/dependencies.json?gems=gemirro'
235
- expect(last_response.headers['Content-Type'])
236
- .to eq('application/json')
237
- expect(last_response.body).to eq('[]')
238
- expect(last_response).to be_ok
218
+ expect(last_response.status).to eq(404)
219
+ expect(last_response).to_not be_ok
239
220
  end
240
221
 
241
- it 'should retrieve json when gem was found' do
222
+ it 'should retrieve nothing and give 404' do
242
223
  MirrorDirectory.new('/var/www/gemirro')
243
224
  .add_directory('quick/Marshal.4.8')
244
225
  # rubocop:disable Metrics/LineLength
@@ -295,11 +276,8 @@ module Gemirro
295
276
  allow(Utils).to receive(:gems_collection)
296
277
  .and_return(collection)
297
278
  get '/api/v1/dependencies.json?gems=volay'
298
- expect(last_response.headers['Content-Type'])
299
- .to eq('application/json')
300
-
301
- expect(last_response.body).to match(/"name":"volay"/)
302
- expect(last_response).to be_ok
279
+ expect(last_response.status).to eq(404)
280
+ expect(last_response).to_not be_ok
303
281
  end
304
282
  end
305
283
  end
@@ -1,4 +1,5 @@
1
1
  require 'spec_helper'
2
+ require 'gemirro/configuration'
2
3
  require 'gemirro/http'
3
4
  require 'gemirro/utils'
4
5
  require 'gemirro/source'
@@ -21,20 +22,11 @@ module Gemirro
21
22
  Struct.new('FetchVersions', :body)
22
23
  result = Struct::FetchVersions.new(true)
23
24
  allow(Http).to receive(:get).once.with(
24
- "https://rubygems.org/#{Configuration.versions_file}"
25
+ "https://rubygems.org/versions"
25
26
  ).and_return(result)
26
27
  expect(@source.fetch_versions).to be_truthy
27
28
  end
28
29
 
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
30
  it 'should fetch gem' do
39
31
  Struct.new('FetchGem', :body)
40
32
  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(@source).to receive(:fetch_prerelease_versions).once.and_return([])
21
- allow(VersionsFile).to receive(:load).with('nothing', 'nothing')
22
- allow(File).to receive(:write).twice
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 = StringIO.new('w')
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.load(spec.string, prerelease.string)
13
+ result = VersionsFile.new(spec)
36
14
  expect(result).to be_a(VersionsFile)
37
15
 
38
- expect(result.versions).to eq([['gemirro', '0.0.1'],
39
- ['gemirro', '0.0.2'],
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.2'],
46
- ['gemirro', '0.0.1.alpha1'],
47
- ['gemirro', '0.0.2.alpha2']
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', '>= 1.0.0'
63
+ gem 'rack', '>= 3.0.0'
64
64
  end
65
65
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gemirro
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.0
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pierre Rambaud
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2025-02-04 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: addressable
@@ -66,34 +65,6 @@ dependencies:
66
65
  - - "~>"
67
66
  - !ruby/object:Gem::Version
68
67
  version: '1.1'
69
- - !ruby/object:Gem::Dependency
70
- name: erubis
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: '2.7'
76
- type: :runtime
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: '2.7'
83
- - !ruby/object:Gem::Dependency
84
- name: httpclient
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: '2.8'
90
- type: :runtime
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "~>"
95
- - !ruby/object:Gem::Version
96
- version: '2.8'
97
68
  - !ruby/object:Gem::Dependency
98
69
  name: logger
99
70
  requirement: !ruby/object:Gem::Requirement
@@ -151,81 +122,75 @@ dependencies:
151
122
  - !ruby/object:Gem::Version
152
123
  version: '1.21'
153
124
  - !ruby/object:Gem::Dependency
154
- name: rubygems-generate_index
125
+ name: puma
155
126
  requirement: !ruby/object:Gem::Requirement
156
127
  requirements:
157
- - - ">"
128
+ - - "~>"
158
129
  - !ruby/object:Gem::Version
159
- version: '0'
130
+ version: '6.4'
160
131
  type: :runtime
161
132
  prerelease: false
162
133
  version_requirements: !ruby/object:Gem::Requirement
163
134
  requirements:
164
- - - ">"
135
+ - - "~>"
165
136
  - !ruby/object:Gem::Version
166
- version: '0'
137
+ version: '6.4'
167
138
  - !ruby/object:Gem::Dependency
168
- name: sinatra
139
+ name: rackup
169
140
  requirement: !ruby/object:Gem::Requirement
170
141
  requirements:
171
- - - ">="
172
- - !ruby/object:Gem::Version
173
- version: '3.1'
174
- - - "<"
142
+ - - "~>"
175
143
  - !ruby/object:Gem::Version
176
- version: '4.0'
144
+ version: '2.2'
177
145
  type: :runtime
178
146
  prerelease: false
179
147
  version_requirements: !ruby/object:Gem::Requirement
180
148
  requirements:
181
- - - ">="
182
- - !ruby/object:Gem::Version
183
- version: '3.1'
184
- - - "<"
149
+ - - "~>"
185
150
  - !ruby/object:Gem::Version
186
- version: '4.0'
151
+ version: '2.2'
187
152
  - !ruby/object:Gem::Dependency
188
- name: slop
153
+ name: rubygems-generate_index
189
154
  requirement: !ruby/object:Gem::Requirement
190
155
  requirements:
191
- - - "~>"
156
+ - - ">"
192
157
  - !ruby/object:Gem::Version
193
- version: '3.6'
158
+ version: '0'
194
159
  type: :runtime
195
160
  prerelease: false
196
161
  version_requirements: !ruby/object:Gem::Requirement
197
162
  requirements:
198
- - - "~>"
163
+ - - ">"
199
164
  - !ruby/object:Gem::Version
200
- version: '3.6'
165
+ version: '0'
201
166
  - !ruby/object:Gem::Dependency
202
- name: stringio
167
+ name: sinatra
203
168
  requirement: !ruby/object:Gem::Requirement
204
169
  requirements:
205
- - - ">"
170
+ - - "~>"
206
171
  - !ruby/object:Gem::Version
207
- version: '0'
172
+ version: '4.0'
208
173
  type: :runtime
209
174
  prerelease: false
210
175
  version_requirements: !ruby/object:Gem::Requirement
211
176
  requirements:
212
- - - ">"
177
+ - - "~>"
213
178
  - !ruby/object:Gem::Version
214
- version: '0'
179
+ version: '4.0'
215
180
  - !ruby/object:Gem::Dependency
216
- name: thin
181
+ name: stringio
217
182
  requirement: !ruby/object:Gem::Requirement
218
183
  requirements:
219
- - - "~>"
184
+ - - ">"
220
185
  - !ruby/object:Gem::Version
221
- version: '1.8'
186
+ version: '0'
222
187
  type: :runtime
223
188
  prerelease: false
224
189
  version_requirements: !ruby/object:Gem::Requirement
225
190
  requirements:
226
- - - "~>"
191
+ - - ">"
227
192
  - !ruby/object:Gem::Version
228
- version: '1.8'
193
+ version: '0'
229
194
  description: Create your own gems mirror.
230
195
  email: pierre.rambaud86@gmail.com
231
196
  executables:
@@ -290,9 +255,6 @@ files:
290
255
  - template/logs/.gitkeep
291
256
  - template/public/dist/css/gemirro.css
292
257
  - 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
258
  - views/gem.erb
297
259
  - views/index.erb
298
260
  - views/layout.erb
@@ -302,7 +264,6 @@ licenses:
302
264
  - GPL-3.0
303
265
  metadata:
304
266
  rubygems_mfa_required: 'true'
305
- post_install_message:
306
267
  rdoc_options: []
307
268
  require_paths:
308
269
  - lib
@@ -310,15 +271,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
310
271
  requirements:
311
272
  - - ">="
312
273
  - !ruby/object:Gem::Version
313
- version: '3.0'
274
+ version: '3.2'
314
275
  required_rubygems_version: !ruby/object:Gem::Requirement
315
276
  requirements:
316
277
  - - ">="
317
278
  - !ruby/object:Gem::Version
318
279
  version: '0'
319
280
  requirements: []
320
- rubygems_version: 3.4.19
321
- signing_key:
281
+ rubygems_version: 3.6.7
322
282
  specification_version: 4
323
283
  summary: Gem for easily creating your own gems mirror.
324
284
  test_files: []
Binary file
Binary file
Binary file