heel 0.6.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -1,4 +1,4 @@
1
- Copyright (c) 2007, Jeremy Hinegardner
1
+ Copyright (c) 2007, 2008, Jeremy Hinegardner
2
2
 
3
3
  All rights reserved.
4
4
 
data/README CHANGED
@@ -6,44 +6,45 @@
6
6
 
7
7
  == DESCRIPTION:
8
8
 
9
- Heel is a small static file web server based on {mongrel}[http://mongrel.rubyforge.org]
10
- for use when you need a quick web server for a directory. Once the server is running heel will use
11
- {launchy}[http://copiousfreetime.rubyforge.org/launchy/] to open your browser at the URL of your document root.
12
-
13
- % heel
14
- ** Signals ready. TERM => stop. USR2 => restart. INT => stop (no restart).
15
- ** heel running at http://127.0.0.1:4331 with document root /Users/jeremy/Projects/heel
16
- ** Use Ctrl-C to stop.
17
- ** Launching your browser...
18
- 127.0.0.1 - - [19/Nov/2007:23:23:33 MST] "GET / HTTP/1.1" 200 8374
19
- 127.0.0.1 - - [19/Nov/2007:23:23:33 MST] "GET /css/listing.css HTTP/1.1" 200 984
20
- 127.0.0.1 - - [19/Nov/2007:23:23:33 MST] "GET /icons/application.png HTTP/1.1" 200 464
21
- 127.0.0.1 - - [19/Nov/2007:23:23:33 MST] "GET /icons/folder.png HTTP/1.1" 200 537
22
- 127.0.0.1 - - [19/Nov/2007:23:23:33 MST] "GET /favicon.ico HTTP/1.1" 404 0
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
- % 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
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
- % heel --kill
31
- Sending TERM to process 1086
32
- Done.
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 127.0.0.1:4331)
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: 127.0.0.1)
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
- * {mongrel}[http://mongrel.rubyforge.org/]
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
- * Zed Shaw for {mongrel}[http://mongrel.rubyforge.org]
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="<%= Heel::SPEC::homepage %>">heel</a>/v<%= Heel::VERSION %>
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="<%= Heel::SPEC::homepage %>">heel</a>/v<%= Heel::VERSION %>
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
- module Heel
2
- APP_ROOT_DIR = File.dirname(File.expand_path(File.join(__FILE__,".."))).freeze
3
- APP_LIB_DIR = File.join(APP_ROOT_DIR,"lib")
4
- APP_DATA_DIR = File.join(APP_ROOT_DIR,"data")
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
- require 'rubygems'
8
- require 'mongrel'
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
- require 'heel/version'
11
- require 'heel/specification'
12
- require 'heel/gemspec'
13
- require 'heel/server'
14
- require 'heel/dir_handler'
15
- require 'heel/error_handler'
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