geminabox 0.1.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.

@@ -0,0 +1,29 @@
1
+ # Gem in a Box
2
+
3
+ ![screen shot](http://i50.tinypic.com/2yknxnr.png)
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/
@@ -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
@@ -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
@@ -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
+ }
@@ -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>
@@ -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>
@@ -0,0 +1,4 @@
1
+ <form method="POST" enctype="multipart/form-data">
2
+ <input type="file" name="file">
3
+ <input type="submit" value="Upload">
4
+ </form>
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
+