setup 4.2.0 → 5.0.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 (55) hide show
  1. data/HISTORY +47 -3
  2. data/MANIFEST +49 -16
  3. data/README.rdoc +148 -0
  4. data/bin/setup.rb +1 -5
  5. data/lib/setup.rb +2 -2
  6. data/lib/setup/base.rb +143 -0
  7. data/lib/setup/command.rb +218 -114
  8. data/lib/setup/compiler.rb +69 -0
  9. data/lib/setup/configuration.rb +822 -0
  10. data/lib/setup/constants.rb +12 -0
  11. data/lib/setup/{rubyver.rb → core_ext.rb} +0 -0
  12. data/lib/setup/documentor.rb +149 -0
  13. data/lib/setup/installer.rb +363 -0
  14. data/lib/setup/project.rb +68 -0
  15. data/lib/setup/rake.rb +44 -45
  16. data/lib/setup/session.rb +233 -0
  17. data/lib/setup/tester.rb +92 -0
  18. data/lib/setup/uninstaller.rb +76 -0
  19. data/meta/active +1 -0
  20. data/meta/collection +1 -0
  21. data/meta/{abstract → description} +0 -0
  22. data/meta/{package → name} +0 -0
  23. data/meta/repository +1 -0
  24. data/meta/ruby +3 -0
  25. data/meta/version +1 -1
  26. data/script/bstrap +5 -0
  27. data/script/bundle +64 -0
  28. data/script/setup +1338 -0
  29. data/script/test +3 -0
  30. data/test/cases/installer.rb +28 -0
  31. data/test/features/config.feature +16 -0
  32. data/test/features/document.feature +2 -0
  33. data/test/features/install.feature +72 -0
  34. data/test/features/make.feature +18 -0
  35. data/test/features/step_definitions/common_steps.rb +34 -0
  36. data/test/features/step_definitions/config_steps.rb +24 -0
  37. data/test/features/step_definitions/env.rb +37 -0
  38. data/test/features/step_definitions/install_steps.rb +75 -0
  39. data/test/features/step_definitions/setup_steps.rb +30 -0
  40. data/test/features/step_definitions/uninstall_steps.rb +8 -0
  41. data/test/features/test.feature +2 -0
  42. data/test/features/uninstall.feature +13 -0
  43. data/test/fixtures/faux-project/bin/faux +3 -0
  44. data/test/fixtures/faux-project/ext/faux/extconf.rb +12 -0
  45. data/test/fixtures/faux-project/ext/faux/faux.c +24 -0
  46. data/test/fixtures/faux-project/lib/faux.rb +1 -0
  47. metadata +58 -29
  48. data/README +0 -106
  49. data/RELEASE +0 -41
  50. data/lib/setup/build.rb +0 -2
  51. data/lib/setup/config.rb +0 -452
  52. data/lib/setup/error.rb +0 -4
  53. data/lib/setup/install.rb +0 -1007
  54. data/meta/setup/metaconfig.rb +0 -3
  55. data/test/test_installer.rb +0 -139
@@ -1,4 +0,0 @@
1
- module Setup
2
- class Error < StandardError; end
3
- end
4
-
@@ -1,1007 +0,0 @@
1
- require 'optparse'
2
- require 'setup/config'
3
-
4
- # TODO: we need to abort install if tests fail (check return code of TESTER)
5
- # We will also need to add a force install option then to by pass failed tests.
6
- #
7
- # TODO: Generate rdocs... Package developer may want to deactivate this. How?
8
- #
9
- # TODO: Should be using Rdoc programmatically, but load issue arose and an error
10
- # was being generated on ri generation. Reverting back to shelling out for now.
11
-
12
- # The name of the package, used to install docs in system doc/ruby-{name}/ location.
13
- # The information must be provided in a file called meta/package.
14
- PACKAGE =(
15
- if file = Dir["{meta,.meta}/package"].first
16
- File.read(file).strip
17
- else
18
- nil
19
- end
20
- )
21
-
22
- # A ruby script that instructs setup how to run tests, located at meta/setup/test.rb
23
- # If the tests fail, the script should exit with a fail status (eg. -1).
24
- TESTER = Dir.glob('{meta,.meta}/setup/test{,rc}.rb', File::FNM_CASEFOLD).first
25
-
26
- # A ruby script that instructs setup how to generate docs, located at meta/setup/doc.rb
27
- # NOTE: Docs must be generate into the doc/ for them to be installed.
28
- DOCTOR = Dir.glob('{meta,.meta}/setup/doc{,rc}.rb', File::FNM_CASEFOLD).first
29
-
30
-
31
- module Setup
32
-
33
- # Installer class handles the actual install procedure,
34
- # as well as the other tasks, such as testing.
35
-
36
- class Installer
37
-
38
- MANIFEST = '.cache/setup/installedfiles'
39
-
40
- FILETYPES = %w( bin lib ext data etc man doc )
41
-
42
- # Configuration
43
- attr :config
44
-
45
- attr_writer :no_harm
46
- attr_writer :verbose
47
- attr_writer :quiet
48
-
49
- attr_accessor :install_prefix
50
- attr_accessor :install_no_test
51
-
52
- # New Installer.
53
- def initialize(config=nil) #:yield:
54
- srcroot = '.'
55
- objroot = '.'
56
-
57
- @config = config || ConfigTable.new
58
-
59
- @srcdir = File.expand_path(srcroot)
60
- @objdir = File.expand_path(objroot)
61
- @currdir = '.'
62
-
63
- self.quiet = ENV['quiet'] if ENV['quiet']
64
- self.verbose = ENV['verbose'] if ENV['verbose']
65
- self.no_harm = ENV['nowrite'] if ENV['nowrite']
66
-
67
- yield(self) if block_given?
68
- end
69
-
70
- #
71
- def inspect
72
- "#<#{self.class} #{File.basename(@srcdir)}>"
73
- end
74
-
75
- # Are we running an installation?
76
- def installation?; @installation; end
77
- def installation!; @installation = true; end
78
-
79
- def no_harm? ; @no_harm ; end
80
- def verbose? ; @verbose ; end
81
- def quiet? ; @quiet ; end
82
-
83
- def verbose_off #:yield:
84
- begin
85
- save, @verbose = verbose?, false
86
- yield
87
- ensure
88
- @verbose = save
89
- end
90
- end
91
-
92
- #
93
- def report_header(phase)
94
- return if quiet?
95
- #center = " "
96
- #c = (center.size - phase.size) / 2
97
- #center[c,phase.size] = phase.to_s.upcase
98
- line = '- ' * 4 + ' -' * 24
99
- #c = (line.size - phase.size) / 2
100
- line[5,phase.size] = " #{phase.to_s.upcase} "
101
- puts "\n" + line + "\n\n"
102
- end
103
-
104
- # Added these for future use in simplificaiton of design.
105
-
106
- def extensions
107
- @extensions ||= Dir['ext/**/extconf.rb']
108
- end
109
-
110
- def compiles?
111
- !extensions.empty?
112
- end
113
-
114
- #
115
- def noop(rel); end
116
-
117
- ##
118
- # Hook Script API bases
119
- #
120
-
121
- def srcdir_root
122
- @srcdir
123
- end
124
-
125
- def objdir_root
126
- @objdir
127
- end
128
-
129
- def relpath
130
- @currdir
131
- end
132
-
133
- ##
134
- # Task all
135
- #
136
-
137
- def exec_all
138
- exec_config
139
- exec_setup
140
- exec_test
141
- exec_doc
142
- exec_install
143
- end
144
-
145
- ##
146
- # TASK config
147
- #
148
-
149
- def exec_config
150
- report_header('config')
151
- config.env_config
152
- config.save_config
153
- config.show if verbose?
154
- puts("Configuration saved.") unless quiet?
155
- exec_task_traverse 'config'
156
- end
157
-
158
- alias config_dir_bin noop
159
- alias config_dir_lib noop
160
-
161
- def config_dir_ext(rel)
162
- extconf if extdir?(curr_srcdir())
163
- end
164
-
165
- alias config_dir_data noop
166
- alias config_dir_etc noop
167
- alias config_dir_man noop
168
- alias config_dir_doc noop
169
-
170
- def extconf
171
- ruby "#{curr_srcdir()}/extconf.rb", config.extconfopt
172
- end
173
-
174
- ##
175
- # TASK show
176
- #
177
-
178
- def exec_show
179
- config.show
180
- end
181
-
182
- ##
183
- # TASK setup
184
- #
185
- # FIXME: Update shebang on install rather than before.
186
- def exec_setup
187
- report_header('setup')
188
- exec_task_traverse 'setup'
189
- puts "Ok."
190
- end
191
-
192
- def setup_dir_bin(rel)
193
- files_of(curr_srcdir()).each do |fname|
194
- update_shebang_line "#{curr_srcdir()}/#{fname}" # MOVE TO INSTALL (BUT HOW?)
195
- end
196
- end
197
-
198
- alias setup_dir_lib noop
199
-
200
- def setup_dir_ext(rel)
201
- make if extdir?(curr_srcdir())
202
- end
203
-
204
- alias setup_dir_data noop
205
- alias setup_dir_etc noop
206
- alias setup_dir_man noop
207
- alias setup_dir_doc noop
208
-
209
- def update_shebang_line(path)
210
- return if no_harm?
211
- return if config.shebang == 'never'
212
- old = Shebang.load(path)
213
- if old
214
- if old.args.size > 1
215
- $stderr.puts "warning: #{path}"
216
- $stderr.puts "Shebang line has too many args."
217
- $stderr.puts "It is not portable and your program may not work."
218
- end
219
- new = new_shebang(old)
220
- return if new.to_s == old.to_s
221
- else
222
- return unless config.shebang == 'all'
223
- new = Shebang.new(config.rubypath)
224
- end
225
- $stderr.puts "updating shebang: #{File.basename(path)}" if verbose?
226
- open_atomic_writer(path) {|output|
227
- File.open(path, 'rb') {|f|
228
- f.gets if old # discard
229
- output.puts new.to_s
230
- output.print f.read
231
- }
232
- }
233
- end
234
-
235
- def new_shebang(old)
236
- if /\Aruby/ =~ File.basename(old.cmd)
237
- Shebang.new(config.rubypath, old.args)
238
- elsif File.basename(old.cmd) == 'env' and old.args.first == 'ruby'
239
- Shebang.new(config.rubypath, old.args[1..-1])
240
- else
241
- return old unless config.shebang == 'all'
242
- Shebang.new(config.rubypath)
243
- end
244
- end
245
-
246
- def open_atomic_writer(path, &block)
247
- tmpfile = File.basename(path) + '.tmp'
248
- begin
249
- File.open(tmpfile, 'wb', &block)
250
- File.rename tmpfile, File.basename(path)
251
- ensure
252
- File.unlink tmpfile if File.exist?(tmpfile)
253
- end
254
- end
255
-
256
- class Shebang
257
- def Shebang.load(path)
258
- line = nil
259
- File.open(path) {|f|
260
- line = f.gets
261
- }
262
- return nil unless /\A#!/ =~ line
263
- parse(line)
264
- end
265
-
266
- def Shebang.parse(line)
267
- cmd, *args = *line.strip.sub(/\A\#!/, '').split(' ')
268
- new(cmd, args)
269
- end
270
-
271
- def initialize(cmd, args = [])
272
- @cmd = cmd
273
- @args = args
274
- end
275
-
276
- attr_reader :cmd
277
- attr_reader :args
278
-
279
- def to_s
280
- "#! #{@cmd}" + (@args.empty? ? '' : " #{@args.join(' ')}")
281
- end
282
- end
283
-
284
- ##
285
- # TASK test
286
- #
287
- # Complexities arise in trying to figure out what test framework
288
- # is used, and how to run tests. To simplify the process, this
289
- # simply looks for a script in meta/setup called testrc.rb,
290
- # or just test.rb.
291
- #
292
- def exec_test
293
- return if install_no_test
294
- file = TESTER
295
- if file
296
- report_header('test')
297
- ruby(file)
298
- end
299
- #puts "Ok." unless quiet?
300
- end
301
-
302
- ### DEPRECATED
303
- #def exec_test
304
- #runner = config.testrunner
305
- #case runner
306
- #when 'testrb' # TODO: needs work
307
- # opt = []
308
- # opt << " -v" if verbose?
309
- # opt << " --runner #{runner}"
310
- # if File.file?('test/suite.rb')
311
- # notests = false
312
- # opt << "test/suite.rb"
313
- # else
314
- # notests = Dir["test/**/*.rb"].empty?
315
- # lib = ["lib"] + config.extensions.collect{ |d| File.dirname(d) }
316
- # opt << "-I" + lib.join(':')
317
- # opt << Dir["test/**/{test,tc}*.rb"]
318
- # end
319
- # opt = opt.flatten.join(' ').strip
320
- # # run tests
321
- # if notests
322
- # $stderr.puts 'no test in this package' if verbose?
323
- # else
324
- # cmd = "testrb #{opt}"
325
- # $stderr.puts cmd if verbose?
326
- # system cmd #config.ruby "-S testrb", opt
327
- # end
328
- #else # autorunner
329
- # unless File.directory?('test')
330
- # $stderr.puts 'no test in this package' if verbose?
331
- # return
332
- # end
333
- # begin
334
- # require 'test/unit'
335
- # rescue LoadError
336
- # setup_rb_error 'test/unit cannot loaded. You need Ruby 1.8 or later to invoke this task.'
337
- # end
338
- # lib = ["lib"] + config.extensions.collect{ |d| File.dirname(d) }
339
- # lib.each{ |l| $LOAD_PATH << l }
340
- # autorunner = Test::Unit::AutoRunner.new(true)
341
- # autorunner.to_run << 'test'
342
- # autorunner.run
343
- #end
344
- #end
345
-
346
- # MAYBE: We could traverse and run each test independently (?)
347
- #def test_dir_test
348
- #end
349
-
350
- ##
351
- # TASK doc
352
-
353
- def exec_doc
354
- return if config.withoutdoc?
355
- report_header('doc')
356
- if file = DOCTOR
357
- ruby(file)
358
- else
359
- exec_rdoc
360
- end
361
- exec_ri
362
- end
363
-
364
- # Generate rdocs.
365
- #
366
- # NOT USED YET B/C WE WOULD HAVE TO KNOW THE NAME OF THE PROJECT
367
- # TO DO THIS CORRECTLY. (WHERE DO WE GET THAT?)
368
- #
369
- # Answer: meta/package or .meta/package
370
- #
371
- def exec_rdoc
372
- main = Dir.glob("README{,.*}", File::FNM_CASEFOLD).first
373
-
374
- if File.exist?('.document')
375
- files = File.read('.document').split("\n")
376
- files.reject!{ |l| l =~ /^\s*[#]/ || l !~ /\S/ }
377
- files.collect!{ |f| f.strip }
378
- else
379
- files = []
380
- files << main if main
381
- files << 'lib' if File.directory?('lib')
382
- files << 'ext' if File.directory?('ext')
383
- end
384
-
385
- checkfiles = (files + files.map{ |f| Dir[File.join(f,'*','**')] }).flatten.uniq
386
- if FileUtils.uptodate?('doc/rdoc', checkfiles)
387
- puts "RDocs look uptodate."
388
- return
389
- end
390
-
391
- output = 'doc/rdoc'
392
- title = (PACKAGE.capitalize + " API").strip
393
- template = config.doctemplate || 'html'
394
-
395
- opt = []
396
- opt << "-U"
397
- opt << "-q" #if quiet?
398
- opt << "--op=#{output}"
399
- #opt << "--template=#{template}"
400
- opt << "--title=#{title}"
401
- opt << "--main=#{main}" if main
402
- #opt << "--debug"
403
- opt << files
404
-
405
- opt = opt.flatten
406
-
407
- cmd = "rdoc " + opt.join(' ')
408
-
409
- if no_harm?
410
- puts cmd
411
- else
412
- begin
413
- system(cmd)
414
- #require 'rdoc/rdoc'
415
- #::RDoc::RDoc.new.document(opt)
416
- puts "Ok rdoc." unless quiet?
417
- rescue Exception
418
- puts "Fail rdoc."
419
- puts "Command was: '#{cmd}'"
420
- puts "Proceeding with install anyway."
421
- end
422
- end
423
- end
424
-
425
- # Generate ri documentation.
426
-
427
- def exec_ri
428
- case config.installdirs
429
- when 'std'
430
- output = "--ri-system"
431
- when 'site'
432
- output = "--ri-site"
433
- when 'home'
434
- output = "--ri"
435
- else
436
- abort "bad config: sould not be possible -- installdirs = #{config.installdirs}"
437
- end
438
-
439
- if File.exist?('.document')
440
- files = File.read('.document').split("\n")
441
- files.reject!{ |l| l =~ /^\s*[#]/ || l !~ /\S/ }
442
- files.collect!{ |f| f.strip }
443
- else
444
- files = []
445
- files << 'lib' if File.directory?('lib')
446
- files << 'ext' if File.directory?('ext')
447
- end
448
-
449
- opt = []
450
- opt << "-U"
451
- opt << "-q" #if quiet?
452
- #opt << "-D" #if $DEBUG
453
- opt << output
454
- opt << files
455
-
456
- opt = opt.flatten
457
-
458
- cmd = "rdoc " + opt.join(' ')
459
-
460
- if no_harm?
461
- puts cmd
462
- else
463
- # Generate in system location specified
464
- begin
465
- system(cmd)
466
- #require 'rdoc/rdoc'
467
- #::RDoc::RDoc.new.document(opt)
468
- puts "Ok ri." unless quiet?
469
- rescue Exception
470
- puts "Fail ri."
471
- puts "Command was: '#{cmd}'"
472
- puts "Proceeding with install anyway."
473
- end
474
- # Now in local directory
475
- #opt = []
476
- #opt << "-U"
477
- #opt << "--ri --op 'doc/ri'"
478
- #opt << files
479
- #opt = opt.flatten
480
- #::RDoc::RDoc.new.document(opt)
481
- end
482
- end
483
-
484
- ##
485
- # TASK install
486
- #
487
-
488
- def exec_install
489
- report_header('install')
490
- installation! # we are installing
491
- #rm_f MANIFEST # we'll append rather then delete!
492
- exec_task_traverse 'install'
493
- $stderr.puts "Done.\n\n" unless quiet?
494
- end
495
-
496
- def install_dir_bin(rel)
497
- install_files targetfiles(), "#{config.bindir}/#{rel}", 0755
498
- end
499
-
500
- def install_dir_lib(rel)
501
- install_files libfiles(), "#{config.rbdir}/#{rel}", 0644
502
- end
503
-
504
- def install_dir_ext(rel)
505
- return unless extdir?(curr_srcdir())
506
- install_files rubyextentions('.'),
507
- "#{config.sodir}/#{File.dirname(rel)}", 0555
508
- end
509
-
510
- def install_dir_data(rel)
511
- install_files targetfiles(), "#{config.datadir}/#{rel}", 0644
512
- end
513
-
514
- def install_dir_etc(rel)
515
- # FIXME: should not remove current config files
516
- # (rename previous file to .old/.org)
517
- install_files targetfiles(), "#{config.sysconfdir}/#{rel}", 0644
518
- end
519
-
520
- def install_dir_man(rel)
521
- install_files targetfiles(), "#{config.mandir}/#{rel}", 0644
522
- end
523
-
524
- # doc installs to directory named: "ruby-#{package}"
525
- def install_dir_doc(rel)
526
- return if config.withoutdoc?
527
- return unless PACKAGE
528
- dir = "#{config.docdir}/ruby-#{PACKAGE}/#{rel}" # "#{config.docdir}/#{rel}"
529
- install_files targetfiles(), dir, 0644
530
- end
531
-
532
- def install_files(list, dest, mode)
533
- mkdir_p dest, install_prefix
534
- list.each do |fname|
535
- install fname, dest, mode, install_prefix
536
- end
537
- end
538
-
539
- def libfiles
540
- glob_reject(%w(*.y *.output), targetfiles())
541
- end
542
-
543
- def rubyextentions(dir)
544
- ents = glob_select("*.#{dllext}", targetfiles())
545
- if ents.empty?
546
- setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first"
547
- end
548
- ents
549
- end
550
-
551
- def dllext
552
- ConfigTable::RBCONFIG['DLEXT']
553
- end
554
-
555
- def targetfiles
556
- mapdir(existfiles() - hookfiles())
557
- end
558
-
559
- def mapdir(ents)
560
- ents.map {|ent|
561
- if File.exist?(ent)
562
- then ent # objdir
563
- else "#{curr_srcdir()}/#{ent}" # srcdir
564
- end
565
- }
566
- end
567
-
568
- # picked up many entries from cvs-1.11.1/src/ignore.c
569
- JUNK_FILES = %w(
570
- core RCSLOG tags TAGS .make.state
571
- .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb
572
- *~ *.old *.bak *.BAK *.orig *.rej _$* *$
573
-
574
- *.org *.in .*
575
- )
576
-
577
- def existfiles
578
- glob_reject(JUNK_FILES, (files_of(curr_srcdir()) | files_of('.')))
579
- end
580
-
581
- def hookfiles
582
- %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt|
583
- %w( etc setup install clean ).map {|t| sprintf(fmt, t) }
584
- }.flatten
585
- end
586
-
587
- def glob_select(pat, ents)
588
- re = globs2re([pat])
589
- ents.select {|ent| re =~ ent }
590
- end
591
-
592
- def glob_reject(pats, ents)
593
- re = globs2re(pats)
594
- ents.reject {|ent| re =~ ent }
595
- end
596
-
597
- GLOB2REGEX = {
598
- '.' => '\.',
599
- '$' => '\$',
600
- '#' => '\#',
601
- '*' => '.*'
602
- }
603
-
604
- def globs2re(pats)
605
- /\A(?:#{
606
- pats.map {|pat| pat.gsub(/[\.\$\#\*]/) {|ch| GLOB2REGEX[ch] } }.join('|')
607
- })\z/
608
- end
609
-
610
- ##
611
- # TASK uninstall
612
- #
613
-
614
- def exec_uninstall
615
- paths = File.read(MANIFEST).split("\n")
616
- dirs, files = paths.partition{ |f| File.dir?(f) }
617
-
618
- remove = []
619
- files.uniq.each do |file|
620
- next if /^\#/ =~ file # skip comments
621
- remove << file if File.exist?(file)
622
- end
623
-
624
- if verbose? && !no_harm?
625
- puts remove.collect{ |f| "rm #{f}" }.join("\n")
626
- ans = ask("Continue?", "yN")
627
- case ans
628
- when 'y', 'Y', 'yes'
629
- else
630
- return # abort?
631
- end
632
- end
633
-
634
- remove.each do |file|
635
- rm_f(file)
636
- end
637
-
638
- dirs.each do |dir|
639
- # okay this is over kill, but playing it safe...
640
- empty = Dir[File.join(dir,'*')].empty?
641
- begin
642
- if no_harm?
643
- $stderr.puts "rmdir #{dir}"
644
- else
645
- rmdir(dir) if empty
646
- end
647
- rescue Errno::ENOTEMPTY
648
- $stderr.puts "may not be empty -- #{dir}" if verbose?
649
- end
650
- end
651
-
652
- rm_f(MANIFEST)
653
- end
654
-
655
- ##
656
- # TASK clean
657
- #
658
-
659
- def exec_clean
660
- exec_task_traverse 'clean'
661
- rm_f ConfigTable::CONFIGFILE
662
- #rm_f MANIFEST # only on clobber!
663
- end
664
-
665
- alias clean_dir_bin noop
666
- alias clean_dir_lib noop
667
- alias clean_dir_data noop
668
- alias clean_dir_etc noop
669
- alias clean_dir_man noop
670
- alias clean_dir_doc noop
671
-
672
- def clean_dir_ext(rel)
673
- return unless extdir?(curr_srcdir())
674
- make 'clean' if File.file?('Makefile')
675
- end
676
-
677
- ##
678
- # TASK distclean
679
- #
680
-
681
- def exec_distclean
682
- exec_task_traverse 'distclean'
683
- rm_f ConfigTable::CONFIGFILE
684
- rm_f MANIFEST
685
- end
686
-
687
- alias distclean_dir_bin noop
688
- alias distclean_dir_lib noop
689
-
690
- def distclean_dir_ext(rel)
691
- return unless extdir?(curr_srcdir())
692
- make 'distclean' if File.file?('Makefile')
693
- end
694
-
695
- alias distclean_dir_data noop
696
- alias distclean_dir_etc noop
697
- alias distclean_dir_man noop
698
-
699
- def distclean_dir_doc(rel)
700
- #rm_rf('rdoc') if File.directory?('rdoc') # RDOC HERE
701
- end
702
-
703
- ##
704
- # Traversing
705
- #
706
-
707
- def exec_task_traverse(task)
708
- run_hook "pre-#{task}"
709
- FILETYPES.each do |type|
710
- if type == 'ext' and config.withoutext? #== 'yes'
711
- $stderr.puts 'skipping ext/* by user option' if verbose?
712
- next
713
- end
714
- traverse task, type, "#{task}_dir_#{type}"
715
- end
716
- run_hook "post-#{task}"
717
- end
718
-
719
- def traverse(task, rel, mid)
720
- dive_into(rel) {
721
- run_hook "pre-#{task}"
722
- __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '')
723
- directories_of(curr_srcdir()).each do |d|
724
- traverse task, "#{rel}/#{d}", mid
725
- end
726
- run_hook "post-#{task}"
727
- }
728
- end
729
-
730
- #
731
- def dive_into(rel)
732
- return unless File.dir?("#{@srcdir}/#{rel}")
733
-
734
- dir = File.basename(rel)
735
- Dir.mkdir dir unless File.dir?(dir)
736
- prevdir = Dir.pwd
737
- Dir.chdir dir
738
- $stderr.puts '---> ' + rel if verbose?
739
- @currdir = rel
740
- yield
741
- Dir.chdir prevdir
742
- $stderr.puts '<--- ' + rel if verbose?
743
- @currdir = File.dirname(rel)
744
- end
745
-
746
- #
747
- def run_hook(id)
748
- path = [ "#{curr_srcdir()}/#{id}",
749
- "#{curr_srcdir()}/#{id}.rb" ].detect {|cand| File.file?(cand) }
750
- return unless path
751
- begin
752
- instance_eval File.read(path), path, 1
753
- rescue
754
- raise if $DEBUG
755
- setup_rb_error "hook #{path} failed:\n" + $!.message
756
- end
757
- end
758
-
759
- ##
760
- # File Operations
761
- #
762
- # This module requires: #verbose?, #no_harm?
763
-
764
- def binread(fname)
765
- File.open(fname, 'rb'){ |f|
766
- return f.read
767
- }
768
- end
769
-
770
- def mkdir_p(dirname, prefix = nil)
771
- dirname = prefix + File.expand_path(dirname) if prefix
772
- $stderr.puts "mkdir -p #{dirname}" if verbose?
773
- return if no_harm?
774
-
775
- # Does not check '/', it's too abnormal.
776
- dirs = File.expand_path(dirname).split(%r<(?=/)>)
777
- if /\A[a-z]:\z/i =~ dirs[0]
778
- disk = dirs.shift
779
- dirs[0] = disk + dirs[0]
780
- end
781
- dirs.each_index do |idx|
782
- path = dirs[0..idx].join('')
783
- Dir.mkdir path unless File.dir?(path)
784
- record_installation(path) # also record directories made
785
- end
786
- end
787
-
788
- def rm_f(path)
789
- $stderr.puts "rm -f #{path}" if verbose?
790
- return if no_harm?
791
- force_remove_file path
792
- end
793
-
794
- def rm_rf(path)
795
- $stderr.puts "rm -rf #{path}" if verbose?
796
- return if no_harm?
797
- remove_tree path
798
- end
799
-
800
- def rmdir(path)
801
- $stderr.puts "rmdir #{path}" if verbose?
802
- return if no_harm?
803
- Dir.rmdir path
804
- end
805
-
806
- def remove_tree(path)
807
- if File.symlink?(path)
808
- remove_file path
809
- elsif File.dir?(path)
810
- remove_tree0 path
811
- else
812
- force_remove_file path
813
- end
814
- end
815
-
816
- def remove_tree0(path)
817
- Dir.foreach(path) do |ent|
818
- next if ent == '.'
819
- next if ent == '..'
820
- entpath = "#{path}/#{ent}"
821
- if File.symlink?(entpath)
822
- remove_file entpath
823
- elsif File.dir?(entpath)
824
- remove_tree0 entpath
825
- else
826
- force_remove_file entpath
827
- end
828
- end
829
- begin
830
- Dir.rmdir path
831
- rescue Errno::ENOTEMPTY
832
- # directory may not be empty
833
- end
834
- end
835
-
836
- def move_file(src, dest)
837
- force_remove_file dest
838
- begin
839
- File.rename src, dest
840
- rescue
841
- File.open(dest, 'wb') {|f|
842
- f.write binread(src)
843
- }
844
- File.chmod File.stat(src).mode, dest
845
- File.unlink src
846
- end
847
- end
848
-
849
- def force_remove_file(path)
850
- begin
851
- remove_file path
852
- rescue
853
- end
854
- end
855
-
856
- def remove_file(path)
857
- File.chmod 0777, path
858
- File.unlink path
859
- end
860
-
861
- def install(from, dest, mode, prefix = nil)
862
- $stderr.puts "install #{from} #{dest}" if verbose?
863
- return if no_harm?
864
-
865
- realdest = prefix ? prefix + File.expand_path(dest) : dest
866
- realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest)
867
- str = binread(from)
868
- if diff?(str, realdest)
869
- verbose_off {
870
- rm_f realdest if File.exist?(realdest)
871
- }
872
- File.open(realdest, 'wb') {|f|
873
- f.write str
874
- }
875
- File.chmod mode, realdest
876
-
877
- if prefix
878
- path = realdest.sub(prefix, '')
879
- else
880
- path = realdest
881
- end
882
-
883
- record_installation(path)
884
- end
885
- end
886
-
887
- def record_installation(path)
888
- FileUtils.mkdir_p(File.dirname("#{objdir_root()}/#{MANIFEST}"))
889
- File.open("#{objdir_root()}/#{MANIFEST}", 'a') do |f|
890
- f.puts(path)
891
- end
892
- end
893
-
894
- def diff?(new_content, path)
895
- return true unless File.exist?(path)
896
- new_content != binread(path)
897
- end
898
-
899
- def command(*args)
900
- $stderr.puts args.join(' ') if verbose?
901
- system(*args) or raise RuntimeError,
902
- "system(#{args.map{|a| a.inspect }.join(' ')}) failed"
903
- end
904
-
905
- def ruby(*args)
906
- command config.rubyprog, *args
907
- end
908
-
909
- def make(task = nil)
910
- command(*[config.makeprog, task].compact)
911
- end
912
-
913
- def extdir?(dir)
914
- File.exist?("#{dir}/MANIFEST") or File.exist?("#{dir}/extconf.rb")
915
- end
916
-
917
- def files_of(dir)
918
- Dir.open(dir) {|d|
919
- return d.select {|ent| File.file?("#{dir}/#{ent}") }
920
- }
921
- end
922
-
923
- DIR_REJECT = %w( . .. CVS SCCS RCS CVS.adm .svn )
924
-
925
- def directories_of(dir)
926
- Dir.open(dir) {|d|
927
- return d.select {|ent| File.dir?("#{dir}/#{ent}") } - DIR_REJECT
928
- }
929
- end
930
-
931
- # Ask a question of the user.
932
- def ask(question, answers=nil)
933
- $stdout << "#{question}"
934
- $stdout << " [#{answers}] " if answers
935
- until inp = $stdin.gets ; sleep 1 ; end
936
- inp.strip
937
- end
938
-
939
- ##
940
- # Hook Script API
941
- #
942
- # These require: #srcdir_root, #objdir_root, #relpath
943
- #
944
-
945
- #
946
- def get_config(key)
947
- config[key]
948
- end
949
-
950
- # obsolete: use metaconfig to change configuration
951
- # TODO: what to do with?
952
- def set_config(key, val)
953
- config[key] = val
954
- end
955
-
956
- # srcdir/objdir (works only in the package directory)
957
- #
958
- # TODO: Since package directory has been deprecated these
959
- # probably can be worked out of the system. ?
960
-
961
- #
962
- def curr_srcdir
963
- "#{srcdir_root()}/#{relpath()}"
964
- end
965
-
966
- def curr_objdir
967
- "#{objdir_root()}/#{relpath()}"
968
- end
969
-
970
- def srcfile(path)
971
- "#{curr_srcdir()}/#{path}"
972
- end
973
-
974
- def srcexist?(path)
975
- File.exist?(srcfile(path))
976
- end
977
-
978
- def srcdirectory?(path)
979
- File.dir?(srcfile(path))
980
- end
981
-
982
- def srcfile?(path)
983
- File.file?(srcfile(path))
984
- end
985
-
986
- def srcentries(path = '.')
987
- Dir.open("#{curr_srcdir()}/#{path}") {|d|
988
- return d.to_a - %w(. ..)
989
- }
990
- end
991
-
992
- def srcfiles(path = '.')
993
- srcentries(path).select {|fname|
994
- File.file?(File.join(curr_srcdir(), path, fname))
995
- }
996
- end
997
-
998
- def srcdirectories(path = '.')
999
- srcentries(path).select {|fname|
1000
- File.dir?(File.join(curr_srcdir(), path, fname))
1001
- }
1002
- end
1003
-
1004
- end
1005
-
1006
- end
1007
-