autotest 4.1.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,61 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{autotest}
8
+ s.version = "4.1.4"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Ryan Davis"]
12
+ s.date = %q{2009-12-19}
13
+ s.executables = ["unit_diff", "autotest"]
14
+ s.extra_rdoc_files = [
15
+ "README.markdown"
16
+ ]
17
+ s.files = [
18
+ ".autotest",
19
+ ".gitignore",
20
+ "History.txt",
21
+ "README.markdown",
22
+ "Rakefile",
23
+ "VERSION",
24
+ "articles/getting_started_with_autotest.html",
25
+ "autotest.gemspec",
26
+ "bin/autotest",
27
+ "bin/unit_diff",
28
+ "example_dot_autotest.rb",
29
+ "lib/autotest.rb",
30
+ "lib/autotest/autoupdate.rb",
31
+ "lib/autotest/once.rb",
32
+ "lib/autotest/rcov.rb",
33
+ "lib/autotest/restart.rb",
34
+ "lib/autotest/timestamp.rb",
35
+ "lib/unit_diff.rb",
36
+ "test/helper.rb",
37
+ "test/test_autotest.rb",
38
+ "test/test_unit_diff.rb"
39
+ ]
40
+ s.homepage = %q{http://github.com/grosser/autotest}
41
+ s.rdoc_options = ["--charset=UTF-8"]
42
+ s.require_paths = ["lib"]
43
+ s.rubygems_version = %q{1.3.5}
44
+ s.summary = %q{Autotest, without ZenTest}
45
+ s.test_files = [
46
+ "test/test_autotest.rb",
47
+ "test/helper.rb",
48
+ "test/test_unit_diff.rb"
49
+ ]
50
+
51
+ if s.respond_to? :specification_version then
52
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
53
+ s.specification_version = 3
54
+
55
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
56
+ else
57
+ end
58
+ else
59
+ end
60
+ end
61
+
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'optparse'
4
+
5
+ options = {}
6
+ OptionParser.new do |opts|
7
+ opts.banner = <<BANNER
8
+ Continuouse testing for your ruby app.
9
+
10
+ Usage:
11
+ autotest [options]
12
+ BANNER
13
+ opts.on("-f", "--fast-start","Do not run full tests at start") { options[:no_full_after_start] = true }
14
+ opts.on("-c", "--no-full-after-failed","Do not run full tests after failed test passed") { options[:no_full_after_failed] = true }
15
+ opts.on("-v", "--verbose","Be verbose. Prints files that autotest doesn't know how to map to tests") { options[:verbose] = true }
16
+ opts.on("-q", "--quiet","Be quiet.") { options[:quiet] = true }
17
+ opts.on("-h", "--help","Show this.") { puts opts;exit }
18
+ end.parse!
19
+
20
+ #TODO remove this ? what does it do ?
21
+ class Dir
22
+ class << self
23
+ alias :old_index :[]
24
+ def [](*args)
25
+ $-w, old_warn = false, $-w
26
+ old_index(*args)
27
+ ensure
28
+ $-w = old_warn
29
+ end
30
+ end
31
+ end
32
+
33
+ #run the correct Autotest variant fitting to the local structure
34
+ require 'autotest'
35
+ Autotest.options.merge!(options)
36
+ target = Autotest
37
+ style = Autotest.autodiscover
38
+ unless style.empty? then
39
+ mod = "autotest/#{style.join("_")}"
40
+ puts "loading #{mod}" unless options[:quiet]
41
+ begin
42
+ require mod
43
+ rescue LoadError
44
+ abort "Autotest style #{mod} doesn't seem to exist. Aborting."
45
+ end
46
+ target = Autotest.const_get(style.map {|s| s.capitalize}.join)
47
+ end
48
+ target.run
@@ -0,0 +1,37 @@
1
+ #!/usr/local/bin/ruby -ws
2
+ #
3
+ # unit_diff - a ruby unit test filter by Ryan Davis <ryand-ruby@zenspider.com>
4
+ #
5
+ # usage:
6
+ #
7
+ # test.rb | unit_diff [options]
8
+ # options:
9
+ # -b ignore whitespace differences
10
+ # -c contextual diff
11
+ # -h show usage
12
+ # -k keep temp diff files around
13
+ # -u unified diff
14
+ # -v display version
15
+
16
+ require 'unit_diff'
17
+
18
+ ############################################################
19
+
20
+ #TODO fix this...
21
+ if defined? $v then
22
+ puts "#{File.basename $0} v. 4.0.3"
23
+ exit 0
24
+ end
25
+
26
+ if defined? $h then
27
+ File.open(__FILE__) do |f|
28
+ begin; end until f.readline =~ /usage:/
29
+ f.readline
30
+ while line = f.readline and line.sub!(/^# ?/, '')
31
+ $stderr.puts line
32
+ end
33
+ end
34
+ exit 0
35
+ end
36
+
37
+ UnitDiff.unit_diff
@@ -0,0 +1,12 @@
1
+ # -*- ruby -*-
2
+
3
+ # require 'autotest/autoupdate'
4
+ # require 'autotest/once'
5
+ # require 'autotest/rcov'
6
+ # require 'autotest/restart'
7
+ # require 'autotest/timestamp'
8
+
9
+ # Autotest::AutoUpdate.sleep_time = o
10
+ # Autotest::AutoUpdate.update_cmd = o
11
+ # Autotest::RCov.command = o
12
+ # Autotest::RCov.pattern = o
@@ -0,0 +1,670 @@
1
+ require 'find'
2
+ require 'rbconfig'
3
+
4
+ $TESTING = false unless defined? $TESTING
5
+
6
+ ##
7
+ # Autotest continuously scans the files in your project for changes
8
+ # and runs the appropriate tests. Test failures are run until they
9
+ # have all passed. Then the full test suite is run to ensure that
10
+ # nothing else was inadvertantly broken.
11
+ #
12
+ # If you want Autotest to start over from the top, hit ^C once. If
13
+ # you want Autotest to quit, hit ^C twice.
14
+ #
15
+ # Rails:
16
+ #
17
+ # The autotest command will automatically discover a Rails directory
18
+ # by looking for config/environment.rb. When Rails is discovered,
19
+ # autotest uses RailsAutotest to perform file mappings and other work.
20
+ # See RailsAutotest for details.
21
+ #
22
+ # Plugins:
23
+ #
24
+ # Plugins are available by creating a .autotest file either in your
25
+ # project root or in your home directory. You can then write event
26
+ # handlers in the form of:
27
+ #
28
+ # Autotest.add_hook hook_name { |autotest| ... }
29
+ #
30
+ # The available hooks are listed in +ALL_HOOKS+.
31
+ #
32
+ # See example_dot_autotest.rb for more details.
33
+ #
34
+ # If a hook returns a true value, it signals to autotest that the hook
35
+ # was handled and should not continue executing hooks.
36
+ #
37
+ # Naming:
38
+ #
39
+ # Autotest uses a simple naming scheme to figure out how to map
40
+ # implementation files to test files following the Test::Unit naming
41
+ # scheme.
42
+ #
43
+ # * Test files must be stored in test/
44
+ # * Test files names must start with test_
45
+ # * Test class names must start with Test
46
+ # * Implementation files must be stored in lib/
47
+ # * Implementation files must match up with a test file named
48
+ # test_.*implementation.rb
49
+ #
50
+ # Strategy:
51
+ #
52
+ # 1. Find all files and associate them from impl <-> test.
53
+ # 2. Run all tests.
54
+ # 3. Scan for failures.
55
+ # 4. Detect changes in ANY (ruby?. file, rerun all failures + changed files.
56
+ # 5. Until 0 defects, goto 3.
57
+ # 6. When 0 defects, goto 2.
58
+
59
+ class Autotest
60
+
61
+ VERSION = File.read( File.join(File.dirname(__FILE__),'..','VERSION') ).strip
62
+
63
+ T0 = Time.at 0
64
+
65
+ ALL_HOOKS = [ :all_good, :died, :green, :initialize, :interrupt, :quit,
66
+ :ran_command, :red, :reset, :run_command, :updated, :waiting ]
67
+
68
+ @@options = {}
69
+ def self.options;@@options;end
70
+ def options;@@options;end
71
+
72
+
73
+ HOOKS = Hash.new { |h,k| h[k] = [] } #unfound keys are []
74
+ unless defined? WINDOZE then
75
+ WINDOZE = /win32/ =~ RUBY_PLATFORM
76
+ SEP = WINDOZE ? '&' : ';'
77
+ end
78
+
79
+ @@discoveries = []
80
+
81
+ ##
82
+ # Add a proc to the collection of discovery procs. See
83
+ # +autodiscover+.
84
+
85
+ def self.add_discovery &proc
86
+ @@discoveries << proc
87
+ end
88
+
89
+ ##
90
+ # Automatically find all potential autotest runner styles by
91
+ # searching your loadpath, vendor/plugins, and rubygems for
92
+ # "autotest/discover.rb". If found, that file is loaded and it
93
+ # should register discovery procs with autotest using
94
+ # +add_discovery+. That proc should return one or more strings
95
+ # describing the user's current environment. Those styles are then
96
+ # combined to dynamically invoke an autotest plugin to suite your
97
+ # environment. That plugin should define a subclass of Autotest with
98
+ # a corresponding name.
99
+ #
100
+ # === Process:
101
+ #
102
+ # 1. All autotest/discover.rb files loaded.
103
+ # 2. Those procs determine your styles (eg ["rails", "rspec"]).
104
+ # 3. Require file by sorting styles and joining (eg 'autotest/rails_rspec').
105
+ # 4. Invoke run method on appropriate class (eg Autotest::RailsRspec.run).
106
+ #
107
+ # === Example autotest/discover.rb:
108
+ #
109
+ # Autotest.add_discovery do
110
+ # "rails" if File.exist? 'config/environment.rb'
111
+ # end
112
+ #
113
+ def self.autodiscover
114
+ require 'rubygems'
115
+
116
+ Gem.find_files("autotest/discover").each do |f|
117
+ load f
118
+ end
119
+
120
+ #call all discover procs an determine style
121
+ @@discoveries.map{ |proc| proc.call }.flatten.compact.sort.uniq
122
+ end
123
+
124
+ ##
125
+ # Initialize and run the system.
126
+
127
+ def self.run
128
+ new.run
129
+ end
130
+
131
+ attr_writer :known_files
132
+ attr_accessor(:completed_re,
133
+ :extra_class_map,
134
+ :extra_files,
135
+ :failed_results_re,
136
+ :files_to_test,
137
+ :find_order,
138
+ :interrupted,
139
+ :last_mtime,
140
+ :libs,
141
+ :order,
142
+ :output,
143
+ :results,
144
+ :sleep,
145
+ :tainted,
146
+ :testlib,
147
+ :find_directories,
148
+ :unit_diff,
149
+ :wants_to_quit)
150
+
151
+ ##
152
+ # Initialize the instance and then load the user's .autotest file, if any.
153
+
154
+ def initialize
155
+ # these two are set directly because they're wrapped with
156
+ # add/remove/clear accessor methods
157
+ @exception_list = []
158
+ @test_mappings = []
159
+
160
+ self.completed_re = /\d+ tests, \d+ assertions, \d+ failures, \d+ errors/
161
+ self.extra_class_map = {}
162
+ self.extra_files = []
163
+ self.failed_results_re = /^\s+\d+\) (?:Failure|Error):\n(.*?)\((.*?)\)/
164
+ self.files_to_test = new_hash_of_arrays
165
+ self.find_order = []
166
+ self.known_files = nil
167
+ self.libs = %w[. lib test].join(File::PATH_SEPARATOR)
168
+ self.order = :random
169
+ self.output = $stderr
170
+ self.sleep = 1
171
+ self.testlib = "test/unit"
172
+ self.find_directories = ['.']
173
+ self.unit_diff = "unit_diff -u"
174
+
175
+ #add Test::Unit mappings
176
+ #file in /lib -> run test in /test
177
+ self.add_mapping(/^lib\/.*\.rb$/) do |filename, _|
178
+ possible = File.basename(filename).gsub '_', '_?'
179
+ files_matching %r%^test/.*#{possible}$%
180
+ end
181
+
182
+ #file in /test -> run it
183
+ self.add_mapping(/^test.*\/test_.*rb$/) do |filename, _|
184
+ filename
185
+ end
186
+
187
+ #execute custom extensions
188
+ [File.expand_path('~/.autotest'), './.autotest'].each do |f|
189
+ load f if File.exist? f
190
+ end
191
+ end
192
+
193
+ ##
194
+ # Repeatedly run failed tests, then all tests, then wait for changes
195
+ # and carry on until killed.
196
+
197
+ def run
198
+ hook :initialize
199
+ reset
200
+ add_sigint_handler
201
+
202
+ self.last_mtime = Time.now if options[:no_full_after_start]
203
+
204
+ loop do
205
+ begin # ^c handler
206
+ get_to_green
207
+ if self.tainted and not options[:no_full_after_failed] then
208
+ rerun_all_tests
209
+ else
210
+ hook :all_good
211
+ end
212
+ wait_for_changes
213
+ rescue Interrupt
214
+ break if self.wants_to_quit
215
+ reset
216
+ end
217
+ end
218
+ hook :quit
219
+ rescue Exception
220
+ hook :died
221
+ end
222
+
223
+ ##
224
+ # Keep running the tests after a change, until all pass.
225
+
226
+ def get_to_green
227
+ begin
228
+ run_tests
229
+ wait_for_changes unless all_good
230
+ end until all_good
231
+ end
232
+
233
+ ##
234
+ # Look for files to test then run the tests and handle the results.
235
+
236
+ def run_tests
237
+ hook :run_command
238
+
239
+ new_mtime = self.find_files_to_test
240
+ return unless new_mtime
241
+ self.last_mtime = new_mtime
242
+
243
+ cmd = self.make_test_cmd self.files_to_test
244
+ return if cmd.empty?
245
+
246
+ puts cmd unless options[:quiet]
247
+
248
+ old_sync = $stdout.sync
249
+ $stdout.sync = true
250
+ self.results = []
251
+ line = []
252
+ begin
253
+ open("| #{cmd}", "r") do |f|
254
+ until f.eof? do
255
+ c = f.getc
256
+ putc c
257
+ line << c
258
+ if c == ?\n then
259
+ self.results << if RUBY_VERSION >= "1.9" then
260
+ line.join
261
+ else
262
+ line.pack "c*"
263
+ end
264
+ line.clear
265
+ end
266
+ end
267
+ end
268
+ ensure
269
+ $stdout.sync = old_sync
270
+ end
271
+ hook :ran_command
272
+ self.results = self.results.join
273
+
274
+ handle_results(self.results)
275
+ end
276
+
277
+ ############################################################
278
+ # Utility Methods, not essential to reading of logic
279
+
280
+ ##
281
+ # Installs a sigint handler.
282
+
283
+ def add_sigint_handler
284
+ trap 'INT' do
285
+ if self.interrupted then
286
+ self.wants_to_quit = true
287
+ else
288
+ unless hook :interrupt then
289
+ puts "Interrupt a second time to quit"
290
+ self.interrupted = true
291
+ Kernel.sleep 1.5
292
+ end
293
+ raise Interrupt, nil # let the run loop catch it
294
+ end
295
+ end
296
+ end
297
+
298
+ ##
299
+ # If there are no files left to test (because they've all passed),
300
+ # then all is good.
301
+
302
+ def all_good
303
+ files_to_test.empty?
304
+ end
305
+
306
+ ##
307
+ # Convert a path in a string, s, into a class name, changing
308
+ # underscores to CamelCase, etc.
309
+
310
+ def path_to_classname(s)
311
+ sep = File::SEPARATOR
312
+ f = s.sub(/^test#{sep}/, '').sub(/\.rb$/, '').split(sep)
313
+ f = f.map { |path| path.split(/_|(\d+)/).map { |seg| seg.capitalize }.join }
314
+ f = f.map { |path| path =~ /^Test/ ? path : "Test#{path}" }
315
+ f.join('::')
316
+ end
317
+
318
+ ##
319
+ # Returns a hash mapping a file name to the known failures for that
320
+ # file.
321
+
322
+ def consolidate_failures(failed)
323
+ filters = new_hash_of_arrays
324
+
325
+ class_map = Hash[*self.find_order.grep(/^test/).map { |f| # TODO: ugly
326
+ [path_to_classname(f), f]
327
+ }.flatten]
328
+ class_map.merge!(self.extra_class_map)
329
+
330
+ failed.each do |method, klass|
331
+ if class_map.has_key? klass then
332
+ filters[class_map[klass]] << method
333
+ else
334
+ output.puts "Unable to map class #{klass} to a file"
335
+ end
336
+ end
337
+
338
+ return filters
339
+ end
340
+
341
+ ##
342
+ # Find the files to process, ignoring temporary files, source
343
+ # configuration management files, etc., and return a Hash mapping
344
+ # filename to modification time.
345
+
346
+ def find_files
347
+ result = {}
348
+ targets = self.find_directories + self.extra_files
349
+ self.find_order.clear
350
+
351
+ targets.each do |target|
352
+ order = []
353
+ Find.find(target) do |f|
354
+ Find.prune if f =~ self.exceptions
355
+
356
+ next if test ?d, f
357
+ next if f =~ /(swp|~|rej|orig)$/ # temporary/patch files
358
+ next if f =~ /\/\.?#/ # Emacs autosave/cvs merge files
359
+
360
+ filename = f.sub(/^\.\//, '')
361
+
362
+ result[filename] = File.stat(filename).mtime rescue next
363
+ order << filename
364
+ end
365
+ self.find_order.push(*order.sort)
366
+ end
367
+
368
+ return result
369
+ end
370
+
371
+ ##
372
+ # Find the files which have been modified, update the recorded
373
+ # timestamps, and use this to update the files to test. Returns
374
+ # the latest mtime of the files modified or nil when nothing was
375
+ # modified.
376
+ def find_files_to_test(files=find_files)
377
+ updated = files.select { |filename, mtime| self.last_mtime < mtime }
378
+
379
+ unless updated.empty? or self.last_mtime.to_i == 0 #nothing to update or initial run
380
+ p updated if options[:verbose]
381
+ hook :updated, updated
382
+ end
383
+
384
+ updated.map { |f,m| test_files_for(f) }.flatten.uniq.each do |filename|
385
+ self.files_to_test[filename] # creates key with default value
386
+ end
387
+
388
+ if updated.empty? then
389
+ nil
390
+ else
391
+ files.values.max
392
+ end
393
+ end
394
+
395
+ ##
396
+ # Check results for failures, set the "bar" to red or green, and if
397
+ # there are failures record this.
398
+
399
+ def handle_results(results)
400
+ failed = results.scan(self.failed_results_re)
401
+ completed = results =~ self.completed_re
402
+
403
+ self.files_to_test = consolidate_failures failed if completed
404
+
405
+ color = completed && self.files_to_test.empty? ? :green : :red
406
+ hook color unless $TESTING
407
+
408
+ self.tainted = true unless self.files_to_test.empty?
409
+ end
410
+
411
+ ##
412
+ # Lazy accessor for the known_files hash.
413
+
414
+ def known_files
415
+ unless @known_files then
416
+ @known_files = Hash[*find_order.map { |f| [f, true] }.flatten]
417
+ end
418
+ @known_files
419
+ end
420
+
421
+ ##
422
+ # Generate the commands to test the supplied files
423
+
424
+ def make_test_cmd files_to_test
425
+ cmds = []
426
+ full, partial = reorder(files_to_test).partition { |k,v| v.empty? }
427
+ base_cmd = "#{ruby} -I#{libs} -rubygems"
428
+
429
+ unless full.empty? then
430
+ classes = full.map {|k,v| k}.flatten.uniq
431
+ classes.unshift testlib
432
+ cmds << "#{base_cmd} -e \"%w[#{classes.join(' ')}].each { |f| require f }\" | #{unit_diff}"
433
+ end
434
+
435
+ partial.each do |klass, methods|
436
+ regexp = Regexp.union(*methods).source
437
+ cmds << "#{base_cmd} #{klass} -n \"/^(#{regexp})$/\" | #{unit_diff}"
438
+ end
439
+
440
+ return cmds.join("#{SEP} ")
441
+ end
442
+
443
+ def new_hash_of_arrays
444
+ Hash.new { |h,k| h[k] = [] }
445
+ end
446
+
447
+ def reorder files_to_test
448
+ case self.order
449
+ when :alpha then
450
+ files_to_test.sort_by { |k,v| k }
451
+ when :reverse then
452
+ files_to_test.sort_by { |k,v| k }.reverse
453
+ when :random then
454
+ max = files_to_test.size
455
+ files_to_test.sort_by { |k,v| rand(max) }
456
+ when :natural then
457
+ (self.find_order & files_to_test.keys).map { |f| [f, files_to_test[f]] }
458
+ else
459
+ raise "unknown order type: #{self.order.inspect}"
460
+ end
461
+ end
462
+
463
+ ##
464
+ # Rerun the tests from cold (reset state)
465
+
466
+ def rerun_all_tests
467
+ reset
468
+ run_tests
469
+
470
+ hook :all_good if all_good
471
+ end
472
+
473
+ ##
474
+ # Clear all state information about test failures and whether
475
+ # interrupts will kill autotest.
476
+
477
+ def reset
478
+ self.files_to_test.clear
479
+ self.find_order.clear
480
+ self.interrupted = false
481
+ self.known_files = nil
482
+ self.last_mtime = T0
483
+ self.tainted = false
484
+ self.wants_to_quit = false
485
+
486
+ hook :reset
487
+ end
488
+
489
+ ##
490
+ # Determine and return the path of the ruby executable.
491
+
492
+ def ruby
493
+ ruby = ENV['RUBY']
494
+ ruby ||= File.join(Config::CONFIG['bindir'],
495
+ Config::CONFIG['ruby_install_name'])
496
+
497
+ ruby.gsub! File::SEPARATOR, File::ALT_SEPARATOR if File::ALT_SEPARATOR
498
+
499
+ return ruby
500
+ end
501
+
502
+ ##
503
+ # Return the name of the file with the tests for filename by finding
504
+ # a +test_mapping+ that matches the file and executing the mapping's
505
+ # proc.
506
+
507
+ def test_files_for(filename)
508
+ result = @test_mappings.find { |file_re, ignored| filename =~ file_re }
509
+
510
+ p :test_file_for => [filename, result.first] if result and $DEBUG
511
+
512
+ result = result.nil? ? [] : [result.last.call(filename, $~)].flatten
513
+
514
+ output.puts "No tests matched #{filename}" if
515
+ (options[:verbose] or $TESTING) and result.empty?
516
+
517
+ result.sort.uniq.select { |f| known_files[f] }
518
+ end
519
+
520
+ ##
521
+ # Sleep then look for files to test, until there are some.
522
+
523
+ def wait_for_changes
524
+ hook :waiting
525
+ Kernel.sleep self.sleep until find_files_to_test
526
+ end
527
+
528
+ ############################################################
529
+ # File Mappings:
530
+
531
+ ##
532
+ # Returns all known files in the codebase matching +regexp+.
533
+
534
+ def files_matching regexp
535
+ self.find_order.select { |k| k =~ regexp }
536
+ end
537
+
538
+ ##
539
+ # Adds a file mapping, optionally prepending the mapping to the
540
+ # front of the list if +prepend+ is true. +regexp+ should match a
541
+ # file path in the codebase. +proc+ is passed a matched filename and
542
+ # Regexp.last_match. +proc+ should return an array of tests to run.
543
+ #
544
+ # For example, if test_helper.rb is modified, rerun all tests:
545
+ #
546
+ # at.add_mapping(/test_helper.rb/) do |f, _|
547
+ # at.files_matching(/^test.*rb$/)
548
+ # end
549
+
550
+ def add_mapping(regexp, prepend = false, &proc)
551
+ if prepend then
552
+ @test_mappings.unshift [regexp, proc]
553
+ else
554
+ @test_mappings.push [regexp, proc]
555
+ end
556
+ nil
557
+ end
558
+
559
+ ##
560
+ # Removed a file mapping matching +regexp+.
561
+
562
+ def remove_mapping regexp
563
+ @test_mappings.delete_if do |k,v|
564
+ k == regexp
565
+ end
566
+ nil
567
+ end
568
+
569
+ ##
570
+ # Clears all file mappings. This is DANGEROUS as it entirely
571
+ # disables autotest. You must add at least one file mapping that
572
+ # does a good job of rerunning appropriate tests.
573
+
574
+ def clear_mappings
575
+ @test_mappings.clear
576
+ nil
577
+ end
578
+
579
+ ############################################################
580
+ # Exceptions:
581
+
582
+ ##
583
+ # Adds +regexp+ to the list of exceptions for find_file. This must
584
+ # be called _before_ the exceptions are compiled.
585
+
586
+ def add_exception regexp
587
+ raise "exceptions already compiled" if defined? @exceptions
588
+ @exception_list << regexp
589
+ nil
590
+ end
591
+
592
+ ##
593
+ # Removes +regexp+ to the list of exceptions for find_file. This
594
+ # must be called _before_ the exceptions are compiled.
595
+
596
+ def remove_exception regexp
597
+ raise "exceptions already compiled" if defined? @exceptions
598
+ @exception_list.delete regexp
599
+ nil
600
+ end
601
+
602
+ ##
603
+ # Clears the list of exceptions for find_file. This must be called
604
+ # _before_ the exceptions are compiled.
605
+
606
+ def clear_exceptions
607
+ raise "exceptions already compiled" if defined? @exceptions
608
+ @exception_list.clear
609
+ nil
610
+ end
611
+
612
+ ##
613
+ # Return a compiled regexp of exceptions for find_files or nil if no
614
+ # filtering should take place. This regexp is generated from
615
+ # +exception_list+.
616
+
617
+ def exceptions
618
+ unless defined? @exceptions then
619
+ if @exception_list.empty? then
620
+ @exceptions = nil
621
+ else
622
+ @exceptions = Regexp.union(*@exception_list)
623
+ end
624
+ end
625
+
626
+ @exceptions
627
+ end
628
+
629
+ ############################################################
630
+ # Hooks:
631
+
632
+ ##
633
+ # Call the event hook named +name+, executing all registered hooks
634
+ # until one returns true. Returns false if no hook handled the
635
+ # event.
636
+
637
+ def hook(name, *args)
638
+ deprecated = {
639
+ # none currently
640
+ }
641
+
642
+ if deprecated[name] and not HOOKS[name].empty? then
643
+ warn "hook #{name} has been deprecated, use #{deprecated[name]}"
644
+ end
645
+
646
+ HOOKS[name].any? do |plugin|
647
+ plugin[self, *args]
648
+ end
649
+ end
650
+
651
+ ##
652
+ # Add the supplied block to the available hooks, with the given
653
+ # name.
654
+
655
+ def self.add_hook(name, &block)
656
+ HOOKS[name] << block
657
+ end
658
+
659
+ private
660
+
661
+ #list of all available rubygem load paths
662
+ def self.rubygem_load_paths
663
+ begin
664
+ require 'rubygems'
665
+ Gem.latest_load_paths
666
+ rescue LoadError
667
+ []
668
+ end
669
+ end
670
+ end