joshbuddy-guard 0.10.0

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.
Files changed (70) hide show
  1. data/CHANGELOG.md +370 -0
  2. data/LICENSE +20 -0
  3. data/README.md +470 -0
  4. data/bin/fsevent_watch_guard +0 -0
  5. data/bin/guard +6 -0
  6. data/images/failed.png +0 -0
  7. data/images/pending.png +0 -0
  8. data/images/success.png +0 -0
  9. data/lib/guard.rb +463 -0
  10. data/lib/guard/cli.rb +125 -0
  11. data/lib/guard/dsl.rb +370 -0
  12. data/lib/guard/dsl_describer.rb +150 -0
  13. data/lib/guard/group.rb +37 -0
  14. data/lib/guard/guard.rb +129 -0
  15. data/lib/guard/hook.rb +118 -0
  16. data/lib/guard/interactor.rb +116 -0
  17. data/lib/guard/listener.rb +351 -0
  18. data/lib/guard/listeners/darwin.rb +60 -0
  19. data/lib/guard/listeners/linux.rb +91 -0
  20. data/lib/guard/listeners/polling.rb +55 -0
  21. data/lib/guard/listeners/windows.rb +61 -0
  22. data/lib/guard/notifier.rb +290 -0
  23. data/lib/guard/templates/Guardfile +2 -0
  24. data/lib/guard/ui.rb +193 -0
  25. data/lib/guard/version.rb +6 -0
  26. data/lib/guard/watcher.rb +114 -0
  27. data/lib/vendor/darwin/Gemfile +6 -0
  28. data/lib/vendor/darwin/Guardfile +8 -0
  29. data/lib/vendor/darwin/LICENSE +20 -0
  30. data/lib/vendor/darwin/README.rdoc +254 -0
  31. data/lib/vendor/darwin/Rakefile +21 -0
  32. data/lib/vendor/darwin/ext/extconf.rb +61 -0
  33. data/lib/vendor/darwin/ext/fsevent/fsevent_watch.c +226 -0
  34. data/lib/vendor/darwin/lib/rb-fsevent.rb +2 -0
  35. data/lib/vendor/darwin/lib/rb-fsevent/fsevent.rb +105 -0
  36. data/lib/vendor/darwin/lib/rb-fsevent/version.rb +3 -0
  37. data/lib/vendor/darwin/rb-fsevent.gemspec +24 -0
  38. data/lib/vendor/darwin/spec/fixtures/folder1/file1.txt +0 -0
  39. data/lib/vendor/darwin/spec/fixtures/folder1/folder2/file2.txt +0 -0
  40. data/lib/vendor/darwin/spec/rb-fsevent/fsevent_spec.rb +75 -0
  41. data/lib/vendor/darwin/spec/spec_helper.rb +24 -0
  42. data/lib/vendor/linux/MIT-LICENSE +20 -0
  43. data/lib/vendor/linux/README.md +66 -0
  44. data/lib/vendor/linux/Rakefile +54 -0
  45. data/lib/vendor/linux/VERSION +1 -0
  46. data/lib/vendor/linux/lib/rb-inotify.rb +17 -0
  47. data/lib/vendor/linux/lib/rb-inotify/event.rb +139 -0
  48. data/lib/vendor/linux/lib/rb-inotify/native.rb +31 -0
  49. data/lib/vendor/linux/lib/rb-inotify/native/flags.rb +89 -0
  50. data/lib/vendor/linux/lib/rb-inotify/notifier.rb +308 -0
  51. data/lib/vendor/linux/lib/rb-inotify/watcher.rb +83 -0
  52. data/lib/vendor/linux/rb-inotify.gemspec +53 -0
  53. data/lib/vendor/windows/Gemfile +4 -0
  54. data/lib/vendor/windows/README.md +34 -0
  55. data/lib/vendor/windows/Rakefile +18 -0
  56. data/lib/vendor/windows/lib/rb-fchange.rb +14 -0
  57. data/lib/vendor/windows/lib/rb-fchange/event.rb +29 -0
  58. data/lib/vendor/windows/lib/rb-fchange/native.rb +45 -0
  59. data/lib/vendor/windows/lib/rb-fchange/native/flags.rb +78 -0
  60. data/lib/vendor/windows/lib/rb-fchange/notifier.rb +149 -0
  61. data/lib/vendor/windows/lib/rb-fchange/version.rb +3 -0
  62. data/lib/vendor/windows/lib/rb-fchange/watcher.rb +99 -0
  63. data/lib/vendor/windows/rb-fchange.gemspec +34 -0
  64. data/lib/vendor/windows/spec/fixtures/folder1/file1.txt +0 -0
  65. data/lib/vendor/windows/spec/fixtures/folder1/folder2/file2.txt +0 -0
  66. data/lib/vendor/windows/spec/rb-fchange/fchange_spec.rb +119 -0
  67. data/lib/vendor/windows/spec/spec_helper.rb +21 -0
  68. data/man/guard.1 +96 -0
  69. data/man/guard.1.html +181 -0
  70. metadata +193 -0
@@ -0,0 +1,125 @@
1
+ require 'thor'
2
+ require 'guard/version'
3
+
4
+ module Guard
5
+
6
+ # Facade for the Guard command line interface managed by [Thor](https://github.com/wycats/thor).
7
+ # This is the main interface to Guard that is called by the Guard binary `bin/guard`.
8
+ # Do not put any logic in here, create a class and delegate instead.
9
+ #
10
+ class CLI < Thor
11
+
12
+ default_task :start
13
+
14
+ desc 'start', 'Starts Guard'
15
+
16
+ method_option :clear,
17
+ :type => :boolean,
18
+ :default => false,
19
+ :aliases => '-c',
20
+ :banner => 'Auto clear shell before each change/run_all/reload'
21
+
22
+ method_option :notify,
23
+ :type => :boolean,
24
+ :default => true,
25
+ :aliases => '-n',
26
+ :banner => 'Notifications feature (growl/libnotify)'
27
+
28
+ method_option :debug,
29
+ :type => :boolean,
30
+ :default => false,
31
+ :aliases => '-d',
32
+ :banner => 'Print debug messages'
33
+
34
+ method_option :group,
35
+ :type => :array,
36
+ :default => [],
37
+ :aliases => '-g',
38
+ :banner => 'Run only the passed groups'
39
+
40
+ method_option :watchdir,
41
+ :type => :string,
42
+ :aliases => '-w',
43
+ :banner => 'Specify the directory to watch'
44
+
45
+ method_option :guardfile,
46
+ :type => :string,
47
+ :aliases => '-G',
48
+ :banner => 'Specify a Guardfile'
49
+
50
+ method_option :no_vendor,
51
+ :type => :boolean,
52
+ :default => false,
53
+ :aliases => '-I',
54
+ :banner => 'Ignore vendored dependencies'
55
+
56
+ method_option :watch_all_modifications,
57
+ :type => :boolean,
58
+ :default => false,
59
+ :aliases => '-A',
60
+ :banner => 'Watch for all file modifications including moves and deletions'
61
+
62
+ method_option :no_interactions,
63
+ :type => :boolean,
64
+ :default => false,
65
+ :aliases => '-i',
66
+ :banner => 'Turn off completely any guard terminal interactions'
67
+
68
+ # Start Guard by initialize the defined Guards and watch the file system.
69
+ # This is the default task, so calling `guard` is the same as calling `guard start`.
70
+ #
71
+ # @see Guard.start
72
+ #
73
+ def start
74
+ ::Guard.start(options)
75
+ end
76
+
77
+ desc 'list', 'Lists guards that can be used with init'
78
+
79
+ # List the Guards that are available for use in your system and marks
80
+ # those that are currently used in your `Guardfile`.
81
+ #
82
+ # @see Guard::DslDescriber.list
83
+ #
84
+ def list
85
+ ::Guard::DslDescriber.list(options)
86
+ end
87
+
88
+ desc 'version', 'Show the Guard version'
89
+ map %w(-v --version) => :version
90
+
91
+ # Shows the current version of Guard.
92
+ #
93
+ # @see Guard::VERSION
94
+ #
95
+ def version
96
+ ::Guard::UI.info "Guard version #{ Guard::VERSION }"
97
+ end
98
+
99
+ desc 'init [GUARD]', 'Generates a Guardfile at the current working directory, or insert the given GUARD to an existing Guardfile'
100
+
101
+ # Appends the Guard template to the `Guardfile`, or creates an initial
102
+ # `Guardfile` when no Guard name is passed.
103
+ #
104
+ # @see Guard.initialize_template
105
+ #
106
+ # @param [String] guard_name the name of the Guard to initialize
107
+ #
108
+ def init(guard_name = nil)
109
+ ::Guard.initialize_template(guard_name)
110
+ end
111
+
112
+ desc 'show', 'Show all defined Guards and their options'
113
+ map %w(-T) => :show
114
+
115
+ # Shows all Guards and their options that are defined in
116
+ # the `Guardfile`.
117
+ #
118
+ # @see Guard::DslDescriber.show
119
+ #
120
+ def show
121
+ ::Guard::DslDescriber.show(options)
122
+ end
123
+
124
+ end
125
+ end
@@ -0,0 +1,370 @@
1
+ module Guard
2
+
3
+ # The DSL class provides the methods that are used in each `Guardfile` to describe
4
+ # the behaviour of Guard.
5
+ #
6
+ # The main keywords of the DSL are `guard` and `watch`. These are necessary to define
7
+ # the used Guards and the file changes they are watching.
8
+ #
9
+ # You can optionally group the Guards with the `group` keyword and ignore certain paths
10
+ # with the `ignore_paths` keyword.
11
+ #
12
+ # A more advanced DSL use is the `callback` keyword that allows you to execute arbitrary
13
+ # code before or after any of the `start`, `stop`, `reload`, `run_all` and `run_on_change`
14
+ # Guards' method. You can even insert more hooks inside these methods.
15
+ # Please [checkout the Wiki page](https://github.com/guard/guard/wiki/Hooks-and-callbacks) for more details.
16
+ #
17
+ # The DSL will also evaluate normal Ruby code.
18
+ #
19
+ # There are two possible locations for the `Guardfile`:
20
+ # - The `Guardfile` in the current directory where Guard has been started
21
+ # - The `.Guardfile` in your home directory.
22
+ #
23
+ # In addition, if a user configuration `.guard.rb` in your home directory is found, it will
24
+ # be appended to the current project `Guardfile`.
25
+ #
26
+ # @example A sample of a complex Guardfile
27
+ #
28
+ # group 'frontend' do
29
+ # guard 'passenger', :ping => true do
30
+ # watch('config/application.rb')
31
+ # watch('config/environment.rb')
32
+ # watch(%r{^config/environments/.+\.rb})
33
+ # watch(%r{^config/initializers/.+\.rb})
34
+ # end
35
+ #
36
+ # guard 'livereload', :apply_js_live => false do
37
+ # watch(%r{^app/.+\.(erb|haml)})
38
+ # watch(%r{^app/helpers/.+\.rb})
39
+ # watch(%r{^public/javascripts/.+\.js})
40
+ # watch(%r{^public/stylesheets/.+\.css})
41
+ # watch(%r{^public/.+\.html})
42
+ # watch(%r{^config/locales/.+\.yml})
43
+ # end
44
+ # end
45
+ #
46
+ # group 'backend' do
47
+ # # Reload the bundle when the Gemfile is modified
48
+ # guard 'bundler' do
49
+ # watch('Gemfile')
50
+ # end
51
+ #
52
+ # # for big project you can fine tune the "timeout" before Spork's launch is considered failed
53
+ # guard 'spork', :wait => 40 do
54
+ # watch('Gemfile')
55
+ # watch('config/application.rb')
56
+ # watch('config/environment.rb')
57
+ # watch(%r{^config/environments/.+\.rb})
58
+ # watch(%r{^config/initializers/.+\.rb})
59
+ # watch('spec/spec_helper.rb')
60
+ # end
61
+ #
62
+ # # use RSpec 2, from the system's gem and with some direct RSpec CLI options
63
+ # guard 'rspec', :version => 2, :cli => "--color --drb -f doc", :bundler => false do
64
+ # watch('spec/spec_helper.rb') { "spec" }
65
+ # watch('app/controllers/application_controller.rb') { "spec/controllers" }
66
+ # watch('config/routes.rb') { "spec/routing" }
67
+ # watch(%r{^spec/support/(controllers|acceptance)_helpers\.rb}) { |m| "spec/#{m[1]}" }
68
+ # watch(%r{^spec/.+_spec\.rb})
69
+ #
70
+ # watch(%r{^app/controllers/(.+)_(controller)\.rb}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
71
+ #
72
+ # watch(%r{^app/(.+)\.rb}) { |m| "spec/#{m[1]}_spec.rb" }
73
+ # watch(%r{^lib/(.+)\.rb}) { |m| "spec/lib/#{m[1]}_spec.rb" }
74
+ # end
75
+ # end
76
+ #
77
+ class Dsl
78
+ class << self
79
+
80
+ @@options = nil
81
+
82
+ # Evaluate the DSL methods in the `Guardfile`.
83
+ #
84
+ # @option options [Array<Symbol,String>] groups the groups to evaluate
85
+ # @option options [String] guardfile the path to a valid Guardfile
86
+ # @option options [String] guardfile_contents a string representing the content of a valid Guardfile
87
+ # @raise [ArgumentError] when options are not a Hash
88
+ #
89
+ def evaluate_guardfile(options = {})
90
+ raise ArgumentError.new('No option hash passed to evaluate_guardfile!') unless options.is_a?(Hash)
91
+
92
+ @@options = options.dup
93
+
94
+ fetch_guardfile_contents
95
+ instance_eval_guardfile(guardfile_contents_with_user_config)
96
+
97
+ UI.error 'No guards found in Guardfile, please add at least one.' if !::Guard.guards.nil? && ::Guard.guards.empty?
98
+ end
99
+
100
+ # Re-evaluate the `Guardfile` to update the current Guard configuration.
101
+ #
102
+ def reevaluate_guardfile
103
+ ::Guard.guards.clear
104
+ ::Guard.reset_groups
105
+ @@options.delete(:guardfile_contents)
106
+ Dsl.evaluate_guardfile(@@options)
107
+ msg = 'Guardfile has been re-evaluated.'
108
+ UI.info(msg)
109
+ Notifier.notify(msg)
110
+ end
111
+
112
+ # Evaluate the content of the `Guardfile`.
113
+ #
114
+ # @param [String] contents the content to evaluate.
115
+ #
116
+ def instance_eval_guardfile(contents)
117
+ new.instance_eval(contents, @@options[:guardfile_path], 1)
118
+ rescue
119
+ UI.error "Invalid Guardfile, original error is:\n#{ $! }"
120
+ exit 1
121
+ end
122
+
123
+ # Test if the current `Guardfile` contains a specific Guard.
124
+ #
125
+ # @param [String] guard_name the name of the Guard
126
+ # @return [Boolean] whether the Guard has been declared
127
+ #
128
+ def guardfile_include?(guard_name)
129
+ guardfile_contents.match(/^guard\s*\(?\s*['":]#{ guard_name }['"]?/)
130
+ end
131
+
132
+ # Read the current `Guardfile` content.
133
+ #
134
+ # @param [String] the path to the Guardfile
135
+ #
136
+ def read_guardfile(guardfile_path)
137
+ @@options[:guardfile_path] = guardfile_path
138
+ @@options[:guardfile_contents] = File.read(guardfile_path)
139
+ rescue
140
+ UI.error("Error reading file #{ guardfile_path }")
141
+ exit 1
142
+ end
143
+
144
+ # Get the content to evaluate and stores it into
145
+ # the options as `:guardfile_contents`.
146
+ #
147
+ def fetch_guardfile_contents
148
+ if @@options[:guardfile_contents]
149
+ UI.info 'Using inline Guardfile.'
150
+ @@options[:guardfile_path] = 'Inline Guardfile'
151
+
152
+ elsif @@options[:guardfile]
153
+ if File.exist?(@@options[:guardfile])
154
+ read_guardfile(@@options[:guardfile])
155
+ UI.info "Using Guardfile at #{ @@options[:guardfile] }."
156
+ else
157
+ UI.error "No Guardfile exists at #{ @@options[:guardfile] }."
158
+ exit 1
159
+ end
160
+
161
+ else
162
+ if File.exist?(guardfile_default_path)
163
+ read_guardfile(guardfile_default_path)
164
+ else
165
+ UI.error 'No Guardfile found, please create one with `guard init`.'
166
+ exit 1
167
+ end
168
+ end
169
+
170
+ unless guardfile_contents_usable?
171
+ UI.error "The command file(#{ @@options[:guardfile] }) seems to be empty."
172
+ exit 1
173
+ end
174
+ end
175
+
176
+ # Get the content of the `Guardfile`.
177
+ #
178
+ # @return [String] the Guardfile content
179
+ #
180
+ def guardfile_contents
181
+ @@options ? @@options[:guardfile_contents] : ''
182
+ end
183
+
184
+ # Get the content of the `Guardfile` and the global
185
+ # user configuration file.
186
+ #
187
+ # @see #user_config_path
188
+ #
189
+ # @return [String] the Guardfile content
190
+ #
191
+ def guardfile_contents_with_user_config
192
+ config = File.read(user_config_path) if File.exist?(user_config_path)
193
+ [guardfile_contents, config].join("\n")
194
+ end
195
+
196
+ # Get the file path to the project `Guardfile`.
197
+ #
198
+ # @return [String] the path to the Guardfile
199
+ #
200
+ def guardfile_path
201
+ @@options ? @@options[:guardfile_path] : ''
202
+ end
203
+
204
+ # Tests if the current `Guardfile` content is usable.
205
+ #
206
+ # @return [Boolean] if the Guardfile is usable
207
+ #
208
+ def guardfile_contents_usable?
209
+ guardfile_contents && guardfile_contents.size >= 'guard :a'.size # Smallest Guard definition
210
+ end
211
+
212
+ # Gets the default path of the `Guardfile`. This returns the `Guardfile`
213
+ # from the current directory when existing, or the global `.Guardfile`
214
+ # at the home directory.
215
+ #
216
+ # @return [String] the path to the Guardfile
217
+ #
218
+ def guardfile_default_path
219
+ File.exist?(local_guardfile_path) ? local_guardfile_path : home_guardfile_path
220
+ end
221
+
222
+ private
223
+
224
+ # The path to the `Guardfile` that is located at
225
+ # the directory, where Guard has been started from.
226
+ #
227
+ # @param [String] the path to the local Guardfile
228
+ #
229
+ def local_guardfile_path
230
+ File.join(Dir.pwd, 'Guardfile')
231
+ end
232
+
233
+ # The path to the `.Guardfile` that is located at
234
+ # the users home directory.
235
+ #
236
+ # @param [String] the path to ~/.Guardfile
237
+ #
238
+ def home_guardfile_path
239
+ File.expand_path(File.join('~', '.Guardfile'))
240
+ end
241
+
242
+ # The path to the user configuration `.guard.rb`
243
+ # that is located at the users home directory.
244
+ #
245
+ # @param [String] the path to ~/.guard.rb
246
+ #
247
+ def user_config_path
248
+ File.expand_path(File.join('~', '.guard.rb'))
249
+ end
250
+
251
+ end
252
+
253
+ # Declares a group of guards to be run with `guard start --group group_name`.
254
+ #
255
+ # @example Declare two groups of Guards
256
+ #
257
+ # group 'backend' do
258
+ # guard 'spork'
259
+ # guard 'rspec'
260
+ # end
261
+ #
262
+ # group 'frontend' do
263
+ # guard 'passenger'
264
+ # guard 'livereload'
265
+ # end
266
+ #
267
+ # @param [Symbol, String] name the group's name called from the CLI
268
+ # @param [Hash] options the options accepted by the group
269
+ # @yield a block where you can declare several guards
270
+ #
271
+ # @see Guard.add_group
272
+ # @see Dsl#guard
273
+ # @see Guard::DslDescriber
274
+ #
275
+ def group(name, options = {})
276
+ @groups = @@options[:group] || []
277
+ name = name.to_sym
278
+
279
+ if block_given? && (@groups.empty? || @groups.map(&:to_sym).include?(name))
280
+ ::Guard.add_group(name.to_s.downcase, options)
281
+ @current_group = name
282
+
283
+ yield if block_given?
284
+
285
+ @current_group = nil
286
+ end
287
+ end
288
+
289
+ # Declare a guard to be used when running `guard start`.
290
+ #
291
+ # The name parameter is usually the name of the gem without
292
+ # the 'guard-' prefix.
293
+ #
294
+ # The available options are different for each Guard implementation.
295
+ #
296
+ # @example Declare a Guard
297
+ #
298
+ # guard 'rspec' do
299
+ # end
300
+ #
301
+ # @param [String] name the Guard name
302
+ # @param [Hash] options the options accepted by the Guard
303
+ # @yield a block where you can declare several watch patterns and actions
304
+ #
305
+ # @see Guard.add_guard
306
+ # @see Dsl#group
307
+ # @see Dsl#watch
308
+ # @see Guard::DslDescriber
309
+ #
310
+ def guard(name, options = {})
311
+ @watchers = []
312
+ @callbacks = []
313
+
314
+ yield if block_given?
315
+
316
+ options.update(:group => (@current_group || :default))
317
+ ::Guard.add_guard(name.to_s.downcase, @watchers, @callbacks, options)
318
+ end
319
+
320
+ # Define a pattern to be watched in order to run actions on file modification.
321
+ #
322
+ # @example Declare watchers for a Guard
323
+ #
324
+ # guard 'rspec' do
325
+ # watch('spec/spec_helper.rb')
326
+ # watch(%r{^.+_spec.rb})
327
+ # watch(%r{^app/controllers/(.+).rb}) { |m| 'spec/acceptance/#{m[1]}s_spec.rb' }
328
+ # end
329
+ #
330
+ # @param [String, Regexp] pattern the pattern to be watched by the guard
331
+ # @yield a block to be run when the pattern is matched
332
+ # @yieldparam [MatchData] m matches of the pattern
333
+ # @yieldreturn a directory, a filename, an array of directories / filenames, or nothing (can be an arbitrary command)
334
+ #
335
+ # @see Guard::Watcher
336
+ # @see Dsl#guard
337
+ #
338
+ def watch(pattern, &action)
339
+ @watchers << ::Guard::Watcher.new(pattern, action)
340
+ end
341
+
342
+ # Define a callback to execute arbitrary code before or after any of
343
+ # the `start`, `stop`, `reload`, `run_all` and `run_on_change` guards' method.
344
+ #
345
+ # @param [Array] args the callback arguments
346
+ # @yield a block with listeners
347
+ #
348
+ # @see Guard::Hook
349
+ #
350
+ def callback(*args, &listener)
351
+ listener, events = args.size > 1 ? args : [listener, args[0]]
352
+ @callbacks << { :events => events, :listener => listener }
353
+ end
354
+
355
+ # Ignore certain paths globally.
356
+ #
357
+ # @example Ignore some paths
358
+ # ignore_paths ".git", ".svn"
359
+ #
360
+ # @param [Array] paths the list of paths to ignore
361
+ #
362
+ # @see Guard::Listener
363
+ #
364
+ def ignore_paths(*paths)
365
+ UI.info "Ignoring paths: #{ paths.join(', ') }"
366
+ ::Guard.listener.ignore_paths.push(*paths)
367
+ end
368
+
369
+ end
370
+ end