Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

root/tags/capistrano_1-4-1/setup.rb

Revision 2525, 28.1 kB (checked in by minam, 3 years ago)

Have setup.rb create a switchtower.cmd file on Win32 platforms

Line 
1 #
2 # setup.rb
3 #
4 # Copyright (c) 2000-2004 Minero Aoki
5 #
6 # This program is free software.
7 # You can distribute/modify this program under the terms of
8 # the GNU Lesser General Public License version 2.1.
9 #
10
11 #
12 # For backward compatibility
13 #
14
15 unless Enumerable.method_defined?(:map)
16   module Enumerable
17     alias map collect
18   end
19 end
20
21 unless Enumerable.method_defined?(:detect)
22   module Enumerable
23     alias detect find
24   end
25 end
26
27 unless Enumerable.method_defined?(:select)
28   module Enumerable
29     alias select find_all
30   end
31 end
32
33 unless Enumerable.method_defined?(:reject)
34   module Enumerable
35     def reject
36       result = []
37       each do |i|
38         result.push i unless yield(i)
39       end
40       result
41     end
42   end
43 end
44
45 unless Enumerable.method_defined?(:inject)
46   module Enumerable
47     def inject(result)
48       each do |i|
49         result = yield(result, i)
50       end
51       result
52     end
53   end
54 end
55
56 unless Enumerable.method_defined?(:any?)
57   module Enumerable
58     def any?
59       each do |i|
60         return true if yield(i)
61       end
62       false
63     end
64   end
65 end
66
67 unless File.respond_to?(:read)
68   def File.read(fname)
69     open(fname) {|f|
70       return f.read
71     }
72   end
73 end
74
75 #
76 # Application independent utilities
77 #
78
79 def File.binread(fname)
80   open(fname, 'rb') {|f|
81     return f.read
82   }
83 end
84
85 # for corrupted windows stat(2)
86 def File.dir?(path)
87   File.directory?((path[-1,1] == '/') ? path : path + '/')
88 end
89
90 #
91 # Config
92 #
93
94 if arg = ARGV.detect{|arg| /\A--rbconfig=/ =~ arg }
95   ARGV.delete(arg)
96   require arg.split(/=/, 2)[1]
97   $".push 'rbconfig.rb'
98 else
99   require 'rbconfig'
100 end
101
102 def multipackage_install?
103   FileTest.directory?(File.dirname($0) + '/packages')
104 end
105
106
107 class ConfigTable
108
109   c = ::Config::CONFIG
110
111   rubypath = c['bindir'] + '/' + c['ruby_install_name']
112
113   major = c['MAJOR'].to_i
114   minor = c['MINOR'].to_i
115   teeny = c['TEENY'].to_i
116   version = "#{major}.#{minor}"
117
118   # ruby ver. >= 1.4.4?
119   newpath_p = ((major >= 2) or
120                ((major == 1) and
121                 ((minor >= 5) or
122                  ((minor == 4) and (teeny >= 4)))))
123  
124   subprefix = lambda {|path|
125     path.sub(/\A#{Regexp.quote(c['prefix'])}/o, '$prefix')
126   }
127
128   if c['rubylibdir']
129     # V < 1.6.3
130     stdruby    = subprefix.call(c['rubylibdir'])
131     siteruby   = subprefix.call(c['sitedir'])
132     versite    = subprefix.call(c['sitelibdir'])
133     sodir      = subprefix.call(c['sitearchdir'])
134   elsif newpath_p
135     # 1.4.4 <= V <= 1.6.3
136     stdruby    = "$prefix/lib/ruby/#{version}"
137     siteruby   = subprefix.call(c['sitedir'])
138     versite    = siteruby + '/' + version
139     sodir      = "$site-ruby/#{c['arch']}"
140   else
141     # V < 1.4.4
142     stdruby    = "$prefix/lib/ruby/#{version}"
143     siteruby   = "$prefix/lib/ruby/#{version}/site_ruby"
144     versite    = siteruby
145     sodir      = "$site-ruby/#{c['arch']}"
146   end
147
148   if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg }
149     makeprog = arg.sub(/'/, '').split(/=/, 2)[1]
150   else
151     makeprog = 'make'
152   end
153
154   common_descripters = [
155     [ 'prefix',    [ c['prefix'],
156                      'path',
157                      'path prefix of target environment' ] ],
158     [ 'std-ruby',  [ stdruby,
159                      'path',
160                      'the directory for standard ruby libraries' ] ],
161     [ 'site-ruby-common', [ siteruby,
162                      'path',
163                      'the directory for version-independent non-standard ruby libraries' ] ],
164     [ 'site-ruby', [ versite,
165                      'path',
166                      'the directory for non-standard ruby libraries' ] ],
167     [ 'bin-dir',   [ '$prefix/bin',
168                      'path',
169                      'the directory for commands' ] ],
170     [ 'rb-dir',    [ '$site-ruby',
171                      'path',
172                      'the directory for ruby scripts' ] ],
173     [ 'so-dir',    [ sodir,
174                      'path',
175                      'the directory for ruby extentions' ] ],
176     [ 'data-dir',  [ '$prefix/share',
177                      'path',
178                      'the directory for shared data' ] ],
179     [ 'ruby-path', [ rubypath,
180                      'path',
181                      'path to set to #! line' ] ],
182     [ 'ruby-prog', [ rubypath,
183                      'name',
184                      'the ruby program using for installation' ] ],
185     [ 'make-prog', [ makeprog,
186                      'name',
187                      'the make program to compile ruby extentions' ] ],
188     [ 'without-ext', [ 'no',
189                        'yes/no',
190                        'does not compile/install ruby extentions' ] ]
191   ]
192   multipackage_descripters = [
193     [ 'with',      [ '',
194                      'name,name...',
195                      'package names that you want to install',
196                      'ALL' ] ],
197     [ 'without',   [ '',
198                      'name,name...',
199                      'package names that you do not want to install',
200                      'NONE' ] ]
201   ]
202   if multipackage_install?
203     DESCRIPTER = common_descripters + multipackage_descripters
204   else
205     DESCRIPTER = common_descripters
206   end
207
208   SAVE_FILE = 'config.save'
209
210   def ConfigTable.each_name(&block)
211     keys().each(&block)
212   end
213
214   def ConfigTable.keys
215     DESCRIPTER.map {|name, *dummy| name }
216   end
217
218   def ConfigTable.each_definition(&block)
219     DESCRIPTER.each(&block)
220   end
221
222   def ConfigTable.get_entry(name)
223     name, ent = DESCRIPTER.assoc(name)
224     ent
225   end
226
227   def ConfigTable.get_entry!(name)
228     get_entry(name) or raise ArgumentError, "no such config: #{name}"
229   end
230
231   def ConfigTable.add_entry(name, vals)
232     ConfigTable::DESCRIPTER.push [name,vals]
233   end
234
235   def ConfigTable.remove_entry(name)
236     get_entry(name) or raise ArgumentError, "no such config: #{name}"
237     DESCRIPTER.delete_if {|n, arr| n == name }
238   end
239
240   def ConfigTable.config_key?(name)
241     get_entry(name) ? true : false
242   end
243
244   def ConfigTable.bool_config?(name)
245     ent = get_entry(name) or return false
246     ent[1] == 'yes/no'
247   end
248
249   def ConfigTable.value_config?(name)
250     ent = get_entry(name) or return false
251     ent[1] != 'yes/no'
252   end
253
254   def ConfigTable.path_config?(name)
255     ent = get_entry(name) or return false
256     ent[1] == 'path'
257   end
258
259
260   class << self
261     alias newobj new
262   end
263
264   def ConfigTable.new
265     c = newobj()
266     c.initialize_from_table
267     c
268   end
269
270   def ConfigTable.load
271     c = newobj()
272     c.initialize_from_file
273     c
274   end
275
276   def initialize_from_table
277     @table = {}
278     DESCRIPTER.each do |k, (default, vname, desc, default2)|
279       @table[k] = default
280     end
281   end
282
283   def initialize_from_file
284     raise InstallError, "#{File.basename $0} config first"\
285         unless File.file?(SAVE_FILE)
286     @table = {}
287     File.foreach(SAVE_FILE) do |line|
288       k, v = line.split(/=/, 2)
289       @table[k] = v.strip
290     end
291   end
292
293   def save
294     File.open(SAVE_FILE, 'w') {|f|
295       @table.each do |k, v|
296         f.printf "%s=%s\n", k, v if v
297       end
298     }
299   end
300
301   def []=(k, v)
302     raise InstallError, "unknown config option #{k}"\
303         unless ConfigTable.config_key?(k)
304     @table[k] = v
305   end
306    
307   def [](key)
308     return nil unless @table[key]
309     @table[key].gsub(%r<\$([^/]+)>) { self[$1] }
310   end
311
312   def set_raw(key, val)
313     @table[key] = val
314   end
315
316   def get_raw(key)
317     @table[key]
318   end
319
320 end
321
322
323 module MetaConfigAPI
324
325   def eval_file_ifexist(fname)
326     instance_eval File.read(fname), fname, 1 if File.file?(fname)
327   end
328
329   def config_names
330     ConfigTable.keys
331   end
332
333   def config?(name)
334     ConfigTable.config_key?(name)
335   end
336
337   def bool_config?(name)
338     ConfigTable.bool_config?(name)
339   end
340
341   def value_config?(name)
342     ConfigTable.value_config?(name)
343   end
344
345   def path_config?(name)
346     ConfigTable.path_config?(name)
347   end
348
349   def add_config(name, argname, default, desc)
350     ConfigTable.add_entry name,[default,argname,desc]
351   end
352
353   def add_path_config(name, default, desc)
354     add_config name, 'path', default, desc
355   end
356
357   def add_bool_config(name, default, desc)
358     add_config name, 'yes/no', default ? 'yes' : 'no', desc
359   end
360
361   def set_config_default(name, default)
362     if bool_config?(name)
363       ConfigTable.get_entry!(name)[0] = (default ? 'yes' : 'no')
364     else
365       ConfigTable.get_entry!(name)[0] = default
366     end
367   end
368
369   def remove_config(name)
370     ent = ConfigTable.get_entry(name)
371     ConfigTable.remove_entry name
372     ent
373   end
374
375 end
376
377 #
378 # File Operations
379 #
380
381 module FileOperations
382
383   def mkdir_p(dirname, prefix = nil)
384     dirname = prefix + dirname if prefix
385     $stderr.puts "mkdir -p #{dirname}" if verbose?
386     return if no_harm?
387
388     # does not check '/'... it's too abnormal case
389     dirs = dirname.split(%r<(?=/)>)
390     if /\A[a-z]:\z/i =~ dirs[0]
391       disk = dirs.shift
392       dirs[0] = disk + dirs[0]
393     end
394     dirs.each_index do |idx|
395       path = dirs[0..idx].join('')
396       Dir.mkdir path unless File.dir?(path)
397     end
398   end
399
400   def rm_f(fname)
401     $stderr.puts "rm -f #{fname}" if verbose?
402     return if no_harm?
403
404     if File.exist?(fname) or File.symlink?(fname)
405       File.chmod 0777, fname
406       File.unlink fname
407     end
408   end
409
410   def rm_rf(dn)
411     $stderr.puts "rm -rf #{dn}" if verbose?
412     return if no_harm?
413
414     Dir.chdir dn
415     Dir.foreach('.') do |fn|
416       next if fn == '.'
417       next if fn == '..'
418       if File.dir?(fn)
419         verbose_off {
420           rm_rf fn
421         }
422       else
423         verbose_off {
424           rm_f fn
425         }
426       end
427     end
428     Dir.chdir '..'
429     Dir.rmdir dn
430   end
431
432   def move_file(src, dest)
433     File.unlink dest if File.exist?(dest)
434     begin
435       File.rename src, dest
436     rescue
437       File.open(dest, 'wb') {|f| f.write File.binread(src) }
438       File.chmod File.stat(src).mode, dest
439       File.unlink src
440     end
441   end
442
443   def install(from, dest, mode, prefix = nil)
444     $stderr.puts "install #{from} #{dest}" if verbose?
445     return if no_harm?
446
447     realdest = prefix + dest if prefix
448     realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest)
449     str = File.binread(from)
450     if diff?(str, realdest)
451       verbose_off {
452         rm_f realdest if File.exist?(realdest)
453       }
454       File.open(realdest, 'wb') {|f|
455         f.write str
456       }
457       File.chmod mode, realdest
458
459       File.open("#{objdir_root()}/InstalledFiles", 'a') {|f|
460         if prefix
461           f.puts realdest.sub(prefix, '')
462         else
463           f.puts realdest
464         end
465       }
466     end
467   end
468
469   def diff?(new_content, path)
470     return true unless File.exist?(path)
471     new_content != File.binread(path)
472   end
473
474   def command(str)
475     $stderr.puts str if verbose?
476     system str or raise RuntimeError, "'system #{str}' failed"
477   end
478
479   def ruby(str)
480     command config('ruby-prog') + ' ' + str
481   end
482  
483   def make(task = '')
484     command config('make-prog') + ' ' + task
485   end
486
487   def extdir?(dir)
488     File.exist?(dir + '/MANIFEST')
489   end
490
491   def all_files_in(dirname)
492     Dir.open(dirname) {|d|
493       return d.select {|ent| File.file?("#{dirname}/#{ent}") }
494     }
495   end
496
497   REJECT_DIRS = %w(
498     CVS SCCS RCS CVS.adm .svn
499   )
500
501   def all_dirs_in(dirname)
502     Dir.open(dirname) {|d|
503       return d.select {|n| File.dir?("#{dirname}/#{n}") } - %w(. ..) - REJECT_DIRS
504     }
505   end
506
507 end
508
509 #
510 # Main Installer
511 #
512
513 class InstallError < StandardError; end
514
515
516 module HookUtils
517
518   def run_hook(name)
519     try_run_hook "#{curr_srcdir()}/#{name}" or
520     try_run_hook "#{curr_srcdir()}/#{name}.rb"
521   end
522
523   def try_run_hook(fname)
524     return false unless File.file?(fname)
525     begin
526       instance_eval File.read(fname), fname, 1
527     rescue
528       raise InstallError, "hook #{fname} failed:\n" + $!.message
529     end
530     true
531   end
532
533 end
534
535
536 module HookScriptAPI
537
538   def get_config(key)
539     @config[key]
540   end
541
542   alias config get_config
543
544   def set_config(key, val)
545     @config[key] = val
546   end
547
548   #
549   # srcdir/objdir (works only in the package directory)
550   #
551
552   #abstract srcdir_root
553   #abstract objdir_root
554   #abstract relpath
555
556   def curr_srcdir
557     "#{srcdir_root()}/#{relpath()}"
558   end
559
560   def curr_objdir
561     "#{objdir_root()}/#{relpath()}"
562   end
563
564   def srcfile(path)
565     "#{curr_srcdir()}/#{path}"
566   end
567
568   def srcexist?(path)
569     File.exist?(srcfile(path))
570   end
571
572   def srcdirectory?(path)
573     File.dir?(srcfile(path))
574   end
575  
576   def srcfile?(path)
577     File.file? srcfile(path)
578   end
579
580   def srcentries(path = '.')
581     Dir.open("#{curr_srcdir()}/#{path}") {|d|
582       return d.to_a - %w(. ..)
583     }
584   end
585
586   def srcfiles(path = '.')
587     srcentries(path).select {|fname|
588       File.file?(File.join(curr_srcdir(), path, fname))
589     }
590   end
591
592   def srcdirectories(path = '.')
593     srcentries(path).select {|fname|
594       File.dir?(File.join(curr_srcdir(), path, fname))
595     }
596   end
597
598 end
599
600
601 class ToplevelInstaller
602
603   Version   = '3.2.4'
604   Copyright = 'Copyright (c) 2000-2004 Minero Aoki'
605
606   TASKS = [
607     [ 'config',   'saves your configurations' ],
608     [ 'show',     'shows current configuration' ],
609     [ 'setup',    'compiles ruby extentions and others' ],
610     [ 'install',  'installs files' ],
611     [ 'clean',    "does `make clean' for each extention" ],
612     [ 'distclean',"does `make distclean' for each extention" ]
613   ]
614
615   def ToplevelInstaller.invoke
616     instance().invoke
617   end
618
619   @singleton = nil
620
621   def ToplevelInstaller.instance
622     @singleton ||= new(File.dirname($0