guard 0.8.2 → 0.8.3

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.
@@ -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