guard 2.10.2 → 2.10.3

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: 3106af4e3722da1f4bd41e051e5baf1ff8ace4f7
4
- data.tar.gz: 0ef587f058e7f02bc5b4195a0b3b3b4d25847ddd
3
+ metadata.gz: 12901ae839ae58fdc3f18c932ffc1aef5fbd5f93
4
+ data.tar.gz: 05665929d7b77277aa5cd37156e6984b11651379
5
5
  SHA512:
6
- metadata.gz: b5f3825c29f9c01f14b50051055e105a3695288da0ce2ba2d42fdd4e4af92881afb455515da551a1faaf192b28ba8eb2e599f0640002ff9c1d2d8db0796c734a
7
- data.tar.gz: c107a499ff6e9814b536a9c1f723c5a7badc97e33f74ae8409f5b72d082fff63c09d3eac630cd9b6b12c9591ed1210b907ea05680f2b615d62bcde31b2eb5784
6
+ metadata.gz: 8d850a23954953c2a6b2ba15813ee408d8fa29d8a85dec0c15b5fb68ab7e51b7bc2e1cb87951975991e5ac24305e58b99ac41088f7e2c96b1f662119e3ad924f
7
+ data.tar.gz: 067ca85ff9546dfedd73972e87acdf97c6aa48cdbfa3ea6475df7280bd8f52bab9b587bd0117511b12410f6bb79c781c8c46e88c6e3fc0698f569fefddf75a99
@@ -3,38 +3,27 @@ require "listen"
3
3
 
4
4
  require "guard/config"
5
5
  require "guard/deprecated/guard" unless Guard::Config.new.strict?
6
+ require "guard/internals/helpers"
6
7
 
7
8
  require "guard/internals/debugging"
8
9
  require "guard/internals/traps"
9
- require "guard/internals/helpers"
10
-
11
10
  require "guard/internals/queue"
12
- require "guard/internals/state"
13
11
 
14
- require "guard/options"
15
- require "guard/commander"
16
- require "guard/dsl"
17
- require "guard/group"
12
+ # TODO: remove this class altogether
18
13
  require "guard/interactor"
19
- require "guard/notifier"
20
- require "guard/plugin_util"
21
- require "guard/runner"
22
- require "guard/sheller"
23
- require "guard/ui"
24
- require "guard/watcher"
25
- require "guard/guardfile/evaluator"
26
14
 
27
15
  # Guard is the main module for all Guard related modules and classes.
28
16
  # Also Guard plugins should use this namespace.
29
- #
30
17
  module Guard
31
18
  Deprecated::Guard.add_deprecated(self) unless Config.new.strict?
32
19
 
33
20
  class << self
21
+ attr_reader :state
22
+ attr_reader :queue
34
23
  attr_reader :listener
24
+ attr_reader :interactor
35
25
 
36
26
  # @private api
37
- attr_reader :queue
38
27
 
39
28
  include Internals::Helpers
40
29
 
@@ -85,10 +74,6 @@ module Guard
85
74
  @state = Internals::State.new(cmdline_options)
86
75
  end
87
76
 
88
- attr_reader :state
89
-
90
- attr_reader :interactor
91
-
92
77
  # Asynchronously trigger changes
93
78
  #
94
79
  # Currently supported args:
@@ -133,21 +118,15 @@ module Guard
133
118
  removed: _relative_pathnames(removed)
134
119
  }
135
120
 
121
+ _guardfile_deprecated_check(relative_paths[:modified])
122
+
136
123
  async_queue_add(relative_paths) if _relevant_changes?(relative_paths)
137
124
  end
138
125
  end
139
126
 
140
127
  # TODO: obsoleted? (move to Dsl?)
141
128
  def _pluginless_guardfile?
142
- # no Reevaluator means there was no Guardfile configured that could be
143
- # reevaluated, so we don't have a pluginless guardfile, because we don't
144
- # have a Guardfile to begin with...
145
- #
146
- # But, if we have a Guardfile, we'll at least have the built-in
147
- # Reevaluator, so the following will work:
148
-
149
- plugins = state.session.plugins.all
150
- plugins.empty? || plugins.map(&:name) == ["reevaluator"]
129
+ state.session.plugins.all.empty?
151
130
  end
152
131
 
153
132
  def _evaluate(options)
@@ -170,5 +149,26 @@ module Guard
170
149
  rescue Guardfile::Evaluator::NoPluginsError => e
171
150
  UI.error(e.message)
172
151
  end
152
+
153
+ # TODO: remove at some point
154
+ # TODO: not tested because collides with ongoing refactoring
155
+ def _guardfile_deprecated_check(modified)
156
+ modified.map!(&:to_s)
157
+ guardfiles = modified.select { |path| /^(?:.+\/)?Guardfile$/.match(path) }
158
+ return if guardfiles.empty?
159
+
160
+ if guardfiles.any? { |path| /^Guardfile$/.match(path) }
161
+ UI.warning <<EOS
162
+ Guardfile changed - Guard will exit so you can restart it manually.
163
+
164
+ More info here: https://github.com/guard/guard/wiki/Guard-2.10.3-exits-when-Guardfile-is-changed
165
+ EOS
166
+ exit 2 # nonzero to break any while loop
167
+ else
168
+ msg = "Config changed: %s - Guard will exit so it can be restarted."
169
+ UI.info format(msg, guardfiles.inspect)
170
+ exit 0 # 0 so any shell while loop can continue
171
+ end
172
+ end
173
173
  end
174
174
  end
@@ -1,9 +1,10 @@
1
1
  require "thor"
2
2
 
3
- require "guard"
4
3
  require "guard/version"
5
- require "guard/guardfile/generator"
4
+
6
5
  require "guard/dsl_describer"
6
+ require "guard/cli/environments/valid"
7
+ require "guard/cli/environments/evaluate_only"
7
8
 
8
9
  module Guard
9
10
  # Facade for the Guard command line interface managed by
@@ -104,8 +105,7 @@ module Guard
104
105
  # @see Guard.start
105
106
  #
106
107
  def start
107
- _verify_bundler_presence unless options[:no_bundler_warning]
108
- _start(options)
108
+ exit(Cli::Environments::Valid.new(options).start_guard)
109
109
  end
110
110
 
111
111
  desc "list", "Lists Guard plugins that can be used with init"
@@ -116,7 +116,7 @@ module Guard
116
116
  # @see Guard::DslDescriber.list
117
117
  #
118
118
  def list
119
- _require_guardfile(options) # just to show which plugins are actually used
119
+ Cli::Environments::EvaluateOnly.new(options).evaluate
120
120
  DslDescriber.new.list
121
121
  end
122
122
 
@@ -127,7 +127,8 @@ module Guard
127
127
  # @see Guard::DslDescriber.notifiers
128
128
  #
129
129
  def notifiers
130
- _require_guardfile(options)
130
+ Cli::Environments::EvaluateOnly.new(options).evaluate
131
+ # TODO: pass the data directly to the notifiers?
131
132
  DslDescriber.new.notifiers
132
133
  end
133
134
 
@@ -164,32 +165,9 @@ module Guard
164
165
  # initialize
165
166
  #
166
167
  def init(*plugin_names)
167
- _verify_bundler_presence unless options[:no_bundler_warning]
168
- bare = options[:bare]
169
-
170
- generator = Guardfile::Generator.new
171
- Guard.init(options)
172
- session = Guard.state.session
173
-
174
- begin
175
- Guardfile::Evaluator.new(session.evaluator_options).evaluate
176
- rescue Guardfile::Evaluator::NoGuardfileError
177
- generator.create_guardfile
178
- end
179
-
180
- return if bare
181
-
182
- # Evaluate because it might have existed and creating was skipped
183
- # FIXME: still, I don't know why this is needed
184
- Guardfile::Evaluator.new(session.evaluator_options).evaluate
185
-
186
- if plugin_names.empty?
187
- generator.initialize_all_templates
188
- else
189
- plugin_names.each do |plugin_name|
190
- generator.initialize_template(plugin_name)
191
- end
192
- end
168
+ env = Cli::Environments::Valid.new(options)
169
+ exitcode = env.initialize_guardfile(plugin_names)
170
+ exit(exitcode)
193
171
  end
194
172
 
195
173
  desc "show", "Show all defined Guard plugins and their options"
@@ -201,53 +179,8 @@ module Guard
201
179
  # @see Guard::DslDescriber.show
202
180
  #
203
181
  def show
204
- _require_guardfile(options)
205
- # TODO: use Metadata class
182
+ Cli::Environments::EvaluateOnly.new(options).evaluate
206
183
  DslDescriber.new.show
207
184
  end
208
-
209
- private
210
-
211
- # Verifies if Guard is run with `bundle exec` and
212
- # shows a hint to do so if not.
213
- #
214
- # TODO: move this elsewhere!!! (because of complex specs)
215
- def _verify_bundler_presence
216
- return unless File.exist?("Gemfile")
217
- return if ENV["BUNDLE_GEMFILE"] || ENV["RUBYGEMS_GEMDEPS"]
218
-
219
- UI.info <<EOF
220
-
221
- Guard here! It looks like your project has a Gemfile, yet you are running
222
- `guard` outside of Bundler. If this is your intent, feel free to ignore this
223
- message. Otherwise, consider using `bundle exec guard` to ensure your
224
- dependencies are loaded correctly.
225
- (You can run `guard` with --no-bundler-warning to get rid of this message.)
226
- EOF
227
- end
228
-
229
- def _require_guardfile(options)
230
- Guard.init(options) # to setup metadata
231
- session = Guard.state.session
232
- Guardfile::Evaluator.new(session.evaluator_options).evaluate
233
- rescue Dsl::Error,
234
- Guardfile::Evaluator::NoPluginsError,
235
- Guardfile::Evaluator::NoGuardfileError,
236
- Guardfile::Evaluator::NoCustomGuardfile => e
237
- # catch to throw message instead of call stack
238
- UI.error(e.message)
239
- abort
240
- end
241
-
242
- def _start(options)
243
- Guard.start(options)
244
- rescue Dsl::Error,
245
- Guardfile::Evaluator::NoPluginsError,
246
- Guardfile::Evaluator::NoGuardfileError,
247
- Guardfile::Evaluator::NoCustomGuardfile => e
248
- # catch to throw message instead of call stack
249
- UI.error(e.message)
250
- abort
251
- end
252
185
  end
253
186
  end
@@ -0,0 +1,22 @@
1
+ require "guard/ui"
2
+
3
+ module Guard
4
+ module Cli
5
+ module Environments
6
+ class Bundler
7
+ def verify
8
+ return unless File.exist?("Gemfile")
9
+ return if ENV["BUNDLE_GEMFILE"] || ENV["RUBYGEMS_GEMDEPS"]
10
+ UI.info <<EOF
11
+
12
+ Guard here! It looks like your project has a Gemfile, yet you are running
13
+ `guard` outside of Bundler. If this is your intent, feel free to ignore this
14
+ message. Otherwise, consider using `bundle exec guard` to ensure your
15
+ dependencies are loaded correctly.
16
+ (You can run `guard` with --no-bundler-warning to get rid of this message.)
17
+ EOF
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,35 @@
1
+ require "guard"
2
+
3
+ module Guard
4
+ module Cli
5
+ module Environments
6
+ class EvaluateOnly
7
+ def initialize(options)
8
+ @options = options
9
+ end
10
+
11
+ def evaluate
12
+ # TODO: check bundler setup first?
13
+ #
14
+ # TODO: it should be easier to pass options created with init
15
+ # directly to evaluator
16
+ #
17
+ # TODO: guardfile/DSL should interact only with a given object, and
18
+ # not global Guard object (setting global state only needed before
19
+ # start() is called)
20
+ #
21
+ Guard.init(@options)
22
+ session = Guard.state.session
23
+ Guardfile::Evaluator.new(session.evaluator_options).evaluate
24
+ rescue \
25
+ Dsl::Error,
26
+ Guardfile::Evaluator::NoPluginsError,
27
+ Guardfile::Evaluator::NoGuardfileError,
28
+ Guardfile::Evaluator::NoCustomGuardfile => e
29
+ UI.error(e.message)
30
+ abort
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,59 @@
1
+ require "guard/cli/environments/bundler"
2
+ require "guard/commander"
3
+ require "guard/guardfile/generator"
4
+
5
+ module Guard
6
+ module Cli
7
+ module Environments
8
+ class Valid
9
+ def initialize(options)
10
+ @options = options
11
+ end
12
+
13
+ def start_guard
14
+ # TODO: just to make sure tests are ok
15
+ Bundler.new.verify unless @options[:no_bundler_warning]
16
+ Guard.start(@options)
17
+ rescue Dsl::Error,
18
+ Guardfile::Evaluator::NoPluginsError,
19
+ Guardfile::Evaluator::NoGuardfileError,
20
+ Guardfile::Evaluator::NoCustomGuardfile => e
21
+ # catch to throw message instead of call stack
22
+ UI.error(e.message)
23
+ abort
24
+ end
25
+
26
+ def initialize_guardfile(plugin_names = [])
27
+ bare = @options[:bare]
28
+
29
+ Guard.init(@options)
30
+ session = Guard.state.session
31
+
32
+ generator = Guardfile::Generator.new
33
+ begin
34
+ Guardfile::Evaluator.new(session.evaluator_options).evaluate
35
+ rescue Guardfile::Evaluator::NoGuardfileError
36
+ generator.create_guardfile
37
+ end
38
+
39
+ return 0 if bare # 0 - exit code
40
+
41
+ # Evaluate because it might have existed and creating was skipped
42
+ # FIXME: still, I don't know why this is needed
43
+ Guardfile::Evaluator.new(session.evaluator_options).evaluate
44
+
45
+ if plugin_names.empty?
46
+ generator.initialize_all_templates
47
+ else
48
+ plugin_names.each do |plugin_name|
49
+ generator.initialize_template(plugin_name)
50
+ end
51
+ end
52
+ # TODO: capture exceptions to show msg and return exit code on
53
+ # failures
54
+ 0 # exit code
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -3,9 +3,9 @@ require "listen"
3
3
  require "guard/notifier"
4
4
  require "guard/interactor"
5
5
  require "guard/runner"
6
- require "guard/reevaluator"
7
6
  require "guard/dsl_describer"
8
- require "guard"
7
+
8
+ require "guard/internals/state"
9
9
 
10
10
  module Guard
11
11
  # Commands supported by guard
@@ -37,14 +37,18 @@ module Guard
37
37
  watched = Guard.state.session.watchdirs.join("', '")
38
38
  UI.info "Guard is now watching at '#{ watched }'"
39
39
 
40
+ exitcode = 0
40
41
  begin
41
42
  while interactor.foreground != :exit
42
43
  Guard.queue.process while Guard.queue.pending?
43
44
  end
44
45
  rescue Interrupt
46
+ rescue SystemExit => e
47
+ exitcode = e.status
45
48
  end
46
49
 
47
50
  stop
51
+ exitcode
48
52
  end
49
53
 
50
54
  def stop
@@ -63,15 +67,9 @@ module Guard
63
67
  # @param [Hash] scopes hash with a Guard plugin or a group scope
64
68
  #
65
69
  def reload(scopes = {})
66
- # TODO: guard reevaluator should probably handle all this
67
70
  UI.clear(force: true)
68
71
  UI.action_with_scopes("Reload", scopes)
69
-
70
- if scopes.empty?
71
- Reevaluator.new.reevaluate
72
- else
73
- Runner.new.run(:reload, scopes)
74
- end
72
+ Runner.new.run(:reload, scopes)
75
73
  end
76
74
 
77
75
  # Trigger `run_all` on all Guard plugins currently enabled.
@@ -1,7 +1,6 @@
1
1
  # required for async_queue_add
2
2
  require "pry"
3
3
 
4
- require "guard/interactor"
5
4
  require "guard"
6
5
 
7
6
  module Guard
@@ -22,7 +21,7 @@ module Guard
22
21
  BANNER
23
22
 
24
23
  def process(*entries)
25
- scopes, unknown = Interactor.convert_scope(entries)
24
+ scopes, unknown = ::Guard.state.session.convert_scope(entries)
26
25
 
27
26
  unless unknown.empty?
28
27
  output.puts "Unknown scopes: #{ unknown.join(", ") }"
@@ -1,6 +1,5 @@
1
1
  require "pry"
2
2
 
3
- require "guard/interactor"
4
3
  require "guard"
5
4
 
6
5
  module Guard
@@ -21,7 +20,7 @@ module Guard
21
20
  BANNER
22
21
 
23
22
  def process(*entries)
24
- scopes, unknown = Interactor.convert_scope(entries)
23
+ scopes, unknown = ::Guard.state.session.convert_scope(entries)
25
24
 
26
25
  unless unknown.empty?
27
26
  output.puts "Unknown scopes: #{ unknown.join(", ") }"