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