5 # Copyright (c) 2000-2005 Minero Aoki
7 # This program is free software.
8 # You can distribute/modify this program under the terms of
9 # the GNU LGPL, Lesser General Public License version 2.1.
12 unless Enumerable.method_defined?(:map) # Ruby 1.4.6
18 unless File.respond_to?(:read) # Ruby 1.6
26 unless Errno.const_defined?(:ENOTEMPTY) # Windows?
29 # We do not raise this exception, implementation is not needed.
34 def File.binread(fname)
35 open(fname, 'rb') {|f|
40 # for corrupted Windows' stat(2)
42 File.directory?((path[-1,1] == '/') ? path : path + '/')
50 def initialize(rbconfig)
61 attr_accessor :install_prefix
62 attr_accessor :config_opt
77 lookup(key).resolve(self)
85 @items.map {|i| i.name }
97 @table[name] or setup_rb_error "no such config item: #{name}"
102 @table[item.name] = item
107 @items.delete_if {|i| i.name == name }
108 @table.delete_if {|name, i| i.name == name }
112 def load_script(path, inst = nil)
114 MetaConfigEnvironment.new(self, inst).instance_eval File.read(path), path
124 File.foreach(savefile()) do |line|
125 k, v = *line.split(/=/, 2)
129 setup_rb_error $!.message + "\n#{File.basename($0)} config first"
134 @items.each {|i| i.value }
135 File.open(savefile(), 'w') {|f|
137 f.printf "%s=%s\n", i.name, i.value if i.value? and i.value
142 def load_standard_entries
143 standard_entries(@rbconfig).each do |ent|
148 def standard_entries(rbconfig)
151 rubypath = File.join(c['bindir'], c['ruby_install_name'] + c['EXEEXT'])
153 major = c['MAJOR'].to_i
154 minor = c['MINOR'].to_i
155 teeny = c['TEENY'].to_i
156 version = "#{major}.#{minor}"
158 # ruby ver. >= 1.4.4?
159 newpath_p = ((major >= 2) or
162 ((minor == 4) and (teeny >= 4)))))
166 libruby = "#{c['prefix']}/lib/ruby"
167 librubyver = c['rubylibdir']
168 librubyverarch = c['archdir']
169 siteruby = c['sitedir']
170 siterubyver = c['sitelibdir']
171 siterubyverarch = c['sitearchdir']
173 # 1.4.4 <= V <= 1.6.3
174 libruby = "#{c['prefix']}/lib/ruby"
175 librubyver = "#{c['prefix']}/lib/ruby/#{version}"
176 librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}"
177 siteruby = c['sitedir']
178 siterubyver = "$siteruby/#{version}"
179 siterubyverarch = "$siterubyver/#{c['arch']}"
182 libruby = "#{c['prefix']}/lib/ruby"
183 librubyver = "#{c['prefix']}/lib/ruby/#{version}"
184 librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}"
185 siteruby = "#{c['prefix']}/lib/ruby/#{version}/site_ruby"
186 siterubyver = siteruby
187 siterubyverarch = "$siterubyver/#{c['arch']}"
189 parameterize = lambda {|path|
190 path.sub(/\A#{Regexp.quote(c['prefix'])}/, '$prefix')
193 if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg }
194 makeprog = arg.sub(/'/, '').split(/=/, 2)[1]
200 ExecItem.new('installdirs', 'std/site/home',
201 'std: install under libruby; site: install under site_ruby; home: install under $HOME')\
205 table['rbdir'] = '$librubyver'
206 table['sodir'] = '$librubyverarch'
208 table['rbdir'] = '$siterubyver'
209 table['sodir'] = '$siterubyverarch'
211 setup_rb_error '$HOME was not set' unless ENV['HOME']
212 table['prefix'] = ENV['HOME']
213 table['rbdir'] = '$libdir/ruby'
214 table['sodir'] = '$libdir/ruby'
217 PathItem.new('prefix', 'path', c['prefix'],
218 'path prefix of target environment'),
219 PathItem.new('bindir', 'path', parameterize.call(c['bindir']),
220 'the directory for commands'),
221 PathItem.new('libdir', 'path', parameterize.call(c['libdir']),
222 'the directory for libraries'),
223 PathItem.new('datadir', 'path', parameterize.call(c['datadir']),
224 'the directory for shared data'),
225 PathItem.new('mandir', 'path', parameterize.call(c['mandir']),
226 'the directory for man pages'),
227 PathItem.new('sysconfdir', 'path', parameterize.call(c['sysconfdir']),
228 'the directory for system configuration files'),
229 PathItem.new('localstatedir', 'path', parameterize.call(c['localstatedir']),
230 'the directory for local state data'),
231 PathItem.new('libruby', 'path', libruby,
232 'the directory for ruby libraries'),
233 PathItem.new('librubyver', 'path', librubyver,
234 'the directory for standard ruby libraries'),
235 PathItem.new('librubyverarch', 'path', librubyverarch,
236 'the directory for standard ruby extensions'),
237 PathItem.new('siteruby', 'path', siteruby,
238 'the directory for version-independent aux ruby libraries'),
239 PathItem.new('siterubyver', 'path', siterubyver,
240 'the directory for aux ruby libraries'),
241 PathItem.new('siterubyverarch', 'path', siterubyverarch,
242 'the directory for aux ruby binaries'),
243 PathItem.new('rbdir', 'path', '$siterubyver',
244 'the directory for ruby scripts'),
245 PathItem.new('sodir', 'path', '$siterubyverarch',
246 'the directory for ruby extentions'),
247 PathItem.new('rubypath', 'path', rubypath,
248 'the path to set to #! line'),
249 ProgramItem.new('rubyprog', 'name', rubypath,
250 'the ruby program using for installation'),
251 ProgramItem.new('makeprog', 'name', makeprog,
252 'the make program to compile ruby extentions'),
253 SelectItem.new('shebang', 'all/ruby/never', 'ruby',
254 'shebang line (#!) editing mode'),
255 BoolItem.new('without-ext', 'yes/no', 'no',
256 'does not compile/install ruby extentions')
259 private :standard_entries
261 def load_multipackage_entries
262 multipackage_entries().each do |ent|
267 def multipackage_entries
269 PackageSelectionItem.new('with', 'name,name...', '', 'ALL',
270 'package names that you want to install'),
271 PackageSelectionItem.new('without', 'name,name...', '', 'NONE',
272 'package names that you do not want to install')
275 private :multipackage_entries
278 'std-ruby' => 'librubyver',
279 'stdruby' => 'librubyver',
280 'rubylibdir' => 'librubyver',
281 'archdir' => 'librubyverarch',
282 'site-ruby-common' => 'siteruby', # For backward compatibility
283 'site-ruby' => 'siterubyver', # For backward compatibility
284 'bin-dir' => 'bindir',
285 'bin-dir' => 'bindir',
288 'data-dir' => 'datadir',
289 'ruby-path' => 'rubypath',
290 'ruby-prog' => 'rubyprog',
291 'ruby' => 'rubyprog',
292 'make-prog' => 'makeprog',
297 ALIASES.each do |ali, name|
298 @table[ali] = @table[name]
302 @options_re = /\A--(#{@table.keys.join('|')})(?:=(.*))?\z/
306 m = @options_re.match(opt) or setup_rb_error "config: unknown option #{opt}"
314 def value_config?(name)
319 def initialize(name, template, default, desc)
328 attr_reader :description
330 attr_accessor :default
331 alias help_default default
334 "--#{@name}=#{@template}"
346 @value.gsub(%r<\$([^/]+)>) { table[$1] }
356 setup_rb_error "config: --#{name} requires argument" unless val
361 class BoolItem < Item
373 return 'yes' unless 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'
378 setup_rb_error "config: --#{@name} accepts only yes/no for argument"
383 class PathItem < Item
391 setup_rb_error "config: --#{@name} requires argument" unless path
392 path[0,1] == '$' ? path : File.expand_path(path)
396 class ProgramItem < Item
402 class SelectItem < Item
403 def initialize(name, selection, default, desc)
405 @ok = selection.split('/')
415 unless @ok.include?(val.strip)
416 setup_rb_error "config: use --#{@name}=#{@template} (#{val})"
422 class ExecItem < Item
423 def initialize(name, selection, desc, &block)
424 super name, selection, nil, desc
425 @ok = selection.split('/')
438 setup_rb_error "$#{name()} wrongly used as option value"
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})"
448 @action.call v, table
452 class PackageSelectionItem < Item
453 def initialize(name, template, default, help_default, desc)
454 super name, template, default, desc
455 @help_default = help_default
458 attr_reader :help_default
467 unless File.dir?("packages/#{val}")
468 setup_rb_error "config: no such package: #{val}"
474 class MetaConfigEnvironment
475 def initialize(config, installer)
477 @installer = installer
488 def bool_config?(name)
489 @config.lookup(name).config_type == 'bool'
492 def path_config?(name)
493 @config.lookup(name).config_type == 'path'
496 def value_config?(name)
497 @config.lookup(name).config_type != 'exec'
504 def add_bool_config(name, default, desc)
505 @config.add BoolItem.new(name, 'yes/no', default ? 'yes' : 'no', desc)
508 def add_path_config(name, default, desc)
509 @config.add PathItem.new(name, 'path', default, desc)
512 def set_config_default(name, default)
513 @config.lookup(name).default = default
516 def remove_config(name)
520 # For only multipackage
522 raise '[setup.rb fatal] multi-package metaconfig API packages() called for single-package; contact application package vendor' unless @installer
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
533 end # class ConfigTable
536 # This module requires: #verbose?, #no_harm?
537 module FileOperations
539 def mkdir_p(dirname, prefix = nil)
540 dirname = prefix + File.expand_path(dirname) if prefix
541 $stderr.puts "mkdir -p #{dirname}" if verbose?
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]
548 dirs[0] = disk + dirs[0]
550 dirs.each_index do |idx|
551 path = dirs[0..idx].join('')
552 Dir.mkdir path unless File.dir?(path)
557 $stderr.puts "rm -f #{path}" if verbose?
559 force_remove_file path
563 $stderr.puts "rm -rf #{path}" if verbose?
568 def remove_tree(path)
569 if File.symlink?(path)
571 elsif File.dir?(path)
574 force_remove_file path
578 def remove_tree0(path)
579 Dir.foreach(path) do |ent|
582 entpath = "#{path}/#{ent}"
583 if File.symlink?(entpath)
585 elsif File.dir?(entpath)
588 force_remove_file entpath
593 rescue Errno::ENOTEMPTY
594 # directory may not be empty
598 def move_file(src, dest)
599 force_remove_file dest
601 File.rename src, dest
603 File.open(dest, 'wb') {|f|
604 f.write File.binread(src)
606 File.chmod File.stat(src).mode, dest
611 def force_remove_file(path)
618 def remove_file(path)
619 File.chmod 0777, path
623 def install(from, dest, mode, prefix = nil)
624 $stderr.puts "install #{from} #{dest}" if verbose?
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)
632 rm_f realdest if File.exist?(realdest)
634 File.open(realdest, 'wb') {|f|
637 File.chmod mode, realdest
639 File.open("#{objdir_root()}/InstalledFiles", 'a') {|f|
641 f.puts realdest.sub(prefix, '')
649 def diff?(new_content, path)
650 return true unless File.exist?(path)
651 new_content != File.binread(path)
655 $stderr.puts args.join(' ') if verbose?
656 system(*args) or raise RuntimeError,
657 "system(#{args.map{|a| a.inspect }.join(' ')}) failed"
661 command config('rubyprog'), *args
665 command(*[config('makeprog'), task].compact)
669 File.exist?("#{dir}/MANIFEST") or File.exist?("#{dir}/extconf.rb")
674 return d.select {|ent| File.file?("#{dir}/#{ent}") }
678 DIR_REJECT = %w( . .. CVS SCCS RCS CVS.adm .svn )
680 def directories_of(dir)
682 return d.select {|ent| File.dir?("#{dir}/#{ent}") } - DIR_REJECT
689 # This module requires: #srcdir_root, #objdir_root, #relpath
696 alias config get_config
698 # obsolete: use metaconfig to change configuration
699 def set_config(key, val)
704 # srcdir/objdir (works only in the package directory)
708 "#{srcdir_root()}/#{relpath()}"
712 "#{objdir_root()}/#{relpath()}"
716 "#{curr_srcdir()}/#{path}"
720 File.exist?(srcfile(path))
723 def srcdirectory?(path)
724 File.dir?(srcfile(path))
728 File.file?(srcfile(path))
731 def srcentries(path = '.')
732 Dir.open("#{curr_srcdir()}/#{path}") {|d|
733 return d.to_a - %w(. ..)
737 def srcfiles(path = '.')
738 srcentries(path).select {|fname|
739 File.file?(File.join(curr_srcdir(), path, fname))
743 def srcdirectories(path = '.')
744 srcentries(path).select {|fname|
745 File.dir?(File.join(curr_srcdir(), path, fname))
752 class ToplevelInstaller
755 Copyright = 'Copyright (c) 2000-2005 Minero Aoki'
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" ]
768 def ToplevelInstaller.invoke
769 config = ConfigTable.new(load_rbconfig())
770 config.load_standard_entries
771 config.load_multipackage_entries if multipackage?
773 klass = (multipackage?() ? ToplevelInstallerMulti : ToplevelInstaller)
774 klass.new(File.dirname($0), config).invoke
777 def ToplevelInstaller.multipackage?
778 File.dir?(File.dirname($0) + '/packages')
781 def ToplevelInstaller.load_rbconfig
782 if arg = ARGV.detect {|arg| /\A--rbconfig=/ =~ arg }
784 load File.expand_path(arg.split(/=/, 2)[1])
785 $".push 'rbconfig.rb'
792 def initialize(ardir_root, config)
793 @ardir = File.expand_path(ardir_root)
804 "#<#{self.class} #{__id__()}>"
809 case task = parsearg_global()
818 when 'config', 'test'
820 when 'clean', 'distclean'
821 @config.load_savefile if File.exist?(@config.savefile)
823 @config.load_savefile
825 __send__ "parsearg_#{task}"
827 __send__ "exec_#{task}"
832 @config.load_script "#{@ardir}/metaconfig"
836 @installer = Installer.new(@config, @ardir, File.expand_path('.'))
840 # Hook Script API bases
860 while arg = ARGV.shift
863 setup_rb_error "invalid task: #{arg}" unless valid_task?(arg)
866 @config.verbose = false
868 @config.verbose = true
873 puts "#{File.basename($0)} version #{Version}"
879 setup_rb_error "unknown global option '#{arg}'"
890 @valid_task_re ||= /\A(?:#{TASKS.map {|task,desc| task }.join('|')})\z/
893 def parsearg_no_options
895 task = caller(0).first.slice(%r<`parsearg_(\w+)'>, 1)
896 setup_rb_error "#{task}: unknown options: #{ARGV.join(' ')}"
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
909 @config.config_opt = []
912 @config.config_opt = ARGV.dup
915 name, value = *@config.parse_opt(i)
916 if @config.value_config?(name)
917 @config[name] = value
919 evalopt.push [name, value]
923 evalopt.each do |name, value|
924 @config.lookup(name).evaluate value, @config
926 # Check if configuration is valid
928 @config[n] if @config.value_config?(n)
933 @config.no_harm = false
934 @config.install_prefix = ''
938 @config.no_harm = true
940 path = a.split(/=/, 2)[1]
941 path = File.expand_path(path) unless path[0,1] == '/'
942 @config.install_prefix = path
944 setup_rb_error "install: unknown option #{a}"
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)"
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>]"
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'
969 TASKS.each do |name, desc|
970 out.printf fmt, name, desc
973 fmt = " %-24s %s [%s]\n"
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
979 out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',"running ruby's"
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', ''
992 @installer.exec_config
993 @config.save # must be final
997 @installer.exec_setup
1001 @installer.exec_install
1005 @installer.exec_test
1010 printf "%-20s %s\n", i.name, i.value if i.value?
1015 @installer.exec_clean
1019 @installer.exec_distclean
1022 end # class ToplevelInstaller
1025 class ToplevelInstallerMulti < ToplevelInstaller
1027 include FileOperations
1029 def initialize(ardir_root, config)
1031 @packages = directories_of("#{@ardir}/packages")
1032 raise 'no package exists' if @packages.empty?
1033 @root_installer = Installer.new(@config, @ardir, File.expand_path('.'))
1037 @config.load_script "#{@ardir}/metaconfig", self
1038 @packages.each do |name|
1039 @config.load_script "#{@ardir}/packages/#{name}/metaconfig"
1043 attr_reader :packages
1046 raise 'package list is empty' if list.empty?
1048 raise "directory packages/#{name} does not exist"\
1049 unless File.dir?("#{@ardir}/packages/#{name}")
1056 @packages.each do |pack|
1057 @installers[pack] = Installer.new(@config,
1058 "#{@ardir}/packages/#{pack}",
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)
1069 def extract_selection(list)
1072 setup_rb_error "no such package: #{name}" unless @installers.key?(name)
1079 f.puts 'Inluded packages:'
1080 f.puts ' ' + @packages.sort.join(' ')
1089 run_hook 'pre-config'
1090 each_selected_installers {|inst| inst.exec_config }
1091 run_hook 'post-config'
1092 @config.save # must be final
1096 run_hook 'pre-setup'
1097 each_selected_installers {|inst| inst.exec_setup }
1098 run_hook 'post-setup'
1102 run_hook 'pre-install'
1103 each_selected_installers {|inst| inst.exec_install }
1104 run_hook 'post-install'
1109 each_selected_installers {|inst| inst.exec_test }
1110 run_hook 'post-test'
1114 rm_f @config.savefile
1115 run_hook 'pre-clean'
1116 each_selected_installers {|inst| inst.exec_clean }
1117 run_hook 'post-clean'
1121 rm_f @config.savefile
1122 run_hook 'pre-distclean'
1123 each_selected_installers {|inst| inst.exec_distclean }
1124 run_hook 'post-distclean'
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]
1143 @root_installer.run_hook id
1146 # module FileOperations requires this
1151 # module FileOperations requires this
1156 end # class ToplevelInstallerMulti
1161 FILETYPES = %w( bin lib ext data conf man )
1163 include FileOperations
1164 include HookScriptAPI
1166 def initialize(config, srcroot, objroot)
1168 @srcdir = File.expand_path(srcroot)
1169 @objdir = File.expand_path(objroot)
1174 "#<#{self.class} #{File.basename(@srcdir)}>"
1181 # Hook Script API base methods
1200 # module FileOperations requires this
1205 # module FileOperations requires this
1212 save, @config.verbose = @config.verbose?, false
1215 @config.verbose = save
1224 exec_task_traverse 'config'
1227 alias config_dir_bin noop
1228 alias config_dir_lib noop
1230 def config_dir_ext(rel)
1231 extconf if extdir?(curr_srcdir())
1234 alias config_dir_data noop
1235 alias config_dir_conf noop
1236 alias config_dir_man noop
1239 ruby "#{curr_srcdir()}/extconf.rb", *@config.config_opt
1247 exec_task_traverse 'setup'
1250 def setup_dir_bin(rel)
1251 files_of(curr_srcdir()).each do |fname|
1252 update_shebang_line "#{curr_srcdir()}/#{fname}"
1256 alias setup_dir_lib noop
1258 def setup_dir_ext(rel)
1259 make if extdir?(curr_srcdir())
1262 alias setup_dir_data noop
1263 alias setup_dir_conf noop
1264 alias setup_dir_man noop
1266 def update_shebang_line(path)
1268 return if config('shebang') == 'never'
1269 old = Shebang.load(path)
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
1275 return unless config('shebang') == 'all'
1276 new = Shebang.new(config('rubypath'))
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
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])
1294 return old unless config('shebang') == 'all'
1295 Shebang.new(config('rubypath'))
1299 def open_atomic_writer(path, &block)
1300 tmpfile = File.basename(path) + '.tmp'
1302 File.open(tmpfile, 'wb', &block)
1303 File.rename tmpfile, File.basename(path)
1305 File.unlink tmpfile if File.exist?(tmpfile)
1310 def Shebang.load(path)
1312 File.open(path) {|f|
1315 return nil unless /\A#!/ =~ line
1319 def Shebang.parse(line)
1320 cmd, *args = *line.strip.sub(/\A\#!/, '').split(' ')
1324 def initialize(cmd, args = [])
1333 "#! #{@cmd}" + (@args.empty? ? '' : " #{@args.join(' ')}")
1342 rm_f 'InstalledFiles'
1343 exec_task_traverse 'install'
1346 def install_dir_bin(rel)
1347 install_files targetfiles(), "#{config('bindir')}/#{rel}", 0755
1350 def install_dir_lib(rel)
1351 install_files libfiles(), "#{config('rbdir')}/#{rel}", 0644
1354 def install_dir_ext(rel)
1355 return unless extdir?(curr_srcdir())
1356 install_files rubyextentions('.'),
1357 "#{config('sodir')}/#{File.dirname(rel)}",
1361 def install_dir_data(rel)
1362 install_files targetfiles(), "#{config('datadir')}/#{rel}", 0644
1365 def install_dir_conf(rel)
1366 # FIXME: should not remove current config files
1367 # (rename previous file to .old/.org)
1368 install_files targetfiles(), "#{config('sysconfdir')}/#{rel}", 0644
1371 def install_dir_man(rel)
1372 install_files targetfiles(), "#{config('mandir')}/#{rel}", 0644
1375 def install_files(list, dest, mode)
1376 mkdir_p dest, @config.install_prefix
1377 list.each do |fname|
1378 install fname, dest, mode, @config.install_prefix
1383 glob_reject(%w(*.y *.output), targetfiles())
1386 def rubyextentions(dir)
1387 ents = glob_select("*.#{@config.dllext}", targetfiles())
1389 setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first"
1395 mapdir(existfiles() - hookfiles())
1402 else "#{curr_srcdir()}/#{ent}" # srcdir
1407 # picked up many entries from cvs-1.11.1/src/ignore.c
1409 core RCSLOG tags TAGS .make.state
1410 .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb
1411 *~ *.old *.bak *.BAK *.orig *.rej _$* *$
1417 glob_reject(JUNK_FILES, (files_of(curr_srcdir()) | files_of('.')))
1421 %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt|
1422 %w( config setup install clean ).map {|t| sprintf(fmt, t) }
1426 def glob_select(pat, ents)
1427 re = globs2re([pat])
1428 ents.select {|ent| re =~ ent }
1431 def glob_reject(pats, ents)
1433 ents.reject {|ent| re =~ ent }
1445 pats.map {|pat| pat.gsub(/[\.\$\#\*]/) {|ch| GLOB2REGEX[ch] } }.join('|')
1456 unless File.directory?('test')
1457 $stderr.puts 'no test in this package' if verbose?
1460 $stderr.puts 'Running tests...' if verbose?
1464 setup_rb_error 'test/unit cannot loaded. You need Ruby 1.8 or later to invoke this task.'
1466 runner = Test::Unit::AutoRunner.new(true)
1467 runner.to_run << TESTDIR
1476 exec_task_traverse 'clean'
1477 rm_f @config.savefile
1478 rm_f 'InstalledFiles'
1481 alias clean_dir_bin noop
1482 alias clean_dir_lib noop
1483 alias clean_dir_data noop
1484 alias clean_dir_conf noop
1485 alias clean_dir_man noop
1487 def clean_dir_ext(rel)
1488 return unless extdir?(curr_srcdir())
1489 make 'clean' if File.file?('Makefile')
1497 exec_task_traverse 'distclean'
1498 rm_f @config.savefile
1499 rm_f 'InstalledFiles'
1502 alias distclean_dir_bin noop
1503 alias distclean_dir_lib noop
1505 def distclean_dir_ext(rel)
1506 return unless extdir?(curr_srcdir())
1507 make 'distclean' if File.file?('Makefile')
1510 alias distclean_dir_data noop
1511 alias distclean_dir_conf noop
1512 alias distclean_dir_man noop
1518 def exec_task_traverse(task)
1519 run_hook "pre-#{task}"
1520 FILETYPES.each do |type|
1521 if type == 'ext' and config('without-ext') == 'yes'
1522 $stderr.puts 'skipping ext/* by user option' if verbose?
1525 traverse task, type, "#{task}_dir_#{type}"
1527 run_hook "post-#{task}"
1530 def traverse(task, rel, mid)
1532 run_hook "pre-#{task}"
1533 __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '')
1534 directories_of(curr_srcdir()).each do |d|
1535 traverse task, "#{rel}/#{d}", mid
1537 run_hook "post-#{task}"
1542 return unless File.dir?("#{@srcdir}/#{rel}")
1544 dir = File.basename(rel)
1545 Dir.mkdir dir unless File.dir?(dir)
1548 $stderr.puts '---> ' + rel if verbose?
1552 $stderr.puts '<--- ' + rel if verbose?
1553 @currdir = File.dirname(rel)
1557 path = [ "#{curr_srcdir()}/#{id}",
1558 "#{curr_srcdir()}/#{id}.rb" ].detect {|cand| File.file?(cand) }
1561 instance_eval File.read(path), path, 1
1564 setup_rb_error "hook #{path} failed:\n" + $!.message
1568 end # class Installer
1571 class SetupError < StandardError; end
1573 def setup_rb_error(msg)
1574 raise SetupError, msg
1579 ToplevelInstaller.invoke
1582 $stderr.puts $!.message
1583 $stderr.puts "Try 'ruby #{$0} --help' for detailed usage."