gemirro 0.11.0 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of gemirro might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 369070871caf336cca42522e1ecf00a33b8146de
4
- data.tar.gz: 45b5271ac12aab2d9db654ecf5ac75d61790f173
3
+ metadata.gz: 8982c03b3986ec30f9cb52186836ff37b677a369
4
+ data.tar.gz: 4983fc83b1bf255c6b74da5a66482ac868ae66c2
5
5
  SHA512:
6
- metadata.gz: 023bb1b397f46bd27afd2d777c2bc0a67f257ee9d32b1031a3bb6f883667d7c44b89ef74d4ce25121ee9a0e7868ff7a71a43985c043288b8a6d756db627d077e
7
- data.tar.gz: 4aeb7d45c0d41f3ee2b2cbd0d8d47cba52ec659a4357b30e8fac170a48dedce7e755718b007d3997cf91ad8b1eccb4de7d509b436c7e0e18e6f63345edcf1e15
6
+ metadata.gz: 379c27532e2525d86ee0590b9b42697672a1e44c517574d6ded98bfc52fd7699192df09cab8158c19a8edacd325a430e946f980ddc18d483b72352ebd4840252
7
+ data.tar.gz: 0ff72c9c524b607df1a98dd2f1662522ef8c5d2fa743a0247241ba7a65b30c3f1049915345157ad05a2ede29ff6d6d9bdad33ab29f74a8703b2e637586293fb4
data/MANIFEST CHANGED
@@ -9,6 +9,7 @@ Rakefile
9
9
  bin/gemirro
10
10
  gemirro.gemspec
11
11
  lib/gemirro.rb
12
+ lib/gemirro/cache.rb
12
13
  lib/gemirro/cli.rb
13
14
  lib/gemirro/cli/index.rb
14
15
  lib/gemirro/cli/init.rb
@@ -63,4 +64,4 @@ template/public/gems/.gitkeep
63
64
  views/gem.erb
64
65
  views/index.erb
65
66
  views/layout.erb
66
- views/not_found.erb
67
+ views/not_found.erb
data/README.md CHANGED
@@ -8,6 +8,7 @@ More, to mirroring a source, you only need to start the server, and gems will au
8
8
 
9
9
  * Ruby 1.9.2 or newer
10
10
  * Enough space to store Gems
11
+ * A recent version of Rubygems (`gem update --system`)
11
12
 
12
13
  ## Installation
13
14
 
data/gemirro.gemspec CHANGED
@@ -1,4 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
+ require 'date'
2
3
  require File.expand_path('../lib/gemirro/version', __FILE__)
3
4
 
4
5
  Gem::Specification.new do |s|
@@ -23,6 +24,7 @@ Gem::Specification.new do |s|
23
24
  s.add_dependency 'builder', '~>3.2'
24
25
  s.add_dependency 'sinatra', '~>1.4'
25
26
  s.add_dependency 'thin', '~>1.6'
27
+ s.add_dependency 'pmap', '~>1.0'
26
28
 
27
29
  s.add_development_dependency 'rake', '~>10.4'
28
30
  s.add_development_dependency 'rack-test', '~>0.6'
@@ -0,0 +1,113 @@
1
+ # -*- coding: utf-8 -*-
2
+ module Gemirro
3
+ ##
4
+ # The Cache class contains all method to store marshal informations
5
+ # into files.
6
+ #
7
+ # @!attribute [r] root_path
8
+ # @return [String]
9
+ #
10
+ class Cache
11
+ attr_reader :root_path
12
+
13
+ ##
14
+ # Initialize cache root path
15
+ #
16
+ # @param [String] path
17
+ #
18
+ def initialize(path)
19
+ @root_path = path
20
+ create_root_path
21
+ end
22
+
23
+ ##
24
+ # Create root path
25
+ #
26
+ def create_root_path
27
+ FileUtils.mkdir_p(@root_path)
28
+ end
29
+
30
+ ##
31
+ # Flush cache directory
32
+ #
33
+ def flush
34
+ FileUtils.rm_rf(@root_path)
35
+ create_root_path
36
+ end
37
+
38
+ ##
39
+ # Flush key
40
+ #
41
+ # @param [String] key
42
+ #
43
+ def flush_key(key)
44
+ path = key_path(key2hash(key))
45
+ FileUtils.rm_f(path)
46
+ end
47
+
48
+ ##
49
+ # Cache data
50
+ #
51
+ # @param [String] key
52
+ #
53
+ # @return [Mixed]
54
+ #
55
+ def cache(key)
56
+ key_hash = key2hash(key)
57
+ read(key_hash) || (write(key_hash, yield) if block_given?)
58
+ end
59
+
60
+ private
61
+
62
+ ##
63
+ # Convert key to hash
64
+ #
65
+ # @param [String] key
66
+ #
67
+ # @return [String]
68
+ #
69
+ def key2hash(key)
70
+ Digest::MD5.hexdigest(key)
71
+ end
72
+
73
+ ##
74
+ # Path from key hash
75
+ #
76
+ # @param [String] key_hash
77
+ #
78
+ # @return [String]
79
+ #
80
+ def key_path(key_hash)
81
+ File.join(@root_path, key_hash)
82
+ end
83
+
84
+ ##
85
+ # Read cache
86
+ #
87
+ # @param [String] key_hash
88
+ #
89
+ # @return [Mixed]
90
+ #
91
+ def read(key_hash)
92
+ path = key_path(key_hash)
93
+ Marshal.load(File.open(path)) if File.exist?(path)
94
+ end
95
+
96
+ ##
97
+ # write cache
98
+ #
99
+ # @param [String] key_hash
100
+ # @param [Mixed] value
101
+ #
102
+ # @return [Mixed]
103
+ #
104
+ def write(key_hash, value)
105
+ return value if value.nil? || value.empty?
106
+ File.open(key_path(key_hash), 'wb') do |f|
107
+ Marshal.dump(value, f)
108
+ end
109
+
110
+ value
111
+ end
112
+ end
113
+ end
@@ -28,7 +28,9 @@ Gemirro::CLI.options.command 'server' do
28
28
  abort
29
29
  end
30
30
 
31
- @pid_file = File.join(config.destination, '..', 'gemirro.pid')
31
+ @pid_file = File.expand_path(File.join(config.destination,
32
+ '..',
33
+ 'gemirro.pid'))
32
34
  require 'gemirro/server'
33
35
  end
34
36
 
@@ -56,7 +58,6 @@ Gemirro::CLI.options.command 'server' do
56
58
  end
57
59
  rescue Errno::ENOENT
58
60
  puts "Error: PID File not found #{@pid_file}"
59
- exit!
60
61
  end
61
62
 
62
63
  def start
@@ -79,6 +80,8 @@ Gemirro::CLI.options.command 'server' do
79
80
 
80
81
  def stop
81
82
  process_pid = pid
83
+ return if process_pid.nil?
84
+
82
85
  begin
83
86
  Process.kill('TERM', process_pid)
84
87
  Timeout.timeout(30) { sleep 0.1 while running?(process_pid) }
data/lib/gemirro/cli.rb CHANGED
@@ -30,6 +30,7 @@ module Gemirro
30
30
  def self.load_configuration(config_file)
31
31
  config_file ||= Configuration.default_configuration_file
32
32
  config_file = File.expand_path(config_file, Dir.pwd)
33
+ config_file += '/config.rb' unless config_file.end_with?('config.rb')
33
34
 
34
35
  unless File.file?(config_file)
35
36
  abort "The configuration file #{config_file} does not exist"
data/lib/gemirro/gem.rb CHANGED
@@ -9,9 +9,11 @@ module Gemirro
9
9
  # @return [String]
10
10
  # @!attribute [r] requirement
11
11
  # @return [Gem::Requirement]
12
+ # @!attribute [r] version
13
+ # @return [Gem::Version]
12
14
  #
13
15
  class Gem
14
- attr_reader :name, :requirement, :platform
16
+ attr_reader :name, :requirement, :platform, :version
15
17
  attr_accessor :gemspec
16
18
 
17
19
  ##
@@ -11,10 +11,12 @@ module Gemirro
11
11
  # @return [Integer]
12
12
  # @!attribute [r] platform
13
13
  # @return [String]
14
+ # @!attribute [r] version
15
+ # @return [Gem::Version]
14
16
  #
15
17
  class GemVersion
16
18
  include Comparable
17
- attr_reader :name, :number, :platform
19
+ attr_reader :name, :number, :platform, :version
18
20
 
19
21
  ##
20
22
  # @param [String] name
@@ -42,7 +44,7 @@ module Gemirro
42
44
  # @return [Gem::Version]
43
45
  #
44
46
  def version
45
- ::Gem::Version.create(number)
47
+ @version ||= ::Gem::Version.create(number)
46
48
  end
47
49
 
48
50
  ##
@@ -25,6 +25,8 @@ module Gemirro
25
25
  GemVersion.new(*object)
26
26
  end
27
27
  end
28
+
29
+ @gems.sort_by!(&:version)
28
30
  end
29
31
 
30
32
  ##
@@ -48,15 +48,9 @@ module Gemirro
48
48
  # @return [Array]
49
49
  #
50
50
  def versions_for(gem)
51
- available = @versions_file.versions_for(gem.name)
52
- versions = gem.version? ? [gem.version] : available
53
- available_names = available.map(&:to_s)
54
-
55
- # Get rid of invalid versions. Due to Gem::Version having a custom ==
56
- # method, which treats "3.4" the same as "3.4.0" we'll have to compare
57
- # the versions as String instances.
58
- versions = versions.select do |version|
59
- available_names.include?(version.to_s)
51
+ available = @versions_file.versions_for(gem.name)
52
+ versions = available.select do |v|
53
+ gem.requirement.satisfied_by?(v)
60
54
  end
61
55
 
62
56
  versions = [available.last] if versions.empty?
@@ -115,7 +109,7 @@ module Gemirro
115
109
  # @return [String]
116
110
  #
117
111
  def fetch_from_source(gem, version, gemspec = false)
118
- data = nil
112
+ data = nil
119
113
  begin
120
114
  data = @source.fetch_gem(gem.name, version) unless gemspec
121
115
  data = @source.fetch_gemspec(gem.name, version) if gemspec
@@ -15,13 +15,17 @@ module Gemirro
15
15
  # @return [String]
16
16
  # @!attribute [r] only_origin
17
17
  # @return [Boolean]
18
+ # @!attribute [r] updated_gems
19
+ # @return [Array]
18
20
  #
19
21
  class Indexer < ::Gem::Indexer
20
22
  attr_accessor(:files,
21
23
  :quick_marshal_dir,
22
24
  :directory,
23
25
  :dest_directory,
24
- :only_origin)
26
+ :only_origin,
27
+ :updated_gems)
28
+ attr_reader :cache
25
29
 
26
30
  ##
27
31
  # Create an indexer that will index the gems in +directory+.
@@ -202,18 +206,18 @@ module Gemirro
202
206
  specs_mtime = File.stat(@dest_specs_index).mtime
203
207
  newest_mtime = Time.at(0)
204
208
 
205
- updated_gems = gem_file_list.select do |gem|
209
+ @updated_gems = gem_file_list.select do |gem|
206
210
  gem_mtime = File.stat(gem).mtime
207
211
  newest_mtime = gem_mtime if gem_mtime > newest_mtime
208
212
  gem_mtime > specs_mtime
209
213
  end
210
214
 
211
- if updated_gems.empty?
215
+ if @updated_gems.empty?
212
216
  logger.info('No new gems')
213
217
  terminate_interaction(0)
214
218
  end
215
219
 
216
- specs = map_gems_to_specs(updated_gems)
220
+ specs = map_gems_to_specs(@updated_gems)
217
221
  prerelease, released = specs.partition { |s| s.version.prerelease? }
218
222
 
219
223
  ::Gem::Specification.dirs = []
@@ -292,6 +296,17 @@ module Gemirro
292
296
  dst_name,
293
297
  verbose: verbose,
294
298
  force: true)
299
+ cache.flush_key(File.basename(dst_name))
300
+ end
301
+
302
+ ##
303
+ # Cache class to store marshal and data into files
304
+ #
305
+ # @return [Gemirro::Cache]
306
+ #
307
+ def cache
308
+ @cache ||= Gemirro::Cache
309
+ .new(File.join(Gemirro.configuration.destination, '.cache'))
295
310
  end
296
311
 
297
312
  def verbose
@@ -12,7 +12,17 @@ module Gemirro
12
12
  # @return [Gemirro::GemsFetcher]
13
13
  #
14
14
  class Server < Sinatra::Base
15
+ # rubocop:disable Metrics/LineLength
16
+ URI_REGEXP = /^(.*)-(\d+(?:\.\d+){1,4}.*?)(?:-x86-(?:(?:mswin|mingw)(?:32|64)).*?)?\.(gem(?:spec\.rz)?)$/
17
+ GEMSPEC_TYPE = 'gemspec.rz'
18
+ GEM_TYPE = 'gem'
19
+ # rubocop:enable Metrics/LineLength
20
+
15
21
  attr_accessor :versions_fetcher, :gems_fetcher
22
+ attr_reader(:gems_orig_collection,
23
+ :gems_source_collection,
24
+ :stored_gems,
25
+ :cache)
16
26
 
17
27
  # rubocop:disable Metrics/LineLength
18
28
  access_logger = Logger.new(Gemirro.configuration.server.access_log).tap do |logger|
@@ -120,6 +130,16 @@ module Gemirro
120
130
  send_file(resource)
121
131
  end
122
132
 
133
+ ##
134
+ # Cache class to store marshal and data into files
135
+ #
136
+ # @return [Gemirro::Cache]
137
+ #
138
+ def cache
139
+ @cache ||= Gemirro::Cache
140
+ .new(File.join(configuration.destination, '.cache'))
141
+ end
142
+
123
143
  ##
124
144
  # Try to fetch gem and download its if it's possible, and
125
145
  # build and install indicies.
@@ -129,22 +149,19 @@ module Gemirro
129
149
  #
130
150
  def fetch_gem(resource)
131
151
  name = File.basename(resource)
132
- # rubocop:disable Metrics/LineLength
133
- regexp = /^(.*)-(\d+(?:\.\d+){2,4}.*?)(?:-x86-(?:(?:mswin|mingw)(?:32|64)).*?)?\.(gem(?:spec\.rz)?)$/
134
- # rubocop:enable Metrics/LineLength
135
- result = name.match(regexp)
152
+ result = name.match(URI_REGEXP)
136
153
  return unless result
137
154
 
138
155
  gem_name, gem_version, gem_type = result.captures
139
156
  return unless gem_name && gem_version
140
157
 
141
158
  begin
142
- gem = Gemirro::Gem.new(gem_name, gem_version)
143
- gem.gemspec = true if gem_type == 'gemspec.rz'
159
+ gem = stored_gem(gem_name, gem_version)
160
+ gem.gemspec = true if gem_type == GEMSPEC_TYPE
144
161
 
145
162
  # rubocop:disable Metrics/LineLength
146
- return if gems_fetcher.gem_exists?(gem.filename(gem_version)) && gem_type == 'gem'
147
- return if gems_fetcher.gemspec_exists?(gem.gemspec_filename(gem_version)) && gem_type == 'gemspec.rz'
163
+ return if gems_fetcher.gem_exists?(gem.filename(gem_version)) && gem_type == GEM_TYPE
164
+ return if gems_fetcher.gemspec_exists?(gem.gemspec_filename(gem_version)) && gem_type == GEMSPEC_TYPE
148
165
  # rubocop:enable Metrics/LineLength
149
166
 
150
167
  logger.info("Try to download #{gem_name} with version #{gem_version}")
@@ -164,12 +181,15 @@ module Gemirro
164
181
  # @return [Indexer]
165
182
  #
166
183
  def update_indexes
167
- indexer = Gemirro::Indexer.new(configuration.destination)
184
+ indexer = Gemirro::Indexer.new(configuration.destination)
168
185
  indexer.only_origin = true
169
186
  indexer.ui = ::Gem::SilentUI.new
170
187
 
171
188
  configuration.logger.info('Generating indexes')
172
189
  indexer.update_index
190
+ indexer.updated_gems.peach do |gem|
191
+ cache.flush_key(gem.name)
192
+ end
173
193
  rescue SystemExit => e
174
194
  configuration.logger.info(e.message)
175
195
  end
@@ -221,15 +241,23 @@ module Gemirro
221
241
  # @return [Gemirro::GemVersionCollection]
222
242
  #
223
243
  def gems_collection(orig = true)
224
- gems = specs_files_paths(orig).map do |specs_file_path|
225
- if File.exist?(specs_file_path)
226
- Marshal.load(Zlib::GzipReader.open(specs_file_path).read)
227
- else
228
- []
244
+ return @gems_orig_collection if orig && !@gems_orig_collection.nil?
245
+ return @gems_source_collection if !orig && !@gems_source_collection.nil?
246
+
247
+ gems = []
248
+ specs_files_paths(orig).pmap do |specs_file_path|
249
+ cache.cache(File.basename(specs_file_path)) do
250
+ # rubocop:disable Metrics/LineLength
251
+ gems.concat(Marshal.load(Zlib::GzipReader.open(specs_file_path).read)) if File.exist?(specs_file_path)
252
+ # rubocop:enable Metrics/LineLength
229
253
  end
230
- end.inject(:|)
254
+ end
255
+
256
+ collection = GemVersionCollection.new(gems)
257
+ @gems_source_collection = collection unless orig
258
+ @gems_orig_collection = collection if orig
231
259
 
232
- GemVersionCollection.new(gems)
260
+ collection
233
261
  end
234
262
 
235
263
  ##
@@ -238,9 +266,11 @@ module Gemirro
238
266
  # @return [Array]
239
267
  #
240
268
  def query_gems_list
241
- gems = query_gems.flat_map do |query_gem|
269
+ gems_collection(false) # load collection
270
+ gems = query_gems.pmap do |query_gem|
242
271
  gem_dependencies(query_gem)
243
272
  end
273
+ gems.flatten!
244
274
  gems = gems.select do |g|
245
275
  !g.empty?
246
276
  end
@@ -254,33 +284,35 @@ module Gemirro
254
284
  # @return [Array]
255
285
  #
256
286
  def gem_dependencies(gem_name)
257
- gems = gems_collection(false)
258
- gem_collection = gems.find_by_name(gem_name)
259
- return '' if gem_collection.nil?
287
+ cache.cache(gem_name) do
288
+ gems = gems_collection(false)
289
+ gem_collection = gems.find_by_name(gem_name)
260
290
 
261
- gem_collection = gem_collection.map do |gem|
262
- [gem, spec_for(gem.name, gem.number, gem.platform)]
263
- end
291
+ return '' if gem_collection.nil?
264
292
 
265
- gem_collection.reject! do |_, spec|
266
- spec.nil?
267
- end
268
-
269
- gem_collection.map do |gem, spec|
270
- dependencies = spec.dependencies.select do |d|
271
- d.type == :runtime
293
+ gem_collection = gem_collection.pmap do |gem|
294
+ [gem, spec_for(gem.name, gem.number, gem.platform)]
272
295
  end
273
-
274
- dependencies.map! do |d|
275
- [d.name.is_a?(Array) ? d.name.first : d.name, d.requirement.to_s]
296
+ gem_collection.reject! do |_, spec|
297
+ spec.nil?
276
298
  end
277
299
 
278
- {
279
- name: gem.name,
280
- number: gem.number,
281
- platform: gem.platform,
282
- dependencies: dependencies
283
- }
300
+ gem_collection.pmap do |gem, spec|
301
+ dependencies = spec.dependencies.select do |d|
302
+ d.type == :runtime
303
+ end
304
+
305
+ dependencies = dependencies.pmap do |d|
306
+ [d.name.is_a?(Array) ? d.name.first : d.name, d.requirement.to_s]
307
+ end
308
+
309
+ {
310
+ name: gem.name,
311
+ number: gem.number,
312
+ platform: gem.platform,
313
+ dependencies: dependencies
314
+ }
315
+ end
284
316
  end
285
317
  end
286
318
 
@@ -292,7 +324,7 @@ module Gemirro
292
324
  #
293
325
  def specs_files_paths(orig = true)
294
326
  marshal_version = Gemirro::Configuration.marshal_version
295
- specs_file_types.map do |specs_file_type|
327
+ specs_file_types.pmap do |specs_file_type|
296
328
  File.join(settings.public_folder,
297
329
  [specs_file_type,
298
330
  marshal_version,
@@ -310,6 +342,23 @@ module Gemirro
310
342
  [:specs, :prerelease_specs]
311
343
  end
312
344
 
345
+ ##
346
+ # Try to cache gem classes
347
+ #
348
+ # @param [String] gem_name Gem name
349
+ # @return [Gem]
350
+ #
351
+ def stored_gem(gem_name, gem_version, platform = 'ruby')
352
+ @stored_gems ||= {}
353
+ # rubocop:disable Metrics/LineLength
354
+ @stored_gems[gem_name] = {} unless @stored_gems.key?(gem_name)
355
+ @stored_gems[gem_name][gem_version] = {} unless @stored_gems[gem_name].key?(gem_version)
356
+ @stored_gems[gem_name][gem_version][platform] ||= Gem.new(gem_name, gem_version, platform) unless @stored_gems[gem_name][gem_version].key?(platform)
357
+ # rubocop:enable Metrics/LineLength
358
+
359
+ @stored_gems[gem_name][gem_version][platform]
360
+ end
361
+
313
362
  helpers do
314
363
  ##
315
364
  # Return gem specification from gemname and version
@@ -319,13 +368,12 @@ module Gemirro
319
368
  # @return [::Gem::Specification]
320
369
  #
321
370
  def spec_for(gemname, version, platform = 'ruby')
322
- gem = Gem.new(gemname, version.to_s, platform)
371
+ gem = stored_gem(gemname, version.to_s, platform)
323
372
  gemspec_path = File.join('quick',
324
373
  Gemirro::Configuration.marshal_identifier,
325
374
  gem.gemspec_filename)
326
375
  spec_file = File.join(settings.public_folder,
327
376
  gemspec_path)
328
-
329
377
  fetch_gem(gemspec_path) unless File.exist?(spec_file)
330
378
  File.open(spec_file, 'r') do |uz_file|
331
379
  uz_file.binmode
@@ -25,12 +25,24 @@ module Gemirro
25
25
  @gems = gems
26
26
  end
27
27
 
28
+ ##
29
+ # @see Gemirro::Configuration#logger
30
+ # @return [Logger]
31
+ #
32
+ def logger
33
+ Gemirro.configuration.logger
34
+ end
35
+
28
36
  ##
29
37
  # Fetches a list of all the available Gems and their versions.
30
38
  #
31
39
  # @return [String]
32
40
  #
33
41
  def fetch_versions
42
+ logger.info(
43
+ "Fetching #{Configuration.versions_file} on #{@name} (#{@host})"
44
+ )
45
+
34
46
  Http.get(host + '/' + Configuration.versions_file).body
35
47
  end
36
48
 
@@ -40,6 +52,10 @@ module Gemirro
40
52
  # @return [String]
41
53
  #
42
54
  def fetch_prerelease_versions
55
+ logger.info(
56
+ "Fetching #{Configuration.prerelease_versions_file}" \
57
+ " on #{@name} (#{@host})"
58
+ )
43
59
  Http.get(host + '/' + Configuration.prerelease_versions_file).body
44
60
  end
45
61
 
@@ -51,6 +67,9 @@ module Gemirro
51
67
  # @return [String]
52
68
  #
53
69
  def fetch_gem(name, version)
70
+ logger.info(
71
+ "Fetching gem #{name}, #{version} on #{@name} (#{@host})"
72
+ )
54
73
  Http.get(host + "/gems/#{name}-#{version}.gem").body
55
74
  end
56
75
 
@@ -62,6 +81,9 @@ module Gemirro
62
81
  # @return [String]
63
82
  #
64
83
  def fetch_gemspec(name, version)
84
+ logger.info(
85
+ "Fetching gemspec #{name}, #{version} on #{@name} (#{@host})"
86
+ )
65
87
  marshal = Gemirro::Configuration.marshal_identifier
66
88
  Http.get(host + "/quick/#{marshal}/#{name}-#{version}.gemspec.rz").body
67
89
  end
@@ -1,5 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  # Gemirro Version
3
3
  module Gemirro
4
- VERSION = '0.11.0'
4
+ VERSION = '0.12.0'
5
5
  end
@@ -21,11 +21,25 @@ module Gemirro
21
21
  # @return [Gemirro::VersionsFile]
22
22
  #
23
23
  def fetch
24
- Gemirro.configuration.logger.info(
25
- "Updating #{source.name} (#{source.host})"
26
- )
24
+ VersionsFile.load(read_file(Configuration.versions_file),
25
+ read_file(Configuration.prerelease_versions_file, true))
26
+ end
27
+
28
+ ##
29
+ # Read file if exists otherwise download its from source
30
+ #
31
+ # @param [String] file name
32
+ # @param [TrueClass|FalseClass] prerelease Is prerelease or not
33
+ #
34
+ def read_file(file, prerelease = false)
35
+ destination = Gemirro.configuration.destination
36
+ file_dst = File.join(destination, file)
37
+ unless File.exist?(file_dst)
38
+ File.write(file_dst, @source.fetch_versions) unless prerelease
39
+ File.write(file_dst, @source.fetch_prerelease_versions) if prerelease
40
+ end
27
41
 
28
- VersionsFile.load(source.fetch_versions, source.fetch_prerelease_versions)
42
+ File.read(file_dst)
29
43
  end
30
44
  end
31
45
  end
data/lib/gemirro.rb CHANGED
@@ -11,6 +11,7 @@ require 'httpclient'
11
11
  require 'logger'
12
12
  require 'stringio'
13
13
  require 'json'
14
+ require 'pmap'
14
15
  require 'tempfile'
15
16
 
16
17
  unless $LOAD_PATH.include?(File.expand_path('../', __FILE__))
@@ -19,6 +20,7 @@ end
19
20
 
20
21
  require 'gemirro/version'
21
22
  require 'gemirro/configuration'
23
+ require 'gemirro/cache'
22
24
  require 'gemirro/gem'
23
25
  require 'gemirro/gem_version'
24
26
  require 'gemirro/gem_version_collection'
@@ -109,7 +109,8 @@ module Gemirro
109
109
  it 'should retrieve versions for specific gem' do
110
110
  gem = Gem.new('gemirro', '0.0.2')
111
111
  allow(@versions_file).to receive(:versions_for)
112
- .once.with('gemirro').and_return(['0.0.1', '0.0.2'])
112
+ .once.with('gemirro').and_return([::Gem::Version.new('0.0.1'),
113
+ ::Gem::Version.new('0.0.2')])
113
114
  expect(@fetcher.versions_for(gem)).to eq([::Gem::Version.new('0.0.2')])
114
115
  end
115
116
 
@@ -52,7 +52,8 @@ module Gemirro
52
52
  '/tmp/gem_generate_index/specs.4.8.gz',
53
53
  '/tmp/gem_generate_index/something.4.8.gz'
54
54
  ]
55
-
55
+ allow(FileUtils).to receive(:mkdir_p).and_return(true)
56
+ allow(FileUtils).to receive(:rm_f).and_return(true)
56
57
  allow(FileUtils).to receive(:mkdir_p)
57
58
  .once.with('/tmp/test/quick', verbose: true)
58
59
  allow(FileUtils).to receive(:rm_rf)
@@ -1,6 +1,8 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  require 'rack/test'
3
3
  require 'json'
4
+ require 'pmap'
5
+ require 'gemirro/cache'
4
6
  require 'gemirro/mirror_directory'
5
7
  require 'gemirro/mirror_file'
6
8
  require 'gemirro/gem_version_collection'
@@ -8,6 +8,7 @@ module Gemirro
8
8
  describe 'Source' do
9
9
  before(:each) do
10
10
  @source = Source.new('RubyGems', 'https://rubygems.org')
11
+ allow(@source.logger).to receive(:info)
11
12
  end
12
13
 
13
14
  it 'should be initialized' do
@@ -25,6 +26,15 @@ module Gemirro
25
26
  expect(@source.fetch_versions).to be_truthy
26
27
  end
27
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
+
28
38
  it 'should fetch gem' do
29
39
  Struct.new('FetchGem', :body)
30
40
  result = Struct::FetchGem.new(true)
@@ -5,6 +5,8 @@ require 'gemirro/versions_fetcher'
5
5
  # VersionsFetcher tests
6
6
  module Gemirro
7
7
  describe 'VersionsFetcher' do
8
+ include FakeFS::SpecHelpers
9
+
8
10
  before(:each) do
9
11
  @source = Source.new('RubyGems', 'https://rubygems.org')
10
12
  @fetcher = VersionsFetcher.new(@source)
@@ -15,11 +17,11 @@ module Gemirro
15
17
  end
16
18
 
17
19
  it 'should fetch versions' do
18
- allow(Gemirro.configuration.logger).to receive(:info)
19
- .once.with("Updating #{@source.name} (#{@source.host})")
20
20
  allow(@source).to receive(:fetch_versions).once.and_return([])
21
21
  allow(@source).to receive(:fetch_prerelease_versions).once.and_return([])
22
- allow(VersionsFile).to receive(:load).with([], [])
22
+ allow(VersionsFile).to receive(:load).with('nothing', 'nothing')
23
+ allow(File).to receive(:write).twice
24
+ allow(File).to receive(:read).twice.and_return('nothing')
23
25
  expect(@fetcher.fetch).to be_nil
24
26
  end
25
27
  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: 0.11.0
4
+ version: 0.12.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: 2015-07-31 00:00:00.000000000 Z
11
+ date: 2015-11-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: slop
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: '1.6'
97
+ - !ruby/object:Gem::Dependency
98
+ name: pmap
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.0'
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: rake
99
113
  requirement: !ruby/object:Gem::Requirement
@@ -196,6 +210,7 @@ files:
196
210
  - bin/gemirro
197
211
  - gemirro.gemspec
198
212
  - lib/gemirro.rb
213
+ - lib/gemirro/cache.rb
199
214
  - lib/gemirro/cli.rb
200
215
  - lib/gemirro/cli/index.rb
201
216
  - lib/gemirro/cli/init.rb