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,21 +1,61 @@
1
1
  require "guard/plugin"
2
2
  require "guard/guardfile/evaluator"
3
+ require "guard/runner"
4
+ require "guard/internals/helpers"
3
5
 
4
6
  module Guard
5
7
  class Reevaluator < Plugin
8
+ include Internals::Helpers
9
+
6
10
  def run_on_modifications(files)
7
- return unless ::Guard::Watcher.match_guardfile?(files)
8
- ::Guard.save_scope
9
- Guard::Guardfile::Evaluator.new(Guard.options).reevaluate_guardfile
10
- rescue ScriptError, StandardError => e
11
- ::Guard::UI.warning("Failed to reevaluate file: #{e}")
11
+ # TODO: this is messed up, because reevaluator adds itself
12
+ # anyway, so it know what the path is
13
+ evaluator = _evaluator
14
+ path = evaluator.path
15
+ return unless files.any? { |file| path == Pathname(file) }
16
+ reevaluate
17
+ rescue Dsl::Error, Guardfile::Evaluator::Error => e
18
+ UI.warning("Failed to reevaluate file: #{e}")
19
+ _add_self_to_plugins
20
+ throw :task_has_failed
21
+ end
12
22
 
13
- options = { watchers: [::Guard::Watcher.new("Guardfile")] }
14
- ::Guard.add_plugin(:reevaluator, options)
23
+ def reevaluate
24
+ evaluator = _evaluator
25
+ return if evaluator.inline?
15
26
 
16
- throw :task_has_failed
17
- ensure
18
- ::Guard.restore_scope
27
+ Runner.new.run(:stop)
28
+
29
+ Guard.state.reset_session
30
+
31
+ Notifier.disconnect
32
+ evaluator.evaluate
33
+ Notifier.connect(Guard.state.session.notify_options)
34
+
35
+ if Guard.send(:_pluginless_guardfile?)
36
+ Notifier.notify(
37
+ "No plugins found in Guardfile, please add at least one.",
38
+ title: "Guard re-evaluate",
39
+ image: :failed)
40
+ else
41
+ msg = "Guardfile has been re-evaluated."
42
+ UI.info(msg)
43
+ Notifier.notify(msg, title: "Guard re-evaluate")
44
+ Runner.new.run(:start)
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ def _evaluator
51
+ Guardfile::Evaluator.new(Guard.state.session.evaluator_options)
52
+ end
53
+
54
+ def _add_self_to_plugins
55
+ # TODO: do this on reload as well
56
+ pattern = _relative_pathname(_evaluator.path).to_s
57
+ options = { watchers: [Watcher.new(pattern)], group: :common }
58
+ Guard.state.session.plugins.add(:reevaluator, options)
19
59
  end
20
60
  end
21
61
  end
@@ -1,6 +1,5 @@
1
1
  require "lumberjack"
2
2
 
3
- require "guard/metadata"
4
3
  require "guard/ui"
5
4
  require "guard/watcher"
6
5
 
@@ -17,12 +16,17 @@ module Guard
17
16
  #
18
17
  def run(task, scope_hash = {})
19
18
  Lumberjack.unit_of_work do
20
- _scoped_plugins(scope_hash || {}) do |plugin|
21
- _supervise(plugin, task) if plugin.respond_to?(task)
19
+ items = Guard.state.scope.grouped_plugins(scope_hash || {})
20
+ items.each do |_group, plugins|
21
+ _run_group_plugins(plugins) do |plugin|
22
+ _supervise(plugin, task) if plugin.respond_to?(task)
23
+ end
22
24
  end
23
25
  end
24
26
  end
25
27
 
28
+ PLUGIN_FAILED = "%s has failed, other group's plugins will be skipped."
29
+
26
30
  MODIFICATION_TASKS = [
27
31
  :run_on_modifications, :run_on_changes, :run_on_change
28
32
  ]
@@ -44,18 +48,18 @@ module Guard
44
48
  REMOVAL_TASKS => removed
45
49
  }
46
50
 
47
- ::Guard::UI.clearable
48
-
49
- _scoped_plugins do |plugin|
50
- ::Guard::UI.clear
51
-
52
- types.each do |tasks, unmatched_paths|
53
- next if unmatched_paths.empty?
54
- match_result = ::Guard::Watcher.match_files(plugin, unmatched_paths)
55
- next if match_result.empty?
56
-
57
- next unless (task = tasks.detect { |meth| plugin.respond_to?(meth) })
58
- _supervise(plugin, task, match_result)
51
+ UI.clearable
52
+
53
+ Guard.state.scope.grouped_plugins.each do |_group, plugins|
54
+ _run_group_plugins(plugins) do |plugin|
55
+ UI.clear
56
+ types.each do |tasks, unmatched_paths|
57
+ next if unmatched_paths.empty?
58
+ match_result = Watcher.match_files(plugin, unmatched_paths)
59
+ next if match_result.empty?
60
+ task = tasks.detect { |meth| plugin.respond_to?(meth) }
61
+ _supervise(plugin, task, match_result) if task
62
+ end
59
63
  end
60
64
  end
61
65
  end
@@ -83,12 +87,12 @@ module Guard
83
87
  result
84
88
  end
85
89
  rescue ScriptError, StandardError, RuntimeError
86
- ::Guard::UI.error("#{ plugin.class.name } failed to achieve its"\
90
+ UI.error("#{ plugin.class.name } failed to achieve its"\
87
91
  " <#{ task }>, exception was:" \
88
92
  "\n#{ $!.class }: #{ $!.message }" \
89
93
  "\n#{ $!.backtrace.join("\n") }")
90
- ::Guard.remove_plugin(plugin)
91
- ::Guard::UI.info("\n#{ plugin.class.name } has just been fired")
94
+ Guard.state.session.plugins.remove(plugin)
95
+ UI.info("\n#{ plugin.class.name } has just been fired")
92
96
  $!
93
97
  end
94
98
 
@@ -97,7 +101,6 @@ module Guard
97
101
  # @note If a Guard group is being run and it has the `:halt_on_fail`
98
102
  # option set, this method returns :no_catch as it will be caught at the
99
103
  # group level.
100
- # @see ._scoped_plugins
101
104
  #
102
105
  # @param [Guard::Plugin] guard the Guard plugin to execute
103
106
  # @return [Symbol] the symbol to catch
@@ -108,97 +111,16 @@ module Guard
108
111
 
109
112
  private
110
113
 
111
- # Loop through all groups and run the given task for each Guard plugin.
112
- #
113
- # If no scope is supplied, the global Guard scope is taken into account.
114
- # If both a plugin and a group scope is given, then only the plugin scope
115
- # is used.
116
- #
117
- # Stop the task run for the all Guard plugins within a group if one Guard
118
- # throws `:task_has_failed`.
119
- #
120
- # @param [Hash] scopes hash with plugins or a groups scope
121
- # @yield the task to run
122
- #
123
- def _scoped_plugins(scopes = {})
124
- fail "NO PLUGIN SCOPE" if scopes.nil?
125
- if plugins = _current_plugins_scope(scopes)
126
- plugins.each do |guard|
127
- yield(guard)
128
- end
129
- else
130
- _current_groups_scope(scopes).each do |group|
131
- fail "Invalid group: #{group.inspect}" unless group.respond_to?(:name)
132
- current_plugin = nil
133
- block_return = catch :task_has_failed do
134
- ::Guard.plugins(group: group.name).each do |guard|
135
- current_plugin = guard
136
- yield(guard)
137
- end
138
- end
139
-
140
- next unless block_return.nil?
141
-
142
- ::Guard::UI.info "#{ current_plugin.class.name } has failed,"\
143
- " other group's plugins execution has been halted."
114
+ def _run_group_plugins(plugins)
115
+ failed_plugin = nil
116
+ catch :task_has_failed do
117
+ plugins.each do |plugin|
118
+ failed_plugin = plugin
119
+ yield plugin
120
+ failed_plugin = nil
144
121
  end
145
122
  end
146
- end
147
-
148
- # Returns the current plugins scope.
149
- # Local plugins scope wins over global plugins scope.
150
- # If no plugins scope is found, then NO plugins are returned.
151
- #
152
- # @param [Hash] scopes hash with a local plugins or a groups scope
153
- # @return [Array<Guard::Plugin>] the plugins to scope to
154
- #
155
- def _current_plugins_scope(scope)
156
- return nil unless (plugins = _find_non_empty_plugins_scope(scope))
157
-
158
- Array(plugins).map { |plugin| _instantiate(:plugin, plugin) }
159
- end
160
-
161
- # Returns the current groups scope.
162
- # Local groups scope wins over global groups scope.
163
- # If no groups scope is found, then ALL groups are returned.
164
- #
165
- # @param [Hash] scopes hash with a local plugins or a groups scope
166
- # @return [Array<Guard::Group>] the groups to scope to
167
- #
168
- def _current_groups_scope(scope)
169
- found = _find_non_empty_groups_scope(scope)
170
- groups = Array(found).map { |group| _instantiate(:group, group) }
171
- return groups if groups.any? { |g| g.name == :common }
172
- ([_instantiate(:group, :common)] + Array(found)).compact
173
- end
174
-
175
- def _instantiate(meth, obj)
176
- (obj.is_a?(Symbol) || obj.is_a?(String)) ? ::Guard.send(meth, obj) : obj
177
- end
178
-
179
- # Find the first non empty element in the given possibilities
180
- #
181
- def _find_non_empty_scope(type, local_scope, *additional_possibilities)
182
- found = [
183
- local_scope[:"#{type}s"],
184
- [local_scope[type.to_sym]],
185
- ::Guard.scope[:"#{type}s"],
186
- additional_possibilities.flatten
187
- ]
188
- found.compact.detect { |a| !Array(a).compact.empty? }
189
- end
190
-
191
- # Find the first non empty plugins scope
192
- #
193
- def _find_non_empty_plugins_scope(scope)
194
- fail "NO PLUGIN SCOPE" if scope.nil?
195
- _find_non_empty_scope(:plugin, scope)
196
- end
197
-
198
- # Find the first non empty groups scope
199
- #
200
- def _find_non_empty_groups_scope(scope)
201
- _find_non_empty_scope(:group, scope, ::Guard.groups)
123
+ UI.info format(PLUGIN_FAILED, failed_plugin.class.name) if failed_plugin
202
124
  end
203
125
  end
204
126
  end
@@ -1,8 +1,8 @@
1
1
  require "lumberjack"
2
2
 
3
+ require "guard/internals/state"
4
+
3
5
  require "guard/options"
4
- require "guard/session"
5
- require "guard/metadata"
6
6
 
7
7
  require "guard/ui/colors"
8
8
 
@@ -104,8 +104,6 @@ module Guard
104
104
  # @option options [String] plugin manually define the calling plugin
105
105
  #
106
106
  def deprecation(message, options = {})
107
- msg = "neither ::Guard.setup nor ::Guard.reset_options was called"
108
- fail msg if ::Guard.options.nil?
109
107
  unless ENV["GUARD_GEM_SILENCE_DEPRECATIONS"] == "1"
110
108
  backtrace = Thread.current.backtrace[1..5].join("\n\t >")
111
109
  msg = format("%s\nDeprecation backtrace: %s", message, backtrace)
@@ -132,13 +130,13 @@ module Guard
132
130
  # Clear the output if clearable.
133
131
  #
134
132
  def clear(opts = {})
135
- return unless ::Guard.options[:clear]
133
+ return unless Guard.state.session.clear?
136
134
 
137
135
  fail "UI not set up!" if @clearable.nil?
138
136
  return unless @clearable || opts[:force]
139
137
 
140
138
  @clearable = false
141
- ::Guard::Terminal.clear
139
+ Terminal.clear
142
140
  rescue Errno::ENOENT => e
143
141
  warning("Failed to clear the screen: #{e.inspect}")
144
142
  end
@@ -162,28 +160,12 @@ module Guard
162
160
  # @param [Hash] scope hash with a guard or a group scope
163
161
  #
164
162
  def action_with_scopes(action, scope)
165
- first_non_blank_scope = _first_non_blank_scope(scope)
166
- unless first_non_blank_scope.nil?
167
- scope_message = first_non_blank_scope.map(&:title).join(", ")
168
- end
169
-
170
- info "#{ action } #{ scope_message || "all" }"
163
+ titles = Guard.state.scope.titles(scope)
164
+ info "#{action} #{titles.join(", ")}"
171
165
  end
172
166
 
173
167
  private
174
168
 
175
- # Returns the first non-blank scope by searching in the given `scope`
176
- # hash and in Guard.scope. Returns nil if no non-blank scope is found.
177
- #
178
- def _first_non_blank_scope(scope)
179
- [:plugins, :groups].each do |scope_name|
180
- s = scope[scope_name] || ::Guard.scope[scope_name]
181
- return s if !s.nil? && !s.empty?
182
- end
183
-
184
- nil
185
- end
186
-
187
169
  # Filters log messages depending on either the
188
170
  # `:only`` or `:except` option.
189
171
  #
@@ -1,3 +1,3 @@
1
1
  module Guard
2
- VERSION = "2.9.0"
2
+ VERSION = "2.9.1"
3
3
  end
@@ -1,3 +1,6 @@
1
+ require "guard/config"
2
+ require "guard/deprecated/watcher" unless Guard::Config.new.strict?
3
+
1
4
  require "guard/ui"
2
5
 
3
6
  module Guard
@@ -7,6 +10,7 @@ module Guard
7
10
  # enable processing the file system change result.
8
11
  #
9
12
  class Watcher
13
+ Deprecated::Watcher.add_deprecated(self) unless Config.new.strict?
10
14
  attr_accessor :pattern, :action
11
15
 
12
16
  # Initializes a file watcher.
@@ -77,18 +81,6 @@ module Guard
77
81
  end
78
82
  end
79
83
 
80
- # Tests if any of the files is the Guardfile.
81
- #
82
- # @param [Array<String>] files the files to test
83
- # @return [Boolean] whether one of these files is the Guardfile
84
- #
85
- def self.match_guardfile?(files)
86
- # TODO: move this method elsewhere
87
- require "guard/guardfile/evaluator"
88
- path = Guard.options[:guardfile]
89
- files.any? { |file| File.expand_path(file) == path }
90
- end
91
-
92
84
  # Test the watchers pattern against a file.
93
85
  #
94
86
  # @param [String] file the file to test
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: guard
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.9.0
4
+ version: 2.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thibaud Guillaume-Gentil
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-26 00:00:00.000000000 Z
11
+ date: 2014-11-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -111,8 +111,10 @@ files:
111
111
  - lib/guard/commands/show.rb
112
112
  - lib/guard/config.rb
113
113
  - lib/guard/deprecated/dsl.rb
114
+ - lib/guard/deprecated/evaluator.rb
114
115
  - lib/guard/deprecated/guard.rb
115
116
  - lib/guard/deprecated/guardfile.rb
117
+ - lib/guard/deprecated/watcher.rb
116
118
  - lib/guard/dsl.rb
117
119
  - lib/guard/dsl.rb.orig
118
120
  - lib/guard/dsl_describer.rb
@@ -124,16 +126,22 @@ files:
124
126
  - lib/guard/interactor.rb
125
127
  - lib/guard/internals/debugging.rb
126
128
  - lib/guard/internals/environment.rb
129
+ - lib/guard/internals/groups.rb
127
130
  - lib/guard/internals/helpers.rb
131
+ - lib/guard/internals/plugins.rb
132
+ - lib/guard/internals/queue.rb
133
+ - lib/guard/internals/scope.rb
134
+ - lib/guard/internals/session.rb
135
+ - lib/guard/internals/state.rb
128
136
  - lib/guard/internals/tracing.rb
129
137
  - lib/guard/internals/traps.rb
130
138
  - lib/guard/jobs/base.rb
131
139
  - lib/guard/jobs/pry_wrapper.rb
132
140
  - lib/guard/jobs/sleep.rb
133
- - lib/guard/metadata.rb
134
141
  - lib/guard/notifier.rb
135
142
  - lib/guard/notifier.rb.orig
136
143
  - lib/guard/notifier/detected.rb
144
+ - lib/guard/notifier/detected.rb.orig
137
145
  - lib/guard/notifiers/base.rb
138
146
  - lib/guard/notifiers/emacs.rb
139
147
  - lib/guard/notifiers/file_notifier.rb
@@ -147,14 +155,11 @@ files:
147
155
  - lib/guard/notifiers/tmux.rb
148
156
  - lib/guard/options.rb
149
157
  - lib/guard/plugin.rb
150
- - lib/guard/plugin/base.rb
151
- - lib/guard/plugin/hooker.rb
152
158
  - lib/guard/plugin_util.rb
153
159
  - lib/guard/rake_task.rb
154
160
  - lib/guard/reevaluator.rb
155
161
  - lib/guard/reevaluator.rb.orig
156
162
  - lib/guard/runner.rb
157
- - lib/guard/session.rb
158
163
  - lib/guard/sheller.rb
159
164
  - lib/guard/templates/Guardfile
160
165
  - lib/guard/templates/Guardfile.orig
@@ -1,190 +0,0 @@
1
- require "guard/group"
2
-
3
- require "guard/plugin_util"
4
-
5
- # TODO: should not be necessary
6
- require "guard/internals/helpers"
7
-
8
- module Guard
9
- extend Internals::Helpers
10
-
11
- # TODO: change to a normal class
12
- class << self
13
- DEFAULT_GROUPS = [:common, :default]
14
-
15
- DEFAULT_OPTIONS = {
16
- clear: false,
17
- notify: true,
18
- debug: false,
19
- group: [],
20
- plugin: [],
21
- watchdir: nil,
22
- guardfile: nil,
23
- no_interactions: false,
24
- no_bundler_warning: false,
25
- latency: nil,
26
- force_polling: false,
27
- wait_for_delay: nil,
28
- listen_on: nil
29
- }
30
-
31
- def add_group(name, options = {})
32
- unless (group = group(name))
33
- group = Group.new(name, options)
34
- @groups << group
35
- end
36
-
37
- group
38
- end
39
-
40
- def group(filter)
41
- groups(filter).first
42
- end
43
-
44
- def groups(filter = nil)
45
- @groups ||= []
46
-
47
- return @groups if filter.nil?
48
-
49
- case filter
50
- when String, Symbol
51
- @groups.select { |group| group.name == filter.to_sym }
52
- when Regexp
53
- @groups.select { |group| group.name.to_s =~ filter }
54
- else
55
- fail "Invalid filter: #{filter.inspect}"
56
- end
57
- end
58
-
59
- # TODO: remove
60
- def _reset_for_tests
61
- @options = nil
62
- @queue = nil
63
- @watchdirs = nil
64
- @watchdirs = nil
65
- @listener = nil
66
- @interactor = nil
67
- @scope = nil
68
- end
69
-
70
- # TODO: remove
71
- def clear_options
72
- @options = nil
73
- end
74
-
75
- # TODO: remove
76
- def reset_groups
77
- @groups = DEFAULT_GROUPS.map { |name| Group.new(name) }
78
- end
79
-
80
- # TODO: remove
81
- def reset_plugins
82
- @plugins = []
83
- end
84
-
85
- def plugins(filter = nil)
86
- @plugins ||= []
87
-
88
- return @plugins if filter.nil?
89
-
90
- filtered_plugins = case filter
91
- when String, Symbol
92
- @plugins.select do |plugin|
93
- plugin.name == filter.to_s.downcase.gsub("-", "")
94
- end
95
- when Regexp
96
- @plugins.select do |plugin|
97
- plugin.name =~ filter
98
- end
99
- when Hash
100
- @plugins.select do |plugin|
101
- filter.all? do |k, v|
102
- case k
103
- when :name
104
- plugin.name == v.to_s.downcase.gsub("-", "")
105
- when :group
106
- plugin.group.name == v.to_sym
107
- end
108
- end
109
- end
110
- end
111
-
112
- filtered_plugins
113
- end
114
-
115
- def scope
116
- fail "::Guard.setup() not called" if @scope.nil?
117
- @scope.dup.freeze
118
- end
119
-
120
- def plugin(filter)
121
- plugins(filter).first
122
- end
123
-
124
- # Used by runner to remove a failed plugin
125
- def remove_plugin(plugin)
126
- # TODO: coverage/aruba
127
- @plugins.delete(plugin)
128
- end
129
-
130
- # TODO: move elsewhere
131
- def add_builtin_plugins(guardfile)
132
- return unless guardfile
133
-
134
- pattern = _relative_pathname(guardfile).to_s
135
- watcher = ::Guard::Watcher.new(pattern)
136
- ::Guard.add_plugin(:reevaluator, watchers: [watcher], group: :common)
137
- end
138
-
139
- def add_plugin(name, options = {})
140
- instance = ::Guard::PluginUtil.new(name).initialize_plugin(options)
141
- @plugins << instance
142
- instance
143
- end
144
-
145
- def reset_scope
146
- # calls Guard.scope=() to set the instance variable directly, as opposed
147
- # to Guard.scope()
148
- ::Guard.scope = { groups: [], plugins: [] }
149
- end
150
-
151
- # Called by Pry scope command
152
-
153
- def scope=(new_scope)
154
- @scope = new_scope
155
- @scope.dup.freeze
156
- end
157
-
158
- # Used to merge CLI options with Setuper defaults
159
- def reset_options(new_options)
160
- @options = ::Guard::Options.new(new_options, DEFAULT_OPTIONS)
161
- end
162
-
163
- def save_scope
164
- # This actually replaces scope from command line,
165
- # so scope set by 'scope' Pry command will be reset
166
- @saved_scope = _prepare_scope(::Guard.scope)
167
- end
168
-
169
- def restore_scope
170
- ::Guard.setup_scope(@saved_scope || {})
171
- end
172
-
173
- private
174
-
175
- def _prepare_scope(new_scope)
176
- fail "Guard::setup() not called!" if options.nil?
177
- {
178
- plugins: _scope_names(new_scope, :plugin),
179
- groups: _scope_names(new_scope, :group)
180
- }
181
- end
182
-
183
- def _scope_names(new_scope, name)
184
- items = Array(options[name])
185
- items = Array(new_scope[:"#{name}s"] || new_scope[name]) if items.empty?
186
- # Convert objects to names
187
- items.map { |p| p.respond_to?(:name) ? p.name : p }
188
- end
189
- end
190
- end