setup 4.0.0

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