glyph_imager 0.0.14 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. data/VERSION +1 -1
  2. data/glyph_imager.gemspec +45 -36
  3. data/lib/glyph_imager.rb +19 -27
  4. data/test/fonts/Musica.ttf +0 -0
  5. data/test/test_glyph_imager.rb +9 -3
  6. data/vendor/ttfunk/.gitignore +1 -0
  7. data/vendor/ttfunk/data/fonts/DejaVuSans.ttf +0 -0
  8. data/vendor/ttfunk/data/fonts/comicsans.ttf +0 -0
  9. data/vendor/ttfunk/example.rb +45 -0
  10. data/vendor/ttfunk/lib/ttfunk.rb +102 -0
  11. data/vendor/ttfunk/lib/ttfunk/directory.rb +17 -0
  12. data/vendor/ttfunk/lib/ttfunk/encoding/mac_roman.rb +88 -0
  13. data/vendor/ttfunk/lib/ttfunk/encoding/windows_1252.rb +69 -0
  14. data/vendor/ttfunk/lib/ttfunk/reader.rb +44 -0
  15. data/vendor/ttfunk/lib/ttfunk/resource_file.rb +78 -0
  16. data/vendor/ttfunk/lib/ttfunk/subset.rb +18 -0
  17. data/vendor/ttfunk/lib/ttfunk/subset/base.rb +141 -0
  18. data/vendor/ttfunk/lib/ttfunk/subset/mac_roman.rb +50 -0
  19. data/vendor/ttfunk/lib/ttfunk/subset/unicode.rb +48 -0
  20. data/vendor/ttfunk/lib/ttfunk/subset/unicode_8bit.rb +63 -0
  21. data/vendor/ttfunk/lib/ttfunk/subset/windows_1252.rb +55 -0
  22. data/vendor/ttfunk/lib/ttfunk/subset_collection.rb +72 -0
  23. data/vendor/ttfunk/lib/ttfunk/table.rb +46 -0
  24. data/vendor/ttfunk/lib/ttfunk/table/cmap.rb +34 -0
  25. data/vendor/ttfunk/lib/ttfunk/table/cmap/format00.rb +54 -0
  26. data/vendor/ttfunk/lib/ttfunk/table/cmap/format04.rb +126 -0
  27. data/vendor/ttfunk/lib/ttfunk/table/cmap/format12.rb +37 -0
  28. data/vendor/ttfunk/lib/ttfunk/table/cmap/subtable.rb +82 -0
  29. data/vendor/ttfunk/lib/ttfunk/table/glyf.rb +64 -0
  30. data/vendor/ttfunk/lib/ttfunk/table/glyf/compound.rb +81 -0
  31. data/vendor/ttfunk/lib/ttfunk/table/glyf/simple.rb +37 -0
  32. data/vendor/ttfunk/lib/ttfunk/table/head.rb +44 -0
  33. data/vendor/ttfunk/lib/ttfunk/table/hhea.rb +41 -0
  34. data/vendor/ttfunk/lib/ttfunk/table/hmtx.rb +47 -0
  35. data/vendor/ttfunk/lib/ttfunk/table/kern.rb +79 -0
  36. data/vendor/ttfunk/lib/ttfunk/table/kern/format0.rb +62 -0
  37. data/vendor/ttfunk/lib/ttfunk/table/loca.rb +43 -0
  38. data/vendor/ttfunk/lib/ttfunk/table/maxp.rb +40 -0
  39. data/vendor/ttfunk/lib/ttfunk/table/name.rb +125 -0
  40. data/vendor/ttfunk/lib/ttfunk/table/os2.rb +78 -0
  41. data/vendor/ttfunk/lib/ttfunk/table/post.rb +91 -0
  42. data/vendor/ttfunk/lib/ttfunk/table/post/format10.rb +43 -0
  43. data/vendor/ttfunk/lib/ttfunk/table/post/format20.rb +35 -0
  44. data/vendor/ttfunk/lib/ttfunk/table/post/format25.rb +23 -0
  45. data/vendor/ttfunk/lib/ttfunk/table/post/format30.rb +17 -0
  46. data/vendor/ttfunk/lib/ttfunk/table/post/format40.rb +17 -0
  47. data/vendor/ttfunk/lib/ttfunk/table/simple.rb +14 -0
  48. metadata +46 -37
  49. data/vendor/ttf-ruby-0.1/AUTHORS +0 -1
  50. data/vendor/ttf-ruby-0.1/COPYING +0 -340
  51. data/vendor/ttf-ruby-0.1/README +0 -49
  52. data/vendor/ttf-ruby-0.1/TODO +0 -23
  53. data/vendor/ttf-ruby-0.1/VERSION +0 -1
  54. data/vendor/ttf-ruby-0.1/lib/ttf.rb +0 -20
  55. data/vendor/ttf-ruby-0.1/lib/ttf/datatypes.rb +0 -181
  56. data/vendor/ttf-ruby-0.1/lib/ttf/encodings.rb +0 -140
  57. data/vendor/ttf-ruby-0.1/lib/ttf/exceptions.rb +0 -28
  58. data/vendor/ttf-ruby-0.1/lib/ttf/font_loader.rb +0 -290
  59. data/vendor/ttf-ruby-0.1/lib/ttf/fontchunk.rb +0 -77
  60. data/vendor/ttf-ruby-0.1/lib/ttf/table/cmap.rb +0 -408
  61. data/vendor/ttf-ruby-0.1/lib/ttf/table/cvt.rb +0 -49
  62. data/vendor/ttf-ruby-0.1/lib/ttf/table/fpgm.rb +0 -48
  63. data/vendor/ttf-ruby-0.1/lib/ttf/table/gasp.rb +0 -88
  64. data/vendor/ttf-ruby-0.1/lib/ttf/table/glyf.rb +0 -452
  65. data/vendor/ttf-ruby-0.1/lib/ttf/table/head.rb +0 -86
  66. data/vendor/ttf-ruby-0.1/lib/ttf/table/hhea.rb +0 -96
  67. data/vendor/ttf-ruby-0.1/lib/ttf/table/hmtx.rb +0 -98
  68. data/vendor/ttf-ruby-0.1/lib/ttf/table/kern.rb +0 -186
  69. data/vendor/ttf-ruby-0.1/lib/ttf/table/loca.rb +0 -75
  70. data/vendor/ttf-ruby-0.1/lib/ttf/table/maxp.rb +0 -81
  71. data/vendor/ttf-ruby-0.1/lib/ttf/table/name.rb +0 -226
  72. data/vendor/ttf-ruby-0.1/lib/ttf/table/os2.rb +0 -172
  73. data/vendor/ttf-ruby-0.1/lib/ttf/table/post.rb +0 -120
  74. data/vendor/ttf-ruby-0.1/lib/ttf/table/prep.rb +0 -27
  75. data/vendor/ttf-ruby-0.1/lib/ttf/table/vhea.rb +0 -45
  76. data/vendor/ttf-ruby-0.1/lib/ttf/table/vmtx.rb +0 -36
  77. data/vendor/ttf-ruby-0.1/setup.rb +0 -1558
  78. data/vendor/ttf-ruby-0.1/tools/README +0 -44
  79. data/vendor/ttf-ruby-0.1/tools/ttfcairoglyphviewer +0 -229
  80. data/vendor/ttf-ruby-0.1/tools/ttfdump +0 -396
  81. data/vendor/ttf-ruby-0.1/tools/ttfglyph2svg +0 -144
  82. data/vendor/ttf-ruby-0.1/tools/ttfsubset +0 -273
@@ -1,120 +0,0 @@
1
- # TTF/Ruby, a library to read and write TrueType fonts in Ruby.
2
- # Copyright (C) 2006 Mathieu Blondel
3
- #
4
- # This program is free software; you can redistribute it and/or modify
5
- # it under the terms of the GNU General Public License as published by
6
- # the Free Software Foundation; either version 2 of the License, or
7
- # (at your option) any later version.
8
- #
9
- # This program is distributed in the hope that it will be useful,
10
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- # GNU General Public License for more details.
13
- #
14
- # You should have received a copy of the GNU General Public License
15
- # along with this program; if not, write to the Free Software
16
- # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17
-
18
- module TTFFont
19
- module TTF
20
- module Table
21
-
22
- # Post is the PostScript table, which contains additional informations needed
23
- # to use TrueType fonts on PostScript printers
24
- class Post < TTFFont::TTF::FontChunk
25
-
26
- attr_accessor :format_type, :italic_angle, :underline_position,
27
- :underline_thickness, :is_fixed_pitch,
28
- :min_mem_type_42, :max_mem_type_42,
29
- :min_mem_type_1, :max_mem_type_1,
30
- :num_glyphs
31
- # An Array of PostscriptName
32
- attr_accessor :names
33
-
34
- PostScriptName = Struct.new(:id, :str)
35
-
36
- def initialize(*args)
37
- super(*args)
38
-
39
- if exists_in_file?
40
- @font.at_offset(@offset) do
41
- @format_type = @font.read_ulong
42
- @italic_angle = @font.read_ulong
43
- @underline_position = @font.read_fword
44
- @underline_thickness = @font.read_fword
45
- @is_fixed_pitch = @font.read_ulong
46
- @min_mem_type_42 = @font.read_ulong
47
- @max_mem_type_42 = @font.read_ulong
48
- @min_mem_type_1 = @font.read_ulong
49
- @max_mem_type_1 = @font.read_ulong
50
-
51
- if format == 2
52
- @num_glyphs = @font.read_ushort
53
- if @num_glyphs != @font.get_table(:maxp).num_glyphs
54
- raise "Number of glyphs is post table and " + \
55
- "maxp table should be the same"
56
- end
57
- name_indices = @font.read_ushorts(@num_glyphs)
58
- @names = []
59
- @num_glyphs.times do |i|
60
- name_id = name_indices[i]
61
- if name_id <= 257
62
- # standard Macintosh name
63
- pn = PostScriptName.new
64
- pn.id = name_indices[i]
65
- pn.str = nil
66
- @names << pn
67
- elsif name_id >= 258 and name_id <= 32767
68
- len = @font.read_byte
69
- pn = PostScriptName.new
70
- pn.id = name_indices[i]
71
- pn.str = @font.read(len)
72
- @names << pn
73
- end
74
- end
75
- else
76
- @num_glyphs = 0
77
- @names = []
78
- end
79
- end
80
- end
81
- end
82
-
83
- def format
84
- {0x00010000 => 1,
85
- 0x00020000 => 2,
86
- 0x00025000 => 2.5,
87
- 0x00030000 => 3}[@format_type]
88
- end
89
-
90
- # Dumps the post table in binary raw format as may be found in a font
91
- # file.
92
- def dump
93
- raw = (@format_type || 0).to_ulong
94
- raw += (@italic_angle || 0).to_ulong
95
- raw += (@underline_position || 0).to_fword
96
- raw += (@underline_thickness || 0).to_fword
97
- raw += (@is_fixed_pitch || 0).to_ulong
98
- raw += (@min_mem_type_42 || 0).to_ulong
99
- raw += (@max_mem_type_42 || 0).to_ulong
100
- raw += (@min_mem_type_1 || 0).to_ulong
101
- raw += (@max_mem_type_1 || 0).to_ulong
102
-
103
- if format == 2
104
- raw += (@names.length || 0).to_ushort
105
- raw += @names.collect { |n| n.id }.to_ushorts
106
- @names.collect { |n| n.str }.find_all { |n| n != nil }.each do
107
- |name|
108
- raw += name.length.to_byte
109
- raw += name
110
- end
111
- end
112
-
113
- raw
114
- end
115
-
116
- end
117
-
118
- end
119
- end
120
- end
@@ -1,27 +0,0 @@
1
- # TTF/Ruby, a library to read and write TrueType fonts in Ruby.
2
- # Copyright (C) 2006 Mathieu Blondel
3
- #
4
- # This program is free software; you can redistribute it and/or modify
5
- # it under the terms of the GNU General Public License as published by
6
- # the Free Software Foundation; either version 2 of the License, or
7
- # (at your option) any later version.
8
- #
9
- # This program is distributed in the hope that it will be useful,
10
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- # GNU General Public License for more details.
13
- #
14
- # You should have received a copy of the GNU General Public License
15
- # along with this program; if not, write to the Free Software
16
- # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17
-
18
- module TTFFont
19
- module TTF
20
- module Table
21
-
22
- class Prep < Fpgm
23
- end
24
-
25
- end
26
- end
27
- end
@@ -1,45 +0,0 @@
1
- # TTF/Ruby, a library to read and write TrueType fonts in Ruby.
2
- # Copyright (C) 2006 Mathieu Blondel
3
- #
4
- # This program is free software; you can redistribute it and/or modify
5
- # it under the terms of the GNU General Public License as published by
6
- # the Free Software Foundation; either version 2 of the License, or
7
- # (at your option) any later version.
8
- #
9
- # This program is distributed in the hope that it will be useful,
10
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- # GNU General Public License for more details.
13
- #
14
- # You should have received a copy of the GNU General Public License
15
- # along with this program; if not, write to the Free Software
16
- # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17
-
18
- module TTFFont
19
- module TTF
20
- module Table
21
-
22
- # Vhea is the Vertical Header table.
23
- class Vhea < Hea
24
-
25
- alias :advance_height_max :advance_max
26
- alias :min_top_side_bearing :min_side_bearing_1
27
- alias :min_bottom_side_bearing :min_side_bearing_2
28
- alias :y_max_extent :max_extent
29
- alias :number_of_vmetrics :number_of_metrics
30
-
31
- alias :advance_height_max= :advance_max=
32
- alias :min_top_side_bearing= :min_side_bearing_1=
33
- alias :min_bottom_side_bearing= :min_side_bearing_2=
34
- alias :y_max_extent= :max_extent=
35
- alias :number_of_vmetrics= :number_of_metrics=
36
-
37
- def initialize(*args)
38
- super(*args)
39
- end
40
-
41
- end
42
-
43
- end
44
- end
45
- end
@@ -1,36 +0,0 @@
1
- # TTF/Ruby, a library to read and write TrueType fonts in Ruby.
2
- # Copyright (C) 2006 Mathieu Blondel
3
- #
4
- # This program is free software; you can redistribute it and/or modify
5
- # it under the terms of the GNU General Public License as published by
6
- # the Free Software Foundation; either version 2 of the License, or
7
- # (at your option) any later version.
8
- #
9
- # This program is distributed in the hope that it will be useful,
10
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- # GNU General Public License for more details.
13
- #
14
- # You should have received a copy of the GNU General Public License
15
- # along with this program; if not, write to the Free Software
16
- # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17
-
18
- module TTFFont
19
- module TTF
20
- module Table
21
-
22
- # Vmtx is the Vertical metrics table.
23
- class Vmtx < Mtx
24
-
25
- alias :vmetrics :metrics
26
- alias :vmetrics= :metrics=
27
-
28
- def initialize(*args)
29
- super(*args)
30
- end
31
-
32
- end
33
-
34
- end
35
- end
36
- end
@@ -1,1558 +0,0 @@
1
- #
2
- # setup.rb
3
- #
4
- # Copyright (c) 2000-2005 Minero Aoki
5
- #
6
- # This program is free software.
7
- # You can distribute/modify this program under the terms of
8
- # the GNU LGPL, Lesser General Public License version 2.1.
9
- #
10
-
11
- unless Enumerable.method_defined?(:map) # Ruby 1.4.6
12
- module Enumerable
13
- alias map collect
14
- end
15
- end
16
-
17
- unless File.respond_to?(:read) # Ruby 1.6
18
- def File.read(fname)
19
- open(fname) {|f|
20
- return f.read
21
- }
22
- end
23
- end
24
-
25
- unless Errno.const_defined?(:ENOTEMPTY) # Windows?
26
- module Errno
27
- class ENOTEMPTY
28
- # We do not raise this exception, implementation is not needed.
29
- end
30
- end
31
- end
32
-
33
- def File.binread(fname)
34
- open(fname, 'rb') {|f|
35
- return f.read
36
- }
37
- end
38
-
39
- # for corrupted Windows' stat(2)
40
- def File.dir?(path)
41
- File.directory?((path[-1,1] == '/') ? path : path + '/')
42
- end
43
-
44
-
45
- class ConfigTable
46
-
47
- include Enumerable
48
-
49
- def initialize(rbconfig)
50
- @rbconfig = rbconfig
51
- @items = []
52
- @table = {}
53
- # options
54
- @install_prefix = nil
55
- @config_opt = nil
56
- @verbose = true
57
- @no_harm = false
58
- @libsrc_pattern = '*.rb'
59
- end
60
-
61
- attr_accessor :install_prefix
62
- attr_accessor :config_opt
63
-
64
- attr_writer :verbose
65
-
66
- def verbose?
67
- @verbose
68
- end
69
-
70
- attr_writer :no_harm
71
-
72
- def no_harm?
73
- @no_harm
74
- end
75
-
76
- attr_accessor :libsrc_pattern
77
-
78
- def [](key)
79
- lookup(key).resolve(self)
80
- end
81
-
82
- def []=(key, val)
83
- lookup(key).set val
84
- end
85
-
86
- def names
87
- @items.map {|i| i.name }
88
- end
89
-
90
- def each(&block)
91
- @items.each(&block)
92
- end
93
-
94
- def key?(name)
95
- @table.key?(name)
96
- end
97
-
98
- def lookup(name)
99
- @table[name] or setup_rb_error "no such config item: #{name}"
100
- end
101
-
102
- def add(item)
103
- @items.push item
104
- @table[item.name] = item
105
- end
106
-
107
- def remove(name)
108
- item = lookup(name)
109
- @items.delete_if {|i| i.name == name }
110
- @table.delete_if {|name, i| i.name == name }
111
- item
112
- end
113
-
114
- def load_script(path, inst = nil)
115
- if File.file?(path)
116
- MetaConfigEnvironment.new(self, inst).instance_eval File.read(path), path
117
- end
118
- end
119
-
120
- def savefile
121
- '.config'
122
- end
123
-
124
- def load_savefile
125
- begin
126
- File.foreach(savefile()) do |line|
127
- k, v = *line.split(/=/, 2)
128
- self[k] = v.strip
129
- end
130
- rescue Errno::ENOENT
131
- setup_rb_error $!.message + "\n#{File.basename($0)} config first"
132
- end
133
- end
134
-
135
- def save
136
- @items.each {|i| i.value }
137
- File.open(savefile(), 'w') {|f|
138
- @items.each do |i|
139
- f.printf "%s=%s\n", i.name, i.value if i.value? and i.value
140
- end
141
- }
142
- end
143
-
144
- def load_standard_entries
145
- standard_entries(@rbconfig).each do |ent|
146
- add ent
147
- end
148
- end
149
-
150
- def standard_entries(rbconfig)
151
- c = rbconfig
152
-
153
- rubypath = c['bindir'] + '/' + c['ruby_install_name']
154
-
155
- major = c['MAJOR'].to_i
156
- minor = c['MINOR'].to_i
157
- teeny = c['TEENY'].to_i
158
- version = "#{major}.#{minor}"
159
-
160
- # ruby ver. >= 1.4.4?
161
- newpath_p = ((major >= 2) or
162
- ((major == 1) and
163
- ((minor >= 5) or
164
- ((minor == 4) and (teeny >= 4)))))
165
-
166
- if c['rubylibdir']
167
- # V > 1.6.3
168
- libruby = "#{c['prefix']}/lib/ruby"
169
- librubyver = c['rubylibdir']
170
- librubyverarch = c['archdir']
171
- siteruby = c['sitedir']
172
- siterubyver = c['sitelibdir']
173
- siterubyverarch = c['sitearchdir']
174
- elsif newpath_p
175
- # 1.4.4 <= V <= 1.6.3
176
- libruby = "#{c['prefix']}/lib/ruby"
177
- librubyver = "#{c['prefix']}/lib/ruby/#{version}"
178
- librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}"
179
- siteruby = c['sitedir']
180
- siterubyver = "$siteruby/#{version}"
181
- siterubyverarch = "$siterubyver/#{c['arch']}"
182
- else
183
- # V < 1.4.4
184
- libruby = "#{c['prefix']}/lib/ruby"
185
- librubyver = "#{c['prefix']}/lib/ruby/#{version}"
186
- librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}"
187
- siteruby = "#{c['prefix']}/lib/ruby/#{version}/site_ruby"
188
- siterubyver = siteruby
189
- siterubyverarch = "$siterubyver/#{c['arch']}"
190
- end
191
- parameterize = lambda {|path|
192
- path.sub(/\A#{Regexp.quote(c['prefix'])}/, '$prefix')
193
- }
194
-
195
- if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg
196
- }
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;
205
- home: install under $HOME')\
206
- {|val, table|
207
- case val
208
- when 'std'
209
- table['rbdir'] = '$librubyver'
210
- table['sodir'] = '$librubyverarch'
211
- when 'site'
212
- table['rbdir'] = '$siterubyver'
213
- table['sodir'] = '$siterubyverarch'
214
- when 'home'
215
- setup_rb_error '$HOME was not set' unless ENV['HOME']
216
- table['prefix'] = ENV['HOME']
217
- table['rbdir'] = '$libdir/ruby'
218
- table['sodir'] = '$libdir/ruby'
219
- end
220
- },
221
- PathItem.new('prefix', 'path', c['prefix'],
222
- 'path prefix of target environment'),
223
- PathItem.new('bindir', 'path', parameterize.call(c['bindir']),
224
- 'the directory for commands'),
225
- PathItem.new('libdir', 'path', parameterize.call(c['libdir']),
226
- 'the directory for libraries'),
227
- PathItem.new('datadir', 'path', parameterize.call(c['datadir']),
228
- 'the directory for shared data'),
229
- PathItem.new('mandir', 'path', parameterize.call(c['mandir']),
230
- 'the directory for man pages'),
231
- PathItem.new('sysconfdir', 'path', parameterize.call(c['sysconfdir']),
232
- 'the directory for system configuration files'),
233
- PathItem.new('localstatedir', 'path',
234
- parameterize.call(c['localstatedir']),
235
- 'the directory for local state data'),
236
- PathItem.new('libruby', 'path', libruby,
237
- 'the directory for ruby libraries'),
238
- PathItem.new('librubyver', 'path', librubyver,
239
- 'the directory for standard ruby libraries'),
240
- PathItem.new('librubyverarch', 'path', librubyverarch,
241
- 'the directory for standard ruby extensions'),
242
- PathItem.new('siteruby', 'path', siteruby,
243
- 'the directory for version-independent aux ruby libraries'),
244
- PathItem.new('siterubyver', 'path', siterubyver,
245
- 'the directory for aux ruby libraries'),
246
- PathItem.new('siterubyverarch', 'path', siterubyverarch,
247
- 'the directory for aux ruby binaries'),
248
- PathItem.new('rbdir', 'path', '$siterubyver',
249
- 'the directory for ruby scripts'),
250
- PathItem.new('sodir', 'path', '$siterubyverarch',
251
- 'the directory for ruby extentions'),
252
- PathItem.new('rubypath', 'path', rubypath,
253
- 'the path to set to #! line'),
254
- ProgramItem.new('rubyprog', 'name', rubypath,
255
- 'the ruby program using for installation'),
256
- ProgramItem.new('makeprog', 'name', makeprog,
257
- 'the make program to compile ruby extentions'),
258
- SelectItem.new('shebang', 'all/ruby/never', 'ruby',
259
- 'shebang line (#!) editing mode'),
260
- BoolItem.new('without-ext', 'yes/no', 'no',
261
- 'does not compile/install ruby extentions')
262
- ]
263
- end
264
- private :standard_entries
265
-
266
- def load_multipackage_entries
267
- multipackage_entries().each do |ent|
268
- add ent
269
- end
270
- end
271
-
272
- def multipackage_entries
273
- [
274
- PackageSelectionItem.new('with', 'name,name...', '', 'ALL',
275
- 'package names that you want to install'),
276
- PackageSelectionItem.new('without', 'name,name...', '', 'NONE',
277
- 'package names that you do not want to install')
278
- ]
279
- end
280
- private :multipackage_entries
281
-
282
- ALIASES = {
283
- 'std-ruby' => 'librubyver',
284
- 'stdruby' => 'librubyver',
285
- 'rubylibdir' => 'librubyver',
286
- 'archdir' => 'librubyverarch',
287
- 'site-ruby-common' => 'siteruby', # For backward compatibility
288
- 'site-ruby' => 'siterubyver', # For backward compatibility
289
- 'bin-dir' => 'bindir',
290
- 'bin-dir' => 'bindir',
291
- 'rb-dir' => 'rbdir',
292
- 'so-dir' => 'sodir',
293
- 'data-dir' => 'datadir',
294
- 'ruby-path' => 'rubypath',
295
- 'ruby-prog' => 'rubyprog',
296
- 'ruby' => 'rubyprog',
297
- 'make-prog' => 'makeprog',
298
- 'make' => 'makeprog'
299
- }
300
-
301
- def fixup
302
- ALIASES.each do |ali, name|
303
- @table[ali] = @table[name]
304
- end
305
- @items.freeze
306
- @table.freeze
307
- @options_re = /\A--(#{@table.keys.join('|')})(?:=(.*))?\z/
308
- end
309
-
310
- def parse_opt(opt)
311
- m = @options_re.match(opt) or setup_rb_error "config: unknown option #{opt}"
312
- m.to_a[1,2]
313
- end
314
-
315
- def dllext
316
- @rbconfig['DLEXT']
317
- end
318
-
319
- def value_config?(name)
320
- lookup(name).value?
321
- end
322
-
323
- class Item
324
- def initialize(name, template, default, desc)
325
- @name = name.freeze
326
- @template = template
327
- @value = default
328
- @default = default
329
- @description = desc
330
- end
331
-
332
- attr_reader :name
333
- attr_reader :description
334
-
335
- attr_accessor :default
336
- alias help_default default
337
-
338
- def help_opt
339
- "--#{@name}=#{@template}"
340
- end
341
-
342
- def value?
343
- true
344
- end
345
-
346
- def value
347
- @value
348
- end
349
-
350
- def resolve(table)
351
- @value.gsub(%r<\$([^/]+)>) { table[$1] }
352
- end
353
-
354
- def set(val)
355
- @value = check(val)
356
- end
357
-
358
- private
359
-
360
- def check(val)
361
- setup_rb_error "config: --#{name} requires argument" unless val
362
- val
363
- end
364
- end
365
-
366
- class BoolItem < Item
367
- def config_type
368
- 'bool'
369
- end
370
-
371
- def help_opt
372
- "--#{@name}"
373
- end
374
-
375
- private
376
-
377
- def check(val)
378
- return 'yes' unless val
379
- unless /\A(y(es)?|n(o)?|t(rue)?|f(alse))\z/i =~ val
380
- setup_rb_error "config: --#{@name} accepts only yes/no for argument"
381
- end
382
- (/\Ay(es)?|\At(rue)/i =~ value) ? 'yes' : 'no'
383
- end
384
- end
385
-
386
- class PathItem < Item
387
- def config_type
388
- 'path'
389
- end
390
-
391
- private
392
-
393
- def check(path)
394
- setup_rb_error "config: --#{@name} requires argument" unless path
395
- path[0,1] == '$' ? path : File.expand_path(path)
396
- end
397
- end
398
-
399
- class ProgramItem < Item
400
- def config_type
401
- 'program'
402
- end
403
- end
404
-
405
- class SelectItem < Item
406
- def initialize(name, selection, default, desc)
407
- super
408
- @ok = selection.split('/')
409
- end
410
-
411
- def config_type
412
- 'select'
413
- end
414
-
415
- private
416
-
417
- def check(val)
418
- unless @ok.include?(val.strip)
419
- setup_rb_error "config: use --#{@name}=#{@template} (#{val})"
420
- end
421
- val.strip
422
- end
423
- end
424
-
425
- class ExecItem < Item
426
- def initialize(name, selection, desc, &block)
427
- super name, selection, nil, desc
428
- @ok = selection.split('/')
429
- @action = block
430
- end
431
-
432
- def config_type
433
- 'exec'
434
- end
435
-
436
- def value?
437
- false
438
- end
439
-
440
- def resolve(table)
441
- setup_rb_error "$#{name()} wrongly used as option value"
442
- end
443
-
444
- undef set
445
-
446
- def evaluate(val, table)
447
- v = val.strip.downcase
448
- unless @ok.include?(v)
449
- setup_rb_error "invalid option --#{@name}=#{val} (use #{@template})"
450
- end
451
- @action.call v, table
452
- end
453
- end
454
-
455
- class PackageSelectionItem < Item
456
- def initialize(name, template, default, help_default, desc)
457
- super name, template, default, desc
458
- @help_default = help_default
459
- end
460
-
461
- attr_reader :help_default
462
-
463
- def config_type
464
- 'package'
465
- end
466
-
467
- private
468
-
469
- def check(val)
470
- unless File.dir?("packages/#{val}")
471
- setup_rb_error "config: no such package: #{val}"
472
- end
473
- val
474
- end
475
- end
476
-
477
- class MetaConfigEnvironment
478
- def intiailize(config, installer)
479
- @config = config
480
- @installer = installer
481
- end
482
-
483
- def config_names
484
- @config.names
485
- end
486
-
487
- def config?(name)
488
- @config.key?(name)
489
- end
490
-
491
- def bool_config?(name)
492
- @config.lookup(name).config_type == 'bool'
493
- end
494
-
495
- def path_config?(name)
496
- @config.lookup(name).config_type == 'path'
497
- end
498
-
499
- def value_config?(name)
500
- @config.lookup(name).config_type != 'exec'
501
- end
502
-
503
- def add_config(item)
504
- @config.add item
505
- end
506
-
507
- def add_bool_config(name, default, desc)
508
- @config.add BoolItem.new(name, 'yes/no', default ? 'yes' : 'no', desc)
509
- end
510
-
511
- def add_path_config(name, default, desc)
512
- @config.add PathItem.new(name, 'path', default, desc)
513
- end
514
-
515
- def set_config_default(name, default)
516
- @config.lookup(name).default = default
517
- end
518
-
519
- def remove_config(name)
520
- @config.remove(name)
521
- end
522
-
523
- # For only multipackage
524
- def packages
525
- raise '[setup.rb fatal] multi-package metaconfig API packages() called for
526
- single-package; contact application package vendor' unless @installer
527
- @installer.packages
528
- end
529
-
530
- # For only multipackage
531
- def declare_packages(list)
532
- raise '[setup.rb fatal] multi-package metaconfig API declare_packages()
533
- called for single-package; contact application package vendor' unless @installer
534
- @installer.packages = list
535
- end
536
- end
537
-
538
- end # class ConfigTable
539
-
540
-
541
- # This module requires: #verbose?, #no_harm?
542
- module FileOperations
543
-
544
- def mkdir_p(dirname, prefix = nil)
545
- dirname = prefix + File.expand_path(dirname) if prefix
546
- $stderr.puts "mkdir -p #{dirname}" if verbose?
547
- return if no_harm?
548
-
549
- # Does not check '/', it's too abnormal.
550
- dirs = File.expand_path(dirname).split(%r<(?=/)>)
551
- if /\A[a-z]:\z/i =~ dirs[0]
552
- disk = dirs.shift
553
- dirs[0] = disk + dirs[0]
554
- end
555
- dirs.each_index do |idx|
556
- path = dirs[0..idx].join('')
557
- Dir.mkdir path unless File.dir?(path)
558
- end
559
- end
560
-
561
- def rm_f(path)
562
- $stderr.puts "rm -f #{path}" if verbose?
563
- return if no_harm?
564
- force_remove_file path
565
- end
566
-
567
- def rm_rf(path)
568
- $stderr.puts "rm -rf #{path}" if verbose?
569
- return if no_harm?
570
- remove_tree path
571
- end
572
-
573
- def remove_tree(path)
574
- if File.symlink?(path)
575
- remove_file path
576
- elsif File.dir?(path)
577
- remove_tree0 path
578
- else
579
- force_remove_file path
580
- end
581
- end
582
-
583
- def remove_tree0(path)
584
- Dir.foreach(path) do |ent|
585
- next if ent == '.'
586
- next if ent == '..'
587
- entpath = "#{path}/#{ent}"
588
- if File.symlink?(entpath)
589
- remove_file entpath
590
- elsif File.dir?(entpath)
591
- remove_tree0 entpath
592
- else
593
- force_remove_file entpath
594
- end
595
- end
596
- begin
597
- Dir.rmdir path
598
- rescue Errno::ENOTEMPTY
599
- # directory may not be empty
600
- end
601
- end
602
-
603
- def move_file(src, dest)
604
- force_remove_file dest
605
- begin
606
- File.rename src, dest
607
- rescue
608
- File.open(dest, 'wb') {|f|
609
- f.write File.binread(src)
610
- }
611
- File.chmod File.stat(src).mode, dest
612
- File.unlink src
613
- end
614
- end
615
-
616
- def force_remove_file(path)
617
- begin
618
- remove_file path
619
- rescue
620
- end
621
- end
622
-
623
- def remove_file(path)
624
- File.chmod 0777, path
625
- File.unlink path
626
- end
627
-
628
- def install(from, dest, mode, prefix = nil)
629
- $stderr.puts "install #{from} #{dest}" if verbose?
630
- return if no_harm?
631
-
632
- realdest = prefix ? prefix + File.expand_path(dest) : dest
633
- realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest)
634
- str = File.binread(from)
635
- if diff?(str, realdest)
636
- verbose_off {
637
- rm_f realdest if File.exist?(realdest)
638
- }
639
- File.open(realdest, 'wb') {|f|
640
- f.write str
641
- }
642
- File.chmod mode, realdest
643
-
644
- File.open("#{objdir_root()}/InstalledFiles", 'a') {|f|
645
- if prefix
646
- f.puts realdest.sub(prefix, '')
647
- else
648
- f.puts realdest
649
- end
650
- }
651
- end
652
- end
653
-
654
- def diff?(new_content, path)
655
- return true unless File.exist?(path)
656
- new_content != File.binread(path)
657
- end
658
-
659
- def command(*args)
660
- $stderr.puts args.join(' ') if verbose?
661
- system(*args) or raise RuntimeError,
662
- "system(#{args.map{|a| a.inspect }.join(' ')}) failed"
663
- end
664
-
665
- def ruby(*args)
666
- command config('rubyprog'), *args
667
- end
668
-
669
- def make(task = nil)
670
- command(*[config('makeprog'), task].compact)
671
- end
672
-
673
- def extdir?(dir)
674
- File.exist?("#{dir}/MANIFEST") or File.exist?("#{dir}/extconf.rb")
675
- end
676
-
677
- def files_of(dir)
678
- Dir.open(dir) {|d|
679
- return d.select {|ent| File.file?("#{dir}/#{ent}") }
680
- }
681
- end
682
-
683
- DIR_REJECT = %w( . .. CVS SCCS RCS CVS.adm .svn )
684
-
685
- def directories_of(dir)
686
- Dir.open(dir) {|d|
687
- return d.select {|ent| File.dir?("#{dir}/#{ent}") } - DIR_REJECT
688
- }
689
- end
690
-
691
- end
692
-
693
-
694
- # This module requires: #srcdir_root, #objdir_root, #relpath
695
- module HookScriptAPI
696
-
697
- def get_config(key)
698
- @config[key]
699
- end
700
-
701
- alias config get_config
702
-
703
- # obsolete: use metaconfig to change configuration
704
- def set_config(key, val)
705
- @config[key] = val
706
- end
707
-
708
- #
709
- # srcdir/objdir (works only in the package directory)
710
- #
711
-
712
- def curr_srcdir
713
- "#{srcdir_root()}/#{relpath()}"
714
- end
715
-
716
- def curr_objdir
717
- "#{objdir_root()}/#{relpath()}"
718
- end
719
-
720
- def srcfile(path)
721
- "#{curr_srcdir()}/#{path}"
722
- end
723
-
724
- def srcexist?(path)
725
- File.exist?(srcfile(path))
726
- end
727
-
728
- def srcdirectory?(path)
729
- File.dir?(srcfile(path))
730
- end
731
-
732
- def srcfile?(path)
733
- File.file?(srcfile(path))
734
- end
735
-
736
- def srcentries(path = '.')
737
- Dir.open("#{curr_srcdir()}/#{path}") {|d|
738
- return d.to_a - %w(. ..)
739
- }
740
- end
741
-
742
- def srcfiles(path = '.')
743
- srcentries(path).select {|fname|
744
- File.file?(File.join(curr_srcdir(), path, fname))
745
- }
746
- end
747
-
748
- def srcdirectories(path = '.')
749
- srcentries(path).select {|fname|
750
- File.dir?(File.join(curr_srcdir(), path, fname))
751
- }
752
- end
753
-
754
- end
755
-
756
-
757
- class ToplevelInstaller
758
-
759
- Version = '3.4.0'
760
- Copyright = 'Copyright (c) 2000-2005 Minero Aoki'
761
-
762
- TASKS = [
763
- [ 'all', 'do config, setup, then install' ],
764
- [ 'config', 'saves your configurations' ],
765
- [ 'show', 'shows current configuration' ],
766
- [ 'setup', 'compiles ruby extentions and others' ],
767
- [ 'install', 'installs files' ],
768
- [ 'test', 'run all tests in test/' ],
769
- [ 'clean', "does `make clean' for each extention" ],
770
- [ 'distclean',"does `make distclean' for each extention" ]
771
- ]
772
-
773
- def ToplevelInstaller.invoke
774
- config = ConfigTable.new(load_rbconfig())
775
- config.load_standard_entries
776
- config.load_multipackage_entries if multipackage?
777
- config.fixup
778
- klass = (multipackage?() ? ToplevelInstallerMulti : ToplevelInstaller)
779
- klass.new(File.dirname($0), config).invoke
780
- end
781
-
782
- def ToplevelInstaller.multipackage?
783
- File.dir?(File.dirname($0) + '/packages')
784
- end
785
-
786
- def ToplevelInstaller.load_rbconfig
787
- if arg = ARGV.detect {|arg| /\A--rbconfig=/ =~ arg }
788
- ARGV.delete(arg)
789
- load File.expand_path(arg.split(/=/, 2)[1])
790
- $".push 'rbconfig.rb'
791
- else
792
- require 'rbconfig'
793
- end
794
- ::Config::CONFIG
795
- end
796
-
797
- def initialize(ardir_root, config)
798
- @ardir = File.expand_path(ardir_root)
799
- @config = config
800
- # cache
801
- @valid_task_re = nil
802
- end
803
-
804
- def config(key)
805
- @config[key]
806
- end
807
-
808
- def inspect
809
- "#<#{self.class} #{__id__()}>"
810
- end
811
-
812
- def invoke
813
- run_metaconfigs
814
- case task = parsearg_global()
815
- when nil, 'all'
816
- parsearg_config
817
- init_installers
818
- exec_config
819
- exec_setup
820
- exec_install
821
- else
822
- case task
823
- when 'config', 'test'
824
- ;
825
- when 'clean', 'distclean'
826
- @config.load_savefile if File.exist?(@config.savefile)
827
- else
828
- @config.load_savefile
829
- end
830
- __send__ "parsearg_#{task}"
831
- init_installers
832
- __send__ "exec_#{task}"
833
- end
834
- end
835
-
836
- def run_metaconfigs
837
- @config.load_script "#{@ardir}/metaconfig"
838
- end
839
-
840
- def init_installers
841
- @installer = Installer.new(@config, @ardir, File.expand_path('.'))
842
- end
843
-
844
- #
845
- # Hook Script API bases
846
- #
847
-
848
- def srcdir_root
849
- @ardir
850
- end
851
-
852
- def objdir_root
853
- '.'
854
- end
855
-
856
- def relpath
857
- '.'
858
- end
859
-
860
- #
861
- # Option Parsing
862
- #
863
-
864
- def parsearg_global
865
- while arg = ARGV.shift
866
- case arg
867
- when /\A\w+\z/
868
- setup_rb_error "invalid task: #{arg}" unless valid_task?(arg)
869
- return arg
870
- when '-q', '--quiet'
871
- @config.verbose = false
872
- when '--verbose'
873
- @config.verbose = true
874
- when '--help'
875
- print_usage $stdout
876
- exit 0
877
- when '--version'
878
- puts "#{File.basename($0)} version #{Version}"
879
- exit 0
880
- when '--copyright'
881
- puts Copyright
882
- exit 0
883
- else
884
- setup_rb_error "unknown global option '#{arg}'"
885
- end
886
- end
887
- nil
888
- end
889
-
890
- def valid_task?(t)
891
- valid_task_re() =~ t
892
- end
893
-
894
- def valid_task_re
895
- @valid_task_re ||= /\A(?:#{TASKS.map {|task,desc| task }.join('|')})\z/
896
- end
897
-
898
- def parsearg_no_options
899
- unless ARGV.empty?
900
- setup_rb_error "#{task}: unknown options: #{ARGV.join(' ')}"
901
- end
902
- end
903
-
904
- alias parsearg_show parsearg_no_options
905
- alias parsearg_setup parsearg_no_options
906
- alias parsearg_test parsearg_no_options
907
- alias parsearg_clean parsearg_no_options
908
- alias parsearg_distclean parsearg_no_options
909
-
910
- def parsearg_config
911
- evalopt = []
912
- set = []
913
- @config.config_opt = []
914
- while i = ARGV.shift
915
- if /\A--?\z/ =~ i
916
- @config.config_opt = ARGV.dup
917
- break
918
- end
919
- name, value = *@config.parse_opt(i)
920
- if @config.value_config?(name)
921
- @config[name] = value
922
- else
923
- evalopt.push [name, value]
924
- end
925
- set.push name
926
- end
927
- evalopt.each do |name, value|
928
- @config.lookup(name).evaluate value, @config
929
- end
930
- # Check if configuration is valid
931
- set.each do |n|
932
- @config[n] if @config.value_config?(n)
933
- end
934
- end
935
-
936
- def parsearg_install
937
- @config.no_harm = false
938
- @config.install_prefix = ''
939
- while a = ARGV.shift
940
- case a
941
- when '--no-harm'
942
- @config.no_harm = true
943
- when /\A--prefix=/
944
- path = a.split(/=/, 2)[1]
945
- path = File.expand_path(path) unless path[0,1] == '/'
946
- @config.install_prefix = path
947
- else
948
- setup_rb_error "install: unknown option #{a}"
949
- end
950
- end
951
- end
952
-
953
- def print_usage(out)
954
- out.puts 'Typical Installation Procedure:'
955
- out.puts " $ ruby #{File.basename $0} config"
956
- out.puts " $ ruby #{File.basename $0} setup"
957
- out.puts " # ruby #{File.basename $0} install (may require root privilege)"
958
- out.puts
959
- out.puts 'Detailed Usage:'
960
- out.puts " ruby #{File.basename $0} <global option>"
961
- out.puts " ruby #{File.basename $0} [<global options>] <task> [<task
962
- options>]"
963
-
964
- fmt = " %-24s %s\n"
965
- out.puts
966
- out.puts 'Global options:'
967
- out.printf fmt, '-q,--quiet', 'suppress message outputs'
968
- out.printf fmt, ' --verbose', 'output messages verbosely'
969
- out.printf fmt, ' --help', 'print this message'
970
- out.printf fmt, ' --version', 'print version and quit'
971
- out.printf fmt, ' --copyright', 'print copyright and quit'
972
- out.puts
973
- out.puts 'Tasks:'
974
- TASKS.each do |name, desc|
975
- out.printf fmt, name, desc
976
- end
977
-
978
- fmt = " %-24s %s [%s]\n"
979
- out.puts
980
- out.puts 'Options for CONFIG or ALL:'
981
- @config.each do |item|
982
- out.printf fmt, item.help_opt, item.description, item.help_default
983
- end
984
- out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',"running ruby's"
985
- out.puts
986
- out.puts 'Options for INSTALL:'
987
- out.printf fmt, '--no-harm', 'only display what to do if given', 'off'
988
- out.printf fmt, '--prefix=path', 'install path prefix', ''
989
- out.puts
990
- end
991
-
992
- #
993
- # Task Handlers
994
- #
995
-
996
- def exec_config
997
- @installer.exec_config
998
- @config.save # must be final
999
- end
1000
-
1001
- def exec_setup
1002
- @installer.exec_setup
1003
- end
1004
-
1005
- def exec_install
1006
- @installer.exec_install
1007
- end
1008
-
1009
- def exec_test
1010
- @installer.exec_test
1011
- end
1012
-
1013
- def exec_show
1014
- @config.each do |i|
1015
- printf "%-20s %s\n", i.name, i.value if i.value?
1016
- end
1017
- end
1018
-
1019
- def exec_clean
1020
- @installer.exec_clean
1021
- end
1022
-
1023
- def exec_distclean
1024
- @installer.exec_distclean
1025
- end
1026
-
1027
- end # class ToplevelInstaller
1028
-
1029
-
1030
- class ToplevelInstallerMulti < ToplevelInstaller
1031
-
1032
- include FileOperations
1033
-
1034
- def initialize(ardir_root, config)
1035
- super
1036
- @packages = directories_of("#{@ardir}/packages")
1037
- raise 'no package exists' if @packages.empty?
1038
- @root_installer = Installer.new(@config, @ardir, File.expand_path('.'))
1039
- end
1040
-
1041
- def run_metaconfigs
1042
- @config.load_script "#{@ardir}/metaconfig", self
1043
- @packages.each do |name|
1044
- @config.load_script "#{@ardir}/packages/#{name}/metaconfig"
1045
- end
1046
- end
1047
-
1048
- attr_reader :packages
1049
-
1050
- def packages=(list)
1051
- raise 'package list is empty' if list.empty?
1052
- list.each do |name|
1053
- raise "directory packages/#{name} does not exist"\
1054
- unless File.dir?("#{@ardir}/packages/#{name}")
1055
- end
1056
- @packages = list
1057
- end
1058
-
1059
- def init_installers
1060
- @installers = {}
1061
- @packages.each do |pack|
1062
- @installers[pack] = Installer.new(@config,
1063
- "#{@ardir}/packages/#{pack}",
1064
- "packages/#{pack}")
1065
- end
1066
- with = extract_selection(config('with'))
1067
- without = extract_selection(config('without'))
1068
- @selected = @installers.keys.select {|name|
1069
- (with.empty? or with.include?(name)) \
1070
- and not without.include?(name)
1071
- }
1072
- end
1073
-
1074
- def extract_selection(list)
1075
- a = list.split(/,/)
1076
- a.each do |name|
1077
- setup_rb_error "no such package: #{name}" unless @installers.key?(name)
1078
- end
1079
- a
1080
- end
1081
-
1082
- def print_usage(f)
1083
- super
1084
- f.puts 'Inluded packages:'
1085
- f.puts ' ' + @packages.sort.join(' ')
1086
- f.puts
1087
- end
1088
-
1089
- #
1090
- # Task Handlers
1091
- #
1092
-
1093
- def exec_config
1094
- run_hook 'pre-config'
1095
- each_selected_installers {|inst| inst.exec_config }
1096
- run_hook 'post-config'
1097
- @config.save # must be final
1098
- end
1099
-
1100
- def exec_setup
1101
- run_hook 'pre-setup'
1102
- each_selected_installers {|inst| inst.exec_setup }
1103
- run_hook 'post-setup'
1104
- end
1105
-
1106
- def exec_install
1107
- run_hook 'pre-install'
1108
- each_selected_installers {|inst| inst.exec_install }
1109
- run_hook 'post-install'
1110
- end
1111
-
1112
- def exec_test
1113
- run_hook 'pre-test'
1114
- each_selected_installers {|inst| inst.exec_test }
1115
- run_hook 'post-test'
1116
- end
1117
-
1118
- def exec_clean
1119
- rm_f @config.savefile
1120
- run_hook 'pre-clean'
1121
- each_selected_installers {|inst| inst.exec_clean }
1122
- run_hook 'post-clean'
1123
- end
1124
-
1125
- def exec_distclean
1126
- rm_f @config.savefile
1127
- run_hook 'pre-distclean'
1128
- each_selected_installers {|inst| inst.exec_distclean }
1129
- run_hook 'post-distclean'
1130
- end
1131
-
1132
- #
1133
- # lib
1134
- #
1135
-
1136
- def each_selected_installers
1137
- Dir.mkdir 'packages' unless File.dir?('packages')
1138
- @selected.each do |pack|
1139
- $stderr.puts "Processing the package `#{pack}' ..." if verbose?
1140
- Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}")
1141
- Dir.chdir "packages/#{pack}"
1142
- yield @installers[pack]
1143
- Dir.chdir '../..'
1144
- end
1145
- end
1146
-
1147
- def run_hook(id)
1148
- @root_installer.run_hook id
1149
- end
1150
-
1151
- # module FileOperations requires this
1152
- def verbose?
1153
- @config.verbose?
1154
- end
1155
-
1156
- # module FileOperations requires this
1157
- def no_harm?
1158
- @config.no_harm?
1159
- end
1160
-
1161
- end # class ToplevelInstallerMulti
1162
-
1163
-
1164
- class Installer
1165
-
1166
- FILETYPES = %w( bin lib ext data conf man )
1167
-
1168
- include FileOperations
1169
- include HookScriptAPI
1170
-
1171
- def initialize(config, srcroot, objroot)
1172
- @config = config
1173
- @srcdir = File.expand_path(srcroot)
1174
- @objdir = File.expand_path(objroot)
1175
- @currdir = '.'
1176
- end
1177
-
1178
- def inspect
1179
- "#<#{self.class} #{File.basename(@srcdir)}>"
1180
- end
1181
-
1182
- #
1183
- # Hook Script API base methods
1184
- #
1185
-
1186
- def srcdir_root
1187
- @srcdir
1188
- end
1189
-
1190
- def objdir_root
1191
- @objdir
1192
- end
1193
-
1194
- def relpath
1195
- @currdir
1196
- end
1197
-
1198
- #
1199
- # Config Access
1200
- #
1201
-
1202
- # module FileOperations requires this
1203
- def verbose?
1204
- @config.verbose?
1205
- end
1206
-
1207
- # module FileOperations requires this
1208
- def no_harm?
1209
- @config.no_harm?
1210
- end
1211
-
1212
- def verbose_off
1213
- begin
1214
- save, @config.verbose = @config.verbose?, false
1215
- yield
1216
- ensure
1217
- @config.verbose = save
1218
- end
1219
- end
1220
-
1221
- #
1222
- # TASK config
1223
- #
1224
-
1225
- def exec_config
1226
- exec_task_traverse 'config'
1227
- end
1228
-
1229
- def config_dir_bin(rel)
1230
- end
1231
-
1232
- def config_dir_lib(rel)
1233
- end
1234
-
1235
- def config_dir_man(rel)
1236
- end
1237
-
1238
- def config_dir_ext(rel)
1239
- extconf if extdir?(curr_srcdir())
1240
- end
1241
-
1242
- def extconf
1243
- ruby "#{curr_srcdir()}/extconf.rb", *@config.config_opt
1244
- end
1245
-
1246
- def config_dir_data(rel)
1247
- end
1248
-
1249
- def config_dir_conf(rel)
1250
- end
1251
-
1252
- #
1253
- # TASK setup
1254
- #
1255
-
1256
- def exec_setup
1257
- exec_task_traverse 'setup'
1258
- end
1259
-
1260
- def setup_dir_bin(rel)
1261
- files_of(curr_srcdir()).each do |fname|
1262
- adjust_shebang "#{curr_srcdir()}/#{fname}"
1263
- end
1264
- end
1265
-
1266
- def adjust_shebang(path)
1267
- return if no_harm?
1268
- tmpfile = File.basename(path) + '.tmp'
1269
- begin
1270
- File.open(path, 'rb') {|r|
1271
- first = r.gets
1272
- return unless File.basename(first.sub(/\A\#!/, '').split[0].to_s) ==
1273
- 'ruby'
1274
- $stderr.puts "adjusting shebang: #{File.basename(path)}" if verbose?
1275
- File.open(tmpfile, 'wb') {|w|
1276
- w.print first.sub(/\A\#!\s*\S+/, '#! ' + config('rubypath'))
1277
- w.write r.read
1278
- }
1279
- }
1280
- move_file tmpfile, File.basename(path)
1281
- ensure
1282
- File.unlink tmpfile if File.exist?(tmpfile)
1283
- end
1284
- end
1285
-
1286
- def setup_dir_lib(rel)
1287
- end
1288
-
1289
- def setup_dir_man(rel)
1290
- end
1291
-
1292
- def setup_dir_ext(rel)
1293
- make if extdir?(curr_srcdir())
1294
- end
1295
-
1296
- def setup_dir_data(rel)
1297
- end
1298
-
1299
- def setup_dir_conf(rel)
1300
- end
1301
-
1302
- #
1303
- # TASK install
1304
- #
1305
-
1306
- def exec_install
1307
- rm_f 'InstalledFiles'
1308
- exec_task_traverse 'install'
1309
- end
1310
-
1311
- def install_dir_bin(rel)
1312
- install_files targetfiles(), "#{config('bindir')}/#{rel}", 0755
1313
- end
1314
-
1315
- def install_dir_lib(rel)
1316
- install_files rubyscripts(), "#{config('rbdir')}/#{rel}", 0644
1317
- end
1318
-
1319
- def install_dir_ext(rel)
1320
- return unless extdir?(curr_srcdir())
1321
- install_files rubyextentions('.'),
1322
- "#{config('sodir')}/#{File.dirname(rel)}",
1323
- 0555
1324
- end
1325
-
1326
- def install_dir_data(rel)
1327
- install_files targetfiles(), "#{config('datadir')}/#{rel}", 0644
1328
- end
1329
-
1330
- def install_dir_conf(rel)
1331
- # FIXME: should not remove current config files
1332
- # (rename previous file to .old/.org)
1333
- install_files targetfiles(), "#{config('sysconfdir')}/#{rel}", 0644
1334
- end
1335
-
1336
- def install_dir_man(rel)
1337
- install_files targetfiles(), "#{config('mandir')}/#{rel}", 0644
1338
- end
1339
-
1340
- def install_files(list, dest, mode)
1341
- mkdir_p dest, @config.install_prefix
1342
- list.each do |fname|
1343
- install fname, dest, mode, @config.install_prefix
1344
- end
1345
- end
1346
-
1347
- def rubyscripts
1348
- glob_select(@config.libsrc_pattern, targetfiles())
1349
- end
1350
-
1351
- def rubyextentions(dir)
1352
- ents = glob_select("*.#{@config.dllext}", targetfiles())
1353
- if ents.empty?
1354
- setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first"
1355
- end
1356
- ents
1357
- end
1358
-
1359
- def targetfiles
1360
- mapdir(existfiles() - hookfiles())
1361
- end
1362
-
1363
- def mapdir(ents)
1364
- ents.map {|ent|
1365
- if File.exist?(ent)
1366
- then ent # objdir
1367
- else "#{curr_srcdir()}/#{ent}" # srcdir
1368
- end
1369
- }
1370
- end
1371
-
1372
- # picked up many entries from cvs-1.11.1/src/ignore.c
1373
- JUNK_FILES = %w(
1374
- core RCSLOG tags TAGS .make.state
1375
- .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb
1376
- *~ *.old *.bak *.BAK *.orig *.rej _$* *$
1377
-
1378
- *.org *.in .*
1379
- )
1380
-
1381
- def existfiles
1382
- glob_reject(JUNK_FILES, (files_of(curr_srcdir()) | files_of('.')))
1383
- end
1384
-
1385
- def hookfiles
1386
- %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt|
1387
- %w( config setup install clean ).map {|t| sprintf(fmt, t) }
1388
- }.flatten
1389
- end
1390
-
1391
- def glob_select(pat, ents)
1392
- re = globs2re([pat])
1393
- ents.select {|ent| re =~ ent }
1394
- end
1395
-
1396
- def glob_reject(pats, ents)
1397
- re = globs2re(pats)
1398
- ents.reject {|ent| re =~ ent }
1399
- end
1400
-
1401
- GLOB2REGEX = {
1402
- '.' => '\.',
1403
- '$' => '\$',
1404
- '#' => '\#',
1405
- '*' => '.*'
1406
- }
1407
-
1408
- def globs2re(pats)
1409
- /\A(?:#{
1410
- pats.map {|pat| pat.gsub(/[\.\$\#\*]/) {|ch| GLOB2REGEX[ch] } }.join('|')
1411
- })\z/
1412
- end
1413
-
1414
- #
1415
- # TASK test
1416
- #
1417
-
1418
- TESTDIR = 'test'
1419
-
1420
- def exec_test
1421
- unless File.directory?('test')
1422
- $stderr.puts 'no test in this package' if verbose?
1423
- return
1424
- end
1425
- $stderr.puts 'Running tests...' if verbose?
1426
- require 'test/unit'
1427
- runner = Test::Unit::AutoRunner.new(true)
1428
- runner.to_run << TESTDIR
1429
- runner.run
1430
- end
1431
-
1432
- #
1433
- # TASK clean
1434
- #
1435
-
1436
- def exec_clean
1437
- exec_task_traverse 'clean'
1438
- rm_f @config.savefile
1439
- rm_f 'InstalledFiles'
1440
- end
1441
-
1442
- def clean_dir_bin(rel)
1443
- end
1444
-
1445
- def clean_dir_lib(rel)
1446
- end
1447
-
1448
- def clean_dir_ext(rel)
1449
- return unless extdir?(curr_srcdir())
1450
- make 'clean' if File.file?('Makefile')
1451
- end
1452
-
1453
- def clean_dir_data(rel)
1454
- end
1455
-
1456
- def clean_dir_conf(rel)
1457
- end
1458
-
1459
- #
1460
- # TASK distclean
1461
- #
1462
-
1463
- def exec_distclean
1464
- exec_task_traverse 'distclean'
1465
- rm_f @config.savefile
1466
- rm_f 'InstalledFiles'
1467
- end
1468
-
1469
- def distclean_dir_bin(rel)
1470
- end
1471
-
1472
- def distclean_dir_lib(rel)
1473
- end
1474
-
1475
- def distclean_dir_ext(rel)
1476
- return unless extdir?(curr_srcdir())
1477
- make 'distclean' if File.file?('Makefile')
1478
- end
1479
-
1480
- def distclean_dir_data(rel)
1481
- end
1482
-
1483
- def distclean_dir_conf(rel)
1484
- end
1485
-
1486
- #
1487
- # lib
1488
- #
1489
-
1490
- def exec_task_traverse(task)
1491
- run_hook "pre-#{task}"
1492
- FILETYPES.each do |type|
1493
- if config('without-ext') == 'yes' and type == 'ext'
1494
- $stderr.puts 'skipping ext/* by user option' if verbose?
1495
- next
1496
- end
1497
- traverse task, type, "#{task}_dir_#{type}"
1498
- end
1499
- run_hook "post-#{task}"
1500
- end
1501
-
1502
- def traverse(task, rel, mid)
1503
- dive_into(rel) {
1504
- run_hook "pre-#{task}"
1505
- __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '')
1506
- directories_of(curr_srcdir()).each do |d|
1507
- traverse task, "#{rel}/#{d}", mid
1508
- end
1509
- run_hook "post-#{task}"
1510
- }
1511
- end
1512
-
1513
- def dive_into(rel)
1514
- return unless File.dir?("#{@srcdir}/#{rel}")
1515
-
1516
- dir = File.basename(rel)
1517
- Dir.mkdir dir unless File.dir?(dir)
1518
- prevdir = Dir.pwd
1519
- Dir.chdir dir
1520
- $stderr.puts '---> ' + rel if verbose?
1521
- @currdir = rel
1522
- yield
1523
- Dir.chdir prevdir
1524
- $stderr.puts '<--- ' + rel if verbose?
1525
- @currdir = File.dirname(rel)
1526
- end
1527
-
1528
- def run_hook(id)
1529
- path = [ "#{curr_srcdir()}/#{id}",
1530
- "#{curr_srcdir()}/#{id}.rb" ].detect {|cand| File.file?(cand) }
1531
- return unless path
1532
- begin
1533
- instance_eval File.read(path), path, 1
1534
- rescue
1535
- raise if $DEBUG
1536
- setup_rb_error "hook #{path} failed:\n" + $!.message
1537
- end
1538
- end
1539
-
1540
- end # class Installer
1541
-
1542
-
1543
- class SetupError < StandardError; end
1544
-
1545
- def setup_rb_error(msg)
1546
- raise SetupError, msg
1547
- end
1548
-
1549
- if $0 == __FILE__
1550
- begin
1551
- ToplevelInstaller.invoke
1552
- rescue SetupError
1553
- raise if $DEBUG
1554
- $stderr.puts $!.message
1555
- $stderr.puts "Try 'ruby #{$0} --help' for detailed usage."
1556
- exit 1
1557
- end
1558
- end