C0 code coverage information
Generated on Sat Feb 02 17:44:29 +0100 2008 with rcov 0.8.1.2
Code reported as executed by Ruby looks like this...
and this: this line is also marked as covered.
Lines considered as run by rcov, but not reported by Ruby, look like this,
and this: these lines were inferred by rcov (using simple heuristics).
Finally, here's a line marked as not executed.
1 # Copyright (c) 2008 Michael Fellinger m.fellinger@gmail.com
2 # All files in this distribution are subject to the terms of the Ruby license.
3
4 require 'set'
5
6 module Ramaze
7
8 # SourceReload provides a way to reload changed files automatically during
9 # runtime. Its default behaviour in Ramaze is to check periodically for
10 # files with newer mtime and then attempts to load them in a controlled
11 # manner.
12
13 class SourceReload
14 attr_accessor :thread, :interval, :map
15
16 # Reload everything which falls under this regex
17 trait :reload_glob => Regexp.union(/^\.\//, Dir.pwd, 'ramaze')
18
19 # Take interval for files that are going to be reloaded.
20
21 def initialize(interval = 1)
22 @interval = interval
23 @map, @files, @paths = [], [], []
24 @mtimes = {}
25 end
26
27 # start reloader-thread and assign it to this instance.
28
29 def start
30 Inform.dev("initialize automatic source reload every #{interval} seconds")
31 @thread = reloader
32 end
33
34 # Takes value of Global.sourcereload and unless it's false calls #start
35
36 def self.startup(options = {})
37 interval = Global.sourcereload
38 instance = new(interval)
39 Thread.main[:sourcereload] = instance
40 instance.reload # initial scan of all files
41 instance.start if interval
42 end
43
44 # Start reload loop in separate Thread
45
46 def reloader
47 Thread.new do
48 loop do
49 reload
50 sleep(@interval)
51 end
52 end
53 end
54
55 # One iteration of reload will look for files that changed since the last
56 # iteration and will try to #safe_load it.
57 # This method is quite handy if you want direct control over when your
58 # code is reloaded
59 #
60 # Usage example:
61 #
62 # trap :HUP do
63 # Ramaze::Inform.info "reloading source"
64 # Thread.main[:sourcereload].reload
65 # end
66 #
67
68 def reload
69 SourceReloadHooks.before_reload
70 all_reload_files.each do |file|
71 mtime = mtime(file)
72
73 next if (@mtimes[file] ||= mtime) == mtime
74
75 Inform.debug("reload #{file}")
76 @mtimes[file] = mtime if safe_load(file)
77 end
78 SourceReloadHooks.after_reload
79 end
80
81 # Scans loaded features and paths for file-paths, filters them in the end
82 # according to the trait[:reload_glob]
83
84 def all_reload_files
85 files = Array[$0, *$LOADED_FEATURES]
86 paths = Array['', './', *$LOAD_PATH]
87
88 unless [@files, @paths] == [files, paths]
89 @files, @paths = files.dup, paths.dup
90
91 map = files.map do |file|
92 paths.map{|pa|
93 File.expand_path(File.join(pa.to_s, file.to_s))
94 }.find{|po| File.exists?(po) }
95 end
96
97 @map = map.compact
98 end
99
100 @map.grep(class_trait[:reload_glob])
101 end
102
103 # Safe mtime
104
105 def mtime(file)
106 File.mtime(file)
107 rescue Errno::ENOENT
108 false
109 end
110
111 # A safe Kernel::load, issuing the SourceReloadHooks depending on the
112 # result.
113
114 def safe_load(file)
115 SourceReloadHooks.before_safe_load(file)
116 load(file)
117 SourceReloadHooks.after_safe_load_succeed(file)
118 true
119 rescue Object => ex
120 SourceReloadHooks.after_safe_load_failed(file, ex)
121 false
122 end
123 end
124
125 # Holds hooks that are called before and after #reload and #safe_load
126
127 module SourceReloadHooks
128 module_function
129
130 # Overwrite to add actions before the reload cycle is started.
131
132 def before_reload
133 end
134
135 # Overwrite to add actions after the reload cycle has ended.
136
137 def after_reload
138 end
139
140 # Overwrite to add actions before a file is Kernel::load-ed
141
142 def before_safe_load(file)
143 end
144
145 # Overwrite to add actions after a file is Kernel::load-ed successfully,
146 # by default we clean the Cache for compiled templates and resolved actions.
147
148 def after_safe_load_succeed(file)
149 Cache.compiled.clear
150 Cache.resolved.clear
151 Cache.action_methods.clear
152 SourceReloadHooks.after_safe_load(file)
153 end
154
155 # Overwrite to add custom hook in addition to default Cache cleaning
156
157 def after_safe_load(file)
158 end
159
160 # Overwrite to add actions after a file is Kernel::load-ed unsuccessfully,
161 # by default we output an error-message with the exception.
162
163 def after_safe_load_failed(file, error)
164 Inform.error(error)
165 end
166 end
167 end
Generated using the rcov code coverage analysis tool for Ruby version 0.8.1.2.