guard 0.8.2 → 0.8.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,14 @@
1
+ ## 0.8.3 - October 1, 2011
2
+
3
+ ### Bugs fixes:
4
+
5
+ - Pull request [#145](https://github.com/guard/guard/pull/145): Fix over-utilization of CPU in Interactor. ([@johnbintz][])
6
+
7
+ ### Improvement:
8
+
9
+ - Pull request [#146](https://github.com/guard/guard/pull/146): Use a mutex instead of a lock for more efficient/simple locking. ([@f1sherman][])
10
+ - Make Guard implementation of `:task_has_failed` simple. ([@netzpirat][])
11
+
1
12
  ## 0.8.2 - September 30, 2011
2
13
 
3
14
  ### Bugs fixes:
@@ -282,6 +293,7 @@
282
293
  [@dnagir]: https://github.com/dnagir
283
294
  [@docwhat]: https://github.com/docwhat
284
295
  [@etehtsea]: https://github.com/etehtsea
296
+ [@f1sherman]: https://github.com/f1sherman
285
297
  [@fabioyamate]: https://github.com/fabioyamate
286
298
  [@fnichol]: https://github.com/fnichol
287
299
  [@Gazer]: https://github.com/Gazer
@@ -1,3 +1,5 @@
1
+ require 'thread'
2
+
1
3
  # Guard is the main module for all Guard related modules and classes.
2
4
  # Also other Guard implementation should use this namespace.
3
5
  #
@@ -39,6 +41,8 @@ module Guard
39
41
 
40
42
  debug_command_execution if @options[:debug]
41
43
 
44
+ @lock = Mutex.new
45
+
42
46
  self
43
47
  end
44
48
 
@@ -123,9 +127,6 @@ module Guard
123
127
  def stop
124
128
  UI.info 'Bye bye...', :reset => true
125
129
 
126
- listener.lock
127
- interactor.lock
128
-
129
130
  run_guard_task(:stop)
130
131
 
131
132
  listener.stop
@@ -151,13 +152,13 @@ module Guard
151
152
  # Pause Guard listening to file changes.
152
153
  #
153
154
  def pause
154
- if listener.locked
155
+ if listener.paused?
155
156
  UI.info 'Un-paused files modification listening', :reset => true
156
157
  listener.clear_changed_files
157
- listener.unlock
158
+ listener.run
158
159
  else
159
160
  UI.info 'Paused files modification listening', :reset => true
160
- listener.lock
161
+ listener.pause
161
162
  end
162
163
  end
163
164
 
@@ -175,31 +176,27 @@ module Guard
175
176
  # @yield the block to run
176
177
  #
177
178
  def run
178
- listener.lock
179
- interactor.lock
180
-
181
179
  UI.clear if options[:clear]
182
180
 
183
- begin
184
- yield
185
- rescue Interrupt
181
+ @lock.synchronize do
182
+ begin
183
+ yield
184
+ rescue Interrupt
185
+ end
186
186
  end
187
-
188
- interactor.unlock
189
- listener.unlock
190
187
  end
191
188
 
192
189
  # Loop through all groups and run the given task for each Guard.
193
190
  #
194
191
  # Stop the task run for the all Guards within a group if one Guard
195
- # throws `:task_has_failed` and the group has its `:halt_on_fail` option to `true`.
192
+ # throws `:task_has_failed`.
196
193
  #
197
194
  # @param [Symbol] task the task to run
198
195
  # @param [Array<String>] files the list of files to pass to the task
199
196
  #
200
197
  def run_guard_task(task, files = nil)
201
198
  groups.each do |group|
202
- catch group.options[:halt_on_fail] == true ? :task_has_failed : :no_catch do
199
+ catch :task_has_failed do
203
200
  guards(:group => group.name).each do |guard|
204
201
  if task == :run_on_change
205
202
  run_on_change_task(files, guard, task)
@@ -262,17 +259,22 @@ module Guard
262
259
 
263
260
  # Run a Guard task, but remove the Guard when his work leads to a system failure.
264
261
  #
262
+ # When the Group has `:halt_on_fail` disabled, we've to catch `:task_has_failed`
263
+ # here in order to avoid an uncaught throw error.
264
+ #
265
265
  # @param [Guard::Guard] guard the Guard to execute
266
266
  # @param [Symbol] task the task to run
267
267
  # @param [Array] args the arguments for the task
268
268
  # @raise [:task_has_failed] when task has failed
269
269
  #
270
270
  def run_supervised_task(guard, task, *args)
271
- guard.hook("#{ task }_begin", *args)
272
- result = guard.send(task, *args)
273
- guard.hook("#{ task }_end", result)
271
+ catch guard_symbol(guard) do
272
+ guard.hook("#{ task }_begin", *args)
273
+ result = guard.send(task, *args)
274
+ guard.hook("#{ task }_end", result)
274
275
 
275
- result
276
+ result
277
+ end
276
278
 
277
279
  rescue Exception => ex
278
280
  UI.error("#{ guard.class.name } failed to achieve its <#{ task.to_s }>, exception was:" +
@@ -284,6 +286,25 @@ module Guard
284
286
  ex
285
287
  end
286
288
 
289
+ # Get the symbol we have to catch when running a supervised task.
290
+ # If we are within a Guard group that has the `:halt_on_fail`
291
+ # option set, we do NOT catch it here, it will be catched at the
292
+ # group level.
293
+ #
294
+ # @see .run_guard_task
295
+ #
296
+ # @param [Guard::Guard] guard the Guard to execute
297
+ # @return [Symbol] the symbol to catch
298
+ #
299
+ def guard_symbol(guard)
300
+ if guard.group.class == Symbol
301
+ group = groups(guard.group)
302
+ group.options[:halt_on_fail] ? :no_catch : :task_has_failed
303
+ else
304
+ :task_has_failed
305
+ end
306
+ end
307
+
287
308
  # Add a Guard to use.
288
309
  #
289
310
  # @param [String] name the Guard name
@@ -12,67 +12,27 @@ module Guard
12
12
  #
13
13
  class Interactor
14
14
 
15
- class LockException < Exception; end
16
- class UnlockException < Exception; end
17
-
18
- attr_reader :locked
19
-
20
- # Initialize the interactor in unlocked state.
21
- #
22
- def initialize
23
- @locked = false
24
- end
25
-
26
15
  # Start the interactor in its own thread.
27
16
  #
28
17
  def start
29
18
  return if ENV["GUARD_ENV"] == 'test'
30
19
 
31
20
  @thread = Thread.new do
32
- loop do
33
- begin
34
- if !@locked && (entry = $stdin.gets)
35
- entry.gsub! /\n/, ''
36
- case entry
37
- when 'stop', 'quit', 'exit', 's', 'q', 'e'
38
- ::Guard.stop
39
- when 'reload', 'r', 'z'
40
- ::Guard::Dsl.reevaluate_guardfile
41
- ::Guard.reload
42
- when 'pause', 'p'
43
- ::Guard.pause
44
- else
45
- ::Guard.run_all
46
- end
47
- end
48
- rescue LockException
49
- lock
50
- rescue UnlockException
51
- unlock
21
+ while entry = $stdin.gets.chomp
22
+ entry.gsub! /\n/, ''
23
+ case entry
24
+ when 'stop', 'quit', 'exit', 's', 'q', 'e'
25
+ ::Guard.stop
26
+ when 'reload', 'r', 'z'
27
+ ::Guard::Dsl.reevaluate_guardfile
28
+ ::Guard.reload
29
+ when 'pause', 'p'
30
+ ::Guard.pause
31
+ else
32
+ ::Guard.run_all
52
33
  end
53
34
  end
54
35
  end
55
36
  end
56
-
57
- # Lock the interactor.
58
- #
59
- def lock
60
- if !@thread || @thread == Thread.current
61
- @locked = true
62
- else
63
- @thread.raise(LockException)
64
- end
65
- end
66
-
67
- # Unlock the interactor.
68
- #
69
- def unlock
70
- if !@thread || @thread == Thread.current
71
- @locked = false
72
- else
73
- @thread.raise(UnlockException)
74
- end
75
- end
76
-
77
37
  end
78
38
  end
@@ -19,7 +19,11 @@ module Guard
19
19
  DEFAULT_IGNORE_PATHS = %w[. .. .bundle .git log tmp vendor]
20
20
 
21
21
  attr_accessor :changed_files
22
- attr_reader :directory, :ignore_paths, :locked
22
+ attr_reader :directory, :ignore_paths
23
+
24
+ def paused?
25
+ @paused
26
+ end
23
27
 
24
28
  # Select the appropriate listener implementation for the
25
29
  # current OS and initializes it.
@@ -52,7 +56,7 @@ module Guard
52
56
  @file_timestamp_hash = {}
53
57
  @relativize_paths = options.fetch(:relativize_paths, true)
54
58
  @changed_files = []
55
- @locked = false
59
+ @paused = false
56
60
  @ignore_paths = DEFAULT_IGNORE_PATHS
57
61
  @ignore_paths |= options[:ignore_paths] if options[:ignore_paths]
58
62
  @watch_all_modifications = options.fetch(:watch_all_modifications, false)
@@ -68,7 +72,7 @@ module Guard
68
72
 
69
73
  Thread.new do
70
74
  loop do
71
- if @changed_files != [] && !@locked
75
+ if @changed_files != [] && !@paused
72
76
  changed_files = @changed_files.dup
73
77
  clear_changed_files
74
78
  ::Guard.run_on_change(changed_files)
@@ -91,16 +95,16 @@ module Guard
91
95
  def stop
92
96
  end
93
97
 
94
- # Lock the listener to ignore change events.
98
+ # Pause the listener to ignore change events.
95
99
  #
96
- def lock
97
- @locked = true
100
+ def pause
101
+ @paused = true
98
102
  end
99
103
 
100
- # Unlock the listener to listen again to change events.
104
+ # Unpause the listener to listen again to change events.
101
105
  #
102
- def unlock
103
- @locked = false
106
+ def run
107
+ @paused = false
104
108
  end
105
109
 
106
110
  # Clear the list of changed files.
@@ -1,6 +1,6 @@
1
1
  module Guard
2
2
  unless defined? Guard::VERSION
3
3
  # The current gem version of Guard
4
- VERSION = '0.8.2'
4
+ VERSION = '0.8.3'
5
5
  end
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: guard
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.2
4
+ version: 0.8.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-09-30 00:00:00.000000000Z
12
+ date: 2011-10-01 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: thor
16
- requirement: &70168902445600 !ruby/object:Gem::Requirement
16
+ requirement: &70160547964420 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 0.14.6
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70168902445600
24
+ version_requirements: *70160547964420
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: bundler
27
- requirement: &70168902457840 !ruby/object:Gem::Requirement
27
+ requirement: &70160547963800 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70168902457840
35
+ version_requirements: *70160547963800
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rspec
38
- requirement: &70168902478500 !ruby/object:Gem::Requirement
38
+ requirement: &70160547962800 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 2.6.0
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70168902478500
46
+ version_requirements: *70160547962800
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: guard-rspec
49
- requirement: &70168902484120 !ruby/object:Gem::Requirement
49
+ requirement: &70160547961820 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 0.3.1
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70168902484120
57
+ version_requirements: *70160547961820
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: yard
60
- requirement: &70168902486840 !ruby/object:Gem::Requirement
60
+ requirement: &70160547961140 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: 0.7.2
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70168902486840
68
+ version_requirements: *70160547961140
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: kramdown
71
- requirement: &70168902520560 !ruby/object:Gem::Requirement
71
+ requirement: &70160547960440 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ~>
@@ -76,7 +76,7 @@ dependencies:
76
76
  version: 0.13.3
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70168902520560
79
+ version_requirements: *70160547960440
80
80
  description: Guard is a command line tool to easily handle events on file system modifications.
81
81
  email:
82
82
  - thibaud@thibaud.me