libxml-ruby 0.5.2.0 → 0.5.3

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 (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
+