~ubuntu-branches/ubuntu/wily/tdiary/wily

« back to all changes in this revision

Viewing changes to vendor/rdtool-0.6.33/setup.rb

  • Committer: Package Import Robot
  • Author(s): Hideki Yamane
  • Date: 2013-05-19 16:14:01 UTC
  • mfrom: (12.1.1 experimental)
  • Revision ID: package-import@ubuntu.com-20130519161401-hf5oyr8g8a94fsew
Tags: 3.2.2-2
Upload to unstable 

Show diffs side-by-side

added added

removed removed

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