ruby-oci8 2.2.10-x64-mingw-ucrt

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +14 -0
  3. data/COPYING +30 -0
  4. data/COPYING_old +64 -0
  5. data/ChangeLog +3826 -0
  6. data/Makefile +92 -0
  7. data/NEWS +1209 -0
  8. data/README.md +66 -0
  9. data/dist-files +112 -0
  10. data/docs/bind-array-to-in_cond.md +38 -0
  11. data/docs/conflicts-local-connections-and-processes.md +98 -0
  12. data/docs/hanging-after-inactivity.md +63 -0
  13. data/docs/install-binary-package.md +44 -0
  14. data/docs/install-full-client.md +111 -0
  15. data/docs/install-instant-client.md +194 -0
  16. data/docs/install-on-osx.md +46 -0
  17. data/docs/ldap-auth-and-function-interposition.md +123 -0
  18. data/docs/number-type-mapping.md +79 -0
  19. data/docs/platform-specific-issues.md +164 -0
  20. data/docs/report-installation-issue.md +50 -0
  21. data/docs/timeout-parameters.md +94 -0
  22. data/lib/.document +1 -0
  23. data/lib/dbd/OCI8.rb +591 -0
  24. data/lib/oci8/.document +8 -0
  25. data/lib/oci8/bindtype.rb +333 -0
  26. data/lib/oci8/check_load_error.rb +146 -0
  27. data/lib/oci8/compat.rb +117 -0
  28. data/lib/oci8/connection_pool.rb +179 -0
  29. data/lib/oci8/cursor.rb +605 -0
  30. data/lib/oci8/datetime.rb +605 -0
  31. data/lib/oci8/encoding-init.rb +45 -0
  32. data/lib/oci8/encoding.yml +537 -0
  33. data/lib/oci8/metadata.rb +2148 -0
  34. data/lib/oci8/object.rb +641 -0
  35. data/lib/oci8/oci8.rb +756 -0
  36. data/lib/oci8/ocihandle.rb +591 -0
  37. data/lib/oci8/oracle_version.rb +153 -0
  38. data/lib/oci8/properties.rb +196 -0
  39. data/lib/oci8/version.rb +3 -0
  40. data/lib/oci8.rb +190 -0
  41. data/lib/oci8lib_310.so +0 -0
  42. data/lib/ruby-oci8.rb +1 -0
  43. data/metaconfig +142 -0
  44. data/pre-distclean.rb +7 -0
  45. data/ruby-oci8.gemspec +85 -0
  46. data/setup.rb +1342 -0
  47. data/test/README.md +37 -0
  48. data/test/config.rb +201 -0
  49. data/test/setup_test_object.sql +199 -0
  50. data/test/setup_test_package.sql +59 -0
  51. data/test/test_all.rb +56 -0
  52. data/test/test_appinfo.rb +62 -0
  53. data/test/test_array_dml.rb +332 -0
  54. data/test/test_bind_array.rb +70 -0
  55. data/test/test_bind_boolean.rb +99 -0
  56. data/test/test_bind_integer.rb +47 -0
  57. data/test/test_bind_raw.rb +45 -0
  58. data/test/test_bind_string.rb +105 -0
  59. data/test/test_bind_time.rb +177 -0
  60. data/test/test_break.rb +125 -0
  61. data/test/test_clob.rb +85 -0
  62. data/test/test_connection_pool.rb +124 -0
  63. data/test/test_connstr.rb +220 -0
  64. data/test/test_datetime.rb +585 -0
  65. data/test/test_dbi.rb +365 -0
  66. data/test/test_dbi_clob.rb +53 -0
  67. data/test/test_encoding.rb +103 -0
  68. data/test/test_error.rb +87 -0
  69. data/test/test_metadata.rb +2674 -0
  70. data/test/test_object.rb +546 -0
  71. data/test/test_oci8.rb +624 -0
  72. data/test/test_oracle_version.rb +68 -0
  73. data/test/test_oradate.rb +255 -0
  74. data/test/test_oranumber.rb +792 -0
  75. data/test/test_package_type.rb +981 -0
  76. data/test/test_properties.rb +17 -0
  77. data/test/test_rowid.rb +32 -0
  78. metadata +123 -0
data/setup.rb ADDED
@@ -0,0 +1,1342 @@
1
+ #
2
+ # setup.rb
3
+ #
4
+ # Copyright (c) 2000-2004 Minero Aoki
5
+ #
6
+ # This program is free software.
7
+ # You can distribute/modify this program under the terms of
8
+ # the GNU Lesser General Public License version 2.1.
9
+ #
10
+
11
+ #
12
+ # For backward compatibility
13
+ #
14
+
15
+ unless Enumerable.method_defined?(:map)
16
+ module Enumerable
17
+ alias map collect
18
+ end
19
+ end
20
+
21
+ unless Enumerable.method_defined?(:detect)
22
+ module Enumerable
23
+ alias detect find
24
+ end
25
+ end
26
+
27
+ unless Enumerable.method_defined?(:select)
28
+ module Enumerable
29
+ alias select find_all
30
+ end
31
+ end
32
+
33
+ unless Enumerable.method_defined?(:reject)
34
+ module Enumerable
35
+ def reject
36
+ result = []
37
+ each do |i|
38
+ result.push i unless yield(i)
39
+ end
40
+ result
41
+ end
42
+ end
43
+ end
44
+
45
+ unless Enumerable.method_defined?(:inject)
46
+ module Enumerable
47
+ def inject(result)
48
+ each do |i|
49
+ result = yield(result, i)
50
+ end
51
+ result
52
+ end
53
+ end
54
+ end
55
+
56
+ unless Enumerable.method_defined?(:any?)
57
+ module Enumerable
58
+ def any?
59
+ each do |i|
60
+ return true if yield(i)
61
+ end
62
+ false
63
+ end
64
+ end
65
+ end
66
+
67
+ unless File.respond_to?(:read)
68
+ def File.read(fname)
69
+ open(fname) {|f|
70
+ return f.read
71
+ }
72
+ end
73
+ end
74
+
75
+ #
76
+ # Application independent utilities
77
+ #
78
+
79
+ def File.binread(fname)
80
+ open(fname, 'rb') {|f|
81
+ return f.read
82
+ }
83
+ end
84
+
85
+ # for corrupted windows stat(2)
86
+ def File.dir?(path)
87
+ File.directory?((path[-1,1] == '/') ? path : path + '/')
88
+ end
89
+
90
+ #
91
+ # Config
92
+ #
93
+
94
+ if arg = ARGV.detect{|a| /\A--rbconfig=/ =~ a }
95
+ ARGV.delete(arg)
96
+ require arg.split(/=/, 2)[1]
97
+ $".push 'rbconfig.rb'
98
+ else
99
+ require 'rbconfig'
100
+ end
101
+
102
+ RbConfig = Config unless defined? RbConfig
103
+
104
+ def multipackage_install?
105
+ FileTest.directory?(File.dirname($0) + '/packages')
106
+ end
107
+
108
+
109
+ class ConfigTable
110
+
111
+ c = ::RbConfig::CONFIG
112
+
113
+ rubypath = c['bindir'] + '/' + c['ruby_install_name']
114
+
115
+ major = c['MAJOR'].to_i
116
+ minor = c['MINOR'].to_i
117
+ teeny = c['TEENY'].to_i
118
+ version = "#{major}.#{minor}"
119
+
120
+ # ruby ver. >= 1.4.4?
121
+ newpath_p = ((major >= 2) or
122
+ ((major == 1) and
123
+ ((minor >= 5) or
124
+ ((minor == 4) and (teeny >= 4)))))
125
+
126
+ subprefix = lambda {|path|
127
+ path.sub(/\A#{Regexp.quote(c['prefix'])}/o, '$prefix')
128
+ }
129
+
130
+ if c['rubylibdir']
131
+ # V < 1.6.3
132
+ stdruby = subprefix.call(c['rubylibdir'])
133
+ siteruby = subprefix.call(c['sitedir'])
134
+ versite = subprefix.call(c['sitelibdir'])
135
+ sodir = subprefix.call(c['sitearchdir'])
136
+ elsif newpath_p
137
+ # 1.4.4 <= V <= 1.6.3
138
+ stdruby = "$prefix/lib/ruby/#{version}"
139
+ siteruby = subprefix.call(c['sitedir'])
140
+ versite = siteruby + '/' + version
141
+ sodir = "$site-ruby/#{c['arch']}"
142
+ else
143
+ # V < 1.4.4
144
+ stdruby = "$prefix/lib/ruby/#{version}"
145
+ siteruby = "$prefix/lib/ruby/#{version}/site_ruby"
146
+ versite = siteruby
147
+ sodir = "$site-ruby/#{c['arch']}"
148
+ end
149
+
150
+ if arg = c['configure_args'].split.detect {|a| /--with-make-prog=/ =~ a }
151
+ makeprog = arg.sub(/'/, '').split(/=/, 2)[1]
152
+ else
153
+ makeprog = 'make'
154
+ end
155
+
156
+ common_descripters = [
157
+ [ 'prefix', [ c['prefix'],
158
+ 'path',
159
+ 'path prefix of target environment' ] ],
160
+ [ 'std-ruby', [ stdruby,
161
+ 'path',
162
+ 'the directory for standard ruby libraries' ] ],
163
+ [ 'site-ruby-common', [ siteruby,
164
+ 'path',
165
+ 'the directory for version-independent non-standard ruby libraries' ] ],
166
+ [ 'site-ruby', [ versite,
167
+ 'path',
168
+ 'the directory for non-standard ruby libraries' ] ],
169
+ [ 'bin-dir', [ '$prefix/bin',
170
+ 'path',
171
+ 'the directory for commands' ] ],
172
+ [ 'rb-dir', [ '$site-ruby',
173
+ 'path',
174
+ 'the directory for ruby scripts' ] ],
175
+ [ 'so-dir', [ sodir,
176
+ 'path',
177
+ 'the directory for ruby extentions' ] ],
178
+ [ 'data-dir', [ '$prefix/share',
179
+ 'path',
180
+ 'the directory for shared data' ] ],
181
+ [ 'ruby-path', [ rubypath,
182
+ 'path',
183
+ 'path to set to #! line' ] ],
184
+ [ 'ruby-prog', [ rubypath,
185
+ 'name',
186
+ 'the ruby program using for installation' ] ],
187
+ [ 'make-prog', [ makeprog,
188
+ 'name',
189
+ 'the make program to compile ruby extentions' ] ],
190
+ [ 'without-ext', [ 'no',
191
+ 'yes/no',
192
+ 'does not compile/install ruby extentions' ] ],
193
+ [ 'with-instant-client-dir', ['',
194
+ 'path',
195
+ 'path to the Oracle instant client directory'] ],
196
+ [ 'with-instant-client-lib', ['',
197
+ 'path',
198
+ 'path to the Oracle instant client libraries'] ],
199
+ [ 'with-instant-client-include', ['',
200
+ 'path',
201
+ 'path to the Oracle instant client header files'] ]
202
+ ]
203
+ multipackage_descripters = [
204
+ [ 'with', [ '',
205
+ 'name,name...',
206
+ 'package names that you want to install',
207
+ 'ALL' ] ],
208
+ [ 'without', [ '',
209
+ 'name,name...',
210
+ 'package names that you do not want to install',
211
+ 'NONE' ] ]
212
+ ]
213
+ if multipackage_install?
214
+ DESCRIPTER = common_descripters + multipackage_descripters
215
+ else
216
+ DESCRIPTER = common_descripters
217
+ end
218
+
219
+ SAVE_FILE = 'config.save'
220
+
221
+ def ConfigTable.each_name(&block)
222
+ keys().each(&block)
223
+ end
224
+
225
+ def ConfigTable.keys
226
+ DESCRIPTER.map {|name, *dummy| name }
227
+ end
228
+
229
+ def ConfigTable.each_definition(&block)
230
+ DESCRIPTER.each(&block)
231
+ end
232
+
233
+ def ConfigTable.get_entry(name)
234
+ name, ent = DESCRIPTER.assoc(name)
235
+ ent
236
+ end
237
+
238
+ def ConfigTable.get_entry!(name)
239
+ get_entry(name) or raise ArgumentError, "no such config: #{name}"
240
+ end
241
+
242
+ def ConfigTable.add_entry(name, vals)
243
+ ConfigTable::DESCRIPTER.push [name,vals]
244
+ end
245
+
246
+ def ConfigTable.remove_entry(name)
247
+ get_entry(name) or raise ArgumentError, "no such config: #{name}"
248
+ DESCRIPTER.delete_if {|n, arr| n == name }
249
+ end
250
+
251
+ def ConfigTable.config_key?(name)
252
+ get_entry(name) ? true : false
253
+ end
254
+
255
+ def ConfigTable.bool_config?(name)
256
+ ent = get_entry(name) or return false
257
+ ent[1] == 'yes/no'
258
+ end
259
+
260
+ def ConfigTable.value_config?(name)
261
+ ent = get_entry(name) or return false
262
+ ent[1] != 'yes/no'
263
+ end
264
+
265
+ def ConfigTable.path_config?(name)
266
+ ent = get_entry(name) or return false
267
+ ent[1] == 'path'
268
+ end
269
+
270
+
271
+ class << self
272
+ alias newobj new
273
+ end
274
+
275
+ def ConfigTable.new
276
+ c = newobj()
277
+ c.initialize_from_table
278
+ c
279
+ end
280
+
281
+ def ConfigTable.load
282
+ c = newobj()
283
+ c.initialize_from_file
284
+ c
285
+ end
286
+
287
+ def initialize_from_table
288
+ @table = {}
289
+ DESCRIPTER.each do |k, (default, *)|
290
+ @table[k] = default
291
+ end
292
+ end
293
+
294
+ def initialize_from_file
295
+ raise InstallError, "#{File.basename $0} config first"\
296
+ unless File.file?(SAVE_FILE)
297
+ @table = {}
298
+ File.foreach(SAVE_FILE) do |line|
299
+ k, v = line.split(/=/, 2)
300
+ @table[k] = v.strip
301
+ end
302
+ end
303
+
304
+ def save
305
+ File.open(SAVE_FILE, 'w') {|f|
306
+ @table.each do |k, v|
307
+ f.printf "%s=%s\n", k, v if v
308
+ end
309
+ }
310
+ end
311
+
312
+ def []=(k, v)
313
+ raise InstallError, "unknown config option #{k}"\
314
+ unless ConfigTable.config_key?(k)
315
+ @table[k] = v
316
+ end
317
+
318
+ def [](key)
319
+ return nil unless @table[key]
320
+ @table[key].gsub(%r<\$([^/]+)>) { self[$1] }
321
+ end
322
+
323
+ def set_raw(key, val)
324
+ @table[key] = val
325
+ end
326
+
327
+ def get_raw(key)
328
+ @table[key]
329
+ end
330
+
331
+ end
332
+
333
+
334
+ module MetaConfigAPI
335
+
336
+ def eval_file_ifexist(fname)
337
+ instance_eval File.read(fname), fname, 1 if File.file?(fname)
338
+ end
339
+
340
+ def config_names
341
+ ConfigTable.keys
342
+ end
343
+
344
+ def config?(name)
345
+ ConfigTable.config_key?(name)
346
+ end
347
+
348
+ def bool_config?(name)
349
+ ConfigTable.bool_config?(name)
350
+ end
351
+
352
+ def value_config?(name)
353
+ ConfigTable.value_config?(name)
354
+ end
355
+
356
+ def path_config?(name)
357
+ ConfigTable.path_config?(name)
358
+ end
359
+
360
+ def add_config(name, argname, default, desc)
361
+ ConfigTable.add_entry name,[default,argname,desc]
362
+ end
363
+
364
+ def add_path_config(name, default, desc)
365
+ add_config name, 'path', default, desc
366
+ end
367
+
368
+ def add_bool_config(name, default, desc)
369
+ add_config name, 'yes/no', default ? 'yes' : 'no', desc
370
+ end
371
+
372
+ def set_config_default(name, default)
373
+ if bool_config?(name)
374
+ ConfigTable.get_entry!(name)[0] = (default ? 'yes' : 'no')
375
+ else
376
+ ConfigTable.get_entry!(name)[0] = default
377
+ end
378
+ end
379
+
380
+ def remove_config(name)
381
+ ent = ConfigTable.get_entry(name)
382
+ ConfigTable.remove_entry name
383
+ ent
384
+ end
385
+
386
+ end
387
+
388
+ #
389
+ # File Operations
390
+ #
391
+
392
+ module FileOperations
393
+
394
+ def mkdir_p(dirname, prefix = nil)
395
+ dirname = prefix + dirname if prefix
396
+ $stderr.puts "mkdir -p #{dirname}" if verbose?
397
+ return if no_harm?
398
+
399
+ # does not check '/'... it's too abnormal case
400
+ dirs = dirname.split(%r<(?=/)>)
401
+ if /\A[a-z]:\z/i =~ dirs[0]
402
+ disk = dirs.shift
403
+ dirs[0] = disk + dirs[0]
404
+ end
405
+ dirs.each_index do |idx|
406
+ path = dirs[0..idx].join('')
407
+ Dir.mkdir path unless File.dir?(path)
408
+ end
409
+ end
410
+
411
+ def rm_f(fname)
412
+ $stderr.puts "rm -f #{fname}" if verbose?
413
+ return if no_harm?
414
+
415
+ if File.exist?(fname) or File.symlink?(fname)
416
+ File.chmod 0777, fname
417
+ File.unlink fname
418
+ end
419
+ end
420
+
421
+ def rm_rf(dn)
422
+ $stderr.puts "rm -rf #{dn}" if verbose?
423
+ return if no_harm?
424
+
425
+ Dir.chdir dn
426
+ Dir.foreach('.') do |fn|
427
+ next if fn == '.'
428
+ next if fn == '..'
429
+ if File.dir?(fn)
430
+ verbose_off {
431
+ rm_rf fn
432
+ }
433
+ else
434
+ verbose_off {
435
+ rm_f fn
436
+ }
437
+ end
438
+ end
439
+ Dir.chdir '..'
440
+ Dir.rmdir dn
441
+ end
442
+
443
+ def move_file(src, dest)
444
+ File.unlink dest if File.exist?(dest)
445
+ begin
446
+ File.rename src, dest
447
+ rescue
448
+ File.open(dest, 'wb') {|f| f.write File.binread(src) }
449
+ File.chmod File.stat(src).mode, dest
450
+ File.unlink src
451
+ end
452
+ end
453
+
454
+ def install(from, dest, mode, prefix = nil)
455
+ $stderr.puts "install #{from} #{dest}" if verbose?
456
+ return if no_harm?
457
+
458
+ realdest = prefix + dest if prefix
459
+ realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest)
460
+ str = File.binread(from)
461
+ if diff?(str, realdest)
462
+ verbose_off {
463
+ rm_f realdest if File.exist?(realdest)
464
+ }
465
+ File.open(realdest, 'wb') {|f|
466
+ f.write str
467
+ }
468
+ File.chmod mode, realdest
469
+
470
+ File.open("#{objdir_root()}/InstalledFiles", 'a') {|f|
471
+ if prefix
472
+ f.puts realdest.sub(prefix, '')
473
+ else
474
+ f.puts realdest
475
+ end
476
+ }
477
+ end
478
+ end
479
+
480
+ def diff?(new_content, path)
481
+ return true unless File.exist?(path)
482
+ new_content != File.binread(path)
483
+ end
484
+
485
+ def command(str)
486
+ $stderr.puts str if verbose?
487
+ system str or raise RuntimeError, "'system #{str}' failed"
488
+ end
489
+
490
+ def ruby(str)
491
+ command config('ruby-prog') + ' ' + str
492
+ end
493
+
494
+ def make(task = '')
495
+ command config('make-prog') + ' ' + task
496
+ end
497
+
498
+ def extdir?(dir)
499
+ File.exist?(dir + '/MANIFEST')
500
+ end
501
+
502
+ def all_files_in(dirname)
503
+ Dir.open(dirname) {|d|
504
+ return d.select {|ent| File.file?("#{dirname}/#{ent}") }
505
+ }
506
+ end
507
+
508
+ REJECT_DIRS = %w(
509
+ CVS SCCS RCS CVS.adm .svn .git
510
+ )
511
+
512
+ def all_dirs_in(dirname)
513
+ Dir.open(dirname) {|d|
514
+ return d.select {|n| File.dir?("#{dirname}/#{n}") } - %w(. ..) - REJECT_DIRS
515
+ }
516
+ end
517
+
518
+ end
519
+
520
+ #
521
+ # Main Installer
522
+ #
523
+
524
+ class InstallError < StandardError; end
525
+
526
+
527
+ module HookUtils
528
+
529
+ def run_hook(name)
530
+ try_run_hook "#{curr_srcdir()}/#{name}" or
531
+ try_run_hook "#{curr_srcdir()}/#{name}.rb"
532
+ end
533
+
534
+ def try_run_hook(fname)
535
+ return false unless File.file?(fname)
536
+ begin
537
+ instance_eval File.read(fname), fname, 1
538
+ rescue
539
+ raise InstallError, "hook #{fname} failed:\n" + $!.message
540
+ end
541
+ true
542
+ end
543
+
544
+ end
545
+
546
+
547
+ module HookScriptAPI
548
+
549
+ def get_config(key)
550
+ @config[key]
551
+ end
552
+
553
+ alias config get_config
554
+
555
+ def set_config(key, val)
556
+ @config[key] = val
557
+ end
558
+
559
+ #
560
+ # srcdir/objdir (works only in the package directory)
561
+ #
562
+
563
+ #abstract srcdir_root
564
+ #abstract objdir_root
565
+ #abstract relpath
566
+
567
+ def curr_srcdir
568
+ "#{srcdir_root()}/#{relpath()}"
569
+ end
570
+
571
+ def curr_objdir
572
+ "#{objdir_root()}/#{relpath()}"
573
+ end
574
+
575
+ def srcfile(path)
576
+ "#{curr_srcdir()}/#{path}"
577
+ end
578
+
579
+ def srcexist?(path)
580
+ File.exist?(srcfile(path))
581
+ end
582
+
583
+ def srcdirectory?(path)
584
+ File.dir?(srcfile(path))
585
+ end
586
+
587
+ def srcfile?(path)
588
+ File.file? srcfile(path)
589
+ end
590
+
591
+ def srcentries(path = '.')
592
+ Dir.open("#{curr_srcdir()}/#{path}") {|d|
593
+ return d.to_a - %w(. ..)
594
+ }
595
+ end
596
+
597
+ def srcfiles(path = '.')
598
+ srcentries(path).select {|fname|
599
+ File.file?(File.join(curr_srcdir(), path, fname))
600
+ }
601
+ end
602
+
603
+ def srcdirectories(path = '.')
604
+ srcentries(path).select {|fname|
605
+ File.dir?(File.join(curr_srcdir(), path, fname))
606
+ }
607
+ end
608
+
609
+ end
610
+
611
+
612
+ class ToplevelInstaller
613
+
614
+ Version = '3.2.4'
615
+ Copyright = 'Copyright (c) 2000-2004 Minero Aoki'
616
+
617
+ TASKS = [
618
+ [ 'config', 'saves your configurations' ],
619
+ [ 'show', 'shows current configuration' ],
620
+ [ 'setup', 'compiles ruby extentions and others' ],
621
+ [ 'install', 'installs files' ],
622
+ [ 'clean', "does `make clean' for each extention" ],
623
+ [ 'distclean',"does `make distclean' for each extention" ]
624
+ ]
625
+
626
+ def ToplevelInstaller.invoke
627
+ instance().invoke
628
+ end
629
+
630
+ @singleton = nil
631
+
632
+ def ToplevelInstaller.instance
633
+ @singleton ||= new(File.dirname($0))
634
+ @singleton
635
+ end
636
+
637
+ include MetaConfigAPI
638
+
639
+ def initialize(ardir_root)
640
+ @config = nil
641
+ @options = { 'verbose' => true }
642
+ @ardir = File.expand_path(ardir_root)
643
+ end
644
+
645
+ def inspect
646
+ "#<#{self.class} #{__id__()}>"
647
+ end
648
+
649
+ def invoke
650
+ run_metaconfigs
651
+ task = parsearg_global()
652
+ @config = load_config(task)
653
+ __send__ "parsearg_#{task}"
654
+ init_installers
655
+ __send__ "exec_#{task}"
656
+ end
657
+
658
+ def run_metaconfigs
659
+ eval_file_ifexist "#{@ardir}/metaconfig"
660
+ end
661
+
662
+ def load_config(task)
663
+ case task
664
+ when 'config'
665
+ ConfigTable.new
666
+ when 'clean', 'distclean'
667
+ if File.exist?('config.save')
668
+ then ConfigTable.load
669
+ else ConfigTable.new
670
+ end
671
+ else
672
+ ConfigTable.load
673
+ end
674
+ end
675
+
676
+ def init_installers
677
+ @installer = Installer.new(@config, @options, @ardir, File.expand_path('.'))
678
+ end
679
+
680
+ #
681
+ # Hook Script API bases
682
+ #
683
+
684
+ def srcdir_root
685
+ @ardir
686
+ end
687
+
688
+ def objdir_root
689
+ '.'
690
+ end
691
+
692
+ def relpath
693
+ '.'
694
+ end
695
+
696
+ #
697
+ # Option Parsing
698
+ #
699
+
700
+ def parsearg_global
701
+ valid_task = /\A(?:#{TASKS.map {|task,desc| task }.join '|'})\z/
702
+
703
+ while arg = ARGV.shift
704
+ case arg
705
+ when /\A\w+\z/
706
+ raise InstallError, "invalid task: #{arg}" unless valid_task =~ arg
707
+ return arg
708
+
709
+ when '-q', '--quiet'
710
+ @options['verbose'] = false
711
+
712
+ when '--verbose'
713
+ @options['verbose'] = true
714
+
715
+ when '-h', '--help'
716
+ print_usage $stdout
717
+ exit 0
718
+
719
+ when '-v', '--version'
720
+ puts "#{File.basename($0)} version #{Version}"
721
+ exit 0
722
+
723
+ when '--copyright'
724
+ puts Copyright
725
+ exit 0
726
+
727
+ else
728
+ raise InstallError, "unknown global option '#{arg}'"
729
+ end
730
+ end
731
+
732
+ raise InstallError, <<EOS
733
+ No task or global option given.
734
+ Typical installation procedure is:
735
+ $ ruby #{File.basename($0)} config
736
+ $ ruby #{File.basename($0)} setup
737
+ # ruby #{File.basename($0)} install (may require root privilege)
738
+ EOS
739
+ end
740
+
741
+
742
+ def parsearg_no_options
743
+ raise InstallError, "#{task}: unknown options: #{ARGV.join ' '}"\
744
+ unless ARGV.empty?
745
+ end
746
+
747
+ alias parsearg_show parsearg_no_options
748
+ alias parsearg_setup parsearg_no_options
749
+ alias parsearg_clean parsearg_no_options
750
+ alias parsearg_distclean parsearg_no_options
751
+
752
+ def parsearg_config
753
+ re = /\A--(#{ConfigTable.keys.join '|'})(?:=(.*))?\z/
754
+ @options['config-opt'] = []
755
+
756
+ while i = ARGV.shift
757
+ if /\A--?\z/ =~ i
758
+ @options['config-opt'] = ARGV.dup
759
+ break
760
+ end
761
+ m = re.match(i) or raise InstallError, "config: unknown option #{i}"
762
+ name, value = m.to_a[1,2]
763
+ if value
764
+ if ConfigTable.bool_config?(name)
765
+ raise InstallError, "config: --#{name} allows only yes/no for argument"\
766
+ unless /\A(y(es)?|n(o)?|t(rue)?|f(alse))\z/i =~ value
767
+ value = (/\Ay(es)?|\At(rue)/i =~ value) ? 'yes' : 'no'
768
+ end
769
+ else
770
+ raise InstallError, "config: --#{name} requires argument"\
771
+ unless ConfigTable.bool_config?(name)
772
+ value = 'yes'
773
+ end
774
+ @config[name] = value
775
+ end
776
+ end
777
+
778
+ def parsearg_install
779
+ @options['no-harm'] = false
780
+ @options['install-prefix'] = ''
781
+ while a = ARGV.shift
782
+ case a
783
+ when /\A--no-harm\z/
784
+ @options['no-harm'] = true
785
+ when /\A--prefix=(.*)\z/
786
+ path = $1
787
+ path = File.expand_path(path) unless path[0,1] == '/'
788
+ @options['install-prefix'] = path
789
+ else
790
+ raise InstallError, "install: unknown option #{a}"
791
+ end
792
+ end
793
+ end
794
+
795
+ def print_usage(out)
796
+ out.puts 'Typical Installation Procedure:'
797
+ out.puts " $ ruby #{File.basename $0} config"
798
+ out.puts " $ ruby #{File.basename $0} setup"
799
+ out.puts " # ruby #{File.basename $0} install (may require root privilege)"
800
+ out.puts
801
+ out.puts 'Detailed Usage:'
802
+ out.puts " ruby #{File.basename $0} <global option>"
803
+ out.puts " ruby #{File.basename $0} [<global options>] <task> [<task options>]"
804
+
805
+ fmt = " %-20s %s\n"
806
+ out.puts
807
+ out.puts 'Global options:'
808
+ out.printf fmt, '-q,--quiet', 'suppress message outputs'
809
+ out.printf fmt, ' --verbose', 'output messages verbosely'
810
+ out.printf fmt, '-h,--help', 'print this message'
811
+ out.printf fmt, '-v,--version', 'print version and quit'
812
+ out.printf fmt, ' --copyright', 'print copyright and quit'
813
+
814
+ out.puts
815
+ out.puts 'Tasks:'
816
+ TASKS.each do |name, desc|
817
+ out.printf " %-10s %s\n", name, desc
818
+ end
819
+
820
+ out.puts
821
+ out.puts 'Options for config:'
822
+ ConfigTable.each_definition do |name, (default, arg, desc, default2)|
823
+ out.printf " %-20s %s [%s]\n",
824
+ '--'+ name + (ConfigTable.bool_config?(name) ? '' : '='+arg),
825
+ desc,
826
+ default2 || default
827
+ end
828
+ out.printf " %-20s %s [%s]\n",
829
+ '--rbconfig=path', 'your rbconfig.rb to load', "running ruby's"
830
+
831
+ out.puts
832
+ out.puts 'Options for install:'
833
+ out.printf " %-20s %s [%s]\n",
834
+ '--no-harm', 'only display what to do if given', 'off'
835
+ out.printf " %-20s %s [%s]\n",
836
+ '--prefix', 'install path prefix', '$prefix'
837
+
838
+ out.puts
839
+ end
840
+
841
+ #
842
+ # Task Handlers
843
+ #
844
+
845
+ def exec_config
846
+ @installer.exec_config
847
+ @config.save # must be final
848
+ end
849
+
850
+ def exec_setup
851
+ @installer.exec_setup
852
+ end
853
+
854
+ def exec_install
855
+ @installer.exec_install
856
+ end
857
+
858
+ def exec_show
859
+ ConfigTable.each_name do |k|
860
+ v = @config.get_raw(k)
861
+ if not v or v.empty?
862
+ v = '(not specified)'
863
+ end
864
+ printf "%-10s %s\n", k, v
865
+ end
866
+ end
867
+
868
+ def exec_clean
869
+ @installer.exec_clean
870
+ end
871
+
872
+ def exec_distclean
873
+ @installer.exec_distclean
874
+ end
875
+
876
+ end
877
+
878
+
879
+ class ToplevelInstallerMulti < ToplevelInstaller
880
+
881
+ include HookUtils
882
+ include HookScriptAPI
883
+ include FileOperations
884
+
885
+ def initialize(ardir)
886
+ super
887
+ @packages = all_dirs_in("#{@ardir}/packages")
888
+ raise 'no package exists' if @packages.empty?
889
+ end
890
+
891
+ def run_metaconfigs
892
+ eval_file_ifexist "#{@ardir}/metaconfig"
893
+ @packages.each do |name|
894
+ eval_file_ifexist "#{@ardir}/packages/#{name}/metaconfig"
895
+ end
896
+ end
897
+
898
+ def init_installers
899
+ @installers = {}
900
+ @packages.each do |pack|
901
+ @installers[pack] = Installer.new(@config, @options,
902
+ "#{@ardir}/packages/#{pack}",
903
+ "packages/#{pack}")
904
+ end
905
+
906
+ with = extract_selection(config('with'))
907
+ without = extract_selection(config('without'))
908
+ @selected = @installers.keys.select {|name|
909
+ (with.empty? or with.include?(name)) \
910
+ and not without.include?(name)
911
+ }
912
+ end
913
+
914
+ def extract_selection(list)
915
+ a = list.split(/,/)
916
+ a.each do |name|
917
+ raise InstallError, "no such package: #{name}" \
918
+ unless @installers.key?(name)
919
+ end
920
+ a
921
+ end
922
+
923
+ def print_usage(f)
924
+ super
925
+ f.puts 'Inluded packages:'
926
+ f.puts ' ' + @packages.sort.join(' ')
927
+ f.puts
928
+ end
929
+
930
+ #
931
+ # multi-package metaconfig API
932
+ #
933
+
934
+ attr_reader :packages
935
+
936
+ def declare_packages(list)
937
+ raise 'package list is empty' if list.empty?
938
+ list.each do |name|
939
+ raise "directory packages/#{name} does not exist"\
940
+ unless File.dir?("#{@ardir}/packages/#{name}")
941
+ end
942
+ @packages = list
943
+ end
944
+
945
+ #
946
+ # Task Handlers
947
+ #
948
+
949
+ def exec_config
950
+ run_hook 'pre-config'
951
+ each_selected_installers {|inst| inst.exec_config }
952
+ run_hook 'post-config'
953
+ @config.save # must be final
954
+ end
955
+
956
+ def exec_setup
957
+ run_hook 'pre-setup'
958
+ each_selected_installers {|inst| inst.exec_setup }
959
+ run_hook 'post-setup'
960
+ end
961
+
962
+ def exec_install
963
+ run_hook 'pre-install'
964
+ each_selected_installers {|inst| inst.exec_install }
965
+ run_hook 'post-install'
966
+ end
967
+
968
+ def exec_clean
969
+ rm_f 'config.save'
970
+ run_hook 'pre-clean'
971
+ each_selected_installers {|inst| inst.exec_clean }
972
+ run_hook 'post-clean'
973
+ end
974
+
975
+ def exec_distclean
976
+ rm_f 'config.save'
977
+ run_hook 'pre-distclean'
978
+ each_selected_installers {|inst| inst.exec_distclean }
979
+ run_hook 'post-distclean'
980
+ end
981
+
982
+ #
983
+ # lib
984
+ #
985
+
986
+ def each_selected_installers
987
+ Dir.mkdir 'packages' unless File.dir?('packages')
988
+ @selected.each do |pack|
989
+ $stderr.puts "Processing the package `#{pack}' ..." if @options['verbose']
990
+ Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}")
991
+ Dir.chdir "packages/#{pack}"
992
+ yield @installers[pack]
993
+ Dir.chdir '../..'
994
+ end
995
+ end
996
+
997
+ def verbose?
998
+ @options['verbose']
999
+ end
1000
+
1001
+ def no_harm?
1002
+ @options['no-harm']
1003
+ end
1004
+
1005
+ end
1006
+
1007
+
1008
+ class Installer
1009
+
1010
+ FILETYPES = %w( bin lib ext data )
1011
+
1012
+ include HookScriptAPI
1013
+ include HookUtils
1014
+ include FileOperations
1015
+
1016
+ def initialize(config, opt, srcroot, objroot)
1017
+ @config = config
1018
+ @options = opt
1019
+ @srcdir = File.expand_path(srcroot)
1020
+ @objdir = File.expand_path(objroot)
1021
+ @currdir = '.'
1022
+ end
1023
+
1024
+ def inspect
1025
+ "#<#{self.class} #{File.basename(@srcdir)}>"
1026
+ end
1027
+
1028
+ #
1029
+ # Hook Script API bases
1030
+ #
1031
+
1032
+ def srcdir_root
1033
+ @srcdir
1034
+ end
1035
+
1036
+ def objdir_root
1037
+ @objdir
1038
+ end
1039
+
1040
+ def relpath
1041
+ @currdir
1042
+ end
1043
+
1044
+ #
1045
+ # configs/options
1046
+ #
1047
+
1048
+ def no_harm?
1049
+ @options['no-harm']
1050
+ end
1051
+
1052
+ def verbose?
1053
+ @options['verbose']
1054
+ end
1055
+
1056
+ def verbose_off
1057
+ begin
1058
+ save, @options['verbose'] = @options['verbose'], false
1059
+ yield
1060
+ ensure
1061
+ @options['verbose'] = save
1062
+ end
1063
+ end
1064
+
1065
+ #
1066
+ # TASK config
1067
+ #
1068
+
1069
+ def exec_config
1070
+ exec_task_traverse 'config'
1071
+ end
1072
+
1073
+ def config_dir_bin(rel)
1074
+ end
1075
+
1076
+ def config_dir_lib(rel)
1077
+ end
1078
+
1079
+ def config_dir_ext(rel)
1080
+ extconf if extdir?(curr_srcdir())
1081
+ end
1082
+
1083
+ def extconf
1084
+ opt = @options['config-opt'].join(' ')
1085
+ command "#{config('ruby-prog')} #{curr_srcdir()}/extconf.rb #{opt}"
1086
+ end
1087
+
1088
+ def config_dir_data(rel)
1089
+ end
1090
+
1091
+ #
1092
+ # TASK setup
1093
+ #
1094
+
1095
+ def exec_setup
1096
+ exec_task_traverse 'setup'
1097
+ end
1098
+
1099
+ def setup_dir_bin(rel)
1100
+ all_files_in(curr_srcdir()).each do |fname|
1101
+ adjust_shebang "#{curr_srcdir()}/#{fname}"
1102
+ end
1103
+ end
1104
+
1105
+ # modify: #!/usr/bin/ruby
1106
+ # modify: #! /usr/bin/ruby
1107
+ # modify: #!ruby
1108
+ # not modify: #!/usr/bin/env ruby
1109
+ SHEBANG_RE = /\A\#!\s*\S*ruby\S*/
1110
+
1111
+ def adjust_shebang(path)
1112
+ return if no_harm?
1113
+
1114
+ tmpfile = File.basename(path) + '.tmp'
1115
+ begin
1116
+ File.open(path, 'rb') {|r|
1117
+ File.open(tmpfile, 'wb') {|w|
1118
+ first = r.gets
1119
+ return unless SHEBANG_RE =~ first
1120
+
1121
+ $stderr.puts "adjusting shebang: #{File.basename path}" if verbose?
1122
+ w.print first.sub(SHEBANG_RE, '#!' + config('ruby-path'))
1123
+ w.write r.read
1124
+ }
1125
+ }
1126
+ move_file tmpfile, File.basename(path)
1127
+ ensure
1128
+ File.unlink tmpfile if File.exist?(tmpfile)
1129
+ end
1130
+ end
1131
+
1132
+ def setup_dir_lib(rel)
1133
+ end
1134
+
1135
+ def setup_dir_ext(rel)
1136
+ make if extdir?(curr_srcdir())
1137
+ end
1138
+
1139
+ def setup_dir_data(rel)
1140
+ end
1141
+
1142
+ #
1143
+ # TASK install
1144
+ #
1145
+
1146
+ def exec_install
1147
+ exec_task_traverse 'install'
1148
+ end
1149
+
1150
+ def install_dir_bin(rel)
1151
+ install_files collect_filenames_auto(), "#{config('bin-dir')}/#{rel}", 0755
1152
+ end
1153
+
1154
+ def install_dir_lib(rel)
1155
+ install_files ruby_scripts(), "#{config('rb-dir')}/#{rel}", 0644
1156
+ end
1157
+
1158
+ def install_dir_ext(rel)
1159
+ return unless extdir?(curr_srcdir())
1160
+ install_files ruby_extentions('.'),
1161
+ "#{config('so-dir')}/#{File.dirname(rel)}",
1162
+ 0555
1163
+ end
1164
+
1165
+ def install_dir_data(rel)
1166
+ install_files collect_filenames_auto(), "#{config('data-dir')}/#{rel}", 0644
1167
+ end
1168
+
1169
+ def install_files(list, dest, mode)
1170
+ mkdir_p dest, @options['install-prefix']
1171
+ list.each do |fname|
1172
+ install fname, dest, mode, @options['install-prefix']
1173
+ end
1174
+ end
1175
+
1176
+ def ruby_scripts
1177
+ collect_filenames_auto().select {|n| /\.(rb|yml)\z/ =~ n }
1178
+ end
1179
+
1180
+ # picked up many entries from cvs-1.11.1/src/ignore.c
1181
+ reject_patterns = %w(
1182
+ core RCSLOG tags TAGS .make.state
1183
+ .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb
1184
+ *~ *.old *.bak *.BAK *.orig *.rej _$* *$
1185
+
1186
+ *.org *.in .*
1187
+ )
1188
+ mapping = {
1189
+ '.' => '\.',
1190
+ '$' => '\$',
1191
+ '#' => '\#',
1192
+ '*' => '.*'
1193
+ }
1194
+ REJECT_PATTERNS = Regexp.new('\A(?:' +
1195
+ reject_patterns.map {|pat|
1196
+ pat.gsub(/[\.\$\#\*]/) {|ch| mapping[ch] }
1197
+ }.join('|') +
1198
+ ')\z')
1199
+
1200
+ def collect_filenames_auto
1201
+ mapdir((existfiles() - hookfiles()).reject {|fname|
1202
+ REJECT_PATTERNS =~ fname
1203
+ })
1204
+ end
1205
+
1206
+ def existfiles
1207
+ all_files_in(curr_srcdir()) | all_files_in('.')
1208
+ end
1209
+
1210
+ def hookfiles
1211
+ %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt|
1212
+ %w( config setup install clean ).map {|t| sprintf(fmt, t) }
1213
+ }.flatten
1214
+ end
1215
+
1216
+ def mapdir(filelist)
1217
+ filelist.map {|fname|
1218
+ if File.exist?(fname) # objdir
1219
+ fname
1220
+ else # srcdir
1221
+ File.join(curr_srcdir(), fname)
1222
+ end
1223
+ }
1224
+ end
1225
+
1226
+ def ruby_extentions(dir)
1227
+ _ruby_extentions(dir) or
1228
+ raise InstallError, "no ruby extention exists: 'ruby #{$0} setup' first"
1229
+ end
1230
+
1231
+ DLEXT = /\.#{ ::RbConfig::CONFIG['DLEXT'] }\z/
1232
+
1233
+ def _ruby_extentions(dir)
1234
+ Dir.open(dir) {|d|
1235
+ return d.select {|fname| DLEXT =~ fname }
1236
+ }
1237
+ end
1238
+
1239
+ #
1240
+ # TASK clean
1241
+ #
1242
+
1243
+ def exec_clean
1244
+ exec_task_traverse 'clean'
1245
+ rm_f 'config.save'
1246
+ rm_f 'InstalledFiles'
1247
+ end
1248
+
1249
+ def clean_dir_bin(rel)
1250
+ end
1251
+
1252
+ def clean_dir_lib(rel)
1253
+ end
1254
+
1255
+ def clean_dir_ext(rel)
1256
+ return unless extdir?(curr_srcdir())
1257
+ make 'clean' if File.file?('Makefile')
1258
+ end
1259
+
1260
+ def clean_dir_data(rel)
1261
+ end
1262
+
1263
+ #
1264
+ # TASK distclean
1265
+ #
1266
+
1267
+ def exec_distclean
1268
+ exec_task_traverse 'distclean'
1269
+ rm_f 'config.save'
1270
+ rm_f 'InstalledFiles'
1271
+ end
1272
+
1273
+ def distclean_dir_bin(rel)
1274
+ end
1275
+
1276
+ def distclean_dir_lib(rel)
1277
+ end
1278
+
1279
+ def distclean_dir_ext(rel)
1280
+ return unless extdir?(curr_srcdir())
1281
+ make 'distclean' if File.file?('Makefile')
1282
+ end
1283
+
1284
+ #
1285
+ # lib
1286
+ #
1287
+
1288
+ def exec_task_traverse(task)
1289
+ run_hook "pre-#{task}"
1290
+ FILETYPES.each do |type|
1291
+ if config('without-ext') == 'yes' and type == 'ext'
1292
+ $stderr.puts 'skipping ext/* by user option' if verbose?
1293
+ next
1294
+ end
1295
+ traverse task, type, "#{task}_dir_#{type}"
1296
+ end
1297
+ run_hook "post-#{task}"
1298
+ end
1299
+
1300
+ def traverse(task, rel, mid)
1301
+ dive_into(rel) {
1302
+ run_hook "pre-#{task}"
1303
+ __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '')
1304
+ all_dirs_in(curr_srcdir()).each do |d|
1305
+ traverse task, "#{rel}/#{d}", mid
1306
+ end
1307
+ run_hook "post-#{task}"
1308
+ }
1309
+ end
1310
+
1311
+ def dive_into(rel)
1312
+ return unless File.dir?("#{@srcdir}/#{rel}")
1313
+
1314
+ dir = File.basename(rel)
1315
+ Dir.mkdir dir unless File.dir?(dir)
1316
+ prevdir = Dir.pwd
1317
+ Dir.chdir dir
1318
+ $stderr.puts '---> ' + rel if verbose?
1319
+ @currdir = rel
1320
+ yield
1321
+ Dir.chdir prevdir
1322
+ $stderr.puts '<--- ' + rel if verbose?
1323
+ @currdir = File.dirname(rel)
1324
+ end
1325
+
1326
+ end
1327
+
1328
+
1329
+ if $0 == __FILE__
1330
+ begin
1331
+ if multipackage_install?
1332
+ ToplevelInstallerMulti.invoke
1333
+ else
1334
+ ToplevelInstaller.invoke
1335
+ end
1336
+ rescue
1337
+ raise if $DEBUG
1338
+ $stderr.puts $!.message
1339
+ $stderr.puts "Try 'ruby #{$0} --help' for detailed usage."
1340
+ exit 1
1341
+ end
1342
+ end