reap 9.3.1 → 9.3.3

Sign up to get free protection for your applications and to get access to all the features.
File without changes
@@ -1,1486 +1,2 @@
1
- #!/usr/bin/env ruby
2
- require 'optparse'
3
- require 'rbconfig'
4
-
5
- # TODO: Is this the best way to do this? Is there any other way?
6
- PACKAGE = (
7
- if file = Dir['{.,meta/}unixname{,.txt}'].first
8
- File.read(file).strip
9
- else
10
- abort "Requires package unix-name. Edit .unixname or meta/unixname."
11
- end
12
- )
13
- GENERATE_DOCS = true # TODO: maybe just check if it already exists instead?
14
-
15
- # UberTask defines all the tasks one needs for the typical end-user
16
- # to configure, compile, test and install a package to their system.
17
-
18
- class UberTask
19
-
20
- attr_accessor :package
21
- attr_accessor :gendocs
22
-
23
- attr :config
24
-
25
- #
26
- def initialize(package_name, generate_docs=true) #:yield:
27
- @package = package_name
28
- @gendocs = generate_docs
29
- @config = Configure.new
30
- yield[self] if block_given?
31
- define
32
- end
33
-
34
- #
35
- def define
36
- # Default task will compile and test.
37
-
38
- task :default => [:setup, :test]
39
-
40
- #
41
- # TASK config
42
- #
43
-
44
- if File.exist?(Configure::FILENAME)
45
- desc "Reconfigure for your system."
46
- else
47
- desc "Configure for your system."
48
- end
49
-
50
- task :config do
51
- config.quiet = Rake.application.options.silent
52
- config.exec_config
53
- end
54
-
55
- #
56
-
57
- task :config_load do
58
- if File.file?('.config')
59
- config.load
60
- else
61
- abort "Run rake config first."
62
- end
63
- end
64
-
65
- #
66
- # TASK show
67
- #
68
-
69
- desc "Display current configuraiton."
70
- task :show do
71
- config.show
72
- end
73
-
74
- #
75
- # TASK clean & clobber
76
- #
77
-
78
- require 'rake/clean'
79
-
80
- CLOBBER.include(Configure::FILENAME)
81
- CLOBBER.include(Installer::MANIFEST)
82
- CLOBBER.include(File.join('doc', PACKAGE, 'rdoc')) if GENERATE_DOCS
83
-
84
- task :clean => [:makeclean]
85
- task :clobber => [:distclean]
86
-
87
- task :makeclean do
88
- config.extensions.each do |dir|
89
- Dir.chdir(dir) do
90
- config.make 'clean' if File.file?('Makefile')
91
- end
92
- end
93
- end
94
-
95
- task :distclean do
96
- config.extensions.each do |dir|
97
- Dir.chdir(dir) do
98
- config.make 'distclean' if File.file?('Makefile')
99
- end
100
- end
101
- end
102
-
103
- #
104
- # TASK all
105
- #
106
-
107
- if File.exist?('.config')
108
- desc "Setup, test, document and install."
109
- task :all => [:setup, :test, :doc, :index, :install]
110
- else
111
- # shortcut
112
- desc "Configure, setup, test, document and install."
113
- task :all => [:config, :setup, :test, :doc, :install]
114
- end
115
-
116
- #
117
- # TASK setup
118
- #
119
-
120
- # TODO: No shebang until it works at install time and doesn't overwrite the repo scripts.
121
-
122
- desc "Compile extensions." # update shebangs
123
- task :setup => [:config_load, :make] #, :shebang]
124
-
125
- task :make => [:config_load] do
126
- config.extensions.each do |ext|
127
- Dir.chdir(File.dirname(ext)) do
128
- config.make
129
- end
130
- end
131
- end
132
-
133
- task :shebang => [:config_load, :installer] do
134
- Dir.chdir('bin') do
135
- executables = Dir['*'].select{ |f| File.file?(f) }
136
- executables.each do |file|
137
- INSTALLER.update_shebang_line(file)
138
- end
139
- end
140
- end
141
-
142
- #
143
- # TASK test
144
- #
145
-
146
- # You can provide a .test file to add options to
147
- # the testrb command.
148
-
149
- desc "Run unit tests."
150
- task :test => [:config_load, :setup] do
151
- runner = config.testrunner
152
- # build testrb options
153
- opt = []
154
- opt << " -v" if verbose?
155
- opt << " --runner #{runner}"
156
- if File.exist?('.test')
157
- notests = false
158
- opt << File.read(".test").strip
159
- else
160
- notests = Dir["test/**/*.rb"].empty?
161
- opt << "-Ilib"
162
- opt << " test/**/*.rb"
163
- end
164
- opt = opt.flatten.join(' ').strip
165
- # run tests
166
- if notests
167
- $stderr.puts 'No tests.' #if verbose?
168
- else
169
- cmd = "#{config.rubyprog} -S testrb #{opt}"
170
- $stderr.puts cmd if verbose?
171
- sh cmd
172
- end
173
- end
174
-
175
- #
176
- # TASK doc
177
- #
178
-
179
- # If a .document file is available, it will be
180
- # used to compile the list of toplevel files
181
- # to document. (For some reason it doesn't use
182
- # the .document file on it's own.)
183
- #
184
- # Note that this places the rdoc in doc/name/rdoc,
185
- # So that they are subsequently installed to your
186
- # system by the installer. To prevent this use
187
- # the @without_doc@ config option.
188
-
189
- if GENERATE_DOCS
190
- desc "Generate html docs."
191
- task :doc => [:config_load] do
192
- output = File.join('doc', PACKAGE, 'rdoc')
193
- title = (PACKAGE.capitalize + " API").strip
194
- main = Dir.glob("README{,.txt}", File::FNM_CASEFOLD).first
195
- template = config.rdoctemplate || 'html'
196
-
197
- opt = []
198
- opt << "-U"
199
- opt << "-S"
200
- opt << "--op=#{output}"
201
- opt << "--template=#{template}"
202
- opt << "--title=#{title}"
203
- opt << "--main=#{main}" if main
204
-
205
- if File.exist?('.document')
206
- files = File.read('.document').split("\n")
207
- files.reject!{ |l| l =~ /^\s*[#]/ || l !~ /\S/ }
208
- files.collect!{ |f| f.strip }
209
- opt << files
210
- else
211
- opt << main if main
212
- opt << ["lib", "ext"]
213
- end
214
-
215
- opt = opt.flatten
216
-
217
- if no_harm?
218
- puts "rdoc #{opt.join(' ').strip}"
219
- else
220
- #sh "rdoc {opt.join(' ').strip}"
221
- require 'rdoc/rdoc'
222
- ::RDoc::RDoc.new.document(opt)
223
- end
224
- end
225
- else
226
- task :doc do
227
- end
228
- end
229
-
230
- #
231
- # TASK index
232
- #
233
-
234
- # This task generates and installs the ri docs to
235
- # the designated installdirs-based location.
236
- #
237
- # It is unfortunate that this isn't more like rdocing.
238
- # In that we can't first generate them, then install them.
239
- # We have to do it all at once. We may be able to fix this
240
- # later, but it requires special action by the installer,
241
- # so it will have to wait.
242
-
243
- desc "Generate and install index docs."
244
- task :index => [:config_load] do
245
- #name = PACKAGE
246
-
247
- case config.installdirs
248
- when 'std'
249
- output = "--ri-system"
250
- when 'site'
251
- output = "--ri-site"
252
- when 'home'
253
- output = "--ri"
254
- else
255
- abort "bad config: sould not be possible -- installdirs = #{config.installdirs}"
256
- end
257
-
258
- opt = []
259
-
260
- if File.exist?('.document')
261
- files = File.read('.document').split("\n")
262
- files.reject!{ |l| l =~ /^\s*[#]/ || l !~ /\S/ }
263
- files.collect!{ |f| f.strip }
264
- opt << files
265
- else
266
- opt << ["lib", "ext"]
267
- end
268
-
269
- opt << "-U"
270
- opt << output
271
- opt << files
272
- opt = opt.flatten
273
-
274
- if no_harm?
275
- puts "rdoc #{opt.join(' ').strip}"
276
- else
277
- #sh "rdoc #{opt.join(' ').strip}"
278
- require 'rdoc/rdoc'
279
- ::RDoc::RDoc.new.document(opt)
280
- end
281
- end
282
-
283
- #
284
- # TASK install & uninstall
285
- #
286
-
287
- # Install uses the installation procedures developed by Minero Aoki
288
- # for setup.rb. Over time it would be nice to "rakeify" these. Every
289
- # file installed is listed in the install manifest (.installedfiles).
290
- #
291
- # The uninstall task simply reads the install manifest, and removes
292
- # the files listed there from your system. Note, when you use the
293
- # clobber task, this file is removed. So be sure not to clobber,
294
- # if you pan to uninstall!
295
- #
296
- # TODO: Maybe the install manifest should never be clobber, expect
297
- # after an uninstall?
298
-
299
- desc "Install package files."
300
- task :install => [:config_load, :setup, :installer] do
301
- @installer.exec_install
302
- unless config.without_index?
303
- Rake::Task[:index].invoke
304
- end
305
- end
306
-
307
- if Installer.uninstallable?
308
- desc "Remove previously installed files."
309
- task :uninstall => [:confg_load, :installer] do
310
- @installer.exec_uninstall
311
- end
312
- end
313
-
314
- task :installer do
315
- @installer = Installer.new(config)
316
- @installer.verbose = env('verbose')
317
- @installer.no_harm = env('noharm')
318
- end
319
-
320
- #
321
- # TASK help
322
- #
323
-
324
- # Yea, we all need help some times ;)
325
-
326
- desc "Display config help information."
327
- task :help do
328
- puts Configure::HELP
329
- end
330
- end
331
-
332
- # Get environament variables.
333
-
334
- def env(*keys)
335
- key = keys.find{ |k| ENV[k.to_s] || ENV[k.to_s.downcase] || ENV[k.to_s.upcase] }
336
- ENV[key] if key
337
- end
338
-
339
- def verbose?
340
- env('verbose')
341
- end
342
-
343
- def no_harm?
344
- env('noharm','nowrite')
345
- end
346
-
347
- end
348
-
349
- # Configure class is used to generate the .config file
350
- # contining the settings used for installing a package.
351
- # These settings can be altered by the user if required
352
- # for their particular system, either via the command line
353
- # or environment variables.
354
-
355
- class Configure
356
-
357
- Version = [1,0,0]
358
- Copyright = "Copyright (c) 2008 Trans"
359
-
360
- Error = Class.new(StandardError)
361
-
362
- RBCONFIG = ::Config::CONFIG
363
- FILENAME = '.config'
364
-
365
- DESCRIPTIONS = [
366
- [:prefix , 'Path prefix of target environment'],
367
- [:bindir , 'Directory for commands'],
368
- [:libdir , 'Directory for libraries'],
369
- [:datadir , 'Directory for shared data'],
370
- [:mandir , 'Directory for man pages'],
371
- [:docdir , 'Directory for documentation'],
372
- [:sysconfdir , 'Directory for system configuration files'],
373
- [:localstatedir , 'Directory for local state data'],
374
- [:libruby , 'Directory for ruby libraries'],
375
- [:librubyver , 'Directory for standard ruby libraries'],
376
- [:librubyverarch , 'Directory for standard ruby extensions'],
377
- [:siteruby , 'Directory for version-independent aux ruby libraries'],
378
- [:siterubyver , 'Directory for aux ruby libraries'],
379
- [:siterubyverarch , 'Directory for aux ruby binaries'],
380
- [:rbdir , 'Directory for ruby scripts'],
381
- [:sodir , 'Directory for ruby extentions'],
382
- [:rubypath , 'Path to set to #! line'],
383
- [:rubyprog , 'Ruby program using for installation'],
384
- [:makeprog , 'Make program to compile ruby extentions'],
385
- [:without_ext , 'Do not compile/install ruby extentions'],
386
- [:without_doc , 'Do not install docs'],
387
- [:without_index , 'Do not generate ri docs'],
388
- [:shebang , 'Shebang line (#!) editing mode (all,ruby,never)'],
389
- [:installdirs , 'Install location mode (std,site,home)'],
390
- [:testrunner , 'Runner to use for testing (console|tk|gtk|gtk2)'],
391
- [:rdoctemplate , 'Document template to use (html)']
392
- ]
393
-
394
- # List of configurable options.
395
- OPTIONS = DESCRIPTIONS.collect{ |(k,v)| k.to_s }
396
-
397
- # Pathname attribute. Pathnames are automatically expanded
398
- # unless they start with '$', a path variable.
399
- def self.attr_pathname(name)
400
- class_eval %{
401
- def #{name}
402
- @#{name}.gsub(%r<\\$([^/]+)>){ self[$1] }
403
- end
404
- def #{name}=(path)
405
- raise Error, "bad config: #{name.to_s.upcase} requires argument" unless path
406
- @#{name} = (path[0,1] == '$' ? path : File.expand_path(path))
407
- end
408
- }
409
- end
410
-
411
- # List of pathnames. These are not expanded though.
412
- def self.attr_pathlist(name)
413
- class_eval %{
414
- def #{name}
415
- @#{name}
416
- end
417
- def #{name}=(pathlist)
418
- case pathlist
419
- when Array
420
- @#{name} = pathlist
421
- else
422
- @#{name} = pathlist.to_s.split(/[:;,]/)
423
- end
424
- end
425
- }
426
- end
427
-
428
- # Adds boolean support.
429
- def self.attr_accessor(*names)
430
- bools, attrs = names.partition{ |name| name.to_s =~ /\?$/ }
431
- attr_boolean *bools
432
- super *attrs
433
- end
434
-
435
- # Boolean attribute. Can be assigned true, false, nil, or
436
- # a string matching yes|true|y|t or no|false|n|f.
437
- def self.attr_boolean(*names)
438
- names.each do |name|
439
- name = name.to_s.chomp('?')
440
- attr_reader name # MAYBE: Deprecate
441
- code = %{
442
- def #{name}?; @#{name}; end
443
- def #{name}=(val)
444
- case val
445
- when true, false, nil
446
- @#{name} = val
447
- else
448
- case val.to_s.downcase
449
- when 'y', 'yes', 't', 'true'
450
- @#{name} = true
451
- when 'n', 'no', 'f', 'false'
452
- @#{name} = false
453
- else
454
- raise Error, "bad config: use #{name.upcase}=(yes|no) [\#{val}]"
455
- end
456
- end
457
- end
458
- }
459
- class_eval code
460
- end
461
- end
462
-
463
- # path prefix of target environment
464
- attr_pathname :prefix
465
-
466
- # directory for commands
467
- attr_pathname :bindir
468
-
469
- #directory for libraries
470
- attr_pathname :libdir
471
-
472
- # directory for shared data
473
- attr_pathname :datadir
474
-
475
- # directory for man pages
476
- attr_pathname :mandir
477
-
478
- # directory for documentation
479
- attr_pathname :docdir
480
-
481
- # directory for system configuration files
482
- attr_pathname :sysconfdir
483
-
484
- # directory for local state data
485
- attr_pathname :localstatedir
486
-
487
- # directory for ruby libraries
488
- attr_pathname :libruby
489
-
490
- # directory for standard ruby libraries
491
- attr_pathname :librubyver
492
-
493
- # directory for standard ruby extensions
494
- attr_pathname :librubyverarch
495
-
496
- # directory for version-independent aux ruby libraries
497
- attr_pathname :siteruby
498
-
499
- # directory for aux ruby libraries
500
- attr_pathname :siterubyver
501
-
502
- # directory for aux ruby binaries
503
- attr_pathname :siterubyverarch
504
-
505
- # directory for ruby scripts
506
- attr_pathname :rbdir
507
-
508
- # directory for ruby extentions
509
- attr_pathname :sodir
510
-
511
- # path to set to #! line
512
- attr_accessor :rubypath
513
-
514
- # ruby program using for installation
515
- attr_accessor :rubyprog
516
-
517
- # program to compile ruby extentions
518
- attr_accessor :makeprog
519
-
520
- # shebang line (#!) editing mode (all,ruby,never)', 'all/ruby/never
521
- attr_accessor :shebang
522
-
523
- # install location mode (std: libruby, site: site_ruby, home: $HOME)
524
- attr_accessor :installdirs
525
-
526
- # options to pass to extconfig.rb
527
- attr_accessor :config_opt
528
-
529
- # do not compile/install ruby extentions
530
- attr_accessor :without_ext?
531
-
532
- # do not compile/install ruby extentions
533
- attr_accessor :without_doc?
534
-
535
- # do not compile/install ruby extentions
536
- attr_accessor :without_index?
537
-
538
- # document template to use [html]
539
- attr_accessor :rdoctemplate
540
-
541
- # runner to use for testing (console|tk|gtk|gtk2)
542
- attr_accessor :testrunner
543
-
544
- # Run silently.
545
- attr_accessor :quiet?
546
-
547
- # shebang has only three options.
548
- def shebang=(val)
549
- if %w(all ruby never).include?(val)
550
- @shebang = val
551
- else
552
- raise Error, "bad config: use SHEBANG=(all|ruby|never) [#{val}]"
553
- end
554
- end
555
-
556
- # installdirs has only three options; and it has side-effects.
557
- def installdirs=(val)
558
- @installdirs = val
559
- case val.to_s
560
- when 'std'
561
- self.rbdir = '$librubyver'
562
- self.sodir = '$librubyverarch'
563
- when 'site'
564
- self.rbdir = '$siterubyver'
565
- self.sodir = '$siterubyverarch'
566
- when 'home'
567
- raise Error, 'HOME is not set.' unless ENV['HOME']
568
- self.prefix = ENV['HOME']
569
- self.rbdir = '$libdir/ruby'
570
- self.sodir = '$libdir/ruby'
571
- else
572
- raise Error, "bad config: use INSTALLDIRS=(std|site|home|local) [#{val}]"
573
- end
574
- end
575
-
576
- # Get configuration from environment.
577
- def getenv
578
- OPTIONS.each do |name|
579
- if value = ENV[name] || ENV[name.upcase]
580
- __send__("#{name}=",value)
581
- end
582
- end
583
- end
584
-
585
- # Load configuration.
586
- def load
587
- #if File.file?(FILENAME)
588
- begin
589
- File.foreach(FILENAME) do |line|
590
- k, v = *line.split(/=/, 2)
591
- __send__("#{k}=",v.strip) #self[k] = v.strip
592
- end
593
- rescue Errno::ENOENT
594
- raise Error, $!.message + "\n#{File.basename($0)} config first"
595
- end
596
- #end
597
- end
598
-
599
- # Save configuration.
600
- def save
601
- File.open(FILENAME, 'w') do |f|
602
- OPTIONS.each do |name|
603
- val = self[name]
604
- case val
605
- when Array
606
- f << "#{name}=#{val.join(';')}\n"
607
- else
608
- f << "#{name}=#{val}\n"
609
- end
610
- end
611
- end
612
- end
613
-
614
- def show
615
- fmt = "%-20s %s\n"
616
- OPTIONS.each do |name|
617
- value = self[name]
618
- printf fmt, name, __send__(name) if value
619
- end
620
- printf fmt, 'VERBOSE', verbose? ? 'yes' : 'no'
621
- printf fmt, 'NOHARM', no_harm? ? 'yes' : 'no'
622
- end
623
-
624
- # Get unresloved attribute.
625
- def [](name)
626
- instance_variable_get("@#{name}")
627
- end
628
-
629
- # Set attribute.
630
- def []=(name, value)
631
- instance_variable_set("@#{name}", value)
632
- end
633
-
634
- # Resolved attribute. (for paths)
635
- #def resolve(name)
636
- # self[name].gsub(%r<\\$([^/]+)>){ self[$1] }
637
- #end
638
-
639
- # New ConfigTable
640
- def initialize(values=nil)
641
- initialize_defaults
642
- if values
643
- values.each{ |k,v| __send__("#{k}=", v) }
644
- end
645
- yeild(self) if block_given?
646
- end
647
-
648
- # Assign CONFIG defaults
649
- #
650
- # TODO: Does this handle 'nmake' on windows?
651
-
652
- def initialize_defaults
653
- prefix = RBCONFIG['prefix']
654
-
655
- rubypath = File.join(RBCONFIG['bindir'], RBCONFIG['ruby_install_name'] + RBCONFIG['EXEEXT'])
656
-
657
- # V > 1.6.3
658
- libruby = "#{prefix}/lib/ruby"
659
- librubyver = RBCONFIG['rubylibdir']
660
- librubyverarch = RBCONFIG['archdir']
661
- siteruby = RBCONFIG['sitedir']
662
- siterubyver = RBCONFIG['sitelibdir']
663
- siterubyverarch = RBCONFIG['sitearchdir']
664
-
665
- if arg = RBCONFIG['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg }
666
- makeprog = arg.sub(/'/, '').split(/=/, 2)[1]
667
- else
668
- makeprog = 'make'
669
- end
670
-
671
- parameterize = lambda do |path|
672
- val = RBCONFIG[path]
673
- val.sub(/\A#{Regexp.quote(prefix)}/, '$prefix')
674
- end
675
-
676
- self.prefix = prefix
677
- self.bindir = parameterize['bindir']
678
- self.libdir = parameterize['libdir']
679
- self.datadir = parameterize['datadir']
680
- self.mandir = parameterize['mandir']
681
- self.docdir = File.dirname(parameterize['docdir']) # b/c of trailing $(PACKAGE)
682
- self.sysconfdir = parameterize['sysconfdir']
683
- self.localstatedir = parameterize['localstatedir']
684
- self.libruby = libruby
685
- self.librubyver = librubyver
686
- self.librubyverarch = librubyverarch
687
- self.siteruby = siteruby
688
- self.siterubyver = siterubyver
689
- self.siterubyverarch = siterubyverarch
690
- self.rbdir = '$siterubyver'
691
- self.sodir = '$siterubyverarch'
692
- self.rubypath = rubypath
693
- self.rubyprog = rubypath
694
- self.makeprog = makeprog
695
- self.shebang = 'ruby'
696
- self.without_ext = 'no'
697
- self.without_doc = 'no'
698
- self.without_index = 'no'
699
- self.installdirs = 'site'
700
- self.rdoctemplate = 'html'
701
- self.testrunner = 'console'
702
- end
703
-
704
- def show
705
- fmt = "%-20s %s\n"
706
- OPTIONS.each do |name|
707
- value = self[name]
708
- printf fmt, name, __send__(name)
709
- end
710
- end
711
-
712
- #
713
- def exec_config
714
- getenv
715
- save
716
- create_makefiles if compiles?
717
- create_rakefile
718
- show unless quiet?
719
- puts "Configuration saved."
720
- end
721
-
722
- def extconfs
723
- @extconfs ||= Dir['ext/**/extconf.rb']
724
- end
725
-
726
- def extensions
727
- @extensions ||= extconfs.collect{ |f| File.dirname(f) }
728
- end
729
-
730
- def compiles?
731
- !extensions.empty?
732
- end
733
-
734
- def create_makefiles
735
- extensions.each do |dir|
736
- Dir.chdir(dir) do
737
- ruby File.basename(file), config_opt
738
- end
739
- end
740
- end
741
-
742
- # Create rakefile, if it doesn't exist.
743
- def create_rakefile
744
- unless Dir['[Rr]akefile{,.rb}'].first
745
- File.open('Rakefile', 'w') do |f|
746
- f << DATA.read
747
- end
748
- end
749
- end
750
-
751
- private
752
-
753
- def ruby(*args)
754
- command rubyprog, *args
755
- end
756
-
757
- def make(task = nil)
758
- command(*[makeprog, task].compact)
759
- end
760
-
761
- def command(*args)
762
- $stderr.puts args.join(' ') if $DEBUG
763
- system(*args) or raise RuntimeError, "system(#{args.map{|a| a.inspect }.join(' ')}) failed"
764
- end
765
-
766
- # Help output.
767
-
768
- HELP = <<-END
769
- The Uber Rakefile v#{Version.join('.')}
770
-
771
- Usage:
772
-
773
- #{File.basename($0)} [options]
774
-
775
- The Uber Rakefile is designed to install a Ruby package. It does this by breaking
776
- the steps involved down into individual rake tasks. This gives the installer the
777
- opportunity to adjust installation settings as required for a particular
778
- platform. A typical installation procedure is:
779
-
780
- $ rake config
781
- $ rake setup
782
- $ rake install
783
-
784
- If you are certain of the default configuration settings (which are usually correct),
785
- you can use the simple shortcut:
786
-
787
- $ rake all
788
-
789
- See rake -T for all available tasks.
790
-
791
- Below is the list of options available for the config task.
792
-
793
- Configuration options:
794
- END
795
-
796
- fmt = " %-20s %s\n"
797
- DESCRIPTIONS.each do |name, desc|
798
- HELP << fmt % ["#{name}", desc]
799
- end
800
-
801
- HELP << <<-END
802
-
803
- Other options:
804
- verbose Provide extra ouput
805
- nowrite Do not write to disk.
806
- noharm Same as nowrite.
807
-
808
- Installdirs options correspond to: libruby, site_ruby and $HOME repsectively.
809
-
810
- END
811
-
812
- # Other options:
813
- # -q --quiet Run silently
814
- # -h --help Display this help information
815
- # --version Show version
816
- # --copyright Show copyright
817
- #
818
- # END
819
-
820
- HELP.gsub!(/^\ \ /,'')
821
-
822
- # CLI runner. This uses OptionParser to parse
823
- # command line arguments. (May chnage to GetoptLong).
824
-
825
- def self.start_cli
826
- config = new
827
-
828
- opts = OptionParser.new
829
-
830
- DESCRIPTIONS.each do |name, desc|
831
- opts.on("--#{name}", desc) do |val|
832
- ENV[name.upcase] = val
833
- end
834
- end
835
-
836
- # Tail options (eg. commands in option form)
837
-
838
- opts.on("-q", "--quiet", "Run silently") do |val|
839
- config.quiet = true
840
- end
841
-
842
- opts.on_tail("-h", "--help", "Display help information") do
843
- puts HELP
844
- exit
845
- end
846
-
847
- opts.on_tail("--version", "Show version") do
848
- puts File.basename($0) + ' v' + Setup::Version.join('.')
849
- exit
850
- end
851
-
852
- opts.on_tail("--copyright", "Show copyright") do
853
- puts Setup::Copyright
854
- exit
855
- end
856
-
857
- begin
858
- opts.parse!(ARGV)
859
- rescue OptionParser::InvalidOption
860
- $stderr.puts $!.capitalize
861
- exit 1
862
- end
863
-
864
- begin
865
- config.exec_config
866
- rescue Configure::Error
867
- raise if $DEBUG
868
- $stderr.puts $!.message
869
- $stderr.puts "Try 'ruby #{$0} --help' for detailed usage."
870
- exit 1
871
- end
872
- end
873
-
874
- end
875
-
876
- # Command line run
877
- if __FILE__ == $0
878
- Configure.start_cli
879
- end
880
-
881
- #
882
- #
883
- #
884
-
885
- class Installer
886
-
887
- MANIFEST = '.installedfiles'
888
-
889
- FILETYPES = %w( bin lib ext data conf man doc )
890
-
891
- # Has this been installed previously?
892
- def self.uninstallable?
893
- File.exist?(MANIFEST)
894
- end
895
-
896
- # Configuration
897
- attr :config
898
-
899
- attr_writer :no_harm
900
- attr_writer :verbose
901
-
902
- attr_accessor :install_prefix
903
-
904
- # New Installer.
905
- def initialize(config) #:yield:
906
- srcroot = '.'
907
- objroot = '.'
908
-
909
- @config = config
910
-
911
- @srcdir = File.expand_path(srcroot)
912
- @objdir = File.expand_path(objroot)
913
- @currdir = '.'
914
-
915
- @verbose = false
916
-
917
- #self.verbose = ENV['VERBOSE'] if ENV['VERBOSE']
918
- #self.no_harm = ENV['NO_HARM'] if ENV['NO_HARM']
919
-
920
- yield(self) if block_given?
921
- end
922
-
923
- def inspect
924
- "#<#{self.class} #{File.basename(@srcdir)}>"
925
- end
926
-
927
- # Do not write to disk.
928
- def no_harm? ; @no_harm; end
929
-
930
- # Verbose output?
931
- def verbose? ; @verbose || @no_harm; end
932
-
933
- # Yes, very very verbose output.
934
- def very_verbose? ; @very_verbose; end
935
-
936
- def verbose_off #:yield:
937
- begin
938
- save, @verbose = verbose?, false
939
- yield
940
- ensure
941
- @verbose = save
942
- end
943
- end
944
-
945
- # Are we running an installation?
946
- def installation?; @installation; end
947
- def installation!; @installation = true; end
948
-
949
- #
950
- # Hook Script API bases
951
- #
952
-
953
- def srcdir_root
954
- @srcdir
955
- end
956
-
957
- def objdir_root
958
- @objdir
959
- end
960
-
961
- def relpath
962
- @currdir
963
- end
964
-
965
- # Used as a null traversal.
966
- def noop(rel) ; end
967
-
968
- def update_shebang_line(path)
969
- return if no_harm?
970
- return if config.shebang == 'never'
971
- old = Shebang.load(path)
972
- if old
973
- if old.args.size > 1
974
- $stderr.puts "warning: #{path}"
975
- $stderr.puts "Shebang line has too many args."
976
- $stderr.puts "It is not portable and your program may not work."
977
- end
978
- new = new_shebang(old)
979
- return if new.to_s == old.to_s
980
- else
981
- return unless config.shebang == 'all'
982
- new = Shebang.new(config.rubypath)
983
- end
984
- $stderr.puts "updating shebang: #{File.basename(path)}" if verbose?
985
- open_atomic_writer(path) {|output|
986
- File.open(path, 'rb') {|f|
987
- f.gets if old # discard
988
- output.puts new.to_s
989
- output.print f.read
990
- }
991
- }
992
- end
993
-
994
- def new_shebang(old)
995
- if /\Aruby/ =~ File.basename(old.cmd)
996
- Shebang.new(config.rubypath, old.args)
997
- elsif File.basename(old.cmd) == 'env' and old.args.first == 'ruby'
998
- Shebang.new(config.rubypath, old.args[1..-1])
999
- else
1000
- return old unless config.shebang == 'all'
1001
- Shebang.new(config.rubypath)
1002
- end
1003
- end
1004
-
1005
- def open_atomic_writer(path, &block)
1006
- tmpfile = File.basename(path) + '.tmp'
1007
- begin
1008
- File.open(tmpfile, 'wb', &block)
1009
- File.rename tmpfile, File.basename(path)
1010
- ensure
1011
- File.unlink tmpfile if File.exist?(tmpfile)
1012
- end
1013
- end
1014
-
1015
- class Shebang
1016
- def Shebang.load(path)
1017
- line = nil
1018
- File.open(path) {|f|
1019
- line = f.gets
1020
- }
1021
- return nil unless /\A#!/ =~ line
1022
- parse(line)
1023
- end
1024
-
1025
- def Shebang.parse(line)
1026
- cmd, *args = *line.strip.sub(/\A\#!/, '').split(' ')
1027
- new(cmd, args)
1028
- end
1029
-
1030
- def initialize(cmd, args = [])
1031
- @cmd = cmd
1032
- @args = args
1033
- end
1034
-
1035
- attr_reader :cmd
1036
- attr_reader :args
1037
-
1038
- def to_s
1039
- "#! #{@cmd}" + (@args.empty? ? '' : " #{@args.join(' ')}")
1040
- end
1041
- end
1042
-
1043
- #
1044
- # TASK install
1045
- #
1046
-
1047
- def exec_install
1048
- installation! # mark that we are installing
1049
- #rm_f MANIFEST # we'll append rather then delete
1050
- exec_task_traverse 'install'
1051
- end
1052
-
1053
- def install_dir_bin(rel)
1054
- install_files targetfiles(), "#{config.bindir}/#{rel}", 0755
1055
- end
1056
-
1057
- def install_dir_lib(rel)
1058
- install_files libfiles(), "#{config.rbdir}/#{rel}", 0644
1059
- end
1060
-
1061
- def install_dir_ext(rel)
1062
- return unless extdir?(curr_srcdir())
1063
- install_files rubyextentions('.'),
1064
- "#{config.sodir}/#{File.dirname(rel)}", 0555
1065
- end
1066
-
1067
- def install_dir_data(rel)
1068
- install_files targetfiles(), "#{config.datadir}/#{rel}", 0644
1069
- end
1070
-
1071
- def install_dir_doc(rel)
1072
- return if config.without_doc?
1073
- install_files targetfiles(), "#{config.docdir}/#{rel}", 0644
1074
- end
1075
-
1076
- def install_dir_conf(rel)
1077
- # FIXME: should not remove current config files
1078
- # (rename previous file to .old/.org)
1079
- install_files targetfiles(), "#{config.sysconfdir}/#{rel}", 0644
1080
- end
1081
-
1082
- def install_dir_man(rel)
1083
- install_files targetfiles(), "#{config.mandir}/#{rel}", 0644
1084
- end
1085
-
1086
- def install_files(list, dest, mode)
1087
- mkdir_p dest, install_prefix
1088
- list.each do |fname|
1089
- install fname, dest, mode, install_prefix
1090
- end
1091
- end
1092
-
1093
- def libfiles
1094
- glob_reject(%w(*.y *.output), targetfiles())
1095
- end
1096
-
1097
- def rubyextentions(dir)
1098
- ents = glob_select("*.#{dllext}", targetfiles())
1099
- if ents.empty?
1100
- setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first"
1101
- end
1102
- ents
1103
- end
1104
-
1105
- def dllext
1106
- RBCONFIG['DLEXT']
1107
- end
1108
-
1109
- def targetfiles
1110
- mapdir(existfiles() - hookfiles())
1111
- end
1112
-
1113
- def mapdir(ents)
1114
- ents.map {|ent|
1115
- if File.exist?(ent)
1116
- then ent # objdir
1117
- else "#{curr_srcdir()}/#{ent}" # srcdir
1118
- end
1119
- }
1120
- end
1121
-
1122
- # picked up many entries from cvs-1.11.1/src/ignore.c
1123
- JUNK_FILES = %w(
1124
- core RCSLOG tags TAGS .make.state
1125
- .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb
1126
- *~ *.old *.bak *.BAK *.orig *.rej _$* *$
1127
-
1128
- *.org *.in .*
1129
- )
1130
-
1131
- def existfiles
1132
- glob_reject(JUNK_FILES, (files_of(curr_srcdir()) | files_of('.')))
1133
- end
1134
-
1135
- def hookfiles
1136
- %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt|
1137
- %w( config setup install clean ).map {|t| sprintf(fmt, t) }
1138
- }.flatten
1139
- end
1140
-
1141
- def glob_select(pat, ents)
1142
- re = globs2re([pat])
1143
- ents.select {|ent| re =~ ent }
1144
- end
1145
-
1146
- def glob_reject(pats, ents)
1147
- re = globs2re(pats)
1148
- ents.reject {|ent| re =~ ent }
1149
- end
1150
-
1151
- GLOB2REGEX = {
1152
- '.' => '\.',
1153
- '$' => '\$',
1154
- '#' => '\#',
1155
- '*' => '.*'
1156
- }
1157
-
1158
- def globs2re(pats)
1159
- /\A(?:#{
1160
- pats.map {|pat| pat.gsub(/[\.\$\#\*]/) {|ch| GLOB2REGEX[ch] } }.join('|')
1161
- })\z/
1162
- end
1163
-
1164
- #
1165
- # TASK uninstall
1166
- #
1167
-
1168
- def exec_uninstall
1169
- files = File.read(MANIFEST).split("\n")
1170
- files.each do |file|
1171
- next if /^\#/ =~ file # skip comments
1172
- rm_f(file) if File.exist?(file)
1173
- end
1174
- end
1175
-
1176
- #
1177
- # Traversing
1178
- #
1179
-
1180
- #
1181
- def exec_task_traverse(task)
1182
- run_hook "pre-#{task}"
1183
- FILETYPES.each do |type|
1184
- if type == 'ext' and config.without_ext == 'yes'
1185
- $stderr.puts 'skipping ext/* by user option' if verbose?
1186
- next
1187
- end
1188
- traverse task, type, "#{task}_dir_#{type}"
1189
- end
1190
- run_hook "post-#{task}"
1191
- end
1192
-
1193
- #
1194
- def traverse(task, rel, mid)
1195
- dive_into(rel) {
1196
- run_hook "pre-#{task}"
1197
- __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '')
1198
- directories_of(curr_srcdir()).each do |d|
1199
- traverse task, "#{rel}/#{d}", mid
1200
- end
1201
- run_hook "post-#{task}"
1202
- }
1203
- end
1204
-
1205
- #
1206
- def dive_into(rel)
1207
- return unless File.dir?("#{@srcdir}/#{rel}")
1208
-
1209
- dir = File.basename(rel)
1210
- Dir.mkdir dir unless File.dir?(dir)
1211
- prevdir = Dir.pwd
1212
- Dir.chdir dir
1213
- $stderr.puts '---> ' + rel if very_verbose?
1214
- @currdir = rel
1215
- yield
1216
- Dir.chdir prevdir
1217
- $stderr.puts '<--- ' + rel if very_verbose?
1218
- @currdir = File.dirname(rel)
1219
- end
1220
-
1221
- #
1222
- def run_hook(id)
1223
- path = [ "#{curr_srcdir()}/#{id}",
1224
- "#{curr_srcdir()}/#{id}.rb" ].detect {|cand| File.file?(cand) }
1225
- return unless path
1226
- begin
1227
- instance_eval File.read(path), path, 1
1228
- rescue
1229
- raise if $DEBUG
1230
- setup_rb_error "hook #{path} failed:\n" + $!.message
1231
- end
1232
- end
1233
-
1234
- # File Operations
1235
- #
1236
- # These use: #verbose? and #no_harm?
1237
-
1238
- def binread(fname)
1239
- File.open(fname, 'rb'){ |f|
1240
- return f.read
1241
- }
1242
- end
1243
-
1244
- def mkdir_p(dirname, prefix = nil)
1245
- dirname = prefix + File.expand_path(dirname) if prefix
1246
- $stderr.puts "mkdir -p #{dirname}" if verbose?
1247
- return if no_harm?
1248
-
1249
- # Does not check '/', it's too abnormal.
1250
- dirs = File.expand_path(dirname).split(%r<(?=/)>)
1251
- if /\A[a-z]:\z/i =~ dirs[0]
1252
- disk = dirs.shift
1253
- dirs[0] = disk + dirs[0]
1254
- end
1255
- dirs.each_index do |idx|
1256
- path = dirs[0..idx].join('')
1257
- Dir.mkdir path unless File.dir?(path)
1258
- end
1259
- end
1260
-
1261
- def rm_f(path)
1262
- $stderr.puts "rm -f #{path}" if verbose?
1263
- return if no_harm?
1264
- force_remove_file path
1265
- end
1266
-
1267
- def rm_rf(path)
1268
- $stderr.puts "rm -rf #{path}" if verbose?
1269
- return if no_harm?
1270
- remove_tree path
1271
- end
1272
-
1273
- def remove_tree(path)
1274
- if File.symlink?(path)
1275
- remove_file path
1276
- elsif File.dir?(path)
1277
- remove_tree0 path
1278
- else
1279
- force_remove_file path
1280
- end
1281
- end
1282
-
1283
- def remove_tree0(path)
1284
- Dir.foreach(path) do |ent|
1285
- next if ent == '.'
1286
- next if ent == '..'
1287
- entpath = "#{path}/#{ent}"
1288
- if File.symlink?(entpath)
1289
- remove_file entpath
1290
- elsif File.dir?(entpath)
1291
- remove_tree0 entpath
1292
- else
1293
- force_remove_file entpath
1294
- end
1295
- end
1296
- begin
1297
- Dir.rmdir path
1298
- rescue Errno::ENOTEMPTY
1299
- # directory may not be empty
1300
- end
1301
- end
1302
-
1303
- def move_file(src, dest)
1304
- force_remove_file dest
1305
- begin
1306
- File.rename src, dest
1307
- rescue
1308
- File.open(dest, 'wb') {|f|
1309
- f.write binread(src)
1310
- }
1311
- File.chmod File.stat(src).mode, dest
1312
- File.unlink src
1313
- end
1314
- end
1315
-
1316
- def force_remove_file(path)
1317
- begin
1318
- remove_file path
1319
- rescue
1320
- end
1321
- end
1322
-
1323
- def remove_file(path)
1324
- File.chmod 0777, path
1325
- File.unlink path
1326
- end
1327
-
1328
- def install(from, dest, mode, prefix = nil)
1329
- $stderr.puts "install #{from} #{dest}" if verbose?
1330
- return if no_harm?
1331
-
1332
- realdest = prefix ? prefix + File.expand_path(dest) : dest
1333
- realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest)
1334
- str = binread(from)
1335
- if diff?(str, realdest)
1336
- verbose_off {
1337
- rm_f realdest if File.exist?(realdest)
1338
- }
1339
- File.open(realdest, 'wb') {|f|
1340
- f.write str
1341
- }
1342
- File.chmod mode, realdest
1343
-
1344
- File.open("#{objdir_root()}/#{MANIFEST}", 'a') {|f|
1345
- if prefix
1346
- f.puts realdest.sub(prefix, '')
1347
- else
1348
- f.puts realdest
1349
- end
1350
- }
1351
- end
1352
- end
1353
-
1354
- def diff?(new_content, path)
1355
- return true unless File.exist?(path)
1356
- new_content != binread(path)
1357
- end
1358
-
1359
- def command(*args)
1360
- $stderr.puts args.join(' ') if verbose?
1361
- system(*args) or raise RuntimeError,
1362
- "system(#{args.map{|a| a.inspect }.join(' ')}) failed"
1363
- end
1364
-
1365
- def ruby(*args)
1366
- command config.rubyprog, *args
1367
- end
1368
-
1369
- def make(task = nil)
1370
- command(*[config.makeprog, task].compact)
1371
- end
1372
-
1373
- def extdir?(dir)
1374
- File.exist?("#{dir}/MANIFEST") or File.exist?("#{dir}/extconf.rb")
1375
- end
1376
-
1377
- def files_of(dir)
1378
- Dir.open(dir) {|d|
1379
- return d.select {|ent| File.file?("#{dir}/#{ent}") }
1380
- }
1381
- end
1382
-
1383
- DIR_REJECT = %w( . .. CVS SCCS RCS CVS.adm .svn )
1384
-
1385
- def directories_of(dir)
1386
- Dir.open(dir) {|d|
1387
- return d.select {|ent| File.dir?("#{dir}/#{ent}") } - DIR_REJECT
1388
- }
1389
- end
1390
-
1391
- #
1392
- # Hook Script API
1393
- #
1394
- # These require: #srcdir_root, #objdir_root, #relpath
1395
- #
1396
-
1397
- #
1398
- def get_config(key)
1399
- config.__send__(key)
1400
- end
1401
-
1402
- # obsolete: use metaconfig to change configuration
1403
- # TODO: what to do with?
1404
- def set_config(key, val)
1405
- config[key] = val
1406
- end
1407
-
1408
- #
1409
- # srcdir/objdir (works only in the package directory)
1410
- #
1411
-
1412
- def curr_srcdir
1413
- "#{srcdir_root()}/#{relpath()}"
1414
- end
1415
-
1416
- def curr_objdir
1417
- "#{objdir_root()}/#{relpath()}"
1418
- end
1419
-
1420
- def srcfile(path)
1421
- "#{curr_srcdir()}/#{path}"
1422
- end
1423
-
1424
- def srcexist?(path)
1425
- File.exist?(srcfile(path))
1426
- end
1427
-
1428
- def srcdirectory?(path)
1429
- File.dir?(srcfile(path))
1430
- end
1431
-
1432
- def srcfile?(path)
1433
- File.file?(srcfile(path))
1434
- end
1435
-
1436
- def srcentries(path = '.')
1437
- Dir.open("#{curr_srcdir()}/#{path}") {|d|
1438
- return d.to_a - %w(. ..)
1439
- }
1440
- end
1441
-
1442
- def srcfiles(path = '.')
1443
- srcentries(path).select {|fname|
1444
- File.file?(File.join(curr_srcdir(), path, fname))
1445
- }
1446
- end
1447
-
1448
- def srcdirectories(path = '.')
1449
- srcentries(path).select {|fname|
1450
- File.dir?(File.join(curr_srcdir(), path, fname))
1451
- }
1452
- end
1453
-
1454
- end
1455
-
1456
- #
1457
- # Ruby extensions
1458
- #
1459
-
1460
- unless File.respond_to?(:read) # Ruby 1.6 and less
1461
- def File.read(fname)
1462
- open(fname) {|f|
1463
- return f.read
1464
- }
1465
- end
1466
- end
1467
-
1468
- unless Errno.const_defined?(:ENOTEMPTY) # Windows?
1469
- module Errno
1470
- class ENOTEMPTY
1471
- # We do not raise this exception, implementation is not needed.
1472
- end
1473
- end
1474
- end
1475
-
1476
- # for corrupted Windows' stat(2)
1477
- def File.dir?(path)
1478
- File.directory?((path[-1,1] == '/') ? path : path + '/')
1479
- end
1480
-
1481
- #
1482
- # The End
1483
- #
1484
-
1485
- UberTask.new(PACKAGE, GENERATE_DOCS)
1
+ require File.join(File.dirname(__FILE__), "setup.rb")
1486
2