reap 9.2.1 → 9.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. data/CHANGES +4 -0
  2. data/COPYING +675 -674
  3. data/MANIFEST +37 -44
  4. data/NOTES +4 -4
  5. data/Rakefile +1486 -0
  6. data/data/reap/base/COPYING +674 -674
  7. data/data/reap/base/README +23 -2
  8. data/data/reap/base/Rakefile +1486 -0
  9. data/data/reap/base/test/template.rb +16 -0
  10. data/data/reap/init/meta/project.yaml +19 -14
  11. data/lib/reap/default.yaml +57 -45
  12. data/lib/reap/extensions/file.rb +8 -0
  13. data/lib/reap/extensions/net/smtp_tls.rb +108 -0
  14. data/lib/reap/extensions.rb +2 -0
  15. data/lib/reap/metadata.rb +3 -2
  16. data/lib/reap/{manager → project}/announce.rb +3 -3
  17. data/lib/reap/{manager → project}/check.rb +1 -1
  18. data/lib/reap/{manager → project}/clean.rb +1 -1
  19. data/lib/reap/{manager → project}/gem.rb +5 -5
  20. data/lib/reap/{manager → project}/html.rb +25 -24
  21. data/lib/reap/{manager → project}/log.rb +19 -9
  22. data/lib/reap/{manager → project}/make.rb +29 -36
  23. data/lib/reap/{manager → project}/package.rb +4 -8
  24. data/lib/reap/{manager → project}/publish.rb +3 -3
  25. data/lib/reap/{manager → project}/rdoc.rb +13 -30
  26. data/lib/reap/{manager → project}/release.rb +5 -5
  27. data/lib/reap/{manager → project}/rubyforge.rb +7 -6
  28. data/lib/reap/{manager → project}/scaffold.rb +7 -2
  29. data/lib/reap/{manager → project}/scm.rb +3 -3
  30. data/lib/reap/{manager → project}/site.rb +1 -1
  31. data/lib/reap/{manager → project}/spec.rb +1 -1
  32. data/lib/reap/{manager → project}/stamp.rb +14 -11
  33. data/lib/reap/{manager → project}/stats.rb +1 -1
  34. data/lib/reap/{manager → project}/svn.rb +1 -1
  35. data/lib/reap/{manager → project}/test.rb +2 -20
  36. data/lib/reap/project.rb +34 -2
  37. data/lib/reap/systems/rubyforge.rb +5 -12
  38. data/lib/reap/systems/subversion.rb +4 -6
  39. data/lib/reap/{utilities/fileutils.rb → utilities.rb} +148 -60
  40. data/log/Changelog.txt +118 -0
  41. data/log/Fixme.txt +26 -0
  42. data/log/Todo.txt +94 -0
  43. data/meta/VERSION +1 -1
  44. data/meta/project.yaml +1 -1
  45. data/meta/unixname +1 -0
  46. data/test/unit/lib/reap/extensions/test_array.rb +12 -0
  47. metadata +44 -46
  48. data/data/reap/build/rake/Rakefile +0 -130
  49. data/data/reap/build/rake/setup.rb +0 -1616
  50. data/data/reap/build/rake-lite/install.rb +0 -79
  51. data/data/reap/build/tasks/task/rdoc +0 -211
  52. data/data/reap/build/tasks/task/setup +0 -1616
  53. data/data/reap/build/tasks/task/test +0 -38
  54. data/lib/reap/manager.rb +0 -75
  55. data/lib/reap/utilities/netutils.rb +0 -221
  56. data/lib/reap/utilities/setuputils.rb +0 -124
  57. data/lib/reap/utilities/shellutils.rb +0 -175
  58. data/log/FIXME.txt +0 -25
  59. data/log/TODO.txt +0 -72
  60. data/task/man +0 -14
  61. data/task/rdoc +0 -20
  62. data/task/setup +0 -1616
@@ -0,0 +1,1486 @@
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)
1486
+