guard 2.9.0 → 2.9.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/guard.rb +43 -160
- data/lib/guard/cli.rb +49 -17
- data/lib/guard/commander.rb +18 -17
- data/lib/guard/commands/all.rb +1 -2
- data/lib/guard/commands/change.rb +1 -2
- data/lib/guard/commands/reload.rb +1 -2
- data/lib/guard/commands/scope.rb +1 -2
- data/lib/guard/deprecated/evaluator.rb +34 -0
- data/lib/guard/deprecated/guard.rb +15 -3
- data/lib/guard/deprecated/watcher.rb +27 -0
- data/lib/guard/dsl.rb +58 -17
- data/lib/guard/dsl_describer.rb +55 -73
- data/lib/guard/guardfile.rb +1 -1
- data/lib/guard/guardfile/evaluator.rb +96 -158
- data/lib/guard/guardfile/generator.rb +45 -41
- data/lib/guard/interactor.rb +4 -2
- data/lib/guard/internals/groups.rb +40 -0
- data/lib/guard/internals/plugins.rb +51 -0
- data/lib/guard/internals/queue.rb +50 -0
- data/lib/guard/internals/scope.rb +110 -0
- data/lib/guard/internals/session.rb +135 -0
- data/lib/guard/internals/state.rb +33 -0
- data/lib/guard/jobs/pry_wrapper.rb +33 -32
- data/lib/guard/jobs/sleep.rb +3 -4
- data/lib/guard/notifier.rb +2 -0
- data/lib/guard/notifier/detected.rb.orig +83 -0
- data/lib/guard/plugin.rb +242 -6
- data/lib/guard/plugin_util.rb +19 -18
- data/lib/guard/reevaluator.rb +50 -10
- data/lib/guard/runner.rb +30 -108
- data/lib/guard/ui.rb +6 -24
- data/lib/guard/version.rb +1 -1
- data/lib/guard/watcher.rb +4 -12
- metadata +11 -6
- data/lib/guard/metadata.rb +0 -190
- data/lib/guard/plugin/base.rb +0 -183
- data/lib/guard/plugin/hooker.rb +0 -108
- data/lib/guard/session.rb +0 -5
data/lib/guard/commands/all.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# required for async_queue_add
|
2
2
|
require "pry"
|
3
3
|
|
4
|
-
# TODO: remove this dependency
|
5
4
|
require "guard/interactor"
|
6
5
|
require "guard"
|
7
6
|
|
@@ -23,7 +22,7 @@ module Guard
|
|
23
22
|
BANNER
|
24
23
|
|
25
24
|
def process(*entries)
|
26
|
-
scopes, unknown =
|
25
|
+
scopes, unknown = Interactor.convert_scope(entries)
|
27
26
|
|
28
27
|
unless unknown.empty?
|
29
28
|
output.puts "Unknown scopes: #{ unknown.join(", ") }"
|
@@ -1,6 +1,5 @@
|
|
1
1
|
require "pry"
|
2
2
|
|
3
|
-
# TODO: remove
|
4
3
|
require "guard"
|
5
4
|
|
6
5
|
module Guard
|
@@ -23,7 +22,7 @@ module Guard
|
|
23
22
|
return
|
24
23
|
end
|
25
24
|
|
26
|
-
|
25
|
+
Guard.async_queue_add(modified: files, added: [], removed: [])
|
27
26
|
end
|
28
27
|
end
|
29
28
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
require "pry"
|
2
2
|
|
3
|
-
# TODO: should not be necessary!
|
4
3
|
require "guard/interactor"
|
5
4
|
require "guard"
|
6
5
|
|
@@ -22,7 +21,7 @@ module Guard
|
|
22
21
|
BANNER
|
23
22
|
|
24
23
|
def process(*entries)
|
25
|
-
scopes, unknown =
|
24
|
+
scopes, unknown = Interactor.convert_scope(entries)
|
26
25
|
|
27
26
|
unless unknown.empty?
|
28
27
|
output.puts "Unknown scopes: #{ unknown.join(", ") }"
|
data/lib/guard/commands/scope.rb
CHANGED
@@ -0,0 +1,34 @@
|
|
1
|
+
require "guard/config"
|
2
|
+
fail "Deprecations disabled (strict mode)" if Guard::Config.new.strict?
|
3
|
+
|
4
|
+
require "guard/ui"
|
5
|
+
|
6
|
+
module Guard
|
7
|
+
module Deprecated
|
8
|
+
module Evaluator
|
9
|
+
def self.add_deprecated(klass)
|
10
|
+
klass.send(:include, self)
|
11
|
+
end
|
12
|
+
|
13
|
+
EVALUATE_GUARDFILE = <<-EOS.gsub(/^\s*/, "")
|
14
|
+
Starting with Guard 2.8.3 'Guard::Evaluator#evaluate_guardfile' is
|
15
|
+
deprecated in favor of '#evaluate'.
|
16
|
+
EOS
|
17
|
+
|
18
|
+
REEVALUATE_GUARDFILE = <<-EOS.gsub(/^\s*/, "")
|
19
|
+
Starting with Guard 2.8.3 'Guard::Evaluator#reevaluate_guardfile' is
|
20
|
+
deprecated in favor of '#reevaluate'.
|
21
|
+
EOS
|
22
|
+
|
23
|
+
def evaluate_guardfile
|
24
|
+
UI.deprecation(EVALUATE_GUARDFILE)
|
25
|
+
evaluate
|
26
|
+
end
|
27
|
+
|
28
|
+
def reevaluate_guardfile
|
29
|
+
UI.deprecation(REEVALUATE_GUARDFILE)
|
30
|
+
::Guard::Reevaluator.new.reevaluate
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -138,10 +138,9 @@ module Guard
|
|
138
138
|
EOS
|
139
139
|
|
140
140
|
def evaluator
|
141
|
-
# TODO: probably deprecate once it isn't used internally
|
142
|
-
# TODO: this will be changed to the following when scope is reworked
|
143
141
|
UI.deprecation(EVALUATOR)
|
144
|
-
::Guard
|
142
|
+
options = ::Guard.state.session.evaluator_options
|
143
|
+
::Guard::Guardfile::Evaluator.new(options)
|
145
144
|
end
|
146
145
|
|
147
146
|
RESET_EVALUATOR = <<-EOS.gsub(/^\s*/, "")
|
@@ -160,6 +159,19 @@ module Guard
|
|
160
159
|
UI.deprecation(RUNNER)
|
161
160
|
::Guard::Runner.new
|
162
161
|
end
|
162
|
+
|
163
|
+
EVALUATE_GUARDFILE = <<-EOS.gsub(/^\s*/, "")
|
164
|
+
Starting with Guard 2.8.2 this method shouldn't be used
|
165
|
+
EOS
|
166
|
+
|
167
|
+
def evaluate_guardfile
|
168
|
+
UI.deprecation(EVALUATE_GUARDFILE)
|
169
|
+
options = ::Guard.state.session.evaluator_options
|
170
|
+
evaluator = ::Guard::Guardfile::Evaluator.new(options)
|
171
|
+
evaluator.evaluate
|
172
|
+
msg = "No plugins found in Guardfile, please add at least one."
|
173
|
+
::Guard::UI.error msg if _pluginless_guardfile?
|
174
|
+
end
|
163
175
|
end
|
164
176
|
end
|
165
177
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require "guard/config"
|
2
|
+
fail "Deprecations disabled (strict mode)" if Guard::Config.new.strict?
|
3
|
+
|
4
|
+
module Guard
|
5
|
+
module Deprecated
|
6
|
+
module Watcher
|
7
|
+
def self.add_deprecated(dsl_klass)
|
8
|
+
dsl_klass.send(:extend, ClassMethods)
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
MATCH_GUARDFILE = <<-EOS.gsub(/^\s*/, "")
|
13
|
+
Starting with Guard 2.8.3 this method is deprecated.
|
14
|
+
EOS
|
15
|
+
|
16
|
+
def match_guardfile?(files)
|
17
|
+
require "guard/guardfile/evaluator"
|
18
|
+
UI.deprecation(MATCH_GUARDFILE)
|
19
|
+
options = ::Guard.state.session.evaluator_options
|
20
|
+
evaluator = ::Guard::Guardfile::Evaluator.new(options)
|
21
|
+
path = evaluator.guardfile_path
|
22
|
+
files.any? { |file| File.expand_path(file) == path }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/guard/dsl.rb
CHANGED
@@ -26,10 +26,10 @@ module Guard
|
|
26
26
|
# {Notifier} for more information about the supported libraries.
|
27
27
|
#
|
28
28
|
# A more advanced DSL use is the {#callback} keyword that allows you to
|
29
|
-
# execute arbitrary code before or after any of the {Plugin
|
30
|
-
# {Plugin
|
31
|
-
# {Plugin
|
32
|
-
# {Plugin
|
29
|
+
# execute arbitrary code before or after any of the {Plugin#start},
|
30
|
+
# {Plugin#stop}, {Plugin#reload}, {Plugin#run_all},
|
31
|
+
# {Plugin#run_on_changes}, {Plugin#run_on_additions},
|
32
|
+
# {Plugin#run_on_modifications} and {Plugin#run_on_removals}
|
33
33
|
# Guard plugins method.
|
34
34
|
# You can even insert more hooks inside these methods. Please [checkout the
|
35
35
|
# Wiki page](https://github.com/guard/guard/wiki/Hooks-and-callbacks) for
|
@@ -50,6 +50,10 @@ module Guard
|
|
50
50
|
class Dsl
|
51
51
|
Deprecated::Dsl.add_deprecated(self) unless Config.new.strict?
|
52
52
|
|
53
|
+
# Wrap exceptions during parsing Guardfile
|
54
|
+
class Error < RuntimeError
|
55
|
+
end
|
56
|
+
|
53
57
|
WARN_INVALID_LOG_LEVEL = "Invalid log level `%s` ignored. "\
|
54
58
|
"Please use either :debug, :info, :warn or :error."
|
55
59
|
|
@@ -88,9 +92,9 @@ module Guard
|
|
88
92
|
def interactor(options)
|
89
93
|
case options
|
90
94
|
when :off
|
91
|
-
|
95
|
+
Interactor.enabled = false
|
92
96
|
when Hash
|
93
|
-
|
97
|
+
Interactor.options = options
|
94
98
|
end
|
95
99
|
end
|
96
100
|
|
@@ -128,7 +132,7 @@ module Guard
|
|
128
132
|
|
129
133
|
if block_given?
|
130
134
|
groups.each do |group|
|
131
|
-
|
135
|
+
Guard.state.session.groups.add(group, options)
|
132
136
|
end
|
133
137
|
|
134
138
|
@current_groups ||= []
|
@@ -138,7 +142,7 @@ module Guard
|
|
138
142
|
|
139
143
|
@current_groups.pop
|
140
144
|
else
|
141
|
-
|
145
|
+
UI.error \
|
142
146
|
"No Guard plugins found in the group '#{ groups.join(", ") }',"\
|
143
147
|
" please add at least one."
|
144
148
|
end
|
@@ -176,7 +180,8 @@ module Guard
|
|
176
180
|
@current_groups ||= []
|
177
181
|
groups = @current_groups && @current_groups.last || [:default]
|
178
182
|
groups.each do |group|
|
179
|
-
|
183
|
+
opts = @plugin_options.merge(group: group)
|
184
|
+
Guard.state.session.plugins.add(name, opts)
|
180
185
|
end
|
181
186
|
|
182
187
|
@plugin_options = nil
|
@@ -214,7 +219,7 @@ module Guard
|
|
214
219
|
@plugin_options ||= nil
|
215
220
|
return guard(:plugin) { watch(pattern, &action) } unless @plugin_options
|
216
221
|
|
217
|
-
@plugin_options[:watchers] <<
|
222
|
+
@plugin_options[:watchers] << Watcher.new(pattern, action)
|
218
223
|
end
|
219
224
|
|
220
225
|
# Defines a callback to execute arbitrary code before or after any of
|
@@ -237,8 +242,6 @@ module Guard
|
|
237
242
|
# @param [Array] args the callback arguments
|
238
243
|
# @yield a callback block
|
239
244
|
#
|
240
|
-
# @see Guard::Hooker
|
241
|
-
#
|
242
245
|
def callback(*args, &block)
|
243
246
|
@plugin_options ||= nil
|
244
247
|
fail "callback must be called within a guard block" unless @plugin_options
|
@@ -262,8 +265,10 @@ module Guard
|
|
262
265
|
#
|
263
266
|
def ignore(*regexps)
|
264
267
|
# TODO: instead, use Guard.reconfigure(ignore: regexps) or something
|
265
|
-
|
268
|
+
Guard.listener.ignore(regexps) if Guard.listener
|
266
269
|
end
|
270
|
+
|
271
|
+
# TODO: deprecate
|
267
272
|
alias filter ignore
|
268
273
|
|
269
274
|
# Replaces ignored paths globally
|
@@ -276,7 +281,7 @@ module Guard
|
|
276
281
|
def ignore!(*regexps)
|
277
282
|
@ignore_regexps ||= []
|
278
283
|
@ignore_regexps << regexps
|
279
|
-
|
284
|
+
Guard.listener.ignore!(@ignore_regexps) if Guard.listener
|
280
285
|
end
|
281
286
|
alias filter! ignore!
|
282
287
|
|
@@ -341,7 +346,7 @@ module Guard
|
|
341
346
|
options[name] = Regexp.new(list.join("|"), Regexp::IGNORECASE)
|
342
347
|
end
|
343
348
|
|
344
|
-
|
349
|
+
UI.options.merge!(options)
|
345
350
|
end
|
346
351
|
|
347
352
|
# Sets the default scope on startup
|
@@ -361,7 +366,43 @@ module Guard
|
|
361
366
|
# @param [Hash] scopes the scope for the groups and plugins
|
362
367
|
#
|
363
368
|
def scope(scope = {})
|
364
|
-
|
369
|
+
Guard.state.session.guardfile_scope(scope)
|
370
|
+
end
|
371
|
+
|
372
|
+
def evaluate(contents, filename, lineno) # :nodoc
|
373
|
+
instance_eval(contents, filename.to_s, lineno)
|
374
|
+
rescue StandardError, ScriptError => e
|
375
|
+
prefix = "\n\t(dsl)> "
|
376
|
+
cleaned_backtrace = _cleanup_backtrace(e.backtrace)
|
377
|
+
backtrace = "#{prefix}#{cleaned_backtrace.join(prefix)}"
|
378
|
+
msg = "Invalid Guardfile, original error is: \n\n%s, \nbacktrace: %s"
|
379
|
+
raise Error, format(msg, e, backtrace)
|
380
|
+
end
|
381
|
+
|
382
|
+
private
|
383
|
+
|
384
|
+
def _cleanup_backtrace(backtrace)
|
385
|
+
dirs = { File.realpath(Dir.pwd) => ".", }
|
386
|
+
|
387
|
+
gem_env = ENV["GEM_HOME"] || ""
|
388
|
+
dirs[gem_env] = "$GEM_HOME" unless gem_env.empty?
|
389
|
+
|
390
|
+
gem_paths = (ENV["GEM_PATH"] || "").split(File::PATH_SEPARATOR)
|
391
|
+
gem_paths.each_with_index do |path, index|
|
392
|
+
dirs[path] = "$GEM_PATH[#{index}]"
|
393
|
+
end
|
394
|
+
|
395
|
+
backtrace.dup.map do |raw_line|
|
396
|
+
path = nil
|
397
|
+
symlinked_path = raw_line.split(":").first
|
398
|
+
begin
|
399
|
+
path = raw_line.sub(symlinked_path, File.realpath(symlinked_path))
|
400
|
+
dirs.detect { |dir, name| path.sub!(File.realpath(dir), name) }
|
401
|
+
path
|
402
|
+
rescue Errno::ENOENT
|
403
|
+
path || symlinked_path
|
404
|
+
end
|
405
|
+
end
|
365
406
|
end
|
366
407
|
|
367
408
|
# Sets the directories to pass to Listen
|
@@ -375,7 +416,7 @@ module Guard
|
|
375
416
|
directories.each do |dir|
|
376
417
|
fail "Directory #{dir.inspect} does not exist!" unless Dir.exist?(dir)
|
377
418
|
end
|
378
|
-
|
419
|
+
Guard.state.session.watchdirs = directories
|
379
420
|
end
|
380
421
|
end
|
381
422
|
end
|
data/lib/guard/dsl_describer.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
require "formatador"
|
3
3
|
|
4
|
-
require "guard/guardfile/evaluator"
|
5
4
|
require "guard/ui"
|
6
|
-
require "guard/
|
5
|
+
require "guard/notifier"
|
6
|
+
|
7
|
+
require "set"
|
8
|
+
require "ostruct"
|
7
9
|
|
8
10
|
module Guard
|
9
11
|
# The DslDescriber evaluates the Guardfile and creates an internal structure
|
@@ -14,20 +16,8 @@ module Guard
|
|
14
16
|
# @see Guard::CLI
|
15
17
|
#
|
16
18
|
class DslDescriber
|
17
|
-
|
18
|
-
|
19
|
-
# @option options [String] guardfile the path to a valid Guardfile
|
20
|
-
#
|
21
|
-
# @option options [String] guardfile_contents a string representing the
|
22
|
-
# content of a valid Guardfile
|
23
|
-
#
|
24
|
-
# @see Guard::Guardfile::Evaluator#initialize
|
25
|
-
#
|
26
|
-
def initialize(options = {})
|
27
|
-
::Guard.reset_groups
|
28
|
-
::Guard.reset_plugins
|
29
|
-
::Guard.reset_scope
|
30
|
-
::Guard.reset_options(options)
|
19
|
+
def initialize(options = nil)
|
20
|
+
fail "options passed to DslDescriber are ignored!" unless options.nil?
|
31
21
|
end
|
32
22
|
|
33
23
|
# List the Guard plugins that are available for use in your system and marks
|
@@ -36,17 +26,21 @@ module Guard
|
|
36
26
|
# @see CLI#list
|
37
27
|
#
|
38
28
|
def list
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
29
|
+
# collect metadata
|
30
|
+
data = PluginUtil.plugin_names.sort.inject({}) do |hash, name|
|
31
|
+
hash[name.capitalize] = Guard.state.session.plugins.all(name).any?
|
32
|
+
hash
|
33
|
+
end
|
34
|
+
|
35
|
+
# presentation
|
36
|
+
header = [:Plugin, :Guardfile]
|
37
|
+
final_rows = []
|
38
|
+
data.each do |name, used|
|
39
|
+
final_rows << { Plugin: name, Guardfile: used ? "✔" : "✘" }
|
47
40
|
end
|
48
41
|
|
49
|
-
|
42
|
+
# render
|
43
|
+
Formatador.display_compact_table(final_rows, header)
|
50
44
|
end
|
51
45
|
|
52
46
|
# Shows all Guard plugins and their options that are defined in
|
@@ -55,53 +49,52 @@ module Guard
|
|
55
49
|
# @see CLI#show
|
56
50
|
#
|
57
51
|
def show
|
58
|
-
|
59
|
-
groups =
|
52
|
+
# collect metadata
|
53
|
+
groups = Guard.state.session.groups.all
|
60
54
|
|
61
|
-
|
55
|
+
objects = []
|
62
56
|
|
63
|
-
|
57
|
+
empty_plugin = OpenStruct.new
|
58
|
+
empty_plugin.options = [["", nil]]
|
64
59
|
|
60
|
+
groups.each do |group|
|
61
|
+
plugins = Array(Guard.state.session.plugins.all(group: group.name))
|
62
|
+
plugins = [empty_plugin] if plugins.empty?
|
65
63
|
plugins.each do |plugin|
|
66
|
-
options = plugin.options
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
rows << :split
|
72
|
-
rows << {
|
73
|
-
Group: group.title,
|
74
|
-
Plugin: plugin.title,
|
75
|
-
Option: "",
|
76
|
-
Value: ""
|
77
|
-
}
|
78
|
-
else
|
79
|
-
options.each_with_index do |(option, value), index|
|
80
|
-
if index == 0
|
81
|
-
rows << :split
|
82
|
-
rows << {
|
83
|
-
Group: group.title,
|
84
|
-
Plugin: plugin.title,
|
85
|
-
Option: option.to_s,
|
86
|
-
Value: value.inspect
|
87
|
-
}
|
88
|
-
else
|
89
|
-
rows << {
|
90
|
-
Group: "",
|
91
|
-
Plugin: "",
|
92
|
-
Option: option.to_s,
|
93
|
-
Value: value.inspect
|
94
|
-
}
|
95
|
-
end
|
96
|
-
end
|
64
|
+
options = plugin.options
|
65
|
+
options = [["", nil]] if options.empty?
|
66
|
+
options.each do |option, raw_value|
|
67
|
+
value = raw_value.nil? ? "" : raw_value.inspect
|
68
|
+
objects << [group.title, plugin.title, option.to_s, value]
|
97
69
|
end
|
98
70
|
end
|
71
|
+
end
|
99
72
|
|
100
|
-
|
73
|
+
# presentation
|
74
|
+
rows = []
|
75
|
+
prev_group = prev_plugin = prev_option = prev_value = nil
|
76
|
+
objects.each do |group, plugin, option, value|
|
77
|
+
group_changed = prev_group != group
|
78
|
+
plugin_changed = (prev_plugin != plugin || group_changed)
|
79
|
+
|
80
|
+
rows << :split if group_changed || plugin_changed
|
81
|
+
|
82
|
+
rows << {
|
83
|
+
Group: group_changed ? group : "",
|
84
|
+
Plugin: plugin_changed ? plugin : "",
|
85
|
+
Option: option,
|
86
|
+
Value: value
|
87
|
+
}
|
88
|
+
|
89
|
+
prev_group = group
|
90
|
+
prev_plugin = plugin
|
91
|
+
prev_option = option
|
92
|
+
prev_value = value
|
101
93
|
end
|
102
94
|
|
95
|
+
# render
|
103
96
|
Formatador.display_compact_table(
|
104
|
-
|
97
|
+
rows.drop(1),
|
105
98
|
[:Group, :Plugin, :Option, :Value]
|
106
99
|
)
|
107
100
|
end
|
@@ -112,8 +105,6 @@ module Guard
|
|
112
105
|
# @see CLI#show
|
113
106
|
#
|
114
107
|
def notifiers
|
115
|
-
_evaluate_guardfile
|
116
|
-
|
117
108
|
supported = ::Guard::Notifier::SUPPORTED
|
118
109
|
Notifier.connect(notify: false)
|
119
110
|
detected = Notifier.notifiers
|
@@ -156,15 +147,6 @@ module Guard
|
|
156
147
|
|
157
148
|
private
|
158
149
|
|
159
|
-
# Evaluates the `Guardfile` by delegating to
|
160
|
-
# {Guard::Guardfile::Evaluator#evaluate_guardfile}.
|
161
|
-
#
|
162
|
-
def _evaluate_guardfile
|
163
|
-
::Guard.save_scope
|
164
|
-
::Guard::Guardfile::Evaluator.new(::Guard.options).evaluate_guardfile
|
165
|
-
::Guard.restore_scope
|
166
|
-
end
|
167
|
-
|
168
150
|
def _merge_options(klass, notifier)
|
169
151
|
notify_options = notifier ? notifier[:options] : {}
|
170
152
|
|