6
# Copyright (c) 2000,2001 Minero Aoki <aamine@loveruby.net>
6
# Copyright (c) 2000-2003 Minero Aoki <aamine@loveruby.net>
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.
13
unless $".include? 'setup/compat.rb' then
14
$".push 'setup/compat.rb'
17
unless Enumerable.instance_methods.include? 'inject' then
21
result = yield( result, i )
30
unless $".include? 'setup/config.rb' then
31
$".push 'setup/config.rb'
34
if i = ARGV.index(/\A--rbconfig=/) then
13
def multipackage_install?
14
FileTest.directory?(File.dirname($0) + '/packages')
22
methods = instance_methods(true)
24
unless methods.include?('map')
28
unless methods.include?('select')
32
unless methods.include?('reject')
36
result.push i unless yield(i)
42
unless methods.include?('inject')
45
result = yield(result, i)
51
unless methods.include?('any?')
54
return true if yield(i)
66
def mkdir_p( dirname, prefix = nil )
67
dirname = prefix + dirname if prefix
68
$stderr.puts "mkdir -p #{dirname}" if verbose?
71
# does not check '/'... it's too abnormal case
72
dirs = dirname.split(%r<(?=/)>)
73
if /\A[a-z]:\z/i === dirs[0]
75
dirs[0] = disk + dirs[0]
77
dirs.each_index do |idx|
78
path = dirs[0..idx].join('')
79
Dir.mkdir path unless dir?(path)
84
$stderr.puts "rm -f #{fname}" if verbose?
87
if FileTest.exist?(fname) or FileTest.symlink?(fname)
88
File.chmod 0777, fname
94
$stderr.puts "rm -rf #{dn}" if verbose?
98
Dir.foreach('.') do |fn|
115
def move_file( src, dest )
116
File.unlink dest if FileTest.exist?(dest)
118
File.rename src, dest
120
File.open(dest, 'wb') {|f| f.write read_file(src) }
121
File.chmod File.stat(src).mode, dest
126
def install( from, dest, mode, prefix = nil )
127
$stderr.puts "install #{from} #{dest}" if verbose?
130
realdest = prefix + dest if prefix
131
realdest += '/' + File.basename(from) if dir?(realdest)
132
str = read_file(from)
133
if diff?(str, realdest)
135
rm_f realdest if File.exist?(realdest)
137
File.open(realdest, 'wb') {|f| f.write str }
138
File.chmod mode, realdest
140
File.open("#{objdir_root()}/InstalledFiles", 'a') {|f| f.puts realdest }
144
def diff?( orig, targ )
145
return true unless File.exist?(targ)
146
orig != read_file(targ)
150
$stderr.puts str if verbose?
151
system str or raise RuntimeError, "'system #{str}' failed"
155
command config('ruby-prog') + ' ' + str
158
def make( task = '' )
159
command config('make-prog') + ' ' + task
163
File.exist?(dir + '/MANIFEST')
167
# for corrupted windows stat()
168
FileTest.directory?((path[-1,1] == '/') ? path : path + '/')
171
def all_files_in( dirname )
172
Dir.open(dirname) {|d|
173
return d.select {|ent| FileTest.file?("#{dirname}/#{ent}") }
181
def all_dirs_in( dirname )
182
Dir.open(dirname) {|d|
183
return d.select {|n| dir?("#{dirname}/#{n}") } - %w(. ..) - REJECT_DIRS
187
def read_file( fname )
188
File.open(fname, 'rb') {|f| return f.read }
196
if i = ARGV.index(/\A--rbconfig=/)
51
213
teeny = c['TEENY'].to_i
52
214
version = "#{major}.#{minor}"
54
# ruby version >= 3.0.2 ?
216
# ruby ver. >= 1.4.4?
55
217
newpath_p = ((major >= 2) or
58
220
((minor == 4) and (teeny >= 4)))))
60
if c['rubylibdir'] then
62
stdruby = c['rubylibdir'] .sub( c['prefix'], '$prefix' )
63
siteruby = c['sitelibdir'] .sub( c['prefix'], '$prefix' )
64
sodir = c['sitearchdir'].sub( c['prefix'], '$prefix' )
222
re = Regexp.new('\A' + Regexp.quote(c['prefix']))
223
subprefix = lambda {|path|
224
re === path and path.sub(re, '$prefix')
229
stdruby = subprefix.call(c['rubylibdir'])
230
siteruby = subprefix.call(c['sitedir'])
231
versite = subprefix.call(c['sitelibdir'])
232
sodir = subprefix.call(c['sitearchdir'])
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']}"
72
241
stdruby = "$prefix/lib/ruby/#{version}"
73
242
siteruby = "$prefix/lib/ruby/#{version}/site_ruby"
74
244
sodir = "$site-ruby/#{c['arch']}"
247
common_descripters = [
78
248
[ 'prefix', [ c['prefix'],
250
'path prefix of target environment' ] ],
81
251
[ 'std-ruby', [ stdruby,
83
253
'the directory for standard ruby libraries' ] ],
84
[ 'site-ruby', [ siteruby,
254
[ 'site-ruby-common', [ siteruby,
256
'the directory for version-independent non-standard ruby libraries' ] ],
257
[ 'site-ruby', [ versite,
86
259
'the directory for non-standard ruby libraries' ] ],
87
260
[ 'bin-dir', [ '$prefix/bin',
101
274
'path to set to #! line' ] ],
102
275
[ 'ruby-prog', [ rubypath,
104
277
'the ruby program using for installation' ] ],
105
278
[ 'make-prog', [ 'make',
107
280
'the make program to compile ruby extentions' ] ],
110
def self.each_name( &block )
111
keys().each( &block )
115
DESCRIPTER.collect {|k,*dummy| k }
281
[ 'without-ext', [ 'no',
283
'does not compile/install ruby extentions' ] ]
285
multipackage_descripters = [
288
'package names that you want to install',
292
'package names that you do not want to install',
295
if multipackage_install?
296
DESCRIPTER = common_descripters + multipackage_descripters
298
DESCRIPTER = common_descripters
119
301
SAVE_FILE = 'config.save'
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
303
def ConfigTable.each_name( &block )
308
DESCRIPTER.map {|name, *dummy| name }
311
def ConfigTable.each_definition( &block )
312
DESCRIPTER.each(&block)
315
def ConfigTable.get_entry( name )
316
name, ent = DESCRIPTER.assoc(name)
320
def ConfigTable.get_entry!( name )
321
get_entry(name) or raise ArgumentError, "no such config: #{name}"
324
def ConfigTable.add_entry( name, vals )
325
ConfigTable::DESCRIPTER.push [name,vals]
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 }
333
def ConfigTable.config_key?( name )
334
get_entry(name) ? true : false
337
def ConfigTable.bool_config?( name )
338
ent = get_entry(name) or return false
342
def ConfigTable.value_config?( name )
343
ent = get_entry(name) or return false
347
def ConfigTable.path_config?( name )
348
ent = get_entry(name) or return false
359
c.initialize_from_table
365
c.initialize_from_file
369
def initialize_from_table
143
371
DESCRIPTER.each do |k, (default, vname, desc, default2)|
144
372
@table[k] = default
376
def initialize_from_file
377
raise InstallError, "#{File.basename $0} config first"\
378
unless FileTest.file?(SAVE_FILE)
380
File.foreach(SAVE_FILE) do |line|
381
k, v = line.split(/=/, 2)
149
File.open( SAVE_FILE, 'w' ) do |f|
150
@table.each do |k, v|
151
f.printf "%s=%s\n", k, v if v
387
File.open(SAVE_FILE, 'w') {|f|
388
@table.each do |k, v|
389
f.printf "%s=%s\n", k, v if 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)
167
@table[key] and @table[key].sub( %r_\$([^/]+)_ ) { self[$1] }
405
return nil unless @table[key]
406
@table[key].gsub(%r<\$([^/]+)>) { self[$1] }
170
def noproc_set( key, val )
409
def set_raw( key, val )
171
410
@table[key] = val
174
def noproc_get( key )
182
unless $".include? 'setup/fileop.rb' then
183
$".push 'setup/fileop.rb'
186
module FileOperations
194
$stderr.puts "mkdir -p #{dname}" if verbose?
197
# does not check '/'... it's too abnormal case
198
dirs = dname.split(%r_(?=/)_)
199
if /\A[a-z]:\z/i === dirs[0] then
201
dirs[0] = disk + dirs[0]
203
dirs.each_index do |idx|
204
path = dirs[0..idx].join('')
205
Dir.mkdir path unless dir? path
210
$stderr.puts "rm -f #{fname}" if verbose?
213
if File.exist? fname or File.symlink? fname then
214
File.chmod 0777, fname
220
$stderr.puts "rm -rf #{dn}" if verbose?
224
Dir.foreach('.') do |fn|
246
File.open( dest, 'wb' ) {|w|
247
File.open(src, 'rb') {|r| w.write r.read }
249
File.chmod File.stat(src).mode, dest
254
def install( from, to, mode )
255
$stderr.puts "install #{from} #{to}" if verbose?
259
to = to + '/' + File.basename(from)
262
File.open( from, 'rb' ) {|f| str = f.read }
263
if diff? str, to then
265
rm_f to if File.exist? to
267
File.open( to, 'wb' ) {|f| f.write str }
270
File.open( objdir + '/InstalledFiles', 'a' ) {|f| f.puts to }
274
def diff?( orig, comp )
275
return true unless File.exist? comp
277
File.open( comp, 'rb' ) {|f| s2 = f.read }
282
$stderr.puts str if verbose?
283
system str or raise RuntimeError, "'system #{str}' failed"
287
command config('ruby-prog') + ' ' + str
291
# for corrupted windows stat()
292
File.directory?( (dname[-1,1] == '/') ? dname : dname + '/' )
295
def all_files( dname )
296
Dir.open( dname ) {|d|
297
return d.find_all {|n| File.file? "#{dname}/#{n}" }
301
def all_dirs( dname )
302
Dir.open( dname ) {|d|
303
return d.find_all {|n| dir? "#{dname}/#{n}" } - %w(. ..)
311
unless $".include? 'setup/base.rb' then
312
$".push 'setup/base.rb'
422
def eval_file_ifexist( fname )
423
instance_eval read_file(fname), fname, 1 if FileTest.file?(fname)
431
ConfigTable.config_key?(name)
434
def bool_config?( name )
435
ConfigTable.bool_config?(name)
438
def value_config?( name )
439
ConfigTable.value_config?(name)
442
def path_config?( name )
443
ConfigTable.path_config?(name)
446
def add_config( name, argname, default, desc )
447
ConfigTable.add_entry name,[default,argname,desc]
450
def add_path_config( name, default, desc )
451
add_config name, 'path', default, desc
454
def add_bool_config( name, default, desc )
455
add_config name, 'yes/no', default ? 'yes' : 'no', desc
458
def set_config_default( name, default )
459
if bool_config?(name)
460
ConfigTable.get_entry!(name)[0] = (default ? 'yes' : 'no')
462
ConfigTable.get_entry!(name)[0] = default
466
def remove_config( name )
467
ent = ConfigTable.get_entry(name)
468
ConfigTable.remove_entry name
315
480
class InstallError < StandardError; end
321
Copyright = 'Copyright (c) 2000,2001 Minero Aoki'
326
def self.declear_toplevel_installer( inst )
328
raise ArgumentError, 'more than one toplevel installer decleared'
332
def self.toplevel_installer
337
FILETYPES = %w( bin lib ext data )
339
include FileOperations
341
def initialize( config, opt, srcroot, objroot )
344
@srcdir = File.expand_path(srcroot)
345
@objdir = File.expand_path(objroot)
350
"#<#{type} #{__id__}>"
486
try_run_hook "#{curr_srcdir()}/#{name}" or
487
try_run_hook "#{curr_srcdir()}/#{name}.rb"
490
def try_run_hook( fname )
491
return false unless FileTest.file?(fname)
493
instance_eval read_file(fname), fname, 1
495
raise InstallError, "hook #{fname} failed:\n" + $!.message
505
def get_config( key )
370
save, @options['verbose'] = @options['verbose'], false
372
@options['verbose'] = save
380
alias srcdir_root srcdir
381
alias package_root srcdir
509
alias config get_config
511
def set_config( key, val )
516
# srcdir/objdir (works only in the package directory)
519
#abstract srcdir_root
520
#abstract objdir_root
384
"#{@srcdir}/#{@currdir}"
524
"#{srcdir_root()}/#{relpath()}"
388
alias objdir_root objdir
391
"#{@objdir}/#{@currdir}"
528
"#{objdir_root()}/#{relpath()}"
394
531
def srcfile( path )
395
curr_srcdir + '/' + path
532
"#{curr_srcdir()}/#{path}"
398
535
def srcexist?( path )
399
File.exist? srcfile(path)
536
FileTest.exist? srcfile(path)
402
539
def srcdirectory?( path )
406
543
def srcfile?( path )
407
File.file? srcfile(path)
544
FileTest.file? srcfile(path)
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(. ..)
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))
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))
429
return unless dir? "#{@srcdir}/#{rel}"
431
dir = File.basename(rel)
432
Dir.mkdir dir unless dir? dir
435
$stderr.puts '---> ' + rel if verbose?
439
$stderr.puts '<--- ' + rel if verbose?
440
@currdir = File.dirname(rel)
570
FILETYPES = %w( bin lib ext data )
572
include HookScriptAPI
574
include FileOperations
576
def initialize( config, opt, srcroot, objroot )
579
@srcdir = File.expand_path(srcroot)
580
@objdir = File.expand_path(objroot)
585
"#<#{self.class} #{File.basename(@srcdir)}>"
589
# Hook Script API bases
618
save, @options['verbose'] = @options['verbose'], false
621
@options['verbose'] = save
457
639
def config_dir_ext( rel )
458
extconf if extdir? curr_srcdir
640
extconf if extdir?(curr_srcdir())
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}"
466
648
def config_dir_data( rel )
474
656
exec_task_traverse 'setup'
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}"
665
# modify: #!/usr/bin/ruby
666
# modify: #! /usr/bin/ruby
668
# not modify: #!/usr/bin/env ruby
483
669
SHEBANG_RE = /\A\#!\s*\S*ruby\S*/
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?
489
674
tmpfile = File.basename(path) + '.tmp'
491
File.open( path ) {|r|
492
File.open( tmpfile, 'w' ) {|w|
494
return unless SHEBANG_RE === first # reject '/usr/bin/env ruby'
677
File.open(tmpfile, 'w') {|w|
679
return unless SHEBANG_RE === first
496
w.print first.sub( SHEBANG_RE, '#!' + config('ruby-path') )
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'))
686
move_file tmpfile, File.basename(path)
501
rm_f tmpfile if File.exist? tmpfile
505
def setup_dir_lib( relpath )
508
def setup_dir_ext( relpath )
509
if extdir? curr_srcdir then
515
command config('make-prog')
518
def setup_dir_data( relpath )
688
File.unlink tmpfile if File.exist?(tmpfile)
692
def setup_dir_lib( rel )
695
def setup_dir_ext( rel )
696
make if extdir?(curr_srcdir())
699
def setup_dir_data( rel )
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
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
537
718
def install_dir_ext( rel )
538
if extdir? curr_srcdir then
539
install_dir_ext_main File.dirname(rel)
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),
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
551
729
def install_files( list, dest, mode )
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']
737
collect_filenames_auto().select {|n| /\.rb\z/ === n }
559
(targfilenames - hookfilenames).collect {|fname|
560
File.exist?(fname) ? fname : File.join(curr_srcdir, fname)
565
[ curr_srcdir, '.' ].inject([]) {|ret, dir|
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 _$* *$
753
REJECT_PATTERNS = Regexp.new('\A(?:' +
754
reject_patterns.map {|pat|
755
pat.gsub(/[\.\$\*]/) {|s| maptab[s] }
759
def collect_filenames_auto
760
mapdir((existfiles() - hookfiles()).reject {|fname|
761
REJECT_PATTERNS === fname
766
all_files_in(curr_srcdir()) | all_files_in('.')
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) }
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
780
File.join(curr_srcdir(), fname)
785
def ruby_extentions( dir )
786
_ruby_extentions(dir) or
787
raise InstallError, "no ruby extention exists: 'ruby #{$0} setup' first"
581
790
DLEXT = /\.#{ ::Config::CONFIG['DLEXT'] }\z/
585
return d.find_all {|fname| DLEXT === fname }
792
def _ruby_extentions( dir )
794
return d.select {|fname| DLEXT === fname }
605
814
def clean_dir_ext( rel )
610
command config('make-prog') + ' clean' if File.file? 'Makefile'
815
return unless extdir?(curr_srcdir())
816
make 'clean' if FileTest.file?('Makefile')
613
819
def clean_dir_data( rel )
827
exec_task_traverse 'distclean'
829
rm_f 'InstalledFiles'
832
def distclean_dir_bin( rel )
835
def distclean_dir_lib( rel )
838
def distclean_dir_ext( rel )
839
return unless extdir?(curr_srcdir())
840
make 'distclean' if FileTest.file?('Makefile')
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?
623
854
traverse task, type, task + '_dir_' + type
625
856
run_hook 'post-' + task
628
859
def traverse( task, rel, mid )
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
635
866
run_hook 'post-' + task
640
try_run_hook curr_srcdir + '/' + name or
641
try_run_hook curr_srcdir + '/' + name + '.rb'
644
def try_run_hook( fname )
645
return false unless File.file? fname
649
File.open( fname ) {|f| s = f.read }
651
env.instance_eval s, fname, 1
653
raise InstallError, "hook #{fname} failed:\n" + $!.message
659
File.exist? dir + '/MANIFEST'
666
unless $".include? 'setup/toplevel.rb' then
667
$".push 'setup/toplevel.rb'
668
### begin toplevel.rb
670
class ToplevelInstaller < Installer
871
return unless dir?("#{@srcdir}/#{rel}")
873
dir = File.basename(rel)
874
Dir.mkdir dir unless dir?(dir)
877
$stderr.puts '---> ' + rel if verbose?
881
$stderr.puts '<--- ' + rel if verbose?
882
@currdir = File.dirname(rel)
890
class ToplevelInstaller
893
Copyright = 'Copyright (c) 2000-2003 Minero Aoki'
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" ]
681
def initialize( argv, root )
683
super nil, {'verbose' => true}, root, '.'
685
Installer.declear_toplevel_installer self
692
task = parsearg_global( argv )
904
def ToplevelInstaller.invoke
910
def ToplevelInstaller.instance
911
@singleton ||= new(File.dirname($0))
915
include MetaConfigAPI
917
def initialize( ardir_root )
919
@options = { 'verbose' => true }
920
@ardir = File.expand_path(ardir_root)
924
"#<#{self.class} #{__id__()}>"
929
task = parsearg_global()
930
@config = load_config(task)
931
__send__ "parsearg_#{task}"
933
__send__ "exec_#{task}"
937
eval_file_ifexist "#{@ardir}/metaconfig"
940
def load_config( task )
696
@config = ConfigTable.create
698
@config = ConfigTable.load
700
parsearg_TASK task, argv
706
if task == 'show' then
714
$stderr.printf "#{File.basename $0}: entering %s phase...\n", task if verbose?
716
__send__ 'exec_' + task
718
$stderr.printf "%s failed\n", task
721
$stderr.printf "#{File.basename $0}: %s done.\n", task if verbose?
725
# processing arguments
728
def parsearg_global( argv )
729
task_re = /\A(?:#{TASKS.collect {|i| i[0] }.join '|'})\z/
731
while arg = argv.shift do
944
when 'clean', 'distclean'
945
if File.exist?('config.save')
946
then ConfigTable.load
955
@installer = Installer.new(@config, @options, @ardir, File.expand_path('.'))
959
# Hook Script API bases
979
valid_task = /\A(?:#{TASKS.map {|task,desc| task }.join '|'})\z/
981
while arg = ARGV.shift
734
task_re === arg or raise InstallError, "wrong task: #{arg}"
984
raise InstallError, "invalid task: #{arg}" unless valid_task === arg
737
987
when '-q', '--quiet'
747
997
when '-v', '--version'
748
puts "#{File.basename $0} version #{Version}"
998
puts "#{File.basename($0)} version #{Version}"
751
1001
when '--copyright'
756
raise InstallError, 'no task given'
759
1006
raise InstallError, "unknown global option '#{arg}'"
765
def parsearg_TASK( task, argv )
766
mid = "parsearg_#{task}"
767
if respond_to? mid, true then
771
raise InstallError, "#{task}: unknown options: #{argv.join ' '}"
775
def parsearg_config( args )
776
re = /\A--(#{ConfigTable.keys.join '|'})=/
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)
1020
def parsearg_no_options
1021
raise InstallError, "#{task}: unknown options: #{ARGV.join ' '}"\
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
1031
re = /\A--(#{ConfigTable.keys.join '|'})(?:=(.*))?\z/
777
1032
@options['config-opt'] = []
779
while i = args.shift do
780
if /\A--?\z/ === i then
781
@options['config-opt'] = args
1034
while i = ARGV.shift
1036
@options['config-opt'] = ARGV.dup
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]
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'
1048
raise InstallError, "config: --#{name} requires argument"\
1049
unless ConfigTable.bool_config?(name)
1052
@config[name] = value
789
def parsearg_install( args )
1056
def parsearg_install
790
1057
@options['no-harm'] = false
792
if i == '--no-harm' then
1058
@options['install-prefix'] = ''
1059
while a = ARGV.shift
1061
when /\A--no-harm\z/
793
1062
@options['no-harm'] = true
1063
when /\A--prefix=(.*)\z/
1065
path = File.expand_path(path) unless path[0,1] == '/'
1066
@options['install-prefix'] = path
795
raise InstallError, "install: unknown option #{i}"
1068
raise InstallError, "install: unknown option #{a}"
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)"
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>]"
807
1083
fmt = " %-20s %s\n"
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'
1125
@installer.exec_config
1129
@installer.exec_setup
1133
@installer.exec_install
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)'
858
1142
printf "%-10s %s\n", k, v
866
unless $".include? 'setup/package.rb' then
867
$".push 'setup/package.rb'
870
ConfigTable::DESCRIPTER.concat [
874
'package names that you want to install',
878
'package names that you do not want to install',
883
class PackageManager < ToplevelInstaller
1147
@installer.exec_clean
1151
@installer.exec_distclean
1157
class ToplevelInstallerMulti < ToplevelInstaller
1160
include HookScriptAPI
1161
include FileOperations
1163
def initialize( ardir )
1165
@packages = all_dirs_in("#{@ardir}/packages")
1166
raise 'no package exists' if @packages.empty?
1170
eval_file_ifexist "#{@ardir}/metaconfig"
1171
@packages.each do |name|
1172
eval_file_ifexist "#{@ardir}/packages/#{name}/metaconfig"
1178
@packages.each do |pack|
1179
@installers[pack] = Installer.new(@config, @options,
1180
"#{@ardir}/packages/#{pack}",
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)
1192
def extract_selection( list )
1195
raise InstallError, "no such package: #{name}" \
1196
unless @installers.key?(name)
885
1201
def print_usage( f )
887
1203
f.puts 'Inluded packages:'
888
f.puts ' ' + packages.sort.join(' ')
1204
f.puts ' ' + @packages.sort.join(' ')
1209
# multi-package metaconfig API
1212
attr_reader :packages
1214
def declare_packages( list )
1215
raise 'package list is empty' if list.empty?
1217
raise "directory packages/#{name} does not exist"\
1218
unless dir?("#{@ardir}/packages/#{name}")
1228
run_hook 'pre-config'
903
1230
each_selected_installers {|inst| inst.exec_config }
1231
run_hook 'post-config'
1235
run_hook 'pre-setup'
908
1236
each_selected_installers {|inst| inst.exec_setup }
1237
run_hook 'post-setup'
911
1240
def exec_install
1241
run_hook 'pre-install'
912
1242
each_selected_installers {|inst| inst.exec_install }
1243
run_hook 'post-install'
1248
run_hook 'pre-clean'
916
1249
each_selected_installers {|inst| inst.exec_clean }
924
packs = all_dirs(srcdir + '/packages')
925
packs.empty? and raise InstallError, 'no package available'
931
packages.each do |dir|
932
@installers[dir] = Installer.new( @config, @options,
933
srcdir + '/packages/' + dir,
939
with = extract_sel( config('with') )
940
without = extract_sel( config('without') )
942
@selected = @installers.keys.find_all {|name|
943
(with.empty? or with.include? name) and
944
not without.include? name
948
def extract_sel( list )
951
@installers.key? name or raise InstallError, "no such package: #{name}"
1250
run_hook 'post-clean'
1255
run_hook 'pre-distclean'
1256
each_selected_installers {|inst| inst.exec_distclean }
1257
run_hook 'post-distclean'
956
1264
def each_selected_installers
957
dive_into( 'packages' ) {
958
@selected.each do |name|
959
dive_into( 'packages/' + name ) {
960
yield @installers[name]
968
with = extract_dirs( config('with') )
969
without = extract_dirs( config('without') )
972
[ [with, with_pack = [], with_dir = []],
973
[without, without_pack = [], without_dir = []] ].each do |orig, pack, dir|
975
if packs.include? i then pack.push i
976
elsif dir? i then dir.push i
978
raise InstallError, "no such package or directory '#{i}'"
983
@installers.delete_if {|name, inst|
984
not is_included? name, with_pack, without_pack \
986
inst.descripter.keys.delete_if {|d|
987
not is_included? d, with_dir, without_dir }.empty?
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 }
993
inst.descripter.delete_if {|k,v| not with_dir.include? k }
998
def extract_dirs( s )
1000
s.split(',').each do |i|
1001
if /[\*\?]/ === i then
1003
tmp.delete_if {|d| not dir? d }
1005
tmp.push i # causes error
1017
def is_included?( name, with, without )
1019
not without.include? name
1025
def install_dir?( dir )
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]
1037
installer = PackageManager.new( ARGV.dup, File.dirname($0) )
1287
if multipackage_install?
1288
ToplevelInstallerMulti.invoke
1290
ToplevelInstaller.invoke
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."