geminabox 1.1.1 → 1.4.1
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/README.md +4 -0
- data/lib/geminabox.rb +21 -19
- data/lib/geminabox/gem_list_merge.rb +29 -14
- data/lib/geminabox/proxy/splicer.rb +3 -2
- data/lib/geminabox/server.rb +24 -2
- data/lib/geminabox/version.rb +1 -1
- data/views/atom.erb +4 -4
- data/views/gem.erb +7 -7
- data/views/index.erb +8 -8
- metadata +20 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d4cd157b68695f62078fdfe0852c583684149a3df1bf12fe49c77f52786cf814
|
4
|
+
data.tar.gz: 81190a65a9f11776e07569922f7284a72cece2f5a39fa3a950155276b95f0ad1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 48c92617e64fd7abfbe55aee1223f2fa56ee5e6c6436e470b3b491182ccf5508ff259822204c53c32503ce9eb2be38f94e817e4cd0c6e6a3df27814006014f93
|
7
|
+
data.tar.gz: 4baad42fcfce75ff75411481cf118cde1e991471bb9f650f6869e9ccd68b8078448debcbbd5185b3d8cbe4a5b478e7485de6e8a8e7e615ea6420ed89a45fc34e
|
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,
|
@@ -66,30 +67,31 @@ module Geminabox
|
|
66
67
|
def settings
|
67
68
|
Server.settings
|
68
69
|
end
|
69
|
-
|
70
|
+
|
70
71
|
def call(env)
|
71
72
|
Server.call env
|
72
73
|
end
|
73
74
|
end
|
74
75
|
|
75
76
|
set_defaults(
|
76
|
-
data:
|
77
|
-
public_folder:
|
78
|
-
build_legacy:
|
79
|
-
incremental_updates:
|
80
|
-
views:
|
81
|
-
allow_replace:
|
82
|
-
gem_permissions:
|
83
|
-
rubygems_proxy:
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
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: File.join(ENV.fetch('TMPDIR', '/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
|
-
|
2
|
-
class GemListMerge
|
3
|
-
attr_accessor :list
|
4
|
-
|
5
|
-
IGNORE_DEPENDENCIES = 0..-2
|
1
|
+
require "set"
|
6
2
|
|
7
|
-
|
8
|
-
|
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
|
12
|
-
|
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
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
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
|
data/lib/geminabox/server.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'reentrant_flock'
|
2
|
+
require 'rubygems/util'
|
2
3
|
|
3
4
|
module Geminabox
|
4
5
|
|
@@ -148,6 +149,27 @@ module Geminabox
|
|
148
149
|
|
149
150
|
end
|
150
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
|
+
|
151
173
|
post '/upload' do
|
152
174
|
unless self.class.allow_upload?
|
153
175
|
error_response(403, 'Gem uploading is disabled')
|
@@ -184,7 +206,7 @@ module Geminabox
|
|
184
206
|
def serialize_update(&block)
|
185
207
|
with_rlock(&block)
|
186
208
|
rescue ReentrantFlock::AlreadyLocked
|
187
|
-
halt 503, { 'Retry-After' => Geminabox.retry_interval }, 'Repository lock is held by another process'
|
209
|
+
halt 503, { 'Retry-After' => Geminabox.retry_interval.to_s }, 'Repository lock is held by another process'
|
188
210
|
end
|
189
211
|
|
190
212
|
def with_rlock(&block)
|
@@ -290,7 +312,7 @@ HTML
|
|
290
312
|
end
|
291
313
|
|
292
314
|
def combined_gem_list
|
293
|
-
GemListMerge.
|
315
|
+
GemListMerge.merge(local_gem_list, remote_gem_list, strategy: Geminabox.rubygems_proxy_merge_strategy)
|
294
316
|
end
|
295
317
|
|
296
318
|
helpers do
|
data/lib/geminabox/version.rb
CHANGED
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.
|
4
|
+
version: 1.4.1
|
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:
|
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
|
-
|
170
|
-
|
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: []
|