reap 9.3.5 → 9.4.0

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