libxml-ruby 0.5.2.0 → 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. data/CHANGES +122 -0
  2. data/LICENSE +2 -1
  3. data/MANIFEST +138 -0
  4. data/NOTES +9 -0
  5. data/README +1 -1
  6. data/Rakefile +27 -205
  7. data/TODO +0 -2
  8. data/VERSION +1 -0
  9. data/ext/{xml → libxml}/cbg.c +0 -0
  10. data/ext/libxml/extconf.rb +309 -0
  11. data/ext/{xml → libxml}/libxml.c +1 -1
  12. data/ext/{xml → libxml}/libxml.h +7 -4
  13. data/ext/{xml → libxml}/ruby_xml_attr.c +1 -1
  14. data/ext/{xml → libxml}/ruby_xml_attr.h +1 -1
  15. data/ext/{xml → libxml}/ruby_xml_document.c +16 -8
  16. data/ext/{xml → libxml}/ruby_xml_document.h +1 -1
  17. data/ext/{xml → libxml}/ruby_xml_dtd.c +0 -0
  18. data/ext/{xml → libxml}/ruby_xml_dtd.h +0 -0
  19. data/ext/{xml → libxml}/ruby_xml_html_parser.c +1 -1
  20. data/ext/{xml → libxml}/ruby_xml_html_parser.h +1 -1
  21. data/ext/{xml → libxml}/ruby_xml_input_cbg.c +0 -0
  22. data/ext/{xml → libxml}/ruby_xml_input_cbg.h +0 -0
  23. data/ext/{xml → libxml}/ruby_xml_node.c +47 -6
  24. data/ext/{xml → libxml}/ruby_xml_node.h +1 -1
  25. data/ext/{xml → libxml}/ruby_xml_node_set.c +1 -1
  26. data/ext/{xml → libxml}/ruby_xml_node_set.h +1 -1
  27. data/ext/{xml → libxml}/ruby_xml_ns.c +1 -1
  28. data/ext/{xml → libxml}/ruby_xml_ns.h +1 -1
  29. data/ext/{xml → libxml}/ruby_xml_parser.c +6 -4
  30. data/ext/{xml → libxml}/ruby_xml_parser.h +1 -1
  31. data/ext/{xml → libxml}/ruby_xml_parser_context.c +1 -1
  32. data/ext/{xml → libxml}/ruby_xml_parser_context.h +1 -1
  33. data/ext/{xml → libxml}/ruby_xml_reader.c +3 -0
  34. data/ext/{xml → libxml}/ruby_xml_reader.h +0 -0
  35. data/ext/{xml → libxml}/ruby_xml_sax_parser.c +1 -1
  36. data/ext/{xml → libxml}/ruby_xml_sax_parser.h +1 -1
  37. data/ext/{xml → libxml}/ruby_xml_schema.c +0 -0
  38. data/ext/{xml → libxml}/ruby_xml_schema.h +0 -0
  39. data/ext/{xml → libxml}/ruby_xml_state.c +0 -0
  40. data/ext/{xml → libxml}/ruby_xml_state.h +0 -0
  41. data/ext/{xml → libxml}/ruby_xml_tree.c +1 -1
  42. data/ext/{xml → libxml}/ruby_xml_tree.h +1 -1
  43. data/ext/{xml → libxml}/ruby_xml_xinclude.c +1 -1
  44. data/ext/{xml → libxml}/ruby_xml_xinclude.h +1 -1
  45. data/ext/{xml → libxml}/ruby_xml_xpath.c +7 -4
  46. data/ext/{xml → libxml}/ruby_xml_xpath.h +1 -1
  47. data/ext/{xml → libxml}/ruby_xml_xpath_context.c +1 -1
  48. data/ext/{xml → libxml}/ruby_xml_xpath_context.h +1 -1
  49. data/ext/{xml → libxml}/ruby_xml_xpath_object.c +65 -32
  50. data/ext/{xml → libxml}/ruby_xml_xpath_object.h +0 -0
  51. data/ext/{xml → libxml}/ruby_xml_xpointer.c +1 -1
  52. data/ext/{xml → libxml}/ruby_xml_xpointer.h +1 -1
  53. data/ext/{xml → libxml}/ruby_xml_xpointer_context.c +1 -1
  54. data/ext/{xml → libxml}/ruby_xml_xpointer_context.h +1 -1
  55. data/ext/{xml → libxml}/sax_parser_callbacks.inc +1 -1
  56. data/ext/libxml/version.h +9 -0
  57. data/{ext/xml → lib}/libxml.rb +7 -2
  58. data/lib/xml/libxml.rb +5 -0
  59. data/{ChangeLog → log/Changelog-0.txt} +0 -0
  60. data/log/Changelog.txt +435 -0
  61. data/meta/project.yaml +27 -0
  62. data/meta/unixname +1 -0
  63. data/setup.rb +1469 -0
  64. data/site/css/normal.css +182 -0
  65. data/site/img/raze-tiny.png +0 -0
  66. data/site/img/red-cube.jpg +0 -0
  67. data/site/img/xml-ruby.png +0 -0
  68. data/site/index.xml +43 -0
  69. data/site/install.xml +77 -0
  70. data/site/layout.rhtml +38 -0
  71. data/site/layout.xsl +67 -0
  72. data/site/license.xml +32 -0
  73. data/site/log/changelog.xml +1324 -0
  74. data/site/log/changelog.xsl +42 -0
  75. data/{tests → test}/dtd-test.rb +2 -2
  76. data/test/etc_doc_to_s.rb +21 -0
  77. data/test/ets_copy_bug.rb +21 -0
  78. data/test/ets_copy_bug2.rb +32 -0
  79. data/test/ets_doc_file.rb +14 -0
  80. data/test/ets_doc_to_s.rb +21 -0
  81. data/test/ets_gpx.rb +26 -0
  82. data/test/ets_node_gc.rb +21 -0
  83. data/test/ets_test.xml +2 -0
  84. data/test/ets_tsr.rb +9 -0
  85. data/{tests → test}/merge_bug.rb +4 -5
  86. data/{tests → test}/model/default_validation_bug.rb +0 -0
  87. data/{tests → test}/model/merge_bug_data.xml +0 -0
  88. data/{tests → test}/model/rubynet.xml +0 -0
  89. data/{tests → test}/model/rubynet_project +1 -1
  90. data/{tests → test}/model/saxtest.xml +0 -0
  91. data/{tests → test}/model/simple.xml +0 -0
  92. data/{tests → test}/model/xinclude.xml +0 -0
  93. data/{tests → test}/schema-test.rb +2 -2
  94. data/{tests → test}/tc_xml_document.rb +2 -2
  95. data/{tests → test}/tc_xml_document_write.rb +1 -2
  96. data/{tests → test}/tc_xml_document_write2.rb +1 -2
  97. data/{tests → test}/tc_xml_document_write3.rb +1 -2
  98. data/{tests → test}/tc_xml_html_parser.rb +7 -8
  99. data/{tests → test}/tc_xml_node.rb +1 -2
  100. data/{tests → test}/tc_xml_node2.rb +1 -2
  101. data/{tests → test}/tc_xml_node3.rb +2 -3
  102. data/{tests → test}/tc_xml_node4.rb +19 -20
  103. data/{tests → test}/tc_xml_node5.rb +8 -9
  104. data/{tests → test}/tc_xml_node6.rb +1 -2
  105. data/{tests → test}/tc_xml_node7.rb +5 -6
  106. data/{tests → test}/tc_xml_node8.rb +5 -5
  107. data/{tests → test}/tc_xml_node9.rb +5 -5
  108. data/test/tc_xml_node_copy.rb +40 -0
  109. data/{tests → test}/tc_xml_node_set.rb +2 -3
  110. data/{tests → test}/tc_xml_node_set2.rb +4 -5
  111. data/test/tc_xml_node_text.rb +17 -0
  112. data/{tests → test}/tc_xml_node_xlink.rb +2 -2
  113. data/{tests → test}/tc_xml_parser.rb +5 -6
  114. data/{tests → test}/tc_xml_parser2.rb +2 -2
  115. data/{tests → test}/tc_xml_parser3.rb +2 -2
  116. data/{tests → test}/tc_xml_parser4.rb +2 -2
  117. data/{tests → test}/tc_xml_parser5.rb +2 -2
  118. data/{tests → test}/tc_xml_parser6.rb +3 -3
  119. data/{tests → test}/tc_xml_parser7.rb +3 -3
  120. data/{tests → test}/tc_xml_parser8.rb +13 -13
  121. data/{tests → test}/tc_xml_parser_context.rb +1 -2
  122. data/{tests → test}/tc_xml_reader.rb +22 -14
  123. data/{tests → test}/tc_xml_sax_parser.rb +21 -22
  124. data/{tests → test}/tc_xml_xinclude.rb +4 -4
  125. data/{tests → test}/tc_xml_xpath.rb +17 -3
  126. data/{tests → test}/tc_xml_xpointer.rb +4 -5
  127. metadata +231 -158
  128. data/CHANGELOG_to200701 +0 -82
  129. data/ext/xml/extconf.rb +0 -98
  130. data/tests/libxml_test.rb +0 -3
  131. data/tests/runner.rb +0 -11
data/meta/project.yaml ADDED
@@ -0,0 +1,27 @@
1
+ ---
2
+ project : libxml-ruby
3
+ title : LibXML-Ruby
4
+ summary : Ruby Bindings for GNU/LibXML2
5
+ description :
6
+ LibXML-Ruby provides bindings to the GNU LibXML2 library.
7
+ homepage : "http://libxml.rubyforge.org"
8
+ repository : "http://libxml.rubyforge.org/svn/"
9
+ contact : Dan Janwoski <danj at 3skel.com>
10
+ authors:
11
+ - Dan Janwoski
12
+ - Ross Bamform
13
+ - Sean Chittenden
14
+ creator : Sean Chittenden
15
+ created : "2004-12-28"
16
+
17
+ default : libxml.rb
18
+ loadpath :
19
+ - lib
20
+ - ext/libxml
21
+
22
+ # Packaging Information
23
+
24
+ exclude : ['work', 'doc', 'ri']
25
+ extensions :
26
+ - ext/libxml/extconf.rb
27
+
data/meta/unixname ADDED
@@ -0,0 +1 @@
1
+ libxml-ruby
data/setup.rb ADDED
@@ -0,0 +1,1469 @@
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
+ reslv = "(none)" if String===reslv && reslv.empty?
325
+ printf fmt, name, reslv if value
326
+ end
327
+ end
328
+
329
+ #
330
+
331
+ def extconfs
332
+ @extconfs ||= Dir['ext/**/extconf.rb']
333
+ end
334
+
335
+ def extensions
336
+ @extensions ||= extconfs.collect{ |f| File.dirname(f) }
337
+ end
338
+
339
+ def compiles?
340
+ !extensions.empty?
341
+ end
342
+
343
+ private
344
+
345
+ # Get unresloved attribute.
346
+ def [](name)
347
+ instance_variable_get("@#{name}")
348
+ end
349
+
350
+ # Set attribute.
351
+ def []=(name, value)
352
+ instance_variable_set("@#{name}", value)
353
+ end
354
+
355
+ # Resolved attribute. (for paths)
356
+ #def resolve(name)
357
+ # self[name].gsub(%r<\\$([^/]+)>){ self[$1] }
358
+ #end
359
+
360
+ end
361
+
362
+ # Installer class handles the actual install procedure,
363
+ # as well as the other tasks, such as testing.
364
+
365
+ class Installer
366
+
367
+ MANIFEST = '.installedfiles'
368
+
369
+ FILETYPES = %w( bin lib ext data conf man doc )
370
+
371
+ TASK_DESCRIPTIONS = [
372
+ [ 'all', 'do config, setup, then install' ],
373
+ [ 'config', 'saves your configurations' ],
374
+ [ 'show', 'shows current configuration' ],
375
+ [ 'setup', 'compiles ruby extentions and others' ],
376
+ [ 'doc', 'generate html documentation' ],
377
+ [ 'index', 'generate index documentation' ],
378
+ [ 'install', 'installs files' ],
379
+ [ 'test', 'run all tests in test/' ],
380
+ [ 'clean', "does `make clean' for each extention" ],
381
+ [ 'distclean',"does `make distclean' for each extention" ]
382
+ ]
383
+
384
+ TASKS = %w(all config show setup test install uninstall doc index clean distclean)
385
+
386
+ # Configuration
387
+ attr :config
388
+
389
+ attr_writer :no_harm
390
+ attr_writer :verbose
391
+ attr_writer :quiet
392
+
393
+ attr_accessor :install_prefix
394
+
395
+ # New Installer.
396
+ def initialize #:yield:
397
+ srcroot = '.'
398
+ objroot = '.'
399
+
400
+ @config = ConfigTable.new
401
+
402
+ @srcdir = File.expand_path(srcroot)
403
+ @objdir = File.expand_path(objroot)
404
+ @currdir = '.'
405
+
406
+ self.quiet = ENV['quiet'] if ENV['quiet']
407
+ self.verbose = ENV['verbose'] if ENV['verbose']
408
+ self.no_harm = ENV['nowrite'] if ENV['nowrite']
409
+
410
+ yield(self) if block_given?
411
+ end
412
+
413
+ def inspect
414
+ "#<#{self.class} #{File.basename(@srcdir)}>"
415
+ end
416
+
417
+ # Are we running an installation?
418
+ def installation?; @installation; end
419
+ def installation!; @installation = true; end
420
+
421
+ def no_harm?; @no_harm; end
422
+ def verbose?; @verbose; end
423
+ def quiet?; @quiet; end
424
+
425
+ def verbose_off #:yield:
426
+ begin
427
+ save, @verbose = verbose?, false
428
+ yield
429
+ ensure
430
+ @verbose = save
431
+ end
432
+ end
433
+
434
+ # Rake task handlers
435
+ def rake_define
436
+ require 'rake/clean'
437
+
438
+ desc 'Config, setup and then install'
439
+ task :all => [:config, :setup, :install]
440
+
441
+ desc 'Saves your configurations'
442
+ task :config do exec_config end
443
+
444
+ desc 'Compiles ruby extentions'
445
+ task :setup do exec_setup end
446
+
447
+ desc 'Generate html api docs'
448
+ task :doc do exec_doc end
449
+
450
+ desc 'Generate api index docs'
451
+ task :index do exec_index end
452
+
453
+ desc 'Installs files'
454
+ task :install do exec_install end
455
+
456
+ desc 'Uninstalls files'
457
+ task :uninstall do exec_uninstall end
458
+
459
+ #desc "Does `make clean' for each extention"
460
+ task :makeclean do exec_clean end
461
+
462
+ task :clean => [:makeclean]
463
+
464
+ #desc "Does `make distclean' for each extention"
465
+ task :distclean do exec_distclean end
466
+
467
+ task :clobber => [:distclean]
468
+
469
+ desc 'Shows current configuration'
470
+ task :show do exec_show end
471
+ end
472
+
473
+ # Added these for future use in simplificaiton of design.
474
+
475
+ def extensions
476
+ @extensions ||= Dir['ext/**/extconf.rb']
477
+ end
478
+
479
+ def compiles?
480
+ !extensions.empty?
481
+ end
482
+
483
+ #
484
+ def noop(rel); end
485
+
486
+ #
487
+ # Hook Script API bases
488
+ #
489
+
490
+ def srcdir_root
491
+ @srcdir
492
+ end
493
+
494
+ def objdir_root
495
+ @objdir
496
+ end
497
+
498
+ def relpath
499
+ @currdir
500
+ end
501
+
502
+ #
503
+ # Task all
504
+ #
505
+
506
+ def exec_all
507
+ exec_config
508
+ exec_setup
509
+ exec_test # TODO: we need to stop here if tests fail (how?)
510
+ exec_doc if GENERATE_RDOCS && !config.without_doc?
511
+ exec_install
512
+ end
513
+
514
+ #
515
+ # TASK config
516
+ #
517
+
518
+ def exec_config
519
+ config.env_config
520
+ config.save_config
521
+ config.show unless quiet?
522
+ puts("Configuration saved.") unless quiet?
523
+ exec_task_traverse 'config'
524
+ end
525
+
526
+ alias config_dir_bin noop
527
+ alias config_dir_lib noop
528
+
529
+ def config_dir_ext(rel)
530
+ extconf if extdir?(curr_srcdir())
531
+ end
532
+
533
+ alias config_dir_data noop
534
+ alias config_dir_conf noop
535
+ alias config_dir_man noop
536
+ alias config_dir_doc noop
537
+
538
+ def extconf
539
+ ruby "#{curr_srcdir()}/extconf.rb", config.extconfopt
540
+ end
541
+
542
+ #
543
+ # TASK show
544
+ #
545
+
546
+ def exec_show
547
+ config.show
548
+ end
549
+
550
+ #
551
+ # TASK setup
552
+ #
553
+ # FIXME: Update shebang at time of install not before.
554
+ # for now I've commented it out the shebang.
555
+
556
+ def exec_setup
557
+ exec_task_traverse 'setup'
558
+ end
559
+
560
+ def setup_dir_bin(rel)
561
+ files_of(curr_srcdir()).each do |fname|
562
+ #update_shebang_line "#{curr_srcdir()}/#{fname}"
563
+ end
564
+ end
565
+
566
+ alias setup_dir_lib noop
567
+
568
+ def setup_dir_ext(rel)
569
+ make if extdir?(curr_srcdir())
570
+ end
571
+
572
+ alias setup_dir_data noop
573
+ alias setup_dir_conf noop
574
+ alias setup_dir_man noop
575
+ alias setup_dir_doc noop
576
+
577
+ def update_shebang_line(path)
578
+ return if no_harm?
579
+ return if config.shebang == 'never'
580
+ old = Shebang.load(path)
581
+ if old
582
+ if old.args.size > 1
583
+ $stderr.puts "warning: #{path}"
584
+ $stderr.puts "Shebang line has too many args."
585
+ $stderr.puts "It is not portable and your program may not work."
586
+ end
587
+ new = new_shebang(old)
588
+ return if new.to_s == old.to_s
589
+ else
590
+ return unless config.shebang == 'all'
591
+ new = Shebang.new(config.rubypath)
592
+ end
593
+ $stderr.puts "updating shebang: #{File.basename(path)}" if verbose?
594
+ open_atomic_writer(path) {|output|
595
+ File.open(path, 'rb') {|f|
596
+ f.gets if old # discard
597
+ output.puts new.to_s
598
+ output.print f.read
599
+ }
600
+ }
601
+ end
602
+
603
+ def new_shebang(old)
604
+ if /\Aruby/ =~ File.basename(old.cmd)
605
+ Shebang.new(config.rubypath, old.args)
606
+ elsif File.basename(old.cmd) == 'env' and old.args.first == 'ruby'
607
+ Shebang.new(config.rubypath, old.args[1..-1])
608
+ else
609
+ return old unless config.shebang == 'all'
610
+ Shebang.new(config.rubypath)
611
+ end
612
+ end
613
+
614
+ def open_atomic_writer(path, &block)
615
+ tmpfile = File.basename(path) + '.tmp'
616
+ begin
617
+ File.open(tmpfile, 'wb', &block)
618
+ File.rename tmpfile, File.basename(path)
619
+ ensure
620
+ File.unlink tmpfile if File.exist?(tmpfile)
621
+ end
622
+ end
623
+
624
+ class Shebang
625
+ def Shebang.load(path)
626
+ line = nil
627
+ File.open(path) {|f|
628
+ line = f.gets
629
+ }
630
+ return nil unless /\A#!/ =~ line
631
+ parse(line)
632
+ end
633
+
634
+ def Shebang.parse(line)
635
+ cmd, *args = *line.strip.sub(/\A\#!/, '').split(' ')
636
+ new(cmd, args)
637
+ end
638
+
639
+ def initialize(cmd, args = [])
640
+ @cmd = cmd
641
+ @args = args
642
+ end
643
+
644
+ attr_reader :cmd
645
+ attr_reader :args
646
+
647
+ def to_s
648
+ "#! #{@cmd}" + (@args.empty? ? '' : " #{@args.join(' ')}")
649
+ end
650
+ end
651
+
652
+ #
653
+ # TASK test
654
+ #
655
+ # TODO: Add spec support.
656
+
657
+ def exec_test
658
+ $stderr.puts 'Running tests...' if verbose?
659
+
660
+ runner = config.testrunner
661
+
662
+ case runner
663
+ when 'auto'
664
+ unless File.directory?('test')
665
+ $stderr.puts 'no test in this package' if verbose?
666
+ return
667
+ end
668
+ begin
669
+ require 'test/unit'
670
+ rescue LoadError
671
+ setup_rb_error 'test/unit cannot loaded. You need Ruby 1.8 or later to invoke this task.'
672
+ end
673
+ autorunner = Test::Unit::AutoRunner.new(true)
674
+ autorunner.to_run << 'test'
675
+ autorunner.run
676
+ else # use testrb
677
+ opt = []
678
+ opt << " -v" if verbose?
679
+ opt << " --runner #{runner}"
680
+ if File.file?('test/suite.rb')
681
+ notests = false
682
+ opt << "test/suite.rb"
683
+ else
684
+ notests = Dir["test/**/*.rb"].empty?
685
+ lib = ["lib"] + config.extensions.collect{ |d| File.dirname(d) }
686
+ opt << "-I" + lib.join(':')
687
+ opt << Dir["test/**/{test,tc}*.rb"]
688
+ end
689
+ opt = opt.flatten.join(' ').strip
690
+ # run tests
691
+ if notests
692
+ $stderr.puts 'no test in this package' if verbose?
693
+ else
694
+ cmd = "testrb #{opt}"
695
+ $stderr.puts cmd if verbose?
696
+ system cmd #config.ruby "-S tesrb", opt
697
+ end
698
+ end
699
+ end
700
+
701
+ # MAYBE: We could traverse and run each test independently (?)
702
+ #def test_dir_test
703
+ #end
704
+
705
+ #
706
+ # TASK doc
707
+ #
708
+
709
+ def exec_doc
710
+ output = File.join('doc', PACKAGE, 'rdoc')
711
+ title = (PACKAGE.capitalize + " API").strip
712
+ main = Dir.glob("README{,.txt}", File::FNM_CASEFOLD).first
713
+ template = config.doctemplate || 'html'
714
+
715
+ opt = []
716
+ opt << "-U"
717
+ opt << "-S"
718
+ opt << "--op=#{output}"
719
+ opt << "--template=#{template}"
720
+ opt << "--title=#{title}"
721
+ opt << "--main=#{main}" if main
722
+
723
+ if File.exist?('.document')
724
+ files = File.read('.document').split("\n")
725
+ files.reject!{ |l| l =~ /^\s*[#]/ || l !~ /\S/ }
726
+ files.collect!{ |f| f.strip }
727
+ opt << files
728
+ else
729
+ opt << main if main
730
+ opt << ["lib", "ext"]
731
+ end
732
+
733
+ opt = opt.flatten
734
+
735
+ if no_harm?
736
+ puts "rdoc " + opt.join(' ').strip
737
+ else
738
+ #sh "rdoc {opt.join(' ').strip}"
739
+ require 'rdoc/rdoc'
740
+ ::RDoc::RDoc.new.document(opt)
741
+ end
742
+ end
743
+
744
+ #
745
+ # TASK index
746
+ #
747
+ # TODO: Totally deprecate stadard ri support in favor of fastri.
748
+
749
+ def exec_index
750
+ begin
751
+ require 'fastri/version'
752
+ fastri = true
753
+ rescue LoadError
754
+ fastri = false
755
+ end
756
+ if fastri
757
+ if no_harm?
758
+ $stderr.puts "fastri-server -b"
759
+ else
760
+ system "fastri-server -b"
761
+ end
762
+ else
763
+ case config.installdirs
764
+ when 'std'
765
+ output = "--ri-system"
766
+ when 'site'
767
+ output = "--ri-site"
768
+ when 'home'
769
+ output = "--ri"
770
+ else
771
+ abort "bad config: sould not be possible -- installdirs = #{config.installdirs}"
772
+ end
773
+
774
+ if File.exist?('.document')
775
+ files = File.read('.document').split("\n")
776
+ files.reject!{ |l| l =~ /^\s*[#]/ || l !~ /\S/ }
777
+ files.collect!{ |f| f.strip }
778
+ else
779
+ files = ["lib", "ext"]
780
+ end
781
+
782
+ opt = []
783
+ opt << "-U"
784
+ opt << output
785
+ opt << files
786
+ opt = opt.flatten
787
+
788
+ if no_harm?
789
+ puts "rdoc #{opt.join(' ').strip}"
790
+ else
791
+ #sh "rdoc #{opt.join(' ').strip}"
792
+ require 'rdoc/rdoc'
793
+ ::RDoc::RDoc.new.document(opt)
794
+ end
795
+ end
796
+ end
797
+
798
+ #
799
+ # TASK install
800
+ #
801
+
802
+ def exec_install
803
+ installation! # were are installing
804
+ #rm_f MANIFEST # we'll append rather then delete!
805
+ exec_task_traverse 'install'
806
+ end
807
+
808
+ def install_dir_bin(rel)
809
+ install_files targetfiles(), "#{config.bindir}/#{rel}", 0755
810
+ end
811
+
812
+ def install_dir_lib(rel)
813
+ install_files libfiles(), "#{config.rbdir}/#{rel}", 0644
814
+ end
815
+
816
+ def install_dir_ext(rel)
817
+ return unless extdir?(curr_srcdir())
818
+ install_files rubyextentions('.'),
819
+ "#{config.sodir}/#{File.dirname(rel)}", 0555
820
+ end
821
+
822
+ def install_dir_data(rel)
823
+ install_files targetfiles(), "#{config.datadir}/#{rel}", 0644
824
+ end
825
+
826
+ def install_dir_conf(rel)
827
+ # FIXME: should not remove current config files
828
+ # (rename previous file to .old/.org)
829
+ install_files targetfiles(), "#{config.sysconfdir}/#{rel}", 0644
830
+ end
831
+
832
+ def install_dir_man(rel)
833
+ install_files targetfiles(), "#{config.mandir}/#{rel}", 0644
834
+ end
835
+
836
+ def install_dir_doc(rel)
837
+ return if config.without_doc?
838
+ install_files targetfiles(), "#{config.docdir}/#{rel}", 0644
839
+ end
840
+
841
+ def install_files(list, dest, mode)
842
+ mkdir_p dest, install_prefix
843
+ list.each do |fname|
844
+ install fname, dest, mode, install_prefix
845
+ end
846
+ end
847
+
848
+ def libfiles
849
+ glob_reject(%w(*.y *.output), targetfiles())
850
+ end
851
+
852
+ def rubyextentions(dir)
853
+ ents = glob_select("*.#{dllext}", targetfiles())
854
+ if ents.empty?
855
+ setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first"
856
+ end
857
+ ents
858
+ end
859
+
860
+ def dllext
861
+ RBCONFIG['DLEXT']
862
+ end
863
+
864
+ def targetfiles
865
+ mapdir(existfiles() - hookfiles())
866
+ end
867
+
868
+ def mapdir(ents)
869
+ ents.map {|ent|
870
+ if File.exist?(ent)
871
+ then ent # objdir
872
+ else "#{curr_srcdir()}/#{ent}" # srcdir
873
+ end
874
+ }
875
+ end
876
+
877
+ # picked up many entries from cvs-1.11.1/src/ignore.c
878
+ JUNK_FILES = %w(
879
+ core RCSLOG tags TAGS .make.state
880
+ .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb
881
+ *~ *.old *.bak *.BAK *.orig *.rej _$* *$
882
+
883
+ *.org *.in .*
884
+ )
885
+
886
+ def existfiles
887
+ glob_reject(JUNK_FILES, (files_of(curr_srcdir()) | files_of('.')))
888
+ end
889
+
890
+ def hookfiles
891
+ %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt|
892
+ %w( config setup install clean ).map {|t| sprintf(fmt, t) }
893
+ }.flatten
894
+ end
895
+
896
+ def glob_select(pat, ents)
897
+ re = globs2re([pat])
898
+ ents.select {|ent| re =~ ent }
899
+ end
900
+
901
+ def glob_reject(pats, ents)
902
+ re = globs2re(pats)
903
+ ents.reject {|ent| re =~ ent }
904
+ end
905
+
906
+ GLOB2REGEX = {
907
+ '.' => '\.',
908
+ '$' => '\$',
909
+ '#' => '\#',
910
+ '*' => '.*'
911
+ }
912
+
913
+ def globs2re(pats)
914
+ /\A(?:#{
915
+ pats.map {|pat| pat.gsub(/[\.\$\#\*]/) {|ch| GLOB2REGEX[ch] } }.join('|')
916
+ })\z/
917
+ end
918
+
919
+ #
920
+ # TASK uninstall
921
+ #
922
+
923
+ def exec_uninstall
924
+ paths = File.read(MANIFEST).split("\n")
925
+ dirs, files = paths.partition{ |f| File.dir?(f) }
926
+
927
+ files.each do |file|
928
+ next if /^\#/ =~ file # skip comments
929
+ rm_f(file) if File.exist?(file)
930
+ end
931
+
932
+ dirs.each do |dir|
933
+ # okay this is over kill, but playing it safe...
934
+ empty = Dir[File.join(dir,'*')].empty?
935
+ begin
936
+ if no_harm?
937
+ $stderr.puts "rmdir #{dir}"
938
+ else
939
+ rmdir(dir) if empty
940
+ end
941
+ rescue Errno::ENOTEMPTY
942
+ $stderr.puts "may not be empty -- #{dir}" if verbose?
943
+ end
944
+ end
945
+
946
+ rm_f(MANIFEST)
947
+ end
948
+
949
+ #
950
+ # TASK clean
951
+ #
952
+
953
+ def exec_clean
954
+ exec_task_traverse 'clean'
955
+ rm_f ConfigTable::CONFIGFILE
956
+ #rm_f MANIFEST # only on clobber!
957
+ end
958
+
959
+ alias clean_dir_bin noop
960
+ alias clean_dir_lib noop
961
+ alias clean_dir_data noop
962
+ alias clean_dir_conf noop
963
+ alias clean_dir_man noop
964
+ alias clean_dir_doc noop
965
+
966
+ def clean_dir_ext(rel)
967
+ return unless extdir?(curr_srcdir())
968
+ make 'clean' if File.file?('Makefile')
969
+ end
970
+
971
+ #
972
+ # TASK distclean
973
+ #
974
+
975
+ def exec_distclean
976
+ exec_task_traverse 'distclean'
977
+ rm_f ConfigTable::CONFIGFILE
978
+ rm_f MANIFEST
979
+ end
980
+
981
+ alias distclean_dir_bin noop
982
+ alias distclean_dir_lib noop
983
+
984
+ def distclean_dir_ext(rel)
985
+ return unless extdir?(curr_srcdir())
986
+ make 'distclean' if File.file?('Makefile')
987
+ end
988
+
989
+ alias distclean_dir_data noop
990
+ alias distclean_dir_conf noop
991
+ alias distclean_dir_man noop
992
+
993
+ def distclean_dir_doc(rel)
994
+ if GENERATE_RDOCS
995
+ rm_rf('rdoc') if File.directory?('rdoc')
996
+ end
997
+ end
998
+
999
+ #
1000
+ # Traversing
1001
+ #
1002
+
1003
+ def exec_task_traverse(task)
1004
+ run_hook "pre-#{task}"
1005
+ FILETYPES.each do |type|
1006
+ if type == 'ext' and config.without_ext == 'yes'
1007
+ $stderr.puts 'skipping ext/* by user option' if verbose?
1008
+ next
1009
+ end
1010
+ traverse task, type, "#{task}_dir_#{type}"
1011
+ end
1012
+ run_hook "post-#{task}"
1013
+ end
1014
+
1015
+ def traverse(task, rel, mid)
1016
+ dive_into(rel) {
1017
+ run_hook "pre-#{task}"
1018
+ __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '')
1019
+ directories_of(curr_srcdir()).each do |d|
1020
+ traverse task, "#{rel}/#{d}", mid
1021
+ end
1022
+ run_hook "post-#{task}"
1023
+ }
1024
+ end
1025
+
1026
+ def dive_into(rel)
1027
+ return unless File.dir?("#{@srcdir}/#{rel}")
1028
+
1029
+ dir = File.basename(rel)
1030
+ Dir.mkdir dir unless File.dir?(dir)
1031
+ prevdir = Dir.pwd
1032
+ Dir.chdir dir
1033
+ $stderr.puts '---> ' + rel if verbose?
1034
+ @currdir = rel
1035
+ yield
1036
+ Dir.chdir prevdir
1037
+ $stderr.puts '<--- ' + rel if verbose?
1038
+ @currdir = File.dirname(rel)
1039
+ end
1040
+
1041
+ def run_hook(id)
1042
+ path = [ "#{curr_srcdir()}/#{id}",
1043
+ "#{curr_srcdir()}/#{id}.rb" ].detect {|cand| File.file?(cand) }
1044
+ return unless path
1045
+ begin
1046
+ instance_eval File.read(path), path, 1
1047
+ rescue
1048
+ raise if $DEBUG
1049
+ setup_rb_error "hook #{path} failed:\n" + $!.message
1050
+ end
1051
+ end
1052
+
1053
+ # File Operations
1054
+ #
1055
+ # This module requires: #verbose?, #no_harm?
1056
+
1057
+ def binread(fname)
1058
+ File.open(fname, 'rb'){ |f|
1059
+ return f.read
1060
+ }
1061
+ end
1062
+
1063
+ def mkdir_p(dirname, prefix = nil)
1064
+ dirname = prefix + File.expand_path(dirname) if prefix
1065
+ $stderr.puts "mkdir -p #{dirname}" if verbose?
1066
+ return if no_harm?
1067
+
1068
+ # Does not check '/', it's too abnormal.
1069
+ dirs = File.expand_path(dirname).split(%r<(?=/)>)
1070
+ if /\A[a-z]:\z/i =~ dirs[0]
1071
+ disk = dirs.shift
1072
+ dirs[0] = disk + dirs[0]
1073
+ end
1074
+ dirs.each_index do |idx|
1075
+ path = dirs[0..idx].join('')
1076
+ Dir.mkdir path unless File.dir?(path)
1077
+ record_installation(path) # also record directories made
1078
+ end
1079
+ end
1080
+
1081
+ def rm_f(path)
1082
+ $stderr.puts "rm -f #{path}" if verbose?
1083
+ return if no_harm?
1084
+ force_remove_file path
1085
+ end
1086
+
1087
+ def rm_rf(path)
1088
+ $stderr.puts "rm -rf #{path}" if verbose?
1089
+ return if no_harm?
1090
+ remove_tree path
1091
+ end
1092
+
1093
+ def rmdir(path)
1094
+ $stderr.puts "rmdir #{path}" if verbose?
1095
+ return if no_harm?
1096
+ Dir.rmdir path
1097
+ end
1098
+
1099
+ def remove_tree(path)
1100
+ if File.symlink?(path)
1101
+ remove_file path
1102
+ elsif File.dir?(path)
1103
+ remove_tree0 path
1104
+ else
1105
+ force_remove_file path
1106
+ end
1107
+ end
1108
+
1109
+ def remove_tree0(path)
1110
+ Dir.foreach(path) do |ent|
1111
+ next if ent == '.'
1112
+ next if ent == '..'
1113
+ entpath = "#{path}/#{ent}"
1114
+ if File.symlink?(entpath)
1115
+ remove_file entpath
1116
+ elsif File.dir?(entpath)
1117
+ remove_tree0 entpath
1118
+ else
1119
+ force_remove_file entpath
1120
+ end
1121
+ end
1122
+ begin
1123
+ Dir.rmdir path
1124
+ rescue Errno::ENOTEMPTY
1125
+ # directory may not be empty
1126
+ end
1127
+ end
1128
+
1129
+ def move_file(src, dest)
1130
+ force_remove_file dest
1131
+ begin
1132
+ File.rename src, dest
1133
+ rescue
1134
+ File.open(dest, 'wb') {|f|
1135
+ f.write binread(src)
1136
+ }
1137
+ File.chmod File.stat(src).mode, dest
1138
+ File.unlink src
1139
+ end
1140
+ end
1141
+
1142
+ def force_remove_file(path)
1143
+ begin
1144
+ remove_file path
1145
+ rescue
1146
+ end
1147
+ end
1148
+
1149
+ def remove_file(path)
1150
+ File.chmod 0777, path
1151
+ File.unlink path
1152
+ end
1153
+
1154
+ def install(from, dest, mode, prefix = nil)
1155
+ $stderr.puts "install #{from} #{dest}" if verbose?
1156
+ return if no_harm?
1157
+
1158
+ realdest = prefix ? prefix + File.expand_path(dest) : dest
1159
+ realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest)
1160
+ str = binread(from)
1161
+ if diff?(str, realdest)
1162
+ verbose_off {
1163
+ rm_f realdest if File.exist?(realdest)
1164
+ }
1165
+ File.open(realdest, 'wb') {|f|
1166
+ f.write str
1167
+ }
1168
+ File.chmod mode, realdest
1169
+
1170
+ if prefix
1171
+ path = realdest.sub(prefix, '')
1172
+ else
1173
+ path = realdest
1174
+ end
1175
+
1176
+ record_installation(path)
1177
+ end
1178
+ end
1179
+
1180
+ def record_installation(path)
1181
+ File.open("#{objdir_root()}/#{MANIFEST}", 'a') do |f|
1182
+ f.puts(path)
1183
+ end
1184
+ end
1185
+
1186
+ def diff?(new_content, path)
1187
+ return true unless File.exist?(path)
1188
+ new_content != binread(path)
1189
+ end
1190
+
1191
+ def command(*args)
1192
+ $stderr.puts args.join(' ') if verbose?
1193
+ system(*args) or raise RuntimeError,
1194
+ "system(#{args.map{|a| a.inspect }.join(' ')}) failed"
1195
+ end
1196
+
1197
+ def ruby(*args)
1198
+ command config.rubyprog, *args
1199
+ end
1200
+
1201
+ def make(task = nil)
1202
+ command(*[config.makeprog, task].compact)
1203
+ end
1204
+
1205
+ def extdir?(dir)
1206
+ File.exist?("#{dir}/MANIFEST") or File.exist?("#{dir}/extconf.rb")
1207
+ end
1208
+
1209
+ def files_of(dir)
1210
+ Dir.open(dir) {|d|
1211
+ return d.select {|ent| File.file?("#{dir}/#{ent}") }
1212
+ }
1213
+ end
1214
+
1215
+ DIR_REJECT = %w( . .. CVS SCCS RCS CVS.adm .svn )
1216
+
1217
+ def directories_of(dir)
1218
+ Dir.open(dir) {|d|
1219
+ return d.select {|ent| File.dir?("#{dir}/#{ent}") } - DIR_REJECT
1220
+ }
1221
+ end
1222
+
1223
+ #
1224
+ # Hook Script API
1225
+ #
1226
+ # These require: #srcdir_root, #objdir_root, #relpath
1227
+ #
1228
+
1229
+ #
1230
+ def get_config(key)
1231
+ config.__send__(key)
1232
+ end
1233
+
1234
+ # obsolete: use metaconfig to change configuration
1235
+ # TODO: what to do with?
1236
+ def set_config(key, val)
1237
+ config[key] = val
1238
+ end
1239
+
1240
+ #
1241
+ # srcdir/objdir (works only in the package directory)
1242
+ #
1243
+
1244
+ def curr_srcdir
1245
+ "#{srcdir_root()}/#{relpath()}"
1246
+ end
1247
+
1248
+ def curr_objdir
1249
+ "#{objdir_root()}/#{relpath()}"
1250
+ end
1251
+
1252
+ def srcfile(path)
1253
+ "#{curr_srcdir()}/#{path}"
1254
+ end
1255
+
1256
+ def srcexist?(path)
1257
+ File.exist?(srcfile(path))
1258
+ end
1259
+
1260
+ def srcdirectory?(path)
1261
+ File.dir?(srcfile(path))
1262
+ end
1263
+
1264
+ def srcfile?(path)
1265
+ File.file?(srcfile(path))
1266
+ end
1267
+
1268
+ def srcentries(path = '.')
1269
+ Dir.open("#{curr_srcdir()}/#{path}") {|d|
1270
+ return d.to_a - %w(. ..)
1271
+ }
1272
+ end
1273
+
1274
+ def srcfiles(path = '.')
1275
+ srcentries(path).select {|fname|
1276
+ File.file?(File.join(curr_srcdir(), path, fname))
1277
+ }
1278
+ end
1279
+
1280
+ def srcdirectories(path = '.')
1281
+ srcentries(path).select {|fname|
1282
+ File.dir?(File.join(curr_srcdir(), path, fname))
1283
+ }
1284
+ end
1285
+
1286
+ end
1287
+
1288
+ # CLI runner.
1289
+ def self.run_cli
1290
+ installer = Setup::Installer.new
1291
+
1292
+ task = ARGV.find{ |a| a !~ /^[-]/ }
1293
+ task = 'all' unless task
1294
+
1295
+ unless Setup::Installer::TASKS.include?(task)
1296
+ $stderr.puts "Not a valid task -- #{task}"
1297
+ exit 1
1298
+ end
1299
+
1300
+ opts = OptionParser.new
1301
+
1302
+ opts.banner = "Usage: #{File.basename($0)} [task] [options]"
1303
+
1304
+ if task == 'config' or task == 'all'
1305
+ opts.separator ""
1306
+ opts.separator "Config options:"
1307
+ Setup::ConfigTable::DESCRIPTIONS.each do |name, type, desc|
1308
+ opts.on("--#{name} #{type.to_s.upcase}", desc) do |val|
1309
+ ENV[name.to_s] = val.to_s
1310
+ end
1311
+ end
1312
+ end
1313
+
1314
+ if task == 'install'
1315
+ opts.separator ""
1316
+ opts.separator "Install options:"
1317
+
1318
+ opts.on("--prefix PATH", "Installation prefix") do |val|
1319
+ installer.install_prefix = val
1320
+ end
1321
+ end
1322
+
1323
+ if task == 'test'
1324
+ opts.separator ""
1325
+ opts.separator "Install options:"
1326
+
1327
+ opts.on("--runner TYPE", "Test runner (auto|console|gtk|gtk2|tk)") do |val|
1328
+ installer.config.testrunner = val
1329
+ end
1330
+ end
1331
+
1332
+ # common options
1333
+ opts.separator ""
1334
+ opts.separator "General options:"
1335
+
1336
+ opts.on("-q", "--quiet", "Silence output") do |val|
1337
+ installer.quiet = val
1338
+ end
1339
+
1340
+ opts.on("--verbose", "Provide verbose output") do |val|
1341
+ installer.verbose = val
1342
+ end
1343
+
1344
+ opts.on("-n", "--no-write", "Do not write to disk") do |val|
1345
+ installer.no_harm = !val
1346
+ end
1347
+
1348
+ opts.on("--dryrun", "Same as --no-write") do |val|
1349
+ installer.no_harm = val
1350
+ end
1351
+
1352
+ # common options
1353
+ opts.separator ""
1354
+ opts.separator "Inform options:"
1355
+
1356
+ # Tail options (eg. commands in option form)
1357
+ opts.on_tail("-h", "--help", "display this help information") do
1358
+ puts Setup.help
1359
+ exit
1360
+ end
1361
+
1362
+ opts.on_tail("--version", "Show version") do
1363
+ puts File.basename($0) + ' v' + Setup::Version.join('.')
1364
+ exit
1365
+ end
1366
+
1367
+ opts.on_tail("--copyright", "Show copyright") do
1368
+ puts Setup::Copyright
1369
+ exit
1370
+ end
1371
+
1372
+ begin
1373
+ opts.parse!(ARGV)
1374
+ rescue OptionParser::InvalidOption
1375
+ $stderr.puts $!.to_s.capitalize
1376
+ exit 1
1377
+ end
1378
+
1379
+ begin
1380
+ installer.__send__("exec_#{task}")
1381
+ rescue SetupError
1382
+ raise if $DEBUG
1383
+ $stderr.puts $!.message
1384
+ $stderr.puts "Try 'ruby #{$0} --help' for detailed usage."
1385
+ exit 1
1386
+ end
1387
+ end
1388
+
1389
+ # Generate help text.
1390
+ def self.help
1391
+ fmt = " " * 10 + "%-10s %s"
1392
+ commands = Installer::TASK_DESCRIPTIONS.collect do |k,d|
1393
+ (fmt % ["#{k}", d])
1394
+ end.join("\n").strip
1395
+
1396
+ fmt = " " * 13 + "%-20s %s"
1397
+ configs = ConfigTable::DESCRIPTIONS.collect do |k,t,d|
1398
+ (fmt % ["--#{k}", d])
1399
+ end.join("\n").strip
1400
+
1401
+ text = <<-END
1402
+ USAGE: #{File.basename($0)} [command] [options]
1403
+
1404
+ Commands:
1405
+ #{commands}
1406
+
1407
+ Options for CONFIG:
1408
+ #{configs}
1409
+
1410
+ Options for INSTALL:
1411
+ --prefix Set the install prefix
1412
+
1413
+ Options in common:
1414
+ -q --quiet Silence output
1415
+ --verbose Provide verbose output
1416
+ -n --no-write Do not write to disk
1417
+
1418
+ END
1419
+
1420
+ text.gsub(/^ \ \ \ \ \ /, '')
1421
+ end
1422
+
1423
+ #
1424
+ def self.run_rake
1425
+ installer = Setup::Installer.new
1426
+ installer.rake_define
1427
+ end
1428
+
1429
+ end
1430
+
1431
+ #
1432
+ # Ruby Extensions
1433
+ #
1434
+
1435
+ unless File.respond_to?(:read) # Ruby 1.6 and less
1436
+ def File.read(fname)
1437
+ open(fname) {|f|
1438
+ return f.read
1439
+ }
1440
+ end
1441
+ end
1442
+
1443
+ unless Errno.const_defined?(:ENOTEMPTY) # Windows?
1444
+ module Errno
1445
+ class ENOTEMPTY
1446
+ # We do not raise this exception, implementation is not needed.
1447
+ end
1448
+ end
1449
+ end
1450
+
1451
+ # for corrupted Windows' stat(2)
1452
+ def File.dir?(path)
1453
+ File.directory?((path[-1,1] == '/') ? path : path + '/')
1454
+ end
1455
+
1456
+ #
1457
+ # Runners
1458
+ #
1459
+
1460
+ if $0 == __FILE__
1461
+
1462
+ Setup.run_cli
1463
+
1464
+ elsif defined?(Rake)
1465
+
1466
+ Setup.run_rake
1467
+
1468
+ end
1469
+