heel 0.6.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/{CHANGES → HISTORY} +3 -3
- data/LICENSE +1 -1
- data/README +28 -26
- data/bin/heel +5 -1
- data/data/error.rhtml +1 -1
- data/data/listing.rhtml +2 -2
- data/gemspec.rb +42 -0
- data/lib/heel.rb +18 -13
- data/lib/heel/configuration.rb +64 -0
- data/lib/heel/directory_indexer.rb +114 -0
- data/lib/heel/error_response.rb +43 -0
- data/lib/heel/logger.rb +42 -0
- data/lib/heel/mime_map.rb +87 -0
- data/lib/heel/rackapp.rb +142 -0
- data/lib/heel/request.rb +66 -0
- data/lib/heel/server.rb +253 -219
- data/lib/heel/version.rb +21 -16
- data/spec/configuration_spec.rb +20 -0
- data/spec/directory_indexer_spec.rb +34 -0
- data/spec/rackapp_spec.rb +43 -0
- data/spec/server_spec.rb +107 -108
- data/tasks/announce.rake +42 -0
- data/tasks/config.rb +103 -0
- data/tasks/distribution.rake +52 -0
- data/tasks/documentation.rake +35 -0
- data/tasks/rspec.rb +33 -0
- data/tasks/rubyforge.rb +52 -0
- data/tasks/utils.rb +85 -0
- metadata +52 -44
- data/lib/heel/dir_handler.rb +0 -310
- data/lib/heel/error_handler.rb +0 -30
- data/lib/heel/gemspec.rb +0 -56
- data/lib/heel/specification.rb +0 -128
- data/spec/dir_handler_spec.rb +0 -128
- data/spec/error_handler_spec.rb +0 -29
data/{CHANGES → HISTORY}
RENAMED
@@ -1,4 +1,7 @@
|
|
1
1
|
= Changelog
|
2
|
+
== Version 1.0.0 - 2008-04-20
|
3
|
+
|
4
|
+
* Convert Heel to a Rack and Thin application
|
2
5
|
|
3
6
|
== Version 0.6.0 - 2007-11-21
|
4
7
|
|
@@ -6,9 +9,6 @@
|
|
6
9
|
* Changed change 'resources' directory to 'data'
|
7
10
|
* Renamed internal constants
|
8
11
|
* Changed operating URL's to avoid conflict with directories heel may be serving
|
9
|
-
** /css -> /heel_css
|
10
|
-
** /icons -> /heel_icons
|
11
|
-
** /status -> /heel_status
|
12
12
|
|
13
13
|
== Version 0.5.0 - 2007-11-19
|
14
14
|
|
data/LICENSE
CHANGED
data/README
CHANGED
@@ -6,44 +6,45 @@
|
|
6
6
|
|
7
7
|
== DESCRIPTION:
|
8
8
|
|
9
|
-
Heel is a small static
|
10
|
-
|
11
|
-
{launchy}[http://copiousfreetime.rubyforge.org/launchy/] to open your browser at
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
9
|
+
Heel is a small static web server for use when you need a quick web server for a
|
10
|
+
directory. Once the server is running, heel will use
|
11
|
+
{launchy}[http://copiousfreetime.rubyforge.org/launchy/] to open your browser at
|
12
|
+
the URL of your document root.
|
13
|
+
|
14
|
+
Heel is built using {Rack}[http://rack.rubyforge.org] and
|
15
|
+
{Thin}[http://code.macournoyer.com/thin/]
|
16
|
+
|
17
|
+
% heel
|
18
|
+
>> Thin web server (v0.8.1 codename Rebel Porpoise)
|
19
|
+
>> Threaded mode OFF
|
20
|
+
>> Maximum connections set to 1024
|
21
|
+
>> Listening on 0.0.0.0:4331, CTRL+C to stop
|
22
|
+
Launching your browser...
|
23
23
|
|
24
24
|
Or run it in the background
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
% heel --daemonize
|
27
|
+
Created /Users/jeremy/.heel
|
28
|
+
heel's PID (/Users/jeremy/.heel/heel.pid) and log file (/Users/jeremy/.heel/heel.log) are stored here
|
29
|
+
Launching your browser at http://0.0.0.0:4331/
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
31
|
+
% heel --kill
|
32
|
+
Sending TERM to process 3304
|
33
|
+
Done.
|
33
34
|
|
34
35
|
== FEATURES
|
35
36
|
|
36
37
|
* Automatic launching of your browser to the URL it is serving with {launchy}[http://copiousfreetime.rubyforge.org/launchy/]
|
37
38
|
* Automatic syntax highlighting of source code files with {coderay}[http://coderay.rubychan.de/]
|
38
39
|
* Run in the foreground or daemonized
|
39
|
-
* Bind to any address and port (default is
|
40
|
+
* Bind to any address and port (default is 0.0.0.0:4331)
|
40
41
|
|
41
42
|
== SYNOPSIS:
|
42
43
|
|
43
44
|
Usage: heel [options]
|
44
45
|
|
45
46
|
-a, --address ADDRESS Address to bind to
|
46
|
-
(default:
|
47
|
+
(default: 0.0.0.0)
|
47
48
|
-d, --daemonize Run daemonized in the background
|
48
49
|
-h, --help Display this text
|
49
50
|
-k, --kill Kill an existing daemonized heel process
|
@@ -65,13 +66,13 @@ Or run it in the background
|
|
65
66
|
* {coderay}[http://coderay.rubychan.de/]
|
66
67
|
* {launchy}[http://copiousfreetime.rubyforge.org/launchy/] >= 0.1.1
|
67
68
|
* {mime-types}[http://mime-types.rubyforge.org/]
|
68
|
-
* {
|
69
|
-
* {rake}[http://rake.rubyforge.org/] >= 0.7.1
|
69
|
+
* {thin}[http://thin.rubyforge.org/]
|
70
70
|
|
71
71
|
=== For development:
|
72
72
|
|
73
73
|
* {rcov}[http://eigenclass.org/hiki.rb?rcov] >= 0.7.0.1
|
74
74
|
* {rspec}[http://rspec.rubyforge.org/] >= 0.7.3
|
75
|
+
* {rake}[http://rake.rubyforge.org/] >= 0.7.1
|
75
76
|
|
76
77
|
== INSTALL:
|
77
78
|
|
@@ -79,12 +80,13 @@ Or run it in the background
|
|
79
80
|
|
80
81
|
== CREDITS:
|
81
82
|
|
82
|
-
*
|
83
|
+
* {Thin}[http://code.macournoyer.com/thin/]
|
84
|
+
* {Rack}[http://rack.rubyforge.org/]
|
83
85
|
* http://www.famfamfam.com/ for amazing icons
|
84
86
|
|
85
87
|
== BSD LICENSE:
|
86
88
|
|
87
|
-
Copyright (c) 2007, Jeremy Hinegardner
|
89
|
+
Copyright (c) 2007, 2008, Jeremy Hinegardner
|
88
90
|
|
89
91
|
All rights reserved.
|
90
92
|
|
data/bin/heel
CHANGED
@@ -1,9 +1,13 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
#--
|
4
|
+
# Copyright (c) 2007, 2008 Jeremy Hinegardner
|
5
|
+
# All rights reserved. Licensed under the BSD license. See LICENSE for details
|
6
|
+
#++
|
7
|
+
|
3
8
|
$: << File.expand_path(File.join(File.dirname(__FILE__),"..","lib"))
|
4
9
|
|
5
10
|
require 'rubygems'
|
6
|
-
require 'mongrel'
|
7
11
|
require 'heel'
|
8
12
|
|
9
13
|
Heel::Server.new(ARGV).run
|
data/data/error.rhtml
CHANGED
@@ -22,7 +22,7 @@
|
|
22
22
|
<b class="c4"></b><b class="c3"></b><b class="c2"></b><b class="c1"></b>
|
23
23
|
</div>
|
24
24
|
<div class="footer">
|
25
|
-
<a href="<%=
|
25
|
+
<a href="<%= homepage %>">heel</a>/v<%= ::Heel::VERSION %>
|
26
26
|
</div>
|
27
27
|
</div>
|
28
28
|
</body>
|
data/data/listing.rhtml
CHANGED
@@ -22,7 +22,7 @@
|
|
22
22
|
<img src="<%= entry.icon_url %>" width="16" height="16" alt="icon for type <%= entry.content_type %>" />
|
23
23
|
<% end %>
|
24
24
|
<a href="<%= "#{base_uri.chomp('/')}/#{entry.link}" %>"><%= entry.name %></a>
|
25
|
-
<% if highlighting and entry.content_type != 'Directory' then %>
|
25
|
+
<% if highlighting? and entry.content_type != 'Directory' then %>
|
26
26
|
(<a href="<%= "#{base_uri.chomp('/')}/#{entry.link}?highlighting=false" %>">download</a>)
|
27
27
|
<% end %>
|
28
28
|
</td>
|
@@ -35,7 +35,7 @@
|
|
35
35
|
</table>
|
36
36
|
</div>
|
37
37
|
<div class="footer">
|
38
|
-
<a href="
|
38
|
+
<a href="http://copiousfreetime.rubyforge.org/heel/">heel</a>/v<%= Heel::VERSION %>
|
39
39
|
</div>
|
40
40
|
</body>
|
41
41
|
</html>
|
data/gemspec.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'heel/version'
|
3
|
+
require 'tasks/config'
|
4
|
+
|
5
|
+
Heel::GEM_SPEC = Gem::Specification.new do |spec|
|
6
|
+
proj = Configuration.for('project')
|
7
|
+
spec.name = proj.name
|
8
|
+
spec.version = Heel::VERSION
|
9
|
+
|
10
|
+
spec.author = proj.author
|
11
|
+
spec.email = proj.email
|
12
|
+
spec.homepage = proj.homepage
|
13
|
+
spec.summary = proj.summary
|
14
|
+
spec.description = proj.description
|
15
|
+
spec.platform = Gem::Platform::RUBY
|
16
|
+
|
17
|
+
|
18
|
+
pkg = Configuration.for('packaging')
|
19
|
+
spec.files = pkg.files.all
|
20
|
+
spec.executables = pkg.files.bin.collect { |b| File.basename(b) }
|
21
|
+
spec.add_dependency("thin", ">= 0.7.0")
|
22
|
+
spec.add_dependency("mime-types", ">= 1.15")
|
23
|
+
spec.add_dependency("launchy", ">= 0.3.1")
|
24
|
+
spec.add_dependency("coderay", ">= 0.7.4.215")
|
25
|
+
|
26
|
+
if rdoc = Configuration.for_if_exist?('rdoc') then
|
27
|
+
spec.has_rdoc = true
|
28
|
+
spec.extra_rdoc_files = pkg.files.rdoc
|
29
|
+
spec.rdoc_options = rdoc.options + [ "--main" , rdoc.main ]
|
30
|
+
else
|
31
|
+
spec.has_rdoc = false
|
32
|
+
end
|
33
|
+
|
34
|
+
if test = Configuration.for_if_exist?('testing') then
|
35
|
+
spec.test_files = test.files
|
36
|
+
end
|
37
|
+
|
38
|
+
if rf = Configuration.for_if_exist?('rubyforge') then
|
39
|
+
spec.rubyforge_project = rf.project
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
data/lib/heel.rb
CHANGED
@@ -1,16 +1,21 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
end
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2007, 2008 Jeremy Hinegardner
|
3
|
+
# All rights reserved. Licensed under the BSD license. See LICENSE for details
|
4
|
+
#++
|
6
5
|
|
7
|
-
|
8
|
-
|
6
|
+
module Heel
|
7
|
+
# recursively descend the directory with the same name as this file and do a
|
8
|
+
# require 'heel/path/to/file'
|
9
|
+
#
|
10
|
+
def self.require_all_libs_relative_to_me
|
11
|
+
remove_parent = File.dirname(File.expand_path(__FILE__)) + File::SEPARATOR
|
12
|
+
descend_dir = File.join(remove_parent,File.basename(__FILE__, ".rb"))
|
9
13
|
|
10
|
-
|
11
|
-
|
12
|
-
require
|
13
|
-
|
14
|
-
|
15
|
-
|
14
|
+
Dir.glob("#{descend_dir}/**/*.rb").each do |rb|
|
15
|
+
lib = rb.gsub(remove_parent,'')
|
16
|
+
require lib
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
16
20
|
|
21
|
+
Heel.require_all_libs_relative_to_me
|
@@ -0,0 +1,64 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2007, 2008 Jeremy Hinegardner
|
3
|
+
# All rights reserved. Licensed under BSD license. See LICENSE for details.
|
4
|
+
#++
|
5
|
+
|
6
|
+
module Heel
|
7
|
+
|
8
|
+
# Configuration module used by all the other modules and classes for
|
9
|
+
# determining paths and default values.
|
10
|
+
#
|
11
|
+
module Configuration
|
12
|
+
|
13
|
+
# The root directory of the project is considered to be the parent directory
|
14
|
+
# of the 'lib' directory.
|
15
|
+
#
|
16
|
+
# returns:: [String] The full expanded path of the parent directory of 'lib'
|
17
|
+
# going up the path from the current file. Trailing
|
18
|
+
# File::SEPARATOR is guaranteed.
|
19
|
+
#
|
20
|
+
def self.root_dir
|
21
|
+
unless @root_dir
|
22
|
+
path_parts = ::File.expand_path(__FILE__).split(::File::SEPARATOR)
|
23
|
+
lib_index = path_parts.rindex("lib")
|
24
|
+
@root_dir = path_parts[0...lib_index].join(::File::SEPARATOR) + ::File::SEPARATOR
|
25
|
+
end
|
26
|
+
return @root_dir
|
27
|
+
end
|
28
|
+
|
29
|
+
# returns:: [String] The full expanded path of the +config+ directory
|
30
|
+
# below _root_dir_. All parameters passed in are joined onto the
|
31
|
+
# result. Trailing File::SEPARATOR is guaranteed if _args_ are
|
32
|
+
# *not* present.
|
33
|
+
#
|
34
|
+
def self.config_path(*args)
|
35
|
+
self.sub_path("config", *args)
|
36
|
+
end
|
37
|
+
|
38
|
+
# returns:: [String] The full expanded path of the +data+ directory below
|
39
|
+
# _root_dir_. All parameters passed in are joined onto the
|
40
|
+
# result. Trailing File::SEPARATOR is guaranteed if
|
41
|
+
# _*args_ are *not* present.
|
42
|
+
#
|
43
|
+
def self.data_path(*args)
|
44
|
+
self.sub_path("data", *args)
|
45
|
+
end
|
46
|
+
|
47
|
+
# returns:: [String] The full expanded path of the +lib+ directory below
|
48
|
+
# _root_dir_. All parameters passed in are joined onto the
|
49
|
+
# result. Trailing File::SEPARATOR is guaranteed if
|
50
|
+
# _*args_ are *not* present.
|
51
|
+
#
|
52
|
+
def self.lib_path(*args)
|
53
|
+
self.sub_path("lib", *args)
|
54
|
+
end
|
55
|
+
|
56
|
+
HOMEPAGE = "http://copiousfreetime.rubyforge.org/heel/"
|
57
|
+
|
58
|
+
private
|
59
|
+
def self.sub_path(sub,*args)
|
60
|
+
sp = ::File.join(root_dir, sub) + File::SEPARATOR
|
61
|
+
sp = ::File.join(sp, *args) if args
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2007, 2008 Jeremy Hinegardner
|
3
|
+
# All rights reserved. Licensed under the BSD license. See LICENSE for details
|
4
|
+
#++
|
5
|
+
|
6
|
+
require 'heel'
|
7
|
+
require 'erb'
|
8
|
+
|
9
|
+
module Heel
|
10
|
+
# generate html index pages of a directory
|
11
|
+
#
|
12
|
+
class DirectoryIndexer
|
13
|
+
|
14
|
+
attr_reader :options
|
15
|
+
attr_reader :template_file
|
16
|
+
attr_reader :template
|
17
|
+
|
18
|
+
def initialize( template_file, options )
|
19
|
+
@template_file = template_file
|
20
|
+
@options = options
|
21
|
+
reload_template
|
22
|
+
end
|
23
|
+
|
24
|
+
def should_ignore?(fname)
|
25
|
+
options[:ignore_globs].each do |glob|
|
26
|
+
return true if ::File.fnmatch(glob,fname)
|
27
|
+
end
|
28
|
+
false
|
29
|
+
end
|
30
|
+
|
31
|
+
def mime_map
|
32
|
+
@mime_map ||= Heel::MimeMap.new
|
33
|
+
end
|
34
|
+
|
35
|
+
def highlighting?
|
36
|
+
@options[:highlighting]
|
37
|
+
end
|
38
|
+
|
39
|
+
def reload_on_template_change?
|
40
|
+
@options[:reload_template_on_change]
|
41
|
+
end
|
42
|
+
|
43
|
+
def using_icons?
|
44
|
+
@options[:using_icons]
|
45
|
+
end
|
46
|
+
|
47
|
+
def reload_template
|
48
|
+
fstat = File.stat(@template_file)
|
49
|
+
@template_mtime ||= fstat.mtime
|
50
|
+
if @template.nil? or fstat.mtime > @template_mtime then
|
51
|
+
@template = ::ERB.new(File.read(@template_file))
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# generate the directory index html page of a directory
|
56
|
+
#
|
57
|
+
def index_page_for(req)
|
58
|
+
reload_template if reload_on_template_change?
|
59
|
+
dir = req.request_path
|
60
|
+
base_uri = req.path_info
|
61
|
+
entries = []
|
62
|
+
Dir.entries(dir).each do |entry|
|
63
|
+
next if should_ignore?(entry)
|
64
|
+
next if dir == @options[:document_root] and entry == ".."
|
65
|
+
|
66
|
+
stat = File.stat(File.join(dir,entry))
|
67
|
+
entry_data = OpenStruct.new
|
68
|
+
|
69
|
+
entry_data.name = entry == ".." ? "Parent Directory" : entry
|
70
|
+
entry_data.link = entry
|
71
|
+
entry_data.size = num_to_bytes(stat.size)
|
72
|
+
entry_data.last_modified = stat.mtime.strftime("%Y-%m-%d %H:%M:%S")
|
73
|
+
|
74
|
+
if stat.directory? then
|
75
|
+
entry_data.content_type = "Directory"
|
76
|
+
entry_data.size = "-"
|
77
|
+
entry_data.name += "/"
|
78
|
+
if using_icons? then
|
79
|
+
entry_data.icon_url = File.join(options[:icon_url], MimeMap.icons_by_mime_type[:directory])
|
80
|
+
end
|
81
|
+
else
|
82
|
+
entry_data.mime_type = mime_map.mime_type_of(entry)
|
83
|
+
entry_data.content_type = entry_data.mime_type.content_type
|
84
|
+
if using_icons? then
|
85
|
+
entry_data.icon_url = File.join(options[:icon_url], mime_map.icon_for(entry_data.mime_type))
|
86
|
+
end
|
87
|
+
end
|
88
|
+
entries << entry_data
|
89
|
+
end
|
90
|
+
|
91
|
+
entries = entries.sort_by { |e| e.link }
|
92
|
+
return template.result(binding)
|
93
|
+
end
|
94
|
+
|
95
|
+
# essentially this is strfbytes from facets
|
96
|
+
#
|
97
|
+
def num_to_bytes(num,fmt="%.2f")
|
98
|
+
case
|
99
|
+
when num < 1024
|
100
|
+
"#{num} bytes"
|
101
|
+
when num < 1024**2
|
102
|
+
"#{fmt % (num.to_f / 1024)} KB"
|
103
|
+
when num < 1024**3
|
104
|
+
"#{fmt % (num.to_f / 1024**2)} MB"
|
105
|
+
when num < 1024**4
|
106
|
+
"#{fmt % (num.to_f / 1024**3)} GB"
|
107
|
+
when num < 1024**5
|
108
|
+
"#{fmt % (num.to_f / 1024**4)} TB"
|
109
|
+
else
|
110
|
+
"#{num} bytes"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2007, 2008 Jeremy Hinegardner
|
3
|
+
# All rights reserved. Licensed under the BSD license. See LICENSE for details
|
4
|
+
#++
|
5
|
+
|
6
|
+
require 'heel'
|
7
|
+
require 'rack'
|
8
|
+
require 'erb'
|
9
|
+
|
10
|
+
module Heel
|
11
|
+
|
12
|
+
class ErrorResponse < ::Rack::Response
|
13
|
+
|
14
|
+
attr_reader :base_uri
|
15
|
+
|
16
|
+
class << self
|
17
|
+
def template_file
|
18
|
+
@template_file ||= Heel::Configuration.data_path("error.rhtml")
|
19
|
+
end
|
20
|
+
|
21
|
+
def template
|
22
|
+
@template ||= ::ERB.new(File.read(template_file))
|
23
|
+
end
|
24
|
+
|
25
|
+
def homepage
|
26
|
+
@homepage ||= Heel::Configuration::HOMEPAGE
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize(base_uri, body, status = 404, header = {})
|
31
|
+
super(body, status, header)
|
32
|
+
self['Content-type'] = 'text/html'
|
33
|
+
@base_uri = base_uri
|
34
|
+
end
|
35
|
+
|
36
|
+
def finish
|
37
|
+
message = ::Rack::Utils::HTTP_STATUS_CODES[status]
|
38
|
+
homepage = ErrorResponse.homepage
|
39
|
+
|
40
|
+
return [ status, header.to_hash, ErrorResponse.template.result(binding) ]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|