guard 0.7.0.rc1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/guard/hook.rb CHANGED
@@ -1,72 +1,72 @@
1
- module Guard
2
- module Hook
3
-
4
- def self.included(base)
5
- base.send :include, InstanceMethods
6
- end
7
-
8
- module InstanceMethods
9
- # When +event+ is a Symbol, #hook will generate a hook name
10
- # by concatenating the method name from where #hook is called
11
- # with the given Symbol.
12
- # Example:
13
- # def run_all
14
- # hook :foo
15
- # end
16
- # Here, when #run_all is called, #hook will notify callbacks
17
- # registered for the "run_all_foo" event.
18
- #
19
- # When +event+ is a String, #hook will directly turn the String
20
- # into a Symbol.
21
- # Example:
22
- # def run_all
23
- # hook "foo_bar"
24
- # end
25
- # Here, when #run_all is called, #hook will notify callbacks
26
- # registered for the "foo_bar" event.
27
- #
28
- # +args+ parameter is passed as is to the callbacks registered
29
- # for the given event.
30
- def hook(event, *args)
31
- hook_name = if event.is_a? Symbol
32
- calling_method = caller[0][/`([^']*)'/, 1]
33
- "#{calling_method}_#{event}"
34
- else
35
- event
36
- end.to_sym
37
-
38
- UI.debug "Hook :#{hook_name} executed for #{self.class}"
39
-
40
- Hook.notify(self.class, hook_name, *args)
41
- end
42
- end
43
-
44
- class << self
45
- def callbacks
46
- @callbacks ||= Hash.new { |hash, key| hash[key] = [] }
47
- end
48
-
49
- def add_callback(listener, guard_class, events)
50
- _events = events.is_a?(Array) ? events : [events]
51
- _events.each do |event|
52
- callbacks[[guard_class, event]] << listener
53
- end
54
- end
55
-
56
- def has_callback?(listener, guard_class, event)
57
- callbacks[[guard_class, event]].include?(listener)
58
- end
59
-
60
- def notify(guard_class, event, *args)
61
- callbacks[[guard_class, event]].each do |listener|
62
- listener.call(guard_class, event, *args)
63
- end
64
- end
65
-
66
- def reset_callbacks!
67
- @callbacks = nil
68
- end
69
- end
70
-
71
- end
72
- end
1
+ module Guard
2
+ module Hook
3
+
4
+ def self.included(base)
5
+ base.send :include, InstanceMethods
6
+ end
7
+
8
+ module InstanceMethods
9
+ # When +event+ is a Symbol, #hook will generate a hook name
10
+ # by concatenating the method name from where #hook is called
11
+ # with the given Symbol.
12
+ # Example:
13
+ # def run_all
14
+ # hook :foo
15
+ # end
16
+ # Here, when #run_all is called, #hook will notify callbacks
17
+ # registered for the "run_all_foo" event.
18
+ #
19
+ # When +event+ is a String, #hook will directly turn the String
20
+ # into a Symbol.
21
+ # Example:
22
+ # def run_all
23
+ # hook "foo_bar"
24
+ # end
25
+ # Here, when #run_all is called, #hook will notify callbacks
26
+ # registered for the "foo_bar" event.
27
+ #
28
+ # +args+ parameter is passed as is to the callbacks registered
29
+ # for the given event.
30
+ def hook(event, *args)
31
+ hook_name = if event.is_a? Symbol
32
+ calling_method = caller[0][/`([^']*)'/, 1]
33
+ "#{calling_method}_#{event}"
34
+ else
35
+ event
36
+ end.to_sym
37
+
38
+ UI.debug "Hook :#{hook_name} executed for #{self.class}"
39
+
40
+ Hook.notify(self.class, hook_name, *args)
41
+ end
42
+ end
43
+
44
+ class << self
45
+ def callbacks
46
+ @callbacks ||= Hash.new { |hash, key| hash[key] = [] }
47
+ end
48
+
49
+ def add_callback(listener, guard_class, events)
50
+ _events = events.is_a?(Array) ? events : [events]
51
+ _events.each do |event|
52
+ callbacks[[guard_class, event]] << listener
53
+ end
54
+ end
55
+
56
+ def has_callback?(listener, guard_class, event)
57
+ callbacks[[guard_class, event]].include?(listener)
58
+ end
59
+
60
+ def notify(guard_class, event, *args)
61
+ callbacks[[guard_class, event]].each do |listener|
62
+ listener.call(guard_class, event, *args)
63
+ end
64
+ end
65
+
66
+ def reset_callbacks!
67
+ @callbacks = nil
68
+ end
69
+ end
70
+
71
+ end
72
+ end
@@ -1,40 +1,40 @@
1
- module Guard
2
- class Interactor
3
-
4
- attr_reader :locked
5
-
6
- def initialize
7
- @locked = false
8
- end
9
-
10
- def start
11
- return if ENV["GUARD_ENV"] == 'test'
12
- Thread.new do
13
- loop do
14
- if (entry = $stdin.gets) && !@locked
15
- entry.gsub! /\n/, ''
16
- case entry
17
- when 'stop', 'quit', 'exit', 's', 'q', 'e'
18
- ::Guard.stop
19
- when 'reload', 'r', 'z'
20
- ::Guard.reload
21
- when 'pause', 'p'
22
- ::Guard.pause
23
- else
24
- ::Guard.run_all
25
- end
26
- end
27
- end
28
- end
29
- end
30
-
31
- def lock
32
- @locked = true
33
- end
34
-
35
- def unlock
36
- @locked = false
37
- end
38
-
39
- end
40
- end
1
+ module Guard
2
+ class Interactor
3
+
4
+ attr_reader :locked
5
+
6
+ def initialize
7
+ @locked = false
8
+ end
9
+
10
+ def start
11
+ return if ENV["GUARD_ENV"] == 'test'
12
+ Thread.new do
13
+ loop do
14
+ if (entry = $stdin.gets) && !@locked
15
+ entry.gsub! /\n/, ''
16
+ case entry
17
+ when 'stop', 'quit', 'exit', 's', 'q', 'e'
18
+ ::Guard.stop
19
+ when 'reload', 'r', 'z'
20
+ ::Guard.reload
21
+ when 'pause', 'p'
22
+ ::Guard.pause
23
+ else
24
+ ::Guard.run_all
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ def lock
32
+ @locked = true
33
+ end
34
+
35
+ def unlock
36
+ @locked = false
37
+ end
38
+
39
+ end
40
+ end
@@ -1,191 +1,191 @@
1
- require 'rbconfig'
2
- require 'digest/sha1'
3
-
4
- module Guard
5
-
6
- autoload :Darwin, 'guard/listeners/darwin'
7
- autoload :Linux, 'guard/listeners/linux'
8
- autoload :Windows, 'guard/listeners/windows'
9
- autoload :Polling, 'guard/listeners/polling'
10
-
11
- class Listener
12
-
13
- DefaultIgnorePaths = %w[. .. .bundle .git log tmp vendor]
14
- attr_accessor :changed_files
15
- attr_reader :directory, :ignore_paths, :locked
16
-
17
- def self.select_and_init(*a)
18
- if mac? && Darwin.usable?
19
- Darwin.new(*a)
20
- elsif linux? && Linux.usable?
21
- Linux.new(*a)
22
- elsif windows? && Windows.usable?
23
- Windows.new(*a)
24
- else
25
- UI.info "Using polling (Please help us to support your system better than that.)"
26
- Polling.new(*a)
27
- end
28
- end
29
-
30
- def initialize(directory = Dir.pwd, options = {})
31
- @directory = directory.to_s
32
- @sha1_checksums_hash = {}
33
- @relativize_paths = options.fetch(:relativize_paths, true)
34
- @changed_files = []
35
- @locked = false
36
- @ignore_paths = DefaultIgnorePaths
37
- @ignore_paths |= options[:ignore_paths] if options[:ignore_paths]
38
-
39
- update_last_event
40
- start_reactor
41
- end
42
-
43
- def start_reactor
44
- return if ENV["GUARD_ENV"] == 'test'
45
- Thread.new do
46
- loop do
47
- if @changed_files != [] && !@locked
48
- changed_files = @changed_files.dup
49
- clear_changed_files
50
- ::Guard.run_on_change(changed_files)
51
- else
52
- sleep 0.1
53
- end
54
- end
55
- end
56
- end
57
-
58
- def start
59
- watch(@directory)
60
- end
61
-
62
- def stop
63
- end
64
-
65
- def lock
66
- @locked = true
67
- end
68
-
69
- def unlock
70
- @locked = false
71
- end
72
-
73
- def clear_changed_files
74
- @changed_files.clear
75
- end
76
-
77
- def on_change(&callback)
78
- @callback = callback
79
- end
80
-
81
- def update_last_event
82
- @last_event = Time.now
83
- end
84
-
85
- def modified_files(dirs, options = {})
86
- last_event = @last_event
87
- update_last_event
88
- files = potentially_modified_files(dirs, options).select { |path| file_modified?(path, last_event) }
89
- relativize_paths(files)
90
- end
91
-
92
- def worker
93
- raise NotImplementedError, "should respond to #watch"
94
- end
95
-
96
- # register a directory to watch. must be implemented by the subclasses
97
- def watch(directory)
98
- raise NotImplementedError, "do whatever you want here, given the directory as only argument"
99
- end
100
-
101
- def all_files
102
- potentially_modified_files([@directory], :all => true)
103
- end
104
-
105
- # scopes all given paths to the current #directory
106
- def relativize_paths(paths)
107
- return paths unless relativize_paths?
108
- paths.map do |path|
109
- path.gsub(%r{^#{@directory}/}, '')
110
- end
111
- end
112
-
113
- def relativize_paths?
114
- !!@relativize_paths
115
- end
116
-
117
- # return children of the passed dirs that are not in the ignore_paths list
118
- def exclude_ignored_paths(dirs, ignore_paths = self.ignore_paths)
119
- Dir.glob(dirs.map { |d| "#{d.sub(%r{/+$}, '')}/*" }, File::FNM_DOTMATCH).reject do |path|
120
- ignore_paths.include?(File.basename(path))
121
- end
122
- end
123
-
124
- private
125
-
126
- def potentially_modified_files(dirs, options={})
127
- paths = exclude_ignored_paths(dirs)
128
-
129
- if options[:all]
130
- paths.inject([]) do |array, path|
131
- if File.file?(path)
132
- array << path
133
- else
134
- array += Dir.glob("#{path}/**/*", File::FNM_DOTMATCH).select { |p| File.file?(p) }
135
- end
136
- array
137
- end
138
- else
139
- paths.select { |path| File.file?(path) }
140
- end
141
- end
142
-
143
- # Depending on the filesystem, mtime/ctime is probably only precise to the second, so round
144
- # both values down to the second for the comparison.
145
- # ctime is used only on == comparison to always catches Rails 3.1 Assets pipelined on Mac OSX
146
- def file_modified?(path, last_event)
147
- ctime = File.ctime(path).to_i
148
- mtime = File.mtime(path).to_i
149
- if [mtime, ctime].max == last_event.to_i
150
- file_content_modified?(path, sha1_checksum(path))
151
- elsif mtime > last_event.to_i
152
- set_sha1_checksums_hash(path, sha1_checksum(path))
153
- true
154
- else
155
- false
156
- end
157
- rescue
158
- false
159
- end
160
-
161
- def file_content_modified?(path, sha1_checksum)
162
- if @sha1_checksums_hash[path] != sha1_checksum
163
- set_sha1_checksums_hash(path, sha1_checksum)
164
- true
165
- else
166
- false
167
- end
168
- end
169
-
170
- def set_sha1_checksums_hash(path, sha1_checksum)
171
- @sha1_checksums_hash[path] = sha1_checksum
172
- end
173
-
174
- def sha1_checksum(path)
175
- Digest::SHA1.file(path).to_s
176
- end
177
-
178
- def self.mac?
179
- RbConfig::CONFIG['target_os'] =~ /darwin/i
180
- end
181
-
182
- def self.linux?
183
- RbConfig::CONFIG['target_os'] =~ /linux/i
184
- end
185
-
186
- def self.windows?
187
- RbConfig::CONFIG['target_os'] =~ /mswin|mingw/i
188
- end
189
-
190
- end
191
- end
1
+ require 'rbconfig'
2
+ require 'digest/sha1'
3
+
4
+ module Guard
5
+
6
+ autoload :Darwin, 'guard/listeners/darwin'
7
+ autoload :Linux, 'guard/listeners/linux'
8
+ autoload :Windows, 'guard/listeners/windows'
9
+ autoload :Polling, 'guard/listeners/polling'
10
+
11
+ class Listener
12
+
13
+ DefaultIgnorePaths = %w[. .. .bundle .git log tmp vendor]
14
+ attr_accessor :changed_files
15
+ attr_reader :directory, :ignore_paths, :locked
16
+
17
+ def self.select_and_init(*a)
18
+ if mac? && Darwin.usable?
19
+ Darwin.new(*a)
20
+ elsif linux? && Linux.usable?
21
+ Linux.new(*a)
22
+ elsif windows? && Windows.usable?
23
+ Windows.new(*a)
24
+ else
25
+ UI.info "Using polling (Please help us to support your system better than that.)"
26
+ Polling.new(*a)
27
+ end
28
+ end
29
+
30
+ def initialize(directory = Dir.pwd, options = {})
31
+ @directory = directory.to_s
32
+ @sha1_checksums_hash = {}
33
+ @relativize_paths = options.fetch(:relativize_paths, true)
34
+ @changed_files = []
35
+ @locked = false
36
+ @ignore_paths = DefaultIgnorePaths
37
+ @ignore_paths |= options[:ignore_paths] if options[:ignore_paths]
38
+
39
+ update_last_event
40
+ start_reactor
41
+ end
42
+
43
+ def start_reactor
44
+ return if ENV["GUARD_ENV"] == 'test'
45
+ Thread.new do
46
+ loop do
47
+ if @changed_files != [] && !@locked
48
+ changed_files = @changed_files.dup
49
+ clear_changed_files
50
+ ::Guard.run_on_change(changed_files)
51
+ else
52
+ sleep 0.1
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ def start
59
+ watch(@directory)
60
+ end
61
+
62
+ def stop
63
+ end
64
+
65
+ def lock
66
+ @locked = true
67
+ end
68
+
69
+ def unlock
70
+ @locked = false
71
+ end
72
+
73
+ def clear_changed_files
74
+ @changed_files.clear
75
+ end
76
+
77
+ def on_change(&callback)
78
+ @callback = callback
79
+ end
80
+
81
+ def update_last_event
82
+ @last_event = Time.now
83
+ end
84
+
85
+ def modified_files(dirs, options = {})
86
+ last_event = @last_event
87
+ update_last_event
88
+ files = potentially_modified_files(dirs, options).select { |path| file_modified?(path, last_event) }
89
+ relativize_paths(files)
90
+ end
91
+
92
+ def worker
93
+ raise NotImplementedError, "should respond to #watch"
94
+ end
95
+
96
+ # register a directory to watch. must be implemented by the subclasses
97
+ def watch(directory)
98
+ raise NotImplementedError, "do whatever you want here, given the directory as only argument"
99
+ end
100
+
101
+ def all_files
102
+ potentially_modified_files([@directory], :all => true)
103
+ end
104
+
105
+ # scopes all given paths to the current #directory
106
+ def relativize_paths(paths)
107
+ return paths unless relativize_paths?
108
+ paths.map do |path|
109
+ path.gsub(%r{^#{@directory}/}, '')
110
+ end
111
+ end
112
+
113
+ def relativize_paths?
114
+ !!@relativize_paths
115
+ end
116
+
117
+ # return children of the passed dirs that are not in the ignore_paths list
118
+ def exclude_ignored_paths(dirs, ignore_paths = self.ignore_paths)
119
+ Dir.glob(dirs.map { |d| "#{d.sub(%r{/+$}, '')}/*" }, File::FNM_DOTMATCH).reject do |path|
120
+ ignore_paths.include?(File.basename(path))
121
+ end
122
+ end
123
+
124
+ private
125
+
126
+ def potentially_modified_files(dirs, options={})
127
+ paths = exclude_ignored_paths(dirs)
128
+
129
+ if options[:all]
130
+ paths.inject([]) do |array, path|
131
+ if File.file?(path)
132
+ array << path
133
+ else
134
+ array += Dir.glob("#{path}/**/*", File::FNM_DOTMATCH).select { |p| File.file?(p) }
135
+ end
136
+ array
137
+ end
138
+ else
139
+ paths.select { |path| File.file?(path) }
140
+ end
141
+ end
142
+
143
+ # Depending on the filesystem, mtime/ctime is probably only precise to the second, so round
144
+ # both values down to the second for the comparison.
145
+ # ctime is used only on == comparison to always catches Rails 3.1 Assets pipelined on Mac OSX
146
+ def file_modified?(path, last_event)
147
+ ctime = File.ctime(path).to_i
148
+ mtime = File.mtime(path).to_i
149
+ if [mtime, ctime].max == last_event.to_i
150
+ file_content_modified?(path, sha1_checksum(path))
151
+ elsif mtime > last_event.to_i
152
+ set_sha1_checksums_hash(path, sha1_checksum(path))
153
+ true
154
+ else
155
+ false
156
+ end
157
+ rescue
158
+ false
159
+ end
160
+
161
+ def file_content_modified?(path, sha1_checksum)
162
+ if @sha1_checksums_hash[path] != sha1_checksum
163
+ set_sha1_checksums_hash(path, sha1_checksum)
164
+ true
165
+ else
166
+ false
167
+ end
168
+ end
169
+
170
+ def set_sha1_checksums_hash(path, sha1_checksum)
171
+ @sha1_checksums_hash[path] = sha1_checksum
172
+ end
173
+
174
+ def sha1_checksum(path)
175
+ Digest::SHA1.file(path).to_s
176
+ end
177
+
178
+ def self.mac?
179
+ RbConfig::CONFIG['target_os'] =~ /darwin/i
180
+ end
181
+
182
+ def self.linux?
183
+ RbConfig::CONFIG['target_os'] =~ /linux/i
184
+ end
185
+
186
+ def self.windows?
187
+ RbConfig::CONFIG['target_os'] =~ /mswin|mingw/i
188
+ end
189
+
190
+ end
191
+ end