guard 2.10.0 → 2.10.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6996dd69034de1636618026e8606df7f10b2b22b
4
- data.tar.gz: c374f6846a61be304447f9518ad72d219ba0b12f
3
+ metadata.gz: 100b160735c5c331821d9fa8119bb168ed5f907e
4
+ data.tar.gz: d677f7e1a7491ff72654d415d7c571f028fbef52
5
5
  SHA512:
6
- metadata.gz: 2d4cf024a8ce54ad66c2bd9ba03b46a457924da685ec6987e6ae0c4823e2ebc30fd15627b9dae5b01f7c844158cc420f1396d532c525e4b6d4175feb0167aef2
7
- data.tar.gz: fc31605dee865f1371c2e6fca5d71c35ef7f4d1ca5255acf364972f9312785ebb897776e985632d966edc88b58b0d9e2d913b6987a9cc9576943041b0e74f304
6
+ metadata.gz: 0dcad099ca8bd1dca2486e078233215366c4236b8a1b0b465336d020667e041bd16e75df106efeef75a6013fcdb9601fdd35bd28eac8130c4eb3a910694004a3
7
+ data.tar.gz: 835a20ae288b6c660d9cb058eeba5b2c25f999bc3790c0dfb0ccf48a7816eff2405fe82e26cc9884b2397f02a610ba73f848c63bf89eb478fd94aae632ff31f7
data/lib/guard.rb CHANGED
@@ -60,8 +60,15 @@ module Guard
60
60
  _evaluate(state.session.evaluator_options)
61
61
 
62
62
  # NOTE: this should be *after* evaluate so :directories can work
63
+ # TODO: move listener setup to session?
63
64
  @listener = Listen.send(*state.session.listener_args, &_listener_callback)
64
65
 
66
+ ignores = state.session.guardfile_ignore
67
+ @listener.ignore(ignores) unless ignores.empty?
68
+
69
+ ignores = state.session.guardfile_ignore_bang
70
+ @listener.ignore!(ignores) unless ignores.empty?
71
+
65
72
  Notifier.connect(state.session.notify_options)
66
73
 
67
74
  traps = Internals::Traps
@@ -86,9 +93,11 @@ module Guard
86
93
  #
87
94
  # Currently supported args:
88
95
  #
89
- # old style hash: {modified: ['foo'], added: ['bar'], removed: []}
96
+ # @example Old style hash:
97
+ # async_queue_add(modified: ['foo'], added: ['bar'], removed: [])
90
98
  #
91
- # new style signals with args: [:guard_pause, :unpaused ]
99
+ # @example New style signals with args:
100
+ # async_queue_add([:guard_pause, :unpaused ])
92
101
  #
93
102
  def async_queue_add(changes)
94
103
  @queue << changes
data/lib/guard.rb.orig CHANGED
@@ -8,11 +8,13 @@ require "guard/internals/debugging"
8
8
  require "guard/internals/traps"
9
9
  require "guard/internals/helpers"
10
10
 
11
- require "guard/metadata"
12
- require "guard/options"
11
+ require "guard/internals/queue"
12
+ require "guard/internals/state"
13
13
 
14
+ require "guard/options"
14
15
  require "guard/commander"
15
16
  require "guard/dsl"
17
+ require "guard/group"
16
18
  require "guard/interactor"
17
19
  require "guard/notifier"
18
20
  require "guard/plugin_util"
@@ -20,6 +22,7 @@ require "guard/runner"
20
22
  require "guard/sheller"
21
23
  require "guard/ui"
22
24
  require "guard/watcher"
25
+ require "guard/guardfile/evaluator"
23
26
 
24
27
  # Guard is the main module for all Guard related modules and classes.
25
28
  # Also Guard plugins should use this namespace.
@@ -30,6 +33,9 @@ module Guard
30
33
  class << self
31
34
  attr_reader :listener
32
35
 
36
+ # @private api
37
+ attr_reader :queue
38
+
33
39
  include Internals::Helpers
34
40
 
35
41
  # Initializes the Guard singleton:
@@ -46,103 +52,52 @@ module Guard
46
52
  # @option options [String] guardfile the path to the Guardfile
47
53
  #
48
54
  # @return [Guard] the Guard singleton
49
- #
55
+ def setup(cmdline_options = {})
56
+ init(cmdline_options)
50
57
 
51
- # TODO: this method has too many instance variables
52
- # and some are mock and leak between tests,
53
- # so ideally there should be a guard "instance"
54
- # object that can be created anew between tests
55
- def setup(opts = {})
56
- # NOTE: must be set before anything calls Guard.options
57
- reset_options(opts)
58
+ @queue = Internals::Queue.new(Guard)
58
59
 
59
- # NOTE: must be set before anything calls Guard::UI.debug
60
- ::Guard::Internals::Debugging.start if options[:debug]
60
+ _evaluate(state.session.evaluator_options)
61
61
 
62
- @queue = Queue.new
63
- self.watchdirs = Array(options[:watchdir])
62
+ # NOTE: this should be *after* evaluate so :directories can work
63
+ # TODO: move listener setup to session?
64
+ @listener = Listen.send(*state.session.listener_args, &_listener_callback)
64
65
 
65
- ::Guard::UI.reset_and_clear
66
+ ignores = state.session.guardfile_ignore
67
+ @listener.ignore(ignores) unless ignores.empty?
66
68
 
67
- @listener = _setup_listener
69
+ ignores = state.session.guardfile_ignore_bang
70
+ @listener.ignore!(ignores) unless ignores.empty?
68
71
 
69
- _reset_all
70
- evaluate_guardfile
71
- setup_scope
72
-
73
- ::Guard::Notifier.connect(notify: options[:notify])
72
+ Notifier.connect(state.session.notify_options)
74
73
 
75
74
  traps = Internals::Traps
76
75
  traps.handle("USR1") { async_queue_add([:guard_pause, :paused]) }
77
76
  traps.handle("USR2") { async_queue_add([:guard_pause, :unpaused]) }
78
77
 
79
- @interactor = ::Guard::Interactor.new(options[:no_interactions])
78
+ @interactor = Interactor.new(state.session.interactor_name == :sleep)
80
79
  traps.handle("INT") { @interactor.handle_interrupt }
81
80
 
82
81
  self
83
82
  end
84
83
 
85
- attr_reader :interactor
86
-
87
- # Used only by tests (for all I know...)
88
- def clear_options
89
- @options = nil
90
- end
91
-
92
- # Initializes the groups array with the default group(s).
93
- #
94
- # @see DEFAULT_GROUPS
95
- #
96
- def reset_groups
97
- @groups = DEFAULT_GROUPS.map { |name| Group.new(name) }
98
- end
99
-
100
- # Initializes the plugins array to an empty array.
101
- #
102
- # @see Guard.plugins
103
- #
104
- def reset_plugins
105
- @plugins = []
84
+ def init(cmdline_options)
85
+ @state = Internals::State.new(cmdline_options)
106
86
  end
107
87
 
108
- attr_reader :watchdirs
88
+ attr_reader :state
109
89
 
110
- # Stores the scopes defined by the user via the `--group` / `-g` option (to
111
- # run only a specific group) or the `--plugin` / `-P` option (to run only a
112
- # specific plugin).
113
- #
114
- # @see CLI#start
115
- # @see Dsl#scope
116
- #
117
- def setup_scope(scope = {})
118
- # TODO: there should be a special Scope class instead
119
- scope = _prepare_scope(scope)
120
-
121
- ::Guard.scope = {
122
- groups: scope[:groups].map { |item| ::Guard.add_group(item) },
123
- plugins: scope[:plugins].map { |item| ::Guard.plugin(item) },
124
- }
125
- end
126
-
127
- # Evaluates the Guardfile content. It displays an error message if no
128
- # Guard plugins are instantiated after the Guardfile evaluation.
129
- #
130
- # @see Guard::Guardfile::Evaluator#evaluate_guardfile
131
- #
132
- def evaluate_guardfile
133
- evaluator = Guard::Guardfile::Evaluator.new(options)
134
- evaluator.evaluate_guardfile
135
- msg = "No plugins found in Guardfile, please add at least one."
136
- ::Guard::UI.error msg if _pluginless_guardfile?
137
- end
90
+ attr_reader :interactor
138
91
 
139
92
  # Asynchronously trigger changes
140
93
  #
141
94
  # Currently supported args:
142
95
  #
143
- # old style hash: {modified: ['foo'], added: ['bar'], removed: []}
96
+ # @example Old style hash:
97
+ # async_queue_add(modified: ['foo'], added: ['bar'], removed: [])
144
98
  #
145
- # new style signals with args: [:guard_pause, :unpaused ]
99
+ # @example New style signals with args:
100
+ # async_queue_add([:guard_pause, :unpaused ])
146
101
  #
147
102
  def async_queue_add(changes)
148
103
  @queue << changes
@@ -152,60 +107,17 @@ module Guard
152
107
  Thread.new { interactor.background }
153
108
  end
154
109
 
155
- def pending_changes?
156
- ! @queue.empty?
157
- end
158
-
159
- def watchdirs=(dirs)
160
- dirs = [Dir.pwd] if dirs.empty?
161
- @watchdirs = dirs.map { |dir| File.expand_path dir }
162
- end
163
-
164
110
  private
165
111
 
166
- # Initializes the listener and registers a callback for changes.
167
- #
168
- def _setup_listener
169
- if options[:listen_on]
170
- Listen.on(options[:listen_on], &_listener_callback)
171
- else
172
- listener_options = {}
173
- [:latency, :force_polling, :wait_for_delay].each do |option|
174
- listener_options[option] = options[option] if options[option]
175
- end
176
- listen_args = watchdirs + [listener_options]
177
- Listen.to(*listen_args, &_listener_callback)
178
- end
179
- end
180
-
181
- # Process the change queue, running tasks within the main Guard thread
182
- def _process_queue
183
- actions, changes = [], { modified: [], added: [], removed: [] }
184
-
185
- while pending_changes?
186
- if (item = @queue.pop).first.is_a?(Symbol)
187
- actions << item
188
- else
189
- item.each { |key, value| changes[key] += value }
190
- end
191
- end
192
-
193
- _run_actions(actions)
194
- return if changes.values.all?(&:empty?)
195
- Runner.new.run_on_changes(*changes.values)
196
- end
197
-
198
- # TODO: Guard::Watch or Guard::Scope should provide this
199
- def _scoped_watchers
200
- watchers = []
201
- Runner.new.send(:_scoped_plugins) { |guard| watchers += guard.watchers }
202
- watchers
203
- end
204
-
205
112
  # Check if any of the changes are actually watched for
113
+ # TODO: why iterate twice? reuse this info when running tasks
206
114
  def _relevant_changes?(changes)
115
+ # TODO: no coverage!
207
116
  files = changes.values.flatten(1)
208
- watchers = _scoped_watchers
117
+ scope = Guard.state.scope
118
+ watchers = scope.grouped_plugins.map do |_group, plugins|
119
+ plugins.map(&:watchers).flatten
120
+ end.flatten
209
121
  watchers.any? { |watcher| files.any? { |file| watcher.match(file) } }
210
122
  end
211
123
 
@@ -213,19 +125,6 @@ module Guard
213
125
  paths.map { |path| _relative_pathname(path) }
214
126
  end
215
127
 
216
- def _run_actions(actions)
217
- actions.each do |action_args|
218
- args = action_args.dup
219
- namespaced_action = args.shift
220
- action = namespaced_action.to_s.sub(/^guard_/, "")
221
- if ::Guard.respond_to?(action)
222
- ::Guard.send(action, *args)
223
- else
224
- fail "Unknown action: #{action.inspect}"
225
- end
226
- end
227
- end
228
-
229
128
  def _listener_callback
230
129
  lambda do |modified, added, removed|
231
130
  relative_paths = {
@@ -238,12 +137,7 @@ module Guard
238
137
  end
239
138
  end
240
139
 
241
- def _reset_all
242
- reset_groups
243
- reset_plugins
244
- reset_scope
245
- end
246
-
140
+ # TODO: obsoleted? (move to Dsl?)
247
141
  def _pluginless_guardfile?
248
142
  # no Reevaluator means there was no Guardfile configured that could be
249
143
  # reevaluated, so we don't have a pluginless guardfile, because we don't
@@ -252,20 +146,29 @@ module Guard
252
146
  # But, if we have a Guardfile, we'll at least have the built-in
253
147
  # Reevaluator, so the following will work:
254
148
 
255
- # TODO: this is a workaround for tests
256
- return true if plugins.empty?
257
-
258
- plugins.map(&:name) == ["reevaluator"]
149
+ plugins = state.session.plugins.all
150
+ plugins.empty? || plugins.map(&:name) == ["reevaluator"]
259
151
  end
260
152
 
261
- def _reset_for_tests
262
- @options = nil
263
- @queue = nil
264
- @watchdirs = nil
265
- @watchdirs = nil
266
- @listener = nil
267
- @interactor = nil
268
- @scope = nil
153
+ def _evaluate(options)
154
+ evaluator = Guardfile::Evaluator.new(options)
155
+ evaluator.evaluate
156
+
157
+ # TODO: remove this workaround when options are removed
158
+ state.session.clearing(state.session.options[:clear])
159
+
160
+ UI.reset_and_clear
161
+
162
+ msg = "No plugins found in Guardfile, please add at least one."
163
+ UI.error msg if _pluginless_guardfile?
164
+
165
+ if evaluator.inline?
166
+ UI.info("Using inline Guardfile.")
167
+ elsif evaluator.custom?
168
+ UI.info("Using Guardfile at #{ evaluator.path }.")
169
+ end
170
+ rescue Guardfile::Evaluator::NoPluginsError => e
171
+ UI.error(e.message)
269
172
  end
270
173
  end
271
174
  end
data/lib/guard/dsl.rb CHANGED
@@ -5,8 +5,6 @@ require "guard/ui"
5
5
  require "guard/watcher"
6
6
 
7
7
  require "guard/deprecated/dsl" unless Guard::Config.new.strict?
8
-
9
- # TODO: only for listener
10
8
  require "guard"
11
9
 
12
10
  module Guard
@@ -75,6 +73,7 @@ module Guard
75
73
  # @see Guard::Notifier for available notifier and its options.
76
74
  #
77
75
  def notification(notifier, options = {})
76
+ # TODO: remove dependency on Notifier (let session handle this)
78
77
  Notifier.add(notifier.to_sym, options.merge(silent: false))
79
78
  end
80
79
 
@@ -90,6 +89,7 @@ module Guard
90
89
  # options
91
90
  #
92
91
  def interactor(options)
92
+ # TODO: remove dependency on Interactor (let session handle this)
93
93
  case options
94
94
  when :off
95
95
  Interactor.enabled = false
@@ -132,6 +132,7 @@ module Guard
132
132
 
133
133
  if block_given?
134
134
  groups.each do |group|
135
+ # TODO: let groups be added *after* evaluation
135
136
  Guard.state.session.groups.add(group, options)
136
137
  end
137
138
 
@@ -181,6 +182,7 @@ module Guard
181
182
  groups = @current_groups && @current_groups.last || [:default]
182
183
  groups.each do |group|
183
184
  opts = @plugin_options.merge(group: group)
185
+ # TODO: let plugins be added *after* evaluation
184
186
  Guard.state.session.plugins.add(name, opts)
185
187
  end
186
188
 
@@ -227,11 +229,10 @@ module Guard
227
229
  # `run_on_additions`, `run_on_modifications` and `run_on_removals` plugin
228
230
  # method.
229
231
  #
230
- # @example Define a callback that'll be called before the `reload` action.
232
+ # @example Add callback before the `reload` action.
231
233
  # callback(:reload_begin) { puts "Let's reload!" }
232
234
  #
233
- # @example Define a callback that'll be called before the `start` and
234
- # `stop` actions.
235
+ # @example Add callback before the `start` and `stop` actions.
235
236
  #
236
237
  # my_lambda = lambda do |plugin, event, *args|
237
238
  # puts "Let's #{event} #{plugin} with #{args}!"
@@ -264,8 +265,8 @@ module Guard
264
265
  # @param [Regexp] regexps a pattern (or list of patterns) for ignoring paths
265
266
  #
266
267
  def ignore(*regexps)
267
- # TODO: instead, use Guard.reconfigure(ignore: regexps) or something
268
- Guard.listener.ignore(regexps) if Guard.listener
268
+ # TODO: use guardfile results class
269
+ Guard.state.session.guardfile_ignore = regexps
269
270
  end
270
271
 
271
272
  # TODO: deprecate
@@ -281,8 +282,11 @@ module Guard
281
282
  def ignore!(*regexps)
282
283
  @ignore_regexps ||= []
283
284
  @ignore_regexps << regexps
284
- Guard.listener.ignore!(@ignore_regexps) if Guard.listener
285
+ # TODO: use guardfile results class
286
+ Guard.state.session.guardfile_ignore_bang = @ignore_regexps
285
287
  end
288
+
289
+ # TODO: deprecate
286
290
  alias filter! ignore!
287
291
 
288
292
  # Configures the Guard logger.
@@ -366,6 +370,7 @@ module Guard
366
370
  # @param [Hash] scopes the scope for the groups and plugins
367
371
  #
368
372
  def scope(scope = {})
373
+ # TODO: use a Guardfile::Results class
369
374
  Guard.state.session.guardfile_scope(scope)
370
375
  end
371
376
 
@@ -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
@@ -222,11 +227,10 @@ module Guard
222
227
  # `run_on_additions`, `run_on_modifications` and `run_on_removals` plugin
223
228
  # method.
224
229
  #
225
- # @example Define a callback that'll be called before the `reload` action.
230
+ # @example Add callback before the `reload` action.
226
231
  # callback(:reload_begin) { puts "Let's reload!" }
227
232
  #
228
- # @example Define a callback that'll be called before the `start` and
229
- # `stop` actions.
233
+ # @example Add callback before the `start` and `stop` actions.
230
234
  #
231
235
  # my_lambda = lambda do |plugin, event, *args|
232
236
  # puts "Let's #{event} #{plugin} with #{args}!"
@@ -237,8 +241,6 @@ module Guard
237
241
  # @param [Array] args the callback arguments
238
242
  # @yield a callback block
239
243
  #
240
- # @see Guard::Hooker
241
- #
242
244
  def callback(*args, &block)
243
245
  @plugin_options ||= nil
244
246
  fail "callback must be called within a guard block" unless @plugin_options
@@ -262,8 +264,10 @@ module Guard
262
264
  #
263
265
  def ignore(*regexps)
264
266
  # TODO: instead, use Guard.reconfigure(ignore: regexps) or something
265
- ::Guard.listener.ignore(regexps) if ::Guard.listener
267
+ Guard.listener.ignore(regexps) if Guard.listener
266
268
  end
269
+
270
+ # TODO: deprecate
267
271
  alias filter ignore
268
272
 
269
273
  # Replaces ignored paths globally
@@ -276,7 +280,7 @@ module Guard
276
280
  def ignore!(*regexps)
277
281
  @ignore_regexps ||= []
278
282
  @ignore_regexps << regexps
279
- ::Guard.listener.ignore!(@ignore_regexps) if ::Guard.listener
283
+ Guard.listener.ignore!(@ignore_regexps) if Guard.listener
280
284
  end
281
285
  alias filter! ignore!
282
286
 
@@ -341,7 +345,7 @@ module Guard
341
345
  options[name] = Regexp.new(list.join("|"), Regexp::IGNORECASE)
342
346
  end
343
347
 
344
- ::Guard::UI.options.merge!(options)
348
+ UI.options.merge!(options)
345
349
  end
346
350
 
347
351
  # Sets the default scope on startup
@@ -361,18 +365,68 @@ module Guard
361
365
  # @param [Hash] scopes the scope for the groups and plugins
362
366
  #
363
367
  def scope(scope = {})
364
- ::Guard.setup_scope(scope)
368
+ Guard.state.session.guardfile_scope(scope)
369
+ end
370
+
371
+ def evaluate(contents, filename, lineno) # :nodoc
372
+ instance_eval(contents, filename.to_s, lineno)
373
+ rescue StandardError, ScriptError => e
374
+ prefix = "\n\t(dsl)> "
375
+ cleaned_backtrace = _cleanup_backtrace(e.backtrace)
376
+ backtrace = "#{prefix}#{cleaned_backtrace.join(prefix)}"
377
+ msg = "Invalid Guardfile, original error is: \n\n%s, \nbacktrace: %s"
378
+ raise Error, format(msg, e, backtrace)
365
379
  end
366
380
 
367
- # Sets the directories to pass to Listen (watchdirs)
381
+ # Sets the directories to pass to Listen
368
382
  #
369
383
  # @example watch only given directories
370
384
  # directories %w(lib specs)
371
385
  #
372
- # @param [Array] directories to watch
386
+ # @param [Array] directories directories for Listen to watch
387
+ #
388
+ def directories(directories)
389
+ directories.each do |dir|
390
+ fail "Directory #{dir.inspect} does not exist!" unless Dir.exist?(dir)
391
+ end
392
+ Guard.state.session.watchdirs = directories
393
+ end
394
+
395
+ # Sets Guard to clear the screen before every task is run
396
+ #
397
+ # @example switching clearing the screen on
398
+ # clearing(:on)
373
399
  #
374
- def directories(dirs)
375
- ::Guard.watchdirs = dirs
400
+ # @param [Symbol] on ':on' to turn on, ':off' (default) to turn off
401
+ #
402
+ def clearing(on)
403
+ Guard.state.session.clearing(on == :on)
404
+ end
405
+
406
+ private
407
+
408
+ def _cleanup_backtrace(backtrace)
409
+ dirs = { File.realpath(Dir.pwd) => ".", }
410
+
411
+ gem_env = ENV["GEM_HOME"] || ""
412
+ dirs[gem_env] = "$GEM_HOME" unless gem_env.empty?
413
+
414
+ gem_paths = (ENV["GEM_PATH"] || "").split(File::PATH_SEPARATOR)
415
+ gem_paths.each_with_index do |path, index|
416
+ dirs[path] = "$GEM_PATH[#{index}]"
417
+ end
418
+
419
+ backtrace.dup.map do |raw_line|
420
+ path = nil
421
+ symlinked_path = raw_line.split(":").first
422
+ begin
423
+ path = raw_line.sub(symlinked_path, File.realpath(symlinked_path))
424
+ dirs.detect { |dir, name| path.sub!(File.realpath(dir), name) }
425
+ path
426
+ rescue Errno::ENOENT
427
+ path || symlinked_path
428
+ end
429
+ end
376
430
  end
377
431
  end
378
432
  end