geminabox 1.1.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c58b87ab694d0e78e224fd5faf56aa4b7676c88f2c10da711980765fbb8bd1bc
4
- data.tar.gz: ca6355cf693daf3a94826f7e9ab29a9f73714077d78dac0c298352e280fbbaee
3
+ metadata.gz: e6202425f155e5ef57fbf61150ddfb36175feaa2fb27f802de8d56fc3c3716af
4
+ data.tar.gz: 3cb74860670ac4a0d53df6fa0fbafec173f7441b0675abb2263f525baf34cfbd
5
5
  SHA512:
6
- metadata.gz: 5cc317ab13ac74784a371820b55bb6625c3d2af1aa3b04a7efcedeb1484ef08c29daa690975079776add41b374a2bb9d9703dfb73ad6930ffdf539d53eee97d9
7
- data.tar.gz: 90da6706ea509db2a15c4aafe267334120954e42a5d5c06a918c4bb5e4a9a5626257ccbeb6b39132efb89cb8a45363794854581b2646831e7906159dcf870170
6
+ metadata.gz: 38234e325f6c2ecf00138cd16b65dbe42bf5724b83c06f1eff3e61d42384ee3330fb57e8c403c2f26a17a0b02b961852970d31d634859c74a4a781b6cdf0f956
7
+ data.tar.gz: 52c9532b79d0ed5fc9c7a5c0d16e75dacd3befb27a85d7f333901380671814908e7b7fdc3eaa1612d8ee6e79089eed290b43427d94a90809e8e1ae470e3709b2
data/README.md CHANGED
@@ -122,6 +122,10 @@ You can also use the gem plugin:
122
122
 
123
123
  gem inabox pkg/my-awesome-gem-1.0.gem
124
124
 
125
+ And since version 1.2.0, Geminabox supports the standard gemcutter yank API:
126
+
127
+ gem yank my-awesome-gem -v 1.0 --host HOST
128
+
125
129
  Configure Gem in a box (interactive prompt to specify where to upload to):
126
130
 
127
131
  gem inabox -c
data/lib/geminabox.rb CHANGED
@@ -46,6 +46,7 @@ module Geminabox
46
46
  :gem_permissions,
47
47
  :allow_delete,
48
48
  :rubygems_proxy,
49
+ :rubygems_proxy_merge_strategy,
49
50
  :http_adapter,
50
51
  :lockfile,
51
52
  :retry_interval,
@@ -73,23 +74,24 @@ module Geminabox
73
74
  end
74
75
 
75
76
  set_defaults(
76
- data: File.join(File.dirname(__FILE__), *%w[.. data]),
77
- public_folder: File.join(File.dirname(__FILE__), *%w[.. public]),
78
- build_legacy: false,
79
- incremental_updates: true,
80
- views: File.join(File.dirname(__FILE__), *%w[.. views]),
81
- allow_replace: false,
82
- gem_permissions: 0644,
83
- rubygems_proxy: (ENV['RUBYGEMS_PROXY'] == 'true'),
84
- allow_delete: true,
85
- http_adapter: HttpClientAdapter.new,
86
- lockfile: '/tmp/geminabox.lockfile',
87
- retry_interval: 60,
88
- allow_remote_failure: false,
89
- ruby_gems_url: 'https://rubygems.org/',
90
- bundler_ruby_gems_url: 'https://bundler.rubygems.org/',
91
- allow_upload: true,
92
- on_gem_received: nil
77
+ data: File.join(File.dirname(__FILE__), *%w[.. data]),
78
+ public_folder: File.join(File.dirname(__FILE__), *%w[.. public]),
79
+ build_legacy: false,
80
+ incremental_updates: true,
81
+ views: File.join(File.dirname(__FILE__), *%w[.. views]),
82
+ allow_replace: false,
83
+ gem_permissions: 0644,
84
+ rubygems_proxy: (ENV['RUBYGEMS_PROXY'] == 'true'),
85
+ rubygems_proxy_merge_strategy: ENV.fetch('RUBYGEMS_PROXY_MERGE_STRATEGY') { :local_gems_take_precedence_over_remote_gems }.to_sym,
86
+ allow_delete: true,
87
+ http_adapter: HttpClientAdapter.new,
88
+ lockfile: '/tmp/geminabox.lockfile',
89
+ retry_interval: 60,
90
+ allow_remote_failure: false,
91
+ ruby_gems_url: 'https://rubygems.org/',
92
+ bundler_ruby_gems_url: 'https://bundler.rubygems.org/',
93
+ allow_upload: true,
94
+ on_gem_received: nil
93
95
  )
94
96
 
95
97
  end
@@ -1,23 +1,38 @@
1
- module Geminabox
2
- class GemListMerge
3
- attr_accessor :list
4
-
5
- IGNORE_DEPENDENCIES = 0..-2
1
+ require "set"
6
2
 
7
- def self.from(*lists)
8
- lists.map{|list| new(list)}.inject(:merge)
3
+ module Geminabox
4
+ module GemListMerge
5
+ def self.merge(local_gem_list, remote_gem_list, strategy:)
6
+ strategy_for(strategy).merge(local_gem_list, remote_gem_list)
9
7
  end
10
8
 
11
- def initialize(list)
12
- @list = list
9
+ def self.strategy_for(strategy)
10
+ case strategy
11
+ when :local_gems_take_precedence_over_remote_gems
12
+ LocalGemsTakePrecedenceOverRemoteGems
13
+ when :combine_local_and_remote_gem_versions
14
+ CombineLocalAndRemoteGemVersions
15
+ else
16
+ raise ArgumentError, "Merge strategy must be :local_gems_take_precedence_over_remote_gems (default) or :merge_local_and_remote_gem_versions"
17
+ end
13
18
  end
14
19
 
15
- def merge(other)
16
- merged = (list + other.list)
17
- merged.uniq! {|val| val.values[IGNORE_DEPENDENCIES] }
18
- merged.sort_by! {|x| x.values[IGNORE_DEPENDENCIES] }
19
- merged
20
+ module LocalGemsTakePrecedenceOverRemoteGems
21
+ def self.merge(local_gem_list, remote_gem_list)
22
+ names = Set.new(local_gem_list.map { |gem| gem[:name] })
23
+ local_gem_list + remote_gem_list.reject { |gem| names.include? gem[:name] }
24
+ end
20
25
  end
21
26
 
27
+ module CombineLocalAndRemoteGemVersions
28
+ IGNORE_DEPENDENCIES = 0..-2
29
+
30
+ def self.merge(local_gem_list, remote_gem_list)
31
+ merged = local_gem_list + remote_gem_list
32
+ merged.uniq! {|val| val.values[IGNORE_DEPENDENCIES] }
33
+ merged.sort_by! {|x| x.values[IGNORE_DEPENDENCIES] }
34
+ merged
35
+ end
36
+ end
22
37
  end
23
38
  end
@@ -1,5 +1,6 @@
1
1
  require 'tempfile'
2
2
  require 'fileutils'
3
+ require 'rubygems/util'
3
4
 
4
5
  module Geminabox
5
6
  module Proxy
@@ -65,11 +66,11 @@ module Geminabox
65
66
  end
66
67
 
67
68
  def unpackage(content)
68
- Marshal.load(Gem.gunzip(content))
69
+ Marshal.load(Gem::Util.gunzip(content))
69
70
  end
70
71
 
71
72
  def package(content)
72
- Gem.gzip(Marshal.dump(content))
73
+ Gem::Util.gzip(Marshal.dump(content))
73
74
  end
74
75
 
75
76
  def merge_text_content
@@ -1,4 +1,5 @@
1
1
  require 'reentrant_flock'
2
+ require 'rubygems/util'
2
3
 
3
4
  module Geminabox
4
5
 
@@ -130,6 +131,7 @@ module Geminabox
130
131
  get '/gems/:gemname' do
131
132
  gems = Hash[load_gems.by_name]
132
133
  @gem = gems[params[:gemname]]
134
+ @allow_delete = self.class.allow_delete?
133
135
  halt 404 unless @gem
134
136
  erb :gem
135
137
  end
@@ -147,6 +149,27 @@ module Geminabox
147
149
 
148
150
  end
149
151
 
152
+ delete '/api/v1/gems/yank' do
153
+ unless self.class.allow_delete?
154
+ error_response(403, 'Gem deletion is disabled')
155
+ end
156
+
157
+ halt 400 unless request.form_data?
158
+
159
+ serialize_update do
160
+ gems = load_gems.select { |gem| request['gem_name'] == gem.name and
161
+ request['version'] == gem.number.version }
162
+ halt 404, 'Gem not found' if gems.size == 0
163
+ gems.each do |gem|
164
+ gem_path = File.expand_path(File.join(Geminabox.data, 'gems',
165
+ "#{gem.gemfile_name}.gem"))
166
+ File.delete gem_path if File.exists? gem_path
167
+ end
168
+ self.class.reindex(:force_rebuild)
169
+ return 200, 'Yanked gem and reindexed'
170
+ end
171
+ end
172
+
150
173
  post '/upload' do
151
174
  unless self.class.allow_upload?
152
175
  error_response(403, 'Gem uploading is disabled')
@@ -243,7 +266,7 @@ HTML
243
266
  def all_gems_with_duplicates
244
267
  specs_files_paths.map do |specs_file_path|
245
268
  if File.exist?(specs_file_path)
246
- Marshal.load(Gem.gunzip(Gem.read_binary(specs_file_path)))
269
+ Marshal.load(Gem::Util.gunzip(Gem.read_binary(specs_file_path)))
247
270
  else
248
271
  []
249
272
  end
@@ -289,7 +312,7 @@ HTML
289
312
  end
290
313
 
291
314
  def combined_gem_list
292
- GemListMerge.from(local_gem_list, remote_gem_list)
315
+ GemListMerge.merge(local_gem_list, remote_gem_list, strategy: Geminabox.rubygems_proxy_merge_strategy)
293
316
  end
294
317
 
295
318
  helpers do
@@ -311,7 +334,7 @@ HTML
311
334
  spec_file = File.join(Geminabox.data, "quick", "Marshal.#{Gem.marshal_version}", "#{filename.join("-")}.gemspec.rz")
312
335
  File::open(spec_file, 'r') do |unzipped_spec_file|
313
336
  unzipped_spec_file.binmode
314
- Marshal.load(Gem.inflate(unzipped_spec_file.read))
337
+ Marshal.load(Gem::Util.inflate(unzipped_spec_file.read))
315
338
  end if File.exist? spec_file
316
339
  end
317
340
 
@@ -1,3 +1,3 @@
1
1
  module Geminabox
2
- VERSION = '1.1.0' unless defined? VERSION
2
+ VERSION = '1.4.0' unless defined? VERSION
3
3
  end
data/views/atom.erb CHANGED
@@ -10,12 +10,12 @@
10
10
  <% newest_gem = versions.newest %>
11
11
  <% spec = spec_for(name, newest_gem.number, newest_gem.platform) %>
12
12
  <entry>
13
- <id><%= name %></id>
13
+ <id><%= h(name) %></id>
14
14
  <updated><%= spec.date.w3cdtf %></updated>
15
- <title><%= name %> (<%= versions.size == 1 ? versions.oldest.number : "#{versions.oldest.number} - #{versions.newest.number}" %>)</title>
16
- <author><name><%= spec.authors.join(", ") %></name></author>
15
+ <title><%= h(name) %> (<%= h(versions.size == 1 ? versions.oldest.number : "#{versions.oldest.number} - #{versions.newest.number}") %>)</title>
16
+ <author><name><%= h(spec.authors.join(", ")) %></name></author>
17
17
  <% versions.each do |version| %>
18
- <link href="<%= url "/gems/#{version.gemfile_name}.gem" %>" />
18
+ <link href="<%= h(url "/gems/#{version.gemfile_name}.gem") %>" />
19
19
  <% end %>
20
20
  </entry>
21
21
  <% end %>
data/views/gem.erb CHANGED
@@ -5,18 +5,18 @@
5
5
  <ul class="gemlist">
6
6
  <% @gem.by_name do |name, versions| %>
7
7
  <li class="gem-version">
8
- <h2><%= name %> (<%= versions.count == 1 ? versions.first.number : "#{versions.oldest.number} - #{versions.newest.number}" %>)</h2>
8
+ <h2><%= h(name) %> (<%= h(versions.count == 1 ? versions.first.number : "#{versions.oldest.number} - #{versions.newest.number}") %>)</h2>
9
9
  <% versions.each.reverse_each do |version| %>
10
10
  <p>
11
- <code>gem install <%= version.name %> <%= "--prerelease" if version.number.to_s.match(/[a-z]/i) %> -v "<%= version.number %>"</code>
11
+ <code>gem install <%= h(version.name) %> <%= "--prerelease" if version.number.to_s.match(/[a-z]/i) %> -v "<%= h(version.number) %>"</code>
12
12
  <% unless version.platform =~ /^ruby/i %>
13
- <small class="platform"><%= version.platform %></small>
13
+ <small class="platform"><%= h(version.platform) %></small>
14
14
  <% end %>
15
15
  </p>
16
16
  <div class="delete-form">
17
- <a class="download" href="<%= url("/gems/#{version.gemfile_name}.gem") %>">download</a>
17
+ <a class="download" href="<%= h(url("/gems/#{version.gemfile_name}.gem")) %>">download</a>
18
18
  <% if @allow_delete %>
19
- <form method="post" action="<%= url("/gems/#{version.gemfile_name}.gem") %>">
19
+ <form method="post" action="<%= h(url("/gems/#{version.gemfile_name}.gem")) %>">
20
20
  <input type="hidden" name="_method" value="DELETE" />
21
21
  <button type="submit">delete</button>
22
22
  </form>
@@ -28,10 +28,10 @@
28
28
  <p>
29
29
  <% newest_gem = versions.newest %>
30
30
  <% if spec = spec_for(name, newest_gem.number, newest_gem.platform) %>
31
- <%= spec.description %>
31
+ <%= h(spec.description) %>
32
32
  <br/>
33
33
  <span class="author">– <%= spec.authors.map do |author|
34
- "<a href='#{href(spec.homepage)}'>#{author}</a>"
34
+ "<a href='#{href(spec.homepage)}'>#{h(author)}</a>"
35
35
  end.join(', ') %></span>
36
36
  <% end %>
37
37
  </p>
data/views/index.erb CHANGED
@@ -18,16 +18,16 @@
18
18
 
19
19
  <% @gems.by_name do |name, versions| %>
20
20
  <li <%= %{id="jump_#{name[0..0].downcase}"} if @index_gems.delete(name[0..0].downcase) %> class="gem-version">
21
- <h2><%= name %> (<%= versions.count == 1 ? versions.first.number : "#{versions.oldest.number} - #{versions.newest.number}" %>)</h2>
21
+ <h2><%= h(name) %> (<%= h(versions.count == 1 ? versions.first.number : "#{versions.oldest.number} - #{versions.newest.number}") %>)</h2>
22
22
  <% versions.each.reverse_each.first(5).each do |version| %>
23
23
  <p>
24
- <code>gem install <%= version.name %> <%= "--prerelease" if version.number.to_s.match(/[a-z]/i) %> -v "<%= version.number %>"</code>
24
+ <code>gem install <%= h(version.name) %> <%= "--prerelease" if version.number.to_s.match(/[a-z]/i) %> -v "<%= h(version.number) %>"</code>
25
25
  <% unless version.platform =~ /^ruby/i %>
26
- <small class="platform"><%= version.platform %></small>
26
+ <small class="platform"><%= h(version.platform) %></small>
27
27
  <% end %>
28
28
  </p>
29
- <form class="delete-form" method="post" action="<%= url("/gems/#{version.gemfile_name}.gem") %>">
30
- <a class="download" href="<%= url("/gems/#{version.gemfile_name}.gem") %>">download</a>
29
+ <form class="delete-form" method="post" action="<%= h(url("/gems/#{version.gemfile_name}.gem")) %>">
30
+ <a class="download" href="<%= h(url("/gems/#{version.gemfile_name}.gem")) %>">download</a>
31
31
  <% if @allow_delete %>
32
32
  <input type="hidden" name="_method" value="DELETE" />
33
33
  <button type="submit">delete</button>
@@ -36,17 +36,17 @@
36
36
  <% end %>
37
37
 
38
38
  <% if versions.count > 5 %>
39
- <a href="<%= url("/gems/#{name}") %>" id="more_link">Older versions...</a>
39
+ <a href="<%= h(url("/gems/#{name}")) %>" id="more_link">Older versions...</a>
40
40
  <% end %>
41
41
 
42
42
  <div class="details">
43
43
  <p>
44
44
  <% newest_gem = versions.newest %>
45
45
  <% if spec = spec_for(name, newest_gem.number, newest_gem.platform) %>
46
- <%= spec.description %>
46
+ <%= h(spec.description) %>
47
47
  <br/>
48
48
  <span class="author">– <%= spec.authors.map do |author|
49
- "<a href='#{href(spec.homepage)}'>#{author}</a>"
49
+ "<a href='#{href(spec.homepage)}'>#{h(author)}</a>"
50
50
  end.join(', ') %></span>
51
51
  <% end %>
52
52
  </p>
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geminabox
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Lea
8
8
  - Jack Foy
9
9
  - Rob Nichols
10
10
  - Naotoshi Seo
11
- autorequire:
11
+ autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2018-04-06 00:00:00.000000000 Z
14
+ date: 2021-05-29 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: sinatra
@@ -97,6 +97,20 @@ dependencies:
97
97
  - - ">="
98
98
  - !ruby/object:Gem::Version
99
99
  version: '0'
100
+ - !ruby/object:Gem::Dependency
101
+ name: rss
102
+ requirement: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ type: :runtime
108
+ prerelease: false
109
+ version_requirements: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
100
114
  description: A sinatra based gem hosting app, with client side gem push style functionality.
101
115
  email:
102
116
  - contrib@tomlea.co.uk
@@ -149,7 +163,7 @@ licenses:
149
163
  - MIT-LICENSE
150
164
  metadata:
151
165
  source_code_uri: https://github.com/geminabox/geminabox
152
- post_install_message:
166
+ post_install_message:
153
167
  rdoc_options:
154
168
  - "--main"
155
169
  - README.md
@@ -166,9 +180,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
166
180
  - !ruby/object:Gem::Version
167
181
  version: '0'
168
182
  requirements: []
169
- rubyforge_project:
170
- rubygems_version: 2.7.4
171
- signing_key:
183
+ rubygems_version: 3.1.2
184
+ signing_key:
172
185
  specification_version: 4
173
186
  summary: Really simple rubygem hosting
174
187
  test_files: []