egalite 0.0.7 → 1.0.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.
Files changed (93) hide show
  1. data/README.md +19 -0
  2. data/lib/egalite/version.rb +1 -1
  3. data/lib/egalite.rb +11 -2
  4. data/test/test_auth.rb +1 -2
  5. data/test/test_blank.rb +2 -3
  6. data/test/test_errorconsole.rb +5 -5
  7. data/test/test_keitai.rb +2 -2
  8. data/test/test_m17n.rb +1 -3
  9. data/test/test_template.rb +11 -0
  10. metadata +4 -87
  11. data/auth/basic.rb +0 -32
  12. data/blank.rb +0 -53
  13. data/egalite.rb +0 -742
  14. data/errorconsole.rb +0 -77
  15. data/helper.rb +0 -251
  16. data/keitai/keitai.rb +0 -107
  17. data/keitai/ketai.rb +0 -11
  18. data/keitai/rack/ketai/carrier/abstract.rb +0 -131
  19. data/keitai/rack/ketai/carrier/au.rb +0 -78
  20. data/keitai/rack/ketai/carrier/docomo.rb +0 -80
  21. data/keitai/rack/ketai/carrier/emoji/ausjisstrtoemojiid.rb +0 -1391
  22. data/keitai/rack/ketai/carrier/emoji/docomosjisstrtoemojiid.rb +0 -759
  23. data/keitai/rack/ketai/carrier/emoji/emojidata.rb +0 -836
  24. data/keitai/rack/ketai/carrier/emoji/softbankutf8strtoemojiid.rb +0 -1119
  25. data/keitai/rack/ketai/carrier/emoji/softbankwebcodetoutf8str.rb +0 -499
  26. data/keitai/rack/ketai/carrier/iphone.rb +0 -8
  27. data/keitai/rack/ketai/carrier/softbank.rb +0 -82
  28. data/keitai/rack/ketai/carrier.rb +0 -17
  29. data/keitai/rack/ketai/middleware.rb +0 -24
  30. data/m17n.rb +0 -193
  31. data/rack/auth/abstract/handler.rb +0 -37
  32. data/rack/auth/abstract/request.rb +0 -37
  33. data/rack/auth/basic.rb +0 -58
  34. data/rack/auth/digest/md5.rb +0 -124
  35. data/rack/auth/digest/nonce.rb +0 -51
  36. data/rack/auth/digest/params.rb +0 -55
  37. data/rack/auth/digest/request.rb +0 -40
  38. data/rack/builder.rb +0 -80
  39. data/rack/cascade.rb +0 -41
  40. data/rack/chunked.rb +0 -49
  41. data/rack/commonlogger.rb +0 -49
  42. data/rack/conditionalget.rb +0 -47
  43. data/rack/config.rb +0 -15
  44. data/rack/content_length.rb +0 -29
  45. data/rack/content_type.rb +0 -23
  46. data/rack/deflater.rb +0 -96
  47. data/rack/directory.rb +0 -157
  48. data/rack/etag.rb +0 -32
  49. data/rack/file.rb +0 -92
  50. data/rack/handler/cgi.rb +0 -62
  51. data/rack/handler/evented_mongrel.rb +0 -8
  52. data/rack/handler/fastcgi.rb +0 -89
  53. data/rack/handler/lsws.rb +0 -63
  54. data/rack/handler/mongrel.rb +0 -90
  55. data/rack/handler/scgi.rb +0 -59
  56. data/rack/handler/swiftiplied_mongrel.rb +0 -8
  57. data/rack/handler/thin.rb +0 -18
  58. data/rack/handler/webrick.rb +0 -73
  59. data/rack/handler.rb +0 -88
  60. data/rack/head.rb +0 -19
  61. data/rack/lint.rb +0 -567
  62. data/rack/lobster.rb +0 -65
  63. data/rack/lock.rb +0 -16
  64. data/rack/logger.rb +0 -20
  65. data/rack/methodoverride.rb +0 -27
  66. data/rack/mime.rb +0 -208
  67. data/rack/mock.rb +0 -190
  68. data/rack/nulllogger.rb +0 -18
  69. data/rack/recursive.rb +0 -61
  70. data/rack/reloader.rb +0 -109
  71. data/rack/request.rb +0 -273
  72. data/rack/response.rb +0 -150
  73. data/rack/rewindable_input.rb +0 -103
  74. data/rack/runtime.rb +0 -27
  75. data/rack/sendfile.rb +0 -144
  76. data/rack/server.rb +0 -271
  77. data/rack/session/abstract/id.rb +0 -140
  78. data/rack/session/cookie.rb +0 -90
  79. data/rack/session/memcache.rb +0 -119
  80. data/rack/session/pool.rb +0 -100
  81. data/rack/showexceptions.rb +0 -349
  82. data/rack/showstatus.rb +0 -106
  83. data/rack/static.rb +0 -38
  84. data/rack/urlmap.rb +0 -55
  85. data/rack/utils.rb +0 -662
  86. data/rack.rb +0 -81
  87. data/route.rb +0 -231
  88. data/sendmail.rb +0 -222
  89. data/sequel_helper.rb +0 -20
  90. data/session.rb +0 -132
  91. data/stringify_hash.rb +0 -63
  92. data/support.rb +0 -35
  93. data/template.rb +0 -287
data/rack/mime.rb DELETED
@@ -1,208 +0,0 @@
1
- module Rack
2
- module Mime
3
- # Returns String with mime type if found, otherwise use +fallback+.
4
- # +ext+ should be filename extension in the '.ext' format that
5
- # File.extname(file) returns.
6
- # +fallback+ may be any object
7
- #
8
- # Also see the documentation for MIME_TYPES
9
- #
10
- # Usage:
11
- # Rack::Mime.mime_type('.foo')
12
- #
13
- # This is a shortcut for:
14
- # Rack::Mime::MIME_TYPES.fetch('.foo', 'application/octet-stream')
15
-
16
- def mime_type(ext, fallback='application/octet-stream')
17
- MIME_TYPES.fetch(ext.to_s.downcase, fallback)
18
- end
19
- module_function :mime_type
20
-
21
- # List of most common mime-types, selected various sources
22
- # according to their usefulness in a webserving scope for Ruby
23
- # users.
24
- #
25
- # To amend this list with your local mime.types list you can use:
26
- #
27
- # require 'webrick/httputils'
28
- # list = WEBrick::HTTPUtils.load_mime_types('/etc/mime.types')
29
- # Rack::Mime::MIME_TYPES.merge!(list)
30
- #
31
- # To add the list mongrel provides, use:
32
- #
33
- # require 'mongrel/handlers'
34
- # Rack::Mime::MIME_TYPES.merge!(Mongrel::DirHandler::MIME_TYPES)
35
-
36
- MIME_TYPES = {
37
- ".3gp" => "video/3gpp",
38
- ".a" => "application/octet-stream",
39
- ".ai" => "application/postscript",
40
- ".aif" => "audio/x-aiff",
41
- ".aiff" => "audio/x-aiff",
42
- ".asc" => "application/pgp-signature",
43
- ".asf" => "video/x-ms-asf",
44
- ".asm" => "text/x-asm",
45
- ".asx" => "video/x-ms-asf",
46
- ".atom" => "application/atom+xml",
47
- ".au" => "audio/basic",
48
- ".avi" => "video/x-msvideo",
49
- ".bat" => "application/x-msdownload",
50
- ".bin" => "application/octet-stream",
51
- ".bmp" => "image/bmp",
52
- ".bz2" => "application/x-bzip2",
53
- ".c" => "text/x-c",
54
- ".cab" => "application/vnd.ms-cab-compressed",
55
- ".cc" => "text/x-c",
56
- ".chm" => "application/vnd.ms-htmlhelp",
57
- ".class" => "application/octet-stream",
58
- ".com" => "application/x-msdownload",
59
- ".conf" => "text/plain",
60
- ".cpp" => "text/x-c",
61
- ".crt" => "application/x-x509-ca-cert",
62
- ".css" => "text/css",
63
- ".csv" => "text/csv",
64
- ".cxx" => "text/x-c",
65
- ".deb" => "application/x-debian-package",
66
- ".der" => "application/x-x509-ca-cert",
67
- ".diff" => "text/x-diff",
68
- ".djv" => "image/vnd.djvu",
69
- ".djvu" => "image/vnd.djvu",
70
- ".dll" => "application/x-msdownload",
71
- ".dmg" => "application/octet-stream",
72
- ".doc" => "application/msword",
73
- ".dot" => "application/msword",
74
- ".dtd" => "application/xml-dtd",
75
- ".dvi" => "application/x-dvi",
76
- ".ear" => "application/java-archive",
77
- ".eml" => "message/rfc822",
78
- ".eps" => "application/postscript",
79
- ".exe" => "application/x-msdownload",
80
- ".f" => "text/x-fortran",
81
- ".f77" => "text/x-fortran",
82
- ".f90" => "text/x-fortran",
83
- ".flv" => "video/x-flv",
84
- ".for" => "text/x-fortran",
85
- ".gem" => "application/octet-stream",
86
- ".gemspec" => "text/x-script.ruby",
87
- ".gif" => "image/gif",
88
- ".gz" => "application/x-gzip",
89
- ".h" => "text/x-c",
90
- ".htc" => "text/x-component",
91
- ".hh" => "text/x-c",
92
- ".htm" => "text/html",
93
- ".html" => "text/html",
94
- ".ico" => "image/vnd.microsoft.icon",
95
- ".ics" => "text/calendar",
96
- ".ifb" => "text/calendar",
97
- ".iso" => "application/octet-stream",
98
- ".jar" => "application/java-archive",
99
- ".java" => "text/x-java-source",
100
- ".jnlp" => "application/x-java-jnlp-file",
101
- ".jpeg" => "image/jpeg",
102
- ".jpg" => "image/jpeg",
103
- ".js" => "application/javascript",
104
- ".json" => "application/json",
105
- ".log" => "text/plain",
106
- ".m3u" => "audio/x-mpegurl",
107
- ".m4v" => "video/mp4",
108
- ".man" => "text/troff",
109
- ".manifest"=> "text/cache-manifest",
110
- ".mathml" => "application/mathml+xml",
111
- ".mbox" => "application/mbox",
112
- ".mdoc" => "text/troff",
113
- ".me" => "text/troff",
114
- ".mid" => "audio/midi",
115
- ".midi" => "audio/midi",
116
- ".mime" => "message/rfc822",
117
- ".mml" => "application/mathml+xml",
118
- ".mng" => "video/x-mng",
119
- ".mov" => "video/quicktime",
120
- ".mp3" => "audio/mpeg",
121
- ".mp4" => "video/mp4",
122
- ".mp4v" => "video/mp4",
123
- ".mpeg" => "video/mpeg",
124
- ".mpg" => "video/mpeg",
125
- ".ms" => "text/troff",
126
- ".msi" => "application/x-msdownload",
127
- ".odp" => "application/vnd.oasis.opendocument.presentation",
128
- ".ods" => "application/vnd.oasis.opendocument.spreadsheet",
129
- ".odt" => "application/vnd.oasis.opendocument.text",
130
- ".ogg" => "application/ogg",
131
- ".ogv" => "video/ogg",
132
- ".p" => "text/x-pascal",
133
- ".pas" => "text/x-pascal",
134
- ".pbm" => "image/x-portable-bitmap",
135
- ".pdf" => "application/pdf",
136
- ".pem" => "application/x-x509-ca-cert",
137
- ".pgm" => "image/x-portable-graymap",
138
- ".pgp" => "application/pgp-encrypted",
139
- ".pkg" => "application/octet-stream",
140
- ".pl" => "text/x-script.perl",
141
- ".pm" => "text/x-script.perl-module",
142
- ".png" => "image/png",
143
- ".pnm" => "image/x-portable-anymap",
144
- ".ppm" => "image/x-portable-pixmap",
145
- ".pps" => "application/vnd.ms-powerpoint",
146
- ".ppt" => "application/vnd.ms-powerpoint",
147
- ".ps" => "application/postscript",
148
- ".psd" => "image/vnd.adobe.photoshop",
149
- ".py" => "text/x-script.python",
150
- ".qt" => "video/quicktime",
151
- ".ra" => "audio/x-pn-realaudio",
152
- ".rake" => "text/x-script.ruby",
153
- ".ram" => "audio/x-pn-realaudio",
154
- ".rar" => "application/x-rar-compressed",
155
- ".rb" => "text/x-script.ruby",
156
- ".rdf" => "application/rdf+xml",
157
- ".roff" => "text/troff",
158
- ".rpm" => "application/x-redhat-package-manager",
159
- ".rss" => "application/rss+xml",
160
- ".rtf" => "application/rtf",
161
- ".ru" => "text/x-script.ruby",
162
- ".s" => "text/x-asm",
163
- ".sgm" => "text/sgml",
164
- ".sgml" => "text/sgml",
165
- ".sh" => "application/x-sh",
166
- ".sig" => "application/pgp-signature",
167
- ".snd" => "audio/basic",
168
- ".so" => "application/octet-stream",
169
- ".svg" => "image/svg+xml",
170
- ".svgz" => "image/svg+xml",
171
- ".swf" => "application/x-shockwave-flash",
172
- ".t" => "text/troff",
173
- ".tar" => "application/x-tar",
174
- ".tbz" => "application/x-bzip-compressed-tar",
175
- ".tcl" => "application/x-tcl",
176
- ".tex" => "application/x-tex",
177
- ".texi" => "application/x-texinfo",
178
- ".texinfo" => "application/x-texinfo",
179
- ".text" => "text/plain",
180
- ".tif" => "image/tiff",
181
- ".tiff" => "image/tiff",
182
- ".torrent" => "application/x-bittorrent",
183
- ".tr" => "text/troff",
184
- ".txt" => "text/plain",
185
- ".vcf" => "text/x-vcard",
186
- ".vcs" => "text/x-vcalendar",
187
- ".vrml" => "model/vrml",
188
- ".war" => "application/java-archive",
189
- ".wav" => "audio/x-wav",
190
- ".webm" => "video/webm",
191
- ".wma" => "audio/x-ms-wma",
192
- ".wmv" => "video/x-ms-wmv",
193
- ".wmx" => "video/x-ms-wmx",
194
- ".wrl" => "model/vrml",
195
- ".wsdl" => "application/wsdl+xml",
196
- ".xbm" => "image/x-xbitmap",
197
- ".xhtml" => "application/xhtml+xml",
198
- ".xls" => "application/vnd.ms-excel",
199
- ".xml" => "application/xml",
200
- ".xpm" => "image/x-xpixmap",
201
- ".xsl" => "application/xml",
202
- ".xslt" => "application/xslt+xml",
203
- ".yaml" => "text/yaml",
204
- ".yml" => "text/yaml",
205
- ".zip" => "application/zip",
206
- }
207
- end
208
- end
data/rack/mock.rb DELETED
@@ -1,190 +0,0 @@
1
- require 'uri'
2
- require 'stringio'
3
- require 'rack'
4
- require 'rack/lint'
5
- require 'rack/utils'
6
- require 'rack/response'
7
-
8
- module Rack
9
- # Rack::MockRequest helps testing your Rack application without
10
- # actually using HTTP.
11
- #
12
- # After performing a request on a URL with get/post/put/delete, it
13
- # returns a MockResponse with useful helper methods for effective
14
- # testing.
15
- #
16
- # You can pass a hash with additional configuration to the
17
- # get/post/put/delete.
18
- # <tt>:input</tt>:: A String or IO-like to be used as rack.input.
19
- # <tt>:fatal</tt>:: Raise a FatalWarning if the app writes to rack.errors.
20
- # <tt>:lint</tt>:: If true, wrap the application in a Rack::Lint.
21
-
22
- class MockRequest
23
- class FatalWarning < RuntimeError
24
- end
25
-
26
- class FatalWarner
27
- def puts(warning)
28
- raise FatalWarning, warning
29
- end
30
-
31
- def write(warning)
32
- raise FatalWarning, warning
33
- end
34
-
35
- def flush
36
- end
37
-
38
- def string
39
- ""
40
- end
41
- end
42
-
43
- DEFAULT_ENV = {
44
- "rack.version" => Rack::VERSION,
45
- "rack.input" => StringIO.new,
46
- "rack.errors" => StringIO.new,
47
- "rack.multithread" => true,
48
- "rack.multiprocess" => true,
49
- "rack.run_once" => false,
50
- }
51
-
52
- def initialize(app)
53
- @app = app
54
- end
55
-
56
- def get(uri, opts={}) request("GET", uri, opts) end
57
- def post(uri, opts={}) request("POST", uri, opts) end
58
- def put(uri, opts={}) request("PUT", uri, opts) end
59
- def delete(uri, opts={}) request("DELETE", uri, opts) end
60
-
61
- def request(method="GET", uri="", opts={})
62
- env = self.class.env_for(uri, opts.merge(:method => method))
63
-
64
- if opts[:lint]
65
- app = Rack::Lint.new(@app)
66
- else
67
- app = @app
68
- end
69
-
70
- errors = env["rack.errors"]
71
- MockResponse.new(*(app.call(env) + [errors]))
72
- end
73
-
74
- # Return the Rack environment used for a request to +uri+.
75
- def self.env_for(uri="", opts={})
76
- uri = URI(uri)
77
- uri.path = "/#{uri.path}" unless uri.path[0] == ?/
78
-
79
- env = DEFAULT_ENV.dup
80
-
81
- env["REQUEST_METHOD"] = opts[:method] ? opts[:method].to_s.upcase : "GET"
82
- env["SERVER_NAME"] = uri.host || "example.org"
83
- env["SERVER_PORT"] = uri.port ? uri.port.to_s : "80"
84
- env["QUERY_STRING"] = uri.query.to_s
85
- env["PATH_INFO"] = (!uri.path || uri.path.empty?) ? "/" : uri.path
86
- env["rack.url_scheme"] = uri.scheme || "http"
87
- env["HTTPS"] = env["rack.url_scheme"] == "https" ? "on" : "off"
88
-
89
- env["SCRIPT_NAME"] = opts[:script_name] || ""
90
-
91
- if opts[:fatal]
92
- env["rack.errors"] = FatalWarner.new
93
- else
94
- env["rack.errors"] = StringIO.new
95
- end
96
-
97
- if params = opts[:params]
98
- if env["REQUEST_METHOD"] == "GET"
99
- params = Utils.parse_nested_query(params) if params.is_a?(String)
100
- params.update(Utils.parse_nested_query(env["QUERY_STRING"]))
101
- env["QUERY_STRING"] = Utils.build_nested_query(params)
102
- elsif !opts.has_key?(:input)
103
- opts["CONTENT_TYPE"] = "application/x-www-form-urlencoded"
104
- if params.is_a?(Hash)
105
- if data = Utils::Multipart.build_multipart(params)
106
- opts[:input] = data
107
- opts["CONTENT_LENGTH"] ||= data.length.to_s
108
- opts["CONTENT_TYPE"] = "multipart/form-data; boundary=#{Utils::Multipart::MULTIPART_BOUNDARY}"
109
- else
110
- opts[:input] = Utils.build_nested_query(params)
111
- end
112
- else
113
- opts[:input] = params
114
- end
115
- end
116
- end
117
-
118
- empty_str = ""
119
- empty_str.force_encoding("ASCII-8BIT") if empty_str.respond_to? :force_encoding
120
- opts[:input] ||= empty_str
121
- if String === opts[:input]
122
- rack_input = StringIO.new(opts[:input])
123
- else
124
- rack_input = opts[:input]
125
- end
126
-
127
- rack_input.set_encoding(Encoding::BINARY) if rack_input.respond_to?(:set_encoding)
128
- env['rack.input'] = rack_input
129
-
130
- env["CONTENT_LENGTH"] ||= env["rack.input"].length.to_s
131
-
132
- opts.each { |field, value|
133
- env[field] = value if String === field
134
- }
135
-
136
- env
137
- end
138
- end
139
-
140
- # Rack::MockResponse provides useful helpers for testing your apps.
141
- # Usually, you don't create the MockResponse on your own, but use
142
- # MockRequest.
143
-
144
- class MockResponse
145
- def initialize(status, headers, body, errors=StringIO.new(""))
146
- @status = status.to_i
147
-
148
- @original_headers = headers
149
- @headers = Rack::Utils::HeaderHash.new
150
- headers.each { |field, values|
151
- @headers[field] = values
152
- @headers[field] = "" if values.empty?
153
- }
154
-
155
- @body = ""
156
- body.each { |part| @body << part }
157
-
158
- @errors = errors.string if errors.respond_to?(:string)
159
- end
160
-
161
- # Status
162
- attr_reader :status
163
-
164
- # Headers
165
- attr_reader :headers, :original_headers
166
-
167
- def [](field)
168
- headers[field]
169
- end
170
-
171
-
172
- # Body
173
- attr_reader :body
174
-
175
- def =~(other)
176
- @body =~ other
177
- end
178
-
179
- def match(other)
180
- @body.match other
181
- end
182
-
183
-
184
- # Errors
185
- attr_accessor :errors
186
-
187
-
188
- include Response::Helpers
189
- end
190
- end
data/rack/nulllogger.rb DELETED
@@ -1,18 +0,0 @@
1
- module Rack
2
- class NullLogger
3
- def initialize(app)
4
- @app = app
5
- end
6
-
7
- def call(env)
8
- env['rack.logger'] = self
9
- @app.call(env)
10
- end
11
-
12
- def info(progname = nil, &block); end
13
- def debug(progname = nil, &block); end
14
- def warn(progname = nil, &block); end
15
- def error(progname = nil, &block); end
16
- def fatal(progname = nil, &block); end
17
- end
18
- end
data/rack/recursive.rb DELETED
@@ -1,61 +0,0 @@
1
- require 'uri'
2
-
3
- module Rack
4
- # Rack::ForwardRequest gets caught by Rack::Recursive and redirects
5
- # the current request to the app at +url+.
6
- #
7
- # raise ForwardRequest.new("/not-found")
8
- #
9
-
10
- class ForwardRequest < Exception
11
- attr_reader :url, :env
12
-
13
- def initialize(url, env={})
14
- @url = URI(url)
15
- @env = env
16
-
17
- @env["PATH_INFO"] = @url.path
18
- @env["QUERY_STRING"] = @url.query if @url.query
19
- @env["HTTP_HOST"] = @url.host if @url.host
20
- @env["HTTP_PORT"] = @url.port if @url.port
21
- @env["rack.url_scheme"] = @url.scheme if @url.scheme
22
-
23
- super "forwarding to #{url}"
24
- end
25
- end
26
-
27
- # Rack::Recursive allows applications called down the chain to
28
- # include data from other applications (by using
29
- # <tt>rack['rack.recursive.include'][...]</tt> or raise a
30
- # ForwardRequest to redirect internally.
31
-
32
- class Recursive
33
- def initialize(app)
34
- @app = app
35
- end
36
-
37
- def call(env)
38
- dup._call(env)
39
- end
40
-
41
- def _call(env)
42
- @script_name = env["SCRIPT_NAME"]
43
- @app.call(env.merge('rack.recursive.include' => method(:include)))
44
- rescue ForwardRequest => req
45
- call(env.merge(req.env))
46
- end
47
-
48
- def include(env, path)
49
- unless path.index(@script_name) == 0 && (path[@script_name.size] == ?/ ||
50
- path[@script_name.size].nil?)
51
- raise ArgumentError, "can only include below #{@script_name}, not #{path}"
52
- end
53
-
54
- env = env.merge("PATH_INFO" => path, "SCRIPT_NAME" => @script_name,
55
- "REQUEST_METHOD" => "GET",
56
- "CONTENT_LENGTH" => "0", "CONTENT_TYPE" => "",
57
- "rack.input" => StringIO.new(""))
58
- @app.call(env)
59
- end
60
- end
61
- end
data/rack/reloader.rb DELETED
@@ -1,109 +0,0 @@
1
- # Copyright (c) 2009 Michael Fellinger m.fellinger@gmail.com
2
- # Rack::Reloader is subject to the terms of an MIT-style license.
3
- # See COPYING or http://www.opensource.org/licenses/mit-license.php.
4
-
5
- require 'pathname'
6
-
7
- module Rack
8
-
9
- # High performant source reloader
10
- #
11
- # This class acts as Rack middleware.
12
- #
13
- # What makes it especially suited for use in a production environment is that
14
- # any file will only be checked once and there will only be made one system
15
- # call stat(2).
16
- #
17
- # Please note that this will not reload files in the background, it does so
18
- # only when actively called.
19
- #
20
- # It is performing a check/reload cycle at the start of every request, but
21
- # also respects a cool down time, during which nothing will be done.
22
- class Reloader
23
- def initialize(app, cooldown = 10, backend = Stat)
24
- @app = app
25
- @cooldown = cooldown
26
- @last = (Time.now - cooldown)
27
- @cache = {}
28
- @mtimes = {}
29
-
30
- extend backend
31
- end
32
-
33
- def call(env)
34
- if @cooldown and Time.now > @last + @cooldown
35
- if Thread.list.size > 1
36
- Thread.exclusive{ reload! }
37
- else
38
- reload!
39
- end
40
-
41
- @last = Time.now
42
- end
43
-
44
- @app.call(env)
45
- end
46
-
47
- def reload!(stderr = $stderr)
48
- rotation do |file, mtime|
49
- previous_mtime = @mtimes[file] ||= mtime
50
- safe_load(file, mtime, stderr) if mtime > previous_mtime
51
- end
52
- end
53
-
54
- # A safe Kernel::load, issuing the hooks depending on the results
55
- def safe_load(file, mtime, stderr = $stderr)
56
- load(file)
57
- stderr.puts "#{self.class}: reloaded `#{file}'"
58
- file
59
- rescue LoadError, SyntaxError => ex
60
- stderr.puts ex
61
- ensure
62
- @mtimes[file] = mtime
63
- end
64
-
65
- module Stat
66
- def rotation
67
- files = [$0, *$LOADED_FEATURES].uniq
68
- paths = ['./', *$LOAD_PATH].uniq
69
-
70
- files.map{|file|
71
- next if file =~ /\.(so|bundle)$/ # cannot reload compiled files
72
-
73
- found, stat = figure_path(file, paths)
74
- next unless found && stat && mtime = stat.mtime
75
-
76
- @cache[file] = found
77
-
78
- yield(found, mtime)
79
- }.compact
80
- end
81
-
82
- # Takes a relative or absolute +file+ name, a couple possible +paths+ that
83
- # the +file+ might reside in. Returns the full path and File::Stat for the
84
- # path.
85
- def figure_path(file, paths)
86
- found = @cache[file]
87
- found = file if !found and Pathname.new(file).absolute?
88
- found, stat = safe_stat(found)
89
- return found, stat if found
90
-
91
- paths.find do |possible_path|
92
- path = ::File.join(possible_path, file)
93
- found, stat = safe_stat(path)
94
- return ::File.expand_path(found), stat if found
95
- end
96
-
97
- return false, false
98
- end
99
-
100
- def safe_stat(file)
101
- return unless file
102
- stat = ::File.stat(file)
103
- return file, stat if stat.file?
104
- rescue Errno::ENOENT, Errno::ENOTDIR
105
- @cache.delete(file) and false
106
- end
107
- end
108
- end
109
- end