guard 2.7.0 → 2.7.1
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.
- checksums.yaml +4 -4
- data/bin/guard +7 -2
- data/lib/guard.rb +16 -5
- data/lib/guard.rb.orig +210 -0
- data/lib/guard/aruba_adapter.rb +59 -0
- data/lib/guard/cli.rb +1 -1
- data/lib/guard/commander.rb +3 -1
- data/lib/guard/commands/scope.rb +1 -1
- data/lib/guard/deprecated_methods.rb +16 -0
- data/lib/guard/deprecator.rb +15 -0
- data/lib/guard/dsl_describer.rb +0 -2
- data/lib/guard/guardfile/evaluator.rb +2 -2
- data/lib/guard/interactor.rb.orig +6 -1
- data/lib/guard/jobs/pry_wrapper.rb +1 -0
- data/lib/guard/jobs/stdin.rb.orig +46 -0
- data/lib/guard/notifiers/emacs.rb +3 -8
- data/lib/guard/notifiers/emacs.rb.orig +103 -0
- data/lib/guard/plugin_util.rb +5 -3
- data/lib/guard/runner.rb +34 -31
- data/lib/guard/setuper.rb +24 -11
- data/lib/guard/setuper.rb.orig +56 -20
- data/lib/guard/sheller.rb +47 -11
- data/lib/guard/sheller.rb.orig +107 -0
- data/lib/guard/tags +182 -107
- data/lib/guard/terminal.rb +11 -0
- data/lib/guard/terminal.rb.orig +0 -0
- data/lib/guard/ui.rb +21 -2
- data/lib/guard/ui.rb.orig +11 -1
- data/lib/guard/version.rb +1 -1
- data/lib/guard/version.rb.orig +1 -1
- data/lib/guard/watcher.rb.orig +119 -0
- metadata +10 -9
- data/lib/guard/cli.rb.orig +0 -215
- data/lib/guard/dsl_describer.rb.orig +0 -184
- data/lib/guard/guard.rb.orig +0 -42
- data/lib/guard/guardfile/evaluator.rb.orig +0 -275
- data/lib/guard/jobs/pry_wrapper.rb.orig +0 -293
- data/lib/guard/plugin_util.rb.orig +0 -178
- data/lib/guard/runner.rb.orig +0 -200
@@ -2,6 +2,7 @@ require "guard/ui"
|
|
2
2
|
|
3
3
|
require "guard/jobs/sleep"
|
4
4
|
require "guard/jobs/pry_wrapper"
|
5
|
+
require "guard/jobs/stdin"
|
5
6
|
|
6
7
|
module Guard
|
7
8
|
class Interactor
|
@@ -12,7 +13,11 @@ module Guard
|
|
12
13
|
def initialize(no_interaction = false)
|
13
14
|
@interactive = !no_interaction && self.class.enabled?
|
14
15
|
|
15
|
-
|
16
|
+
|
17
|
+
# TODO: restore
|
18
|
+
# job_klass = interactive? ? Jobs::PryWrapper : Jobs::Sleep
|
19
|
+
job_klass = Jobs::StdinJob
|
20
|
+
|
16
21
|
@idle_job = job_klass.new(self.class.options)
|
17
22
|
end
|
18
23
|
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require "guard/jobs/base"
|
2
|
+
|
3
|
+
module Guard
|
4
|
+
module Jobs
|
5
|
+
class StdinJob
|
6
|
+
def initialize(options)
|
7
|
+
@mode = :stopped
|
8
|
+
@sleeping = false
|
9
|
+
end
|
10
|
+
|
11
|
+
def foreground
|
12
|
+
output "Guard is idle" # needed for child-process cucumber tests
|
13
|
+
|
14
|
+
line = $stdin.readline.chomp
|
15
|
+
return :exit if line == "exit"
|
16
|
+
|
17
|
+
m = /^sleep (?<seconds>\d+)$/.match(line)
|
18
|
+
return @mode unless m
|
19
|
+
|
20
|
+
seconds = Integer(m[:seconds][/\d+/])
|
21
|
+
@sleeping = true
|
22
|
+
sleep seconds
|
23
|
+
@sleeping = false
|
24
|
+
@mode
|
25
|
+
rescue EOFError, Interrupt
|
26
|
+
@sleeping = false
|
27
|
+
:exit
|
28
|
+
end
|
29
|
+
|
30
|
+
def background
|
31
|
+
Thread.main.wakeup if @sleeping
|
32
|
+
end
|
33
|
+
|
34
|
+
def handle_interrupt
|
35
|
+
@mode = :exit
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def output(text)
|
41
|
+
$stdout.puts text
|
42
|
+
$stdout.flush
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -18,18 +18,13 @@ module Guard
|
|
18
18
|
}
|
19
19
|
|
20
20
|
def self.available?(opts = {})
|
21
|
-
|
22
|
-
end
|
21
|
+
return false unless super
|
23
22
|
|
24
|
-
# @private
|
25
|
-
#
|
26
|
-
# @return [Boolean] whether or not the emacs client is available
|
27
|
-
#
|
28
|
-
def self._emacs_client_available?(opts)
|
29
23
|
client_name = opts.fetch(:client, DEFAULTS[:client])
|
30
24
|
cmd = "#{client_name} --eval '1' 2> #{DEV_NULL} || echo 'N/A'"
|
31
25
|
stdout = Sheller.stdout(cmd)
|
32
|
-
|
26
|
+
return false if stdout.nil?
|
27
|
+
!%w(N/A 'N/A').include?(stdout.chomp)
|
33
28
|
end
|
34
29
|
|
35
30
|
# Shows a system notification.
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require "guard/notifiers/base"
|
2
|
+
|
3
|
+
module Guard
|
4
|
+
module Notifier
|
5
|
+
# Send a notification to Emacs with emacsclient
|
6
|
+
# (http://www.emacswiki.org/emacs/EmacsClient).
|
7
|
+
#
|
8
|
+
# @example Add the `:emacs` notifier to your `Guardfile`
|
9
|
+
# notification :emacs
|
10
|
+
#
|
11
|
+
class Emacs < Base
|
12
|
+
DEFAULTS = {
|
13
|
+
client: "emacsclient",
|
14
|
+
success: "ForestGreen",
|
15
|
+
failed: "Firebrick",
|
16
|
+
default: "Black",
|
17
|
+
fontcolor: "White",
|
18
|
+
}
|
19
|
+
|
20
|
+
def self.available?(opts = {})
|
21
|
+
super && _emacs_client_available?(opts)
|
22
|
+
end
|
23
|
+
|
24
|
+
# @private
|
25
|
+
#
|
26
|
+
# @return [Boolean] whether or not the emacs client is available
|
27
|
+
#
|
28
|
+
def self._emacs_client_available?(opts)
|
29
|
+
client_name = opts.fetch(:client, DEFAULTS[:client])
|
30
|
+
cmd = "#{client_name} --eval '1' 2> #{DEV_NULL} || echo 'N/A'"
|
31
|
+
stdout = Sheller.stdout(cmd)
|
32
|
+
!%w(N/A 'N/A').include?(stdout.chomp!)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Shows a system notification.
|
36
|
+
#
|
37
|
+
# @param [String] type the notification type. Either 'success',
|
38
|
+
# 'pending', 'failed' or 'notify'
|
39
|
+
# @param [String] title the notification title
|
40
|
+
# @param [String] message the notification message body
|
41
|
+
# @param [String] image the path to the notification image
|
42
|
+
# @param [Hash] opts additional notification library options
|
43
|
+
# @option opts [String] success the color to use for success
|
44
|
+
# notifications (default is 'ForestGreen')
|
45
|
+
# @option opts [String] failed the color to use for failure
|
46
|
+
# notifications (default is 'Firebrick')
|
47
|
+
# @option opts [String] pending the color to use for pending
|
48
|
+
# notifications
|
49
|
+
# @option opts [String] default the default color to use (default is
|
50
|
+
# 'Black')
|
51
|
+
# @option opts [String] client the client to use for notification
|
52
|
+
# (default is 'emacsclient')
|
53
|
+
# @option opts [String, Integer] priority specify an int or named key
|
54
|
+
# (default is 0)
|
55
|
+
#
|
56
|
+
def notify(message, opts = {})
|
57
|
+
super
|
58
|
+
|
59
|
+
opts = DEFAULTS.merge(opts)
|
60
|
+
color = emacs_color(opts[:type], opts)
|
61
|
+
fontcolor = emacs_color(:fontcolor, opts)
|
62
|
+
elisp = <<-EOF.gsub(/\s+/, " ").strip
|
63
|
+
(set-face-attribute 'mode-line nil
|
64
|
+
:background "#{color}"
|
65
|
+
:foreground "#{fontcolor}")
|
66
|
+
EOF
|
67
|
+
|
68
|
+
_run_cmd(opts[:client], "--eval", elisp)
|
69
|
+
end
|
70
|
+
|
71
|
+
# Get the Emacs color for the notification type.
|
72
|
+
# You can configure your own color by overwrite the defaults.
|
73
|
+
#
|
74
|
+
# @param [String] type the notification type
|
75
|
+
# @param [Hash] options aditional notification options
|
76
|
+
#
|
77
|
+
# @option options [String] success the color to use for success
|
78
|
+
# notifications (default is 'ForestGreen')
|
79
|
+
#
|
80
|
+
# @option options [String] failed the color to use for failure
|
81
|
+
# notifications (default is 'Firebrick')
|
82
|
+
#
|
83
|
+
# @option options [String] pending the color to use for pending
|
84
|
+
# notifications
|
85
|
+
#
|
86
|
+
# @option options [String] default the default color to use (default is
|
87
|
+
# 'Black')
|
88
|
+
#
|
89
|
+
# @return [String] the name of the emacs color
|
90
|
+
#
|
91
|
+
def emacs_color(type, options = {})
|
92
|
+
default = options.fetch(:default, DEFAULTS[:default])
|
93
|
+
options.fetch(type.to_sym, default)
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def _run_cmd(cmd, *args)
|
99
|
+
Sheller.run(cmd, *args)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
data/lib/guard/plugin_util.rb
CHANGED
@@ -69,10 +69,12 @@ module Guard
|
|
69
69
|
# https://github.com/guard/guard/wiki/Upgrading-to-Guard-2.0
|
70
70
|
#
|
71
71
|
def initialize_plugin(options)
|
72
|
-
|
73
|
-
|
72
|
+
klass = plugin_class
|
73
|
+
fail "Could not load class: #{_constant_name.inspect}" unless klass
|
74
|
+
if klass.superclass.to_s == "Guard::Guard"
|
75
|
+
klass.new(options.delete(:watchers), options)
|
74
76
|
else
|
75
|
-
|
77
|
+
klass.new(options)
|
76
78
|
end
|
77
79
|
end
|
78
80
|
|
data/lib/guard/runner.rb
CHANGED
@@ -14,12 +14,10 @@ module Guard
|
|
14
14
|
# @param [Hash] scopes either the Guard plugin or the group to run the task
|
15
15
|
# on
|
16
16
|
#
|
17
|
-
|
18
|
-
#
|
19
|
-
def run(task, scope = {})
|
17
|
+
def run(task, scope_hash = {})
|
20
18
|
Lumberjack.unit_of_work do
|
21
|
-
_scoped_plugins(
|
22
|
-
|
19
|
+
_scoped_plugins(scope_hash || {}) do |plugin|
|
20
|
+
_supervise(plugin, task) if plugin.respond_to?(task)
|
23
21
|
end
|
24
22
|
end
|
25
23
|
end
|
@@ -47,15 +45,16 @@ module Guard
|
|
47
45
|
|
48
46
|
::Guard::UI.clearable
|
49
47
|
|
50
|
-
_scoped_plugins do |
|
48
|
+
_scoped_plugins do |plugin|
|
51
49
|
::Guard::UI.clear
|
52
50
|
|
53
51
|
types.each do |tasks, unmatched_paths|
|
54
|
-
|
55
|
-
|
52
|
+
next if unmatched_paths.empty?
|
53
|
+
match_result = ::Guard::Watcher.match_files(plugin, unmatched_paths)
|
54
|
+
next if match_result.empty?
|
56
55
|
|
57
|
-
next unless (task = tasks.detect { |meth|
|
58
|
-
|
56
|
+
next unless (task = tasks.detect { |meth| plugin.respond_to?(meth) })
|
57
|
+
_supervise(plugin, task, match_result)
|
59
58
|
end
|
60
59
|
end
|
61
60
|
end
|
@@ -71,24 +70,24 @@ module Guard
|
|
71
70
|
# @param [Array] args the arguments for the task
|
72
71
|
# @raise [:task_has_failed] when task has failed
|
73
72
|
#
|
74
|
-
def
|
75
|
-
catch self.class.stopping_symbol_for(
|
76
|
-
|
73
|
+
def _supervise(plugin, task, *args)
|
74
|
+
catch self.class.stopping_symbol_for(plugin) do
|
75
|
+
plugin.hook("#{ task }_begin", *args)
|
77
76
|
begin
|
78
|
-
result =
|
77
|
+
result = plugin.send(task, *args)
|
79
78
|
rescue Interrupt
|
80
79
|
throw(:task_has_failed)
|
81
80
|
end
|
82
|
-
|
81
|
+
plugin.hook("#{ task }_end", result)
|
83
82
|
result
|
84
83
|
end
|
85
84
|
rescue ScriptError, StandardError, RuntimeError
|
86
|
-
::Guard::UI.error("#{
|
85
|
+
::Guard::UI.error("#{ plugin.class.name } failed to achieve its"\
|
87
86
|
" <#{ task }>, exception was:" \
|
88
87
|
"\n#{ $!.class }: #{ $!.message }" \
|
89
88
|
"\n#{ $!.backtrace.join("\n") }")
|
90
|
-
::Guard.
|
91
|
-
::Guard::UI.info("\n#{
|
89
|
+
::Guard.remove_plugin(plugin)
|
90
|
+
::Guard::UI.info("\n#{ plugin.class.name } has just been fired")
|
92
91
|
$!
|
93
92
|
end
|
94
93
|
|
@@ -121,12 +120,14 @@ module Guard
|
|
121
120
|
# @yield the task to run
|
122
121
|
#
|
123
122
|
def _scoped_plugins(scopes = {})
|
123
|
+
fail "NO PLUGIN SCOPE" if scopes.nil?
|
124
124
|
if plugins = _current_plugins_scope(scopes)
|
125
125
|
plugins.each do |guard|
|
126
126
|
yield(guard)
|
127
127
|
end
|
128
128
|
else
|
129
129
|
_current_groups_scope(scopes).each do |group|
|
130
|
+
fail "Invalid group: #{group.inspect}" unless group.respond_to?(:name)
|
130
131
|
current_plugin = nil
|
131
132
|
block_return = catch :task_has_failed do
|
132
133
|
::Guard.plugins(group: group.name).each do |guard|
|
@@ -151,13 +152,9 @@ module Guard
|
|
151
152
|
# @return [Array<Guard::Plugin>] the plugins to scope to
|
152
153
|
#
|
153
154
|
def _current_plugins_scope(scope)
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
end
|
158
|
-
else
|
159
|
-
nil
|
160
|
-
end
|
155
|
+
return nil unless (plugins = _find_non_empty_plugins_scope(scope))
|
156
|
+
|
157
|
+
Array(plugins).map { |plugin| _instantiate(:plugin, plugin) }
|
161
158
|
end
|
162
159
|
|
163
160
|
# Returns the current groups scope.
|
@@ -168,9 +165,14 @@ module Guard
|
|
168
165
|
# @return [Array<Guard::Group>] the groups to scope to
|
169
166
|
#
|
170
167
|
def _current_groups_scope(scope)
|
171
|
-
|
172
|
-
|
173
|
-
|
168
|
+
found = _find_non_empty_groups_scope(scope)
|
169
|
+
groups = Array(found).map { |group| _instantiate(:group, group) }
|
170
|
+
return groups if groups.any? { |g| g.name == :common }
|
171
|
+
([_instantiate(:group, :common)] + Array(found)).compact
|
172
|
+
end
|
173
|
+
|
174
|
+
def _instantiate(meth, obj)
|
175
|
+
(obj.is_a?(Symbol) || obj.is_a?(String)) ? ::Guard.send(meth, obj) : obj
|
174
176
|
end
|
175
177
|
|
176
178
|
# Find the first non empty element in the given possibilities
|
@@ -178,16 +180,17 @@ module Guard
|
|
178
180
|
def _find_non_empty_scope(type, local_scope, *additional_possibilities)
|
179
181
|
found = [
|
180
182
|
local_scope[:"#{type}s"],
|
181
|
-
local_scope[type.to_sym],
|
183
|
+
[local_scope[type.to_sym]],
|
182
184
|
::Guard.scope[:"#{type}s"],
|
183
185
|
additional_possibilities.flatten
|
184
|
-
]
|
185
|
-
found
|
186
|
+
]
|
187
|
+
found.compact.detect { |a| !Array(a).compact.empty? }
|
186
188
|
end
|
187
189
|
|
188
190
|
# Find the first non empty plugins scope
|
189
191
|
#
|
190
192
|
def _find_non_empty_plugins_scope(scope)
|
193
|
+
fail "NO PLUGIN SCOPE" if scope.nil?
|
191
194
|
_find_non_empty_scope(:plugin, scope)
|
192
195
|
end
|
193
196
|
|
data/lib/guard/setuper.rb
CHANGED
@@ -51,7 +51,7 @@ module Guard
|
|
51
51
|
@runner = ::Guard::Runner.new
|
52
52
|
@watchdirs = _setup_watchdirs
|
53
53
|
|
54
|
-
::Guard::UI.
|
54
|
+
::Guard::UI.setup(options)
|
55
55
|
|
56
56
|
_setup_debug if options[:debug]
|
57
57
|
@listener = _setup_listener
|
@@ -62,7 +62,7 @@ module Guard
|
|
62
62
|
self
|
63
63
|
end
|
64
64
|
|
65
|
-
attr_reader :options, :
|
65
|
+
attr_reader :options, :interactor
|
66
66
|
|
67
67
|
# Used only by tests (for all I know...)
|
68
68
|
def clear_options
|
@@ -127,12 +127,11 @@ module Guard
|
|
127
127
|
def setup_scope(scope = {})
|
128
128
|
# TODO: there should be a special Scope class instead
|
129
129
|
scope = _prepare_scope(scope)
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
end
|
130
|
+
|
131
|
+
::Guard.scope = {
|
132
|
+
groups: scope[:groups].map { |item| ::Guard.add_group(item) },
|
133
|
+
plugins: scope[:plugins].map { |item| ::Guard.plugin(item) },
|
134
|
+
}
|
136
135
|
end
|
137
136
|
|
138
137
|
# Evaluates the Guardfile content. It displays an error message if no
|
@@ -143,7 +142,7 @@ module Guard
|
|
143
142
|
def evaluate_guardfile
|
144
143
|
evaluator.evaluate_guardfile
|
145
144
|
msg = "No plugins found in Guardfile, please add at least one."
|
146
|
-
::Guard::UI.error msg unless
|
145
|
+
::Guard::UI.error msg unless _pluginless_guardfile?
|
147
146
|
end
|
148
147
|
|
149
148
|
# Asynchronously trigger changes
|
@@ -343,16 +342,30 @@ module Guard
|
|
343
342
|
end
|
344
343
|
|
345
344
|
def _prepare_scope(scope)
|
345
|
+
fail "Guard::setup() not called!" if options.nil?
|
346
346
|
plugins = Array(options[:plugin])
|
347
347
|
plugins = Array(scope[:plugins] || scope[:plugin]) if plugins.empty?
|
348
348
|
|
349
|
+
# Convert objects to names
|
350
|
+
plugins.map! { |p| p.respond_to?(:name) ? p.name : p }
|
351
|
+
|
349
352
|
groups = Array(options[:group])
|
350
353
|
groups = Array(scope[:groups] || scope[:group]) if groups.empty?
|
351
354
|
|
355
|
+
# Convert objects to names
|
356
|
+
groups.map! { |g| g.respond_to?(:name) ? g.name : g }
|
357
|
+
|
352
358
|
{ plugins: plugins, groups: groups }
|
353
359
|
end
|
354
360
|
|
355
|
-
def
|
361
|
+
def _pluginless_guardfile?
|
362
|
+
# no Reevaluator means there was no Guardfile configured that could be
|
363
|
+
# reevaluated, so we don't have a pluginless guardfile, because we don't
|
364
|
+
# have a Guardfile to begin with...
|
365
|
+
#
|
366
|
+
# But, if we have a Guardfile, we'll at least have the built-in
|
367
|
+
# Reevaluator, so the following will work:
|
368
|
+
|
356
369
|
plugins.map(&:name) != ["reevaluator"]
|
357
370
|
end
|
358
371
|
|
@@ -365,7 +378,7 @@ module Guard
|
|
365
378
|
@watchdirs = nil
|
366
379
|
@listener = nil
|
367
380
|
@interactor = nil
|
368
|
-
|
381
|
+
@scope = nil
|
369
382
|
end
|
370
383
|
end
|
371
384
|
end
|
data/lib/guard/setuper.rb.orig
CHANGED
@@ -38,8 +38,18 @@ module Guard
|
|
38
38
|
#
|
39
39
|
# @return [Guard] the Guard singleton
|
40
40
|
#
|
41
|
+
|
42
|
+
# TODO: this method has too many instance variables
|
43
|
+
# and some are mock and leak between tests,
|
44
|
+
# so ideally there should be a guard "instance"
|
45
|
+
# object that can be created anew between tests
|
41
46
|
def setup(opts = {})
|
42
|
-
|
47
|
+
reset_options(opts)
|
48
|
+
reset_evaluator(opts)
|
49
|
+
|
50
|
+
@queue = Queue.new
|
51
|
+
@runner = ::Guard::Runner.new
|
52
|
+
@watchdirs = _setup_watchdirs
|
43
53
|
|
44
54
|
::Guard::UI.clear(force: true)
|
45
55
|
|
@@ -52,7 +62,7 @@ module Guard
|
|
52
62
|
self
|
53
63
|
end
|
54
64
|
|
55
|
-
attr_reader :options, :
|
65
|
+
attr_reader :options, :interactor
|
56
66
|
|
57
67
|
# Used only by tests (for all I know...)
|
58
68
|
def clear_options
|
@@ -85,6 +95,16 @@ module Guard
|
|
85
95
|
::Guard.scope = { groups: [], plugins: [] }
|
86
96
|
end
|
87
97
|
|
98
|
+
# Used to merge CLI options with Setuper defaults
|
99
|
+
def reset_options(new_options)
|
100
|
+
@options = ::Guard::Options.new(new_options, DEFAULT_OPTIONS)
|
101
|
+
end
|
102
|
+
|
103
|
+
# TODO: code smell - too many reset_* methods
|
104
|
+
def reset_evaluator(new_options)
|
105
|
+
@evaluator = ::Guard::Guardfile::Evaluator.new(new_options)
|
106
|
+
end
|
107
|
+
|
88
108
|
def save_scope
|
89
109
|
# This actually replaces scope from command line,
|
90
110
|
# so scope set by 'scope' Pry command will be reset
|
@@ -107,12 +127,11 @@ module Guard
|
|
107
127
|
def setup_scope(scope = {})
|
108
128
|
# TODO: there should be a special Scope class instead
|
109
129
|
scope = _prepare_scope(scope)
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
end
|
130
|
+
|
131
|
+
::Guard.scope = {
|
132
|
+
groups: scope[:groups].map { |item| ::Guard.add_group(item) },
|
133
|
+
plugins: scope[:plugins].map { |item| ::Guard.plugin(item) },
|
134
|
+
}
|
116
135
|
end
|
117
136
|
|
118
137
|
# Evaluates the Guardfile content. It displays an error message if no
|
@@ -123,7 +142,7 @@ module Guard
|
|
123
142
|
def evaluate_guardfile
|
124
143
|
evaluator.evaluate_guardfile
|
125
144
|
msg = "No plugins found in Guardfile, please add at least one."
|
126
|
-
::Guard::UI.error msg unless
|
145
|
+
::Guard::UI.error msg unless _pluginless_guardfile?
|
127
146
|
end
|
128
147
|
|
129
148
|
# Asynchronously trigger changes
|
@@ -146,8 +165,7 @@ module Guard
|
|
146
165
|
! @queue.empty?
|
147
166
|
end
|
148
167
|
|
149
|
-
def add_builtin_plugins
|
150
|
-
guardfile = ::Guard.evaluator.guardfile_path
|
168
|
+
def add_builtin_plugins(guardfile)
|
151
169
|
return unless guardfile
|
152
170
|
|
153
171
|
pattern = _relative_pathname(guardfile).to_s
|
@@ -306,14 +324,6 @@ module Guard
|
|
306
324
|
end
|
307
325
|
end
|
308
326
|
|
309
|
-
def _init_options(opts)
|
310
|
-
@queue = Queue.new
|
311
|
-
@runner = ::Guard::Runner.new
|
312
|
-
@evaluator = ::Guard::Guardfile::Evaluator.new(opts)
|
313
|
-
@options = ::Guard::Options.new(opts, DEFAULT_OPTIONS)
|
314
|
-
@watchdirs = _setup_watchdirs
|
315
|
-
end
|
316
|
-
|
317
327
|
def _reset_all
|
318
328
|
reset_groups
|
319
329
|
reset_plugins
|
@@ -332,17 +342,43 @@ module Guard
|
|
332
342
|
end
|
333
343
|
|
334
344
|
def _prepare_scope(scope)
|
345
|
+
fail "Guard::setup() not called!" if options.nil?
|
335
346
|
plugins = Array(options[:plugin])
|
336
347
|
plugins = Array(scope[:plugins] || scope[:plugin]) if plugins.empty?
|
337
348
|
|
349
|
+
# Convert objects to names
|
350
|
+
plugins.map! { |p| p.respond_to?(:name) ? p.name : p }
|
351
|
+
|
338
352
|
groups = Array(options[:group])
|
339
353
|
groups = Array(scope[:groups] || scope[:group]) if groups.empty?
|
340
354
|
|
355
|
+
# Convert objects to names
|
356
|
+
groups.map! { |g| g.respond_to?(:name) ? g.name : g }
|
357
|
+
|
341
358
|
{ plugins: plugins, groups: groups }
|
342
359
|
end
|
343
360
|
|
344
|
-
def
|
361
|
+
def _pluginless_guardfile?
|
362
|
+
# no Reevaluator means there was no Guardfile configured that could be
|
363
|
+
# reevaluated, so we don't have a pluginless guardfile, because we don't
|
364
|
+
# have a Guardfile to begin with...
|
365
|
+
#
|
366
|
+
# But, if we have a Guardfile, we'll at least have the built-in
|
367
|
+
# Reevaluator, so the following will work:
|
368
|
+
|
345
369
|
plugins.map(&:name) != ["reevaluator"]
|
346
370
|
end
|
371
|
+
|
372
|
+
def _reset_for_tests
|
373
|
+
@options = nil
|
374
|
+
@queue = nil
|
375
|
+
@runner = nil
|
376
|
+
@evaluator = nil
|
377
|
+
@watchdirs = nil
|
378
|
+
@watchdirs = nil
|
379
|
+
@listener = nil
|
380
|
+
@interactor = nil
|
381
|
+
@scope = nil
|
382
|
+
end
|
347
383
|
end
|
348
384
|
end
|