reap 6.0.0 → 6.0.1

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