rack-unreloader 1.8.0 → 2.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.
- checksums.yaml +4 -4
- data/CHANGELOG +14 -0
- data/MIT-LICENSE +1 -1
- data/README.rdoc +38 -13
- data/lib/rack/unreloader/autoload_reloader.rb +89 -0
- data/lib/rack/unreloader/reloader.rb +8 -62
- data/lib/rack/unreloader.rb +93 -24
- metadata +8 -11
- data/Rakefile +0 -45
- data/spec/spec_helper.rb +0 -87
- data/spec/strip_paths_spec.rb +0 -858
- data/spec/unreloader_spec.rb +0 -515
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 01a3ddc58ad8308cd61dd10991e7478f546bd7d1bc2fc4bb88203b4a37d7b335
|
4
|
+
data.tar.gz: ceff468f0b2755347859e3d2a408087379a056975e00c73fe35adc5854c3cbc0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 71c0dc1e1ebfcad459d8bf6d1533200ad071f857fe2b53fb7f26af1e079169eca3835b2b1eee4a39d572244bf3208bd51718120f7e89f4dcd5b646cbed6195ca
|
7
|
+
data.tar.gz: d9e9ab98a9b36a44d0d819f0142a1c9c49a21598a390da18c7cee48199cd365a0acac7c4fd95955e49b3f18a7ef8e0fe75bfa138312e3b2d16f57ebc7574731f
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
= 2.1.0 (2023-01-18)
|
2
|
+
|
3
|
+
* Add reload? and autoload? methods for determining what mode the unreloader is operating in (jeremyevans)
|
4
|
+
|
5
|
+
* Support :autoload option and autoload method for autoloading files and directories (jeremyevans)
|
6
|
+
|
7
|
+
= 2.0.0 (2022-06-23)
|
8
|
+
|
9
|
+
* Fix TypeError being raised when requiring a file results in an error (jeremyevans)
|
10
|
+
|
11
|
+
* Drop Unreloader#strip_path_prefix (jeremyevans)
|
12
|
+
|
13
|
+
* Drop Ruby 1.8 support (jeremyevans)
|
14
|
+
|
1
15
|
= 1.8.0 (2021-10-15)
|
2
16
|
|
3
17
|
* Avoid warnings in verbose warning mode on Ruby 3+ (jeremyevans)
|
data/MIT-LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -195,7 +195,7 @@ class.
|
|
195
195
|
|
196
196
|
== Requiring
|
197
197
|
|
198
|
-
Rack::Unreloader#require is a little different than require in that it takes
|
198
|
+
Rack::Unreloader#require is a little different than Kernel#require in that it takes
|
199
199
|
a file glob, not a normal require path. For that reason, you must specify
|
200
200
|
the extension when requiring the file, and it will only look in the current
|
201
201
|
directory by default:
|
@@ -253,17 +253,44 @@ decide that instead of specifying the constants, ObjectSpace should be used to
|
|
253
253
|
automatically determine the constants loaded. You can specify this by having the
|
254
254
|
block return the :ObjectSpace symbol.
|
255
255
|
|
256
|
-
|
256
|
+
=== Autoload
|
257
257
|
|
258
|
-
|
259
|
-
|
260
|
-
|
258
|
+
To further speed things up in development mode, or when only running a subset of
|
259
|
+
tests, it can be helpful to autoload files instead of require them, so that if
|
260
|
+
the related constants are not accessed, you don't need to pay the cost of loading
|
261
|
+
the related files. To enable autoloading, pass the +:autoload+ option when
|
262
|
+
creating the reloader:
|
261
263
|
|
262
|
-
Unreloader.
|
263
|
-
Dir.chroot(Dir.pwd)
|
264
|
+
Unreloader = Rack::Unreloader.new(autoload: true){App}
|
264
265
|
|
265
|
-
|
266
|
-
|
266
|
+
Then, you can call +autoload+ instead of +require+:
|
267
|
+
|
268
|
+
Unreloader.autoload('models'){|f| File.basename(f).sub(/\.rb\z/, '').capitalize}
|
269
|
+
|
270
|
+
This will monitor the models directory for files, setting up autoloads for each
|
271
|
+
file. After the file has been loaded, normal reloading will happen for the
|
272
|
+
file. Note that for +autoload+, a block is required because the constant names
|
273
|
+
are needed before loading the file to setup the autoload.
|
274
|
+
|
275
|
+
If the <tt>reload: false</tt> option is given when creating the reloader,
|
276
|
+
autoloads will still be setup by +autoload+, but no reloading will happen. This
|
277
|
+
can be useful when testing subsets of an application. When testing subsets of
|
278
|
+
an application, you don't need reloading, but you can benefit from autoloading,
|
279
|
+
so parts of the application you are not testing are not loaded.
|
280
|
+
|
281
|
+
If you do not pass the +:autoload+ option when creating the reloader, then calls
|
282
|
+
to +autoload+ will implicitly be transformed to calls to +require+. This makes
|
283
|
+
it possible to use the same +autoload+ call in all cases, and handle four
|
284
|
+
separate scenarios:
|
285
|
+
|
286
|
+
1. Autoload then reload: Fast development mode startup, loading the minimum
|
287
|
+
number of files, but reloading if those files are changed
|
288
|
+
2. Autoload without reload: Useful for faster testing of a subset of an
|
289
|
+
application, so the untested subsets is not loaded.
|
290
|
+
3. Require then reload: Slower development mode startup, but have entire
|
291
|
+
application loaded before accepting requests
|
292
|
+
4. Require without reload: Normal production/testing mode with nothing autoloaded
|
293
|
+
or reloaded
|
267
294
|
|
268
295
|
== Usage Outside Rack
|
269
296
|
|
@@ -296,11 +323,9 @@ environment anytime there are any changes) are going to be more robust than
|
|
296
323
|
this approach, but probably slower. Be aware that you are trading robustness
|
297
324
|
for speed when using this library.
|
298
325
|
|
299
|
-
==
|
326
|
+
== Ruby Version Support
|
300
327
|
|
301
|
-
Rack::Unreloader works correctly on Ruby 1.
|
302
|
-
also works on older versions of JRuby if you use a proc to specify the constants
|
303
|
-
to unload.
|
328
|
+
Rack::Unreloader works correctly on Ruby 1.9.2+ and JRuby 9.1+.
|
304
329
|
|
305
330
|
== License
|
306
331
|
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require_relative 'reloader'
|
2
|
+
|
3
|
+
module Rack
|
4
|
+
class Unreloader
|
5
|
+
class AutoloadReloader < Reloader
|
6
|
+
def initialize(opts={})
|
7
|
+
super
|
8
|
+
|
9
|
+
# Files that autoloads have been setup for, but have not yet been loaded.
|
10
|
+
# Hash with realpath keys and values that are arrays with the
|
11
|
+
# a block that will return constant name strings that will autoload the
|
12
|
+
# file, the modified time the file, and the delete hook.
|
13
|
+
@autoload_files = {}
|
14
|
+
|
15
|
+
# Directories where new files will be setup for autoloading.
|
16
|
+
# Uses same format as @monitor_dirs.
|
17
|
+
@autoload_dirs = {}
|
18
|
+
end
|
19
|
+
|
20
|
+
def autoload_dependencies(paths, opts={}, &block)
|
21
|
+
delete_hook = opts[:delete_hook]
|
22
|
+
|
23
|
+
Unreloader.expand_paths(paths).each do |file|
|
24
|
+
if File.directory?(file)
|
25
|
+
@autoload_dirs[file] = [nil, [], block, delete_hook]
|
26
|
+
check_autoload_dir(file)
|
27
|
+
else
|
28
|
+
# Comparisons against $LOADED_FEATURES need realpaths
|
29
|
+
@autoload_files[File.realpath(file)] = [block, modified_at(file), delete_hook]
|
30
|
+
Unreloader.autoload_constants(yield(file), file, @logger)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def remove_autoload(file, strings)
|
36
|
+
strings = Array(strings)
|
37
|
+
log("Removing autoload for #{file}: #{strings.join(" ")}") unless strings.empty?
|
38
|
+
strings.each do |s|
|
39
|
+
obj, mod = Unreloader.split_autoload(s)
|
40
|
+
# Assume that if the autoload string was valid to create the
|
41
|
+
# autoload, it is still valid when removing the autoload.
|
42
|
+
obj.send(:remove_const, mod)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def check_autoload_dir(dir)
|
47
|
+
subdir_times, files, block, delete_hook = md = @autoload_dirs[dir]
|
48
|
+
return if subdir_times && subdir_times.all?{|subdir, time| File.directory?(subdir) && modified_at(subdir) == time}
|
49
|
+
md[0] = subdir_times(dir)
|
50
|
+
|
51
|
+
cur_files = Unreloader.ruby_files(dir)
|
52
|
+
return if files == cur_files
|
53
|
+
|
54
|
+
removed_files = files - cur_files
|
55
|
+
new_files = cur_files - files
|
56
|
+
|
57
|
+
# Removed files that were never required should have the constant removed
|
58
|
+
# so that accesses to the constant do not attempt to autoload a file that
|
59
|
+
# no longer exists.
|
60
|
+
removed_files.each do |file|
|
61
|
+
remove_autoload(file, block.call(file)) unless @monitor_files[file]
|
62
|
+
end
|
63
|
+
|
64
|
+
# New files not yet loaded should have autoloads added for them.
|
65
|
+
autoload_dependencies(new_files, :delete_hook=>delete_hook, &block) unless new_files.empty?
|
66
|
+
|
67
|
+
files.replace(cur_files)
|
68
|
+
end
|
69
|
+
|
70
|
+
def reload!
|
71
|
+
(@autoload_files.keys & $LOADED_FEATURES).each do |file|
|
72
|
+
# Files setup for autoloads were autoloaded, move metadata to locations
|
73
|
+
# used for required files.
|
74
|
+
log("Autoloaded file required, setting up reloading: #{file}")
|
75
|
+
block, *metadata = @autoload_files.delete(file)
|
76
|
+
@constants_defined[file] = block
|
77
|
+
@monitor_files[file] = metadata
|
78
|
+
@files[file] = {:features=>Set.new, :constants=>Array(block.call(file))}
|
79
|
+
end
|
80
|
+
|
81
|
+
@autoload_dirs.each_key do |dir|
|
82
|
+
check_autoload_dir(dir)
|
83
|
+
end
|
84
|
+
|
85
|
+
super
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -5,12 +5,6 @@ module Rack
|
|
5
5
|
class Reloader
|
6
6
|
File = ::File
|
7
7
|
|
8
|
-
# Regexp for valid constant names, to prevent code execution.
|
9
|
-
VALID_CONSTANT_NAME_REGEXP = /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/.freeze
|
10
|
-
|
11
|
-
# Options hash to force loading of files even if they haven't changed.
|
12
|
-
FORCE = {:force=>true}.freeze
|
13
|
-
|
14
8
|
# Setup the reloader. Supports :logger and :subclasses options, see
|
15
9
|
# Rack::Unloader.new for details.
|
16
10
|
def initialize(opts={})
|
@@ -55,47 +49,6 @@ module Rack
|
|
55
49
|
@skip_reload = []
|
56
50
|
end
|
57
51
|
|
58
|
-
# Strip the given path prefix from the internal data structures.
|
59
|
-
def strip_path_prefix(path_prefix)
|
60
|
-
empty = ''.freeze
|
61
|
-
|
62
|
-
# Strip the path prefix from $LOADED_FEATURES, otherwise the reloading won't work.
|
63
|
-
# Hopefully a future version of ruby will do this automatically when chrooting.
|
64
|
-
$LOADED_FEATURES.map!{|s| s.sub(path_prefix, empty)}
|
65
|
-
|
66
|
-
fix_path = lambda do |s|
|
67
|
-
s.sub(path_prefix, empty)
|
68
|
-
end
|
69
|
-
|
70
|
-
[@dependency_order, @skip_reload].each do |a|
|
71
|
-
a.map!(&fix_path)
|
72
|
-
end
|
73
|
-
|
74
|
-
[@files, @old_entries].each do |hash|
|
75
|
-
hash.each do |k,h|
|
76
|
-
h[:features].map!(&fix_path)
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
@monitor_dirs.each_value do |a|
|
81
|
-
a[1].map!(&fix_path)
|
82
|
-
end
|
83
|
-
|
84
|
-
@dependencies.each_value do |a|
|
85
|
-
a.map!(&fix_path)
|
86
|
-
end
|
87
|
-
|
88
|
-
[@files, @old_entries, @monitor_files, @monitor_dirs, @constants_defined, @dependencies].each do |hash|
|
89
|
-
hash.keys.each do |k|
|
90
|
-
if k.start_with?(path_prefix)
|
91
|
-
hash[fix_path.call(k)] = hash.delete(k)
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
nil
|
97
|
-
end
|
98
|
-
|
99
52
|
# Unload all reloadable constants and features, and clear the list
|
100
53
|
# of files to monitor.
|
101
54
|
def clear!
|
@@ -157,11 +110,7 @@ module Rack
|
|
157
110
|
return if changed_files.empty?
|
158
111
|
|
159
112
|
unless @dependencies.empty?
|
160
|
-
changed_files = reload_files(changed_files)
|
161
|
-
changed_files.flatten!
|
162
|
-
changed_files.map!{|f| File.directory?(f) ? Unreloader.ruby_files(f) : f}
|
163
|
-
changed_files.flatten!
|
164
|
-
changed_files.uniq!
|
113
|
+
changed_files = Unreloader.expand_directory_paths(reload_files(changed_files))
|
165
114
|
|
166
115
|
order = @dependency_order
|
167
116
|
order &= changed_files
|
@@ -169,14 +118,14 @@ module Rack
|
|
169
118
|
end
|
170
119
|
|
171
120
|
unless @skip_reload.empty?
|
172
|
-
|
173
|
-
skip_reload.flatten!
|
174
|
-
skip_reload.uniq!
|
175
|
-
changed_files -= skip_reload
|
121
|
+
changed_files -= Unreloader.expand_directory_paths(@skip_reload)
|
176
122
|
end
|
177
123
|
|
124
|
+
changed_files.select! do |file|
|
125
|
+
@monitor_files.has_key?(file)
|
126
|
+
end
|
178
127
|
changed_files.each do |file|
|
179
|
-
safe_load(file
|
128
|
+
safe_load(file)
|
180
129
|
end
|
181
130
|
end
|
182
131
|
|
@@ -200,14 +149,14 @@ module Rack
|
|
200
149
|
begin
|
201
150
|
safe_load(file, options)
|
202
151
|
rescue NameError, LoadError => error
|
203
|
-
log "Cyclic dependency reload for #{error}"
|
152
|
+
log "Cyclic dependency reload for #{error.class}: #{error.message}"
|
204
153
|
rescue Exception => error
|
154
|
+
log "Error: #{error.class}: #{error.message}"
|
205
155
|
break
|
206
156
|
end
|
207
157
|
end
|
208
158
|
|
209
159
|
if error
|
210
|
-
log error
|
211
160
|
raise error
|
212
161
|
end
|
213
162
|
end
|
@@ -301,9 +250,6 @@ module Rack
|
|
301
250
|
# by the require, and rolling back the constants and features if there
|
302
251
|
# are any errors.
|
303
252
|
def safe_load(file, options={})
|
304
|
-
return unless @monitor_files.has_key?(file)
|
305
|
-
return unless options[:force] || file_changed?(file)
|
306
|
-
|
307
253
|
prepare(file) # might call #safe_load recursively
|
308
254
|
log "Loading #{file}"
|
309
255
|
begin
|
data/lib/rack/unreloader.rb
CHANGED
@@ -8,27 +8,31 @@ module Rack
|
|
8
8
|
# Mutex used to synchronize reloads
|
9
9
|
MUTEX = Monitor.new
|
10
10
|
|
11
|
-
# Reference to ::File as File
|
11
|
+
# Reference to ::File as File may return Rack::File by default.
|
12
12
|
File = ::File
|
13
13
|
|
14
|
+
# Regexp for valid constant names, to prevent code execution.
|
15
|
+
VALID_CONSTANT_NAME_REGEXP = /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/.freeze
|
16
|
+
|
14
17
|
# Given the list of paths, find all matching files, or matching ruby files
|
15
18
|
# in subdirecories if given a directory, and return an array of expanded
|
16
19
|
# paths.
|
17
20
|
def self.expand_directory_paths(paths)
|
18
|
-
expand_paths(paths)
|
19
|
-
|
20
|
-
|
21
|
+
paths = expand_paths(paths)
|
22
|
+
paths.map!{|f| File.directory?(f) ? ruby_files(f) : f}
|
23
|
+
paths.flatten!
|
24
|
+
paths
|
21
25
|
end
|
22
26
|
|
23
27
|
# Given the path glob or array of path globs, find all matching files
|
24
28
|
# or directories, and return an array of expanded paths.
|
25
29
|
def self.expand_paths(paths)
|
26
|
-
Array(paths).
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
30
|
+
paths = Array(paths).flatten
|
31
|
+
paths.map!{|path| Dir.glob(path).sort_by!{|filename| filename.count('/')}}
|
32
|
+
paths.flatten!
|
33
|
+
paths.map!{|path| File.expand_path(path)}
|
34
|
+
paths.uniq!
|
35
|
+
paths
|
32
36
|
end
|
33
37
|
|
34
38
|
# The .rb files in the given directory or any subdirectory.
|
@@ -40,11 +44,51 @@ module Rack
|
|
40
44
|
files.sort
|
41
45
|
end
|
42
46
|
|
47
|
+
# Autoload the file for the given objects. objs should be a string, symbol,
|
48
|
+
# or array of them holding a Ruby constant name. Access to the constant will
|
49
|
+
# load the related file. A non-nil logger will have output logged to it.
|
50
|
+
def self.autoload_constants(objs, file, logger)
|
51
|
+
strings = Array(objs).map(&:to_s)
|
52
|
+
if strings.empty?
|
53
|
+
# Remove file from $LOADED_FEATURES if there are no constants to autoload.
|
54
|
+
# In general that is because the file is part of another class that will
|
55
|
+
# handle loading the file separately, and if that class is reloaded, we
|
56
|
+
# want to remove the loaded feature so the file can get loaded again.
|
57
|
+
$LOADED_FEATURES.delete(file)
|
58
|
+
else
|
59
|
+
logger.info("Setting up autoload for #{file}: #{strings.join(' ')}") if logger
|
60
|
+
strings.each do |s|
|
61
|
+
obj, mod = split_autoload(s)
|
62
|
+
|
63
|
+
if obj
|
64
|
+
obj.autoload(mod, file)
|
65
|
+
elsif logger
|
66
|
+
logger.info("Invalid constant name: #{s}")
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Split the given string into an array. The first is a module/class to add the
|
73
|
+
# autoload to, and the second is the name of the constant to be autoloaded.
|
74
|
+
def self.split_autoload(mod_string)
|
75
|
+
if m = VALID_CONSTANT_NAME_REGEXP.match(mod_string)
|
76
|
+
ns, sep, mod = m[1].rpartition('::')
|
77
|
+
if sep.empty?
|
78
|
+
[Object, mod]
|
79
|
+
else
|
80
|
+
[Object.module_eval("::#{ns}", __FILE__, __LINE__), mod]
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
43
85
|
# The Rack::Unreloader::Reloader instead related to this instance, if one.
|
44
86
|
attr_reader :reloader
|
45
87
|
|
46
88
|
# Setup the reloader. Options:
|
47
89
|
#
|
90
|
+
# :autoload :: Whether to allow autoloading. If not set to true, calls to
|
91
|
+
# autoload will eagerly require the related files instead of autoloading.
|
48
92
|
# :cooldown :: The number of seconds to wait between checks for changed files.
|
49
93
|
# Defaults to 1. Set to nil/false to not check for changed files.
|
50
94
|
# :handle_reload_errors :: Whether reload to handle reload errors by returning
|
@@ -58,12 +102,19 @@ module Rack
|
|
58
102
|
# match exactly, since modules don't have superclasses.
|
59
103
|
def initialize(opts={}, &block)
|
60
104
|
@app_block = block
|
105
|
+
@autoload = opts[:autoload]
|
106
|
+
@logger = opts[:logger]
|
61
107
|
if opts.fetch(:reload, true)
|
62
108
|
@cooldown = opts.fetch(:cooldown, 1)
|
63
109
|
@handle_reload_errors = opts[:handle_reload_errors]
|
64
110
|
@last = Time.at(0)
|
65
|
-
|
66
|
-
|
111
|
+
if @autoload
|
112
|
+
require_relative('unreloader/autoload_reloader')
|
113
|
+
@reloader = AutoloadReloader.new(opts)
|
114
|
+
else
|
115
|
+
require_relative('unreloader/reloader')
|
116
|
+
@reloader = Reloader.new(opts)
|
117
|
+
end
|
67
118
|
reload!
|
68
119
|
else
|
69
120
|
@reloader = @cooldown = @handle_reload_errors = false
|
@@ -86,6 +137,18 @@ module Rack
|
|
86
137
|
@app_block.call.call(env)
|
87
138
|
end
|
88
139
|
|
140
|
+
# Whether the unreloader is setup for reloading. If false, no reloading
|
141
|
+
# is done after the initial require.
|
142
|
+
def reload?
|
143
|
+
!!@reloader
|
144
|
+
end
|
145
|
+
|
146
|
+
# Whether the unreloader is setup for autoloading. If false, autoloads
|
147
|
+
# are treated as requires.
|
148
|
+
def autoload?
|
149
|
+
!!@autoload
|
150
|
+
end
|
151
|
+
|
89
152
|
# Add a file glob or array of file globs to monitor for changes.
|
90
153
|
# Options:
|
91
154
|
# :delete_hook :: When a file being monitored is deleted, call
|
@@ -98,6 +161,24 @@ module Rack
|
|
98
161
|
end
|
99
162
|
end
|
100
163
|
|
164
|
+
# Add a file glob or array of file global to autoload and monitor
|
165
|
+
# for changes. A block is required. It will be called with the
|
166
|
+
# path to be autoloaded, and should return the symbol for the
|
167
|
+
# constant name to autoload. Accepts the same options as #require.
|
168
|
+
def autoload(paths, opts={}, &block)
|
169
|
+
raise ArgumentError, "block required" unless block
|
170
|
+
|
171
|
+
if @autoload
|
172
|
+
if @reloader
|
173
|
+
@reloader.autoload_dependencies(paths, opts, &block)
|
174
|
+
else
|
175
|
+
Unreloader.expand_directory_paths(paths).each{|f| Unreloader.autoload_constants(yield(f), f, @logger)}
|
176
|
+
end
|
177
|
+
else
|
178
|
+
require(paths, opts, &block)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
101
182
|
# Records that each path in +files+ depends on +dependency+. If there
|
102
183
|
# is a modification to +dependency+, all related files will be reloaded
|
103
184
|
# after +dependency+ is reloaded. Both +dependency+ and each entry in +files+
|
@@ -128,17 +209,5 @@ module Rack
|
|
128
209
|
def reload!
|
129
210
|
@reloader.reload! if @reloader
|
130
211
|
end
|
131
|
-
|
132
|
-
# Strip the given path prefix from all absolute paths used by the
|
133
|
-
# reloader. This is designed when chrooting an application.
|
134
|
-
#
|
135
|
-
# Options:
|
136
|
-
# :strip_core :: Also strips the path prefix from $LOADED_FEATURES and
|
137
|
-
# $LOAD_PATH.
|
138
|
-
def strip_path_prefix(path_prefix, opts={})
|
139
|
-
if @reloader
|
140
|
-
@reloader.strip_path_prefix(path_prefix)
|
141
|
-
end
|
142
|
-
end
|
143
212
|
end
|
144
213
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-unreloader
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Evans
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-01-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -66,12 +66,9 @@ files:
|
|
66
66
|
- CHANGELOG
|
67
67
|
- MIT-LICENSE
|
68
68
|
- README.rdoc
|
69
|
-
- Rakefile
|
70
69
|
- lib/rack/unreloader.rb
|
70
|
+
- lib/rack/unreloader/autoload_reloader.rb
|
71
71
|
- lib/rack/unreloader/reloader.rb
|
72
|
-
- spec/spec_helper.rb
|
73
|
-
- spec/strip_paths_spec.rb
|
74
|
-
- spec/unreloader_spec.rb
|
75
72
|
homepage: http://github.com/jeremyevans/rack-unreloader
|
76
73
|
licenses:
|
77
74
|
- MIT
|
@@ -80,7 +77,7 @@ metadata:
|
|
80
77
|
changelog_uri: https://github.com/jeremyevans/rack-unreloader/blob/master/CHANGELOG
|
81
78
|
mailing_list_uri: https://github.com/jeremyevans/rack-unreloader/discussions
|
82
79
|
source_code_uri: https://github.com/jeremyevans/rack-unreloader
|
83
|
-
post_install_message:
|
80
|
+
post_install_message:
|
84
81
|
rdoc_options:
|
85
82
|
- "--quiet"
|
86
83
|
- "--line-numbers"
|
@@ -95,15 +92,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
95
92
|
requirements:
|
96
93
|
- - ">="
|
97
94
|
- !ruby/object:Gem::Version
|
98
|
-
version: 1.
|
95
|
+
version: 1.9.2
|
99
96
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
100
97
|
requirements:
|
101
98
|
- - ">="
|
102
99
|
- !ruby/object:Gem::Version
|
103
100
|
version: '0'
|
104
101
|
requirements: []
|
105
|
-
rubygems_version: 3.
|
106
|
-
signing_key:
|
102
|
+
rubygems_version: 3.4.1
|
103
|
+
signing_key:
|
107
104
|
specification_version: 4
|
108
105
|
summary: Reload application when files change, unloading constants first
|
109
106
|
test_files: []
|
data/Rakefile
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
require "rake"
|
2
|
-
require "rake/clean"
|
3
|
-
|
4
|
-
CLEAN.include ["rack-unreloader-*.gem", "rdoc"]
|
5
|
-
|
6
|
-
desc "Build rack-unreloader gem"
|
7
|
-
task :package=>[:clean] do |p|
|
8
|
-
sh %{#{FileUtils::RUBY} -S gem build rack-unreloader.gemspec}
|
9
|
-
end
|
10
|
-
|
11
|
-
### Specs
|
12
|
-
|
13
|
-
desc "Run specs"
|
14
|
-
task :spec do
|
15
|
-
sh "#{FileUtils::RUBY} #{'-w ' if RUBY_VERSION >= '3'}spec/unreloader_spec.rb"
|
16
|
-
end
|
17
|
-
|
18
|
-
task :default => :spec
|
19
|
-
|
20
|
-
### RDoc
|
21
|
-
|
22
|
-
RDOC_DEFAULT_OPTS = ["--quiet", "--line-numbers", "--inline-source", '--title', 'Rack::Unreloader: Reload application when files change, unloading constants first']
|
23
|
-
|
24
|
-
begin
|
25
|
-
gem 'hanna-nouveau'
|
26
|
-
RDOC_DEFAULT_OPTS.concat(['-f', 'hanna'])
|
27
|
-
rescue Gem::LoadError
|
28
|
-
end
|
29
|
-
|
30
|
-
rdoc_task_class = begin
|
31
|
-
require "rdoc/task"
|
32
|
-
RDoc::Task
|
33
|
-
rescue LoadError
|
34
|
-
require "rake/rdoctask"
|
35
|
-
Rake::RDocTask
|
36
|
-
end
|
37
|
-
|
38
|
-
RDOC_OPTS = RDOC_DEFAULT_OPTS + ['--main', 'README.rdoc']
|
39
|
-
|
40
|
-
rdoc_task_class.new do |rdoc|
|
41
|
-
rdoc.rdoc_dir = "rdoc"
|
42
|
-
rdoc.options += RDOC_OPTS
|
43
|
-
rdoc.rdoc_files.add %w"README.rdoc CHANGELOG MIT-LICENSE lib/**/*.rb"
|
44
|
-
end
|
45
|
-
|
data/spec/spec_helper.rb
DELETED
@@ -1,87 +0,0 @@
|
|
1
|
-
require File.join(File.dirname(File.expand_path(__FILE__)), '../lib/rack/unreloader')
|
2
|
-
require 'rubygems'
|
3
|
-
$: << 'lib'
|
4
|
-
ENV['MT_NO_PLUGINS'] = '1' # Work around stupid autoloading of plugins
|
5
|
-
gem 'minitest'
|
6
|
-
require 'minitest/global_expectations/autorun'
|
7
|
-
require 'minitest/hooks'
|
8
|
-
|
9
|
-
module ModifiedAt
|
10
|
-
def set_modified_time(file, time)
|
11
|
-
time = Time.now + time if time.is_a?(Integer)
|
12
|
-
modified_times[File.expand_path(file)] = time
|
13
|
-
end
|
14
|
-
|
15
|
-
def modified_times
|
16
|
-
@modified_times ||= {}
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def modified_at(file)
|
22
|
-
modified_times[file] || super
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
class Minitest::Spec
|
27
|
-
def code(i)
|
28
|
-
"class App; class << self; def call(env) @a end; alias call call; end; @a ||= []; @a << #{i}; end"
|
29
|
-
end
|
30
|
-
|
31
|
-
def update_app(code, file=@filename)
|
32
|
-
if ru.reloader
|
33
|
-
ru.reloader.set_modified_time(File.dirname(file), @i += 1) unless File.file?(file)
|
34
|
-
ru.reloader.set_modified_time(file, @i += 1)
|
35
|
-
end
|
36
|
-
File.open(file, 'wb'){|f| f.write(code)}
|
37
|
-
end
|
38
|
-
|
39
|
-
def file_delete(file)
|
40
|
-
if ru.reloader
|
41
|
-
ru.reloader.set_modified_time(File.dirname(file), @i += 1)
|
42
|
-
end
|
43
|
-
File.delete(file)
|
44
|
-
end
|
45
|
-
|
46
|
-
def logger
|
47
|
-
return @logger if @logger
|
48
|
-
@logger = []
|
49
|
-
def @logger.method_missing(meth, log)
|
50
|
-
self << log
|
51
|
-
end
|
52
|
-
@logger
|
53
|
-
end
|
54
|
-
|
55
|
-
def base_ru(opts={})
|
56
|
-
block = opts[:block] || proc{App}
|
57
|
-
@ru = Rack::Unreloader.new({:logger=>logger, :cooldown=>0}.merge(opts), &block)
|
58
|
-
@ru.reloader.extend ModifiedAt if @ru.reloader
|
59
|
-
Object.const_set(:RU, @ru)
|
60
|
-
end
|
61
|
-
|
62
|
-
def ru(opts={})
|
63
|
-
return @ru if @ru
|
64
|
-
base_ru(opts)
|
65
|
-
update_app(opts[:code]||code(1))
|
66
|
-
@ru.require @filename
|
67
|
-
@ru
|
68
|
-
end
|
69
|
-
|
70
|
-
def log_match(*logs)
|
71
|
-
@logger.length.must_equal logs.length
|
72
|
-
logs.zip(@logger).each{|l, log| l.is_a?(String) ? log.must_equal(l) : log.must_match(l)}
|
73
|
-
end
|
74
|
-
|
75
|
-
before do
|
76
|
-
@i = 0
|
77
|
-
@filename = 'spec/app.rb'
|
78
|
-
end
|
79
|
-
|
80
|
-
after do
|
81
|
-
ru.reloader.clear! if ru.reloader
|
82
|
-
Object.send(:remove_const, :RU)
|
83
|
-
Object.send(:remove_const, :App) if defined?(::App)
|
84
|
-
Object.send(:remove_const, :App2) if defined?(::App2)
|
85
|
-
Dir['spec/app*.rb'].each{|f| File.delete(f)}
|
86
|
-
end
|
87
|
-
end
|