guard 2.9.0 → 2.9.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 = ::Guard::Interactor.convert_scope(entries)
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
- ::Guard.async_queue_add(modified: files, added: [], removed: [])
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 = ::Guard::Interactor.convert_scope(entries)
24
+ scopes, unknown = Interactor.convert_scope(entries)
26
25
 
27
26
  unless unknown.empty?
28
27
  output.puts "Unknown scopes: #{ unknown.join(", ") }"
@@ -29,8 +29,7 @@ module Guard
29
29
  return
30
30
  end
31
31
 
32
- # TODO: provide a way for guard to know this was called from Pry
33
- ::Guard.setup_scope(scope)
32
+ Guard.state.scope.from_interactor(scope)
34
33
  end
35
34
  end
36
35
  end
@@ -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::Guardfile::Evaluator.new(::Guard.options)
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
@@ -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::Base#start},
30
- # {Plugin::Base#stop}, {Plugin::Base#reload}, {Plugin::Base#run_all},
31
- # {Plugin::Base#run_on_changes}, {Plugin::Base#run_on_additions},
32
- # {Plugin::Base#run_on_modifications} and {Plugin::Base#run_on_removals}
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
- ::Guard::Interactor.enabled = false
95
+ Interactor.enabled = false
92
96
  when Hash
93
- ::Guard::Interactor.options = options
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
- ::Guard.add_group(group, options)
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
- ::Guard::UI.error \
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
- ::Guard.add_plugin(name, @plugin_options.merge(group: group))
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] << ::Guard::Watcher.new(pattern, action)
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
- ::Guard.listener.ignore(regexps) if ::Guard.listener
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
- ::Guard.listener.ignore!(@ignore_regexps) if ::Guard.listener
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
- ::Guard::UI.options.merge!(options)
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
- ::Guard.setup_scope(scope)
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
- ::Guard.watchdirs = directories
419
+ Guard.state.session.watchdirs = directories
379
420
  end
380
421
  end
381
422
  end
@@ -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/metadata"
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
- # Initializes a new DslDescriber object.
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
- _evaluate_guardfile
40
- names = ::Guard::PluginUtil.plugin_names.sort.uniq
41
- final_rows = names.inject([]) do |rows, name|
42
- used = ::Guard.plugins(name).any?
43
- rows << {
44
- Plugin: name.capitalize,
45
- Guardfile: used ? "✔" : "✘"
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
- Formatador.display_compact_table(final_rows, [:Plugin, :Guardfile])
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
- _evaluate_guardfile
59
- groups = ::Guard.groups
52
+ # collect metadata
53
+ groups = Guard.state.session.groups.all
60
54
 
61
- final_rows = groups.each_with_object([]) do |group, rows|
55
+ objects = []
62
56
 
63
- plugins = Array(::Guard.plugins(group: group.name))
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.inject({}) do |o, (k, v)|
67
- o.tap { |option| option[k.to_s] = v }
68
- end.sort
69
-
70
- if options.empty?
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
- rows
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
- final_rows.drop(1),
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