~ubuntu-branches/ubuntu/intrepid/racc/intrepid

« back to all changes in this revision

Viewing changes to setup.rb

  • Committer: Bazaar Package Importer
  • Author(s): akira yamada
  • Date: 2005-04-09 17:54:44 UTC
  • mfrom: (1.2.1 upstream) (2.1.1 warty)
  • Revision ID: james.westby@ubuntu.com-20050409175444-fvtir838ypkn7a58
Tags: 1.4.4-1
* new upstream version.  (closes: #301768)
* added racc2y.1 and y2racc.1.
* modified racc2y and y2racc to use optparse instead of deprecated getopts.

Show diffs side-by-side

added added

removed removed

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