Develop and Download Open Source Software

Browse CVS Repository

Annotation of /exerb/exerb/setup.rb

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.5 - (hide annotations) (download)
Thu Dec 15 02:59:12 2005 UTC (18 years, 3 months ago) by yuya
Branch: MAIN
CVS Tags: release510, release430, release410, snapshot20060420, snapshot20060531, release400p1, release490, release440, release400, release461, release460, release540, release420, release500, release520, snapshot20060519, release480, ChangeLog, release450, release530, release470, HEAD
Changes since 1.4: +105 -71 lines
* setup.rbを3.4.1に変更

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

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26