guard 2.9.0 → 2.9.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.
@@ -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