reap 9.3.1 → 9.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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