cuts 0.0.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.
@@ -0,0 +1,23 @@
1
+ ---
2
+ project : cuts
3
+
4
+ contact : Trans <transfire@gmail.com>
5
+ license : MIT
6
+ created : 2008-02-21
7
+ homepage : http://cuts.rubyforge.org
8
+ repository : http://cuts.rubyforge.org/svn
9
+
10
+ # Title. This defaults to project capitalized, if not given.
11
+ title : Cuts
12
+
13
+ # One line description.
14
+ brief : Cut-based AOP for Ruby
15
+
16
+ # Detailed description.
17
+ description: >
18
+ Cuts is an expiremental implementation of cut-based
19
+ AOP for Ruby.
20
+
21
+ # Directories to exclude from package.
22
+ exclude : [ work, doc, ri ]
23
+
@@ -0,0 +1 @@
1
+ cuts
@@ -0,0 +1 @@
1
+ 0.0.1 alpha (2008-02-21)
@@ -0,0 +1,1467 @@
1
+ #!/usr/bin/env ruby
2
+ # Setup.rb v3.5.0
3
+ # Copyright (c) 2008 Minero Aoki, Trans
4
+ #
5
+ # This program is free software.
6
+ # You can distribute/modify this program under the terms of
7
+ # the GNU LGPL, Lesser General Public License version 2.1.
8
+
9
+ # Need the package name, and whether to generate documentation.
10
+ PACKAGE = File.read(Dir.glob('{.,meta/}unixname{,.txt}', File::FNM_CASEFOLD).first).strip
11
+ GENERATE_RDOCS = true # package developer may need to deactivate
12
+
13
+ require 'optparse'
14
+ require 'rbconfig'
15
+
16
+ class SetupError < StandardError; end
17
+
18
+ # Typical installation procedure:
19
+ #
20
+ # $ ./setup.rb
21
+ #
22
+ # -- or --
23
+ #
24
+ # $ ./setup.rb config
25
+ # $ ./setup.rb setup
26
+ # $ ./setup.rb install
27
+ #
28
+ # @all@ and @install@ may require root privileges.
29
+ #
30
+ # This update only works with Ruby 1.6.3 and above.
31
+ #
32
+ # TODO: Update shebangs on install of binaries.
33
+ # TODO: Make cleaning more comprehensive (?)
34
+
35
+ module Setup
36
+ Version = "3.5.0"
37
+
38
+ Copyright = "Copyright (c) 2000,2008 Minero Aoki, Trans"
39
+
40
+ # ConfigTable stores platform information.
41
+
42
+ class ConfigTable
43
+
44
+ RBCONFIG = ::Config::CONFIG
45
+
46
+ CONFIGFILE = '.config'
47
+
48
+ DESCRIPTIONS = [
49
+ [:prefix , :path, 'path prefix of target environment'],
50
+ [:bindir , :path, 'directory for commands'],
51
+ [:libdir , :path, 'directory for libraries'],
52
+ [:datadir , :path, 'directory for shared data'],
53
+ [:mandir , :path, 'directory for man pages'],
54
+ [:docdir , :path, 'Directory for documentation'],
55
+ [:sysconfdir , :path, 'directory for system configuration files'],
56
+ [:localstatedir , :path, 'directory for local state data'],
57
+ [:libruby , :path, 'directory for ruby libraries'],
58
+ [:librubyver , :path, 'directory for standard ruby libraries'],
59
+ [:librubyverarch , :path, 'directory for standard ruby extensions'],
60
+ [:siteruby , :path, 'directory for version-independent aux ruby libraries'],
61
+ [:siterubyver , :path, 'directory for aux ruby libraries'],
62
+ [:siterubyverarch , :path, 'directory for aux ruby binaries'],
63
+ [:rbdir , :path, 'directory for ruby scripts'],
64
+ [:sodir , :path, 'directory for ruby extentions'],
65
+ [:rubypath , :prog, 'path to set to #! line'],
66
+ [:rubyprog , :prog, 'ruby program using for installation'],
67
+ [:makeprog , :prog, 'make program to compile ruby extentions'],
68
+ [:without_ext , :bool, 'do not compile/install ruby extentions'],
69
+ [:without_doc , :bool, 'do not generate html documentation'],
70
+ [:shebang , :pick, 'shebang line (#!) editing mode (all,ruby,never)'],
71
+ [:doctemplate , :pick, 'document template to use (html|xml)'],
72
+ [:testrunner , :pick, 'Runner to use for testing (auto|console|tk|gtk|gtk2)'],
73
+ [:installdirs , :pick, 'install location mode (std,site,home :: libruby,site_ruby,$HOME)']
74
+ ]
75
+
76
+ # List of configurable options.
77
+ OPTIONS = DESCRIPTIONS.collect{ |(k,t,v)| k.to_s }
78
+
79
+ # Pathname attribute. Pathnames are automatically expanded
80
+ # unless they start with '$', a path variable.
81
+ def self.attr_pathname(name)
82
+ class_eval %{
83
+ def #{name}
84
+ @#{name}.gsub(%r<\\$([^/]+)>){ self[$1] }
85
+ end
86
+ def #{name}=(path)
87
+ raise SetupError, "bad config: #{name.to_s.upcase} requires argument" unless path
88
+ @#{name} = (path[0,1] == '$' ? path : File.expand_path(path))
89
+ end
90
+ }
91
+ end
92
+
93
+ # List of pathnames. These are not expanded though.
94
+ def self.attr_pathlist(name)
95
+ class_eval %{
96
+ def #{name}
97
+ @#{name}
98
+ end
99
+ def #{name}=(pathlist)
100
+ case pathlist
101
+ when Array
102
+ @#{name} = pathlist
103
+ else
104
+ @#{name} = pathlist.to_s.split(/[:;,]/)
105
+ end
106
+ end
107
+ }
108
+ end
109
+
110
+ # Adds boolean support.
111
+ def self.attr_accessor(*names)
112
+ bools, attrs = names.partition{ |name| name.to_s =~ /\?$/ }
113
+ attr_boolean *bools
114
+ super *attrs
115
+ end
116
+
117
+ # Boolean attribute. Can be assigned true, false, nil, or
118
+ # a string matching yes|true|y|t or no|false|n|f.
119
+ def self.attr_boolean(*names)
120
+ names.each do |name|
121
+ name = name.to_s.chomp('?')
122
+ attr_reader name # MAYBE: Deprecate
123
+ code = %{
124
+ def #{name}?; @#{name}; end
125
+ def #{name}=(val)
126
+ case val
127
+ when true, false, nil
128
+ @#{name} = val
129
+ else
130
+ case val.to_s.downcase
131
+ when 'y', 'yes', 't', 'true'
132
+ @#{name} = true
133
+ when 'n', 'no', 'f', 'false'
134
+ @#{name} = false
135
+ else
136
+ raise SetupError, "bad config: use #{name.upcase}=(yes|no) [\#{val}]"
137
+ end
138
+ end
139
+ end
140
+ }
141
+ class_eval code
142
+ end
143
+ end
144
+
145
+ DESCRIPTIONS.each do |k,t,d|
146
+ case t
147
+ when :path
148
+ attr_pathname k
149
+ when :bool
150
+ attr_boolean k
151
+ else
152
+ attr_accessor k
153
+ end
154
+ end
155
+
156
+ # # provide verbosity (default is true)
157
+ # attr_accessor :verbose?
158
+
159
+ # # don't actually write files to system
160
+ # attr_accessor :no_harm?
161
+
162
+ # shebang has only three options.
163
+ def shebang=(val)
164
+ if %w(all ruby never).include?(val)
165
+ @shebang = val
166
+ else
167
+ raise SetupError, "bad config: use SHEBANG=(all|ruby|never) [#{val}]"
168
+ end
169
+ end
170
+
171
+ # installdirs has only three options; and it has side-effects.
172
+ def installdirs=(val)
173
+ @installdirs = val
174
+ case val.to_s
175
+ when 'std'
176
+ self.rbdir = '$librubyver'
177
+ self.sodir = '$librubyverarch'
178
+ when 'site'
179
+ self.rbdir = '$siterubyver'
180
+ self.sodir = '$siterubyverarch'
181
+ when 'home'
182
+ raise SetupError, 'HOME is not set.' unless ENV['HOME']
183
+ self.prefix = ENV['HOME']
184
+ self.rbdir = '$libdir/ruby'
185
+ self.sodir = '$libdir/ruby'
186
+ else
187
+ raise SetupError, "bad config: use INSTALLDIRS=(std|site|home|local) [#{val}]"
188
+ end
189
+ end
190
+
191
+ # New ConfigTable
192
+ def initialize(values=nil)
193
+ initialize_defaults
194
+ if values
195
+ values.each{ |k,v| __send__("#{k}=", v) }
196
+ end
197
+ yeild(self) if block_given?
198
+ load_config if File.file?(CONFIGFILE)
199
+ end
200
+
201
+ # Assign CONFIG defaults
202
+ #
203
+ # TODO: Does this handle 'nmake' on windows?
204
+ def initialize_defaults
205
+ prefix = RBCONFIG['prefix']
206
+
207
+ rubypath = File.join(RBCONFIG['bindir'], RBCONFIG['ruby_install_name'] + RBCONFIG['EXEEXT'])
208
+
209
+ major = RBCONFIG['MAJOR'].to_i
210
+ minor = RBCONFIG['MINOR'].to_i
211
+ teeny = RBCONFIG['TEENY'].to_i
212
+ version = "#{major}.#{minor}"
213
+
214
+ # ruby ver. >= 1.4.4?
215
+ newpath_p = ((major >= 2) or
216
+ ((major == 1) and
217
+ ((minor >= 5) or
218
+ ((minor == 4) and (teeny >= 4)))))
219
+
220
+ if RBCONFIG['rubylibdir']
221
+ # V > 1.6.3
222
+ libruby = "#{prefix}/lib/ruby"
223
+ librubyver = RBCONFIG['rubylibdir']
224
+ librubyverarch = RBCONFIG['archdir']
225
+ siteruby = RBCONFIG['sitedir']
226
+ siterubyver = RBCONFIG['sitelibdir']
227
+ siterubyverarch = RBCONFIG['sitearchdir']
228
+ elsif newpath_p
229
+ # 1.4.4 <= V <= 1.6.3
230
+ libruby = "#{prefix}/lib/ruby"
231
+ librubyver = "#{prefix}/lib/ruby/#{version}"
232
+ librubyverarch = "#{prefix}/lib/ruby/#{version}/#{c['arch']}"
233
+ siteruby = RBCONFIG['sitedir']
234
+ siterubyver = "$siteruby/#{version}"
235
+ siterubyverarch = "$siterubyver/#{RBCONFIG['arch']}"
236
+ else
237
+ # V < 1.4.4
238
+ libruby = "#{prefix}/lib/ruby"
239
+ librubyver = "#{prefix}/lib/ruby/#{version}"
240
+ librubyverarch = "#{prefix}/lib/ruby/#{version}/#{c['arch']}"
241
+ siteruby = "#{prefix}/lib/ruby/#{version}/site_ruby"
242
+ siterubyver = siteruby
243
+ siterubyverarch = "$siterubyver/#{RBCONFIG['arch']}"
244
+ end
245
+
246
+ if arg = RBCONFIG['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg }
247
+ makeprog = arg.sub(/'/, '').split(/=/, 2)[1]
248
+ else
249
+ makeprog = 'make'
250
+ end
251
+
252
+ parameterize = lambda do |path|
253
+ val = RBCONFIG[path]
254
+ val.sub(/\A#{Regexp.quote(prefix)}/, '$prefix')
255
+ end
256
+
257
+ self.prefix = prefix
258
+ self.bindir = parameterize['bindir']
259
+ self.libdir = parameterize['libdir']
260
+ self.datadir = parameterize['datadir']
261
+ self.mandir = parameterize['mandir']
262
+ self.docdir = File.dirname(parameterize['docdir']) # b/c of trailing $(PACKAGE)
263
+ self.sysconfdir = parameterize['sysconfdir']
264
+ self.localstatedir = parameterize['localstatedir']
265
+ self.libruby = libruby
266
+ self.librubyver = librubyver
267
+ self.librubyverarch = librubyverarch
268
+ self.siteruby = siteruby
269
+ self.siterubyver = siterubyver
270
+ self.siterubyverarch = siterubyverarch
271
+ self.rbdir = '$siterubyver'
272
+ self.sodir = '$siterubyverarch'
273
+ self.rubypath = rubypath
274
+ self.rubyprog = rubypath
275
+ self.makeprog = makeprog
276
+ self.shebang = 'ruby'
277
+ self.without_ext = 'no'
278
+ self.without_doc = 'yes'
279
+ self.doctemplate = 'html'
280
+ self.testrunner = 'auto'
281
+ self.installdirs = 'site'
282
+ end
283
+
284
+ # Get configuration from environment.
285
+ def env_config
286
+ OPTIONS.each do |name|
287
+ if value = ENV[name]
288
+ __send__("#{name}=",value)
289
+ end
290
+ end
291
+ end
292
+
293
+ # Load configuration.
294
+ def load_config
295
+ #if File.file?(CONFIGFILE)
296
+ begin
297
+ File.foreach(CONFIGFILE) do |line|
298
+ k, v = *line.split(/=/, 2)
299
+ __send__("#{k}=",v.strip) #self[k] = v.strip
300
+ end
301
+ rescue Errno::ENOENT
302
+ raise SetupError, $!.message + "\n#{File.basename($0)} config first"
303
+ end
304
+ #end
305
+ end
306
+
307
+ # Save configuration.
308
+ def save_config
309
+ File.open(CONFIGFILE, 'w') do |f|
310
+ OPTIONS.each do |name|
311
+ val = self[name]
312
+ f << "#{name}=#{val}\n"
313
+ end
314
+ end
315
+ end
316
+
317
+ def show
318
+ fmt = "%-20s %s\n"
319
+ OPTIONS.each do |name|
320
+ value = self[name]
321
+ printf fmt, name, __send__(name) if value
322
+ end
323
+ #printf fmt, 'verbose', verbose? ? 'yes' : 'no'
324
+ #printf fmt, 'no-write', no_harm? ? 'yes' : 'no'
325
+ end
326
+
327
+ #
328
+
329
+ def extconfs
330
+ @extconfs ||= Dir['ext/**/extconf.rb']
331
+ end
332
+
333
+ def extensions
334
+ @extensions ||= extconfs.collect{ |f| File.dirname(f) }
335
+ end
336
+
337
+ def compiles?
338
+ !extensions.empty?
339
+ end
340
+
341
+ private
342
+
343
+ # Get unresloved attribute.
344
+ def [](name)
345
+ instance_variable_get("@#{name}")
346
+ end
347
+
348
+ # Set attribute.
349
+ def []=(name, value)
350
+ instance_variable_set("@#{name}", value)
351
+ end
352
+
353
+ # Resolved attribute. (for paths)
354
+ #def resolve(name)
355
+ # self[name].gsub(%r<\\$([^/]+)>){ self[$1] }
356
+ #end
357
+
358
+ end
359
+
360
+ # Installer class handles the actual install procedure,
361
+ # as well as the other tasks, such as testing.
362
+
363
+ class Installer
364
+
365
+ MANIFEST = '.installedfiles'
366
+
367
+ FILETYPES = %w( bin lib ext data conf man doc )
368
+
369
+ TASK_DESCRIPTIONS = [
370
+ [ 'all', 'do config, setup, then install' ],
371
+ [ 'config', 'saves your configurations' ],
372
+ [ 'show', 'shows current configuration' ],
373
+ [ 'setup', 'compiles ruby extentions and others' ],
374
+ [ 'doc', 'generate html documentation' ],
375
+ [ 'index', 'generate index documentation' ],
376
+ [ 'install', 'installs files' ],
377
+ [ 'test', 'run all tests in test/' ],
378
+ [ 'clean', "does `make clean' for each extention" ],
379
+ [ 'distclean',"does `make distclean' for each extention" ]
380
+ ]
381
+
382
+ TASKS = %w(all config show setup test install uninstall doc index clean distclean)
383
+
384
+ # Configuration
385
+ attr :config
386
+
387
+ attr_writer :no_harm
388
+ attr_writer :verbose
389
+ attr_writer :quiet
390
+
391
+ attr_accessor :install_prefix
392
+
393
+ # New Installer.
394
+ def initialize #:yield:
395
+ srcroot = '.'
396
+ objroot = '.'
397
+
398
+ @config = ConfigTable.new
399
+
400
+ @srcdir = File.expand_path(srcroot)
401
+ @objdir = File.expand_path(objroot)
402
+ @currdir = '.'
403
+
404
+ self.quiet = ENV['quiet'] if ENV['quiet']
405
+ self.verbose = ENV['verbose'] if ENV['verbose']
406
+ self.no_harm = ENV['nowrite'] if ENV['nowrite']
407
+
408
+ yield(self) if block_given?
409
+ end
410
+
411
+ def inspect
412
+ "#<#{self.class} #{File.basename(@srcdir)}>"
413
+ end
414
+
415
+ # Are we running an installation?
416
+ def installation?; @installation; end
417
+ def installation!; @installation = true; end
418
+
419
+ def no_harm?; @no_harm; end
420
+ def verbose?; @verbose; end
421
+ def quiet?; @quiet; end
422
+
423
+ def verbose_off #:yield:
424
+ begin
425
+ save, @verbose = verbose?, false
426
+ yield
427
+ ensure
428
+ @verbose = save
429
+ end
430
+ end
431
+
432
+ # Rake task handlers
433
+ def rake_define
434
+ require 'rake/clean'
435
+
436
+ desc 'Config, setup and then install'
437
+ task :all => [:config, :setup, :install]
438
+
439
+ desc 'Saves your configurations'
440
+ task :config do exec_config end
441
+
442
+ desc 'Compiles ruby extentions'
443
+ task :setup do exec_setup end
444
+
445
+ desc 'Generate html api docs'
446
+ task :doc do exec_doc end
447
+
448
+ desc 'Generate api index docs'
449
+ task :index do exec_index end
450
+
451
+ desc 'Installs files'
452
+ task :install do exec_install end
453
+
454
+ desc 'Uninstalls files'
455
+ task :uninstall do exec_uninstall end
456
+
457
+ #desc "Does `make clean' for each extention"
458
+ task :makeclean do exec_clean end
459
+
460
+ task :clean => [:makeclean]
461
+
462
+ #desc "Does `make distclean' for each extention"
463
+ task :distclean do exec_distclean end
464
+
465
+ task :clobber => [:distclean]
466
+
467
+ desc 'Shows current configuration'
468
+ task :show do exec_show end
469
+ end
470
+
471
+ # Added these for future use in simplificaiton of design.
472
+
473
+ def extensions
474
+ @extensions ||= Dir['ext/**/extconf.rb']
475
+ end
476
+
477
+ def compiles?
478
+ !extensions.empty?
479
+ end
480
+
481
+ #
482
+ def noop(rel); end
483
+
484
+ #
485
+ # Hook Script API bases
486
+ #
487
+
488
+ def srcdir_root
489
+ @srcdir
490
+ end
491
+
492
+ def objdir_root
493
+ @objdir
494
+ end
495
+
496
+ def relpath
497
+ @currdir
498
+ end
499
+
500
+ #
501
+ # Task all
502
+ #
503
+
504
+ def exec_all
505
+ exec_config
506
+ exec_setup
507
+ exec_test # TODO: we need to stop here if tests fail (how?)
508
+ exec_doc if GENERATE_RDOCS && !config.without_doc?
509
+ exec_install
510
+ end
511
+
512
+ #
513
+ # TASK config
514
+ #
515
+
516
+ def exec_config
517
+ config.env_config
518
+ config.save_config
519
+ exec_task_traverse 'config'
520
+ config.show unless quiet?
521
+ puts("Configuration saved.") unless quiet?
522
+ end
523
+
524
+ alias config_dir_bin noop
525
+ alias config_dir_lib noop
526
+
527
+ def config_dir_ext(rel)
528
+ extconf if extdir?(curr_srcdir())
529
+ end
530
+
531
+ alias config_dir_data noop
532
+ alias config_dir_conf noop
533
+ alias config_dir_man noop
534
+ alias config_dir_doc noop
535
+
536
+ def extconf
537
+ ruby "#{curr_srcdir()}/extconf.rb", config_opt
538
+ end
539
+
540
+ #
541
+ # TASK show
542
+ #
543
+
544
+ def exec_show
545
+ config.show
546
+ end
547
+
548
+ #
549
+ # TASK setup
550
+ #
551
+ # FIXME: Update shebang at time of install not before.
552
+ # for now I've commented it out the shebang.
553
+
554
+ def exec_setup
555
+ exec_task_traverse 'setup'
556
+ end
557
+
558
+ def setup_dir_bin(rel)
559
+ files_of(curr_srcdir()).each do |fname|
560
+ #update_shebang_line "#{curr_srcdir()}/#{fname}"
561
+ end
562
+ end
563
+
564
+ alias setup_dir_lib noop
565
+
566
+ def setup_dir_ext(rel)
567
+ make if extdir?(curr_srcdir())
568
+ end
569
+
570
+ alias setup_dir_data noop
571
+ alias setup_dir_conf noop
572
+ alias setup_dir_man noop
573
+ alias setup_dir_doc noop
574
+
575
+ def update_shebang_line(path)
576
+ return if no_harm?
577
+ return if config.shebang == 'never'
578
+ old = Shebang.load(path)
579
+ if old
580
+ if old.args.size > 1
581
+ $stderr.puts "warning: #{path}"
582
+ $stderr.puts "Shebang line has too many args."
583
+ $stderr.puts "It is not portable and your program may not work."
584
+ end
585
+ new = new_shebang(old)
586
+ return if new.to_s == old.to_s
587
+ else
588
+ return unless config.shebang == 'all'
589
+ new = Shebang.new(config.rubypath)
590
+ end
591
+ $stderr.puts "updating shebang: #{File.basename(path)}" if verbose?
592
+ open_atomic_writer(path) {|output|
593
+ File.open(path, 'rb') {|f|
594
+ f.gets if old # discard
595
+ output.puts new.to_s
596
+ output.print f.read
597
+ }
598
+ }
599
+ end
600
+
601
+ def new_shebang(old)
602
+ if /\Aruby/ =~ File.basename(old.cmd)
603
+ Shebang.new(config.rubypath, old.args)
604
+ elsif File.basename(old.cmd) == 'env' and old.args.first == 'ruby'
605
+ Shebang.new(config.rubypath, old.args[1..-1])
606
+ else
607
+ return old unless config.shebang == 'all'
608
+ Shebang.new(config.rubypath)
609
+ end
610
+ end
611
+
612
+ def open_atomic_writer(path, &block)
613
+ tmpfile = File.basename(path) + '.tmp'
614
+ begin
615
+ File.open(tmpfile, 'wb', &block)
616
+ File.rename tmpfile, File.basename(path)
617
+ ensure
618
+ File.unlink tmpfile if File.exist?(tmpfile)
619
+ end
620
+ end
621
+
622
+ class Shebang
623
+ def Shebang.load(path)
624
+ line = nil
625
+ File.open(path) {|f|
626
+ line = f.gets
627
+ }
628
+ return nil unless /\A#!/ =~ line
629
+ parse(line)
630
+ end
631
+
632
+ def Shebang.parse(line)
633
+ cmd, *args = *line.strip.sub(/\A\#!/, '').split(' ')
634
+ new(cmd, args)
635
+ end
636
+
637
+ def initialize(cmd, args = [])
638
+ @cmd = cmd
639
+ @args = args
640
+ end
641
+
642
+ attr_reader :cmd
643
+ attr_reader :args
644
+
645
+ def to_s
646
+ "#! #{@cmd}" + (@args.empty? ? '' : " #{@args.join(' ')}")
647
+ end
648
+ end
649
+
650
+ #
651
+ # TASK test
652
+ #
653
+ # TODO: Add spec support.
654
+
655
+ def exec_test
656
+ $stderr.puts 'Running tests...' if verbose?
657
+
658
+ runner = config.testrunner
659
+
660
+ case runner
661
+ when 'auto'
662
+ unless File.directory?('test')
663
+ $stderr.puts 'no test in this package' if verbose?
664
+ return
665
+ end
666
+ begin
667
+ require 'test/unit'
668
+ rescue LoadError
669
+ setup_rb_error 'test/unit cannot loaded. You need Ruby 1.8 or later to invoke this task.'
670
+ end
671
+ autorunner = Test::Unit::AutoRunner.new(true)
672
+ autorunner.to_run << 'test'
673
+ autorunner.run
674
+ else # use testrb
675
+ opt = []
676
+ opt << " -v" if verbose?
677
+ opt << " --runner #{runner}"
678
+ if File.file?('test/suite.rb')
679
+ notests = false
680
+ opt << "test/suite.rb"
681
+ else
682
+ notests = Dir["test/**/*.rb"].empty?
683
+ lib = ["lib"] + config.extensions.collect{ |d| File.dirname(d) }
684
+ opt << "-I" + lib.join(':')
685
+ opt << Dir["test/**/{test,tc}*.rb"]
686
+ end
687
+ opt = opt.flatten.join(' ').strip
688
+ # run tests
689
+ if notests
690
+ $stderr.puts 'no test in this package' if verbose?
691
+ else
692
+ cmd = "testrb #{opt}"
693
+ $stderr.puts cmd if verbose?
694
+ system cmd #config.ruby "-S tesrb", opt
695
+ end
696
+ end
697
+ end
698
+
699
+ # MAYBE: We could traverse and run each test independently (?)
700
+ #def test_dir_test
701
+ #end
702
+
703
+ #
704
+ # TASK doc
705
+ #
706
+
707
+ def exec_doc
708
+ output = File.join('doc', PACKAGE, 'rdoc')
709
+ title = (PACKAGE.capitalize + " API").strip
710
+ main = Dir.glob("README{,.txt}", File::FNM_CASEFOLD).first
711
+ template = config.doctemplate || 'html'
712
+
713
+ opt = []
714
+ opt << "-U"
715
+ opt << "-S"
716
+ opt << "--op=#{output}"
717
+ opt << "--template=#{template}"
718
+ opt << "--title=#{title}"
719
+ opt << "--main=#{main}" if main
720
+
721
+ if File.exist?('.document')
722
+ files = File.read('.document').split("\n")
723
+ files.reject!{ |l| l =~ /^\s*[#]/ || l !~ /\S/ }
724
+ files.collect!{ |f| f.strip }
725
+ opt << files
726
+ else
727
+ opt << main if main
728
+ opt << ["lib", "ext"]
729
+ end
730
+
731
+ opt = opt.flatten
732
+
733
+ if no_harm?
734
+ puts "rdoc " + opt.join(' ').strip
735
+ else
736
+ #sh "rdoc {opt.join(' ').strip}"
737
+ require 'rdoc/rdoc'
738
+ ::RDoc::RDoc.new.document(opt)
739
+ end
740
+ end
741
+
742
+ #
743
+ # TASK index
744
+ #
745
+ # TODO: Totally deprecate stadard ri support in favor of fastri.
746
+
747
+ def exec_index
748
+ begin
749
+ require 'fastri/version'
750
+ fastri = true
751
+ rescue LoadError
752
+ fastri = false
753
+ end
754
+ if fastri
755
+ if no_harm?
756
+ $stderr.puts "fastri-server -b"
757
+ else
758
+ system "fastri-server -b"
759
+ end
760
+ else
761
+ case config.installdirs
762
+ when 'std'
763
+ output = "--ri-system"
764
+ when 'site'
765
+ output = "--ri-site"
766
+ when 'home'
767
+ output = "--ri"
768
+ else
769
+ abort "bad config: sould not be possible -- installdirs = #{config.installdirs}"
770
+ end
771
+
772
+ if File.exist?('.document')
773
+ files = File.read('.document').split("\n")
774
+ files.reject!{ |l| l =~ /^\s*[#]/ || l !~ /\S/ }
775
+ files.collect!{ |f| f.strip }
776
+ else
777
+ files = ["lib", "ext"]
778
+ end
779
+
780
+ opt = []
781
+ opt << "-U"
782
+ opt << output
783
+ opt << files
784
+ opt = opt.flatten
785
+
786
+ if no_harm?
787
+ puts "rdoc #{opt.join(' ').strip}"
788
+ else
789
+ #sh "rdoc #{opt.join(' ').strip}"
790
+ require 'rdoc/rdoc'
791
+ ::RDoc::RDoc.new.document(opt)
792
+ end
793
+ end
794
+ end
795
+
796
+ #
797
+ # TASK install
798
+ #
799
+
800
+ def exec_install
801
+ installation! # were are installing
802
+ #rm_f MANIFEST # we'll append rather then delete!
803
+ exec_task_traverse 'install'
804
+ end
805
+
806
+ def install_dir_bin(rel)
807
+ install_files targetfiles(), "#{config.bindir}/#{rel}", 0755
808
+ end
809
+
810
+ def install_dir_lib(rel)
811
+ install_files libfiles(), "#{config.rbdir}/#{rel}", 0644
812
+ end
813
+
814
+ def install_dir_ext(rel)
815
+ return unless extdir?(curr_srcdir())
816
+ install_files rubyextentions('.'),
817
+ "#{config.sodir}/#{File.dirname(rel)}", 0555
818
+ end
819
+
820
+ def install_dir_data(rel)
821
+ install_files targetfiles(), "#{config.datadir}/#{rel}", 0644
822
+ end
823
+
824
+ def install_dir_conf(rel)
825
+ # FIXME: should not remove current config files
826
+ # (rename previous file to .old/.org)
827
+ install_files targetfiles(), "#{config.sysconfdir}/#{rel}", 0644
828
+ end
829
+
830
+ def install_dir_man(rel)
831
+ install_files targetfiles(), "#{config.mandir}/#{rel}", 0644
832
+ end
833
+
834
+ def install_dir_doc(rel)
835
+ return if config.without_doc?
836
+ install_files targetfiles(), "#{config.docdir}/#{rel}", 0644
837
+ end
838
+
839
+ def install_files(list, dest, mode)
840
+ mkdir_p dest, install_prefix
841
+ list.each do |fname|
842
+ install fname, dest, mode, install_prefix
843
+ end
844
+ end
845
+
846
+ def libfiles
847
+ glob_reject(%w(*.y *.output), targetfiles())
848
+ end
849
+
850
+ def rubyextentions(dir)
851
+ ents = glob_select("*.#{dllext}", targetfiles())
852
+ if ents.empty?
853
+ setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first"
854
+ end
855
+ ents
856
+ end
857
+
858
+ def dllext
859
+ RBCONFIG['DLEXT']
860
+ end
861
+
862
+ def targetfiles
863
+ mapdir(existfiles() - hookfiles())
864
+ end
865
+
866
+ def mapdir(ents)
867
+ ents.map {|ent|
868
+ if File.exist?(ent)
869
+ then ent # objdir
870
+ else "#{curr_srcdir()}/#{ent}" # srcdir
871
+ end
872
+ }
873
+ end
874
+
875
+ # picked up many entries from cvs-1.11.1/src/ignore.c
876
+ JUNK_FILES = %w(
877
+ core RCSLOG tags TAGS .make.state
878
+ .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb
879
+ *~ *.old *.bak *.BAK *.orig *.rej _$* *$
880
+
881
+ *.org *.in .*
882
+ )
883
+
884
+ def existfiles
885
+ glob_reject(JUNK_FILES, (files_of(curr_srcdir()) | files_of('.')))
886
+ end
887
+
888
+ def hookfiles
889
+ %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt|
890
+ %w( config setup install clean ).map {|t| sprintf(fmt, t) }
891
+ }.flatten
892
+ end
893
+
894
+ def glob_select(pat, ents)
895
+ re = globs2re([pat])
896
+ ents.select {|ent| re =~ ent }
897
+ end
898
+
899
+ def glob_reject(pats, ents)
900
+ re = globs2re(pats)
901
+ ents.reject {|ent| re =~ ent }
902
+ end
903
+
904
+ GLOB2REGEX = {
905
+ '.' => '\.',
906
+ '$' => '\$',
907
+ '#' => '\#',
908
+ '*' => '.*'
909
+ }
910
+
911
+ def globs2re(pats)
912
+ /\A(?:#{
913
+ pats.map {|pat| pat.gsub(/[\.\$\#\*]/) {|ch| GLOB2REGEX[ch] } }.join('|')
914
+ })\z/
915
+ end
916
+
917
+ #
918
+ # TASK uninstall
919
+ #
920
+
921
+ def exec_uninstall
922
+ paths = File.read(MANIFEST).split("\n")
923
+ dirs, files = paths.partition{ |f| File.dir?(f) }
924
+
925
+ files.each do |file|
926
+ next if /^\#/ =~ file # skip comments
927
+ rm_f(file) if File.exist?(file)
928
+ end
929
+
930
+ dirs.each do |dir|
931
+ # okay this is over kill, but playing it safe...
932
+ empty = Dir[File.join(dir,'*')].empty?
933
+ begin
934
+ if no_harm?
935
+ $stderr.puts "rmdir #{dir}"
936
+ else
937
+ rmdir(dir) if empty
938
+ end
939
+ rescue Errno::ENOTEMPTY
940
+ $stderr.puts "may not be empty -- #{dir}" if verbose?
941
+ end
942
+ end
943
+
944
+ rm_f(MANIFEST)
945
+ end
946
+
947
+ #
948
+ # TASK clean
949
+ #
950
+
951
+ def exec_clean
952
+ exec_task_traverse 'clean'
953
+ rm_f ConfigTable::CONFIGFILE
954
+ #rm_f MANIFEST # only on clobber!
955
+ end
956
+
957
+ alias clean_dir_bin noop
958
+ alias clean_dir_lib noop
959
+ alias clean_dir_data noop
960
+ alias clean_dir_conf noop
961
+ alias clean_dir_man noop
962
+ alias clean_dir_doc noop
963
+
964
+ def clean_dir_ext(rel)
965
+ return unless extdir?(curr_srcdir())
966
+ make 'clean' if File.file?('Makefile')
967
+ end
968
+
969
+ #
970
+ # TASK distclean
971
+ #
972
+
973
+ def exec_distclean
974
+ exec_task_traverse 'distclean'
975
+ rm_f ConfigTable::CONFIGFILE
976
+ rm_f MANIFEST
977
+ end
978
+
979
+ alias distclean_dir_bin noop
980
+ alias distclean_dir_lib noop
981
+
982
+ def distclean_dir_ext(rel)
983
+ return unless extdir?(curr_srcdir())
984
+ make 'distclean' if File.file?('Makefile')
985
+ end
986
+
987
+ alias distclean_dir_data noop
988
+ alias distclean_dir_conf noop
989
+ alias distclean_dir_man noop
990
+
991
+ def distclean_dir_doc(rel)
992
+ if GENERATE_RDOCS
993
+ rm_rf('rdoc') if File.directory?('rdoc')
994
+ end
995
+ end
996
+
997
+ #
998
+ # Traversing
999
+ #
1000
+
1001
+ def exec_task_traverse(task)
1002
+ run_hook "pre-#{task}"
1003
+ FILETYPES.each do |type|
1004
+ if type == 'ext' and config.without_ext == 'yes'
1005
+ $stderr.puts 'skipping ext/* by user option' if verbose?
1006
+ next
1007
+ end
1008
+ traverse task, type, "#{task}_dir_#{type}"
1009
+ end
1010
+ run_hook "post-#{task}"
1011
+ end
1012
+
1013
+ def traverse(task, rel, mid)
1014
+ dive_into(rel) {
1015
+ run_hook "pre-#{task}"
1016
+ __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '')
1017
+ directories_of(curr_srcdir()).each do |d|
1018
+ traverse task, "#{rel}/#{d}", mid
1019
+ end
1020
+ run_hook "post-#{task}"
1021
+ }
1022
+ end
1023
+
1024
+ def dive_into(rel)
1025
+ return unless File.dir?("#{@srcdir}/#{rel}")
1026
+
1027
+ dir = File.basename(rel)
1028
+ Dir.mkdir dir unless File.dir?(dir)
1029
+ prevdir = Dir.pwd
1030
+ Dir.chdir dir
1031
+ $stderr.puts '---> ' + rel if verbose?
1032
+ @currdir = rel
1033
+ yield
1034
+ Dir.chdir prevdir
1035
+ $stderr.puts '<--- ' + rel if verbose?
1036
+ @currdir = File.dirname(rel)
1037
+ end
1038
+
1039
+ def run_hook(id)
1040
+ path = [ "#{curr_srcdir()}/#{id}",
1041
+ "#{curr_srcdir()}/#{id}.rb" ].detect {|cand| File.file?(cand) }
1042
+ return unless path
1043
+ begin
1044
+ instance_eval File.read(path), path, 1
1045
+ rescue
1046
+ raise if $DEBUG
1047
+ setup_rb_error "hook #{path} failed:\n" + $!.message
1048
+ end
1049
+ end
1050
+
1051
+ # File Operations
1052
+ #
1053
+ # This module requires: #verbose?, #no_harm?
1054
+
1055
+ def binread(fname)
1056
+ File.open(fname, 'rb'){ |f|
1057
+ return f.read
1058
+ }
1059
+ end
1060
+
1061
+ def mkdir_p(dirname, prefix = nil)
1062
+ dirname = prefix + File.expand_path(dirname) if prefix
1063
+ $stderr.puts "mkdir -p #{dirname}" if verbose?
1064
+ return if no_harm?
1065
+
1066
+ # Does not check '/', it's too abnormal.
1067
+ dirs = File.expand_path(dirname).split(%r<(?=/)>)
1068
+ if /\A[a-z]:\z/i =~ dirs[0]
1069
+ disk = dirs.shift
1070
+ dirs[0] = disk + dirs[0]
1071
+ end
1072
+ dirs.each_index do |idx|
1073
+ path = dirs[0..idx].join('')
1074
+ Dir.mkdir path unless File.dir?(path)
1075
+ record_installation(path) # also record directories made
1076
+ end
1077
+ end
1078
+
1079
+ def rm_f(path)
1080
+ $stderr.puts "rm -f #{path}" if verbose?
1081
+ return if no_harm?
1082
+ force_remove_file path
1083
+ end
1084
+
1085
+ def rm_rf(path)
1086
+ $stderr.puts "rm -rf #{path}" if verbose?
1087
+ return if no_harm?
1088
+ remove_tree path
1089
+ end
1090
+
1091
+ def rmdir(path)
1092
+ $stderr.puts "rmdir #{path}" if verbose?
1093
+ return if no_harm?
1094
+ Dir.rmdir path
1095
+ end
1096
+
1097
+ def remove_tree(path)
1098
+ if File.symlink?(path)
1099
+ remove_file path
1100
+ elsif File.dir?(path)
1101
+ remove_tree0 path
1102
+ else
1103
+ force_remove_file path
1104
+ end
1105
+ end
1106
+
1107
+ def remove_tree0(path)
1108
+ Dir.foreach(path) do |ent|
1109
+ next if ent == '.'
1110
+ next if ent == '..'
1111
+ entpath = "#{path}/#{ent}"
1112
+ if File.symlink?(entpath)
1113
+ remove_file entpath
1114
+ elsif File.dir?(entpath)
1115
+ remove_tree0 entpath
1116
+ else
1117
+ force_remove_file entpath
1118
+ end
1119
+ end
1120
+ begin
1121
+ Dir.rmdir path
1122
+ rescue Errno::ENOTEMPTY
1123
+ # directory may not be empty
1124
+ end
1125
+ end
1126
+
1127
+ def move_file(src, dest)
1128
+ force_remove_file dest
1129
+ begin
1130
+ File.rename src, dest
1131
+ rescue
1132
+ File.open(dest, 'wb') {|f|
1133
+ f.write binread(src)
1134
+ }
1135
+ File.chmod File.stat(src).mode, dest
1136
+ File.unlink src
1137
+ end
1138
+ end
1139
+
1140
+ def force_remove_file(path)
1141
+ begin
1142
+ remove_file path
1143
+ rescue
1144
+ end
1145
+ end
1146
+
1147
+ def remove_file(path)
1148
+ File.chmod 0777, path
1149
+ File.unlink path
1150
+ end
1151
+
1152
+ def install(from, dest, mode, prefix = nil)
1153
+ $stderr.puts "install #{from} #{dest}" if verbose?
1154
+ return if no_harm?
1155
+
1156
+ realdest = prefix ? prefix + File.expand_path(dest) : dest
1157
+ realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest)
1158
+ str = binread(from)
1159
+ if diff?(str, realdest)
1160
+ verbose_off {
1161
+ rm_f realdest if File.exist?(realdest)
1162
+ }
1163
+ File.open(realdest, 'wb') {|f|
1164
+ f.write str
1165
+ }
1166
+ File.chmod mode, realdest
1167
+
1168
+ if prefix
1169
+ path = realdest.sub(prefix, '')
1170
+ else
1171
+ path = realdest
1172
+ end
1173
+
1174
+ record_installation(path)
1175
+ end
1176
+ end
1177
+
1178
+ def record_installation(path)
1179
+ File.open("#{objdir_root()}/#{MANIFEST}", 'a') do |f|
1180
+ f.puts(path)
1181
+ end
1182
+ end
1183
+
1184
+ def diff?(new_content, path)
1185
+ return true unless File.exist?(path)
1186
+ new_content != binread(path)
1187
+ end
1188
+
1189
+ def command(*args)
1190
+ $stderr.puts args.join(' ') if verbose?
1191
+ system(*args) or raise RuntimeError,
1192
+ "system(#{args.map{|a| a.inspect }.join(' ')}) failed"
1193
+ end
1194
+
1195
+ def ruby(*args)
1196
+ command config.rubyprog, *args
1197
+ end
1198
+
1199
+ def make(task = nil)
1200
+ command(*[config.makeprog, task].compact)
1201
+ end
1202
+
1203
+ def extdir?(dir)
1204
+ File.exist?("#{dir}/MANIFEST") or File.exist?("#{dir}/extconf.rb")
1205
+ end
1206
+
1207
+ def files_of(dir)
1208
+ Dir.open(dir) {|d|
1209
+ return d.select {|ent| File.file?("#{dir}/#{ent}") }
1210
+ }
1211
+ end
1212
+
1213
+ DIR_REJECT = %w( . .. CVS SCCS RCS CVS.adm .svn )
1214
+
1215
+ def directories_of(dir)
1216
+ Dir.open(dir) {|d|
1217
+ return d.select {|ent| File.dir?("#{dir}/#{ent}") } - DIR_REJECT
1218
+ }
1219
+ end
1220
+
1221
+ #
1222
+ # Hook Script API
1223
+ #
1224
+ # These require: #srcdir_root, #objdir_root, #relpath
1225
+ #
1226
+
1227
+ #
1228
+ def get_config(key)
1229
+ config.__send__(key)
1230
+ end
1231
+
1232
+ # obsolete: use metaconfig to change configuration
1233
+ # TODO: what to do with?
1234
+ def set_config(key, val)
1235
+ config[key] = val
1236
+ end
1237
+
1238
+ #
1239
+ # srcdir/objdir (works only in the package directory)
1240
+ #
1241
+
1242
+ def curr_srcdir
1243
+ "#{srcdir_root()}/#{relpath()}"
1244
+ end
1245
+
1246
+ def curr_objdir
1247
+ "#{objdir_root()}/#{relpath()}"
1248
+ end
1249
+
1250
+ def srcfile(path)
1251
+ "#{curr_srcdir()}/#{path}"
1252
+ end
1253
+
1254
+ def srcexist?(path)
1255
+ File.exist?(srcfile(path))
1256
+ end
1257
+
1258
+ def srcdirectory?(path)
1259
+ File.dir?(srcfile(path))
1260
+ end
1261
+
1262
+ def srcfile?(path)
1263
+ File.file?(srcfile(path))
1264
+ end
1265
+
1266
+ def srcentries(path = '.')
1267
+ Dir.open("#{curr_srcdir()}/#{path}") {|d|
1268
+ return d.to_a - %w(. ..)
1269
+ }
1270
+ end
1271
+
1272
+ def srcfiles(path = '.')
1273
+ srcentries(path).select {|fname|
1274
+ File.file?(File.join(curr_srcdir(), path, fname))
1275
+ }
1276
+ end
1277
+
1278
+ def srcdirectories(path = '.')
1279
+ srcentries(path).select {|fname|
1280
+ File.dir?(File.join(curr_srcdir(), path, fname))
1281
+ }
1282
+ end
1283
+
1284
+ end
1285
+
1286
+ # CLI runner.
1287
+ def self.run_cli
1288
+ installer = Setup::Installer.new
1289
+
1290
+ task = ARGV.find{ |a| a !~ /^[-]/ }
1291
+ task = 'all' unless task
1292
+
1293
+ unless Setup::Installer::TASKS.include?(task)
1294
+ $stderr.puts "Not a valid task -- #{task}"
1295
+ exit 1
1296
+ end
1297
+
1298
+ opts = OptionParser.new
1299
+
1300
+ opts.banner = "Usage: #{File.basename($0)} [task] [options]"
1301
+
1302
+ if task == 'config' or task == 'all'
1303
+ opts.separator ""
1304
+ opts.separator "Config options:"
1305
+ Setup::ConfigTable::DESCRIPTIONS.each do |name, type, desc|
1306
+ opts.on("--#{name} #{type.to_s.upcase}", desc) do |val|
1307
+ ENV[name.to_s] = val.to_s
1308
+ end
1309
+ end
1310
+ end
1311
+
1312
+ if task == 'install'
1313
+ opts.separator ""
1314
+ opts.separator "Install options:"
1315
+
1316
+ opts.on("--prefix PATH", "Installation prefix") do |val|
1317
+ installer.install_prefix = val
1318
+ end
1319
+ end
1320
+
1321
+ if task == 'test'
1322
+ opts.separator ""
1323
+ opts.separator "Install options:"
1324
+
1325
+ opts.on("--runner TYPE", "Test runner (auto|console|gtk|gtk2|tk)") do |val|
1326
+ installer.config.testrunner = val
1327
+ end
1328
+ end
1329
+
1330
+ # common options
1331
+ opts.separator ""
1332
+ opts.separator "General options:"
1333
+
1334
+ opts.on("-q", "--quiet", "Silence output") do |val|
1335
+ installer.quiet = val
1336
+ end
1337
+
1338
+ opts.on("--verbose", "Provide verbose output") do |val|
1339
+ installer.verbose = val
1340
+ end
1341
+
1342
+ opts.on("-n", "--no-write", "Do not write to disk") do |val|
1343
+ installer.no_harm = !val
1344
+ end
1345
+
1346
+ opts.on("--dryrun", "Same as --no-write") do |val|
1347
+ installer.no_harm = val
1348
+ end
1349
+
1350
+ # common options
1351
+ opts.separator ""
1352
+ opts.separator "Inform options:"
1353
+
1354
+ # Tail options (eg. commands in option form)
1355
+ opts.on_tail("-h", "--help", "display this help information") do
1356
+ puts Setup.help
1357
+ exit
1358
+ end
1359
+
1360
+ opts.on_tail("--version", "Show version") do
1361
+ puts File.basename($0) + ' v' + Setup::Version.join('.')
1362
+ exit
1363
+ end
1364
+
1365
+ opts.on_tail("--copyright", "Show copyright") do
1366
+ puts Setup::Copyright
1367
+ exit
1368
+ end
1369
+
1370
+ begin
1371
+ opts.parse!(ARGV)
1372
+ rescue OptionParser::InvalidOption
1373
+ $stderr.puts $!.to_s.capitalize
1374
+ exit 1
1375
+ end
1376
+
1377
+ begin
1378
+ installer.__send__("exec_#{task}")
1379
+ rescue SetupError
1380
+ raise if $DEBUG
1381
+ $stderr.puts $!.message
1382
+ $stderr.puts "Try 'ruby #{$0} --help' for detailed usage."
1383
+ exit 1
1384
+ end
1385
+ end
1386
+
1387
+ # Generate help text.
1388
+ def self.help
1389
+ fmt = " " * 10 + "%-10s %s"
1390
+ commands = Installer::TASK_DESCRIPTIONS.collect do |k,d|
1391
+ (fmt % ["#{k}", d])
1392
+ end.join("\n").strip
1393
+
1394
+ fmt = " " * 13 + "%-20s %s"
1395
+ configs = ConfigTable::DESCRIPTIONS.collect do |k,t,d|
1396
+ (fmt % ["--#{k}", d])
1397
+ end.join("\n").strip
1398
+
1399
+ text = <<-END
1400
+ USAGE: #{File.basename($0)} [command] [options]
1401
+
1402
+ Commands:
1403
+ #{commands}
1404
+
1405
+ Options for CONFIG:
1406
+ #{configs}
1407
+
1408
+ Options for INSTALL:
1409
+ --prefix Set the install prefix
1410
+
1411
+ Options in common:
1412
+ -q --quiet Silence output
1413
+ --verbose Provide verbose output
1414
+ -n --no-write Do not write to disk
1415
+
1416
+ END
1417
+
1418
+ text.gsub(/^ \ \ \ \ \ /, '')
1419
+ end
1420
+
1421
+ #
1422
+ def self.run_rake
1423
+ installer = Setup::Installer.new
1424
+ installer.rake_define
1425
+ end
1426
+
1427
+ end
1428
+
1429
+ #
1430
+ # Ruby Extensions
1431
+ #
1432
+
1433
+ unless File.respond_to?(:read) # Ruby 1.6 and less
1434
+ def File.read(fname)
1435
+ open(fname) {|f|
1436
+ return f.read
1437
+ }
1438
+ end
1439
+ end
1440
+
1441
+ unless Errno.const_defined?(:ENOTEMPTY) # Windows?
1442
+ module Errno
1443
+ class ENOTEMPTY
1444
+ # We do not raise this exception, implementation is not needed.
1445
+ end
1446
+ end
1447
+ end
1448
+
1449
+ # for corrupted Windows' stat(2)
1450
+ def File.dir?(path)
1451
+ File.directory?((path[-1,1] == '/') ? path : path + '/')
1452
+ end
1453
+
1454
+ #
1455
+ # Runners
1456
+ #
1457
+
1458
+ if $0 == __FILE__
1459
+
1460
+ Setup.run_cli
1461
+
1462
+ elsif defined?(Rake)
1463
+
1464
+ Setup.run_rake
1465
+
1466
+ end
1467
+