setup 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
+