Module: Padrino::Reloader
- Defined in:
- lib/vendored-middleman-deps/padrino-core-0.11.2/lib/padrino-core/reloader.rb
Overview
High performance source code reloader middleware
Defined Under Namespace
Classes: Rack
Constant Summary collapse
- MTIMES =
The modification times for every file in a project.
{}
- LOADED_FILES =
The list of files loaded as part of a project.
{}
- LOADED_CLASSES =
The list of object constants and classes loaded as part of the project.
{}
Class Method Summary collapse
-
.changed? ⇒ Boolean
(also: run!)
Returns true if any file changes are detected and populates the MTIMES cache.
-
.clear! ⇒ Object
Remove files and classes loaded with stat.
-
.exclude ⇒ Object
Specified folders can be excluded from the code reload detection process.
-
.exclude_constants ⇒ Object
Specified constants can be excluded from the code unloading process.
-
.figure_path(file) ⇒ Object
Returns true if the file is defined in our padrino root.
-
.include_constants ⇒ Object
Specified constants can be configured to be reloaded on every request.
-
.lock! ⇒ Object
We lock dependencies sets to prevent reloading of protected constants.
-
.reload! ⇒ Object
Reload all files with changes detected.
-
.remove_constant(const) ⇒ Object
Removes the specified class and constant.
-
.safe_load(file, options = {}) ⇒ Object
A safe Kernel::require which issues the necessary hooks depending on results.
Class Method Details
.changed? ⇒ Boolean Also known as: run!
Returns true if any file changes are detected and populates the MTIMES cache
85 86 87 88 89 90 91 92 93 |
# File 'lib/vendored-middleman-deps/padrino-core-0.11.2/lib/padrino-core/reloader.rb', line 85 def changed? changed = false rotation do |file, mtime| new_file = MTIMES[file].nil? previous_mtime = MTIMES[file] changed = true if new_file || mtime > previous_mtime end changed end |
.clear! ⇒ Object
Remove files and classes loaded with stat
76 77 78 79 80 |
# File 'lib/vendored-middleman-deps/padrino-core-0.11.2/lib/padrino-core/reloader.rb', line 76 def clear! clear_modification_times clear_loaded_classes clear_loaded_files_and_features end |
.exclude ⇒ Object
Specified folders can be excluded from the code reload detection process. Default excluded directories at Padrino.root are: test, spec, features, tmp, config, db and public
28 29 30 |
# File 'lib/vendored-middleman-deps/padrino-core-0.11.2/lib/padrino-core/reloader.rb', line 28 def exclude @_exclude ||= %w(test spec tmp features config public db).map { |path| Padrino.root(path) } end |
.exclude_constants ⇒ Object
Specified constants can be excluded from the code unloading process.
35 36 37 |
# File 'lib/vendored-middleman-deps/padrino-core-0.11.2/lib/padrino-core/reloader.rb', line 35 def exclude_constants @_exclude_constants ||= Set.new end |
.figure_path(file) ⇒ Object
Returns true if the file is defined in our padrino root
159 160 161 162 163 164 165 166 |
# File 'lib/vendored-middleman-deps/padrino-core-0.11.2/lib/padrino-core/reloader.rb', line 159 def figure_path(file) return file if Pathname.new(file).absolute? $:.each do |path| found = File.join(path, file) return File.(found) if File.exist?(found) end file end |
.include_constants ⇒ Object
Specified constants can be configured to be reloaded on every request. Default included constants are: [none]
43 44 45 |
# File 'lib/vendored-middleman-deps/padrino-core-0.11.2/lib/padrino-core/reloader.rb', line 43 def include_constants @_include_constants ||= Set.new end |
.lock! ⇒ Object
We lock dependencies sets to prevent reloading of protected constants
99 100 101 102 103 104 105 106 |
# File 'lib/vendored-middleman-deps/padrino-core-0.11.2/lib/padrino-core/reloader.rb', line 99 def lock! klasses = ObjectSpace.classes do |klass| klass._orig_klass_name.split('::')[0] end klasses = klasses | Padrino.mounted_apps.map { |app| app.app_class } Padrino::Reloader.exclude_constants.merge(klasses) end |
.reload! ⇒ Object
Reload all files with changes detected.
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/vendored-middleman-deps/padrino-core-0.11.2/lib/padrino-core/reloader.rb', line 50 def reload! # Detect changed files rotation do |file, mtime| # Retrive the last modified time new_file = MTIMES[file].nil? previous_mtime = MTIMES[file] ||= mtime logger.devel "Detected a new file #{file}" if new_file # We skip to next file if it is not new and not modified next unless new_file || mtime > previous_mtime # Now we can reload our file apps = mounted_apps_of(file) if apps.present? apps.each { |app| app.app_obj.reload! } else safe_load(file, :force => new_file) # Reload also apps Padrino.mounted_apps.each do |app| app.app_obj.reload! if app.app_obj.dependencies.include?(file) end end end end |
.remove_constant(const) ⇒ Object
Removes the specified class and constant.
171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/vendored-middleman-deps/padrino-core-0.11.2/lib/padrino-core/reloader.rb', line 171 def remove_constant(const) return if exclude_constants.any? { |c| const._orig_klass_name.index(c) == 0 } && !include_constants.any? { |c| const._orig_klass_name.index(c) == 0 } begin parts = const.to_s.sub(/^::(Object)?/, 'Object::').split('::') object = parts.pop base = parts.empty? ? Object : Inflector.constantize(parts * '::') base.send :remove_const, object logger.devel "Removed constant: #{const} from #{base}" rescue NameError; end end |
.safe_load(file, options = {}) ⇒ Object
A safe Kernel::require which issues the necessary hooks depending on results
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/vendored-middleman-deps/padrino-core-0.11.2/lib/padrino-core/reloader.rb', line 111 def safe_load(file, ={}) began_at = Time.now force = [:force] file = figure_path(file) reload = should_reload?(file) m_time = modification_time(file) return if !force && m_time && !reload remove_loaded_file_classes(file) remove_loaded_file_features(file) # Duplicate objects and loaded features before load file klasses = ObjectSpace.classes files = Set.new($LOADED_FEATURES.dup) reload_deps_of_file(file) # And finally load the specified file begin logger.devel :loading, began_at, file if !reload logger.debug :reload, began_at, file if reload $LOADED_FEATURES.delete(file) if files.include?(file) Padrino::Utils.silence_output loaded = false require(file) loaded = true update_modification_time(file) rescue SyntaxError => e logger.error "Cannot require #{file} due to a syntax error: #{e.}" ensure Padrino::Utils.unsilence_output new_constants = ObjectSpace.new_classes(klasses) if loaded process_loaded_file(:file => file, :constants => new_constants, :files => files) else logger.devel "Failed to load #{file}; removing partially defined constants" unload_constants(new_constants) end end end |