geminabox 0.1.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.
- data/README.markdown +29 -0
- data/lib/geminabox.rb +76 -0
- data/lib/hostess.rb +42 -0
- data/public/master.css +71 -0
- data/views/index.erb +14 -0
- data/views/layout.erb +15 -0
- data/views/upload.erb +4 -0
- metadata +81 -0
data/README.markdown
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Gem in a Box
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
## Really simple rubygem hosting
|
|
6
|
+
|
|
7
|
+
Gem in a box is a simple [sinatra][sinatra] app to allow you to host your own own in-house gems.
|
|
8
|
+
|
|
9
|
+
It has no security, or authentication so you should handle this yourself.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
gem install geminabox
|
|
14
|
+
|
|
15
|
+
Create a config.ru as follows:
|
|
16
|
+
|
|
17
|
+
require "rubygems"
|
|
18
|
+
require "geminabox"
|
|
19
|
+
|
|
20
|
+
Geminabox.data = "/var/geminabox-data" # …or wherever
|
|
21
|
+
run Geminabox
|
|
22
|
+
|
|
23
|
+
And finally, hook up the config.ru as you normally would ([passenger][passenger], [thin][thin], [unicorn][unicorn], whatever floats you boat).
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
[sinatra]: http://www.sinatrarb.com/
|
|
27
|
+
[passenger]: http://www.modrails.com/
|
|
28
|
+
[thin]: http://code.macournoyer.com/thin/
|
|
29
|
+
[unicorn]: http://unicorn.bogomips.org/
|
data/lib/geminabox.rb
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
require "builder"
|
|
2
|
+
require 'sinatra/base'
|
|
3
|
+
require 'rubygems'
|
|
4
|
+
require "rubygems/indexer"
|
|
5
|
+
|
|
6
|
+
require 'hostess'
|
|
7
|
+
|
|
8
|
+
class Geminabox < Sinatra::Base
|
|
9
|
+
enable :static, :methodoverride
|
|
10
|
+
|
|
11
|
+
set :public, File.join(File.dirname(__FILE__), *%w[.. public])
|
|
12
|
+
set :data, File.join(File.dirname(__FILE__), *%w[.. data])
|
|
13
|
+
set :views, File.join(File.dirname(__FILE__), *%w[.. views])
|
|
14
|
+
use Hostess
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
get '/' do
|
|
18
|
+
begin
|
|
19
|
+
@gems = Marshal.load(Gem.gunzip(Gem.read_binary( File.join(options.data, "specs.#{Gem.marshal_version}.gz")) ))
|
|
20
|
+
rescue
|
|
21
|
+
@gems = []
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
erb :index
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
get '/upload' do
|
|
28
|
+
erb :upload
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
delete '/gems/*.gem' do
|
|
32
|
+
File.delete file_path if File.exists? file_path
|
|
33
|
+
reindex
|
|
34
|
+
redirect "/"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
post '/upload' do
|
|
38
|
+
unless params[:file] && (tmpfile = params[:file][:tempfile]) && (name = params[:file][:filename])
|
|
39
|
+
@error = "No file selected"
|
|
40
|
+
return erb(:upload)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
Dir.mkdir(File.join(options.data, "gems")) unless File.directory? File.join(options.data, "gems")
|
|
44
|
+
|
|
45
|
+
File.open(File.join(options.data, "gems", File.basename(name)), "w") do |f|
|
|
46
|
+
while blk = tmpfile.read(65536)
|
|
47
|
+
f << blk
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
reindex
|
|
51
|
+
redirect "/"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
def reindex
|
|
56
|
+
Gem::Indexer.new(options.data).generate_index
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def file_path
|
|
60
|
+
File.expand_path(File.join(options.data, *request.path_info))
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
helpers do
|
|
64
|
+
def url_for(path)
|
|
65
|
+
url = request.scheme + "://"
|
|
66
|
+
url << request.host
|
|
67
|
+
|
|
68
|
+
if request.scheme == "https" && request.port != 443 ||
|
|
69
|
+
request.scheme == "http" && request.port != 80
|
|
70
|
+
url << ":#{request.port}"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
url << path
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
data/lib/hostess.rb
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require 'sinatra/base'
|
|
2
|
+
|
|
3
|
+
class Hostess < Sinatra::Base
|
|
4
|
+
def serve
|
|
5
|
+
send_file(File.expand_path(File.join(Geminabox.data, *request.path_info)))
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
%w[/specs.4.8.gz
|
|
9
|
+
/latest_specs.4.8.gz
|
|
10
|
+
/prerelease_specs.4.8.gz
|
|
11
|
+
].each do |index|
|
|
12
|
+
get index do
|
|
13
|
+
content_type('application/x-gzip')
|
|
14
|
+
serve
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
%w[/quick/Marshal.4.8/*.gemspec.rz
|
|
19
|
+
/yaml.Z
|
|
20
|
+
/Marshal.4.8.Z
|
|
21
|
+
].each do |deflated_index|
|
|
22
|
+
get deflated_index do
|
|
23
|
+
content_type('application/x-deflate')
|
|
24
|
+
serve
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
%w[/yaml
|
|
29
|
+
/Marshal.4.8
|
|
30
|
+
/specs.4.8
|
|
31
|
+
/latest_specs.4.8
|
|
32
|
+
/prerelease_specs.4.8
|
|
33
|
+
].each do |old_index|
|
|
34
|
+
get old_index do
|
|
35
|
+
serve
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
get "/gems/*.gem" do
|
|
40
|
+
serve
|
|
41
|
+
end
|
|
42
|
+
end
|
data/public/master.css
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
body {
|
|
2
|
+
background: #a00;
|
|
3
|
+
color: #444;
|
|
4
|
+
font-size: 1.2em;
|
|
5
|
+
font-family: sans-serif;
|
|
6
|
+
margin: 0;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
a {
|
|
10
|
+
text-decoration: none;
|
|
11
|
+
color: #00a;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
a:hover {
|
|
15
|
+
color: #00f;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
code {
|
|
19
|
+
font-size: 0.7em;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
#content {
|
|
23
|
+
background: #fff;
|
|
24
|
+
width: 600px;
|
|
25
|
+
position: absolute;
|
|
26
|
+
left: 50%;
|
|
27
|
+
margin-left: -300px;
|
|
28
|
+
margin-top: 2em;
|
|
29
|
+
padding: 1em;
|
|
30
|
+
border: 1px solid #000;
|
|
31
|
+
box-shadow: 0 0 3em #fff; -moz-box-shadow: 0 0 3em #fff; -webkit-box-shadow: 0 0 3em #fff;
|
|
32
|
+
border-radius: 1em; -moz-border-radius: 1em; -webkit-border-radius: 1em;
|
|
33
|
+
text-align: center;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
#content h1 {
|
|
37
|
+
margin: 0;
|
|
38
|
+
color: #a00;
|
|
39
|
+
text-shadow: #444 1px 1px 3px;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
ul.gemlist {
|
|
43
|
+
list-style: none;
|
|
44
|
+
margin: 2em 0;
|
|
45
|
+
padding: 0;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
ul.gemlist li {
|
|
49
|
+
margin: 1em;
|
|
50
|
+
background: #eee;
|
|
51
|
+
border: 1px solid #444;
|
|
52
|
+
padding: .4em;
|
|
53
|
+
border-radius: .5em; -moz-border-radius: .5em; -webkit-border-radius: .5em;
|
|
54
|
+
position: relative;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
ul.gemlist li strong {
|
|
58
|
+
display: block;
|
|
59
|
+
font-size: 1.2em;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
ul.gemlist li .delete-form {
|
|
63
|
+
position: absolute;
|
|
64
|
+
top: 0;
|
|
65
|
+
right: 0;
|
|
66
|
+
display: none;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
ul.gemlist li:hover .delete-form {
|
|
70
|
+
display: block;
|
|
71
|
+
}
|
data/views/index.erb
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<ul class="gemlist">
|
|
2
|
+
<% @gems.each do |name, version| %>
|
|
3
|
+
<li>
|
|
4
|
+
<strong><%= name %> (<%= version %>)</strong>
|
|
5
|
+
<code>gem install <%= name %> -v "<%= version %>"</code>
|
|
6
|
+
<form class="delete-form" method="post" action="/gems/<%= name %>-<%= version %>.gem">
|
|
7
|
+
<input type="hidden" name="_method" value="DELETE" />
|
|
8
|
+
<input type="submit" value="delete" />
|
|
9
|
+
</form>
|
|
10
|
+
</li>
|
|
11
|
+
<% end %>
|
|
12
|
+
</ul>
|
|
13
|
+
|
|
14
|
+
<a href="upload">Upload Another Gem</a>
|
data/views/layout.erb
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<html>
|
|
2
|
+
<head>
|
|
3
|
+
<title>Gem in a Box</title>
|
|
4
|
+
<link rel="stylesheet" href="/master.css" type="text/css" media="screen" charset="utf-8">
|
|
5
|
+
</head>
|
|
6
|
+
<body>
|
|
7
|
+
<div id="content">
|
|
8
|
+
<h1>Gem in a Box</h1>
|
|
9
|
+
<p>
|
|
10
|
+
<code>gem sources -a <%= url_for "/" %></code>
|
|
11
|
+
</p>
|
|
12
|
+
<%= yield %>
|
|
13
|
+
</div>
|
|
14
|
+
</body>
|
|
15
|
+
</html>
|
data/views/upload.erb
ADDED
metadata
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: geminabox
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Tom Lea
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
|
|
12
|
+
date: 2010-01-07 00:00:00 +00:00
|
|
13
|
+
default_executable:
|
|
14
|
+
dependencies:
|
|
15
|
+
- !ruby/object:Gem::Dependency
|
|
16
|
+
name: sinatra
|
|
17
|
+
type: :runtime
|
|
18
|
+
version_requirement:
|
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
20
|
+
requirements:
|
|
21
|
+
- - ">="
|
|
22
|
+
- !ruby/object:Gem::Version
|
|
23
|
+
version: "0"
|
|
24
|
+
version:
|
|
25
|
+
- !ruby/object:Gem::Dependency
|
|
26
|
+
name: builder
|
|
27
|
+
type: :runtime
|
|
28
|
+
version_requirement:
|
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: "0"
|
|
34
|
+
version:
|
|
35
|
+
description:
|
|
36
|
+
email: contrib@tomlea.co.uk
|
|
37
|
+
executables: []
|
|
38
|
+
|
|
39
|
+
extensions: []
|
|
40
|
+
|
|
41
|
+
extra_rdoc_files:
|
|
42
|
+
- README.markdown
|
|
43
|
+
files:
|
|
44
|
+
- README.markdown
|
|
45
|
+
- lib/geminabox.rb
|
|
46
|
+
- lib/hostess.rb
|
|
47
|
+
- public/master.css
|
|
48
|
+
- views/index.erb
|
|
49
|
+
- views/layout.erb
|
|
50
|
+
- views/upload.erb
|
|
51
|
+
has_rdoc: true
|
|
52
|
+
homepage: http://tomlea.co.uk
|
|
53
|
+
licenses: []
|
|
54
|
+
|
|
55
|
+
post_install_message:
|
|
56
|
+
rdoc_options:
|
|
57
|
+
- --main
|
|
58
|
+
- README.markdown
|
|
59
|
+
require_paths:
|
|
60
|
+
- lib
|
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
62
|
+
requirements:
|
|
63
|
+
- - ">="
|
|
64
|
+
- !ruby/object:Gem::Version
|
|
65
|
+
version: "0"
|
|
66
|
+
version:
|
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
68
|
+
requirements:
|
|
69
|
+
- - ">="
|
|
70
|
+
- !ruby/object:Gem::Version
|
|
71
|
+
version: "0"
|
|
72
|
+
version:
|
|
73
|
+
requirements: []
|
|
74
|
+
|
|
75
|
+
rubyforge_project:
|
|
76
|
+
rubygems_version: 1.3.5
|
|
77
|
+
signing_key:
|
|
78
|
+
specification_version: 3
|
|
79
|
+
summary: Really simple rubygem hosting
|
|
80
|
+
test_files: []
|
|
81
|
+
|