swissmedic-diff 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,1345 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Setup.rb, 2010-01-26 21:50:03
4
+ # http://proutils.github.com/setup/
5
+ #
6
+ # This is a stand-alone bundle of the setup.rb application.
7
+ # You can place it in your projects script/ directory, or
8
+ # rename it to 'setup.rb' and place it in your project's
9
+ # root directory (just like old times).
10
+ #
11
+ module Setup
12
+ VERSION = '5.0.0'
13
+ end
14
+ class << File #:nodoc: all
15
+ unless respond_to?(:read) # Ruby 1.6 and less
16
+ def read(fname)
17
+ open(fname){ |f| return f.read }
18
+ end
19
+ end
20
+ def dir?(path)
21
+ directory?((path[-1,1] == '/') ? path : path + '/')
22
+ end
23
+ end
24
+ unless Errno.const_defined?(:ENOTEMPTY) # Windows?
25
+ module Errno #:nodoc:
26
+ class ENOTEMPTY #:nodoc:
27
+ end
28
+ end
29
+ end
30
+ module Setup
31
+ META_EXTENSION_DIR = '.setup'
32
+ FILETYPES = %w( bin lib ext data etc man doc )
33
+ INSTALL_RECORD = 'InstalledFiles' #'.cache/setup/installedfiles'
34
+ end
35
+ module Setup
36
+ class Project
37
+ ROOT_MARKER = '{setup.rb,script/setup,meta/,MANIFEST,lib/}'
38
+ def rootdir
39
+ @rootdir ||= (
40
+ root = Dir[File.join(Dir.pwd, ROOT_MARKER)].first
41
+ if !root
42
+ raise Error, "not a project directory"
43
+ else
44
+ Dir.pwd
45
+ end
46
+ )
47
+ end
48
+ def name
49
+ @name = (
50
+ if file = Dir["{script/setup,meta,.meta}/name"].first
51
+ File.read(file).strip
52
+ else
53
+ nil
54
+ end
55
+ )
56
+ end
57
+ def loadpath
58
+ @loadpath ||= (
59
+ if file = Dir.glob('{script/setup,meta,.meta}/loadpath').first
60
+ raw = File.read(file).strip.chomp(']')
61
+ raw.split(/[\n,]/).map do |e|
62
+ e.strip.sub(/^[\[-]\s*/,'')
63
+ end
64
+ else
65
+ nil
66
+ end
67
+ )
68
+ end
69
+ def extconfs
70
+ @extconfs ||= Dir['ext/**/extconf.rb']
71
+ end
72
+ def extensions
73
+ @extensions ||= extconfs.collect{ |f| File.dirname(f) }
74
+ end
75
+ def compiles?
76
+ !extensions.empty?
77
+ end
78
+ end
79
+ end
80
+ module Setup
81
+ class Session
82
+ attr :options
83
+ def initialize(options={})
84
+ @options = options
85
+ self.io ||= StringIO.new # log instead ?
86
+ end
87
+ def io
88
+ @options[:io]
89
+ end
90
+ def io=(anyio)
91
+ @options[:io] = anyio
92
+ end
93
+ def trace?; @options[:trace]; end
94
+ def trace=(val)
95
+ @options[:trace] = val
96
+ end
97
+ def trial?; @options[:trial]; end
98
+ def trial=(val)
99
+ @options[:trial] = val
100
+ end
101
+ def quiet?; @options[:quiet]; end
102
+ def quiet=(val)
103
+ @options[:quiet] = val
104
+ end
105
+ def force?; @options[:force]; end
106
+ def force=(val)
107
+ @options[:force] = val
108
+ end
109
+ def compile?
110
+ configuration.compile? && project.compiles?
111
+ end
112
+ def all
113
+ config
114
+ if compile?
115
+ make
116
+ end
117
+ if configuration.test?
118
+ ok = test
119
+ exit 1 unless ok
120
+ end
121
+ install
122
+ if configuration.ri?
123
+ document
124
+ end
125
+ end
126
+ def config
127
+ log_header('Configure')
128
+ if configuration.save_config
129
+ io.puts "Configuration saved." unless quiet?
130
+ else
131
+ io.puts "Configuration current." unless quiet?
132
+ end
133
+ puts configuration if trace? && !quiet?
134
+ compiler.configure if compile? #compiler.compiles?
135
+ end
136
+ def make
137
+ abort "must setup config first" unless configuration.exist?
138
+ log_header('Compile')
139
+ compiler.compile
140
+ end
141
+ alias_method :setup, :make
142
+ def install
143
+ abort "must setup config first" unless configuration.exist?
144
+ log_header('Install')
145
+ installer.install
146
+ end
147
+ def test
148
+ return true unless tester.testable?
149
+ log_header('Test')
150
+ tester.test
151
+ end
152
+ def document
153
+ log_header('Document')
154
+ documentor.document
155
+ end
156
+ def clean
157
+ log_header('Clean')
158
+ compiler.clean
159
+ end
160
+ def distclean
161
+ log_header('Distclean')
162
+ compiler.distclean
163
+ end
164
+ def uninstall
165
+ if !File.exist?(INSTALL_RECORD)
166
+ io.puts "Nothing is installed."
167
+ return
168
+ end
169
+ log_header('Uninstall')
170
+ uninstaller.uninstall
171
+ io.puts('Ok.')
172
+ end
173
+ def show
174
+ puts configuration
175
+ end
176
+ def project
177
+ @project ||= Project.new
178
+ end
179
+ def configuration
180
+ @configuration ||= Configuration.new
181
+ end
182
+ def compiler
183
+ @compiler ||= Compiler.new(project, configuration, options)
184
+ end
185
+ def installer
186
+ @installer ||= Installer.new(project, configuration, options)
187
+ end
188
+ def tester
189
+ @tester ||= Tester.new(project, configuration, options)
190
+ end
191
+ def documentor
192
+ @documentor ||= Documentor.new(project, configuration, options)
193
+ end
194
+ def uninstaller
195
+ @uninstaller ||= Uninstaller.new(project, configuration, options)
196
+ end
197
+ def log_header(phase)
198
+ return if quiet?
199
+ if trial?
200
+ str = "#{phase.upcase} (trail run)"
201
+ else
202
+ str = "#{phase.upcase}"
203
+ end
204
+ line = "- " * 35
205
+ line[0..str.size+3] = str
206
+ io.puts("\n- - #{line}\n\n")
207
+ end
208
+ end
209
+ end
210
+ module Setup
211
+ class Base
212
+ attr :project
213
+ attr :config
214
+ attr_accessor :trial
215
+ attr_accessor :trace
216
+ attr_accessor :quiet
217
+ attr_accessor :force
218
+ attr_accessor :io
219
+ def initialize(project, configuration, options={})
220
+ @project = project
221
+ @config = configuration
222
+ initialize_hooks
223
+ options.each do |k,v|
224
+ __send__("#{k}=", v) if respond_to?("#{k}=")
225
+ end
226
+ end
227
+ def initialize_hooks
228
+ file = META_EXTENSION_DIR + "/#{self.class.name.downcase}.rb"
229
+ if File.exist?(file)
230
+ script = File.read(file)
231
+ (class << self; self; end).class_eval(script)
232
+ end
233
+ end
234
+ def trial? ; @trial ; end
235
+ def trace? ; @trace ; end
236
+ def quiet? ; @quiet ; end
237
+ def force? ; @force ; end
238
+ def rootdir
239
+ project.rootdir
240
+ end
241
+ def bash(*args)
242
+ $stderr.puts args.join(' ') if trace?
243
+ system(*args) or raise RuntimeError, "system(#{args.map{|a| a.inspect }.join(' ')}) failed"
244
+ end
245
+ alias_method :command, :bash
246
+ def ruby(*args)
247
+ bash(config.rubyprog, *args)
248
+ end
249
+ def trace_off #:yield:
250
+ begin
251
+ save, @trace = trace?, false
252
+ yield
253
+ ensure
254
+ @trace = save
255
+ end
256
+ end
257
+ def rm_f(path)
258
+ io.puts "rm -f #{path}" if trace? or trial?
259
+ return if trial?
260
+ force_remove_file(path)
261
+ end
262
+ def force_remove_file(path)
263
+ begin
264
+ remove_file(path)
265
+ rescue
266
+ end
267
+ end
268
+ def remove_file(path)
269
+ File.chmod 0777, path
270
+ File.unlink(path)
271
+ end
272
+ def rmdir(path)
273
+ io.puts "rmdir #{path}" if trace? or trial?
274
+ return if trial?
275
+ Dir.rmdir(path)
276
+ end
277
+ end
278
+ class Error < StandardError
279
+ end
280
+ end
281
+ module Setup
282
+ class Compiler < Base
283
+ def compiles?
284
+ !extdirs.empty?
285
+ end
286
+ def configure
287
+ extdirs.each do |dir|
288
+ Dir.chdir(dir) do
289
+ if File.exist?('extconf.rb') && !FileUtils.uptodate?('Makefile', ['extconf.rb'])
290
+ ruby("extconf.rb")
291
+ end
292
+ end
293
+ end
294
+ end
295
+ def compile
296
+ extdirs.each do |dir|
297
+ Dir.chdir(dir) do
298
+ make
299
+ end
300
+ end
301
+ end
302
+ def clean
303
+ extdirs.each do |dir|
304
+ Dir.chdir(dir) do
305
+ make('clean')
306
+ end
307
+ end
308
+ end
309
+ def distclean
310
+ extdirs.each do |dir|
311
+ Dir.chdir(dir) do
312
+ make('distclean')
313
+ end
314
+ end
315
+ end
316
+ def extdirs
317
+ Dir['ext/**/*/{MANIFEST,extconf.rb}'].map do |f|
318
+ File.dirname(f)
319
+ end.uniq
320
+ end
321
+ def make(task=nil)
322
+ return unless File.exist?('Makefile')
323
+ bash(*[config.makeprog, task].compact)
324
+ end
325
+ end
326
+ end
327
+ require 'rbconfig'
328
+ require 'fileutils'
329
+ require 'erb'
330
+ require 'yaml'
331
+ require 'shellwords'
332
+ module Setup
333
+ class Configuration
334
+ RBCONFIG = ::Config::CONFIG
335
+ CONFIG_FILE = 'SetupConfig' # '.cache/setup/config'
336
+ META_CONFIG_FILE = META_EXTENSION_DIR + '/configuration.rb'
337
+ def self.options
338
+ @@options ||= []
339
+ end
340
+ def self.option(name, *args) #type, description)
341
+ options << [name.to_s, *args] #type, description]
342
+ attr_accessor(name)
343
+ end
344
+ option :prefix , :path, 'path prefix of target environment'
345
+ option :bindir , :path, 'directory for commands'
346
+ option :libdir , :path, 'directory for libraries'
347
+ option :datadir , :path, 'directory for shared data'
348
+ option :mandir , :path, 'directory for man pages'
349
+ option :docdir , :path, 'directory for documentation'
350
+ option :rbdir , :path, 'directory for ruby scripts'
351
+ option :sodir , :path, 'directory for ruby extentions'
352
+ option :sysconfdir , :path, 'directory for system configuration files'
353
+ option :localstatedir , :path, 'directory for local state data'
354
+ option :libruby , :path, 'directory for ruby libraries'
355
+ option :librubyver , :path, 'directory for standard ruby libraries'
356
+ option :librubyverarch , :path, 'directory for standard ruby extensions'
357
+ option :siteruby , :path, 'directory for version-independent aux ruby libraries'
358
+ option :siterubyver , :path, 'directory for aux ruby libraries'
359
+ option :siterubyverarch , :path, 'directory for aux ruby binaries'
360
+ option :rubypath , :prog, 'path to set to #! line'
361
+ option :rubyprog , :prog, 'ruby program used for installation'
362
+ option :makeprog , :prog, 'make program to compile ruby extentions'
363
+ option :extconfopt , :opts, 'options to pass-thru to extconf.rb'
364
+ option :shebang , :pick, 'shebang line (#!) editing mode (all,ruby,never)'
365
+ option :no_test, :t , :bool, 'run pre-installation tests'
366
+ option :no_ri, :d , :bool, 'generate ri documentation'
367
+ option :no_doc , :bool, 'install doc/ directory'
368
+ option :no_ext , :bool, 'compile/install ruby extentions'
369
+ option :install_prefix , :path, 'install to alternate root location'
370
+ option :root , :path, 'install to alternate root location'
371
+ option :installdirs , :pick, 'install location mode (site,std,home)' #, local)
372
+ option :type , :pick, 'install location mode (site,std,home)'
373
+ ::Config::CONFIG.each do |key,val|
374
+ next if key == "configure_args"
375
+ name = key.to_s.downcase
376
+ define_method(name){ val }
377
+ end
378
+ config_args = Shellwords.shellwords(::Config::CONFIG["configure_args"])
379
+ config_args.each do |ent|
380
+ if ent.index("=")
381
+ key, val = *ent.split("=")
382
+ else
383
+ key, val = ent, true
384
+ end
385
+ name = key.downcase
386
+ name = name.sub(/^--/,'')
387
+ name = name.gsub(/-/,'_')
388
+ define_method(name){ val }
389
+ end
390
+ def options
391
+ self.class.options
392
+ end
393
+ def initialize(values={})
394
+ initialize_metaconfig
395
+ initialize_defaults
396
+ initialize_environment
397
+ initialize_configfile
398
+ values.each{ |k,v| __send__("#{k}=", v) }
399
+ yeild(self) if block_given?
400
+ end
401
+ def initialize_metaconfig
402
+ if File.exist?(META_CONFIG_FILE)
403
+ script = File.read(META_CONFIG_FILE)
404
+ (class << self; self; end).class_eval(script)
405
+ end
406
+ end
407
+ def initialize_defaults
408
+ self.type = 'site'
409
+ self.no_ri = true
410
+ self.no_test = true
411
+ self.no_doc = false
412
+ self.no_ext = false
413
+ end
414
+ def initialize_environment
415
+ options.each do |name, *args|
416
+ if value = ENV["RUBYSETUP_#{name.to_s.upcase}"]
417
+ __send__("#{name}=", value)
418
+ end
419
+ end
420
+ end
421
+ def initialize_configfile
422
+ if File.exist?(CONFIG_FILE)
423
+ erb = ERB.new(File.read(CONFIG_FILE))
424
+ txt = erb.result(binding)
425
+ dat = YAML.load(txt)
426
+ dat.each do |k, v|
427
+ next if 'type' == k
428
+ next if 'installdirs' == k
429
+ k = k.gsub('-','_')
430
+ __send__("#{k}=", v)
431
+ end
432
+ if dat['type']
433
+ self.type = dat['type']
434
+ end
435
+ if dat['installdirs']
436
+ self.installdirs = dat['installdirs']
437
+ end
438
+ end
439
+ end
440
+ def base_bindir
441
+ @base_bindir ||= subprefix('bindir')
442
+ end
443
+ def base_libdir
444
+ @base_libdir ||= subprefix('libdir')
445
+ end
446
+ def base_datadir
447
+ @base_datadir ||= subprefix('datadir')
448
+ end
449
+ def base_mandir
450
+ @base_mandir ||= subprefix('mandir')
451
+ end
452
+ def base_docdir
453
+ @base_docdir || File.dirname(subprefix('docdir'))
454
+ end
455
+ def base_rubylibdir
456
+ @rubylibdir ||= subprefix('rubylibdir')
457
+ end
458
+ def base_rubyarchdir
459
+ @base_rubyarchdir ||= subprefix('archdir')
460
+ end
461
+ def base_sysconfdir
462
+ @base_sysconfdir ||= subprefix('sysconfdir')
463
+ end
464
+ def base_localstatedir
465
+ @base_localstatedir ||= subprefix('localstatedir')
466
+ end
467
+ def type
468
+ @type ||= 'site'
469
+ end
470
+ def type=(val)
471
+ @type = val
472
+ case val.to_s
473
+ when 'std', 'ruby'
474
+ @rbdir = librubyver #'$librubyver'
475
+ @sodir = librubyverarch #'$librubyverarch'
476
+ when 'site'
477
+ @rbdir = siterubyver #'$siterubyver'
478
+ @sodir = siterubyverarch #'$siterubyverarch'
479
+ when 'home'
480
+ self.prefix = File.join(home, '.local') # TODO: Use XDG
481
+ @rbdir = nil #'$libdir/ruby'
482
+ @sodir = nil #'$libdir/ruby'
483
+ else
484
+ raise Error, "bad config: use type=(std|site|home) [#{val}]"
485
+ end
486
+ end
487
+ alias_method :installdirs, :type
488
+ alias_method :installdirs=, :type=
489
+ alias_method :install_prefix, :root
490
+ alias_method :install_prefix=, :root=
491
+ def prefix
492
+ @prefix ||= RBCONFIG['prefix']
493
+ end
494
+ def prefix=(path)
495
+ @prefix = pathname(path)
496
+ end
497
+ def libruby
498
+ @libruby ||= RBCONFIG['prefix'] + "/lib/ruby"
499
+ end
500
+ def libruby=(path)
501
+ path = pathname(path)
502
+ @librubyver = librubyver.sub(libruby, path)
503
+ @librubyverarch = librubyverarch.sub(libruby, path)
504
+ @libruby = path
505
+ end
506
+ def librubyver
507
+ @librubyver ||= RBCONFIG['rubylibdir']
508
+ end
509
+ def librubyver=(path)
510
+ @librubyver = pathname(path)
511
+ end
512
+ def librubyverarch
513
+ @librubyverarch ||= RBCONFIG['archdir']
514
+ end
515
+ def librubyverarch=(path)
516
+ @librubyverarch = pathname(path)
517
+ end
518
+ def siteruby
519
+ @siteruby ||= RBCONFIG['sitedir']
520
+ end
521
+ def siteruby=(path)
522
+ path = pathname(path)
523
+ @siterubyver = siterubyver.sub(siteruby, path)
524
+ @siterubyverarch = siterubyverarch.sub(siteruby, path)
525
+ @siteruby = path
526
+ end
527
+ def siterubyver
528
+ @siterubyver ||= RBCONFIG['sitelibdir']
529
+ end
530
+ def siterubyver=(path)
531
+ @siterubyver = pathname(path)
532
+ end
533
+ def siterubyverarch
534
+ @siterubyverarch ||= RBCONFIG['sitearchdir']
535
+ end
536
+ def siterubyverarch=(path)
537
+ @siterubyverarch = pathname(path)
538
+ end
539
+ def bindir
540
+ @bindir || File.join(prefix, base_bindir)
541
+ end
542
+ def bindir=(path)
543
+ @bindir = pathname(path)
544
+ end
545
+ def libdir
546
+ @libdir || File.join(prefix, base_libdir)
547
+ end
548
+ def libdir=(path)
549
+ @libdir = pathname(path)
550
+ end
551
+ def datadir
552
+ @datadir || File.join(prefix, base_datadir)
553
+ end
554
+ def datadir=(path)
555
+ @datadir = pathname(path)
556
+ end
557
+ def mandir
558
+ @mandir || File.join(prefix, base_mandir)
559
+ end
560
+ def mandir=(path)
561
+ @mandir = pathname(path)
562
+ end
563
+ def docdir
564
+ @docdir || File.join(prefix, base_docdir)
565
+ end
566
+ def docdir=(path)
567
+ @docdir = pathname(path)
568
+ end
569
+ def rbdir
570
+ @rbdir || File.join(prefix, base_rubylibdir)
571
+ end
572
+ def sodir
573
+ @sodir || File.join(prefix, base_rubyarchdir)
574
+ end
575
+ def sysconfdir
576
+ @sysconfdir ||= base_sysconfdir
577
+ end
578
+ def sysconfdir=(path)
579
+ @sysconfdir = pathname(path)
580
+ end
581
+ def localstatedir
582
+ @localstatedir ||= base_localstatedir
583
+ end
584
+ def localstatedir=(path)
585
+ @localstatedir = pathname(path)
586
+ end
587
+ def rubypath
588
+ @rubypath ||= File.join(RBCONFIG['bindir'], RBCONFIG['ruby_install_name'] + RBCONFIG['EXEEXT'])
589
+ end
590
+ def rubypath=(path)
591
+ @rubypath = pathname(path)
592
+ end
593
+ def rubyprog
594
+ @rubyprog || rubypath
595
+ end
596
+ def rubyprog=(command)
597
+ @rubyprog = command
598
+ end
599
+ def makeprog
600
+ @makeprog ||= (
601
+ if arg = RBCONFIG['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg }
602
+ arg.sub(/'/, '').split(/=/, 2)[1]
603
+ else
604
+ 'make'
605
+ end
606
+ )
607
+ end
608
+ def makeprog=(command)
609
+ @makeprog = command
610
+ end
611
+ def extconfopt
612
+ @extconfopt ||= ''
613
+ end
614
+ def extconfopt=(string)
615
+ @extconfopt = string
616
+ end
617
+ def shebang
618
+ @shebang ||= 'ruby'
619
+ end
620
+ def shebang=(val)
621
+ if %w(all ruby never).include?(val)
622
+ @shebang = val
623
+ else
624
+ raise Error, "bad config: use SHEBANG=(all|ruby|never) [#{val}]"
625
+ end
626
+ end
627
+ def no_ext
628
+ @no_ext
629
+ end
630
+ def no_ext=(val)
631
+ @no_ext = boolean(val)
632
+ end
633
+ def no_test
634
+ @no_test
635
+ end
636
+ def no_test=(val)
637
+ @no_test = boolean(val)
638
+ end
639
+ def no_doc
640
+ @no_doc
641
+ end
642
+ def no_doc=(val)
643
+ @no_doc = boolean(val)
644
+ end
645
+ def no_ri
646
+ @no_ri
647
+ end
648
+ def no_ri=(val)
649
+ @no_ri = boolean(val)
650
+ end
651
+ def compile?
652
+ !no_ext
653
+ end
654
+ def test?
655
+ !no_test
656
+ end
657
+ def ri?
658
+ !no_ri
659
+ end
660
+ def doc?
661
+ !no_doc
662
+ end
663
+ def to_h
664
+ h = {}
665
+ options.each do |name, *args|
666
+ h[name.to_s] = __send__(name)
667
+ end
668
+ h
669
+ end
670
+ def to_s
671
+ to_yaml.sub(/\A---\s*\n/,'')
672
+ end
673
+ def to_yaml(*args)
674
+ to_h.to_yaml(*args)
675
+ end
676
+ def save_config
677
+ out = to_yaml
678
+ if not File.exist?(File.dirname(CONFIG_FILE))
679
+ FileUtils.mkdir_p(File.dirname(CONFIG_FILE))
680
+ end
681
+ if File.exist?(CONFIG_FILE)
682
+ txt = File.read(CONFIG_FILE)
683
+ return nil if txt == out
684
+ end
685
+ File.open(CONFIG_FILE, 'w'){ |f| f << out }
686
+ true
687
+ end
688
+ def exist?
689
+ File.exist?(CONFIG_FILE)
690
+ end
691
+ private
692
+ def pathname(path)
693
+ path.gsub(%r<\\$([^/]+)>){ self[$1] }
694
+ end
695
+ def boolean(val, name=nil)
696
+ case val
697
+ when true, false, nil
698
+ val
699
+ else
700
+ case val.to_s.downcase
701
+ when 'y', 'yes', 't', 'true'
702
+ true
703
+ when 'n', 'no', 'f', 'false'
704
+ false
705
+ else
706
+ raise Error, "bad config: use --#{name}=(yes|no) [\#{val}]"
707
+ end
708
+ end
709
+ end
710
+ def subprefix(path, with='')
711
+ val = RBCONFIG[path]
712
+ raise "Unknown path -- #{path}" if val.nil?
713
+ prefix = Regexp.quote(RBCONFIG['prefix'])
714
+ val.sub(/\A#{prefix}/, with)
715
+ end
716
+ def home
717
+ ENV['HOME'] || raise(Error, 'HOME is not set.')
718
+ end
719
+ end #class ConfigTable
720
+ end #module Setup
721
+ =begin
722
+ def inintialize_metaconfig
723
+ path = Dir.glob(METACONFIG_FILE).first
724
+ if path && File.file?(path)
725
+ MetaConfigEnvironment.new(self).instance_eval(File.read(path), path)
726
+ end
727
+ end
728
+ class MetaConfigEnvironment
729
+ def initialize(config) #, installer)
730
+ @config = config
731
+ end
732
+ def config_names
733
+ @config.descriptions.collect{ |n, t, d| n.to_s }
734
+ end
735
+ def config?(name)
736
+ @config.descriptions.find do |sym, type, desc|
737
+ sym.to_s == name.to_s
738
+ end
739
+ end
740
+ def bool_config?(name)
741
+ @config.descriptions.find do |sym, type, desc|
742
+ sym.to_s == name.to_s && type == :bool
743
+ end
744
+ end
745
+ def path_config?(name)
746
+ @config.descriptions.find do |sym, type, desc|
747
+ sym.to_s == name.to_s && type == :path
748
+ end
749
+ end
750
+ def value_config?(name)
751
+ @config.descriptions.find do |sym, type, desc|
752
+ sym.to_s == name.to_s && type != :prog
753
+ end
754
+ end
755
+ def add_config(name, default, desc)
756
+ @config.descriptions << [name.to_sym, nil, desc]
757
+ end
758
+ def add_bool_config(name, default, desc)
759
+ @config.descriptions << [name.to_sym, :bool, desc]
760
+ end
761
+ def add_path_config(name, default, desc)
762
+ @config.descriptions << [name.to_sym, :path, desc]
763
+ end
764
+ def set_config_default(name, default)
765
+ @config[name] = default
766
+ end
767
+ def remove_config(name)
768
+ item = @config.descriptions.find do |sym, type, desc|
769
+ sym.to_s == name.to_s
770
+ end
771
+ index = @config.descriptions.index(item)
772
+ @config.descriptions.delete(index)
773
+ end
774
+ end
775
+ =end
776
+ module Setup
777
+ class Documentor < Base
778
+ def document
779
+ return if config.no_doc
780
+ exec_ri
781
+ end
782
+ def exec_ri
783
+ case config.type #installdirs
784
+ when 'std', 'ruby'
785
+ output = "--ri-site"
786
+ when 'site'
787
+ output = "--ri-site"
788
+ when 'home'
789
+ output = "--ri"
790
+ else
791
+ abort "bad config: should not be possible -- type=#{config.type}"
792
+ end
793
+ if File.exist?('.document')
794
+ files = File.read('.document').split("\n")
795
+ files.reject!{ |l| l =~ /^\s*[#]/ || l !~ /\S/ }
796
+ files.collect!{ |f| f.strip }
797
+ else
798
+ files = []
799
+ files << 'lib' if File.directory?('lib')
800
+ files << 'ext' if File.directory?('ext')
801
+ end
802
+ opt = []
803
+ opt << "-U"
804
+ opt << "-q" #if quiet?
805
+ opt << output
806
+ opt << files
807
+ opt = opt.flatten
808
+ cmd = "rdoc " + opt.join(' ')
809
+ if trial?
810
+ puts cmd
811
+ else
812
+ begin
813
+ success = system(cmd)
814
+ raise unless success
815
+ io.puts "Ok ri." #unless quiet?
816
+ rescue Exception
817
+ $stderr.puts "ri generation failed"
818
+ $stderr.puts "command was: '#{cmd}'"
819
+ end
820
+ end
821
+ end
822
+ def exec_rdoc
823
+ main = Dir.glob("README{,.*}", File::FNM_CASEFOLD).first
824
+ if File.exist?('.document')
825
+ files = File.read('.document').split("\n")
826
+ files.reject!{ |l| l =~ /^\s*[#]/ || l !~ /\S/ }
827
+ files.collect!{ |f| f.strip }
828
+ else
829
+ files = []
830
+ files << main if main
831
+ files << 'lib' if File.directory?('lib')
832
+ files << 'ext' if File.directory?('ext')
833
+ end
834
+ checkfiles = (files + files.map{ |f| Dir[File.join(f,'*','**')] }).flatten.uniq
835
+ if FileUtils.uptodate?('doc/rdoc', checkfiles)
836
+ puts "RDocs look current."
837
+ return
838
+ end
839
+ output = 'doc/rdoc'
840
+ title = (PACKAGE.capitalize + " API").strip if PACKAGE
841
+ template = config.doctemplate || 'html'
842
+ opt = []
843
+ opt << "-U"
844
+ opt << "-q" #if quiet?
845
+ opt << "--op=#{output}"
846
+ opt << "--title=#{title}"
847
+ opt << "--main=#{main}" if main
848
+ opt << files
849
+ opt = opt.flatten
850
+ cmd = "rdoc " + opt.join(' ')
851
+ if trial?
852
+ puts cmd
853
+ else
854
+ begin
855
+ system(cmd)
856
+ puts "Ok rdoc." unless quiet?
857
+ rescue Exception
858
+ puts "Fail rdoc."
859
+ puts "Command was: '#{cmd}'"
860
+ puts "Proceeding with install anyway."
861
+ end
862
+ end
863
+ end
864
+ end
865
+ end
866
+ module Setup
867
+ class Installer < Base
868
+ def install_prefix
869
+ config.install_prefix
870
+ end
871
+ def install
872
+ Dir.chdir(rootdir) do
873
+ install_bin
874
+ install_ext
875
+ install_lib
876
+ install_data
877
+ install_man
878
+ install_doc
879
+ install_etc
880
+ prune_install_record
881
+ end
882
+ end
883
+ def install_bin
884
+ return unless directory?('bin')
885
+ report_transfer('bin', config.bindir)
886
+ files = files('bin')
887
+ install_files('bin', files, config.bindir, 0755)
888
+ end
889
+ def install_ext
890
+ return unless directory?('ext')
891
+ report_transfer('ext', config.sodir)
892
+ files = files('ext')
893
+ files = select_dllext(files)
894
+ files.each do |file|
895
+ name = File.join(File.dirname(File.dirname(file)), File.basename(file))
896
+ dest = destination(config.sodir, name)
897
+ install_file('ext', file, dest, 0555, install_prefix)
898
+ end
899
+ end
900
+ def install_lib
901
+ return unless directory?('lib')
902
+ report_transfer('lib', config.rbdir)
903
+ files = files('lib')
904
+ install_files('lib', files, config.rbdir, 0644)
905
+ end
906
+ def install_data
907
+ return unless directory?('data')
908
+ report_transfer('data', config.datadir)
909
+ files = files('data')
910
+ install_files('data', files, config.datadir, 0644)
911
+ end
912
+ def install_etc
913
+ return unless directory?('etc')
914
+ report_transfer('etc', config.sysconfdir)
915
+ files = files('etc')
916
+ install_files('etc', files, config.sysconfdir, 0644)
917
+ end
918
+ def install_man
919
+ return unless directory?('man')
920
+ report_transfer('man', config.mandir)
921
+ files = files('man')
922
+ install_files('man', files, config.mandir, 0644)
923
+ end
924
+ def install_doc
925
+ return unless config.doc?
926
+ return unless directory?('doc')
927
+ return unless project.name
928
+ dir = File.join(config.docdir, "ruby-{project.name}")
929
+ report_transfer('doc', dir)
930
+ files = files('doc')
931
+ install_files('doc', files, dir, 0644)
932
+ end
933
+ private
934
+ def report_transfer(source, directory)
935
+ unless quiet?
936
+ if install_prefix
937
+ out = File.join(install_prefix, directory)
938
+ else
939
+ out = directory
940
+ end
941
+ io.puts "* #{source} -> #{out}"
942
+ end
943
+ end
944
+ def directory?(path)
945
+ File.directory?(path)
946
+ end
947
+ def files(dir)
948
+ files = Dir["#{dir}/**/*"]
949
+ files = files.select{ |f| File.file?(f) }
950
+ files = files.map{ |f| f.sub("#{dir}/", '') }
951
+ files
952
+ end
953
+ def select_dllext(files)
954
+ ents = files.select do |file|
955
+ File.extname(file) == ".#{dllext}"
956
+ end
957
+ if ents.empty? && !files.empty?
958
+ raise Error, "ruby extention not compiled: 'setup.rb setup' first"
959
+ end
960
+ ents
961
+ end
962
+ def dllext
963
+ config.dlext
964
+ end
965
+ def install_files(dir, list, dest, mode)
966
+ list.each do |fname|
967
+ rdest = destination(dest, fname)
968
+ install_file(dir, fname, rdest, mode, install_prefix)
969
+ end
970
+ end
971
+ def install_file(dir, from, dest, mode, prefix=nil)
972
+ mkdir_p(File.dirname(dest))
973
+ if trace? or trial?
974
+ io.puts "install #{dir}/#{from} #{dest}"
975
+ end
976
+ return if trial?
977
+ str = binread(File.join(dir, from))
978
+ if diff?(str, dest)
979
+ trace_off {
980
+ rm_f(dest) if File.exist?(dest)
981
+ }
982
+ File.open(dest, 'wb'){ |f| f.write(str) }
983
+ File.chmod(mode, dest)
984
+ end
985
+ record_installation(dest) # record file as installed
986
+ end
987
+ def mkdir_p(dirname) #, prefix=nil)
988
+ return if File.directory?(dirname)
989
+ io.puts "mkdir -p #{dirname}" if trace? or trial?
990
+ return if trial?
991
+ dirs = File.expand_path(dirname).split(%r<(?=/)>)
992
+ if /\A[a-z]:\z/i =~ dirs[0]
993
+ disk = dirs.shift
994
+ dirs[0] = disk + dirs[0]
995
+ end
996
+ dirs.each_index do |idx|
997
+ path = dirs[0..idx].join('')
998
+ unless File.dir?(path)
999
+ Dir.mkdir(path)
1000
+ end
1001
+ record_installation(path) # record directories made
1002
+ end
1003
+ end
1004
+ def record_installation(path)
1005
+ File.open(install_record, 'a') do |f|
1006
+ f.puts(path)
1007
+ end
1008
+ end
1009
+ def prune_install_record
1010
+ entries = File.read(install_record).split("\n")
1011
+ entries.uniq!
1012
+ File.open(install_record, 'w') do |f|
1013
+ f << entries.join("\n")
1014
+ f << "\n"
1015
+ end
1016
+ end
1017
+ def install_record
1018
+ @install_record ||= (
1019
+ file = INSTALL_RECORD
1020
+ dir = File.dirname(file)
1021
+ unless File.directory?(dir)
1022
+ FileUtils.mkdir_p(dir)
1023
+ end
1024
+ file
1025
+ )
1026
+ end
1027
+ def destination(dir, file)
1028
+ dest = install_prefix ? File.join(install_prefix, File.expand_path(dir)) : dir
1029
+ dest = File.join(dest, file) #if File.dir?(dest)
1030
+ dest = File.expand_path(dest)
1031
+ dest
1032
+ end
1033
+ def diff?(new_content, path)
1034
+ return true unless File.exist?(path)
1035
+ new_content != binread(path)
1036
+ end
1037
+ def binread(fname)
1038
+ File.open(fname, 'rb') do |f|
1039
+ return f.read
1040
+ end
1041
+ end
1042
+ def install_shebang(files, dir)
1043
+ files.each do |file|
1044
+ path = File.join(dir, File.basename(file))
1045
+ update_shebang_line(path)
1046
+ end
1047
+ end
1048
+ def update_shebang_line(path)
1049
+ return if trial?
1050
+ return if config.shebang == 'never'
1051
+ old = Shebang.load(path)
1052
+ if old
1053
+ if old.args.size > 1
1054
+ $stderr.puts "warning: #{path}"
1055
+ $stderr.puts "Shebang line has too many args."
1056
+ $stderr.puts "It is not portable and your program may not work."
1057
+ end
1058
+ new = new_shebang(old)
1059
+ return if new.to_s == old.to_s
1060
+ else
1061
+ return unless config.shebang == 'all'
1062
+ new = Shebang.new(config.rubypath)
1063
+ end
1064
+ $stderr.puts "updating shebang: #{File.basename(path)}" if trace?
1065
+ open_atomic_writer(path) do |output|
1066
+ File.open(path, 'rb') do |f|
1067
+ f.gets if old # discard
1068
+ output.puts new.to_s
1069
+ output.print f.read
1070
+ end
1071
+ end
1072
+ end
1073
+ def new_shebang(old)
1074
+ if /\Aruby/ =~ File.basename(old.cmd)
1075
+ Shebang.new(config.rubypath, old.args)
1076
+ elsif File.basename(old.cmd) == 'env' and old.args.first == 'ruby'
1077
+ Shebang.new(config.rubypath, old.args[1..-1])
1078
+ else
1079
+ return old unless config.shebang == 'all'
1080
+ Shebang.new(config.rubypath)
1081
+ end
1082
+ end
1083
+ def open_atomic_writer(path, &block)
1084
+ tmpfile = File.basename(path) + '.tmp'
1085
+ begin
1086
+ File.open(tmpfile, 'wb', &block)
1087
+ File.rename tmpfile, File.basename(path)
1088
+ ensure
1089
+ File.unlink tmpfile if File.exist?(tmpfile)
1090
+ end
1091
+ end
1092
+ class Shebang
1093
+ def Shebang.load(path)
1094
+ line = nil
1095
+ File.open(path) {|f|
1096
+ line = f.gets
1097
+ }
1098
+ return nil unless /\A#!/ =~ line
1099
+ parse(line)
1100
+ end
1101
+ def Shebang.parse(line)
1102
+ cmd, *args = *line.strip.sub(/\A\#!/, '').split(' ')
1103
+ new(cmd, args)
1104
+ end
1105
+ def initialize(cmd, args = [])
1106
+ @cmd = cmd
1107
+ @args = args
1108
+ end
1109
+ attr_reader :cmd
1110
+ attr_reader :args
1111
+ def to_s
1112
+ "#! #{@cmd}" + (@args.empty? ? '' : " #{@args.join(' ')}")
1113
+ end
1114
+ end
1115
+ end
1116
+ end
1117
+ module Setup
1118
+ class Tester < Base
1119
+ RUBYSCRIPT = META_EXTENSION_DIR + '/testrc.rb'
1120
+ SHELLSCRIPT = 'script/test'
1121
+ def testable?
1122
+ return false if config.no_test
1123
+ return true if File.exist?(RUBYSCRIPT)
1124
+ return true if File.exist?(SHELLSCRIPT)
1125
+ false
1126
+ end
1127
+ def test
1128
+ return true if !testable?
1129
+ if File.exist?(RUBYSCRIPT)
1130
+ test_rubyscript
1131
+ elsif File.exist?(SHELLSCRIPT)
1132
+ test_shellscript
1133
+ end
1134
+ end
1135
+ def test_shellscript
1136
+ bash(SHELLSCRIPT)
1137
+ end
1138
+ def test_rubyscript
1139
+ ruby(RUBYSCRIPT)
1140
+ end
1141
+ end
1142
+ end
1143
+ module Setup
1144
+ class Uninstaller < Base
1145
+ def uninstall
1146
+ return unless File.exist?(INSTALL_RECORD)
1147
+ files = []
1148
+ dirs = []
1149
+ paths.each do |path|
1150
+ dirs << path if File.dir?(path)
1151
+ files << path if File.file?(path)
1152
+ end
1153
+ if dirs.empty? && files.empty?
1154
+ io.outs "Nothing to remove."
1155
+ return
1156
+ end
1157
+ files.sort!{ |a,b| b.size <=> a.size }
1158
+ dirs.sort!{ |a,b| b.size <=> a.size }
1159
+ if !force? && !trial?
1160
+ puts (files + dirs).collect{ |f| "#{f}" }.join("\n")
1161
+ puts
1162
+ puts "Must use --force option to remove these files and directories that become empty."
1163
+ return
1164
+ end
1165
+ files.each do |file|
1166
+ rm_f(file)
1167
+ end
1168
+ dirs.each do |dir|
1169
+ entries = Dir.entries(dir)
1170
+ entries.delete('.')
1171
+ entries.delete('..')
1172
+ rmdir(dir) if entries.empty?
1173
+ end
1174
+ rm_f(INSTALL_RECORD)
1175
+ end
1176
+ private
1177
+ def paths
1178
+ @paths ||= (
1179
+ lines = File.read(INSTALL_RECORD).split(/\s*\n/)
1180
+ lines = lines.map{ |line| line.strip }
1181
+ lines = lines.uniq
1182
+ lines = lines.reject{ |line| line.empty? } # skip blank lines
1183
+ lines = lines.reject{ |line| line[0,1] == '#' } # skip blank lines
1184
+ lines
1185
+ )
1186
+ end
1187
+ end
1188
+ end
1189
+ require 'optparse'
1190
+ module Setup
1191
+ class Command
1192
+ def self.run(*argv)
1193
+ new.run(*argv)
1194
+ end
1195
+ def self.tasks
1196
+ @tasks ||= {}
1197
+ end
1198
+ def self.order
1199
+ @order ||= []
1200
+ end
1201
+ def self.task(name, description)
1202
+ tasks[name] = description
1203
+ order << name
1204
+ end
1205
+ task 'all' , "config, setup, test, install"
1206
+ task 'config' , "saves your configuration"
1207
+ task 'show' , "show current configuration"
1208
+ task 'make' , "compile ruby extentions"
1209
+ task 'test' , "run test suite"
1210
+ task 'doc' , "generate ri documentation"
1211
+ task 'install' , "install project files"
1212
+ task 'uninstall', "uninstall previously installed files"
1213
+ task 'clean' , "does `make clean' for each extention"
1214
+ task 'distclean', "does `make distclean' for each extention"
1215
+ def run(*argv)
1216
+ ARGV.replace(argv) unless argv.empty?
1217
+ task = ARGV.find{ |a| a !~ /^[-]/ }
1218
+ task = 'all' unless task
1219
+ unless task_names.include?(task)
1220
+ $stderr.puts "Not a valid task -- #{task}"
1221
+ exit 1
1222
+ end
1223
+ parser = OptionParser.new
1224
+ options = {}
1225
+ parser.banner = "Usage: #{File.basename($0)} [TASK] [OPTIONS]"
1226
+ optparse_header(parser, options)
1227
+ case task
1228
+ when 'all'
1229
+ optparse_all(parser, options)
1230
+ when 'config'
1231
+ optparse_config(parser, options)
1232
+ when 'install'
1233
+ optparse_install(parser, options)
1234
+ end
1235
+ optparse_common(parser, options)
1236
+ begin
1237
+ parser.parse!(ARGV)
1238
+ rescue OptionParser::InvalidOption
1239
+ $stderr.puts $!.to_s.capitalize
1240
+ exit 1
1241
+ end
1242
+ rootdir = session.project.rootdir
1243
+ print_header
1244
+ begin
1245
+ session.__send__(task)
1246
+ rescue Error
1247
+ raise if $DEBUG
1248
+ $stderr.puts $!.message
1249
+ $stderr.puts "Try 'setup.rb --help' for detailed usage."
1250
+ exit 1
1251
+ end
1252
+ puts unless session.quiet?
1253
+ end
1254
+ def session
1255
+ @session ||= Session.new(:io=>$stdout)
1256
+ end
1257
+ def configuration
1258
+ @configuration ||= session.configuration
1259
+ end
1260
+ def optparse_header(parser, options)
1261
+ parser.banner = "USAGE: #{File.basename($0)} [command] [options]"
1262
+ end
1263
+ def optparse_all(parser, options)
1264
+ optparse_config(parser, options)
1265
+ end
1266
+ def optparse_config(parser, options)
1267
+ parser.separator ""
1268
+ parser.separator "Configuration options:"
1269
+ configuration.options.each do |args|
1270
+ args = args.dup
1271
+ desc = args.pop
1272
+ type = args.pop
1273
+ name, shortcut = *args
1274
+ optname = name.to_s.gsub('_', '-')
1275
+ case type
1276
+ when :bool
1277
+ if optname.index('no-') == 0
1278
+ optname = "[no-]" + optname.sub(/^no-/, '')
1279
+ opts = shortcut ? ["-#{shortcut}", "--#{optname}", desc] : ["--#{optname}", desc]
1280
+ parser.on(*opts) do |val|
1281
+ configuration.__send__("#{name}=", !val)
1282
+ end
1283
+ else
1284
+ optname = "[no-]" + optname.sub(/^no-/, '')
1285
+ opts = shortcut ? ["-#{shortcut}", "--#{optname}", desc] : ["--#{optname}", desc]
1286
+ parser.on(*opts) do |val|
1287
+ configuration.__send__("#{name}=", val)
1288
+ end
1289
+ end
1290
+ else
1291
+ opts = shortcut ? ["-#{shortcut}", "--#{optname} #{type.to_s.upcase}", desc] : ["--#{optname} #{type.to_s.upcase}", desc]
1292
+ parser.on(*opts) do |val|
1293
+ configuration.__send__("#{name}=", val)
1294
+ end
1295
+ end
1296
+ end
1297
+ end
1298
+ def optparse_install(parser, options)
1299
+ parser.separator ""
1300
+ parser.separator "Install options:"
1301
+ parser.on("--prefix PATH", "Installation prefix") do |val|
1302
+ configuration.install_prefix = val
1303
+ end
1304
+ end
1305
+ def optparse_common(parser, options)
1306
+ parser.separator ""
1307
+ parser.separator "General options:"
1308
+ parser.on("-q", "--quiet", "Suppress output") do
1309
+ session.quiet = true
1310
+ end
1311
+ parser.on("-f", "--force", "Force operation") do
1312
+ session.force = true
1313
+ end
1314
+ parser.on("--trace", "--verbose", "Watch execution") do |val|
1315
+ session.trace = true
1316
+ end
1317
+ parser.on("--trial", "--no-harm", "Do not write to disk") do |val|
1318
+ session.trial = true
1319
+ end
1320
+ parser.on("--debug", "Turn on debug mode") do |val|
1321
+ $DEBUG = true
1322
+ end
1323
+ parser.separator ""
1324
+ parser.separator "Inform options:"
1325
+ parser.on_tail("-h", "--help", "display this help information") do
1326
+ puts parser
1327
+ exit
1328
+ end
1329
+ parser.on_tail("--version", "-v", "Show version") do
1330
+ puts File.basename($0) + ' v' + Setup::VERSION #Version.join('.')
1331
+ exit
1332
+ end
1333
+ parser.on_tail("--copyright", "Show copyright") do
1334
+ puts Setup::COPYRIGHT #opyright
1335
+ exit
1336
+ end
1337
+ end
1338
+ def task_names
1339
+ self.class.tasks.keys
1340
+ end
1341
+ def print_header
1342
+ end
1343
+ end
1344
+ end
1345
+ Setup::Command.run