rbibtex 0.0.1

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.
data/papers.html ADDED
@@ -0,0 +1,223 @@
1
+ <html>
2
+ <head>
3
+ <style type="text/css">
4
+ div.entry { margin-bottom: 1em; padding-bottom: 1em; border-bottom: 1px dashed silver; }
5
+ span.title { font-weight: bold; }
6
+ span.author { font-style: oblique; }
7
+ .links a { background: silver; }
8
+ span.note { display: block; margin: 0.5em; margin-left: 5em; margin-right: 5em; }
9
+ </style>
10
+ </head>
11
+ <body>
12
+ <div class="entry">
13
+ <span class="author">Hongcheng Wang and Narendra Ahuja</span>
14
+ <span class="title">Facial Expression Decomposition</span>
15
+ <span class="year">2003</span>
16
+ <span class="booktitle">ICCV</span>
17
+ <span class="pages">958-965</span>
18
+ <span class="links"
19
+ <a href="">pdf</a>
20
+ <a href="local/iccv03_facial.ps.gz">ps</a>
21
+ </span
22
+ <span class="note">Using a 2D Deformable Face Model they do a HOSVD used
23
+ to decompose a Tensor like in
24
+ \ref{vlasic05:multilinear}. Sped up HOSVD by PCA to
25
+ reduce dimensionality of face description. </span>
26
+ </div>
27
+ <div class="entry">
28
+ <span class="author">Vladimir Kolmogorov and Antonio Criminisi and Andrew
29
+ Blake and Geoff Cross and Carsten Rother</span>
30
+ <span class="title">Bi-Layer Segmentation of Binocular Stereo Video.</span>
31
+ <span class="year">2005</span>
32
+ <span class="booktitle">CVPR (2)</span>
33
+ <span class="pages">407-414</span>
34
+ <span class="links"
35
+ <a href="local/Criminisi_cvpr2005.pdf">pdf</a>
36
+ <a href="">ps</a>
37
+ </span
38
+ <span class="note"></span>
39
+ </div>
40
+ <div class="entry">
41
+ <span class="author"></span>
42
+ <span class="title">2005 IEEE Computer Society Conference on Computer
43
+ Vision and Pattern Recognition (CVPR 2005), 20-26 June
44
+ 2005, San Diego, CA, USA</span>
45
+ <span class="year">2005</span>
46
+ <span class="booktitle">CVPR</span>
47
+ <span class="isbn">0-7695-2372-2</span>
48
+ <span class="publisher">IEEE Computer Society</span>
49
+ <span class="links"
50
+ <a href="">pdf</a>
51
+ <a href="">ps</a>
52
+ </span
53
+ <span class="note"></span>
54
+ </div>
55
+ <div class="entry">
56
+ <span class="author">Yang Wang and Xiaolei Huang and Chan-Su Lee and Song Zhang and
57
+ Zhiguo Li and Dimitris Samaras and Dimitris Metaxas and Ahmed
58
+ Elgammal and Peisen Huang</span>
59
+ <span class="title">High Resolution Acquisition, Learning and Transfer of
60
+ Dynamic 3-D Facial Expressions</span>
61
+ <span class="year">2004</span>
62
+ <span class="booktitle">Computer Graphics Forum</span>
63
+ <span class="pages">III: 677-686</span>
64
+ <span class="links"
65
+ <a href="local/hr_transfer/paper1044.pdf">pdf</a>
66
+ <a href="">ps</a>
67
+ </span
68
+ <span class="note">Mapping 3D Scans expression trajectories onto a low
69
+ dimensional manifold -> warping the manifolds of the
70
+ same expression of different people into the same shape
71
+ -> Learning mappings from the warped manifolds to the
72
+ original high-dimensional manifolds. They claim that
73
+ the warped manifolds contain the essence of a smile,
74
+ while the mapping function contains the person specific
75
+ style. Their morphs are not very convincing, the
76
+ intermediate faces are not mixtures of the original
77
+ faces. Maybe because of the nonlinearity of the model
78
+ and the linear warping.</span>
79
+ </div>
80
+ <div class="entry">
81
+ <span class="author">A. Criminisi and J. Shotton and A. Blake and P. H. S.
82
+ Torr</span>
83
+ <span class="title">Gaze Manipulation for One-to-one Teleconferencing</span>
84
+ <span class="year">2003</span>
85
+ <span class="address">Washington, DC, USA</span>
86
+ <span class="booktitle">ICCV '03: Proceedings of the Ninth IEEE International
87
+ Conference on Computer Vision</span>
88
+ <span class="isbn">0-7695-1950-4</span>
89
+ <span class="pages">191</span>
90
+ <span class="publisher">IEEE Computer Society</span>
91
+ <span class="links"
92
+ <a href="local/criminisi_iccv03.pdf">pdf</a>
93
+ <a href="">ps</a>
94
+ </span
95
+ <span class="note"></span>
96
+ </div>
97
+ <div class="entry">
98
+ <span class="author">Jennifer Huang and Bernd Heisele and Volker Blanz</span>
99
+ <span class="title">Component-based Face Recognition with 3D Morphable
100
+ Models</span>
101
+ <span class="year">2003</span>
102
+ <span class="address">Surrey, UK</span>
103
+ <span class="booktitle">International Conference on Audio- and Video-Based
104
+ Biometric Person Authentication (AVBPA-03)</span>
105
+ <span class="editor">Kittler, Josef and Nixon, Mark S.</span>
106
+ <span class="number">-</span>
107
+ <span class="pages">27--34</span>
108
+ <span class="publisher">Springer</span>
109
+ <span class="series">Lecture Notes in Computer Science</span>
110
+ <span class="volume">2688</span>
111
+ <span class="links"
112
+ <a href="local/avbpa2003.pdf">pdf</a>
113
+ <a href="">ps</a>
114
+ </span
115
+ <span class="note"></span>
116
+ </div>
117
+ <div class="entry">
118
+ <span class="author">Daniel Vlasic and Matthew Brand and Hanspeter Pfister
119
+ and Jovan Popovi{'c}</span>
120
+ <span class="title">Face transfer with multilinear models</span>
121
+ <span class="year">2005</span>
122
+ <span class="address">New York, NY, USA</span>
123
+ <span class="doi">http://doi.acm.org/10.1145/1073204.1073209</span>
124
+ <span class="issn">0730-0301</span>
125
+ <span class="journal">ACM Trans. Graph.</span>
126
+ <span class="number">3</span>
127
+ <span class="pages">426--433</span>
128
+ <span class="publisher">ACM Press</span>
129
+ <span class="volume">24</span>
130
+ <span class="links"
131
+ <a href="local/face_transfer/vlasic-2005-ftm.pdf">pdf</a>
132
+ <a href="">ps</a>
133
+ </span
134
+ <span class="note">Quite similar to the approach in Basel, but with
135
+ multilinear models based on tensor decomposition. Quite
136
+ good results with only a few example images. Inputation
137
+ of missing datasets. </span>
138
+ </div>
139
+ <div class="entry">
140
+ <span class="author">Xiaolei Huang and Song Zhang and Yang Wang and Dimitris
141
+ Metaxas and Dimitris Samaras</span>
142
+ <span class="title">A Hierarchical Framework for Hight Resolution Facial
143
+ Expression Tracking</span>
144
+ <span class="year">2004</span>
145
+ <span class="booktitle">IEEE Workshop on Articulated and Nonridgid Motion</span>
146
+ <span class="pages">22</span>
147
+ <span class="links"
148
+ <a href="local/anm04-face-tracking.pdf">pdf</a>
149
+ <a href="">ps</a>
150
+ </span
151
+ <span class="note">Detailed high framerate aquisition of frontal mesh and
152
+ texture data of faces using structured light. Tracking
153
+ of correspondences along frames by a simple two step
154
+ algorithm. First fitting of coarse mesh using a
155
+ gradient descent algorithms where source surface points
156
+ move to the closest target surface point, then bspline
157
+ deformation of fine mesh initialized bu coarse mesh.</span>
158
+ </div>
159
+ <div class="entry">
160
+ <span class="author"></span>
161
+ <span class="title">9th IEEE International Conference on Computer Vision
162
+ (ICCV 2003), 14-17 October 2003, Nice, France</span>
163
+ <span class="year">2003</span>
164
+ <span class="isbn">0-7695-1950-4</span>
165
+ <span class="publisher">IEEE Computer Society</span>
166
+ <span class="links"
167
+ <a href="">pdf</a>
168
+ <a href="">ps</a>
169
+ </span
170
+ <span class="note"></span>
171
+ </div>
172
+ <div class="entry">
173
+ <span class="author">P�rez, P. and Gangnet, M. and Blake, A.</span>
174
+ <span class="title">Poisson image editing</span>
175
+ <span class="year">2003</span>
176
+ <span class="journal">ACM Transactions on Graphics (SIGGRAPH'03)</span>
177
+ <span class="number">3</span>
178
+ <span class="pages">313--318</span>
179
+ <span class="volume">22</span>
180
+ <span class="links"
181
+ <a href="local/perez_siggraph03.pdf">pdf</a>
182
+ <a href="">ps</a>
183
+ </span
184
+ <span class="note"></span>
185
+ </div>
186
+ <div class="entry">
187
+ <span class="author">Volker Blanz and Curzio Basso and Thomas Vetter and
188
+ Tomaso Poggio</span>
189
+ <span class="title">Reanimating Faces in Images and Video</span>
190
+ <span class="year">2003</span>
191
+ <span class="address">Granada, Spain</span>
192
+ <span class="booktitle">EUROGRAPHICS 2003 (EUROGRAPHICS-03) : the European
193
+ Association for Computer Graphics, 24th Annual
194
+ Conference</span>
195
+ <span class="editor">Brunet, Pere and Fellner, Dieter W.</span>
196
+ <span class="isbn">0167-7055</span>
197
+ <span class="number">3</span>
198
+ <span class="organization">The Eurographics Association</span>
199
+ <span class="pages">641--650</span>
200
+ <span class="publisher">Blackwell</span>
201
+ <span class="series">Computer Graphics Forum</span>
202
+ <span class="volume">22</span>
203
+ <span class="links"
204
+ <a href="local/blanz_eg03.pdf">pdf</a>
205
+ <a href="">ps</a>
206
+ </span
207
+ <span class="note">Lineares Modell mit Visemen fuer den Mundebereich.
208
+ Keine Koartikulation. The Morphable model with tracking
209
+ and inpainting.</span>
210
+ </div>
211
+ <div class="entry">
212
+ <span class="author">Sami Romdhani</span>
213
+ <span class="title">Face Image Analysis using a Multiple Feature Fitting
214
+ Strateg</span>
215
+ <span class="year">2005</span>
216
+ <span class="school">University of basel</span>
217
+ <span class="links"
218
+ <a href="local/romdhani_thesis.pdf">pdf</a>
219
+ <a href="">ps</a>
220
+ </span
221
+ <span class="note"></span>
222
+ </div>
223
+ </body></html>
data/setup.rb ADDED
@@ -0,0 +1,1552 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # setup.rb
4
+ #
5
+ # Copyright (c) 2000-2005 Minero Aoki
6
+ #
7
+ # This program is free software.
8
+ # You can distribute/modify this program under the terms of
9
+ # the GNU LGPL, Lesser General Public License version 2.1.
10
+ #
11
+
12
+ unless Enumerable.method_defined?(:map) # Ruby 1.4.6
13
+ module Enumerable
14
+ alias map collect
15
+ end
16
+ end
17
+
18
+ unless File.respond_to?(:read) # Ruby 1.6
19
+ def File.read(fname)
20
+ open(fname) {|f|
21
+ return f.read
22
+ }
23
+ end
24
+ end
25
+
26
+ unless Errno.const_defined?(:ENOTEMPTY) # Windows?
27
+ module Errno
28
+ class ENOTEMPTY
29
+ # We do not raise this exception, implementation is not needed.
30
+ end
31
+ end
32
+ end
33
+
34
+ def File.binread(fname)
35
+ open(fname, 'rb') {|f|
36
+ return f.read
37
+ }
38
+ end
39
+
40
+ # for corrupted Windows' stat(2)
41
+ def File.dir?(path)
42
+ File.directory?((path[-1,1] == '/') ? path : path + '/')
43
+ end
44
+
45
+
46
+ class ConfigTable
47
+
48
+ include Enumerable
49
+
50
+ def initialize(rbconfig)
51
+ @rbconfig = rbconfig
52
+ @items = []
53
+ @table = {}
54
+ # options
55
+ @install_prefix = nil
56
+ @config_opt = nil
57
+ @verbose = true
58
+ @no_harm = false
59
+ @libsrc_pattern = '*.rb'
60
+ end
61
+
62
+ attr_accessor :install_prefix
63
+ attr_accessor :config_opt
64
+
65
+ attr_writer :verbose
66
+
67
+ def verbose?
68
+ @verbose
69
+ end
70
+
71
+ attr_writer :no_harm
72
+
73
+ def no_harm?
74
+ @no_harm
75
+ end
76
+
77
+ attr_accessor :libsrc_pattern
78
+
79
+ def [](key)
80
+ lookup(key).resolve(self)
81
+ end
82
+
83
+ def []=(key, val)
84
+ lookup(key).set val
85
+ end
86
+
87
+ def names
88
+ @items.map {|i| i.name }
89
+ end
90
+
91
+ def each(&block)
92
+ @items.each(&block)
93
+ end
94
+
95
+ def key?(name)
96
+ @table.key?(name)
97
+ end
98
+
99
+ def lookup(name)
100
+ @table[name] or setup_rb_error "no such config item: #{name}"
101
+ end
102
+
103
+ def add(item)
104
+ @items.push item
105
+ @table[item.name] = item
106
+ end
107
+
108
+ def remove(name)
109
+ item = lookup(name)
110
+ @items.delete_if {|i| i.name == name }
111
+ @table.delete_if {|name, i| i.name == name }
112
+ item
113
+ end
114
+
115
+ def load_script(path, inst = nil)
116
+ if File.file?(path)
117
+ MetaConfigEnvironment.new(self, inst).instance_eval File.read(path), path
118
+ end
119
+ end
120
+
121
+ def savefile
122
+ '.config'
123
+ end
124
+
125
+ def load_savefile
126
+ begin
127
+ File.foreach(savefile()) do |line|
128
+ k, v = *line.split(/=/, 2)
129
+ self[k] = v.strip
130
+ end
131
+ rescue Errno::ENOENT
132
+ setup_rb_error $!.message + "\n#{File.basename($0)} config first"
133
+ end
134
+ end
135
+
136
+ def save
137
+ @items.each {|i| i.value }
138
+ File.open(savefile(), 'w') {|f|
139
+ @items.each do |i|
140
+ f.printf "%s=%s\n", i.name, i.value if i.value? and i.value
141
+ end
142
+ }
143
+ end
144
+
145
+ def load_standard_entries
146
+ standard_entries(@rbconfig).each do |ent|
147
+ add ent
148
+ end
149
+ end
150
+
151
+ def standard_entries(rbconfig)
152
+ c = rbconfig
153
+
154
+ rubypath = c['bindir'] + '/' + c['ruby_install_name']
155
+
156
+ major = c['MAJOR'].to_i
157
+ minor = c['MINOR'].to_i
158
+ teeny = c['TEENY'].to_i
159
+ version = "#{major}.#{minor}"
160
+
161
+ # ruby ver. >= 1.4.4?
162
+ newpath_p = ((major >= 2) or
163
+ ((major == 1) and
164
+ ((minor >= 5) or
165
+ ((minor == 4) and (teeny >= 4)))))
166
+
167
+ if c['rubylibdir']
168
+ # V > 1.6.3
169
+ libruby = "#{c['prefix']}/lib/ruby"
170
+ librubyver = c['rubylibdir']
171
+ librubyverarch = c['archdir']
172
+ siteruby = c['sitedir']
173
+ siterubyver = c['sitelibdir']
174
+ siterubyverarch = c['sitearchdir']
175
+ elsif newpath_p
176
+ # 1.4.4 <= V <= 1.6.3
177
+ libruby = "#{c['prefix']}/lib/ruby"
178
+ librubyver = "#{c['prefix']}/lib/ruby/#{version}"
179
+ librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}"
180
+ siteruby = c['sitedir']
181
+ siterubyver = "$siteruby/#{version}"
182
+ siterubyverarch = "$siterubyver/#{c['arch']}"
183
+ else
184
+ # V < 1.4.4
185
+ libruby = "#{c['prefix']}/lib/ruby"
186
+ librubyver = "#{c['prefix']}/lib/ruby/#{version}"
187
+ librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}"
188
+ siteruby = "#{c['prefix']}/lib/ruby/#{version}/site_ruby"
189
+ siterubyver = siteruby
190
+ siterubyverarch = "$siterubyver/#{c['arch']}"
191
+ end
192
+ parameterize = lambda {|path|
193
+ path.sub(/\A#{Regexp.quote(c['prefix'])}/, '$prefix')
194
+ }
195
+
196
+ if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg }
197
+ makeprog = arg.sub(/'/, '').split(/=/, 2)[1]
198
+ else
199
+ makeprog = 'make'
200
+ end
201
+
202
+ [
203
+ ExecItem.new('installdirs', 'std/site/home',
204
+ 'std: install under libruby; site: install under site_ruby; home: install under $HOME')\
205
+ {|val, table|
206
+ case val
207
+ when 'std'
208
+ table['rbdir'] = '$librubyver'
209
+ table['sodir'] = '$librubyverarch'
210
+ when 'site'
211
+ table['rbdir'] = '$siterubyver'
212
+ table['sodir'] = '$siterubyverarch'
213
+ when 'home'
214
+ setup_rb_error '$HOME was not set' unless ENV['HOME']
215
+ table['prefix'] = ENV['HOME']
216
+ table['rbdir'] = '$libdir/ruby'
217
+ table['sodir'] = '$libdir/ruby'
218
+ end
219
+ },
220
+ PathItem.new('prefix', 'path', c['prefix'],
221
+ 'path prefix of target environment'),
222
+ PathItem.new('bindir', 'path', parameterize.call(c['bindir']),
223
+ 'the directory for commands'),
224
+ PathItem.new('libdir', 'path', parameterize.call(c['libdir']),
225
+ 'the directory for libraries'),
226
+ PathItem.new('datadir', 'path', parameterize.call(c['datadir']),
227
+ 'the directory for shared data'),
228
+ PathItem.new('mandir', 'path', parameterize.call(c['mandir']),
229
+ 'the directory for man pages'),
230
+ PathItem.new('sysconfdir', 'path', parameterize.call(c['sysconfdir']),
231
+ 'the directory for system configuration files'),
232
+ PathItem.new('localstatedir', 'path', parameterize.call(c['localstatedir']),
233
+ 'the directory for local state data'),
234
+ PathItem.new('libruby', 'path', libruby,
235
+ 'the directory for ruby libraries'),
236
+ PathItem.new('librubyver', 'path', librubyver,
237
+ 'the directory for standard ruby libraries'),
238
+ PathItem.new('librubyverarch', 'path', librubyverarch,
239
+ 'the directory for standard ruby extensions'),
240
+ PathItem.new('siteruby', 'path', siteruby,
241
+ 'the directory for version-independent aux ruby libraries'),
242
+ PathItem.new('siterubyver', 'path', siterubyver,
243
+ 'the directory for aux ruby libraries'),
244
+ PathItem.new('siterubyverarch', 'path', siterubyverarch,
245
+ 'the directory for aux ruby binaries'),
246
+ PathItem.new('rbdir', 'path', '$siterubyver',
247
+ 'the directory for ruby scripts'),
248
+ PathItem.new('sodir', 'path', '$siterubyverarch',
249
+ 'the directory for ruby extentions'),
250
+ PathItem.new('rubypath', 'path', rubypath,
251
+ 'the path to set to #! line'),
252
+ ProgramItem.new('rubyprog', 'name', rubypath,
253
+ 'the ruby program using for installation'),
254
+ ProgramItem.new('makeprog', 'name', makeprog,
255
+ 'the make program to compile ruby extentions'),
256
+ SelectItem.new('shebang', 'all/ruby/never', 'ruby',
257
+ 'shebang line (#!) editing mode'),
258
+ BoolItem.new('without-ext', 'yes/no', 'no',
259
+ 'does not compile/install ruby extentions')
260
+ ]
261
+ end
262
+ private :standard_entries
263
+
264
+ def load_multipackage_entries
265
+ multipackage_entries().each do |ent|
266
+ add ent
267
+ end
268
+ end
269
+
270
+ def multipackage_entries
271
+ [
272
+ PackageSelectionItem.new('with', 'name,name...', '', 'ALL',
273
+ 'package names that you want to install'),
274
+ PackageSelectionItem.new('without', 'name,name...', '', 'NONE',
275
+ 'package names that you do not want to install')
276
+ ]
277
+ end
278
+ private :multipackage_entries
279
+
280
+ ALIASES = {
281
+ 'std-ruby' => 'librubyver',
282
+ 'stdruby' => 'librubyver',
283
+ 'rubylibdir' => 'librubyver',
284
+ 'archdir' => 'librubyverarch',
285
+ 'site-ruby-common' => 'siteruby', # For backward compatibility
286
+ 'site-ruby' => 'siterubyver', # For backward compatibility
287
+ 'bin-dir' => 'bindir',
288
+ 'bin-dir' => 'bindir',
289
+ 'rb-dir' => 'rbdir',
290
+ 'so-dir' => 'sodir',
291
+ 'data-dir' => 'datadir',
292
+ 'ruby-path' => 'rubypath',
293
+ 'ruby-prog' => 'rubyprog',
294
+ 'ruby' => 'rubyprog',
295
+ 'make-prog' => 'makeprog',
296
+ 'make' => 'makeprog'
297
+ }
298
+
299
+ def fixup
300
+ ALIASES.each do |ali, name|
301
+ @table[ali] = @table[name]
302
+ end
303
+ @items.freeze
304
+ @table.freeze
305
+ @options_re = /\A--(#{@table.keys.join('|')})(?:=(.*))?\z/
306
+ end
307
+
308
+ def parse_opt(opt)
309
+ m = @options_re.match(opt) or setup_rb_error "config: unknown option #{opt}"
310
+ m.to_a[1,2]
311
+ end
312
+
313
+ def dllext
314
+ @rbconfig['DLEXT']
315
+ end
316
+
317
+ def value_config?(name)
318
+ lookup(name).value?
319
+ end
320
+
321
+ class Item
322
+ def initialize(name, template, default, desc)
323
+ @name = name.freeze
324
+ @template = template
325
+ @value = default
326
+ @default = default
327
+ @description = desc
328
+ end
329
+
330
+ attr_reader :name
331
+ attr_reader :description
332
+
333
+ attr_accessor :default
334
+ alias help_default default
335
+
336
+ def help_opt
337
+ "--#{@name}=#{@template}"
338
+ end
339
+
340
+ def value?
341
+ true
342
+ end
343
+
344
+ def value
345
+ @value
346
+ end
347
+
348
+ def resolve(table)
349
+ @value.gsub(%r<\$([^/]+)>) { table[$1] }
350
+ end
351
+
352
+ def set(val)
353
+ @value = check(val)
354
+ end
355
+
356
+ private
357
+
358
+ def check(val)
359
+ setup_rb_error "config: --#{name} requires argument" unless val
360
+ val
361
+ end
362
+ end
363
+
364
+ class BoolItem < Item
365
+ def config_type
366
+ 'bool'
367
+ end
368
+
369
+ def help_opt
370
+ "--#{@name}"
371
+ end
372
+
373
+ private
374
+
375
+ def check(val)
376
+ return 'yes' unless val
377
+ unless /\A(y(es)?|n(o)?|t(rue)?|f(alse))\z/i =~ val
378
+ setup_rb_error "config: --#{@name} accepts only yes/no for argument"
379
+ end
380
+ (/\Ay(es)?|\At(rue)/i =~ value) ? 'yes' : 'no'
381
+ end
382
+ end
383
+
384
+ class PathItem < Item
385
+ def config_type
386
+ 'path'
387
+ end
388
+
389
+ private
390
+
391
+ def check(path)
392
+ setup_rb_error "config: --#{@name} requires argument" unless path
393
+ path[0,1] == '$' ? path : File.expand_path(path)
394
+ end
395
+ end
396
+
397
+ class ProgramItem < Item
398
+ def config_type
399
+ 'program'
400
+ end
401
+ end
402
+
403
+ class SelectItem < Item
404
+ def initialize(name, selection, default, desc)
405
+ super
406
+ @ok = selection.split('/')
407
+ end
408
+
409
+ def config_type
410
+ 'select'
411
+ end
412
+
413
+ private
414
+
415
+ def check(val)
416
+ unless @ok.include?(val.strip)
417
+ setup_rb_error "config: use --#{@name}=#{@template} (#{val})"
418
+ end
419
+ val.strip
420
+ end
421
+ end
422
+
423
+ class ExecItem < Item
424
+ def initialize(name, selection, desc, &block)
425
+ super name, selection, nil, desc
426
+ @ok = selection.split('/')
427
+ @action = block
428
+ end
429
+
430
+ def config_type
431
+ 'exec'
432
+ end
433
+
434
+ def value?
435
+ false
436
+ end
437
+
438
+ def resolve(table)
439
+ setup_rb_error "$#{name()} wrongly used as option value"
440
+ end
441
+
442
+ undef set
443
+
444
+ def evaluate(val, table)
445
+ v = val.strip.downcase
446
+ unless @ok.include?(v)
447
+ setup_rb_error "invalid option --#{@name}=#{val} (use #{@template})"
448
+ end
449
+ @action.call v, table
450
+ end
451
+ end
452
+
453
+ class PackageSelectionItem < Item
454
+ def initialize(name, template, default, help_default, desc)
455
+ super name, template, default, desc
456
+ @help_default = help_default
457
+ end
458
+
459
+ attr_reader :help_default
460
+
461
+ def config_type
462
+ 'package'
463
+ end
464
+
465
+ private
466
+
467
+ def check(val)
468
+ unless File.dir?("packages/#{val}")
469
+ setup_rb_error "config: no such package: #{val}"
470
+ end
471
+ val
472
+ end
473
+ end
474
+
475
+ class MetaConfigEnvironment
476
+ def intiailize(config, installer)
477
+ @config = config
478
+ @installer = installer
479
+ end
480
+
481
+ def config_names
482
+ @config.names
483
+ end
484
+
485
+ def config?(name)
486
+ @config.key?(name)
487
+ end
488
+
489
+ def bool_config?(name)
490
+ @config.lookup(name).config_type == 'bool'
491
+ end
492
+
493
+ def path_config?(name)
494
+ @config.lookup(name).config_type == 'path'
495
+ end
496
+
497
+ def value_config?(name)
498
+ @config.lookup(name).config_type != 'exec'
499
+ end
500
+
501
+ def add_config(item)
502
+ @config.add item
503
+ end
504
+
505
+ def add_bool_config(name, default, desc)
506
+ @config.add BoolItem.new(name, 'yes/no', default ? 'yes' : 'no', desc)
507
+ end
508
+
509
+ def add_path_config(name, default, desc)
510
+ @config.add PathItem.new(name, 'path', default, desc)
511
+ end
512
+
513
+ def set_config_default(name, default)
514
+ @config.lookup(name).default = default
515
+ end
516
+
517
+ def remove_config(name)
518
+ @config.remove(name)
519
+ end
520
+
521
+ # For only multipackage
522
+ def packages
523
+ raise '[setup.rb fatal] multi-package metaconfig API packages() called for single-package; contact application package vendor' unless @installer
524
+ @installer.packages
525
+ end
526
+
527
+ # For only multipackage
528
+ def declare_packages(list)
529
+ raise '[setup.rb fatal] multi-package metaconfig API declare_packages() called for single-package; contact application package vendor' unless @installer
530
+ @installer.packages = list
531
+ end
532
+ end
533
+
534
+ end # class ConfigTable
535
+
536
+
537
+ # This module requires: #verbose?, #no_harm?
538
+ module FileOperations
539
+
540
+ def mkdir_p(dirname, prefix = nil)
541
+ dirname = prefix + File.expand_path(dirname) if prefix
542
+ $stderr.puts "mkdir -p #{dirname}" if verbose?
543
+ return if no_harm?
544
+
545
+ # Does not check '/', it's too abnormal.
546
+ dirs = File.expand_path(dirname).split(%r<(?=/)>)
547
+ if /\A[a-z]:\z/i =~ dirs[0]
548
+ disk = dirs.shift
549
+ dirs[0] = disk + dirs[0]
550
+ end
551
+ dirs.each_index do |idx|
552
+ path = dirs[0..idx].join('')
553
+ Dir.mkdir path unless File.dir?(path)
554
+ end
555
+ end
556
+
557
+ def rm_f(path)
558
+ $stderr.puts "rm -f #{path}" if verbose?
559
+ return if no_harm?
560
+ force_remove_file path
561
+ end
562
+
563
+ def rm_rf(path)
564
+ $stderr.puts "rm -rf #{path}" if verbose?
565
+ return if no_harm?
566
+ remove_tree path
567
+ end
568
+
569
+ def remove_tree(path)
570
+ if File.symlink?(path)
571
+ remove_file path
572
+ elsif File.dir?(path)
573
+ remove_tree0 path
574
+ else
575
+ force_remove_file path
576
+ end
577
+ end
578
+
579
+ def remove_tree0(path)
580
+ Dir.foreach(path) do |ent|
581
+ next if ent == '.'
582
+ next if ent == '..'
583
+ entpath = "#{path}/#{ent}"
584
+ if File.symlink?(entpath)
585
+ remove_file entpath
586
+ elsif File.dir?(entpath)
587
+ remove_tree0 entpath
588
+ else
589
+ force_remove_file entpath
590
+ end
591
+ end
592
+ begin
593
+ Dir.rmdir path
594
+ rescue Errno::ENOTEMPTY
595
+ # directory may not be empty
596
+ end
597
+ end
598
+
599
+ def move_file(src, dest)
600
+ force_remove_file dest
601
+ begin
602
+ File.rename src, dest
603
+ rescue
604
+ File.open(dest, 'wb') {|f|
605
+ f.write File.binread(src)
606
+ }
607
+ File.chmod File.stat(src).mode, dest
608
+ File.unlink src
609
+ end
610
+ end
611
+
612
+ def force_remove_file(path)
613
+ begin
614
+ remove_file path
615
+ rescue
616
+ end
617
+ end
618
+
619
+ def remove_file(path)
620
+ File.chmod 0777, path
621
+ File.unlink path
622
+ end
623
+
624
+ def install(from, dest, mode, prefix = nil)
625
+ $stderr.puts "install #{from} #{dest}" if verbose?
626
+ return if no_harm?
627
+
628
+ realdest = prefix ? prefix + File.expand_path(dest) : dest
629
+ realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest)
630
+ str = File.binread(from)
631
+ if diff?(str, realdest)
632
+ verbose_off {
633
+ rm_f realdest if File.exist?(realdest)
634
+ }
635
+ File.open(realdest, 'wb') {|f|
636
+ f.write str
637
+ }
638
+ File.chmod mode, realdest
639
+
640
+ File.open("#{objdir_root()}/InstalledFiles", 'a') {|f|
641
+ if prefix
642
+ f.puts realdest.sub(prefix, '')
643
+ else
644
+ f.puts realdest
645
+ end
646
+ }
647
+ end
648
+ end
649
+
650
+ def diff?(new_content, path)
651
+ return true unless File.exist?(path)
652
+ new_content != File.binread(path)
653
+ end
654
+
655
+ def command(*args)
656
+ $stderr.puts args.join(' ') if verbose?
657
+ system(*args) or raise RuntimeError,
658
+ "system(#{args.map{|a| a.inspect }.join(' ')}) failed"
659
+ end
660
+
661
+ def ruby(*args)
662
+ command config('rubyprog'), *args
663
+ end
664
+
665
+ def make(task = nil)
666
+ command(*[config('makeprog'), task].compact)
667
+ end
668
+
669
+ def extdir?(dir)
670
+ File.exist?("#{dir}/MANIFEST") or File.exist?("#{dir}/extconf.rb")
671
+ end
672
+
673
+ def files_of(dir)
674
+ Dir.open(dir) {|d|
675
+ return d.select {|ent| File.file?("#{dir}/#{ent}") }
676
+ }
677
+ end
678
+
679
+ DIR_REJECT = %w( . .. CVS SCCS RCS CVS.adm .svn )
680
+
681
+ def directories_of(dir)
682
+ Dir.open(dir) {|d|
683
+ return d.select {|ent| File.dir?("#{dir}/#{ent}") } - DIR_REJECT
684
+ }
685
+ end
686
+
687
+ end
688
+
689
+
690
+ # This module requires: #srcdir_root, #objdir_root, #relpath
691
+ module HookScriptAPI
692
+
693
+ def get_config(key)
694
+ @config[key]
695
+ end
696
+
697
+ alias config get_config
698
+
699
+ # obsolete: use metaconfig to change configuration
700
+ def set_config(key, val)
701
+ @config[key] = val
702
+ end
703
+
704
+ #
705
+ # srcdir/objdir (works only in the package directory)
706
+ #
707
+
708
+ def curr_srcdir
709
+ "#{srcdir_root()}/#{relpath()}"
710
+ end
711
+
712
+ def curr_objdir
713
+ "#{objdir_root()}/#{relpath()}"
714
+ end
715
+
716
+ def srcfile(path)
717
+ "#{curr_srcdir()}/#{path}"
718
+ end
719
+
720
+ def srcexist?(path)
721
+ File.exist?(srcfile(path))
722
+ end
723
+
724
+ def srcdirectory?(path)
725
+ File.dir?(srcfile(path))
726
+ end
727
+
728
+ def srcfile?(path)
729
+ File.file?(srcfile(path))
730
+ end
731
+
732
+ def srcentries(path = '.')
733
+ Dir.open("#{curr_srcdir()}/#{path}") {|d|
734
+ return d.to_a - %w(. ..)
735
+ }
736
+ end
737
+
738
+ def srcfiles(path = '.')
739
+ srcentries(path).select {|fname|
740
+ File.file?(File.join(curr_srcdir(), path, fname))
741
+ }
742
+ end
743
+
744
+ def srcdirectories(path = '.')
745
+ srcentries(path).select {|fname|
746
+ File.dir?(File.join(curr_srcdir(), path, fname))
747
+ }
748
+ end
749
+
750
+ end
751
+
752
+
753
+ class ToplevelInstaller
754
+
755
+ Version = '3.4.0'
756
+ Copyright = 'Copyright (c) 2000-2005 Minero Aoki'
757
+
758
+ TASKS = [
759
+ [ 'all', 'do config, setup, then install' ],
760
+ [ 'config', 'saves your configurations' ],
761
+ [ 'show', 'shows current configuration' ],
762
+ [ 'setup', 'compiles ruby extentions and others' ],
763
+ [ 'install', 'installs files' ],
764
+ [ 'test', 'run all tests in test/' ],
765
+ [ 'clean', "does `make clean' for each extention" ],
766
+ [ 'distclean',"does `make distclean' for each extention" ]
767
+ ]
768
+
769
+ def ToplevelInstaller.invoke
770
+ config = ConfigTable.new(load_rbconfig())
771
+ config.load_standard_entries
772
+ config.load_multipackage_entries if multipackage?
773
+ config.fixup
774
+ klass = (multipackage?() ? ToplevelInstallerMulti : ToplevelInstaller)
775
+ klass.new(File.dirname($0), config).invoke
776
+ end
777
+
778
+ def ToplevelInstaller.multipackage?
779
+ File.dir?(File.dirname($0) + '/packages')
780
+ end
781
+
782
+ def ToplevelInstaller.load_rbconfig
783
+ if arg = ARGV.detect {|arg| /\A--rbconfig=/ =~ arg }
784
+ ARGV.delete(arg)
785
+ load File.expand_path(arg.split(/=/, 2)[1])
786
+ $".push 'rbconfig.rb'
787
+ else
788
+ require 'rbconfig'
789
+ end
790
+ ::Config::CONFIG
791
+ end
792
+
793
+ def initialize(ardir_root, config)
794
+ @ardir = File.expand_path(ardir_root)
795
+ @config = config
796
+ # cache
797
+ @valid_task_re = nil
798
+ end
799
+
800
+ def config(key)
801
+ @config[key]
802
+ end
803
+
804
+ def inspect
805
+ "#<#{self.class} #{__id__()}>"
806
+ end
807
+
808
+ def invoke
809
+ run_metaconfigs
810
+ case task = parsearg_global()
811
+ when nil, 'all'
812
+ parsearg_config
813
+ init_installers
814
+ exec_config
815
+ exec_setup
816
+ exec_install
817
+ else
818
+ case task
819
+ when 'config', 'test'
820
+ ;
821
+ when 'clean', 'distclean'
822
+ @config.load_savefile if File.exist?(@config.savefile)
823
+ else
824
+ @config.load_savefile
825
+ end
826
+ __send__ "parsearg_#{task}"
827
+ init_installers
828
+ __send__ "exec_#{task}"
829
+ end
830
+ end
831
+
832
+ def run_metaconfigs
833
+ @config.load_script "#{@ardir}/metaconfig"
834
+ end
835
+
836
+ def init_installers
837
+ @installer = Installer.new(@config, @ardir, File.expand_path('.'))
838
+ end
839
+
840
+ #
841
+ # Hook Script API bases
842
+ #
843
+
844
+ def srcdir_root
845
+ @ardir
846
+ end
847
+
848
+ def objdir_root
849
+ '.'
850
+ end
851
+
852
+ def relpath
853
+ '.'
854
+ end
855
+
856
+ #
857
+ # Option Parsing
858
+ #
859
+
860
+ def parsearg_global
861
+ while arg = ARGV.shift
862
+ case arg
863
+ when /\A\w+\z/
864
+ setup_rb_error "invalid task: #{arg}" unless valid_task?(arg)
865
+ return arg
866
+ when '-q', '--quiet'
867
+ @config.verbose = false
868
+ when '--verbose'
869
+ @config.verbose = true
870
+ when '--help'
871
+ print_usage $stdout
872
+ exit 0
873
+ when '--version'
874
+ puts "#{File.basename($0)} version #{Version}"
875
+ exit 0
876
+ when '--copyright'
877
+ puts Copyright
878
+ exit 0
879
+ else
880
+ setup_rb_error "unknown global option '#{arg}'"
881
+ end
882
+ end
883
+ nil
884
+ end
885
+
886
+ def valid_task?(t)
887
+ valid_task_re() =~ t
888
+ end
889
+
890
+ def valid_task_re
891
+ @valid_task_re ||= /\A(?:#{TASKS.map {|task,desc| task }.join('|')})\z/
892
+ end
893
+
894
+ def parsearg_no_options
895
+ unless ARGV.empty?
896
+ setup_rb_error "#{task}: unknown options: #{ARGV.join(' ')}"
897
+ end
898
+ end
899
+
900
+ alias parsearg_show parsearg_no_options
901
+ alias parsearg_setup parsearg_no_options
902
+ alias parsearg_test parsearg_no_options
903
+ alias parsearg_clean parsearg_no_options
904
+ alias parsearg_distclean parsearg_no_options
905
+
906
+ def parsearg_config
907
+ evalopt = []
908
+ set = []
909
+ @config.config_opt = []
910
+ while i = ARGV.shift
911
+ if /\A--?\z/ =~ i
912
+ @config.config_opt = ARGV.dup
913
+ break
914
+ end
915
+ name, value = *@config.parse_opt(i)
916
+ if @config.value_config?(name)
917
+ @config[name] = value
918
+ else
919
+ evalopt.push [name, value]
920
+ end
921
+ set.push name
922
+ end
923
+ evalopt.each do |name, value|
924
+ @config.lookup(name).evaluate value, @config
925
+ end
926
+ # Check if configuration is valid
927
+ set.each do |n|
928
+ @config[n] if @config.value_config?(n)
929
+ end
930
+ end
931
+
932
+ def parsearg_install
933
+ @config.no_harm = false
934
+ @config.install_prefix = ''
935
+ while a = ARGV.shift
936
+ case a
937
+ when '--no-harm'
938
+ @config.no_harm = true
939
+ when /\A--prefix=/
940
+ path = a.split(/=/, 2)[1]
941
+ path = File.expand_path(path) unless path[0,1] == '/'
942
+ @config.install_prefix = path
943
+ else
944
+ setup_rb_error "install: unknown option #{a}"
945
+ end
946
+ end
947
+ end
948
+
949
+ def print_usage(out)
950
+ out.puts 'Typical Installation Procedure:'
951
+ out.puts " $ ruby #{File.basename $0} config"
952
+ out.puts " $ ruby #{File.basename $0} setup"
953
+ out.puts " # ruby #{File.basename $0} install (may require root privilege)"
954
+ out.puts
955
+ out.puts 'Detailed Usage:'
956
+ out.puts " ruby #{File.basename $0} <global option>"
957
+ out.puts " ruby #{File.basename $0} [<global options>] <task> [<task options>]"
958
+
959
+ fmt = " %-24s %s\n"
960
+ out.puts
961
+ out.puts 'Global options:'
962
+ out.printf fmt, '-q,--quiet', 'suppress message outputs'
963
+ out.printf fmt, ' --verbose', 'output messages verbosely'
964
+ out.printf fmt, ' --help', 'print this message'
965
+ out.printf fmt, ' --version', 'print version and quit'
966
+ out.printf fmt, ' --copyright', 'print copyright and quit'
967
+ out.puts
968
+ out.puts 'Tasks:'
969
+ TASKS.each do |name, desc|
970
+ out.printf fmt, name, desc
971
+ end
972
+
973
+ fmt = " %-24s %s [%s]\n"
974
+ out.puts
975
+ out.puts 'Options for CONFIG or ALL:'
976
+ @config.each do |item|
977
+ out.printf fmt, item.help_opt, item.description, item.help_default
978
+ end
979
+ out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',"running ruby's"
980
+ out.puts
981
+ out.puts 'Options for INSTALL:'
982
+ out.printf fmt, '--no-harm', 'only display what to do if given', 'off'
983
+ out.printf fmt, '--prefix=path', 'install path prefix', ''
984
+ out.puts
985
+ end
986
+
987
+ #
988
+ # Task Handlers
989
+ #
990
+
991
+ def exec_config
992
+ @installer.exec_config
993
+ @config.save # must be final
994
+ end
995
+
996
+ def exec_setup
997
+ @installer.exec_setup
998
+ end
999
+
1000
+ def exec_install
1001
+ @installer.exec_install
1002
+ end
1003
+
1004
+ def exec_test
1005
+ @installer.exec_test
1006
+ end
1007
+
1008
+ def exec_show
1009
+ @config.each do |i|
1010
+ printf "%-20s %s\n", i.name, i.value if i.value?
1011
+ end
1012
+ end
1013
+
1014
+ def exec_clean
1015
+ @installer.exec_clean
1016
+ end
1017
+
1018
+ def exec_distclean
1019
+ @installer.exec_distclean
1020
+ end
1021
+
1022
+ end # class ToplevelInstaller
1023
+
1024
+
1025
+ class ToplevelInstallerMulti < ToplevelInstaller
1026
+
1027
+ include FileOperations
1028
+
1029
+ def initialize(ardir_root, config)
1030
+ super
1031
+ @packages = directories_of("#{@ardir}/packages")
1032
+ raise 'no package exists' if @packages.empty?
1033
+ @root_installer = Installer.new(@config, @ardir, File.expand_path('.'))
1034
+ end
1035
+
1036
+ def run_metaconfigs
1037
+ @config.load_script "#{@ardir}/metaconfig", self
1038
+ @packages.each do |name|
1039
+ @config.load_script "#{@ardir}/packages/#{name}/metaconfig"
1040
+ end
1041
+ end
1042
+
1043
+ attr_reader :packages
1044
+
1045
+ def packages=(list)
1046
+ raise 'package list is empty' if list.empty?
1047
+ list.each do |name|
1048
+ raise "directory packages/#{name} does not exist"\
1049
+ unless File.dir?("#{@ardir}/packages/#{name}")
1050
+ end
1051
+ @packages = list
1052
+ end
1053
+
1054
+ def init_installers
1055
+ @installers = {}
1056
+ @packages.each do |pack|
1057
+ @installers[pack] = Installer.new(@config,
1058
+ "#{@ardir}/packages/#{pack}",
1059
+ "packages/#{pack}")
1060
+ end
1061
+ with = extract_selection(config('with'))
1062
+ without = extract_selection(config('without'))
1063
+ @selected = @installers.keys.select {|name|
1064
+ (with.empty? or with.include?(name)) \
1065
+ and not without.include?(name)
1066
+ }
1067
+ end
1068
+
1069
+ def extract_selection(list)
1070
+ a = list.split(/,/)
1071
+ a.each do |name|
1072
+ setup_rb_error "no such package: #{name}" unless @installers.key?(name)
1073
+ end
1074
+ a
1075
+ end
1076
+
1077
+ def print_usage(f)
1078
+ super
1079
+ f.puts 'Inluded packages:'
1080
+ f.puts ' ' + @packages.sort.join(' ')
1081
+ f.puts
1082
+ end
1083
+
1084
+ #
1085
+ # Task Handlers
1086
+ #
1087
+
1088
+ def exec_config
1089
+ run_hook 'pre-config'
1090
+ each_selected_installers {|inst| inst.exec_config }
1091
+ run_hook 'post-config'
1092
+ @config.save # must be final
1093
+ end
1094
+
1095
+ def exec_setup
1096
+ run_hook 'pre-setup'
1097
+ each_selected_installers {|inst| inst.exec_setup }
1098
+ run_hook 'post-setup'
1099
+ end
1100
+
1101
+ def exec_install
1102
+ run_hook 'pre-install'
1103
+ each_selected_installers {|inst| inst.exec_install }
1104
+ run_hook 'post-install'
1105
+ end
1106
+
1107
+ def exec_test
1108
+ run_hook 'pre-test'
1109
+ each_selected_installers {|inst| inst.exec_test }
1110
+ run_hook 'post-test'
1111
+ end
1112
+
1113
+ def exec_clean
1114
+ rm_f @config.savefile
1115
+ run_hook 'pre-clean'
1116
+ each_selected_installers {|inst| inst.exec_clean }
1117
+ run_hook 'post-clean'
1118
+ end
1119
+
1120
+ def exec_distclean
1121
+ rm_f @config.savefile
1122
+ run_hook 'pre-distclean'
1123
+ each_selected_installers {|inst| inst.exec_distclean }
1124
+ run_hook 'post-distclean'
1125
+ end
1126
+
1127
+ #
1128
+ # lib
1129
+ #
1130
+
1131
+ def each_selected_installers
1132
+ Dir.mkdir 'packages' unless File.dir?('packages')
1133
+ @selected.each do |pack|
1134
+ $stderr.puts "Processing the package `#{pack}' ..." if verbose?
1135
+ Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}")
1136
+ Dir.chdir "packages/#{pack}"
1137
+ yield @installers[pack]
1138
+ Dir.chdir '../..'
1139
+ end
1140
+ end
1141
+
1142
+ def run_hook(id)
1143
+ @root_installer.run_hook id
1144
+ end
1145
+
1146
+ # module FileOperations requires this
1147
+ def verbose?
1148
+ @config.verbose?
1149
+ end
1150
+
1151
+ # module FileOperations requires this
1152
+ def no_harm?
1153
+ @config.no_harm?
1154
+ end
1155
+
1156
+ end # class ToplevelInstallerMulti
1157
+
1158
+
1159
+ class Installer
1160
+
1161
+ FILETYPES = %w( bin lib ext data conf man )
1162
+
1163
+ include FileOperations
1164
+ include HookScriptAPI
1165
+
1166
+ def initialize(config, srcroot, objroot)
1167
+ @config = config
1168
+ @srcdir = File.expand_path(srcroot)
1169
+ @objdir = File.expand_path(objroot)
1170
+ @currdir = '.'
1171
+ end
1172
+
1173
+ def inspect
1174
+ "#<#{self.class} #{File.basename(@srcdir)}>"
1175
+ end
1176
+
1177
+ #
1178
+ # Hook Script API base methods
1179
+ #
1180
+
1181
+ def srcdir_root
1182
+ @srcdir
1183
+ end
1184
+
1185
+ def objdir_root
1186
+ @objdir
1187
+ end
1188
+
1189
+ def relpath
1190
+ @currdir
1191
+ end
1192
+
1193
+ #
1194
+ # Config Access
1195
+ #
1196
+
1197
+ # module FileOperations requires this
1198
+ def verbose?
1199
+ @config.verbose?
1200
+ end
1201
+
1202
+ # module FileOperations requires this
1203
+ def no_harm?
1204
+ @config.no_harm?
1205
+ end
1206
+
1207
+ def verbose_off
1208
+ begin
1209
+ save, @config.verbose = @config.verbose?, false
1210
+ yield
1211
+ ensure
1212
+ @config.verbose = save
1213
+ end
1214
+ end
1215
+
1216
+ #
1217
+ # TASK config
1218
+ #
1219
+
1220
+ def exec_config
1221
+ exec_task_traverse 'config'
1222
+ end
1223
+
1224
+ def config_dir_bin(rel)
1225
+ end
1226
+
1227
+ def config_dir_lib(rel)
1228
+ end
1229
+
1230
+ def config_dir_man(rel)
1231
+ end
1232
+
1233
+ def config_dir_ext(rel)
1234
+ extconf if extdir?(curr_srcdir())
1235
+ end
1236
+
1237
+ def extconf
1238
+ ruby "#{curr_srcdir()}/extconf.rb", *@config.config_opt
1239
+ end
1240
+
1241
+ def config_dir_data(rel)
1242
+ end
1243
+
1244
+ def config_dir_conf(rel)
1245
+ end
1246
+
1247
+ #
1248
+ # TASK setup
1249
+ #
1250
+
1251
+ def exec_setup
1252
+ exec_task_traverse 'setup'
1253
+ end
1254
+
1255
+ def setup_dir_bin(rel)
1256
+ files_of(curr_srcdir()).each do |fname|
1257
+ adjust_shebang "#{curr_srcdir()}/#{fname}"
1258
+ end
1259
+ end
1260
+
1261
+ def adjust_shebang(path)
1262
+ return if no_harm?
1263
+ tmpfile = File.basename(path) + '.tmp'
1264
+ begin
1265
+ File.open(path, 'rb') {|r|
1266
+ first = r.gets
1267
+ return unless File.basename(first.sub(/\A\#!/, '').split[0].to_s) == 'ruby'
1268
+ $stderr.puts "adjusting shebang: #{File.basename(path)}" if verbose?
1269
+ File.open(tmpfile, 'wb') {|w|
1270
+ w.print first.sub(/\A\#!\s*\S+/, '#! ' + config('rubypath'))
1271
+ w.write r.read
1272
+ }
1273
+ }
1274
+ move_file tmpfile, File.basename(path)
1275
+ ensure
1276
+ File.unlink tmpfile if File.exist?(tmpfile)
1277
+ end
1278
+ end
1279
+
1280
+ def setup_dir_lib(rel)
1281
+ end
1282
+
1283
+ def setup_dir_man(rel)
1284
+ end
1285
+
1286
+ def setup_dir_ext(rel)
1287
+ make if extdir?(curr_srcdir())
1288
+ end
1289
+
1290
+ def setup_dir_data(rel)
1291
+ end
1292
+
1293
+ def setup_dir_conf(rel)
1294
+ end
1295
+
1296
+ #
1297
+ # TASK install
1298
+ #
1299
+
1300
+ def exec_install
1301
+ rm_f 'InstalledFiles'
1302
+ exec_task_traverse 'install'
1303
+ end
1304
+
1305
+ def install_dir_bin(rel)
1306
+ install_files targetfiles(), "#{config('bindir')}/#{rel}", 0755
1307
+ end
1308
+
1309
+ def install_dir_lib(rel)
1310
+ install_files rubyscripts(), "#{config('rbdir')}/#{rel}", 0644
1311
+ end
1312
+
1313
+ def install_dir_ext(rel)
1314
+ return unless extdir?(curr_srcdir())
1315
+ install_files rubyextentions('.'),
1316
+ "#{config('sodir')}/#{File.dirname(rel)}",
1317
+ 0555
1318
+ end
1319
+
1320
+ def install_dir_data(rel)
1321
+ install_files targetfiles(), "#{config('datadir')}/#{rel}", 0644
1322
+ end
1323
+
1324
+ def install_dir_conf(rel)
1325
+ # FIXME: should not remove current config files
1326
+ # (rename previous file to .old/.org)
1327
+ install_files targetfiles(), "#{config('sysconfdir')}/#{rel}", 0644
1328
+ end
1329
+
1330
+ def install_dir_man(rel)
1331
+ install_files targetfiles(), "#{config('mandir')}/#{rel}", 0644
1332
+ end
1333
+
1334
+ def install_files(list, dest, mode)
1335
+ mkdir_p dest, @config.install_prefix
1336
+ list.each do |fname|
1337
+ install fname, dest, mode, @config.install_prefix
1338
+ end
1339
+ end
1340
+
1341
+ def rubyscripts
1342
+ glob_select(@config.libsrc_pattern, targetfiles())
1343
+ end
1344
+
1345
+ def rubyextentions(dir)
1346
+ ents = glob_select("*.#{@config.dllext}", targetfiles())
1347
+ if ents.empty?
1348
+ setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first"
1349
+ end
1350
+ ents
1351
+ end
1352
+
1353
+ def targetfiles
1354
+ mapdir(existfiles() - hookfiles())
1355
+ end
1356
+
1357
+ def mapdir(ents)
1358
+ ents.map {|ent|
1359
+ if File.exist?(ent)
1360
+ then ent # objdir
1361
+ else "#{curr_srcdir()}/#{ent}" # srcdir
1362
+ end
1363
+ }
1364
+ end
1365
+
1366
+ # picked up many entries from cvs-1.11.1/src/ignore.c
1367
+ JUNK_FILES = %w(
1368
+ core RCSLOG tags TAGS .make.state
1369
+ .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb
1370
+ *~ *.old *.bak *.BAK *.orig *.rej _$* *$
1371
+
1372
+ *.org *.in .*
1373
+ )
1374
+
1375
+ def existfiles
1376
+ glob_reject(JUNK_FILES, (files_of(curr_srcdir()) | files_of('.')))
1377
+ end
1378
+
1379
+ def hookfiles
1380
+ %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt|
1381
+ %w( config setup install clean ).map {|t| sprintf(fmt, t) }
1382
+ }.flatten
1383
+ end
1384
+
1385
+ def glob_select(pat, ents)
1386
+ re = globs2re([pat])
1387
+ ents.select {|ent| re =~ ent }
1388
+ end
1389
+
1390
+ def glob_reject(pats, ents)
1391
+ re = globs2re(pats)
1392
+ ents.reject {|ent| re =~ ent }
1393
+ end
1394
+
1395
+ GLOB2REGEX = {
1396
+ '.' => '\.',
1397
+ '$' => '\$',
1398
+ '#' => '\#',
1399
+ '*' => '.*'
1400
+ }
1401
+
1402
+ def globs2re(pats)
1403
+ /\A(?:#{
1404
+ pats.map {|pat| pat.gsub(/[\.\$\#\*]/) {|ch| GLOB2REGEX[ch] } }.join('|')
1405
+ })\z/
1406
+ end
1407
+
1408
+ #
1409
+ # TASK test
1410
+ #
1411
+
1412
+ TESTDIR = 'test'
1413
+
1414
+ def exec_test
1415
+ unless File.directory?('test')
1416
+ $stderr.puts 'no test in this package' if verbose?
1417
+ return
1418
+ end
1419
+ $stderr.puts 'Running tests...' if verbose?
1420
+ require 'test/unit'
1421
+ runner = Test::Unit::AutoRunner.new(true)
1422
+ runner.to_run << TESTDIR
1423
+ runner.run
1424
+ end
1425
+
1426
+ #
1427
+ # TASK clean
1428
+ #
1429
+
1430
+ def exec_clean
1431
+ exec_task_traverse 'clean'
1432
+ rm_f @config.savefile
1433
+ rm_f 'InstalledFiles'
1434
+ end
1435
+
1436
+ def clean_dir_bin(rel)
1437
+ end
1438
+
1439
+ def clean_dir_lib(rel)
1440
+ end
1441
+
1442
+ def clean_dir_ext(rel)
1443
+ return unless extdir?(curr_srcdir())
1444
+ make 'clean' if File.file?('Makefile')
1445
+ end
1446
+
1447
+ def clean_dir_data(rel)
1448
+ end
1449
+
1450
+ def clean_dir_conf(rel)
1451
+ end
1452
+
1453
+ #
1454
+ # TASK distclean
1455
+ #
1456
+
1457
+ def exec_distclean
1458
+ exec_task_traverse 'distclean'
1459
+ rm_f @config.savefile
1460
+ rm_f 'InstalledFiles'
1461
+ end
1462
+
1463
+ def distclean_dir_bin(rel)
1464
+ end
1465
+
1466
+ def distclean_dir_lib(rel)
1467
+ end
1468
+
1469
+ def distclean_dir_ext(rel)
1470
+ return unless extdir?(curr_srcdir())
1471
+ make 'distclean' if File.file?('Makefile')
1472
+ end
1473
+
1474
+ def distclean_dir_data(rel)
1475
+ end
1476
+
1477
+ def distclean_dir_conf(rel)
1478
+ end
1479
+
1480
+ #
1481
+ # lib
1482
+ #
1483
+
1484
+ def exec_task_traverse(task)
1485
+ run_hook "pre-#{task}"
1486
+ FILETYPES.each do |type|
1487
+ if config('without-ext') == 'yes' and type == 'ext'
1488
+ $stderr.puts 'skipping ext/* by user option' if verbose?
1489
+ next
1490
+ end
1491
+ traverse task, type, "#{task}_dir_#{type}"
1492
+ end
1493
+ run_hook "post-#{task}"
1494
+ end
1495
+
1496
+ def traverse(task, rel, mid)
1497
+ dive_into(rel) {
1498
+ run_hook "pre-#{task}"
1499
+ __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '')
1500
+ directories_of(curr_srcdir()).each do |d|
1501
+ traverse task, "#{rel}/#{d}", mid
1502
+ end
1503
+ run_hook "post-#{task}"
1504
+ }
1505
+ end
1506
+
1507
+ def dive_into(rel)
1508
+ return unless File.dir?("#{@srcdir}/#{rel}")
1509
+
1510
+ dir = File.basename(rel)
1511
+ Dir.mkdir dir unless File.dir?(dir)
1512
+ prevdir = Dir.pwd
1513
+ Dir.chdir dir
1514
+ $stderr.puts '---> ' + rel if verbose?
1515
+ @currdir = rel
1516
+ yield
1517
+ Dir.chdir prevdir
1518
+ $stderr.puts '<--- ' + rel if verbose?
1519
+ @currdir = File.dirname(rel)
1520
+ end
1521
+
1522
+ def run_hook(id)
1523
+ path = [ "#{curr_srcdir()}/#{id}",
1524
+ "#{curr_srcdir()}/#{id}.rb" ].detect {|cand| File.file?(cand) }
1525
+ return unless path
1526
+ begin
1527
+ instance_eval File.read(path), path, 1
1528
+ rescue
1529
+ raise if $DEBUG
1530
+ setup_rb_error "hook #{path} failed:\n" + $!.message
1531
+ end
1532
+ end
1533
+
1534
+ end # class Installer
1535
+
1536
+
1537
+ class SetupError < StandardError; end
1538
+
1539
+ def setup_rb_error(msg)
1540
+ raise SetupError, msg
1541
+ end
1542
+
1543
+ if $0 == __FILE__
1544
+ begin
1545
+ ToplevelInstaller.invoke
1546
+ rescue SetupError
1547
+ raise if $DEBUG
1548
+ $stderr.puts $!.message
1549
+ $stderr.puts "Try 'ruby #{$0} --help' for detailed usage."
1550
+ exit 1
1551
+ end
1552
+ end