geminabox 0.8.0 → 0.9.0

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

Potentially problematic release.


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

@@ -15,7 +15,7 @@ class Geminabox < Sinatra::Base
15
15
  set :public_folder, File.join(File.dirname(__FILE__), *%w[.. public])
16
16
  set :data, File.join(File.dirname(__FILE__), *%w[.. data])
17
17
  set :build_legacy, false
18
- set :incremental_updates, false
18
+ set :incremental_updates, true
19
19
  set :views, File.join(File.dirname(__FILE__), *%w[.. views])
20
20
  set :allow_replace, false
21
21
  set :gem_permissions, 0644
@@ -52,11 +52,10 @@ class Geminabox < Sinatra::Base
52
52
  erb :atom, :layout => false
53
53
  end
54
54
 
55
- get '/api/v1/dependencies' do
56
- query_gems = params[:gems].split(',').sort
57
- cache_key = query_gems.join(',')
58
- disk_cache.cache(cache_key) do
59
- deps = load_gems.select {|gem| query_gems.include?(gem.name) }.map do |gem|
55
+ # Return a list of versions of gem 'gem_name' with the dependencies of each version.
56
+ def gem_dependencies(gem_name)
57
+ dependency_cache.marshal_cache(gem_name) do
58
+ load_gems.select {|gem| gem_name == gem.name }.map do |gem|
60
59
  spec = spec_for(gem.name, gem.number)
61
60
  {
62
61
  :name => gem.name,
@@ -65,10 +64,15 @@ class Geminabox < Sinatra::Base
65
64
  :dependencies => spec.dependencies.select {|dep| dep.type == :runtime}.map {|dep| [dep.name, dep.requirement.to_s] }
66
65
  }
67
66
  end
68
- Marshal.dump(deps)
69
67
  end
70
68
  end
71
69
 
70
+ get '/api/v1/dependencies' do
71
+ query_gems = params[:gems].split(',')
72
+ deps = query_gems.each_with_object([]) {|query_gem, memo| memo.concat gem_dependencies(query_gem) }
73
+ Marshal.dump(deps)
74
+ end
75
+
72
76
  get '/upload' do
73
77
  erb :upload
74
78
  end
@@ -165,16 +169,20 @@ HTML
165
169
  force_rebuild = true unless settings.incremental_updates
166
170
  if force_rebuild
167
171
  indexer.generate_index
172
+ dependency_cache.flush
168
173
  else
169
174
  begin
175
+ require 'geminabox/indexer'
176
+ updated_gemspecs = Geminabox::Indexer.updated_gemspecs(indexer)
177
+ Geminabox::Indexer.patch_rubygems_update_index_pre_1_8_25(indexer)
170
178
  indexer.update_index
179
+ updated_gemspecs.each { |gem| dependency_cache.flush_key(gem.name) }
171
180
  rescue => e
172
181
  puts "#{e.class}:#{e.message}"
173
182
  puts e.backtrace.join("\n")
174
183
  reindex(:force_rebuild)
175
184
  end
176
185
  end
177
- disk_cache.flush
178
186
  end
179
187
 
180
188
  def indexer
@@ -185,8 +193,8 @@ HTML
185
193
  File.expand_path(File.join(settings.data, *request.path_info))
186
194
  end
187
195
 
188
- def disk_cache
189
- @disk_cache = Geminabox::DiskCache.new(File.join(settings.data, "_cache"))
196
+ def dependency_cache
197
+ @dependency_cache ||= Geminabox::DiskCache.new(File.join(settings.data, "_cache"))
190
198
  end
191
199
 
192
200
  def all_gems
@@ -8,27 +8,24 @@ class Geminabox::DiskCache
8
8
  ensure_dir_exists!
9
9
  end
10
10
 
11
+ def flush_key(key)
12
+ path = path(key_hash(key))
13
+ FileUtils.rm_f(path)
14
+ end
15
+
11
16
  def flush
12
17
  FileUtils.rm_rf(root_path)
13
18
  ensure_dir_exists!
14
19
  end
15
20
 
16
21
  def cache(key)
17
- key = Digest::MD5.hexdigest(key)
18
- read(key) || write(key, yield)
19
- end
20
-
21
- def read(key)
22
- path = File.join(root_path, key)
23
- File.read(path) if File.exists?(path)
22
+ key_hash = key_hash(key)
23
+ read(key_hash) || write(key_hash, yield)
24
24
  end
25
25
 
26
- def write(key, value)
27
- path = File.join(root_path, key)
28
- File.open(path, 'wb'){|f|
29
- f << value
30
- }
31
- value
26
+ def marshal_cache(key)
27
+ key_hash = key_hash(key)
28
+ marshal_read(key_hash) || marshal_write(key_hash, yield)
32
29
  end
33
30
 
34
31
  protected
@@ -36,4 +33,40 @@ protected
36
33
  def ensure_dir_exists!
37
34
  FileUtils.mkdir_p(root_path)
38
35
  end
36
+
37
+ def key_hash(key)
38
+ Digest::MD5.hexdigest(key)
39
+ end
40
+
41
+ def path(key_hash)
42
+ File.join(root_path, key_hash)
43
+ end
44
+
45
+ def read(key_hash)
46
+ read_int(key_hash) { |path| File.read(path) }
47
+ end
48
+
49
+ def marshal_read(key_hash)
50
+ read_int(key_hash) { |path| Marshal.load(File.open(path)) }
51
+ end
52
+
53
+ def read_int(key_hash)
54
+ path = path(key_hash)
55
+ yield(path) if File.exists?(path)
56
+ end
57
+
58
+ def write(key_hash, value)
59
+ write_int(key_hash) { |f| f << value }
60
+ value
61
+ end
62
+
63
+ def marshal_write(key_hash, value)
64
+ write_int(key_hash) { |f| Marshal.dump(value, f) }
65
+ value
66
+ end
67
+
68
+ def write_int(key_hash)
69
+ File.open(path(key_hash), 'wb') { |f| yield(f) }
70
+ end
71
+
39
72
  end
@@ -0,0 +1,46 @@
1
+
2
+ # This module addresses Geminabox issue
3
+ # https://github.com/cwninja/geminabox/issues/70
4
+ #
5
+ # The underlying problem is rubygems issue
6
+ # https://github.com/rubygems/rubygems/issues/232, fixed by
7
+ # https://github.com/rubygems/rubygems/pull/364
8
+ #
9
+ # This library (and its call) should be deleted once that pull request is resolved.
10
+
11
+ require 'geminabox'
12
+ require 'rubygems/indexer'
13
+
14
+ module Geminabox::Indexer
15
+ def self.germane?
16
+ gem_version = Gem::Version.new(Gem::VERSION)
17
+ v1_8 = Gem::Version.new('1.8')
18
+ v1_8_25 = Gem::Version.new('1.8.25')
19
+
20
+ (gem_version >= v1_8) && (gem_version < v1_8_25)
21
+ end
22
+
23
+ def self.updated_gemspecs(indexer)
24
+ specs_mtime = File.stat(indexer.dest_specs_index).mtime
25
+ newest_mtime = Time.at 0
26
+
27
+ updated_gems = indexer.gem_file_list.select do |gem|
28
+ gem_mtime = File.stat(gem).mtime
29
+ newest_mtime = gem_mtime if gem_mtime > newest_mtime
30
+ gem_mtime >= specs_mtime
31
+ end
32
+
33
+ indexer.map_gems_to_specs updated_gems
34
+ end
35
+
36
+ def self.patch_rubygems_update_index_pre_1_8_25(indexer)
37
+ if germane?
38
+ specs = updated_gemspecs(indexer)
39
+
40
+ unless specs.empty?
41
+ Gem::Specification.dirs = []
42
+ Gem::Specification.add_specs(*specs)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -1 +1 @@
1
- GeminaboxVersion = '0.8.0' unless defined? GeminaboxVersion
1
+ GeminaboxVersion = '0.9.0' unless defined? GeminaboxVersion
metadata CHANGED
@@ -1,115 +1,160 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geminabox
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
5
4
  prerelease:
5
+ version: 0.9.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Tom Lea
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-26 00:00:00.000000000 Z
12
+ date: 2013-01-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: sinatra
16
- requirement: &70361993784940 !ruby/object:Gem::Requirement
15
+ type: :runtime
16
+ version_requirements: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
20
20
  - !ruby/object:Gem::Version
21
21
  version: '0'
22
- type: :runtime
22
+ name: sinatra
23
23
  prerelease: false
24
- version_requirements: *70361993784940
25
- - !ruby/object:Gem::Dependency
26
- name: builder
27
- requirement: &70361993784400 !ruby/object:Gem::Requirement
24
+ requirement: !ruby/object:Gem::Requirement
28
25
  none: false
29
26
  requirements:
30
27
  - - ! '>='
31
28
  - !ruby/object:Gem::Version
32
29
  version: '0'
30
+ - !ruby/object:Gem::Dependency
33
31
  type: :runtime
32
+ version_requirements: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ name: builder
34
39
  prerelease: false
35
- version_requirements: *70361993784400
36
- - !ruby/object:Gem::Dependency
37
- name: httpclient
38
- requirement: &70361993783860 !ruby/object:Gem::Requirement
40
+ requirement: !ruby/object:Gem::Requirement
39
41
  none: false
40
42
  requirements:
41
43
  - - ! '>='
42
44
  - !ruby/object:Gem::Version
43
45
  version: '0'
46
+ - !ruby/object:Gem::Dependency
44
47
  type: :runtime
48
+ version_requirements: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: 2.2.7
54
+ name: httpclient
45
55
  prerelease: false
46
- version_requirements: *70361993783860
56
+ requirement: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 2.2.7
47
62
  - !ruby/object:Gem::Dependency
48
- name: rake
49
- requirement: &70361993783320 !ruby/object:Gem::Requirement
63
+ type: :development
64
+ version_requirements: !ruby/object:Gem::Requirement
50
65
  none: false
51
66
  requirements:
52
67
  - - ! '>='
53
68
  - !ruby/object:Gem::Version
54
69
  version: '0'
55
- type: :development
70
+ name: rake
56
71
  prerelease: false
57
- version_requirements: *70361993783320
58
- - !ruby/object:Gem::Dependency
59
- name: rack-test
60
- requirement: &70361993782680 !ruby/object:Gem::Requirement
72
+ requirement: !ruby/object:Gem::Requirement
61
73
  none: false
62
74
  requirements:
63
75
  - - ! '>='
64
76
  - !ruby/object:Gem::Version
65
77
  version: '0'
78
+ - !ruby/object:Gem::Dependency
66
79
  type: :development
80
+ version_requirements: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ name: rack-test
67
87
  prerelease: false
68
- version_requirements: *70361993782680
69
- - !ruby/object:Gem::Dependency
70
- name: minitest
71
- requirement: &70361993781820 !ruby/object:Gem::Requirement
88
+ requirement: !ruby/object:Gem::Requirement
72
89
  none: false
73
90
  requirements:
74
91
  - - ! '>='
75
92
  - !ruby/object:Gem::Version
76
93
  version: '0'
94
+ - !ruby/object:Gem::Dependency
77
95
  type: :development
96
+ version_requirements: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ name: minitest
78
103
  prerelease: false
79
- version_requirements: *70361993781820
80
- - !ruby/object:Gem::Dependency
81
- name: capybara
82
- requirement: &70361993797280 !ruby/object:Gem::Requirement
104
+ requirement: !ruby/object:Gem::Requirement
83
105
  none: false
84
106
  requirements:
85
107
  - - ! '>='
86
108
  - !ruby/object:Gem::Version
87
109
  version: '0'
110
+ - !ruby/object:Gem::Dependency
88
111
  type: :development
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ name: capybara
89
119
  prerelease: false
90
- version_requirements: *70361993797280
91
- - !ruby/object:Gem::Dependency
92
- name: capybara-mechanize
93
- requirement: &70361993796080 !ruby/object:Gem::Requirement
120
+ requirement: !ruby/object:Gem::Requirement
94
121
  none: false
95
122
  requirements:
96
123
  - - ! '>='
97
124
  - !ruby/object:Gem::Version
98
125
  version: '0'
126
+ - !ruby/object:Gem::Dependency
99
127
  type: :development
128
+ version_requirements: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ name: capybara-mechanize
100
135
  prerelease: false
101
- version_requirements: *70361993796080
102
- - !ruby/object:Gem::Dependency
103
- name: pry
104
- requirement: &70361993795380 !ruby/object:Gem::Requirement
136
+ requirement: !ruby/object:Gem::Requirement
105
137
  none: false
106
138
  requirements:
107
139
  - - ! '>='
108
140
  - !ruby/object:Gem::Version
109
141
  version: '0'
142
+ - !ruby/object:Gem::Dependency
110
143
  type: :development
144
+ version_requirements: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ name: pry
111
151
  prerelease: false
112
- version_requirements: *70361993795380
152
+ requirement: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
113
158
  description: A sinatra based gem hosting app, with client side gem push style functionality.
114
159
  email: contrib@tomlea.co.uk
115
160
  executables: []
@@ -121,6 +166,7 @@ files:
121
166
  - lib/geminabox/disk_cache.rb
122
167
  - lib/geminabox/gem_version.rb
123
168
  - lib/geminabox/gem_version_collection.rb
169
+ - lib/geminabox/indexer.rb
124
170
  - lib/geminabox/version.rb
125
171
  - lib/geminabox.rb
126
172
  - lib/geminabox_client.rb
@@ -149,22 +195,22 @@ required_ruby_version: !ruby/object:Gem::Requirement
149
195
  requirements:
150
196
  - - ! '>='
151
197
  - !ruby/object:Gem::Version
152
- version: '0'
153
198
  segments:
154
199
  - 0
155
- hash: -1477264842366552590
200
+ hash: 332321015016906523
201
+ version: '0'
156
202
  required_rubygems_version: !ruby/object:Gem::Requirement
157
203
  none: false
158
204
  requirements:
159
205
  - - ! '>='
160
206
  - !ruby/object:Gem::Version
161
- version: '0'
162
207
  segments:
163
208
  - 0
164
- hash: -1477264842366552590
209
+ hash: 332321015016906523
210
+ version: '0'
165
211
  requirements: []
166
212
  rubyforge_project:
167
- rubygems_version: 1.8.15
213
+ rubygems_version: 1.8.24
168
214
  signing_key:
169
215
  specification_version: 3
170
216
  summary: Really simple rubygem hosting