cbot-mime-types 1.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (9) hide show
  1. data/ChangeLog +104 -0
  2. data/LICENCE +18 -0
  3. data/README +30 -0
  4. data/Rakefile +208 -0
  5. data/lib/mime/types.rb +1558 -0
  6. data/pre-setup.rb +46 -0
  7. data/setup.rb +1366 -0
  8. data/tests/testall.rb +18 -0
  9. metadata +65 -0
data/pre-setup.rb ADDED
@@ -0,0 +1,46 @@
1
+ require 'rdoc/rdoc'
2
+ ##
3
+ # Build the rdoc documentation. Also, try to build the RI documentation.
4
+ #
5
+ def build_rdoc(options)
6
+ RDoc::RDoc.new.document(options)
7
+ rescue RDoc::RDocError => e
8
+ $stderr.puts e.message
9
+ rescue Exception => e
10
+ $stderr.puts "Couldn't build RDoc documentation\n#{e.message}"
11
+ end
12
+
13
+ def build_ri(files)
14
+ RDoc::RDoc.new(["--ri-site", "--merge"] + files)
15
+ rescue RDoc::RDocError => e
16
+ $stderr.puts e.message
17
+ rescue Exception => e
18
+ $stderr.puts "Couldn't build Ri documentation\n#{e.message}"
19
+ end
20
+
21
+ def run_tests(test_list)
22
+ return if test_list.empty?
23
+
24
+ require 'test/unit/ui/console/testrunner'
25
+ $:.unshift "lib"
26
+ test_list.each do |test|
27
+ next if File.directory?(test)
28
+ require test
29
+ end
30
+
31
+ tests = []
32
+ ObjectSpace.each_object { |o| tests << o if o.kind_of?(Class) }
33
+ tests.delete_if { |o| !o.ancestors.include?(Test::Unit::TestCase) }
34
+ tests.delete_if { |o| o == Test::Unit::TestCase }
35
+
36
+ tests.each { |test| Test::Unit::UI::Console::TestRunner.run(test) }
37
+ $:.shift
38
+ end
39
+
40
+ rdoc = %w(--main README --line-numbers
41
+ --title MIME::Types)
42
+ ri = %w(--ri-site --merge)
43
+ dox = %w(README ChangeLog lib)
44
+ build_rdoc rdoc + dox
45
+ build_ri ri + dox
46
+ run_tests Dir["tests/**/*"]
data/setup.rb ADDED
@@ -0,0 +1,1366 @@
1
+ #
2
+ # setup.rb
3
+ #
4
+ # Copyright (c) 2000-2004 Minero Aoki
5
+ #
6
+ # This program is free software.
7
+ # You can distribute/modify this program under the terms of
8
+ # the GNU LGPL, Lesser General Public License version 2.1.
9
+ #
10
+
11
+ unless Enumerable.method_defined?(:map) # Ruby 1.4.6
12
+ module Enumerable
13
+ alias map collect
14
+ end
15
+ end
16
+
17
+ unless File.respond_to?(:read) # Ruby 1.6
18
+ def File.read(fname)
19
+ open(fname) {|f|
20
+ return f.read
21
+ }
22
+ end
23
+ end
24
+
25
+ def File.binread(fname)
26
+ open(fname, 'rb') {|f|
27
+ return f.read
28
+ }
29
+ end
30
+
31
+ # for corrupted windows stat(2)
32
+ def File.dir?(path)
33
+ File.directory?((path[-1,1] == '/') ? path : path + '/')
34
+ end
35
+
36
+
37
+ class SetupError < StandardError; end
38
+
39
+ def setup_rb_error(msg)
40
+ raise SetupError, msg
41
+ end
42
+
43
+ #
44
+ # Config
45
+ #
46
+
47
+ if arg = ARGV.detect {|arg| /\A--rbconfig=/ =~ arg }
48
+ ARGV.delete(arg)
49
+ require arg.split(/=/, 2)[1]
50
+ $".push 'rbconfig.rb'
51
+ else
52
+ require 'rbconfig'
53
+ end
54
+
55
+ def multipackage_install?
56
+ FileTest.directory?(File.dirname($0) + '/packages')
57
+ end
58
+
59
+
60
+ class ConfigItem
61
+ def initialize(name, template, default, desc)
62
+ @name = name.freeze
63
+ @template = template
64
+ @value = default
65
+ @default = default.dup.freeze
66
+ @description = desc
67
+ end
68
+
69
+ attr_reader :name
70
+ attr_reader :description
71
+
72
+ attr_accessor :default
73
+ alias help_default default
74
+
75
+ def help_opt
76
+ "--#{@name}=#{@template}"
77
+ end
78
+
79
+ def value
80
+ @value
81
+ end
82
+
83
+ def eval(table)
84
+ @value.gsub(%r<\$([^/]+)>) { table[$1] }
85
+ end
86
+
87
+ def set(val)
88
+ @value = check(val)
89
+ end
90
+
91
+ private
92
+
93
+ def check(val)
94
+ setup_rb_error "config: --#{name} requires argument" unless val
95
+ val
96
+ end
97
+ end
98
+
99
+ class BoolItem < ConfigItem
100
+ def config_type
101
+ 'bool'
102
+ end
103
+
104
+ def help_opt
105
+ "--#{@name}"
106
+ end
107
+
108
+ private
109
+
110
+ def check(val)
111
+ return 'yes' unless val
112
+ unless /\A(y(es)?|n(o)?|t(rue)?|f(alse))\z/i =~ val
113
+ setup_rb_error "config: --#{@name} accepts only yes/no for argument"
114
+ end
115
+ (/\Ay(es)?|\At(rue)/i =~ value) ? 'yes' : 'no'
116
+ end
117
+ end
118
+
119
+ class PathItem < ConfigItem
120
+ def config_type
121
+ 'path'
122
+ end
123
+
124
+ private
125
+
126
+ def check(path)
127
+ setup_rb_error "config: --#{@name} requires argument" unless path
128
+ path[0,1] == '$' ? path : File.expand_path(path)
129
+ end
130
+ end
131
+
132
+ class ProgramItem < ConfigItem
133
+ def config_type
134
+ 'program'
135
+ end
136
+ end
137
+
138
+ class SelectItem < ConfigItem
139
+ def initialize(name, template, default, desc)
140
+ super
141
+ @ok = template.split('/')
142
+ end
143
+
144
+ def config_type
145
+ 'select'
146
+ end
147
+
148
+ private
149
+
150
+ def check(val)
151
+ unless @ok.include?(val.strip)
152
+ setup_rb_error "config: use --#{@name}=#{@template} (#{val})"
153
+ end
154
+ val.strip
155
+ end
156
+ end
157
+
158
+ class PackageSelectionItem < ConfigItem
159
+ def initialize(name, template, default, help_default, desc)
160
+ super name, template, default, desc
161
+ @help_default = help_default
162
+ end
163
+
164
+ attr_reader :help_default
165
+
166
+ def config_type
167
+ 'package'
168
+ end
169
+
170
+ private
171
+
172
+ def check(val)
173
+ unless File.dir?("packages/#{val}")
174
+ setup_rb_error "config: no such package: #{val}"
175
+ end
176
+ val
177
+ end
178
+ end
179
+
180
+ class ConfigTable_class
181
+
182
+ def initialize(items)
183
+ @items = items
184
+ @table = {}
185
+ items.each do |i|
186
+ @table[i.name] = i
187
+ end
188
+ ALIASES.each do |ali, name|
189
+ @table[ali] = @table[name]
190
+ end
191
+ @script_extensions = ['rb']
192
+ end
193
+
194
+ attr_accessor :script_extensions
195
+
196
+ include Enumerable
197
+
198
+ def each(&block)
199
+ @items.each(&block)
200
+ end
201
+
202
+ def key?(name)
203
+ @table.key?(name)
204
+ end
205
+
206
+ def lookup(name)
207
+ @table[name] or raise ArgumentError, "no such config item: #{name}"
208
+ end
209
+
210
+ def add(item)
211
+ @items.push item
212
+ @table[item.name] = item
213
+ end
214
+
215
+ def remove(name)
216
+ item = lookup(name)
217
+ @items.delete_if {|i| i.name == name }
218
+ @table.delete_if {|name, i| i.name == name }
219
+ item
220
+ end
221
+
222
+ def new
223
+ dup()
224
+ end
225
+
226
+ def savefile
227
+ '.config'
228
+ end
229
+
230
+ def load
231
+ begin
232
+ t = dup()
233
+ File.foreach(savefile()) do |line|
234
+ k, v = *line.split(/=/, 2)
235
+ t[k] = v.strip
236
+ end
237
+ t
238
+ rescue Errno::ENOENT
239
+ setup_rb_error $!.message + "#{File.basename($0)} config first"
240
+ end
241
+ end
242
+
243
+ def save
244
+ @items.each {|i| i.value }
245
+ File.open(savefile(), 'w') {|f|
246
+ @items.each do |i|
247
+ f.printf "%s=%s\n", i.name, i.value if i.value
248
+ end
249
+ }
250
+ end
251
+
252
+ def [](key)
253
+ lookup(key).eval(self)
254
+ end
255
+
256
+ def []=(key, val)
257
+ lookup(key).set val
258
+ end
259
+
260
+ end
261
+
262
+ c = ::Config::CONFIG
263
+
264
+ rubypath = c['bindir'] + '/' + c['ruby_install_name']
265
+
266
+ major = c['MAJOR'].to_i
267
+ minor = c['MINOR'].to_i
268
+ teeny = c['TEENY'].to_i
269
+ version = "#{major}.#{minor}"
270
+
271
+ # ruby ver. >= 1.4.4?
272
+ newpath_p = ((major >= 2) or
273
+ ((major == 1) and
274
+ ((minor >= 5) or
275
+ ((minor == 4) and (teeny >= 4)))))
276
+
277
+ if c['rubylibdir']
278
+ # V < 1.6.3
279
+ _stdruby = c['rubylibdir']
280
+ _siteruby = c['sitedir']
281
+ _siterubyver = c['sitelibdir']
282
+ _siterubyverarch = c['sitearchdir']
283
+ elsif newpath_p
284
+ # 1.4.4 <= V <= 1.6.3
285
+ _stdruby = "$prefix/lib/ruby/#{version}"
286
+ _siteruby = c['sitedir']
287
+ _siterubyver = "$siteruby/#{version}"
288
+ _siterubyverarch = "$siterubyver/#{c['arch']}"
289
+ else
290
+ # V < 1.4.4
291
+ _stdruby = "$prefix/lib/ruby/#{version}"
292
+ _siteruby = "$prefix/lib/ruby/#{version}/site_ruby"
293
+ _siterubyver = _siteruby
294
+ _siterubyverarch = "$siterubyver/#{c['arch']}"
295
+ end
296
+ libdir = '-* dummy libdir *-'
297
+ stdruby = '-* dummy rubylibdir *-'
298
+ siteruby = '-* dummy site_ruby *-'
299
+ siterubyver = '-* dummy site_ruby version *-'
300
+ parameterize = lambda {|path|
301
+ path.sub(/\A#{Regexp.quote(c['prefix'])}/, '$prefix')\
302
+ .sub(/\A#{Regexp.quote(libdir)}/, '$libdir')\
303
+ .sub(/\A#{Regexp.quote(stdruby)}/, '$stdruby')\
304
+ .sub(/\A#{Regexp.quote(siteruby)}/, '$siteruby')\
305
+ .sub(/\A#{Regexp.quote(siterubyver)}/, '$siterubyver')
306
+ }
307
+ libdir = parameterize.call(c['libdir'])
308
+ stdruby = parameterize.call(_stdruby)
309
+ siteruby = parameterize.call(_siteruby)
310
+ siterubyver = parameterize.call(_siterubyver)
311
+ siterubyverarch = parameterize.call(_siterubyverarch)
312
+
313
+ if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg }
314
+ makeprog = arg.sub(/'/, '').split(/=/, 2)[1]
315
+ else
316
+ makeprog = 'make'
317
+ end
318
+
319
+ common_conf = [
320
+ PathItem.new('prefix', 'path', c['prefix'],
321
+ 'path prefix of target environment'),
322
+ PathItem.new('bindir', 'path', parameterize.call(c['bindir']),
323
+ 'the directory for commands'),
324
+ PathItem.new('libdir', 'path', libdir,
325
+ 'the directory for libraries'),
326
+ PathItem.new('datadir', 'path', parameterize.call(c['datadir']),
327
+ 'the directory for shared data'),
328
+ PathItem.new('mandir', 'path', parameterize.call(c['mandir']),
329
+ 'the directory for man pages'),
330
+ PathItem.new('sysconfdir', 'path', parameterize.call(c['sysconfdir']),
331
+ 'the directory for man pages'),
332
+ PathItem.new('stdruby', 'path', stdruby,
333
+ 'the directory for standard ruby libraries'),
334
+ PathItem.new('siteruby', 'path', siteruby,
335
+ 'the directory for version-independent aux ruby libraries'),
336
+ PathItem.new('siterubyver', 'path', siterubyver,
337
+ 'the directory for aux ruby libraries'),
338
+ PathItem.new('siterubyverarch', 'path', siterubyverarch,
339
+ 'the directory for aux ruby binaries'),
340
+ PathItem.new('rbdir', 'path', '$siterubyver',
341
+ 'the directory for ruby scripts'),
342
+ PathItem.new('sodir', 'path', '$siterubyverarch',
343
+ 'the directory for ruby extentions'),
344
+ PathItem.new('rubypath', 'path', rubypath,
345
+ 'the path to set to #! line'),
346
+ ProgramItem.new('rubyprog', 'name', rubypath,
347
+ 'the ruby program using for installation'),
348
+ ProgramItem.new('makeprog', 'name', makeprog,
349
+ 'the make program to compile ruby extentions'),
350
+ SelectItem.new('shebang', 'all/ruby/never', 'ruby',
351
+ 'shebang line (#!) editing mode'),
352
+ BoolItem.new('without-ext', 'yes/no', 'no',
353
+ 'does not compile/install ruby extentions')
354
+ ]
355
+ class ConfigTable_class # open again
356
+ ALIASES = {
357
+ 'std-ruby' => 'stdruby',
358
+ 'site-ruby-common' => 'siteruby', # For backward compatibility
359
+ 'site-ruby' => 'siterubyver', # For backward compatibility
360
+ 'bin-dir' => 'bindir',
361
+ 'bin-dir' => 'bindir',
362
+ 'rb-dir' => 'rbdir',
363
+ 'so-dir' => 'sodir',
364
+ 'data-dir' => 'datadir',
365
+ 'ruby-path' => 'rubypath',
366
+ 'ruby-prog' => 'rubyprog',
367
+ 'ruby' => 'rubyprog',
368
+ 'make-prog' => 'makeprog',
369
+ 'make' => 'makeprog'
370
+ }
371
+ end
372
+ multipackage_conf = [
373
+ PackageSelectionItem.new('with', 'name,name...', '', 'ALL',
374
+ 'package names that you want to install'),
375
+ PackageSelectionItem.new('without', 'name,name...', '', 'NONE',
376
+ 'package names that you do not want to install')
377
+ ]
378
+ if multipackage_install?
379
+ ConfigTable = ConfigTable_class.new(common_conf + multipackage_conf)
380
+ else
381
+ ConfigTable = ConfigTable_class.new(common_conf)
382
+ end
383
+
384
+
385
+ module MetaConfigAPI
386
+
387
+ def eval_file_ifexist(fname)
388
+ instance_eval File.read(fname), fname, 1 if File.file?(fname)
389
+ end
390
+
391
+ def config_names
392
+ ConfigTable.map {|i| i.name }
393
+ end
394
+
395
+ def config?(name)
396
+ ConfigTable.key?(name)
397
+ end
398
+
399
+ def bool_config?(name)
400
+ ConfigTable.lookup(name).config_type == 'bool'
401
+ end
402
+
403
+ def path_config?(name)
404
+ ConfigTable.lookup(name).config_type == 'path'
405
+ end
406
+
407
+ def value_config?(name)
408
+ case ConfigTable.lookup(name).config_type
409
+ when 'bool', 'path'
410
+ true
411
+ else
412
+ false
413
+ end
414
+ end
415
+
416
+ def add_config(item)
417
+ ConfigTable.add item
418
+ end
419
+
420
+ def add_bool_config(name, default, desc)
421
+ ConfigTable.add BoolItem.new(name, 'yes/no', default ? 'yes' : 'no', desc)
422
+ end
423
+
424
+ def add_path_config(name, default, desc)
425
+ ConfigTable.add PathItem.new(name, 'path', default, desc)
426
+ end
427
+
428
+ def set_config_default(name, default)
429
+ ConfigTable.lookup(name).default = default
430
+ end
431
+
432
+ def remove_config(name)
433
+ ConfigTable.remove(name)
434
+ end
435
+
436
+ def add_script_extension(ext)
437
+ ConfigTable.script_extensions << ext
438
+ end
439
+ end
440
+
441
+
442
+ #
443
+ # File Operations
444
+ #
445
+
446
+ module FileOperations
447
+
448
+ def mkdir_p(dirname, prefix = nil)
449
+ dirname = prefix + File.expand_path(dirname) if prefix
450
+ $stderr.puts "mkdir -p #{dirname}" if verbose?
451
+ return if no_harm?
452
+
453
+ # does not check '/'... it's too abnormal case
454
+ dirs = File.expand_path(dirname).split(%r<(?=/)>)
455
+ if /\A[a-z]:\z/i =~ dirs[0]
456
+ disk = dirs.shift
457
+ dirs[0] = disk + dirs[0]
458
+ end
459
+ dirs.each_index do |idx|
460
+ path = dirs[0..idx].join('')
461
+ Dir.mkdir path unless File.dir?(path)
462
+ end
463
+ end
464
+
465
+ def rm_f(fname)
466
+ $stderr.puts "rm -f #{fname}" if verbose?
467
+ return if no_harm?
468
+
469
+ if File.exist?(fname) or File.symlink?(fname)
470
+ File.chmod 0777, fname
471
+ File.unlink fname
472
+ end
473
+ end
474
+
475
+ def rm_rf(dn)
476
+ $stderr.puts "rm -rf #{dn}" if verbose?
477
+ return if no_harm?
478
+
479
+ Dir.chdir dn
480
+ Dir.foreach('.') do |fn|
481
+ next if fn == '.'
482
+ next if fn == '..'
483
+ if File.dir?(fn)
484
+ verbose_off {
485
+ rm_rf fn
486
+ }
487
+ else
488
+ verbose_off {
489
+ rm_f fn
490
+ }
491
+ end
492
+ end
493
+ Dir.chdir '..'
494
+ Dir.rmdir dn
495
+ end
496
+
497
+ def move_file(src, dest)
498
+ File.unlink dest if File.exist?(dest)
499
+ begin
500
+ File.rename src, dest
501
+ rescue
502
+ File.open(dest, 'wb') {|f| f.write File.binread(src) }
503
+ File.chmod File.stat(src).mode, dest
504
+ File.unlink src
505
+ end
506
+ end
507
+
508
+ def install(from, dest, mode, prefix = nil)
509
+ $stderr.puts "install #{from} #{dest}" if verbose?
510
+ return if no_harm?
511
+
512
+ realdest = prefix ? prefix + File.expand_path(dest) : dest
513
+ realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest)
514
+ str = File.binread(from)
515
+ if diff?(str, realdest)
516
+ verbose_off {
517
+ rm_f realdest if File.exist?(realdest)
518
+ }
519
+ File.open(realdest, 'wb') {|f|
520
+ f.write str
521
+ }
522
+ File.chmod mode, realdest
523
+
524
+ File.open("#{objdir_root()}/InstalledFiles", 'a') {|f|
525
+ if prefix
526
+ f.puts realdest.sub(prefix, '')
527
+ else
528
+ f.puts realdest
529
+ end
530
+ }
531
+ end
532
+ end
533
+
534
+ def diff?(new_content, path)
535
+ return true unless File.exist?(path)
536
+ new_content != File.binread(path)
537
+ end
538
+
539
+ def command(str)
540
+ $stderr.puts str if verbose?
541
+ system str or raise RuntimeError, "'system #{str}' failed"
542
+ end
543
+
544
+ def ruby(str)
545
+ command config('rubyprog') + ' ' + str
546
+ end
547
+
548
+ def make(task = '')
549
+ command config('makeprog') + ' ' + task
550
+ end
551
+
552
+ def extdir?(dir)
553
+ File.exist?(dir + '/MANIFEST')
554
+ end
555
+
556
+ def all_files_in(dirname)
557
+ Dir.open(dirname) {|d|
558
+ return d.select {|ent| File.file?("#{dirname}/#{ent}") }
559
+ }
560
+ end
561
+
562
+ REJECT_DIRS = %w(
563
+ CVS SCCS RCS CVS.adm .svn
564
+ )
565
+
566
+ def all_dirs_in(dirname)
567
+ Dir.open(dirname) {|d|
568
+ return d.select {|n| File.dir?("#{dirname}/#{n}") } - %w(. ..) - REJECT_DIRS
569
+ }
570
+ end
571
+
572
+ end
573
+
574
+
575
+ #
576
+ # Main Installer
577
+ #
578
+
579
+ module HookUtils
580
+
581
+ def run_hook(name)
582
+ try_run_hook "#{curr_srcdir()}/#{name}" or
583
+ try_run_hook "#{curr_srcdir()}/#{name}.rb"
584
+ end
585
+
586
+ def try_run_hook(fname)
587
+ return false unless File.file?(fname)
588
+ begin
589
+ instance_eval File.read(fname), fname, 1
590
+ rescue
591
+ setup_rb_error "hook #{fname} failed:\n" + $!.message
592
+ end
593
+ true
594
+ end
595
+
596
+ end
597
+
598
+
599
+ module HookScriptAPI
600
+
601
+ def get_config(key)
602
+ @config[key]
603
+ end
604
+
605
+ alias config get_config
606
+
607
+ def set_config(key, val)
608
+ @config[key] = val
609
+ end
610
+
611
+ #
612
+ # srcdir/objdir (works only in the package directory)
613
+ #
614
+
615
+ #abstract srcdir_root
616
+ #abstract objdir_root
617
+ #abstract relpath
618
+
619
+ def curr_srcdir
620
+ "#{srcdir_root()}/#{relpath()}"
621
+ end
622
+
623
+ def curr_objdir
624
+ "#{objdir_root()}/#{relpath()}"
625
+ end
626
+
627
+ def srcfile(path)
628
+ "#{curr_srcdir()}/#{path}"
629
+ end
630
+
631
+ def srcexist?(path)
632
+ File.exist?(srcfile(path))
633
+ end
634
+
635
+ def srcdirectory?(path)
636
+ File.dir?(srcfile(path))
637
+ end
638
+
639
+ def srcfile?(path)
640
+ File.file? srcfile(path)
641
+ end
642
+
643
+ def srcentries(path = '.')
644
+ Dir.open("#{curr_srcdir()}/#{path}") {|d|
645
+ return d.to_a - %w(. ..)
646
+ }
647
+ end
648
+
649
+ def srcfiles(path = '.')
650
+ srcentries(path).select {|fname|
651
+ File.file?(File.join(curr_srcdir(), path, fname))
652
+ }
653
+ end
654
+
655
+ def srcdirectories(path = '.')
656
+ srcentries(path).select {|fname|
657
+ File.dir?(File.join(curr_srcdir(), path, fname))
658
+ }
659
+ end
660
+
661
+ end
662
+
663
+
664
+ class ToplevelInstaller
665
+
666
+ Version = '3.3.1'
667
+ Copyright = 'Copyright (c) 2000-2004 Minero Aoki'
668
+
669
+ TASKS = [
670
+ [ 'all', 'do config, setup, then install' ],
671
+ [ 'config', 'saves your configurations' ],
672
+ [ 'show', 'shows current configuration' ],
673
+ [ 'setup', 'compiles ruby extentions and others' ],
674
+ [ 'install', 'installs files' ],
675
+ [ 'clean', "does `make clean' for each extention" ],
676
+ [ 'distclean',"does `make distclean' for each extention" ]
677
+ ]
678
+
679
+ def ToplevelInstaller.invoke
680
+ instance().invoke
681
+ end
682
+
683
+ @singleton = nil
684
+
685
+ def ToplevelInstaller.instance
686
+ @singleton ||= new(File.dirname($0))
687
+ @singleton
688
+ end
689
+
690
+ include MetaConfigAPI
691
+
692
+ def initialize(ardir_root)
693
+ @config = nil
694
+ @options = { 'verbose' => true }
695
+ @ardir = File.expand_path(ardir_root)
696
+ end
697
+
698
+ def inspect
699
+ "#<#{self.class} #{__id__()}>"
700
+ end
701
+
702
+ def invoke
703
+ run_metaconfigs
704
+ case task = parsearg_global()
705
+ when nil, 'all'
706
+ @config = load_config('config')
707
+ parsearg_config
708
+ init_installers
709
+ exec_config
710
+ exec_setup
711
+ exec_install
712
+ else
713
+ @config = load_config(task)
714
+ __send__ "parsearg_#{task}"
715
+ init_installers
716
+ __send__ "exec_#{task}"
717
+ end
718
+ end
719
+
720
+ def run_metaconfigs
721
+ eval_file_ifexist "#{@ardir}/metaconfig"
722
+ end
723
+
724
+ def load_config(task)
725
+ case task
726
+ when 'config'
727
+ ConfigTable.new
728
+ when 'clean', 'distclean'
729
+ if File.exist?(ConfigTable.savefile)
730
+ then ConfigTable.load
731
+ else ConfigTable.new
732
+ end
733
+ else
734
+ ConfigTable.load
735
+ end
736
+ end
737
+
738
+ def init_installers
739
+ @installer = Installer.new(@config, @options, @ardir, File.expand_path('.'))
740
+ end
741
+
742
+ #
743
+ # Hook Script API bases
744
+ #
745
+
746
+ def srcdir_root
747
+ @ardir
748
+ end
749
+
750
+ def objdir_root
751
+ '.'
752
+ end
753
+
754
+ def relpath
755
+ '.'
756
+ end
757
+
758
+ #
759
+ # Option Parsing
760
+ #
761
+
762
+ def parsearg_global
763
+ valid_task = /\A(?:#{TASKS.map {|task,desc| task }.join '|'})\z/
764
+
765
+ while arg = ARGV.shift
766
+ case arg
767
+ when /\A\w+\z/
768
+ setup_rb_error "invalid task: #{arg}" unless valid_task =~ arg
769
+ return arg
770
+
771
+ when '-q', '--quiet'
772
+ @options['verbose'] = false
773
+
774
+ when '--verbose'
775
+ @options['verbose'] = true
776
+
777
+ when '-h', '--help'
778
+ print_usage $stdout
779
+ exit 0
780
+
781
+ when '-v', '--version'
782
+ puts "#{File.basename($0)} version #{Version}"
783
+ exit 0
784
+
785
+ when '--copyright'
786
+ puts Copyright
787
+ exit 0
788
+
789
+ else
790
+ setup_rb_error "unknown global option '#{arg}'"
791
+ end
792
+ end
793
+
794
+ nil
795
+ end
796
+
797
+
798
+ def parsearg_no_options
799
+ unless ARGV.empty?
800
+ setup_rb_error "#{task}: unknown options: #{ARGV.join ' '}"
801
+ end
802
+ end
803
+
804
+ alias parsearg_show parsearg_no_options
805
+ alias parsearg_setup parsearg_no_options
806
+ alias parsearg_clean parsearg_no_options
807
+ alias parsearg_distclean parsearg_no_options
808
+
809
+ def parsearg_config
810
+ re = /\A--(#{ConfigTable.map {|i| i.name }.join('|')})(?:=(.*))?\z/
811
+ @options['config-opt'] = []
812
+
813
+ while i = ARGV.shift
814
+ if /\A--?\z/ =~ i
815
+ @options['config-opt'] = ARGV.dup
816
+ break
817
+ end
818
+ m = re.match(i) or setup_rb_error "config: unknown option #{i}"
819
+ name, value = *m.to_a[1,2]
820
+ @config[name] = value
821
+ end
822
+ end
823
+
824
+ def parsearg_install
825
+ @options['no-harm'] = false
826
+ @options['install-prefix'] = ''
827
+ while a = ARGV.shift
828
+ case a
829
+ when /\A--no-harm\z/
830
+ @options['no-harm'] = true
831
+ when /\A--prefix=(.*)\z/
832
+ path = $1
833
+ path = File.expand_path(path) unless path[0,1] == '/'
834
+ @options['install-prefix'] = path
835
+ else
836
+ setup_rb_error "install: unknown option #{a}"
837
+ end
838
+ end
839
+ end
840
+
841
+ def print_usage(out)
842
+ out.puts 'Typical Installation Procedure:'
843
+ out.puts " $ ruby #{File.basename $0} config"
844
+ out.puts " $ ruby #{File.basename $0} setup"
845
+ out.puts " # ruby #{File.basename $0} install (may require root privilege)"
846
+ out.puts
847
+ out.puts 'Detailed Usage:'
848
+ out.puts " ruby #{File.basename $0} <global option>"
849
+ out.puts " ruby #{File.basename $0} [<global options>] <task> [<task options>]"
850
+
851
+ fmt = " %-24s %s\n"
852
+ out.puts
853
+ out.puts 'Global options:'
854
+ out.printf fmt, '-q,--quiet', 'suppress message outputs'
855
+ out.printf fmt, ' --verbose', 'output messages verbosely'
856
+ out.printf fmt, '-h,--help', 'print this message'
857
+ out.printf fmt, '-v,--version', 'print version and quit'
858
+ out.printf fmt, ' --copyright', 'print copyright and quit'
859
+ out.puts
860
+ out.puts 'Tasks:'
861
+ TASKS.each do |name, desc|
862
+ out.printf fmt, name, desc
863
+ end
864
+
865
+ fmt = " %-24s %s [%s]\n"
866
+ out.puts
867
+ out.puts 'Options for CONFIG or ALL:'
868
+ ConfigTable.each do |item|
869
+ out.printf fmt, item.help_opt, item.description, item.help_default
870
+ end
871
+ out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',"running ruby's"
872
+ out.puts
873
+ out.puts 'Options for INSTALL:'
874
+ out.printf fmt, '--no-harm', 'only display what to do if given', 'off'
875
+ out.printf fmt, '--prefix=path', 'install path prefix', '$prefix'
876
+ out.puts
877
+ end
878
+
879
+ #
880
+ # Task Handlers
881
+ #
882
+
883
+ def exec_config
884
+ @installer.exec_config
885
+ @config.save # must be final
886
+ end
887
+
888
+ def exec_setup
889
+ @installer.exec_setup
890
+ end
891
+
892
+ def exec_install
893
+ @installer.exec_install
894
+ end
895
+
896
+ def exec_show
897
+ ConfigTable.each do |i|
898
+ printf "%-20s %s\n", i.name, i.value
899
+ end
900
+ end
901
+
902
+ def exec_clean
903
+ @installer.exec_clean
904
+ end
905
+
906
+ def exec_distclean
907
+ @installer.exec_distclean
908
+ end
909
+
910
+ end
911
+
912
+
913
+ class ToplevelInstallerMulti < ToplevelInstaller
914
+
915
+ include HookUtils
916
+ include HookScriptAPI
917
+ include FileOperations
918
+
919
+ def initialize(ardir)
920
+ super
921
+ @packages = all_dirs_in("#{@ardir}/packages")
922
+ raise 'no package exists' if @packages.empty?
923
+ end
924
+
925
+ def run_metaconfigs
926
+ eval_file_ifexist "#{@ardir}/metaconfig"
927
+ @packages.each do |name|
928
+ eval_file_ifexist "#{@ardir}/packages/#{name}/metaconfig"
929
+ end
930
+ end
931
+
932
+ def init_installers
933
+ @installers = {}
934
+ @packages.each do |pack|
935
+ @installers[pack] = Installer.new(@config, @options,
936
+ "#{@ardir}/packages/#{pack}",
937
+ "packages/#{pack}")
938
+ end
939
+
940
+ with = extract_selection(config('with'))
941
+ without = extract_selection(config('without'))
942
+ @selected = @installers.keys.select {|name|
943
+ (with.empty? or with.include?(name)) \
944
+ and not without.include?(name)
945
+ }
946
+ end
947
+
948
+ def extract_selection(list)
949
+ a = list.split(/,/)
950
+ a.each do |name|
951
+ setup_rb_error "no such package: #{name}" unless @installers.key?(name)
952
+ end
953
+ a
954
+ end
955
+
956
+ def print_usage(f)
957
+ super
958
+ f.puts 'Inluded packages:'
959
+ f.puts ' ' + @packages.sort.join(' ')
960
+ f.puts
961
+ end
962
+
963
+ #
964
+ # multi-package metaconfig API
965
+ #
966
+
967
+ attr_reader :packages
968
+
969
+ def declare_packages(list)
970
+ raise 'package list is empty' if list.empty?
971
+ list.each do |name|
972
+ raise "directory packages/#{name} does not exist"\
973
+ unless File.dir?("#{@ardir}/packages/#{name}")
974
+ end
975
+ @packages = list
976
+ end
977
+
978
+ #
979
+ # Task Handlers
980
+ #
981
+
982
+ def exec_config
983
+ run_hook 'pre-config'
984
+ each_selected_installers {|inst| inst.exec_config }
985
+ run_hook 'post-config'
986
+ @config.save # must be final
987
+ end
988
+
989
+ def exec_setup
990
+ run_hook 'pre-setup'
991
+ each_selected_installers {|inst| inst.exec_setup }
992
+ run_hook 'post-setup'
993
+ end
994
+
995
+ def exec_install
996
+ run_hook 'pre-install'
997
+ each_selected_installers {|inst| inst.exec_install }
998
+ run_hook 'post-install'
999
+ end
1000
+
1001
+ def exec_clean
1002
+ rm_f ConfigTable.savefile
1003
+ run_hook 'pre-clean'
1004
+ each_selected_installers {|inst| inst.exec_clean }
1005
+ run_hook 'post-clean'
1006
+ end
1007
+
1008
+ def exec_distclean
1009
+ rm_f ConfigTable.savefile
1010
+ run_hook 'pre-distclean'
1011
+ each_selected_installers {|inst| inst.exec_distclean }
1012
+ run_hook 'post-distclean'
1013
+ end
1014
+
1015
+ #
1016
+ # lib
1017
+ #
1018
+
1019
+ def each_selected_installers
1020
+ Dir.mkdir 'packages' unless File.dir?('packages')
1021
+ @selected.each do |pack|
1022
+ $stderr.puts "Processing the package `#{pack}' ..." if @options['verbose']
1023
+ Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}")
1024
+ Dir.chdir "packages/#{pack}"
1025
+ yield @installers[pack]
1026
+ Dir.chdir '../..'
1027
+ end
1028
+ end
1029
+
1030
+ def verbose?
1031
+ @options['verbose']
1032
+ end
1033
+
1034
+ def no_harm?
1035
+ @options['no-harm']
1036
+ end
1037
+
1038
+ end
1039
+
1040
+
1041
+ class Installer
1042
+
1043
+ FILETYPES = %w( bin lib ext data )
1044
+
1045
+ include HookScriptAPI
1046
+ include HookUtils
1047
+ include FileOperations
1048
+
1049
+ def initialize(config, opt, srcroot, objroot)
1050
+ @config = config
1051
+ @options = opt
1052
+ @srcdir = File.expand_path(srcroot)
1053
+ @objdir = File.expand_path(objroot)
1054
+ @currdir = '.'
1055
+ end
1056
+
1057
+ def inspect
1058
+ "#<#{self.class} #{File.basename(@srcdir)}>"
1059
+ end
1060
+
1061
+ #
1062
+ # Hook Script API base methods
1063
+ #
1064
+
1065
+ def srcdir_root
1066
+ @srcdir
1067
+ end
1068
+
1069
+ def objdir_root
1070
+ @objdir
1071
+ end
1072
+
1073
+ def relpath
1074
+ @currdir
1075
+ end
1076
+
1077
+ #
1078
+ # configs/options
1079
+ #
1080
+
1081
+ def no_harm?
1082
+ @options['no-harm']
1083
+ end
1084
+
1085
+ def verbose?
1086
+ @options['verbose']
1087
+ end
1088
+
1089
+ def verbose_off
1090
+ begin
1091
+ save, @options['verbose'] = @options['verbose'], false
1092
+ yield
1093
+ ensure
1094
+ @options['verbose'] = save
1095
+ end
1096
+ end
1097
+
1098
+ #
1099
+ # TASK config
1100
+ #
1101
+
1102
+ def exec_config
1103
+ exec_task_traverse 'config'
1104
+ end
1105
+
1106
+ def config_dir_bin(rel)
1107
+ end
1108
+
1109
+ def config_dir_lib(rel)
1110
+ end
1111
+
1112
+ def config_dir_ext(rel)
1113
+ extconf if extdir?(curr_srcdir())
1114
+ end
1115
+
1116
+ def extconf
1117
+ opt = @options['config-opt'].join(' ')
1118
+ command "#{config('rubyprog')} #{curr_srcdir()}/extconf.rb #{opt}"
1119
+ end
1120
+
1121
+ def config_dir_data(rel)
1122
+ end
1123
+
1124
+ #
1125
+ # TASK setup
1126
+ #
1127
+
1128
+ def exec_setup
1129
+ exec_task_traverse 'setup'
1130
+ end
1131
+
1132
+ def setup_dir_bin(rel)
1133
+ all_files_in(curr_srcdir()).each do |fname|
1134
+ adjust_shebang "#{curr_srcdir()}/#{fname}"
1135
+ end
1136
+ end
1137
+
1138
+ def adjust_shebang(path)
1139
+ return if no_harm?
1140
+ tmpfile = File.basename(path) + '.tmp'
1141
+ begin
1142
+ File.open(path, 'rb') {|r|
1143
+ first = r.gets
1144
+ return unless File.basename(config('rubypath')) == 'ruby'
1145
+ return unless File.basename(first.sub(/\A\#!/, '').split[0]) == 'ruby'
1146
+ $stderr.puts "adjusting shebang: #{File.basename(path)}" if verbose?
1147
+ File.open(tmpfile, 'wb') {|w|
1148
+ w.print first.sub(/\A\#!\s*\S+/, '#! ' + config('rubypath'))
1149
+ w.write r.read
1150
+ }
1151
+ move_file tmpfile, File.basename(path)
1152
+ }
1153
+ ensure
1154
+ File.unlink tmpfile if File.exist?(tmpfile)
1155
+ end
1156
+ end
1157
+
1158
+ def setup_dir_lib(rel)
1159
+ end
1160
+
1161
+ def setup_dir_ext(rel)
1162
+ make if extdir?(curr_srcdir())
1163
+ end
1164
+
1165
+ def setup_dir_data(rel)
1166
+ end
1167
+
1168
+ #
1169
+ # TASK install
1170
+ #
1171
+
1172
+ def exec_install
1173
+ rm_f 'InstalledFiles'
1174
+ exec_task_traverse 'install'
1175
+ end
1176
+
1177
+ def install_dir_bin(rel)
1178
+ install_files collect_filenames_auto(), "#{config('bindir')}/#{rel}", 0755
1179
+ end
1180
+
1181
+ def install_dir_lib(rel)
1182
+ install_files ruby_scripts(), "#{config('rbdir')}/#{rel}", 0644
1183
+ end
1184
+
1185
+ def install_dir_ext(rel)
1186
+ return unless extdir?(curr_srcdir())
1187
+ install_files ruby_extentions('.'),
1188
+ "#{config('sodir')}/#{File.dirname(rel)}",
1189
+ 0555
1190
+ end
1191
+
1192
+ def install_dir_data(rel)
1193
+ install_files collect_filenames_auto(), "#{config('datadir')}/#{rel}", 0644
1194
+ end
1195
+
1196
+ def install_files(list, dest, mode)
1197
+ mkdir_p dest, @options['install-prefix']
1198
+ list.each do |fname|
1199
+ install fname, dest, mode, @options['install-prefix']
1200
+ end
1201
+ end
1202
+
1203
+ def ruby_scripts
1204
+ collect_filenames_auto().select {|n| /\.(#{ConfigTable.script_extensions.join('|')})\z/ =~ n }
1205
+ end
1206
+
1207
+ # picked up many entries from cvs-1.11.1/src/ignore.c
1208
+ reject_patterns = %w(
1209
+ core RCSLOG tags TAGS .make.state
1210
+ .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb
1211
+ *~ *.old *.bak *.BAK *.orig *.rej _$* *$
1212
+
1213
+ *.org *.in .*
1214
+ )
1215
+ mapping = {
1216
+ '.' => '\.',
1217
+ '$' => '\$',
1218
+ '#' => '\#',
1219
+ '*' => '.*'
1220
+ }
1221
+ REJECT_PATTERNS = Regexp.new('\A(?:' +
1222
+ reject_patterns.map {|pat|
1223
+ pat.gsub(/[\.\$\#\*]/) {|ch| mapping[ch] }
1224
+ }.join('|') +
1225
+ ')\z')
1226
+
1227
+ def collect_filenames_auto
1228
+ mapdir((existfiles() - hookfiles()).reject {|fname|
1229
+ REJECT_PATTERNS =~ fname
1230
+ })
1231
+ end
1232
+
1233
+ def existfiles
1234
+ all_files_in(curr_srcdir()) | all_files_in('.')
1235
+ end
1236
+
1237
+ def hookfiles
1238
+ %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt|
1239
+ %w( config setup install clean ).map {|t| sprintf(fmt, t) }
1240
+ }.flatten
1241
+ end
1242
+
1243
+ def mapdir(filelist)
1244
+ filelist.map {|fname|
1245
+ if File.exist?(fname) # objdir
1246
+ fname
1247
+ else # srcdir
1248
+ File.join(curr_srcdir(), fname)
1249
+ end
1250
+ }
1251
+ end
1252
+
1253
+ def ruby_extentions(dir)
1254
+ Dir.open(dir) {|d|
1255
+ ents = d.select {|fname| /\.#{::Config::CONFIG['DLEXT']}\z/ =~ fname }
1256
+ if ents.empty?
1257
+ setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first"
1258
+ end
1259
+ return ents
1260
+ }
1261
+ end
1262
+
1263
+ #
1264
+ # TASK clean
1265
+ #
1266
+
1267
+ def exec_clean
1268
+ exec_task_traverse 'clean'
1269
+ rm_f ConfigTable.savefile
1270
+ rm_f 'InstalledFiles'
1271
+ end
1272
+
1273
+ def clean_dir_bin(rel)
1274
+ end
1275
+
1276
+ def clean_dir_lib(rel)
1277
+ end
1278
+
1279
+ def clean_dir_ext(rel)
1280
+ return unless extdir?(curr_srcdir())
1281
+ make 'clean' if File.file?('Makefile')
1282
+ end
1283
+
1284
+ def clean_dir_data(rel)
1285
+ end
1286
+
1287
+ #
1288
+ # TASK distclean
1289
+ #
1290
+
1291
+ def exec_distclean
1292
+ exec_task_traverse 'distclean'
1293
+ rm_f ConfigTable.savefile
1294
+ rm_f 'InstalledFiles'
1295
+ end
1296
+
1297
+ def distclean_dir_bin(rel)
1298
+ end
1299
+
1300
+ def distclean_dir_lib(rel)
1301
+ end
1302
+
1303
+ def distclean_dir_ext(rel)
1304
+ return unless extdir?(curr_srcdir())
1305
+ make 'distclean' if File.file?('Makefile')
1306
+ end
1307
+
1308
+ #
1309
+ # lib
1310
+ #
1311
+
1312
+ def exec_task_traverse(task)
1313
+ run_hook "pre-#{task}"
1314
+ FILETYPES.each do |type|
1315
+ if config('without-ext') == 'yes' and type == 'ext'
1316
+ $stderr.puts 'skipping ext/* by user option' if verbose?
1317
+ next
1318
+ end
1319
+ traverse task, type, "#{task}_dir_#{type}"
1320
+ end
1321
+ run_hook "post-#{task}"
1322
+ end
1323
+
1324
+ def traverse(task, rel, mid)
1325
+ dive_into(rel) {
1326
+ run_hook "pre-#{task}"
1327
+ __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '')
1328
+ all_dirs_in(curr_srcdir()).each do |d|
1329
+ traverse task, "#{rel}/#{d}", mid
1330
+ end
1331
+ run_hook "post-#{task}"
1332
+ }
1333
+ end
1334
+
1335
+ def dive_into(rel)
1336
+ return unless File.dir?("#{@srcdir}/#{rel}")
1337
+
1338
+ dir = File.basename(rel)
1339
+ Dir.mkdir dir unless File.dir?(dir)
1340
+ prevdir = Dir.pwd
1341
+ Dir.chdir dir
1342
+ $stderr.puts '---> ' + rel if verbose?
1343
+ @currdir = rel
1344
+ yield
1345
+ Dir.chdir prevdir
1346
+ $stderr.puts '<--- ' + rel if verbose?
1347
+ @currdir = File.dirname(rel)
1348
+ end
1349
+
1350
+ end
1351
+
1352
+
1353
+ if $0 == __FILE__
1354
+ begin
1355
+ if multipackage_install?
1356
+ ToplevelInstallerMulti.invoke
1357
+ else
1358
+ ToplevelInstaller.invoke
1359
+ end
1360
+ rescue SetupError
1361
+ raise if $DEBUG
1362
+ $stderr.puts $!.message
1363
+ $stderr.puts "Try 'ruby #{$0} --help' for detailed usage."
1364
+ exit 1
1365
+ end
1366
+ end