guard 1.0.3 → 1.1.0.alpha

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.
Files changed (77) hide show
  1. data/CHANGELOG.md +0 -6
  2. data/README.md +38 -30
  3. data/lib/guard.rb +158 -285
  4. data/lib/guard/cli.rb +16 -2
  5. data/lib/guard/dsl.rb +41 -20
  6. data/lib/guard/dsl_describer.rb +1 -1
  7. data/lib/guard/group.rb +1 -1
  8. data/lib/guard/guard.rb +39 -5
  9. data/lib/guard/guardfile.rb +70 -0
  10. data/lib/guard/runner.rb +179 -0
  11. data/lib/guard/ui.rb +1 -1
  12. data/lib/guard/version.rb +2 -4
  13. data/lib/guard/watcher.rb +1 -0
  14. metadata +16 -77
  15. data/bin/fsevent_watch_guard_guard +0 -0
  16. data/lib/guard/listener.rb +0 -376
  17. data/lib/guard/listeners/darwin.rb +0 -62
  18. data/lib/guard/listeners/linux.rb +0 -93
  19. data/lib/guard/listeners/polling.rb +0 -55
  20. data/lib/guard/listeners/windows.rb +0 -63
  21. data/lib/vendor/darwin/Gemfile +0 -6
  22. data/lib/vendor/darwin/Guardfile +0 -8
  23. data/lib/vendor/darwin/LICENSE +0 -20
  24. data/lib/vendor/darwin/README.rdoc +0 -255
  25. data/lib/vendor/darwin/Rakefile +0 -21
  26. data/lib/vendor/darwin/bin/fsevent_watch +0 -0
  27. data/lib/vendor/darwin/ext/fsevent_watch/Info.plist +0 -38
  28. data/lib/vendor/darwin/ext/fsevent_watch/LICENSE +0 -21
  29. data/lib/vendor/darwin/ext/fsevent_watch/fsevent_watch.xcodeproj/project.pbxproj +0 -254
  30. data/lib/vendor/darwin/ext/fsevent_watch/fsevent_watch/TSICTString.c +0 -394
  31. data/lib/vendor/darwin/ext/fsevent_watch/fsevent_watch/TSICTString.h +0 -74
  32. data/lib/vendor/darwin/ext/fsevent_watch/fsevent_watch/cli.c +0 -160
  33. data/lib/vendor/darwin/ext/fsevent_watch/fsevent_watch/cli.h +0 -45
  34. data/lib/vendor/darwin/ext/fsevent_watch/fsevent_watch/common.h +0 -34
  35. data/lib/vendor/darwin/ext/fsevent_watch/fsevent_watch/compat.c +0 -20
  36. data/lib/vendor/darwin/ext/fsevent_watch/fsevent_watch/compat.h +0 -40
  37. data/lib/vendor/darwin/ext/fsevent_watch/fsevent_watch/main.c +0 -509
  38. data/lib/vendor/darwin/ext/fsevent_watch/xcconfig/Common.xcconfig +0 -82
  39. data/lib/vendor/darwin/ext/fsevent_watch/xcconfig/Debug.xcconfig +0 -19
  40. data/lib/vendor/darwin/ext/fsevent_watch/xcconfig/Release.xcconfig +0 -23
  41. data/lib/vendor/darwin/ext/fsevent_watch/xcconfig/fsevent_watch.xcconfig +0 -17
  42. data/lib/vendor/darwin/ext/rakefile.rb +0 -47
  43. data/lib/vendor/darwin/ext/rb-fsevent.xcconfig +0 -33
  44. data/lib/vendor/darwin/lib/rb-fsevent.rb +0 -2
  45. data/lib/vendor/darwin/lib/rb-fsevent/fsevent.rb +0 -111
  46. data/lib/vendor/darwin/lib/rb-fsevent/version.rb +0 -3
  47. data/lib/vendor/darwin/rb-fsevent.gemspec +0 -25
  48. data/lib/vendor/darwin/spec/fixtures/folder1/file1.txt +0 -0
  49. data/lib/vendor/darwin/spec/fixtures/folder1/folder2/file2.txt +0 -0
  50. data/lib/vendor/darwin/spec/rb-fsevent/fsevent_spec.rb +0 -88
  51. data/lib/vendor/darwin/spec/spec_helper.rb +0 -23
  52. data/lib/vendor/linux/MIT-LICENSE +0 -20
  53. data/lib/vendor/linux/README.md +0 -66
  54. data/lib/vendor/linux/Rakefile +0 -54
  55. data/lib/vendor/linux/VERSION +0 -1
  56. data/lib/vendor/linux/lib/rb-inotify.rb +0 -17
  57. data/lib/vendor/linux/lib/rb-inotify/event.rb +0 -139
  58. data/lib/vendor/linux/lib/rb-inotify/native.rb +0 -31
  59. data/lib/vendor/linux/lib/rb-inotify/native/flags.rb +0 -89
  60. data/lib/vendor/linux/lib/rb-inotify/notifier.rb +0 -308
  61. data/lib/vendor/linux/lib/rb-inotify/watcher.rb +0 -83
  62. data/lib/vendor/linux/rb-inotify.gemspec +0 -53
  63. data/lib/vendor/windows/Gemfile +0 -4
  64. data/lib/vendor/windows/README.md +0 -34
  65. data/lib/vendor/windows/Rakefile +0 -18
  66. data/lib/vendor/windows/lib/rb-fchange.rb +0 -14
  67. data/lib/vendor/windows/lib/rb-fchange/event.rb +0 -29
  68. data/lib/vendor/windows/lib/rb-fchange/native.rb +0 -45
  69. data/lib/vendor/windows/lib/rb-fchange/native/flags.rb +0 -78
  70. data/lib/vendor/windows/lib/rb-fchange/notifier.rb +0 -149
  71. data/lib/vendor/windows/lib/rb-fchange/version.rb +0 -3
  72. data/lib/vendor/windows/lib/rb-fchange/watcher.rb +0 -99
  73. data/lib/vendor/windows/rb-fchange.gemspec +0 -34
  74. data/lib/vendor/windows/spec/fixtures/folder1/file1.txt +0 -0
  75. data/lib/vendor/windows/spec/fixtures/folder1/folder2/file2.txt +0 -0
  76. data/lib/vendor/windows/spec/rb-fchange/fchange_spec.rb +0 -119
  77. data/lib/vendor/windows/spec/spec_helper.rb +0 -21
data/lib/guard/cli.rb CHANGED
@@ -47,17 +47,19 @@ module Guard
47
47
  :aliases => '-G',
48
48
  :banner => 'Specify a Guardfile'
49
49
 
50
+ # DEPRECATED
50
51
  method_option :no_vendor,
51
52
  :type => :boolean,
52
53
  :default => false,
53
54
  :aliases => '-I',
54
- :banner => 'Ignore vendored dependencies'
55
+ :banner => 'DEPRECATED: Ignore vendored dependencies'
55
56
 
57
+ # DEPRECATED
56
58
  method_option :watch_all_modifications,
57
59
  :type => :boolean,
58
60
  :default => false,
59
61
  :aliases => '-A',
60
- :banner => 'Watch for all file modifications including moves and deletions'
62
+ :banner => 'DEPRECATED: Watch for all file modifications including moves and deletions'
61
63
 
62
64
  method_option :no_interactions,
63
65
  :type => :boolean,
@@ -71,6 +73,18 @@ module Guard
71
73
  :aliases => '-B',
72
74
  :banner => 'Turn off warning when Bundler is not present'
73
75
 
76
+ # Listen options
77
+ method_option :latency,
78
+ :type => :numeric,
79
+ :aliases => '-l',
80
+ :banner => 'Overwrite Listen default latency'
81
+
82
+ method_option :force_polling,
83
+ :type => :boolean,
84
+ :default => false,
85
+ :aliases => '-p',
86
+ :banner => 'Force Listen polling listener usage'
87
+
74
88
  # Start Guard by initialize the defined Guards and watch the file system.
75
89
  # This is the default task, so calling `guard` is the same as calling `guard start`.
76
90
  #
data/lib/guard/dsl.rb CHANGED
@@ -6,8 +6,8 @@ module Guard
6
6
  # The main keywords of the DSL are `guard` and `watch`. These are necessary to define
7
7
  # the used Guards and the file changes they are watching.
8
8
  #
9
- # You can optionally group the Guards with the `group` keyword and ignore certain paths
10
- # with the `ignore_paths` keyword.
9
+ # You can optionally group the Guards with the `group` keyword and ignore and filter certain paths
10
+ # with the `ignore` and `filter` keywords.
11
11
  #
12
12
  # You can set your preferred system notification library with `notification` and pass
13
13
  # some optional configuration options for the library. If you don't configure a library,
@@ -82,6 +82,15 @@ module Guard
82
82
  # end
83
83
  #
84
84
  class Dsl
85
+
86
+ # Deprecation message for the `ignore_paths` method
87
+ IGNORE_PATHS_DEPRECATION = <<-EOS.gsub(/^\s*/, '')
88
+ Starting with Guard v1.1 the use of the 'ignore_paths' Guardfile dsl method is deprecated.
89
+
90
+ Please replace that method with the better 'ignore' or/and 'filter' methods.
91
+ Documentation on the README: https://github.com/guard/guard#guardfile-dsl-ignore
92
+ EOS
93
+
85
94
  class << self
86
95
 
87
96
  @@options = nil
@@ -105,23 +114,18 @@ module Guard
105
114
  # Re-evaluate the `Guardfile` to update the current Guard configuration.
106
115
  #
107
116
  def reevaluate_guardfile
108
- ::Guard.run do
109
- before_reevaluate_guardfile
110
- Dsl.evaluate_guardfile(@@options)
111
- after_reevaluate_guardfile
112
- end
117
+ before_reevaluate_guardfile
118
+ Dsl.evaluate_guardfile(@@options)
119
+ after_reevaluate_guardfile
113
120
  end
114
121
 
115
122
  # Stop Guards and clear internal state
116
123
  # before the Guardfile will be re-evaluated.
117
124
  #
118
125
  def before_reevaluate_guardfile
119
- ::Guard.run_on_guards do |guard|
120
- ::Guard.run_supervised_task(guard, :stop)
121
- end
122
-
126
+ ::Guard.runner.run(:stop)
123
127
  ::Guard.guards.clear
124
- ::Guard.reset_groups
128
+ ::Guard.setup_groups
125
129
  ::Guard::Notifier.clear_notifications
126
130
 
127
131
  @@options.delete(:guardfile_contents)
@@ -140,9 +144,7 @@ module Guard
140
144
  ::Guard::UI.info(msg)
141
145
  ::Guard::Notifier.notify(msg, :title => 'Guard re-evaluate')
142
146
 
143
- ::Guard.run_on_guards do |guard|
144
- ::Guard.run_supervised_task(guard, :start)
145
- end
147
+ ::Guard.runner.run(:start)
146
148
  end
147
149
  end
148
150
 
@@ -421,18 +423,37 @@ module Guard
421
423
  @callbacks << { :events => events, :listener => listener }
422
424
  end
423
425
 
424
- # Ignore certain paths globally.
426
+ # @deprecated Ignore certain paths globally.
425
427
  #
426
428
  # @example Ignore some paths
427
429
  # ignore_paths ".git", ".svn"
428
430
  #
429
431
  # @param [Array] paths the list of paths to ignore
430
432
  #
431
- # @see Guard::Listener
432
- #
433
433
  def ignore_paths(*paths)
434
- UI.info "Ignoring paths: #{ paths.join(', ') }"
435
- ::Guard.listener.ignore_paths.push(*paths)
434
+ UI.deprecation(IGNORE_PATHS_DEPRECATION)
435
+ end
436
+
437
+ # Ignore certain patterns paths globally.
438
+ #
439
+ # @example Ignore some paths
440
+ # ignore %r{^ignored/path/}, /man/
441
+ #
442
+ # @param [Regexp] regexp a pattern for ignoring paths
443
+ #
444
+ def ignore(*regexps)
445
+ ::Guard.listener = ::Guard.listener.ignore(*regexps)
446
+ end
447
+
448
+ # Filter certain patterns paths globally.
449
+ #
450
+ # @example Filter some files
451
+ # ignore /\.txt$/, /.*\.zip/
452
+ #
453
+ # @param [Regexp] regexp a pattern for filtering paths
454
+ #
455
+ def filter(*regexps)
456
+ ::Guard.listener = ::Guard.listener.filter(*regexps)
436
457
  end
437
458
 
438
459
  end
@@ -2,7 +2,7 @@ require 'guard/dsl'
2
2
 
3
3
  module Guard
4
4
 
5
- autoload :UI, 'guard/ui'
5
+ autoload :UI, 'guard/ui'
6
6
 
7
7
  # The DslDescriber overrides methods to create an internal structure
8
8
  # of the Guardfile that is used in some inspection utility methods
data/lib/guard/group.rb CHANGED
@@ -20,7 +20,7 @@ module Guard
20
20
 
21
21
  attr_accessor :name, :options
22
22
 
23
- # Initialize a Group.
23
+ # Initializes a Group.
24
24
  #
25
25
  # @param [String] name the name of the group
26
26
  # @param [Hash] options the group options
data/lib/guard/guard.rb CHANGED
@@ -38,7 +38,7 @@ module Guard
38
38
 
39
39
  attr_accessor :watchers, :options, :group
40
40
 
41
- # Initialize a Guard.
41
+ # Initializes a Guard.
42
42
  #
43
43
  # @param [Array<Guard::Watcher>] watchers the Guard file watchers
44
44
  # @param [Hash] options the custom Guard options
@@ -106,24 +106,58 @@ module Guard
106
106
  def run_all
107
107
  end
108
108
 
109
+ # Default behavious on file(s) changes that the Guard watches.
110
+ #
111
+ # @param [Array<String>] paths the changes files or paths
112
+ # @raise [:task_has_failed] when run_on_change has failed
113
+ # @return [Object] the task result
114
+ #
115
+ def run_on_changes(paths)
116
+ raise NotImplementedError
117
+ end
118
+
119
+ # Called on file(s) additions that the Guard watches.
120
+ #
121
+ # @param [Array<String>] paths the changes files or paths
122
+ # @raise [:task_has_failed] when run_on_change has failed
123
+ # @return [Object] the task result
124
+ #
125
+ def run_on_addtions(paths)
126
+ run_on_changes(paths)
127
+ end
128
+
109
129
  # Called on file(s) modifications that the Guard watches.
110
130
  #
111
131
  # @param [Array<String>] paths the changes files or paths
112
132
  # @raise [:task_has_failed] when run_on_change has failed
113
133
  # @return [Object] the task result
114
134
  #
115
- def run_on_change(paths)
135
+ def run_on_modifications(paths)
136
+ run_on_changes(paths)
116
137
  end
117
138
 
118
- # Called on file(s) deletions that the Guard watches.
139
+ # Called on file(s) removals that the Guard watches.
119
140
  #
120
- # @param [Array<String>] paths the deleted files or paths
141
+ # @param [Array<String>] paths the changes files or paths
121
142
  # @raise [:task_has_failed] when run_on_change has failed
122
143
  # @return [Object] the task result
123
144
  #
124
- def run_on_deletion(paths)
145
+ def run_on_removals(paths)
146
+ run_on_changes(paths)
125
147
  end
126
148
 
149
+ # @deprecated Use #run_on_modifications or #run_on_addtions instead
150
+ #
151
+ # def run_on_change(paths)
152
+ # raise NotImplementedError
153
+ # end
154
+
155
+ # @deprecated Use #run_on_removals instead
156
+ #
157
+ # def run_on_deletion(paths)
158
+ # raise NotImplementedError
159
+ # end
160
+
127
161
  end
128
162
 
129
163
  end
@@ -0,0 +1,70 @@
1
+ module Guard
2
+
3
+ # The Guardfile is responsible for generating the Guardfile
4
+ # and adding guards' template into it.
5
+ #
6
+ # @see Guard::CLI
7
+ #
8
+ class Guardfile
9
+
10
+ class << self
11
+
12
+ # Creates the initial Guardfile template when it does not
13
+ # already exist.
14
+ #
15
+ # @see Guard::CLI.init
16
+ #
17
+ # @param [Hash] options The options for creating a Guardfile
18
+ # @option options [Boolean] :abort_on_existence Whether to abort or not when a Guardfile already exists
19
+ #
20
+ def create_guardfile(options = {})
21
+ if !File.exist?('Guardfile')
22
+ ::Guard::UI.info "Writing new Guardfile to #{ Dir.pwd }/Guardfile"
23
+ FileUtils.cp(GUARDFILE_TEMPLATE, 'Guardfile')
24
+ elsif options[:abort_on_existence]
25
+ ::Guard::UI.error "Guardfile already exists at #{ Dir.pwd }/Guardfile"
26
+ abort
27
+ end
28
+ end
29
+
30
+ # Adds the Guardfile template of a Guard implementation
31
+ # to an existing Guardfile.
32
+ #
33
+ # @see Guard::CLI.init
34
+ #
35
+ # @param [String] guard_name the name of the Guard or template to initialize
36
+ #
37
+ def initialize_template(guard_name)
38
+ guard_class = ::Guard.get_guard_class(guard_name, true)
39
+
40
+ if guard_class
41
+ guard_class.init(guard_name)
42
+ elsif File.exist?(File.join(HOME_TEMPLATES, guard_name))
43
+ content = File.read('Guardfile')
44
+ template = File.read(File.join(HOME_TEMPLATES, guard_name))
45
+
46
+ File.open('Guardfile', 'wb') do |f|
47
+ f.puts(content)
48
+ f.puts('')
49
+ f.puts(template)
50
+ end
51
+
52
+ ::Guard::UI.info "#{ guard_name } template added to Guardfile, feel free to edit it"
53
+ else
54
+ const_name = guard_name.downcase.gsub('-', '')
55
+ UI.error "Could not load 'guard/#{ guard_name.downcase }' or '~/.guard/templates/#{ guard_name.downcase }' or find class Guard::#{ const_name.capitalize }"
56
+ end
57
+ end
58
+
59
+ # Adds the templates of all installed Guard implementations
60
+ # to an existing Guardfile.
61
+ #
62
+ # @see Guard::CLI.init
63
+ #
64
+ def initialize_all_templates
65
+ ::Guard.guard_gem_names.each { |g| initialize_template(g) }
66
+ end
67
+
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,179 @@
1
+ module Guard
2
+
3
+ # The runner is responsible for running all methods defined on each guards.
4
+ #
5
+ class Runner
6
+
7
+ # Deprecation message for the `run_on_change` method
8
+ RUN_ON_CHANGE_DEPRECATION = <<-EOS.gsub(/^\s*/, '')
9
+ Starting with Guard v1.1 the use of the 'run_on_change' method in the '%s' guard is deprecated.
10
+
11
+ Please consider replacing that method-call with 'run_on_changes' if the type of change
12
+ is not important for your usecase or using either 'run_on_modifications' or 'run_on_addtions'
13
+ based on the type of the changes you want to handle.
14
+
15
+ For more information on how to update existing guards, please head over to:
16
+ https://github.com/guard/guard/wiki/Upgrade-guide-for-existing-guards-to-Guard-v1.1
17
+ EOS
18
+
19
+ # Deprecation message for the `run_on_deletion` method
20
+ RUN_ON_DELETION_DEPRECATION = <<-EOS.gsub(/^\s*/, '')
21
+ Starting with Guard v1.1 the use of the 'run_on_deletion' method in the '%s' guard is deprecated.
22
+
23
+ Please consider replacing that method-call with 'run_on_removals' for future proofing your code.
24
+
25
+ For more information on how to update existing guards, please head over to:
26
+ https://github.com/guard/guard/wiki/Upgrade-guide-for-existing-guards-to-Guard-v1.1
27
+ EOS
28
+
29
+ # Displays a warning for each deprecated-method used is any registered guard.
30
+ #
31
+ def deprecation_warning
32
+ ::Guard.guards.each do |guard|
33
+ UI.deprecation(RUN_ON_CHANGE_DEPRECATION % guard.class.name) if guard.respond_to?(:run_on_change)
34
+ UI.deprecation(RUN_ON_DELETION_DEPRECATION % guard.class.name) if guard.respond_to?(:run_on_deletion)
35
+ end
36
+ end
37
+
38
+ # Runs a Guard-task on all registered guards.
39
+ #
40
+ # @param [Symbol] task the task to run
41
+ # @param [Hash] scope either the guard or the group to run the task on
42
+ #
43
+ # @see self.run_supervised_task
44
+ #
45
+ def run(task, scopes = {})
46
+ scoped_guards(scopes) do |guard|
47
+ run_supervised_task(guard, task)
48
+ end
49
+ end
50
+
51
+ # Runs the appropriate tasks on all registered guards
52
+ # based on the passed changes.
53
+ #
54
+ # @param [Array<String>] modified the modified paths.
55
+ # @param [Array<String>] added the added paths.
56
+ # @param [Array<String>] removed the removed paths.
57
+ #
58
+ def run_on_changes(modified, added, removed)
59
+ scoped_guards do |guard|
60
+ modified_paths = Watcher.match_files(guard, modified)
61
+ added_paths = Watcher.match_files(guard, added)
62
+ removed_paths = Watcher.match_files(guard, removed)
63
+
64
+ if !modified_paths.empty? || !added_paths.empty? || !removed_paths.empty?
65
+ UI.clear
66
+
67
+ unless modified_paths.empty?
68
+ run_first_task_found(guard, [:run_on_modifications, :run_on_change], modified_paths)
69
+ end
70
+ unless added_paths.empty?
71
+ run_first_task_found(guard, [:run_on_addtions, :run_on_change], added_paths)
72
+ end
73
+ unless removed_paths.empty?
74
+ run_first_task_found(guard, [:run_on_removals, :run_on_deletion], removed_paths)
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ # Run a Guard task, but remove the Guard when his work leads to a system failure.
81
+ #
82
+ # When the Group has `:halt_on_fail` disabled, we've to catch `:task_has_failed`
83
+ # here in order to avoid an uncaught throw error.
84
+ #
85
+ # @param [Guard::Guard] guard the Guard to execute
86
+ # @param [Symbol] task the task to run
87
+ # @param [Array] args the arguments for the task
88
+ # @raise [:task_has_failed] when task has failed
89
+ #
90
+ def run_supervised_task(guard, task, *args)
91
+ ::Guard.within_preserved_state do
92
+ begin
93
+ catch Runner.stopping_symbol_for(guard) do
94
+ guard.hook("#{ task }_begin", *args)
95
+ result = guard.send(task, *args)
96
+ guard.hook("#{ task }_end", result)
97
+ result
98
+ end
99
+
100
+ rescue NotImplementedError => ex
101
+ raise ex
102
+ rescue Exception => ex
103
+ UI.error("#{ guard.class.name } failed to achieve its <#{ task.to_s }>, exception was:" +
104
+ "\n#{ ex.class }: #{ ex.message }\n#{ ex.backtrace.join("\n") }")
105
+
106
+ ::Guard.guards.delete guard
107
+ UI.info("\n#{ guard.class.name } has just been fired")
108
+
109
+ ex
110
+ end
111
+ end
112
+ end
113
+
114
+ # Returns the symbol that has to be caught when running a supervised task.
115
+ #
116
+ # @note If a Guard group is being run and it has the `:halt_on_fail`
117
+ # option set, this method returns :no_catch as it will be caught at the
118
+ # group level.
119
+ # @see .scoped_guards
120
+ #
121
+ # @param [Guard::Guard] guard the Guard to execute
122
+ #
123
+ # @return [Symbol] the symbol to catch
124
+ #
125
+ def self.stopping_symbol_for(guard)
126
+ return :task_has_failed if guard.group.class != Symbol
127
+
128
+ group = ::Guard.groups(guard.group)
129
+ group.options[:halt_on_fail] ? :no_catch : :task_has_failed
130
+ end
131
+
132
+ private
133
+
134
+ # Tries to run the first implemented task by a given guard
135
+ # from a collection of tasks.
136
+ #
137
+ # @param [Guard::Guard] guard the guard to run the found task on
138
+ # @param [Array<Symbol>] tasks the tasks to run the first among
139
+ # @param [Object] task_param the param to pass to each task
140
+ #
141
+ def run_first_task_found(guard, tasks, task_param)
142
+ enum = tasks.to_enum
143
+
144
+ begin
145
+ task = enum.next
146
+ UI.debug "Trying to run #{ guard.class.name }##{ task.to_s } with #{ task_param.inspect }"
147
+ run_supervised_task(guard, task, task_param)
148
+ rescue StopIteration
149
+ # Do nothing
150
+ rescue NotImplementedError
151
+ retry
152
+ end
153
+ end
154
+
155
+ # Loop through all groups and run the given task for each Guard.
156
+ #
157
+ # Stop the task run for the all Guards within a group if one Guard
158
+ # throws `:task_has_failed`.
159
+ #
160
+ # @param [Hash] scope an hash with a guard or a group scope
161
+ # @yield the task to run
162
+ #
163
+ def scoped_guards(scopes = {})
164
+ if guard = scopes[:guard]
165
+ yield(guard)
166
+ else
167
+ groups = scopes[:group] ? [scopes[:group]] : ::Guard.groups
168
+ groups.each do |group|
169
+ catch :task_has_failed do
170
+ ::Guard.guards(:group => group.name).each do |guard|
171
+ yield(guard)
172
+ end
173
+ end
174
+ end
175
+ end
176
+ end
177
+
178
+ end
179
+ end