1 # -*- encoding: binary -*-
2 # frozen_string_literal: false
6 # Copyright (c) 2000-2005 Minero Aoki
8 # This program is free software.
9 # You can distribute/modify this program under the terms of
10 # the GNU LGPL, Lesser General Public License version 2.1.
13 unless Enumerable.method_defined?(:map) # Ruby 1.4.6
19 unless File.respond_to?(:read) # Ruby 1.6
27 unless Errno.const_defined?(:ENOTEMPTY) # Windows?
30 # We do not raise this exception, implementation is not needed.
35 def File.binread(fname)
36 open(fname, 'rb') {|f|
41 # for corrupted Windows' stat(2)
43 File.directory?((path[-1,1] == '/') ? path : path + '/')
51 def initialize(rbconfig)
62 attr_accessor :install_prefix
63 attr_accessor :config_opt
78 lookup(key).resolve(self)
86 @items.map {|i| i.name }
98 @table[name] or setup_rb_error "no such config item: #{name}"
103 @table[item.name] = item
108 @items.delete_if {|i| i.name == name }
109 @table.delete_if {|name, i| i.name == name }
113 def load_script(path, inst = nil)
115 MetaConfigEnvironment.new(self, inst).instance_eval File.read(path), path
125 File.foreach(savefile()) do |line|
126 k, v = *line.split(/=/, 2)
130 setup_rb_error $!.message + "\n#{File.basename($0)} config first"
135 @items.each {|i| i.value }
136 File.open(savefile(), 'w') {|f|
138 f.printf "%s=%s\n", i.name, i.value if i.value? and i.value
143 def load_standard_entries
144 standard_entries(@rbconfig).each do |ent|
149 def standard_entries(rbconfig)
152 rubypath = File.join(c['bindir'], c['ruby_install_name'] + c['EXEEXT'])
154 major = c['MAJOR'].to_i
155 minor = c['MINOR'].to_i
156 teeny = c['TEENY'].to_i
157 version = "#{major}.#{minor}"
159 # ruby ver. >= 1.4.4?
160 newpath_p = ((major >= 2) or
163 ((minor == 4) and (teeny >= 4)))))
167 libruby = "#{c['prefix']}/lib/ruby"
168 librubyver = c['rubylibdir']
169 librubyverarch = c['archdir']
170 siteruby = c['sitedir']
171 siterubyver = c['sitelibdir']
172 siterubyverarch = c['sitearchdir']
174 # 1.4.4 <= V <= 1.6.3
175 libruby = "#{c['prefix']}/lib/ruby"
176 librubyver = "#{c['prefix']}/lib/ruby/#{version}"
177 librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}"
178 siteruby = c['sitedir']
179 siterubyver = "$siteruby/#{version}"
180 siterubyverarch = "$siterubyver/#{c['arch']}"
183 libruby = "#{c['prefix']}/lib/ruby"
184 librubyver = "#{c['prefix']}/lib/ruby/#{version}"
185 librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}"
186 siteruby = "#{c['prefix']}/lib/ruby/#{version}/site_ruby"
187 siterubyver = siteruby
188 siterubyverarch = "$siterubyver/#{c['arch']}"
190 parameterize = lambda {|path|
191 path.sub(/\A#{Regexp.quote(c['prefix'])}/, '$prefix')
194 if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg }
195 makeprog = arg.sub(/'/, '').split(/=/, 2)[1]
201 ExecItem.new('installdirs', 'std/site/home',
202 'std: install under libruby; site: install under site_ruby; home: install under $HOME')\
206 table['rbdir'] = '$librubyver'
207 table['sodir'] = '$librubyverarch'
209 table['rbdir'] = '$siterubyver'
210 table['sodir'] = '$siterubyverarch'
212 setup_rb_error '$HOME was not set' unless ENV['HOME']
213 table['prefix'] = ENV['HOME']
214 table['rbdir'] = '$libdir/ruby'
215 table['sodir'] = '$libdir/ruby'
218 PathItem.new('prefix', 'path', c['prefix'],
219 'path prefix of target environment'),
220 PathItem.new('bindir', 'path', parameterize.call(c['bindir']),
221 'the directory for commands'),
222 PathItem.new('libdir', 'path', parameterize.call(c['libdir']),
223 'the directory for libraries'),
224 PathItem.new('datadir', 'path', parameterize.call(c['datadir']),
225 'the directory for shared data'),
226 PathItem.new('mandir', 'path', parameterize.call(c['mandir']),
227 'the directory for man pages'),
228 PathItem.new('sysconfdir', 'path', parameterize.call(c['sysconfdir']),
229 'the directory for system configuration files'),
230 PathItem.new('localstatedir', 'path', parameterize.call(c['localstatedir']),
231 'the directory for local state data'),
232 PathItem.new('libruby', 'path', libruby,
233 'the directory for ruby libraries'),
234 PathItem.new('librubyver', 'path', librubyver,
235 'the directory for standard ruby libraries'),
236 PathItem.new('librubyverarch', 'path', librubyverarch,
237 'the directory for standard ruby extensions'),
238 PathItem.new('siteruby', 'path', siteruby,
239 'the directory for version-independent aux ruby libraries'),
240 PathItem.new('siterubyver', 'path', siterubyver,
241 'the directory for aux ruby libraries'),
242 PathItem.new('siterubyverarch', 'path', siterubyverarch,
243 'the directory for aux ruby binaries'),
244 PathItem.new('rbdir', 'path', '$siterubyver',
245 'the directory for ruby scripts'),
246 PathItem.new('sodir', 'path', '$siterubyverarch',
247 'the directory for ruby extentions'),
248 PathItem.new('rubypath', 'path', rubypath,
249 'the path to set to #! line'),
250 ProgramItem.new('rubyprog', 'name', rubypath,
251 'the ruby program using for installation'),
252 ProgramItem.new('makeprog', 'name', makeprog,
253 'the make program to compile ruby extentions'),
254 SelectItem.new('shebang', 'all/ruby/never', 'ruby',
255 'shebang line (#!) editing mode'),
256 BoolItem.new('without-ext', 'yes/no', 'no',
257 'does not compile/install ruby extentions')
260 private :standard_entries
262 def load_multipackage_entries
263 multipackage_entries().each do |ent|
268 def multipackage_entries
270 PackageSelectionItem.new('with', 'name,name...', '', 'ALL',
271 'package names that you want to install'),
272 PackageSelectionItem.new('without', 'name,name...', '', 'NONE',
273 'package names that you do not want to install')
276 private :multipackage_entries
279 'std-ruby' => 'librubyver',
280 'stdruby' => 'librubyver',
281 'rubylibdir' => 'librubyver',
282 'archdir' => 'librubyverarch',
283 'site-ruby-common' => 'siteruby', # For backward compatibility
284 'site-ruby' => 'siterubyver', # For backward compatibility
285 'bin-dir' => 'bindir',
286 'bin-dir' => 'bindir',
289 'data-dir' => 'datadir',
290 'ruby-path' => 'rubypath',
291 'ruby-prog' => 'rubyprog',
292 'ruby' => 'rubyprog',
293 'make-prog' => 'makeprog',
298 ALIASES.each do |ali, name|
299 @table[ali] = @table[name]
303 @options_re = /\A--(#{@table.keys.join('|')})(?:=(.*))?\z/
307 m = @options_re.match(opt) or setup_rb_error "config: unknown option #{opt}"
315 def value_config?(name)
320 def initialize(name, template, default, desc)
329 attr_reader :description
331 attr_accessor :default
332 alias help_default default
335 "--#{@name}=#{@template}"
347 @value.gsub(%r<\$([^/]+)>) { table[$1] }
357 setup_rb_error "config: --#{name} requires argument" unless val
362 class BoolItem < Item
374 return 'yes' unless val
376 when /\Ay(es)?\z/i, /\At(rue)?\z/i then 'yes'
377 when /\An(o)?\z/i, /\Af(alse)\z/i then 'no'
379 setup_rb_error "config: --#{@name} accepts only yes/no for argument"
384 class PathItem < Item
392 setup_rb_error "config: --#{@name} requires argument" unless path
393 path[0,1] == '$' ? path : File.expand_path(path)
397 class ProgramItem < Item
403 class SelectItem < Item
404 def initialize(name, selection, default, desc)
406 @ok = selection.split('/')
416 unless @ok.include?(val.strip)
417 setup_rb_error "config: use --#{@name}=#{@template} (#{val})"
423 class ExecItem < Item
424 def initialize(name, selection, desc, &block)
425 super name, selection, nil, desc
426 @ok = selection.split('/')
439 setup_rb_error "$#{name()} wrongly used as option value"
444 def evaluate(val, table)
445 v = val.strip.downcase
446 unless @ok.include?(v)
447 setup_rb_error "invalid option --#{@name}=#{val} (use #{@template})"
449 @action.call v, table
453 class PackageSelectionItem < Item
454 def initialize(name, template, default, help_default, desc)
455 super name, template, default, desc
456 @help_default = help_default
459 attr_reader :help_default
468 unless File.dir?("packages/#{val}")
469 setup_rb_error "config: no such package: #{val}"
475 class MetaConfigEnvironment
476 def initialize(config, installer)
478 @installer = installer
489 def bool_config?(name)
490 @config.lookup(name).config_type == 'bool'
493 def path_config?(name)
494 @config.lookup(name).config_type == 'path'
497 def value_config?(name)
498 @config.lookup(name).config_type != 'exec'
505 def add_bool_config(name, default, desc)
506 @config.add BoolItem.new(name, 'yes/no', default ? 'yes' : 'no', desc)
509 def add_path_config(name, default, desc)
510 @config.add PathItem.new(name, 'path', default, desc)
513 def set_config_default(name, default)
514 @config.lookup(name).default = default
517 def remove_config(name)
521 # For only multipackage
523 raise '[setup.rb fatal] multi-package metaconfig API packages() called for single-package; contact application package vendor' unless @installer
527 # For only multipackage
528 def declare_packages(list)
529 raise '[setup.rb fatal] multi-package metaconfig API declare_packages() called for single-package; contact application package vendor' unless @installer
530 @installer.packages = list
534 end # class ConfigTable
537 # This module requires: #verbose?, #no_harm?
538 module FileOperations
540 def mkdir_p(dirname, prefix = nil)
541 dirname = prefix + File.expand_path(dirname) if prefix
542 $stderr.puts "mkdir -p #{dirname}" if verbose?
545 # Does not check '/', it's too abnormal.
546 dirs = File.expand_path(dirname).split(%r<(?=/)>)
547 if /\A[a-z]:\z/i =~ dirs[0]
549 dirs[0] = disk + dirs[0]
551 dirs.each_index do |idx|
552 path = dirs[0..idx].join('')
553 Dir.mkdir path unless File.dir?(path)
558 $stderr.puts "rm -f #{path}" if verbose?
560 force_remove_file path
564 $stderr.puts "rm -rf #{path}" if verbose?
569 def remove_tree(path)
570 if File.symlink?(path)
572 elsif File.dir?(path)
575 force_remove_file path
579 def remove_tree0(path)
580 Dir.foreach(path) do |ent|
583 entpath = "#{path}/#{ent}"
584 if File.symlink?(entpath)
586 elsif File.dir?(entpath)
589 force_remove_file entpath
594 rescue Errno::ENOTEMPTY
595 # directory may not be empty
599 def move_file(src, dest)
600 force_remove_file dest
602 File.rename src, dest
604 File.open(dest, 'wb') {|f|
605 f.write File.binread(src)
607 File.chmod File.stat(src).mode, dest
612 def force_remove_file(path)
619 def remove_file(path)
620 File.chmod 0777, path
624 def install(from, dest, mode, prefix = nil)
625 $stderr.puts "install #{from} #{dest}" if verbose?
628 realdest = prefix ? prefix + File.expand_path(dest) : dest
629 realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest)
630 str = File.binread(from)
631 if diff?(str, realdest)
633 rm_f realdest if File.exist?(realdest)
635 File.open(realdest, 'wb') {|f|
638 File.chmod mode, realdest
640 File.open("#{objdir_root()}/InstalledFiles", 'a') {|f|
642 f.puts realdest.sub(prefix, '')
650 def diff?(new_content, path)
651 return true unless File.exist?(path)
652 new_content != File.binread(path)
656 $stderr.puts args.join(' ') if verbose?
657 system(*args) or raise RuntimeError,
658 "system(#{args.map{|a| a.inspect }.join(' ')}) failed"
662 command config('rubyprog'), *args
666 command(*[config('makeprog'), task].compact)
670 File.exist?("#{dir}/MANIFEST") or File.exist?("#{dir}/extconf.rb")
675 return d.select {|ent| File.file?("#{dir}/#{ent}") }
679 DIR_REJECT = %w( . .. CVS SCCS RCS CVS.adm .svn )
681 def directories_of(dir)
683 return d.select {|ent| File.dir?("#{dir}/#{ent}") } - DIR_REJECT
690 # This module requires: #srcdir_root, #objdir_root, #relpath
697 alias config get_config
699 # obsolete: use metaconfig to change configuration
700 def set_config(key, val)
705 # srcdir/objdir (works only in the package directory)
709 "#{srcdir_root()}/#{relpath()}"
713 "#{objdir_root()}/#{relpath()}"
717 "#{curr_srcdir()}/#{path}"
721 File.exist?(srcfile(path))
724 def srcdirectory?(path)
725 File.dir?(srcfile(path))
729 File.file?(srcfile(path))
732 def srcentries(path = '.')
733 Dir.open("#{curr_srcdir()}/#{path}") {|d|
734 return d.to_a - %w(. ..)
738 def srcfiles(path = '.')
739 srcentries(path).select {|fname|
740 File.file?(File.join(curr_srcdir(), path, fname))
744 def srcdirectories(path = '.')
745 srcentries(path).select {|fname|
746 File.dir?(File.join(curr_srcdir(), path, fname))
753 class ToplevelInstaller
756 Copyright = 'Copyright (c) 2000-2005 Minero Aoki'
759 [ 'all', 'do config, setup, then install' ],
760 [ 'config', 'saves your configurations' ],
761 [ 'show', 'shows current configuration' ],
762 [ 'setup', 'compiles ruby extentions and others' ],
763 [ 'install', 'installs files' ],
764 [ 'test', 'run all tests in test/' ],
765 [ 'clean', "does `make clean' for each extention" ],
766 [ 'distclean',"does `make distclean' for each extention" ]
769 def ToplevelInstaller.invoke
770 config = ConfigTable.new(load_rbconfig())
771 config.load_standard_entries
772 config.load_multipackage_entries if multipackage?
774 klass = (multipackage?() ? ToplevelInstallerMulti : ToplevelInstaller)
775 klass.new(File.dirname($0), config).invoke
778 def ToplevelInstaller.multipackage?
779 File.dir?(File.dirname($0) + '/packages')
782 def ToplevelInstaller.load_rbconfig
783 if arg = ARGV.detect {|arg| /\A--rbconfig=/ =~ arg }
785 load File.expand_path(arg.split(/=/, 2)[1])
786 $".push 'rbconfig.rb'
793 def initialize(ardir_root, config)
794 @ardir = File.expand_path(ardir_root)
805 "#<#{self.class} #{__id__()}>"
810 case task = parsearg_global()
819 when 'config', 'test'
821 when 'clean', 'distclean'
822 @config.load_savefile if File.exist?(@config.savefile)
824 @config.load_savefile
826 __send__ "parsearg_#{task}"
828 __send__ "exec_#{task}"
833 @config.load_script "#{@ardir}/metaconfig"
837 @installer = Installer.new(@config, @ardir, File.expand_path('.'))
841 # Hook Script API bases
861 while arg = ARGV.shift
864 setup_rb_error "invalid task: #{arg}" unless valid_task?(arg)
867 @config.verbose = false
869 @config.verbose = true
874 puts "#{File.basename($0)} version #{Version}"
880 setup_rb_error "unknown global option '#{arg}'"
891 @valid_task_re ||= /\A(?:#{TASKS.map {|task,desc| task }.join('|')})\z/
894 def parsearg_no_options
896 task = caller(0).first.slice(%r<`parsearg_(\w+)'>, 1)
897 setup_rb_error "#{task}: unknown options: #{ARGV.join(' ')}"
901 alias parsearg_show parsearg_no_options
902 alias parsearg_setup parsearg_no_options
903 alias parsearg_test parsearg_no_options
904 alias parsearg_clean parsearg_no_options
905 alias parsearg_distclean parsearg_no_options
910 @config.config_opt = []
913 @config.config_opt = ARGV.dup
916 name, value = *@config.parse_opt(i)
917 if @config.value_config?(name)
918 @config[name] = value
920 evalopt.push [name, value]
924 evalopt.each do |name, value|
925 @config.lookup(name).evaluate value, @config
927 # Check if configuration is valid
929 @config[n] if @config.value_config?(n)
934 @config.no_harm = false
935 @config.install_prefix = ''
939 @config.no_harm = true
941 path = a.split(/=/, 2)[1]
942 path = File.expand_path(path) unless path[0,1] == '/'
943 @config.install_prefix = path
945 setup_rb_error "install: unknown option #{a}"
951 out.puts 'Typical Installation Procedure:'
952 out.puts " $ ruby #{File.basename $0} config"
953 out.puts " $ ruby #{File.basename $0} setup"
954 out.puts " # ruby #{File.basename $0} install (may require root privilege)"
956 out.puts 'Detailed Usage:'
957 out.puts " ruby #{File.basename $0} <global option>"
958 out.puts " ruby #{File.basename $0} [<global options>] <task> [<task options>]"
962 out.puts 'Global options:'
963 out.printf fmt, '-q,--quiet', 'suppress message outputs'
964 out.printf fmt, ' --verbose', 'output messages verbosely'
965 out.printf fmt, ' --help', 'print this message'
966 out.printf fmt, ' --version', 'print version and quit'
967 out.printf fmt, ' --copyright', 'print copyright and quit'
970 TASKS.each do |name, desc|
971 out.printf fmt, name, desc
974 fmt = " %-24s %s [%s]\n"
976 out.puts 'Options for CONFIG or ALL:'
977 @config.each do |item|
978 out.printf fmt, item.help_opt, item.description, item.help_default
980 out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',"running ruby's"
982 out.puts 'Options for INSTALL:'
983 out.printf fmt, '--no-harm', 'only display what to do if given', 'off'
984 out.printf fmt, '--prefix=path', 'install path prefix', ''
993 @installer.exec_config
994 @config.save # must be final
998 @installer.exec_setup
1002 @installer.exec_install
1006 @installer.exec_test
1011 printf "%-20s %s\n", i.name, i.value if i.value?
1016 @installer.exec_clean
1020 @installer.exec_distclean
1023 end # class ToplevelInstaller
1026 class ToplevelInstallerMulti < ToplevelInstaller
1028 include FileOperations
1030 def initialize(ardir_root, config)
1032 @packages = directories_of("#{@ardir}/packages")
1033 raise 'no package exists' if @packages.empty?
1034 @root_installer = Installer.new(@config, @ardir, File.expand_path('.'))
1038 @config.load_script "#{@ardir}/metaconfig", self
1039 @packages.each do |name|
1040 @config.load_script "#{@ardir}/packages/#{name}/metaconfig"
1044 attr_reader :packages
1047 raise 'package list is empty' if list.empty?
1049 raise "directory packages/#{name} does not exist"\
1050 unless File.dir?("#{@ardir}/packages/#{name}")
1057 @packages.each do |pack|
1058 @installers[pack] = Installer.new(@config,
1059 "#{@ardir}/packages/#{pack}",
1062 with = extract_selection(config('with'))
1063 without = extract_selection(config('without'))
1064 @selected = @installers.keys.select {|name|
1065 (with.empty? or with.include?(name)) \
1066 and not without.include?(name)
1070 def extract_selection(list)
1073 setup_rb_error "no such package: #{name}" unless @installers.key?(name)
1080 f.puts 'Inluded packages:'
1081 f.puts ' ' + @packages.sort.join(' ')
1090 run_hook 'pre-config'
1091 each_selected_installers {|inst| inst.exec_config }
1092 run_hook 'post-config'
1093 @config.save # must be final
1097 run_hook 'pre-setup'
1098 each_selected_installers {|inst| inst.exec_setup }
1099 run_hook 'post-setup'
1103 run_hook 'pre-install'
1104 each_selected_installers {|inst| inst.exec_install }
1105 run_hook 'post-install'
1110 each_selected_installers {|inst| inst.exec_test }
1111 run_hook 'post-test'
1115 rm_f @config.savefile
1116 run_hook 'pre-clean'
1117 each_selected_installers {|inst| inst.exec_clean }
1118 run_hook 'post-clean'
1122 rm_f @config.savefile
1123 run_hook 'pre-distclean'
1124 each_selected_installers {|inst| inst.exec_distclean }
1125 run_hook 'post-distclean'
1132 def each_selected_installers
1133 Dir.mkdir 'packages' unless File.dir?('packages')
1134 @selected.each do |pack|
1135 $stderr.puts "Processing the package `#{pack}' ..." if verbose?
1136 Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}")
1137 Dir.chdir "packages/#{pack}"
1138 yield @installers[pack]
1144 @root_installer.run_hook id
1147 # module FileOperations requires this
1152 # module FileOperations requires this
1157 end # class ToplevelInstallerMulti
1162 FILETYPES = %w( bin lib ext data conf man )
1164 include FileOperations
1165 include HookScriptAPI
1167 def initialize(config, srcroot, objroot)
1169 @srcdir = File.expand_path(srcroot)
1170 @objdir = File.expand_path(objroot)
1175 "#<#{self.class} #{File.basename(@srcdir)}>"
1182 # Hook Script API base methods
1201 # module FileOperations requires this
1206 # module FileOperations requires this
1213 save, @config.verbose = @config.verbose?, false
1216 @config.verbose = save
1225 exec_task_traverse 'config'
1228 alias config_dir_bin noop
1229 alias config_dir_lib noop
1231 def config_dir_ext(rel)
1232 extconf if extdir?(curr_srcdir())
1235 alias config_dir_data noop
1236 alias config_dir_conf noop
1237 alias config_dir_man noop
1240 ruby "#{curr_srcdir()}/extconf.rb", *@config.config_opt
1248 exec_task_traverse 'setup'
1251 def setup_dir_bin(rel)
1252 files_of(curr_srcdir()).each do |fname|
1253 update_shebang_line "#{curr_srcdir()}/#{fname}"
1257 alias setup_dir_lib noop
1259 def setup_dir_ext(rel)
1260 make if extdir?(curr_srcdir())
1263 alias setup_dir_data noop
1264 alias setup_dir_conf noop
1265 alias setup_dir_man noop
1267 def update_shebang_line(path)
1269 return if config('shebang') == 'never'
1270 old = Shebang.load(path)
1272 $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
1273 new = new_shebang(old)
1274 return if new.to_s == old.to_s
1276 return unless config('shebang') == 'all'
1277 new = Shebang.new(config('rubypath'))
1279 $stderr.puts "updating shebang: #{File.basename(path)}" if verbose?
1280 open_atomic_writer(path) {|output|
1281 File.open(path, 'rb') {|f|
1282 f.gets if old # discard
1283 output.puts new.to_s
1289 def new_shebang(old)
1290 if /\Aruby/ =~ File.basename(old.cmd)
1291 Shebang.new(config('rubypath'), old.args)
1292 elsif File.basename(old.cmd) == 'env' and old.args.first == 'ruby'
1293 Shebang.new(config('rubypath'), old.args[1..-1])
1295 return old unless config('shebang') == 'all'
1296 Shebang.new(config('rubypath'))
1300 def open_atomic_writer(path, &block)
1301 tmpfile = File.basename(path) + '.tmp'
1303 File.open(tmpfile, 'wb', &block)
1304 File.rename tmpfile, File.basename(path)
1306 File.unlink tmpfile if File.exist?(tmpfile)
1311 def Shebang.load(path)
1313 File.open(path) {|f|
1316 return nil unless /\A#!/ =~ line
1320 def Shebang.parse(line)
1321 cmd, *args = *line.strip.sub(/\A\#!/, '').split(' ')
1325 def initialize(cmd, args = [])
1334 "#! #{@cmd}" + (@args.empty? ? '' : " #{@args.join(' ')}")
1343 rm_f 'InstalledFiles'
1344 exec_task_traverse 'install'
1347 def install_dir_bin(rel)
1348 install_files targetfiles(), "#{config('bindir')}/#{rel}", 0755
1351 def install_dir_lib(rel)
1352 install_files libfiles(), "#{config('rbdir')}/#{rel}", 0644
1355 def install_dir_ext(rel)
1356 return unless extdir?(curr_srcdir())
1357 install_files rubyextentions('.'),
1358 "#{config('sodir')}/#{File.dirname(rel)}",
1362 def install_dir_data(rel)
1363 install_files targetfiles(), "#{config('datadir')}/#{rel}", 0644
1366 def install_dir_conf(rel)
1367 # FIXME: should not remove current config files
1368 # (rename previous file to .old/.org)
1369 install_files targetfiles(), "#{config('sysconfdir')}/#{rel}", 0644
1372 def install_dir_man(rel)
1373 install_files targetfiles(), "#{config('mandir')}/#{rel}", 0644
1376 def install_files(list, dest, mode)
1377 mkdir_p dest, @config.install_prefix
1378 list.each do |fname|
1379 install fname, dest, mode, @config.install_prefix
1384 glob_reject(%w(*.y *.output), targetfiles())
1387 def rubyextentions(dir)
1388 ents = glob_select("*.#{@config.dllext}", targetfiles())
1390 setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first"
1396 mapdir(existfiles() - hookfiles())
1403 else "#{curr_srcdir()}/#{ent}" # srcdir
1408 # picked up many entries from cvs-1.11.1/src/ignore.c
1410 core RCSLOG tags TAGS .make.state
1411 .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb
1412 *~ *.old *.bak *.BAK *.orig *.rej _$* *$
1418 glob_reject(JUNK_FILES, (files_of(curr_srcdir()) | files_of('.')))
1422 %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt|
1423 %w( config setup install clean ).map {|t| sprintf(fmt, t) }
1427 def glob_select(pat, ents)
1428 re = globs2re([pat])
1429 ents.select {|ent| re =~ ent }
1432 def glob_reject(pats, ents)
1434 ents.reject {|ent| re =~ ent }
1446 pats.map {|pat| pat.gsub(/[\.\$\#\*]/) {|ch| GLOB2REGEX[ch] } }.join('|')
1457 unless File.directory?('test')
1458 $stderr.puts 'no test in this package' if verbose?
1461 $stderr.puts 'Running tests...' if verbose?
1465 setup_rb_error 'test/unit cannot loaded. You need Ruby 1.8 or later to invoke this task.'
1467 runner = Test::Unit::AutoRunner.new(true)
1468 runner.to_run << TESTDIR
1477 exec_task_traverse 'clean'
1478 rm_f @config.savefile
1479 rm_f 'InstalledFiles'
1482 alias clean_dir_bin noop
1483 alias clean_dir_lib noop
1484 alias clean_dir_data noop
1485 alias clean_dir_conf noop
1486 alias clean_dir_man noop
1488 def clean_dir_ext(rel)
1489 return unless extdir?(curr_srcdir())
1490 make 'clean' if File.file?('Makefile')
1498 exec_task_traverse 'distclean'
1499 rm_f @config.savefile
1500 rm_f 'InstalledFiles'
1503 alias distclean_dir_bin noop
1504 alias distclean_dir_lib noop
1506 def distclean_dir_ext(rel)
1507 return unless extdir?(curr_srcdir())
1508 make 'distclean' if File.file?('Makefile')
1511 alias distclean_dir_data noop
1512 alias distclean_dir_conf noop
1513 alias distclean_dir_man noop
1519 def exec_task_traverse(task)
1520 run_hook "pre-#{task}"
1521 FILETYPES.each do |type|
1522 if type == 'ext' and config('without-ext') == 'yes'
1523 $stderr.puts 'skipping ext/* by user option' if verbose?
1526 traverse task, type, "#{task}_dir_#{type}"
1528 run_hook "post-#{task}"
1531 def traverse(task, rel, mid)
1533 run_hook "pre-#{task}"
1534 __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '')
1535 directories_of(curr_srcdir()).each do |d|
1536 traverse task, "#{rel}/#{d}", mid
1538 run_hook "post-#{task}"
1543 return unless File.dir?("#{@srcdir}/#{rel}")
1545 dir = File.basename(rel)
1546 Dir.mkdir dir unless File.dir?(dir)
1549 $stderr.puts '---> ' + rel if verbose?
1553 $stderr.puts '<--- ' + rel if verbose?
1554 @currdir = File.dirname(rel)
1558 path = [ "#{curr_srcdir()}/#{id}",
1559 "#{curr_srcdir()}/#{id}.rb" ].detect {|cand| File.file?(cand) }
1562 instance_eval File.read(path), path, 1
1565 setup_rb_error "hook #{path} failed:\n" + $!.message
1569 end # class Installer
1572 class SetupError < StandardError; end
1574 def setup_rb_error(msg)
1575 raise SetupError, msg
1580 ToplevelInstaller.invoke
1583 $stderr.puts $!.message
1584 $stderr.puts "Try 'ruby #{$0} --help' for detailed usage."