kwalify 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES.txt +232 -0
- data/MIT-LICENSE +20 -0
- data/README.txt +16 -19
- data/bin/kwalify +3 -3
- data/contrib/inline-require +6 -4
- data/contrib/kwalify +3719 -2427
- data/doc-api/classes/CommandOptionError.html +17 -17
- data/doc-api/classes/CommandOptionParser.html +63 -63
- data/doc-api/classes/Kwalify.html +29 -7
- data/doc-api/classes/Kwalify/AssertionError.html +9 -9
- data/doc-api/classes/Kwalify/BaseError.html +72 -71
- data/doc-api/classes/Kwalify/BaseParser.html +461 -0
- data/doc-api/classes/Kwalify/CommandOptionError.html +11 -11
- data/doc-api/classes/Kwalify/ErrorHelper.html +51 -46
- data/doc-api/classes/Kwalify/HashInterface.html +13 -135
- data/doc-api/classes/Kwalify/Json.html +105 -0
- data/doc-api/classes/Kwalify/Main.html +129 -126
- data/doc-api/classes/Kwalify/MetaValidator.html +248 -232
- data/doc-api/classes/Kwalify/Parser.html +12 -12
- data/doc-api/classes/Kwalify/PlainYamlParser.html +166 -163
- data/doc-api/classes/Kwalify/PlainYamlParser/Alias.html +11 -11
- data/doc-api/classes/Kwalify/Rule.html +152 -130
- data/doc-api/classes/Kwalify/SchemaError.html +10 -10
- data/doc-api/classes/Kwalify/SyntaxError.html +185 -0
- data/doc-api/classes/Kwalify/Types.html +26 -25
- data/doc-api/classes/Kwalify/Util.html +389 -0
- data/doc-api/classes/Kwalify/Util/HashLike.html +246 -0
- data/doc-api/classes/Kwalify/Util/OrderedHash.html +330 -0
- data/doc-api/classes/Kwalify/ValidationError.html +10 -10
- data/doc-api/classes/Kwalify/Validator.html +153 -86
- data/doc-api/classes/Kwalify/Yaml.html +181 -0
- data/doc-api/classes/Kwalify/Yaml/Parser.html +1538 -0
- data/doc-api/classes/Kwalify/YamlParser.html +190 -183
- data/doc-api/classes/Kwalify/YamlSyntaxError.html +8 -57
- data/doc-api/created.rid +1 -1
- data/doc-api/files/__/README_txt.html +17 -22
- data/doc-api/files/kwalify/errors_rb.html +2 -2
- data/doc-api/files/kwalify/main_rb.html +4 -3
- data/doc-api/files/kwalify/messages_rb.html +2 -2
- data/doc-api/files/kwalify/meta-validator_rb.html +3 -3
- data/doc-api/files/kwalify/{util/yaml-helper_rb.html → parser/base_rb.html} +8 -6
- data/doc-api/files/kwalify/parser/yaml_rb.html +117 -0
- data/doc-api/files/kwalify/rule_rb.html +2 -2
- data/doc-api/files/kwalify/types_rb.html +2 -2
- data/doc-api/files/kwalify/util/assert-text-equal_rb.html +2 -2
- data/doc-api/files/kwalify/util/hash-interface_rb.html +9 -2
- data/doc-api/files/kwalify/util/hashlike_rb.html +107 -0
- data/doc-api/files/kwalify/util/option-parser_rb.html +2 -2
- data/doc-api/files/kwalify/util/ordered-hash_rb.html +107 -0
- data/doc-api/files/kwalify/util/testcase-helper_rb.html +2 -2
- data/doc-api/files/kwalify/util_rb.html +107 -0
- data/doc-api/files/kwalify/validator_rb.html +2 -2
- data/doc-api/files/kwalify/yaml-parser_rb.html +2 -2
- data/doc-api/files/kwalify_rb.html +3 -2
- data/doc-api/fr_class_index.html +8 -1
- data/doc-api/fr_file_index.html +5 -1
- data/doc-api/fr_method_index.html +128 -69
- data/doc/img/fig01.png +0 -0
- data/doc/users-guide.html +882 -717
- data/examples/address-book/address-book.schema.yaml +2 -2
- data/examples/data-binding/BABEL.data.yaml +63 -0
- data/examples/data-binding/BABEL.schema.yaml +31 -0
- data/examples/data-binding/Makefile +8 -0
- data/examples/data-binding/Rakefile +13 -0
- data/examples/data-binding/main.rb +27 -0
- data/examples/invoice/invoice.schema.yaml +3 -3
- data/examples/tapkit/tapkit.schema.yaml +2 -2
- data/lib/kwalify.rb +41 -4
- data/lib/kwalify/errors.rb +118 -96
- data/lib/kwalify/kwalify.schema.yaml +58 -0
- data/lib/kwalify/main.rb +384 -377
- data/lib/kwalify/messages.rb +41 -27
- data/lib/kwalify/meta-validator.rb +251 -331
- data/lib/kwalify/parser/base.rb +127 -0
- data/lib/kwalify/parser/yaml.rb +837 -0
- data/lib/kwalify/rule.rb +545 -487
- data/lib/kwalify/templates/genclass-java.eruby +189 -162
- data/lib/kwalify/templates/genclass-php.eruby +104 -0
- data/lib/kwalify/templates/genclass-ruby.eruby +95 -66
- data/lib/kwalify/types.rb +107 -106
- data/lib/kwalify/util.rb +157 -0
- data/lib/kwalify/util/assert-text-equal.rb +33 -31
- data/lib/kwalify/util/hash-interface.rb +11 -30
- data/lib/kwalify/util/hashlike.rb +51 -0
- data/lib/kwalify/util/option-parser.rb +144 -144
- data/lib/kwalify/util/ordered-hash.rb +57 -0
- data/lib/kwalify/util/testcase-helper.rb +3 -3
- data/lib/kwalify/validator.rb +267 -212
- data/lib/kwalify/yaml-parser.rb +822 -768
- data/setup.rb +861 -607
- data/test/Rookbook.yaml +10 -0
- data/test/{tmp.dir/Context.java → data/users-guide/AddressBook.java.expected} +11 -11
- data/test/data/users-guide/BABEL.data.yaml +24 -0
- data/test/data/users-guide/BABEL.schema.yaml +30 -0
- data/test/data/users-guide/ExampleAddressBook.java +47 -0
- data/test/{tmp.dir/Group.java → data/users-guide/Group.java.expected} +2 -11
- data/test/data/users-guide/Person.java.expected +44 -0
- data/test/data/users-guide/address_book.rb +52 -0
- data/test/data/users-guide/address_book.schema.yaml +28 -0
- data/test/data/users-guide/address_book.yaml +27 -0
- data/test/data/users-guide/answers-schema.yaml +12 -0
- data/test/data/users-guide/answers-validator.rb +52 -0
- data/test/data/users-guide/babel_genclass.result +26 -0
- data/test/data/users-guide/config.schema.yaml +7 -0
- data/test/data/users-guide/config.yaml +4 -0
- data/test/{tmp.dir/silent1.document → data/users-guide/document01a.yaml} +0 -0
- data/test/data/users-guide/document01b.yaml +3 -0
- data/test/data/users-guide/document02a.yaml +4 -0
- data/test/data/users-guide/document02b.yaml +4 -0
- data/test/data/users-guide/document03a.yaml +6 -0
- data/test/data/users-guide/document03b.yaml +6 -0
- data/test/data/users-guide/document04a.yaml +9 -0
- data/test/data/users-guide/document04b.yaml +9 -0
- data/test/data/users-guide/document05a.yaml +11 -0
- data/test/data/users-guide/document05b.yaml +12 -0
- data/test/data/users-guide/document06a.yaml +15 -0
- data/test/data/users-guide/document06b.yaml +16 -0
- data/test/data/users-guide/document07a.yaml +9 -0
- data/test/data/users-guide/document07b.yaml +7 -0
- data/test/data/users-guide/document12a.json +10 -0
- data/test/data/users-guide/document12b.json +6 -0
- data/test/data/users-guide/document13a.yaml +17 -0
- data/test/data/users-guide/document14a.yaml +3 -0
- data/test/data/users-guide/document14b.yaml +3 -0
- data/test/data/users-guide/document15a.yaml +6 -0
- data/test/data/users-guide/document15b.yaml +5 -0
- data/test/data/users-guide/example_address_book.rb +10 -0
- data/test/data/users-guide/example_address_book_java.result +32 -0
- data/test/data/users-guide/example_address_book_ruby.result +31 -0
- data/test/data/users-guide/genclass_java.result +4 -0
- data/test/data/users-guide/howto-validation-with-parsing.rb +28 -0
- data/test/data/users-guide/howto-validation.rb +25 -0
- data/test/data/users-guide/howto3.rb +6 -0
- data/test/data/users-guide/howto3.result +5 -0
- data/test/data/users-guide/howto3.yaml +8 -0
- data/test/data/users-guide/howto5_databinding.result +111 -0
- data/test/data/users-guide/invalid01.result +3 -0
- data/test/data/users-guide/invalid02.result +5 -0
- data/test/data/users-guide/invalid03.result +5 -0
- data/test/data/users-guide/invalid04.result +4 -0
- data/test/data/users-guide/invalid05.result +11 -0
- data/test/data/users-guide/invalid06.result +4 -0
- data/test/data/users-guide/invalid07.result +3 -0
- data/test/data/users-guide/invalid08.result +3 -0
- data/test/data/users-guide/invalid12.json +8 -0
- data/test/data/users-guide/invalid14.result +4 -0
- data/test/data/users-guide/invalid15.result +4 -0
- data/test/data/users-guide/loadbabel.rb +27 -0
- data/test/data/users-guide/loadconfig.rb +15 -0
- data/test/data/users-guide/loadconfig.result +2 -0
- data/test/data/users-guide/models.rb +22 -0
- data/test/data/users-guide/option_ha.result +6 -0
- data/test/data/users-guide/option_ha_genclass_java.result +7 -0
- data/test/{tmp.dir/meta1.schema → data/users-guide/schema01.yaml} +0 -0
- data/test/data/users-guide/schema02.yaml +12 -0
- data/test/data/users-guide/schema03.yaml +9 -0
- data/test/data/users-guide/schema04.yaml +20 -0
- data/test/data/users-guide/schema05.yaml +29 -0
- data/test/data/users-guide/schema06.yaml +11 -0
- data/test/data/users-guide/schema12.json +12 -0
- data/test/data/users-guide/schema13.yaml +13 -0
- data/test/data/users-guide/schema14.yaml +5 -0
- data/test/data/users-guide/schema15.yaml +21 -0
- data/test/data/users-guide/valid01.result +2 -0
- data/test/data/users-guide/valid02.result +2 -0
- data/test/data/users-guide/valid03.result +2 -0
- data/test/data/users-guide/valid04.result +2 -0
- data/test/data/users-guide/valid05.result +2 -0
- data/test/data/users-guide/valid06.result +2 -0
- data/test/data/users-guide/valid07.result +2 -0
- data/test/data/users-guide/valid08.result +2 -0
- data/test/data/users-guide/valid12.result +2 -0
- data/test/data/users-guide/valid13.result +2 -0
- data/test/data/users-guide/valid14.result +2 -0
- data/test/data/users-guide/valid15.result +2 -0
- data/test/data/users-guide/validate08.rb +37 -0
- data/test/test-action.rb +78 -0
- data/test/test-action.yaml +738 -0
- data/test/test-databinding.rb +80 -0
- data/test/test-databinding.yaml +301 -0
- data/test/test-main.rb +129 -150
- data/test/test-main.yaml +126 -321
- data/test/test-metavalidator.rb +47 -47
- data/test/test-metavalidator.yaml +77 -21
- data/test/test-parser-yaml.rb +57 -0
- data/test/test-parser-yaml.yaml +1749 -0
- data/test/test-rule.rb +14 -15
- data/test/test-rule.yaml +6 -3
- data/test/test-users-guide.rb +75 -0
- data/test/test-validator.rb +77 -52
- data/test/test-validator.yaml +168 -6
- data/test/test-yaml-parser.rb +47 -0
- data/test/{test-yamlparser.yaml → test-yaml-parser.yaml} +159 -52
- data/test/test.rb +37 -21
- metadata +136 -37
- data/COPYING +0 -340
- data/ChangeLog +0 -70
- data/doc-api/classes/YamlHelper.html +0 -259
- data/lib/kwalify/util/yaml-helper.rb +0 -82
- data/test/test-yamlparser.rb +0 -58
- data/test/tmp.dir/User.java +0 -43
- data/test/tmp.dir/action1.document +0 -18
- data/test/tmp.dir/action1.schema +0 -32
- data/test/tmp.dir/action2.document +0 -18
- data/test/tmp.dir/action2.schema +0 -32
- data/test/tmp.dir/emacs.document +0 -6
- data/test/tmp.dir/emacs.schema +0 -6
- data/test/tmp.dir/meta1.document +0 -0
- data/test/tmp.dir/meta2.document +0 -0
- data/test/tmp.dir/meta2.schema +0 -3
- data/test/tmp.dir/silent1.schema +0 -3
- data/test/tmp.dir/silent2.document +0 -7
- data/test/tmp.dir/silent2.schema +0 -3
- data/test/tmp.dir/stream.invalid +0 -8
- data/test/tmp.dir/stream.schema +0 -3
- data/test/tmp.dir/stream.valid +0 -8
- data/test/tmp.dir/untabify.document +0 -5
- data/test/tmp.dir/untabify.schema +0 -10
- data/todo.txt +0 -34
data/setup.rb
CHANGED
@@ -1,70 +1,20 @@
|
|
1
1
|
#
|
2
2
|
# setup.rb
|
3
3
|
#
|
4
|
-
# Copyright (c) 2000-
|
4
|
+
# Copyright (c) 2000-2005 Minero Aoki
|
5
5
|
#
|
6
6
|
# This program is free software.
|
7
7
|
# You can distribute/modify this program under the terms of
|
8
|
-
# the GNU Lesser General Public License version 2.1.
|
8
|
+
# the GNU LGPL, Lesser General Public License version 2.1.
|
9
9
|
#
|
10
10
|
|
11
|
-
#
|
12
|
-
# For backward compatibility
|
13
|
-
#
|
14
|
-
|
15
|
-
unless Enumerable.method_defined?(:map)
|
11
|
+
unless Enumerable.method_defined?(:map) # Ruby 1.4.6
|
16
12
|
module Enumerable
|
17
13
|
alias map collect
|
18
14
|
end
|
19
15
|
end
|
20
16
|
|
21
|
-
unless
|
22
|
-
module Enumerable
|
23
|
-
alias detect find
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
unless Enumerable.method_defined?(:select)
|
28
|
-
module Enumerable
|
29
|
-
alias select find_all
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
unless Enumerable.method_defined?(:reject)
|
34
|
-
module Enumerable
|
35
|
-
def reject
|
36
|
-
result = []
|
37
|
-
each do |i|
|
38
|
-
result.push i unless yield(i)
|
39
|
-
end
|
40
|
-
result
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
unless Enumerable.method_defined?(:inject)
|
46
|
-
module Enumerable
|
47
|
-
def inject(result)
|
48
|
-
each do |i|
|
49
|
-
result = yield(result, i)
|
50
|
-
end
|
51
|
-
result
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
unless Enumerable.method_defined?(:any?)
|
57
|
-
module Enumerable
|
58
|
-
def any?
|
59
|
-
each do |i|
|
60
|
-
return true if yield(i)
|
61
|
-
end
|
62
|
-
false
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
unless File.respond_to?(:read)
|
17
|
+
unless File.respond_to?(:read) # Ruby 1.6
|
68
18
|
def File.read(fname)
|
69
19
|
open(fname) {|f|
|
70
20
|
return f.read
|
@@ -72,9 +22,13 @@ unless File.respond_to?(:read)
|
|
72
22
|
end
|
73
23
|
end
|
74
24
|
|
75
|
-
#
|
76
|
-
|
77
|
-
|
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
|
78
32
|
|
79
33
|
def File.binread(fname)
|
80
34
|
open(fname, 'rb') {|f|
|
@@ -82,311 +36,512 @@ def File.binread(fname)
|
|
82
36
|
}
|
83
37
|
end
|
84
38
|
|
85
|
-
# for corrupted
|
39
|
+
# for corrupted Windows' stat(2)
|
86
40
|
def File.dir?(path)
|
87
41
|
File.directory?((path[-1,1] == '/') ? path : path + '/')
|
88
42
|
end
|
89
43
|
|
90
|
-
#
|
91
|
-
# Config
|
92
|
-
#
|
93
|
-
|
94
|
-
if arg = ARGV.detect{|arg| /\A--rbconfig=/ =~ arg }
|
95
|
-
ARGV.delete(arg)
|
96
|
-
require arg.split(/=/, 2)[1]
|
97
|
-
$".push 'rbconfig.rb'
|
98
|
-
else
|
99
|
-
require 'rbconfig'
|
100
|
-
end
|
101
|
-
|
102
|
-
def multipackage_install?
|
103
|
-
FileTest.directory?(File.dirname($0) + '/packages')
|
104
|
-
end
|
105
|
-
|
106
44
|
|
107
45
|
class ConfigTable
|
108
46
|
|
109
|
-
|
47
|
+
include Enumerable
|
110
48
|
|
111
|
-
|
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
|
+
end
|
112
59
|
|
113
|
-
|
114
|
-
|
115
|
-
teeny = c['TEENY'].to_i
|
116
|
-
version = "#{major}.#{minor}"
|
60
|
+
attr_accessor :install_prefix
|
61
|
+
attr_accessor :config_opt
|
117
62
|
|
118
|
-
|
119
|
-
newpath_p = ((major >= 2) or
|
120
|
-
((major == 1) and
|
121
|
-
((minor >= 5) or
|
122
|
-
((minor == 4) and (teeny >= 4)))))
|
123
|
-
|
124
|
-
subprefix = lambda {|path|
|
125
|
-
path.sub(/\A#{Regexp.quote(c['prefix'])}/o, '$prefix')
|
126
|
-
}
|
63
|
+
attr_writer :verbose
|
127
64
|
|
128
|
-
|
129
|
-
|
130
|
-
stdruby = subprefix.call(c['rubylibdir'])
|
131
|
-
siteruby = subprefix.call(c['sitedir'])
|
132
|
-
versite = subprefix.call(c['sitelibdir'])
|
133
|
-
sodir = subprefix.call(c['sitearchdir'])
|
134
|
-
elsif newpath_p
|
135
|
-
# 1.4.4 <= V <= 1.6.3
|
136
|
-
stdruby = "$prefix/lib/ruby/#{version}"
|
137
|
-
siteruby = subprefix.call(c['sitedir'])
|
138
|
-
versite = siteruby + '/' + version
|
139
|
-
sodir = "$site-ruby/#{c['arch']}"
|
140
|
-
else
|
141
|
-
# V < 1.4.4
|
142
|
-
stdruby = "$prefix/lib/ruby/#{version}"
|
143
|
-
siteruby = "$prefix/lib/ruby/#{version}/site_ruby"
|
144
|
-
versite = siteruby
|
145
|
-
sodir = "$site-ruby/#{c['arch']}"
|
146
|
-
end
|
147
|
-
|
148
|
-
if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg }
|
149
|
-
makeprog = arg.sub(/'/, '').split(/=/, 2)[1]
|
150
|
-
else
|
151
|
-
makeprog = 'make'
|
152
|
-
end
|
153
|
-
|
154
|
-
common_descripters = [
|
155
|
-
[ 'prefix', [ c['prefix'],
|
156
|
-
'path',
|
157
|
-
'path prefix of target environment' ] ],
|
158
|
-
[ 'std-ruby', [ stdruby,
|
159
|
-
'path',
|
160
|
-
'the directory for standard ruby libraries' ] ],
|
161
|
-
[ 'site-ruby-common', [ siteruby,
|
162
|
-
'path',
|
163
|
-
'the directory for version-independent non-standard ruby libraries' ] ],
|
164
|
-
[ 'site-ruby', [ versite,
|
165
|
-
'path',
|
166
|
-
'the directory for non-standard ruby libraries' ] ],
|
167
|
-
[ 'bin-dir', [ '$prefix/bin',
|
168
|
-
'path',
|
169
|
-
'the directory for commands' ] ],
|
170
|
-
[ 'rb-dir', [ '$site-ruby',
|
171
|
-
'path',
|
172
|
-
'the directory for ruby scripts' ] ],
|
173
|
-
[ 'so-dir', [ sodir,
|
174
|
-
'path',
|
175
|
-
'the directory for ruby extentions' ] ],
|
176
|
-
[ 'data-dir', [ '$prefix/share',
|
177
|
-
'path',
|
178
|
-
'the directory for shared data' ] ],
|
179
|
-
[ 'ruby-path', [ rubypath,
|
180
|
-
'path',
|
181
|
-
'path to set to #! line' ] ],
|
182
|
-
[ 'ruby-prog', [ rubypath,
|
183
|
-
'name',
|
184
|
-
'the ruby program using for installation' ] ],
|
185
|
-
[ 'make-prog', [ makeprog,
|
186
|
-
'name',
|
187
|
-
'the make program to compile ruby extentions' ] ],
|
188
|
-
[ 'without-ext', [ 'no',
|
189
|
-
'yes/no',
|
190
|
-
'does not compile/install ruby extentions' ] ]
|
191
|
-
]
|
192
|
-
multipackage_descripters = [
|
193
|
-
[ 'with', [ '',
|
194
|
-
'name,name...',
|
195
|
-
'package names that you want to install',
|
196
|
-
'ALL' ] ],
|
197
|
-
[ 'without', [ '',
|
198
|
-
'name,name...',
|
199
|
-
'package names that you do not want to install',
|
200
|
-
'NONE' ] ]
|
201
|
-
]
|
202
|
-
if multipackage_install?
|
203
|
-
DESCRIPTER = common_descripters + multipackage_descripters
|
204
|
-
else
|
205
|
-
DESCRIPTER = common_descripters
|
65
|
+
def verbose?
|
66
|
+
@verbose
|
206
67
|
end
|
207
68
|
|
208
|
-
|
69
|
+
attr_writer :no_harm
|
209
70
|
|
210
|
-
def
|
211
|
-
|
71
|
+
def no_harm?
|
72
|
+
@no_harm
|
212
73
|
end
|
213
74
|
|
214
|
-
def
|
215
|
-
|
75
|
+
def [](key)
|
76
|
+
lookup(key).resolve(self)
|
216
77
|
end
|
217
78
|
|
218
|
-
def
|
219
|
-
|
79
|
+
def []=(key, val)
|
80
|
+
lookup(key).set val
|
220
81
|
end
|
221
82
|
|
222
|
-
def
|
223
|
-
|
224
|
-
ent
|
83
|
+
def names
|
84
|
+
@items.map {|i| i.name }
|
225
85
|
end
|
226
86
|
|
227
|
-
def
|
228
|
-
|
87
|
+
def each(&block)
|
88
|
+
@items.each(&block)
|
229
89
|
end
|
230
90
|
|
231
|
-
def
|
232
|
-
|
91
|
+
def key?(name)
|
92
|
+
@table.key?(name)
|
233
93
|
end
|
234
94
|
|
235
|
-
def
|
236
|
-
|
237
|
-
DESCRIPTER.delete_if {|n, arr| n == name }
|
95
|
+
def lookup(name)
|
96
|
+
@table[name] or setup_rb_error "no such config item: #{name}"
|
238
97
|
end
|
239
98
|
|
240
|
-
def
|
241
|
-
|
99
|
+
def add(item)
|
100
|
+
@items.push item
|
101
|
+
@table[item.name] = item
|
242
102
|
end
|
243
103
|
|
244
|
-
def
|
245
|
-
|
246
|
-
|
104
|
+
def remove(name)
|
105
|
+
item = lookup(name)
|
106
|
+
@items.delete_if {|i| i.name == name }
|
107
|
+
@table.delete_if {|name, i| i.name == name }
|
108
|
+
item
|
247
109
|
end
|
248
110
|
|
249
|
-
def
|
250
|
-
|
251
|
-
|
111
|
+
def load_script(path, inst = nil)
|
112
|
+
if File.file?(path)
|
113
|
+
MetaConfigEnvironment.new(self, inst).instance_eval File.read(path), path
|
114
|
+
end
|
252
115
|
end
|
253
116
|
|
254
|
-
def
|
255
|
-
|
256
|
-
ent[1] == 'path'
|
117
|
+
def savefile
|
118
|
+
'.config'
|
257
119
|
end
|
258
120
|
|
259
|
-
|
260
|
-
|
261
|
-
|
121
|
+
def load_savefile
|
122
|
+
begin
|
123
|
+
File.foreach(savefile()) do |line|
|
124
|
+
k, v = *line.split(/=/, 2)
|
125
|
+
self[k] = v.strip
|
126
|
+
end
|
127
|
+
rescue Errno::ENOENT
|
128
|
+
setup_rb_error $!.message + "\n#{File.basename($0)} config first"
|
129
|
+
end
|
262
130
|
end
|
263
131
|
|
264
|
-
def
|
265
|
-
|
266
|
-
|
267
|
-
|
132
|
+
def save
|
133
|
+
@items.each {|i| i.value }
|
134
|
+
File.open(savefile(), 'w') {|f|
|
135
|
+
@items.each do |i|
|
136
|
+
f.printf "%s=%s\n", i.name, i.value if i.value? and i.value
|
137
|
+
end
|
138
|
+
}
|
268
139
|
end
|
269
140
|
|
270
|
-
def
|
271
|
-
|
272
|
-
|
273
|
-
|
141
|
+
def load_standard_entries
|
142
|
+
standard_entries(@rbconfig).each do |ent|
|
143
|
+
add ent
|
144
|
+
end
|
274
145
|
end
|
275
146
|
|
276
|
-
def
|
277
|
-
|
278
|
-
|
279
|
-
|
147
|
+
def standard_entries(rbconfig)
|
148
|
+
c = rbconfig
|
149
|
+
|
150
|
+
rubypath = File.join(c['bindir'], c['ruby_install_name'] + c['EXEEXT'])
|
151
|
+
|
152
|
+
major = c['MAJOR'].to_i
|
153
|
+
minor = c['MINOR'].to_i
|
154
|
+
teeny = c['TEENY'].to_i
|
155
|
+
version = "#{major}.#{minor}"
|
156
|
+
|
157
|
+
# ruby ver. >= 1.4.4?
|
158
|
+
newpath_p = ((major >= 2) or
|
159
|
+
((major == 1) and
|
160
|
+
((minor >= 5) or
|
161
|
+
((minor == 4) and (teeny >= 4)))))
|
162
|
+
|
163
|
+
if c['rubylibdir']
|
164
|
+
# V > 1.6.3
|
165
|
+
libruby = "#{c['prefix']}/lib/ruby"
|
166
|
+
librubyver = c['rubylibdir']
|
167
|
+
librubyverarch = c['archdir']
|
168
|
+
siteruby = c['sitedir']
|
169
|
+
siterubyver = c['sitelibdir']
|
170
|
+
siterubyverarch = c['sitearchdir']
|
171
|
+
elsif newpath_p
|
172
|
+
# 1.4.4 <= V <= 1.6.3
|
173
|
+
libruby = "#{c['prefix']}/lib/ruby"
|
174
|
+
librubyver = "#{c['prefix']}/lib/ruby/#{version}"
|
175
|
+
librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}"
|
176
|
+
siteruby = c['sitedir']
|
177
|
+
siterubyver = "$siteruby/#{version}"
|
178
|
+
siterubyverarch = "$siterubyver/#{c['arch']}"
|
179
|
+
else
|
180
|
+
# V < 1.4.4
|
181
|
+
libruby = "#{c['prefix']}/lib/ruby"
|
182
|
+
librubyver = "#{c['prefix']}/lib/ruby/#{version}"
|
183
|
+
librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}"
|
184
|
+
siteruby = "#{c['prefix']}/lib/ruby/#{version}/site_ruby"
|
185
|
+
siterubyver = siteruby
|
186
|
+
siterubyverarch = "$siterubyver/#{c['arch']}"
|
280
187
|
end
|
281
|
-
|
188
|
+
parameterize = lambda {|path|
|
189
|
+
path.sub(/\A#{Regexp.quote(c['prefix'])}/, '$prefix')
|
190
|
+
}
|
282
191
|
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
File.foreach(SAVE_FILE) do |line|
|
288
|
-
k, v = line.split(/=/, 2)
|
289
|
-
@table[k] = v.strip
|
192
|
+
if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg }
|
193
|
+
makeprog = arg.sub(/'/, '').split(/=/, 2)[1]
|
194
|
+
else
|
195
|
+
makeprog = 'make'
|
290
196
|
end
|
291
|
-
end
|
292
197
|
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
198
|
+
[
|
199
|
+
ExecItem.new('installdirs', 'std/site/home',
|
200
|
+
'std: install under libruby; site: install under site_ruby; home: install under $HOME')\
|
201
|
+
{|val, table|
|
202
|
+
case val
|
203
|
+
when 'std'
|
204
|
+
table['rbdir'] = '$librubyver'
|
205
|
+
table['sodir'] = '$librubyverarch'
|
206
|
+
when 'site'
|
207
|
+
table['rbdir'] = '$siterubyver'
|
208
|
+
table['sodir'] = '$siterubyverarch'
|
209
|
+
when 'home'
|
210
|
+
setup_rb_error '$HOME was not set' unless ENV['HOME']
|
211
|
+
table['prefix'] = ENV['HOME']
|
212
|
+
table['rbdir'] = '$libdir/ruby'
|
213
|
+
table['sodir'] = '$libdir/ruby'
|
214
|
+
end
|
215
|
+
},
|
216
|
+
PathItem.new('prefix', 'path', c['prefix'],
|
217
|
+
'path prefix of target environment'),
|
218
|
+
PathItem.new('bindir', 'path', parameterize.call(c['bindir']),
|
219
|
+
'the directory for commands'),
|
220
|
+
PathItem.new('libdir', 'path', parameterize.call(c['libdir']),
|
221
|
+
'the directory for libraries'),
|
222
|
+
PathItem.new('datadir', 'path', parameterize.call(c['datadir']),
|
223
|
+
'the directory for shared data'),
|
224
|
+
PathItem.new('mandir', 'path', parameterize.call(c['mandir']),
|
225
|
+
'the directory for man pages'),
|
226
|
+
PathItem.new('sysconfdir', 'path', parameterize.call(c['sysconfdir']),
|
227
|
+
'the directory for system configuration files'),
|
228
|
+
PathItem.new('localstatedir', 'path', parameterize.call(c['localstatedir']),
|
229
|
+
'the directory for local state data'),
|
230
|
+
PathItem.new('libruby', 'path', libruby,
|
231
|
+
'the directory for ruby libraries'),
|
232
|
+
PathItem.new('librubyver', 'path', librubyver,
|
233
|
+
'the directory for standard ruby libraries'),
|
234
|
+
PathItem.new('librubyverarch', 'path', librubyverarch,
|
235
|
+
'the directory for standard ruby extensions'),
|
236
|
+
PathItem.new('siteruby', 'path', siteruby,
|
237
|
+
'the directory for version-independent aux ruby libraries'),
|
238
|
+
PathItem.new('siterubyver', 'path', siterubyver,
|
239
|
+
'the directory for aux ruby libraries'),
|
240
|
+
PathItem.new('siterubyverarch', 'path', siterubyverarch,
|
241
|
+
'the directory for aux ruby binaries'),
|
242
|
+
PathItem.new('rbdir', 'path', '$siterubyver',
|
243
|
+
'the directory for ruby scripts'),
|
244
|
+
PathItem.new('sodir', 'path', '$siterubyverarch',
|
245
|
+
'the directory for ruby extentions'),
|
246
|
+
PathItem.new('rubypath', 'path', rubypath,
|
247
|
+
'the path to set to #! line'),
|
248
|
+
ProgramItem.new('rubyprog', 'name', rubypath,
|
249
|
+
'the ruby program using for installation'),
|
250
|
+
ProgramItem.new('makeprog', 'name', makeprog,
|
251
|
+
'the make program to compile ruby extentions'),
|
252
|
+
SelectItem.new('shebang', 'all/ruby/never', 'ruby',
|
253
|
+
'shebang line (#!) editing mode'),
|
254
|
+
BoolItem.new('without-ext', 'yes/no', 'no',
|
255
|
+
'does not compile/install ruby extentions')
|
256
|
+
]
|
257
|
+
end
|
258
|
+
private :standard_entries
|
259
|
+
|
260
|
+
def load_multipackage_entries
|
261
|
+
multipackage_entries().each do |ent|
|
262
|
+
add ent
|
263
|
+
end
|
299
264
|
end
|
300
265
|
|
301
|
-
def
|
302
|
-
|
303
|
-
|
304
|
-
|
266
|
+
def multipackage_entries
|
267
|
+
[
|
268
|
+
PackageSelectionItem.new('with', 'name,name...', '', 'ALL',
|
269
|
+
'package names that you want to install'),
|
270
|
+
PackageSelectionItem.new('without', 'name,name...', '', 'NONE',
|
271
|
+
'package names that you do not want to install')
|
272
|
+
]
|
273
|
+
end
|
274
|
+
private :multipackage_entries
|
275
|
+
|
276
|
+
ALIASES = {
|
277
|
+
'std-ruby' => 'librubyver',
|
278
|
+
'stdruby' => 'librubyver',
|
279
|
+
'rubylibdir' => 'librubyver',
|
280
|
+
'archdir' => 'librubyverarch',
|
281
|
+
'site-ruby-common' => 'siteruby', # For backward compatibility
|
282
|
+
'site-ruby' => 'siterubyver', # For backward compatibility
|
283
|
+
'bin-dir' => 'bindir',
|
284
|
+
'bin-dir' => 'bindir',
|
285
|
+
'rb-dir' => 'rbdir',
|
286
|
+
'so-dir' => 'sodir',
|
287
|
+
'data-dir' => 'datadir',
|
288
|
+
'ruby-path' => 'rubypath',
|
289
|
+
'ruby-prog' => 'rubyprog',
|
290
|
+
'ruby' => 'rubyprog',
|
291
|
+
'make-prog' => 'makeprog',
|
292
|
+
'make' => 'makeprog'
|
293
|
+
}
|
294
|
+
|
295
|
+
def fixup
|
296
|
+
ALIASES.each do |ali, name|
|
297
|
+
@table[ali] = @table[name]
|
298
|
+
end
|
299
|
+
@items.freeze
|
300
|
+
@table.freeze
|
301
|
+
@options_re = /\A--(#{@table.keys.join('|')})(?:=(.*))?\z/
|
305
302
|
end
|
306
|
-
|
307
|
-
def
|
308
|
-
|
309
|
-
|
303
|
+
|
304
|
+
def parse_opt(opt)
|
305
|
+
m = @options_re.match(opt) or setup_rb_error "config: unknown option #{opt}"
|
306
|
+
m.to_a[1,2]
|
310
307
|
end
|
311
308
|
|
312
|
-
def
|
313
|
-
@
|
309
|
+
def dllext
|
310
|
+
@rbconfig['DLEXT']
|
314
311
|
end
|
315
312
|
|
316
|
-
def
|
317
|
-
|
313
|
+
def value_config?(name)
|
314
|
+
lookup(name).value?
|
318
315
|
end
|
319
316
|
|
320
|
-
|
317
|
+
class Item
|
318
|
+
def initialize(name, template, default, desc)
|
319
|
+
@name = name.freeze
|
320
|
+
@template = template
|
321
|
+
@value = default
|
322
|
+
@default = default
|
323
|
+
@description = desc
|
324
|
+
end
|
321
325
|
|
326
|
+
attr_reader :name
|
327
|
+
attr_reader :description
|
322
328
|
|
323
|
-
|
329
|
+
attr_accessor :default
|
330
|
+
alias help_default default
|
324
331
|
|
325
|
-
|
326
|
-
|
327
|
-
|
332
|
+
def help_opt
|
333
|
+
"--#{@name}=#{@template}"
|
334
|
+
end
|
328
335
|
|
329
|
-
|
330
|
-
|
331
|
-
|
336
|
+
def value?
|
337
|
+
true
|
338
|
+
end
|
332
339
|
|
333
|
-
|
334
|
-
|
335
|
-
|
340
|
+
def value
|
341
|
+
@value
|
342
|
+
end
|
343
|
+
|
344
|
+
def resolve(table)
|
345
|
+
@value.gsub(%r<\$([^/]+)>) { table[$1] }
|
346
|
+
end
|
336
347
|
|
337
|
-
|
338
|
-
|
348
|
+
def set(val)
|
349
|
+
@value = check(val)
|
350
|
+
end
|
351
|
+
|
352
|
+
private
|
353
|
+
|
354
|
+
def check(val)
|
355
|
+
setup_rb_error "config: --#{name} requires argument" unless val
|
356
|
+
val
|
357
|
+
end
|
339
358
|
end
|
340
359
|
|
341
|
-
|
342
|
-
|
360
|
+
class BoolItem < Item
|
361
|
+
def config_type
|
362
|
+
'bool'
|
363
|
+
end
|
364
|
+
|
365
|
+
def help_opt
|
366
|
+
"--#{@name}"
|
367
|
+
end
|
368
|
+
|
369
|
+
private
|
370
|
+
|
371
|
+
def check(val)
|
372
|
+
return 'yes' unless val
|
373
|
+
case val
|
374
|
+
when /\Ay(es)?\z/i, /\At(rue)?\z/i then 'yes'
|
375
|
+
when /\An(o)?\z/i, /\Af(alse)\z/i then 'no'
|
376
|
+
else
|
377
|
+
setup_rb_error "config: --#{@name} accepts only yes/no for argument"
|
378
|
+
end
|
379
|
+
end
|
343
380
|
end
|
344
381
|
|
345
|
-
|
346
|
-
|
382
|
+
class PathItem < Item
|
383
|
+
def config_type
|
384
|
+
'path'
|
385
|
+
end
|
386
|
+
|
387
|
+
private
|
388
|
+
|
389
|
+
def check(path)
|
390
|
+
setup_rb_error "config: --#{@name} requires argument" unless path
|
391
|
+
path[0,1] == '$' ? path : File.expand_path(path)
|
392
|
+
end
|
347
393
|
end
|
348
394
|
|
349
|
-
|
350
|
-
|
395
|
+
class ProgramItem < Item
|
396
|
+
def config_type
|
397
|
+
'program'
|
398
|
+
end
|
351
399
|
end
|
352
400
|
|
353
|
-
|
354
|
-
|
401
|
+
class SelectItem < Item
|
402
|
+
def initialize(name, selection, default, desc)
|
403
|
+
super
|
404
|
+
@ok = selection.split('/')
|
405
|
+
end
|
406
|
+
|
407
|
+
def config_type
|
408
|
+
'select'
|
409
|
+
end
|
410
|
+
|
411
|
+
private
|
412
|
+
|
413
|
+
def check(val)
|
414
|
+
unless @ok.include?(val.strip)
|
415
|
+
setup_rb_error "config: use --#{@name}=#{@template} (#{val})"
|
416
|
+
end
|
417
|
+
val.strip
|
418
|
+
end
|
355
419
|
end
|
356
420
|
|
357
|
-
|
358
|
-
|
421
|
+
class ExecItem < Item
|
422
|
+
def initialize(name, selection, desc, &block)
|
423
|
+
super name, selection, nil, desc
|
424
|
+
@ok = selection.split('/')
|
425
|
+
@action = block
|
426
|
+
end
|
427
|
+
|
428
|
+
def config_type
|
429
|
+
'exec'
|
430
|
+
end
|
431
|
+
|
432
|
+
def value?
|
433
|
+
false
|
434
|
+
end
|
435
|
+
|
436
|
+
def resolve(table)
|
437
|
+
setup_rb_error "$#{name()} wrongly used as option value"
|
438
|
+
end
|
439
|
+
|
440
|
+
undef set
|
441
|
+
|
442
|
+
def evaluate(val, table)
|
443
|
+
v = val.strip.downcase
|
444
|
+
unless @ok.include?(v)
|
445
|
+
setup_rb_error "invalid option --#{@name}=#{val} (use #{@template})"
|
446
|
+
end
|
447
|
+
@action.call v, table
|
448
|
+
end
|
359
449
|
end
|
360
450
|
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
451
|
+
class PackageSelectionItem < Item
|
452
|
+
def initialize(name, template, default, help_default, desc)
|
453
|
+
super name, template, default, desc
|
454
|
+
@help_default = help_default
|
455
|
+
end
|
456
|
+
|
457
|
+
attr_reader :help_default
|
458
|
+
|
459
|
+
def config_type
|
460
|
+
'package'
|
461
|
+
end
|
462
|
+
|
463
|
+
private
|
464
|
+
|
465
|
+
def check(val)
|
466
|
+
unless File.dir?("packages/#{val}")
|
467
|
+
setup_rb_error "config: no such package: #{val}"
|
468
|
+
end
|
469
|
+
val
|
366
470
|
end
|
367
471
|
end
|
368
472
|
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
473
|
+
class MetaConfigEnvironment
|
474
|
+
def initialize(config, installer)
|
475
|
+
@config = config
|
476
|
+
@installer = installer
|
477
|
+
end
|
478
|
+
|
479
|
+
def config_names
|
480
|
+
@config.names
|
481
|
+
end
|
482
|
+
|
483
|
+
def config?(name)
|
484
|
+
@config.key?(name)
|
485
|
+
end
|
486
|
+
|
487
|
+
def bool_config?(name)
|
488
|
+
@config.lookup(name).config_type == 'bool'
|
489
|
+
end
|
490
|
+
|
491
|
+
def path_config?(name)
|
492
|
+
@config.lookup(name).config_type == 'path'
|
493
|
+
end
|
494
|
+
|
495
|
+
def value_config?(name)
|
496
|
+
@config.lookup(name).config_type != 'exec'
|
497
|
+
end
|
498
|
+
|
499
|
+
def add_config(item)
|
500
|
+
@config.add item
|
501
|
+
end
|
502
|
+
|
503
|
+
def add_bool_config(name, default, desc)
|
504
|
+
@config.add BoolItem.new(name, 'yes/no', default ? 'yes' : 'no', desc)
|
505
|
+
end
|
506
|
+
|
507
|
+
def add_path_config(name, default, desc)
|
508
|
+
@config.add PathItem.new(name, 'path', default, desc)
|
509
|
+
end
|
510
|
+
|
511
|
+
def set_config_default(name, default)
|
512
|
+
@config.lookup(name).default = default
|
513
|
+
end
|
514
|
+
|
515
|
+
def remove_config(name)
|
516
|
+
@config.remove(name)
|
517
|
+
end
|
518
|
+
|
519
|
+
# For only multipackage
|
520
|
+
def packages
|
521
|
+
raise '[setup.rb fatal] multi-package metaconfig API packages() called for single-package; contact application package vendor' unless @installer
|
522
|
+
@installer.packages
|
523
|
+
end
|
524
|
+
|
525
|
+
# For only multipackage
|
526
|
+
def declare_packages(list)
|
527
|
+
raise '[setup.rb fatal] multi-package metaconfig API declare_packages() called for single-package; contact application package vendor' unless @installer
|
528
|
+
@installer.packages = list
|
529
|
+
end
|
373
530
|
end
|
374
531
|
|
375
|
-
end
|
532
|
+
end # class ConfigTable
|
376
533
|
|
377
|
-
#
|
378
|
-
# File Operations
|
379
|
-
#
|
380
534
|
|
535
|
+
# This module requires: #verbose?, #no_harm?
|
381
536
|
module FileOperations
|
382
537
|
|
383
538
|
def mkdir_p(dirname, prefix = nil)
|
384
|
-
dirname = prefix + dirname if prefix
|
539
|
+
dirname = prefix + File.expand_path(dirname) if prefix
|
385
540
|
$stderr.puts "mkdir -p #{dirname}" if verbose?
|
386
541
|
return if no_harm?
|
387
542
|
|
388
|
-
#
|
389
|
-
dirs = dirname.split(%r<(?=/)>)
|
543
|
+
# Does not check '/', it's too abnormal.
|
544
|
+
dirs = File.expand_path(dirname).split(%r<(?=/)>)
|
390
545
|
if /\A[a-z]:\z/i =~ dirs[0]
|
391
546
|
disk = dirs.shift
|
392
547
|
dirs[0] = disk + dirs[0]
|
@@ -397,54 +552,78 @@ module FileOperations
|
|
397
552
|
end
|
398
553
|
end
|
399
554
|
|
400
|
-
def rm_f(
|
401
|
-
$stderr.puts "rm -f #{
|
555
|
+
def rm_f(path)
|
556
|
+
$stderr.puts "rm -f #{path}" if verbose?
|
402
557
|
return if no_harm?
|
403
|
-
|
404
|
-
if File.exist?(fname) or File.symlink?(fname)
|
405
|
-
File.chmod 0777, fname
|
406
|
-
File.unlink fname
|
407
|
-
end
|
558
|
+
force_remove_file path
|
408
559
|
end
|
409
560
|
|
410
|
-
def rm_rf(
|
411
|
-
$stderr.puts "rm -rf #{
|
561
|
+
def rm_rf(path)
|
562
|
+
$stderr.puts "rm -rf #{path}" if verbose?
|
412
563
|
return if no_harm?
|
564
|
+
remove_tree path
|
565
|
+
end
|
566
|
+
|
567
|
+
def remove_tree(path)
|
568
|
+
if File.symlink?(path)
|
569
|
+
remove_file path
|
570
|
+
elsif File.dir?(path)
|
571
|
+
remove_tree0 path
|
572
|
+
else
|
573
|
+
force_remove_file path
|
574
|
+
end
|
575
|
+
end
|
413
576
|
|
414
|
-
|
415
|
-
Dir.foreach(
|
416
|
-
next if
|
417
|
-
next if
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
577
|
+
def remove_tree0(path)
|
578
|
+
Dir.foreach(path) do |ent|
|
579
|
+
next if ent == '.'
|
580
|
+
next if ent == '..'
|
581
|
+
entpath = "#{path}/#{ent}"
|
582
|
+
if File.symlink?(entpath)
|
583
|
+
remove_file entpath
|
584
|
+
elsif File.dir?(entpath)
|
585
|
+
remove_tree0 entpath
|
422
586
|
else
|
423
|
-
|
424
|
-
rm_f fn
|
425
|
-
}
|
587
|
+
force_remove_file entpath
|
426
588
|
end
|
427
589
|
end
|
428
|
-
|
429
|
-
|
590
|
+
begin
|
591
|
+
Dir.rmdir path
|
592
|
+
rescue Errno::ENOTEMPTY
|
593
|
+
# directory may not be empty
|
594
|
+
end
|
430
595
|
end
|
431
596
|
|
432
597
|
def move_file(src, dest)
|
433
|
-
|
598
|
+
force_remove_file dest
|
434
599
|
begin
|
435
600
|
File.rename src, dest
|
436
601
|
rescue
|
437
|
-
File.open(dest, 'wb') {|f|
|
602
|
+
File.open(dest, 'wb') {|f|
|
603
|
+
f.write File.binread(src)
|
604
|
+
}
|
438
605
|
File.chmod File.stat(src).mode, dest
|
439
606
|
File.unlink src
|
440
607
|
end
|
441
608
|
end
|
442
609
|
|
610
|
+
def force_remove_file(path)
|
611
|
+
begin
|
612
|
+
remove_file path
|
613
|
+
rescue
|
614
|
+
end
|
615
|
+
end
|
616
|
+
|
617
|
+
def remove_file(path)
|
618
|
+
File.chmod 0777, path
|
619
|
+
File.unlink path
|
620
|
+
end
|
621
|
+
|
443
622
|
def install(from, dest, mode, prefix = nil)
|
444
623
|
$stderr.puts "install #{from} #{dest}" if verbose?
|
445
624
|
return if no_harm?
|
446
625
|
|
447
|
-
realdest = prefix + dest
|
626
|
+
realdest = prefix ? prefix + File.expand_path(dest) : dest
|
448
627
|
realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest)
|
449
628
|
str = File.binread(from)
|
450
629
|
if diff?(str, realdest)
|
@@ -471,68 +650,42 @@ module FileOperations
|
|
471
650
|
new_content != File.binread(path)
|
472
651
|
end
|
473
652
|
|
474
|
-
def command(
|
475
|
-
$stderr.puts
|
476
|
-
system
|
653
|
+
def command(*args)
|
654
|
+
$stderr.puts args.join(' ') if verbose?
|
655
|
+
system(*args) or raise RuntimeError,
|
656
|
+
"system(#{args.map{|a| a.inspect }.join(' ')}) failed"
|
477
657
|
end
|
478
658
|
|
479
|
-
def ruby(
|
480
|
-
command config('
|
659
|
+
def ruby(*args)
|
660
|
+
command config('rubyprog'), *args
|
481
661
|
end
|
482
662
|
|
483
|
-
def make(task =
|
484
|
-
command
|
663
|
+
def make(task = nil)
|
664
|
+
command(*[config('makeprog'), task].compact)
|
485
665
|
end
|
486
666
|
|
487
667
|
def extdir?(dir)
|
488
|
-
File.exist?(dir
|
668
|
+
File.exist?("#{dir}/MANIFEST") or File.exist?("#{dir}/extconf.rb")
|
489
669
|
end
|
490
670
|
|
491
|
-
def
|
492
|
-
Dir.open(
|
493
|
-
return d.select {|ent| File.file?("#{
|
671
|
+
def files_of(dir)
|
672
|
+
Dir.open(dir) {|d|
|
673
|
+
return d.select {|ent| File.file?("#{dir}/#{ent}") }
|
494
674
|
}
|
495
675
|
end
|
496
676
|
|
497
|
-
|
498
|
-
CVS SCCS RCS CVS.adm
|
499
|
-
)
|
677
|
+
DIR_REJECT = %w( . .. CVS SCCS RCS CVS.adm .svn )
|
500
678
|
|
501
|
-
def
|
502
|
-
Dir.open(
|
503
|
-
return d.select {|
|
679
|
+
def directories_of(dir)
|
680
|
+
Dir.open(dir) {|d|
|
681
|
+
return d.select {|ent| File.dir?("#{dir}/#{ent}") } - DIR_REJECT
|
504
682
|
}
|
505
683
|
end
|
506
684
|
|
507
685
|
end
|
508
686
|
|
509
|
-
#
|
510
|
-
# Main Installer
|
511
|
-
#
|
512
|
-
|
513
|
-
class InstallError < StandardError; end
|
514
|
-
|
515
|
-
|
516
|
-
module HookUtils
|
517
|
-
|
518
|
-
def run_hook(name)
|
519
|
-
try_run_hook "#{curr_srcdir()}/#{name}" or
|
520
|
-
try_run_hook "#{curr_srcdir()}/#{name}.rb"
|
521
|
-
end
|
522
|
-
|
523
|
-
def try_run_hook(fname)
|
524
|
-
return false unless File.file?(fname)
|
525
|
-
begin
|
526
|
-
instance_eval File.read(fname), fname, 1
|
527
|
-
rescue
|
528
|
-
raise InstallError, "hook #{fname} failed:\n" + $!.message
|
529
|
-
end
|
530
|
-
true
|
531
|
-
end
|
532
|
-
|
533
|
-
end
|
534
|
-
|
535
687
|
|
688
|
+
# This module requires: #srcdir_root, #objdir_root, #relpath
|
536
689
|
module HookScriptAPI
|
537
690
|
|
538
691
|
def get_config(key)
|
@@ -541,6 +694,7 @@ module HookScriptAPI
|
|
541
694
|
|
542
695
|
alias config get_config
|
543
696
|
|
697
|
+
# obsolete: use metaconfig to change configuration
|
544
698
|
def set_config(key, val)
|
545
699
|
@config[key] = val
|
546
700
|
end
|
@@ -549,10 +703,6 @@ module HookScriptAPI
|
|
549
703
|
# srcdir/objdir (works only in the package directory)
|
550
704
|
#
|
551
705
|
|
552
|
-
#abstract srcdir_root
|
553
|
-
#abstract objdir_root
|
554
|
-
#abstract relpath
|
555
|
-
|
556
706
|
def curr_srcdir
|
557
707
|
"#{srcdir_root()}/#{relpath()}"
|
558
708
|
end
|
@@ -574,7 +724,7 @@ module HookScriptAPI
|
|
574
724
|
end
|
575
725
|
|
576
726
|
def srcfile?(path)
|
577
|
-
File.file?
|
727
|
+
File.file?(srcfile(path))
|
578
728
|
end
|
579
729
|
|
580
730
|
def srcentries(path = '.')
|
@@ -600,35 +750,53 @@ end
|
|
600
750
|
|
601
751
|
class ToplevelInstaller
|
602
752
|
|
603
|
-
Version = '3.
|
604
|
-
Copyright = 'Copyright (c) 2000-
|
753
|
+
Version = '3.4.1'
|
754
|
+
Copyright = 'Copyright (c) 2000-2005 Minero Aoki'
|
605
755
|
|
606
756
|
TASKS = [
|
757
|
+
[ 'all', 'do config, setup, then install' ],
|
607
758
|
[ 'config', 'saves your configurations' ],
|
608
759
|
[ 'show', 'shows current configuration' ],
|
609
760
|
[ 'setup', 'compiles ruby extentions and others' ],
|
610
761
|
[ 'install', 'installs files' ],
|
762
|
+
[ 'test', 'run all tests in test/' ],
|
611
763
|
[ 'clean', "does `make clean' for each extention" ],
|
612
764
|
[ 'distclean',"does `make distclean' for each extention" ]
|
613
765
|
]
|
614
766
|
|
615
767
|
def ToplevelInstaller.invoke
|
616
|
-
|
768
|
+
config = ConfigTable.new(load_rbconfig())
|
769
|
+
config.load_standard_entries
|
770
|
+
config.load_multipackage_entries if multipackage?
|
771
|
+
config.fixup
|
772
|
+
klass = (multipackage?() ? ToplevelInstallerMulti : ToplevelInstaller)
|
773
|
+
klass.new(File.dirname($0), config).invoke
|
617
774
|
end
|
618
775
|
|
619
|
-
|
620
|
-
|
621
|
-
def ToplevelInstaller.instance
|
622
|
-
@singleton ||= new(File.dirname($0))
|
623
|
-
@singleton
|
776
|
+
def ToplevelInstaller.multipackage?
|
777
|
+
File.dir?(File.dirname($0) + '/packages')
|
624
778
|
end
|
625
779
|
|
626
|
-
|
780
|
+
def ToplevelInstaller.load_rbconfig
|
781
|
+
if arg = ARGV.detect {|arg| /\A--rbconfig=/ =~ arg }
|
782
|
+
ARGV.delete(arg)
|
783
|
+
load File.expand_path(arg.split(/=/, 2)[1])
|
784
|
+
$".push 'rbconfig.rb'
|
785
|
+
else
|
786
|
+
require 'rbconfig'
|
787
|
+
end
|
788
|
+
::Config::CONFIG
|
789
|
+
end
|
627
790
|
|
628
|
-
def initialize(ardir_root)
|
629
|
-
@config = nil
|
630
|
-
@options = { 'verbose' => true }
|
791
|
+
def initialize(ardir_root, config)
|
631
792
|
@ardir = File.expand_path(ardir_root)
|
793
|
+
@config = config
|
794
|
+
# cache
|
795
|
+
@valid_task_re = nil
|
796
|
+
end
|
797
|
+
|
798
|
+
def config(key)
|
799
|
+
@config[key]
|
632
800
|
end
|
633
801
|
|
634
802
|
def inspect
|
@@ -637,33 +805,34 @@ class ToplevelInstaller
|
|
637
805
|
|
638
806
|
def invoke
|
639
807
|
run_metaconfigs
|
640
|
-
task = parsearg_global()
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
def run_metaconfigs
|
648
|
-
eval_file_ifexist "#{@ardir}/metaconfig"
|
649
|
-
end
|
650
|
-
|
651
|
-
def load_config(task)
|
652
|
-
case task
|
653
|
-
when 'config'
|
654
|
-
ConfigTable.new
|
655
|
-
when 'clean', 'distclean'
|
656
|
-
if File.exist?('config.save')
|
657
|
-
then ConfigTable.load
|
658
|
-
else ConfigTable.new
|
659
|
-
end
|
808
|
+
case task = parsearg_global()
|
809
|
+
when nil, 'all'
|
810
|
+
parsearg_config
|
811
|
+
init_installers
|
812
|
+
exec_config
|
813
|
+
exec_setup
|
814
|
+
exec_install
|
660
815
|
else
|
661
|
-
|
816
|
+
case task
|
817
|
+
when 'config', 'test'
|
818
|
+
;
|
819
|
+
when 'clean', 'distclean'
|
820
|
+
@config.load_savefile if File.exist?(@config.savefile)
|
821
|
+
else
|
822
|
+
@config.load_savefile
|
823
|
+
end
|
824
|
+
__send__ "parsearg_#{task}"
|
825
|
+
init_installers
|
826
|
+
__send__ "exec_#{task}"
|
662
827
|
end
|
663
828
|
end
|
829
|
+
|
830
|
+
def run_metaconfigs
|
831
|
+
@config.load_script "#{@ardir}/metaconfig"
|
832
|
+
end
|
664
833
|
|
665
834
|
def init_installers
|
666
|
-
@installer = Installer.new(@config, @
|
835
|
+
@installer = Installer.new(@config, @ardir, File.expand_path('.'))
|
667
836
|
end
|
668
837
|
|
669
838
|
#
|
@@ -687,96 +856,91 @@ class ToplevelInstaller
|
|
687
856
|
#
|
688
857
|
|
689
858
|
def parsearg_global
|
690
|
-
valid_task = /\A(?:#{TASKS.map {|task,desc| task }.join '|'})\z/
|
691
|
-
|
692
859
|
while arg = ARGV.shift
|
693
860
|
case arg
|
694
861
|
when /\A\w+\z/
|
695
|
-
|
862
|
+
setup_rb_error "invalid task: #{arg}" unless valid_task?(arg)
|
696
863
|
return arg
|
697
|
-
|
698
864
|
when '-q', '--quiet'
|
699
|
-
@
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
when '-h', '--help'
|
865
|
+
@config.verbose = false
|
866
|
+
when '--verbose'
|
867
|
+
@config.verbose = true
|
868
|
+
when '--help'
|
705
869
|
print_usage $stdout
|
706
870
|
exit 0
|
707
|
-
|
708
|
-
when '-v', '--version'
|
871
|
+
when '--version'
|
709
872
|
puts "#{File.basename($0)} version #{Version}"
|
710
873
|
exit 0
|
711
|
-
|
712
874
|
when '--copyright'
|
713
875
|
puts Copyright
|
714
876
|
exit 0
|
715
|
-
|
716
877
|
else
|
717
|
-
|
878
|
+
setup_rb_error "unknown global option '#{arg}'"
|
718
879
|
end
|
719
880
|
end
|
881
|
+
nil
|
882
|
+
end
|
720
883
|
|
721
|
-
|
722
|
-
|
723
|
-
Typical installation procedure is:
|
724
|
-
$ ruby #{File.basename($0)} config
|
725
|
-
$ ruby #{File.basename($0)} setup
|
726
|
-
# ruby #{File.basename($0)} install (may require root privilege)
|
727
|
-
EOS
|
884
|
+
def valid_task?(t)
|
885
|
+
valid_task_re() =~ t
|
728
886
|
end
|
729
887
|
|
888
|
+
def valid_task_re
|
889
|
+
@valid_task_re ||= /\A(?:#{TASKS.map {|task,desc| task }.join('|')})\z/
|
890
|
+
end
|
730
891
|
|
731
892
|
def parsearg_no_options
|
732
|
-
|
733
|
-
|
893
|
+
unless ARGV.empty?
|
894
|
+
task = caller(0).first.slice(%r<`parsearg_(\w+)'>, 1)
|
895
|
+
setup_rb_error "#{task}: unknown options: #{ARGV.join(' ')}"
|
896
|
+
end
|
734
897
|
end
|
735
898
|
|
736
899
|
alias parsearg_show parsearg_no_options
|
737
900
|
alias parsearg_setup parsearg_no_options
|
901
|
+
alias parsearg_test parsearg_no_options
|
738
902
|
alias parsearg_clean parsearg_no_options
|
739
903
|
alias parsearg_distclean parsearg_no_options
|
740
904
|
|
741
905
|
def parsearg_config
|
742
|
-
|
743
|
-
|
744
|
-
|
906
|
+
evalopt = []
|
907
|
+
set = []
|
908
|
+
@config.config_opt = []
|
745
909
|
while i = ARGV.shift
|
746
910
|
if /\A--?\z/ =~ i
|
747
|
-
@
|
911
|
+
@config.config_opt = ARGV.dup
|
748
912
|
break
|
749
913
|
end
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
if ConfigTable.bool_config?(name)
|
754
|
-
raise InstallError, "config: --#{name} allows only yes/no for argument"\
|
755
|
-
unless /\A(y(es)?|n(o)?|t(rue)?|f(alse))\z/i =~ value
|
756
|
-
value = (/\Ay(es)?|\At(rue)/i =~ value) ? 'yes' : 'no'
|
757
|
-
end
|
914
|
+
name, value = *@config.parse_opt(i)
|
915
|
+
if @config.value_config?(name)
|
916
|
+
@config[name] = value
|
758
917
|
else
|
759
|
-
|
760
|
-
unless ConfigTable.bool_config?(name)
|
761
|
-
value = 'yes'
|
918
|
+
evalopt.push [name, value]
|
762
919
|
end
|
763
|
-
|
920
|
+
set.push name
|
921
|
+
end
|
922
|
+
evalopt.each do |name, value|
|
923
|
+
@config.lookup(name).evaluate value, @config
|
924
|
+
end
|
925
|
+
# Check if configuration is valid
|
926
|
+
set.each do |n|
|
927
|
+
@config[n] if @config.value_config?(n)
|
764
928
|
end
|
765
929
|
end
|
766
930
|
|
767
931
|
def parsearg_install
|
768
|
-
@
|
769
|
-
@
|
932
|
+
@config.no_harm = false
|
933
|
+
@config.install_prefix = ''
|
770
934
|
while a = ARGV.shift
|
771
935
|
case a
|
772
|
-
when
|
773
|
-
@
|
774
|
-
when /\A--prefix
|
775
|
-
path =
|
936
|
+
when '--no-harm'
|
937
|
+
@config.no_harm = true
|
938
|
+
when /\A--prefix=/
|
939
|
+
path = a.split(/=/, 2)[1]
|
776
940
|
path = File.expand_path(path) unless path[0,1] == '/'
|
777
|
-
@
|
941
|
+
@config.install_prefix = path
|
778
942
|
else
|
779
|
-
|
943
|
+
setup_rb_error "install: unknown option #{a}"
|
780
944
|
end
|
781
945
|
end
|
782
946
|
end
|
@@ -791,39 +955,31 @@ EOS
|
|
791
955
|
out.puts " ruby #{File.basename $0} <global option>"
|
792
956
|
out.puts " ruby #{File.basename $0} [<global options>] <task> [<task options>]"
|
793
957
|
|
794
|
-
fmt = " %-
|
958
|
+
fmt = " %-24s %s\n"
|
795
959
|
out.puts
|
796
960
|
out.puts 'Global options:'
|
797
961
|
out.printf fmt, '-q,--quiet', 'suppress message outputs'
|
798
962
|
out.printf fmt, ' --verbose', 'output messages verbosely'
|
799
|
-
out.printf fmt, '
|
800
|
-
out.printf fmt, '
|
963
|
+
out.printf fmt, ' --help', 'print this message'
|
964
|
+
out.printf fmt, ' --version', 'print version and quit'
|
801
965
|
out.printf fmt, ' --copyright', 'print copyright and quit'
|
802
|
-
|
803
966
|
out.puts
|
804
967
|
out.puts 'Tasks:'
|
805
968
|
TASKS.each do |name, desc|
|
806
|
-
out.printf
|
969
|
+
out.printf fmt, name, desc
|
807
970
|
end
|
808
971
|
|
972
|
+
fmt = " %-24s %s [%s]\n"
|
809
973
|
out.puts
|
810
|
-
out.puts 'Options for
|
811
|
-
|
812
|
-
out.printf
|
813
|
-
'--'+ name + (ConfigTable.bool_config?(name) ? '' : '='+arg),
|
814
|
-
desc,
|
815
|
-
default2 || default
|
974
|
+
out.puts 'Options for CONFIG or ALL:'
|
975
|
+
@config.each do |item|
|
976
|
+
out.printf fmt, item.help_opt, item.description, item.help_default
|
816
977
|
end
|
817
|
-
out.printf "
|
818
|
-
'--rbconfig=path', 'your rbconfig.rb to load', "running ruby's"
|
819
|
-
|
978
|
+
out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',"running ruby's"
|
820
979
|
out.puts
|
821
|
-
out.puts 'Options for
|
822
|
-
out.printf
|
823
|
-
|
824
|
-
out.printf " %-20s %s [%s]\n",
|
825
|
-
'--prefix', 'install path prefix', '$prefix'
|
826
|
-
|
980
|
+
out.puts 'Options for INSTALL:'
|
981
|
+
out.printf fmt, '--no-harm', 'only display what to do if given', 'off'
|
982
|
+
out.printf fmt, '--prefix=path', 'install path prefix', ''
|
827
983
|
out.puts
|
828
984
|
end
|
829
985
|
|
@@ -844,13 +1000,13 @@ EOS
|
|
844
1000
|
@installer.exec_install
|
845
1001
|
end
|
846
1002
|
|
1003
|
+
def exec_test
|
1004
|
+
@installer.exec_test
|
1005
|
+
end
|
1006
|
+
|
847
1007
|
def exec_show
|
848
|
-
|
849
|
-
|
850
|
-
if not v or v.empty?
|
851
|
-
v = '(not specified)'
|
852
|
-
end
|
853
|
-
printf "%-10s %s\n", k, v
|
1008
|
+
@config.each do |i|
|
1009
|
+
printf "%-20s %s\n", i.name, i.value if i.value?
|
854
1010
|
end
|
855
1011
|
end
|
856
1012
|
|
@@ -862,36 +1018,45 @@ EOS
|
|
862
1018
|
@installer.exec_distclean
|
863
1019
|
end
|
864
1020
|
|
865
|
-
end
|
1021
|
+
end # class ToplevelInstaller
|
866
1022
|
|
867
1023
|
|
868
1024
|
class ToplevelInstallerMulti < ToplevelInstaller
|
869
1025
|
|
870
|
-
include HookUtils
|
871
|
-
include HookScriptAPI
|
872
1026
|
include FileOperations
|
873
1027
|
|
874
|
-
def initialize(
|
1028
|
+
def initialize(ardir_root, config)
|
875
1029
|
super
|
876
|
-
@packages =
|
1030
|
+
@packages = directories_of("#{@ardir}/packages")
|
877
1031
|
raise 'no package exists' if @packages.empty?
|
1032
|
+
@root_installer = Installer.new(@config, @ardir, File.expand_path('.'))
|
878
1033
|
end
|
879
1034
|
|
880
1035
|
def run_metaconfigs
|
881
|
-
|
1036
|
+
@config.load_script "#{@ardir}/metaconfig", self
|
882
1037
|
@packages.each do |name|
|
883
|
-
|
1038
|
+
@config.load_script "#{@ardir}/packages/#{name}/metaconfig"
|
884
1039
|
end
|
885
1040
|
end
|
886
1041
|
|
1042
|
+
attr_reader :packages
|
1043
|
+
|
1044
|
+
def packages=(list)
|
1045
|
+
raise 'package list is empty' if list.empty?
|
1046
|
+
list.each do |name|
|
1047
|
+
raise "directory packages/#{name} does not exist"\
|
1048
|
+
unless File.dir?("#{@ardir}/packages/#{name}")
|
1049
|
+
end
|
1050
|
+
@packages = list
|
1051
|
+
end
|
1052
|
+
|
887
1053
|
def init_installers
|
888
1054
|
@installers = {}
|
889
1055
|
@packages.each do |pack|
|
890
|
-
@installers[pack] = Installer.new(@config,
|
1056
|
+
@installers[pack] = Installer.new(@config,
|
891
1057
|
"#{@ardir}/packages/#{pack}",
|
892
1058
|
"packages/#{pack}")
|
893
1059
|
end
|
894
|
-
|
895
1060
|
with = extract_selection(config('with'))
|
896
1061
|
without = extract_selection(config('without'))
|
897
1062
|
@selected = @installers.keys.select {|name|
|
@@ -903,8 +1068,7 @@ class ToplevelInstallerMulti < ToplevelInstaller
|
|
903
1068
|
def extract_selection(list)
|
904
1069
|
a = list.split(/,/)
|
905
1070
|
a.each do |name|
|
906
|
-
|
907
|
-
unless @installers.key?(name)
|
1071
|
+
setup_rb_error "no such package: #{name}" unless @installers.key?(name)
|
908
1072
|
end
|
909
1073
|
a
|
910
1074
|
end
|
@@ -916,21 +1080,6 @@ class ToplevelInstallerMulti < ToplevelInstaller
|
|
916
1080
|
f.puts
|
917
1081
|
end
|
918
1082
|
|
919
|
-
#
|
920
|
-
# multi-package metaconfig API
|
921
|
-
#
|
922
|
-
|
923
|
-
attr_reader :packages
|
924
|
-
|
925
|
-
def declare_packages(list)
|
926
|
-
raise 'package list is empty' if list.empty?
|
927
|
-
list.each do |name|
|
928
|
-
raise "directory packages/#{name} does not exist"\
|
929
|
-
unless File.dir?("#{@ardir}/packages/#{name}")
|
930
|
-
end
|
931
|
-
@packages = list
|
932
|
-
end
|
933
|
-
|
934
1083
|
#
|
935
1084
|
# Task Handlers
|
936
1085
|
#
|
@@ -954,15 +1103,21 @@ class ToplevelInstallerMulti < ToplevelInstaller
|
|
954
1103
|
run_hook 'post-install'
|
955
1104
|
end
|
956
1105
|
|
1106
|
+
def exec_test
|
1107
|
+
run_hook 'pre-test'
|
1108
|
+
each_selected_installers {|inst| inst.exec_test }
|
1109
|
+
run_hook 'post-test'
|
1110
|
+
end
|
1111
|
+
|
957
1112
|
def exec_clean
|
958
|
-
rm_f
|
1113
|
+
rm_f @config.savefile
|
959
1114
|
run_hook 'pre-clean'
|
960
1115
|
each_selected_installers {|inst| inst.exec_clean }
|
961
1116
|
run_hook 'post-clean'
|
962
1117
|
end
|
963
1118
|
|
964
1119
|
def exec_distclean
|
965
|
-
rm_f
|
1120
|
+
rm_f @config.savefile
|
966
1121
|
run_hook 'pre-distclean'
|
967
1122
|
each_selected_installers {|inst| inst.exec_distclean }
|
968
1123
|
run_hook 'post-distclean'
|
@@ -975,7 +1130,7 @@ class ToplevelInstallerMulti < ToplevelInstaller
|
|
975
1130
|
def each_selected_installers
|
976
1131
|
Dir.mkdir 'packages' unless File.dir?('packages')
|
977
1132
|
@selected.each do |pack|
|
978
|
-
$stderr.puts "Processing the package `#{pack}' ..." if
|
1133
|
+
$stderr.puts "Processing the package `#{pack}' ..." if verbose?
|
979
1134
|
Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}")
|
980
1135
|
Dir.chdir "packages/#{pack}"
|
981
1136
|
yield @installers[pack]
|
@@ -983,28 +1138,32 @@ class ToplevelInstallerMulti < ToplevelInstaller
|
|
983
1138
|
end
|
984
1139
|
end
|
985
1140
|
|
1141
|
+
def run_hook(id)
|
1142
|
+
@root_installer.run_hook id
|
1143
|
+
end
|
1144
|
+
|
1145
|
+
# module FileOperations requires this
|
986
1146
|
def verbose?
|
987
|
-
@
|
1147
|
+
@config.verbose?
|
988
1148
|
end
|
989
1149
|
|
1150
|
+
# module FileOperations requires this
|
990
1151
|
def no_harm?
|
991
|
-
@
|
1152
|
+
@config.no_harm?
|
992
1153
|
end
|
993
1154
|
|
994
|
-
end
|
1155
|
+
end # class ToplevelInstallerMulti
|
995
1156
|
|
996
1157
|
|
997
1158
|
class Installer
|
998
1159
|
|
999
|
-
FILETYPES = %w( bin lib ext data )
|
1160
|
+
FILETYPES = %w( bin lib ext data conf man )
|
1000
1161
|
|
1001
|
-
include HookScriptAPI
|
1002
|
-
include HookUtils
|
1003
1162
|
include FileOperations
|
1163
|
+
include HookScriptAPI
|
1004
1164
|
|
1005
|
-
def initialize(config,
|
1165
|
+
def initialize(config, srcroot, objroot)
|
1006
1166
|
@config = config
|
1007
|
-
@options = opt
|
1008
1167
|
@srcdir = File.expand_path(srcroot)
|
1009
1168
|
@objdir = File.expand_path(objroot)
|
1010
1169
|
@currdir = '.'
|
@@ -1014,8 +1173,11 @@ class Installer
|
|
1014
1173
|
"#<#{self.class} #{File.basename(@srcdir)}>"
|
1015
1174
|
end
|
1016
1175
|
|
1176
|
+
def noop(rel)
|
1177
|
+
end
|
1178
|
+
|
1017
1179
|
#
|
1018
|
-
# Hook Script API
|
1180
|
+
# Hook Script API base methods
|
1019
1181
|
#
|
1020
1182
|
|
1021
1183
|
def srcdir_root
|
@@ -1031,23 +1193,25 @@ class Installer
|
|
1031
1193
|
end
|
1032
1194
|
|
1033
1195
|
#
|
1034
|
-
#
|
1196
|
+
# Config Access
|
1035
1197
|
#
|
1036
1198
|
|
1037
|
-
|
1038
|
-
|
1199
|
+
# module FileOperations requires this
|
1200
|
+
def verbose?
|
1201
|
+
@config.verbose?
|
1039
1202
|
end
|
1040
1203
|
|
1041
|
-
|
1042
|
-
|
1204
|
+
# module FileOperations requires this
|
1205
|
+
def no_harm?
|
1206
|
+
@config.no_harm?
|
1043
1207
|
end
|
1044
1208
|
|
1045
1209
|
def verbose_off
|
1046
1210
|
begin
|
1047
|
-
save, @
|
1211
|
+
save, @config.verbose = @config.verbose?, false
|
1048
1212
|
yield
|
1049
1213
|
ensure
|
1050
|
-
@
|
1214
|
+
@config.verbose = save
|
1051
1215
|
end
|
1052
1216
|
end
|
1053
1217
|
|
@@ -1059,22 +1223,19 @@ class Installer
|
|
1059
1223
|
exec_task_traverse 'config'
|
1060
1224
|
end
|
1061
1225
|
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
def config_dir_lib(rel)
|
1066
|
-
end
|
1226
|
+
alias config_dir_bin noop
|
1227
|
+
alias config_dir_lib noop
|
1067
1228
|
|
1068
1229
|
def config_dir_ext(rel)
|
1069
1230
|
extconf if extdir?(curr_srcdir())
|
1070
1231
|
end
|
1071
1232
|
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
end
|
1233
|
+
alias config_dir_data noop
|
1234
|
+
alias config_dir_conf noop
|
1235
|
+
alias config_dir_man noop
|
1076
1236
|
|
1077
|
-
def
|
1237
|
+
def extconf
|
1238
|
+
ruby "#{curr_srcdir()}/extconf.rb", *@config.config_opt
|
1078
1239
|
end
|
1079
1240
|
|
1080
1241
|
#
|
@@ -1086,46 +1247,90 @@ class Installer
|
|
1086
1247
|
end
|
1087
1248
|
|
1088
1249
|
def setup_dir_bin(rel)
|
1089
|
-
|
1090
|
-
|
1250
|
+
files_of(curr_srcdir()).each do |fname|
|
1251
|
+
update_shebang_line "#{curr_srcdir()}/#{fname}"
|
1091
1252
|
end
|
1092
1253
|
end
|
1093
1254
|
|
1094
|
-
|
1095
|
-
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1255
|
+
alias setup_dir_lib noop
|
1256
|
+
|
1257
|
+
def setup_dir_ext(rel)
|
1258
|
+
make if extdir?(curr_srcdir())
|
1259
|
+
end
|
1260
|
+
|
1261
|
+
alias setup_dir_data noop
|
1262
|
+
alias setup_dir_conf noop
|
1263
|
+
alias setup_dir_man noop
|
1099
1264
|
|
1100
|
-
def
|
1265
|
+
def update_shebang_line(path)
|
1101
1266
|
return if no_harm?
|
1267
|
+
return if config('shebang') == 'never'
|
1268
|
+
old = Shebang.load(path)
|
1269
|
+
if old
|
1270
|
+
$stderr.puts "warning: #{path}: Shebang line includes too many args. It is not portable and your program may not work." if old.args.size > 1
|
1271
|
+
new = new_shebang(old)
|
1272
|
+
return if new.to_s == old.to_s
|
1273
|
+
else
|
1274
|
+
return unless config('shebang') == 'all'
|
1275
|
+
new = Shebang.new(config('rubypath'))
|
1276
|
+
end
|
1277
|
+
$stderr.puts "updating shebang: #{File.basename(path)}" if verbose?
|
1278
|
+
open_atomic_writer(path) {|output|
|
1279
|
+
File.open(path, 'rb') {|f|
|
1280
|
+
f.gets if old # discard
|
1281
|
+
output.puts new.to_s
|
1282
|
+
output.print f.read
|
1283
|
+
}
|
1284
|
+
}
|
1285
|
+
end
|
1286
|
+
|
1287
|
+
def new_shebang(old)
|
1288
|
+
if /\Aruby/ =~ File.basename(old.cmd)
|
1289
|
+
Shebang.new(config('rubypath'), old.args)
|
1290
|
+
elsif File.basename(old.cmd) == 'env' and old.args.first == 'ruby'
|
1291
|
+
Shebang.new(config('rubypath'), old.args[1..-1])
|
1292
|
+
else
|
1293
|
+
return old unless config('shebang') == 'all'
|
1294
|
+
Shebang.new(config('rubypath'))
|
1295
|
+
end
|
1296
|
+
end
|
1102
1297
|
|
1298
|
+
def open_atomic_writer(path, &block)
|
1103
1299
|
tmpfile = File.basename(path) + '.tmp'
|
1104
1300
|
begin
|
1105
|
-
File.open(
|
1106
|
-
|
1107
|
-
first = r.gets
|
1108
|
-
return unless SHEBANG_RE =~ first
|
1109
|
-
|
1110
|
-
$stderr.puts "adjusting shebang: #{File.basename path}" if verbose?
|
1111
|
-
w.print first.sub(SHEBANG_RE, '#!' + config('ruby-path'))
|
1112
|
-
w.write r.read
|
1113
|
-
}
|
1114
|
-
}
|
1115
|
-
move_file tmpfile, File.basename(path)
|
1301
|
+
File.open(tmpfile, 'wb', &block)
|
1302
|
+
File.rename tmpfile, File.basename(path)
|
1116
1303
|
ensure
|
1117
1304
|
File.unlink tmpfile if File.exist?(tmpfile)
|
1118
1305
|
end
|
1119
1306
|
end
|
1120
1307
|
|
1121
|
-
|
1122
|
-
|
1308
|
+
class Shebang
|
1309
|
+
def Shebang.load(path)
|
1310
|
+
line = nil
|
1311
|
+
File.open(path) {|f|
|
1312
|
+
line = f.gets
|
1313
|
+
}
|
1314
|
+
return nil unless /\A#!/ =~ line
|
1315
|
+
parse(line)
|
1316
|
+
end
|
1123
1317
|
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1318
|
+
def Shebang.parse(line)
|
1319
|
+
cmd, *args = *line.strip.sub(/\A\#!/, '').split(' ')
|
1320
|
+
new(cmd, args)
|
1321
|
+
end
|
1322
|
+
|
1323
|
+
def initialize(cmd, args = [])
|
1324
|
+
@cmd = cmd
|
1325
|
+
@args = args
|
1326
|
+
end
|
1327
|
+
|
1328
|
+
attr_reader :cmd
|
1329
|
+
attr_reader :args
|
1127
1330
|
|
1128
|
-
|
1331
|
+
def to_s
|
1332
|
+
"#! #{@cmd}" + (@args.empty? ? '' : " #{@args.join(' ')}")
|
1333
|
+
end
|
1129
1334
|
end
|
1130
1335
|
|
1131
1336
|
#
|
@@ -1133,67 +1338,82 @@ class Installer
|
|
1133
1338
|
#
|
1134
1339
|
|
1135
1340
|
def exec_install
|
1341
|
+
rm_f 'InstalledFiles'
|
1136
1342
|
exec_task_traverse 'install'
|
1137
1343
|
end
|
1138
1344
|
|
1139
1345
|
def install_dir_bin(rel)
|
1140
|
-
install_files
|
1346
|
+
install_files targetfiles(), "#{config('bindir')}/#{rel}", 0755
|
1141
1347
|
end
|
1142
1348
|
|
1143
1349
|
def install_dir_lib(rel)
|
1144
|
-
install_files
|
1350
|
+
install_files libfiles(), "#{config('rbdir')}/#{rel}", 0644
|
1145
1351
|
end
|
1146
1352
|
|
1147
1353
|
def install_dir_ext(rel)
|
1148
1354
|
return unless extdir?(curr_srcdir())
|
1149
|
-
install_files
|
1150
|
-
"#{config('
|
1355
|
+
install_files rubyextentions('.'),
|
1356
|
+
"#{config('sodir')}/#{File.dirname(rel)}",
|
1151
1357
|
0555
|
1152
1358
|
end
|
1153
1359
|
|
1154
1360
|
def install_dir_data(rel)
|
1155
|
-
install_files
|
1361
|
+
install_files targetfiles(), "#{config('datadir')}/#{rel}", 0644
|
1362
|
+
end
|
1363
|
+
|
1364
|
+
def install_dir_conf(rel)
|
1365
|
+
# FIXME: should not remove current config files
|
1366
|
+
# (rename previous file to .old/.org)
|
1367
|
+
install_files targetfiles(), "#{config('sysconfdir')}/#{rel}", 0644
|
1368
|
+
end
|
1369
|
+
|
1370
|
+
def install_dir_man(rel)
|
1371
|
+
install_files targetfiles(), "#{config('mandir')}/#{rel}", 0644
|
1156
1372
|
end
|
1157
1373
|
|
1158
1374
|
def install_files(list, dest, mode)
|
1159
|
-
mkdir_p dest, @
|
1375
|
+
mkdir_p dest, @config.install_prefix
|
1160
1376
|
list.each do |fname|
|
1161
|
-
install fname, dest, mode, @
|
1377
|
+
install fname, dest, mode, @config.install_prefix
|
1162
1378
|
end
|
1163
1379
|
end
|
1164
1380
|
|
1165
|
-
def
|
1166
|
-
|
1381
|
+
def libfiles
|
1382
|
+
glob_reject(%w(*.y *.output), targetfiles())
|
1167
1383
|
end
|
1168
|
-
|
1384
|
+
|
1385
|
+
def rubyextentions(dir)
|
1386
|
+
ents = glob_select("*.#{@config.dllext}", targetfiles())
|
1387
|
+
if ents.empty?
|
1388
|
+
setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first"
|
1389
|
+
end
|
1390
|
+
ents
|
1391
|
+
end
|
1392
|
+
|
1393
|
+
def targetfiles
|
1394
|
+
mapdir(existfiles() - hookfiles())
|
1395
|
+
end
|
1396
|
+
|
1397
|
+
def mapdir(ents)
|
1398
|
+
ents.map {|ent|
|
1399
|
+
if File.exist?(ent)
|
1400
|
+
then ent # objdir
|
1401
|
+
else "#{curr_srcdir()}/#{ent}" # srcdir
|
1402
|
+
end
|
1403
|
+
}
|
1404
|
+
end
|
1405
|
+
|
1169
1406
|
# picked up many entries from cvs-1.11.1/src/ignore.c
|
1170
|
-
|
1407
|
+
JUNK_FILES = %w(
|
1171
1408
|
core RCSLOG tags TAGS .make.state
|
1172
1409
|
.nse_depinfo #* .#* cvslog.* ,* .del-* *.olb
|
1173
1410
|
*~ *.old *.bak *.BAK *.orig *.rej _$* *$
|
1174
1411
|
|
1175
1412
|
*.org *.in .*
|
1176
1413
|
)
|
1177
|
-
mapping = {
|
1178
|
-
'.' => '\.',
|
1179
|
-
'$' => '\$',
|
1180
|
-
'#' => '\#',
|
1181
|
-
'*' => '.*'
|
1182
|
-
}
|
1183
|
-
REJECT_PATTERNS = Regexp.new('\A(?:' +
|
1184
|
-
reject_patterns.map {|pat|
|
1185
|
-
pat.gsub(/[\.\$\#\*]/) {|ch| mapping[ch] }
|
1186
|
-
}.join('|') +
|
1187
|
-
')\z')
|
1188
|
-
|
1189
|
-
def collect_filenames_auto
|
1190
|
-
mapdir((existfiles() - hookfiles()).reject {|fname|
|
1191
|
-
REJECT_PATTERNS =~ fname
|
1192
|
-
})
|
1193
|
-
end
|
1194
1414
|
|
1195
1415
|
def existfiles
|
1196
|
-
|
1416
|
+
glob_reject(JUNK_FILES, (files_of(curr_srcdir()) | files_of('.')))
|
1197
1417
|
end
|
1198
1418
|
|
1199
1419
|
def hookfiles
|
@@ -1202,27 +1422,49 @@ class Installer
|
|
1202
1422
|
}.flatten
|
1203
1423
|
end
|
1204
1424
|
|
1205
|
-
def
|
1206
|
-
|
1207
|
-
|
1208
|
-
fname
|
1209
|
-
else # srcdir
|
1210
|
-
File.join(curr_srcdir(), fname)
|
1211
|
-
end
|
1212
|
-
}
|
1425
|
+
def glob_select(pat, ents)
|
1426
|
+
re = globs2re([pat])
|
1427
|
+
ents.select {|ent| re =~ ent }
|
1213
1428
|
end
|
1214
1429
|
|
1215
|
-
def
|
1216
|
-
|
1217
|
-
|
1430
|
+
def glob_reject(pats, ents)
|
1431
|
+
re = globs2re(pats)
|
1432
|
+
ents.reject {|ent| re =~ ent }
|
1218
1433
|
end
|
1219
1434
|
|
1220
|
-
|
1435
|
+
GLOB2REGEX = {
|
1436
|
+
'.' => '\.',
|
1437
|
+
'$' => '\$',
|
1438
|
+
'#' => '\#',
|
1439
|
+
'*' => '.*'
|
1440
|
+
}
|
1221
1441
|
|
1222
|
-
def
|
1223
|
-
|
1224
|
-
|
1225
|
-
}
|
1442
|
+
def globs2re(pats)
|
1443
|
+
/\A(?:#{
|
1444
|
+
pats.map {|pat| pat.gsub(/[\.\$\#\*]/) {|ch| GLOB2REGEX[ch] } }.join('|')
|
1445
|
+
})\z/
|
1446
|
+
end
|
1447
|
+
|
1448
|
+
#
|
1449
|
+
# TASK test
|
1450
|
+
#
|
1451
|
+
|
1452
|
+
TESTDIR = 'test'
|
1453
|
+
|
1454
|
+
def exec_test
|
1455
|
+
unless File.directory?('test')
|
1456
|
+
$stderr.puts 'no test in this package' if verbose?
|
1457
|
+
return
|
1458
|
+
end
|
1459
|
+
$stderr.puts 'Running tests...' if verbose?
|
1460
|
+
begin
|
1461
|
+
require 'test/unit'
|
1462
|
+
rescue LoadError
|
1463
|
+
setup_rb_error 'test/unit cannot loaded. You need Ruby 1.8 or later to invoke this task.'
|
1464
|
+
end
|
1465
|
+
runner = Test::Unit::AutoRunner.new(true)
|
1466
|
+
runner.to_run << TESTDIR
|
1467
|
+
runner.run
|
1226
1468
|
end
|
1227
1469
|
|
1228
1470
|
#
|
@@ -1231,53 +1473,51 @@ class Installer
|
|
1231
1473
|
|
1232
1474
|
def exec_clean
|
1233
1475
|
exec_task_traverse 'clean'
|
1234
|
-
rm_f
|
1476
|
+
rm_f @config.savefile
|
1235
1477
|
rm_f 'InstalledFiles'
|
1236
1478
|
end
|
1237
1479
|
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
1480
|
+
alias clean_dir_bin noop
|
1481
|
+
alias clean_dir_lib noop
|
1482
|
+
alias clean_dir_data noop
|
1483
|
+
alias clean_dir_conf noop
|
1484
|
+
alias clean_dir_man noop
|
1243
1485
|
|
1244
1486
|
def clean_dir_ext(rel)
|
1245
1487
|
return unless extdir?(curr_srcdir())
|
1246
1488
|
make 'clean' if File.file?('Makefile')
|
1247
1489
|
end
|
1248
1490
|
|
1249
|
-
def clean_dir_data(rel)
|
1250
|
-
end
|
1251
|
-
|
1252
1491
|
#
|
1253
1492
|
# TASK distclean
|
1254
1493
|
#
|
1255
1494
|
|
1256
1495
|
def exec_distclean
|
1257
1496
|
exec_task_traverse 'distclean'
|
1258
|
-
rm_f
|
1497
|
+
rm_f @config.savefile
|
1259
1498
|
rm_f 'InstalledFiles'
|
1260
1499
|
end
|
1261
1500
|
|
1262
|
-
|
1263
|
-
|
1264
|
-
|
1265
|
-
def distclean_dir_lib(rel)
|
1266
|
-
end
|
1501
|
+
alias distclean_dir_bin noop
|
1502
|
+
alias distclean_dir_lib noop
|
1267
1503
|
|
1268
1504
|
def distclean_dir_ext(rel)
|
1269
1505
|
return unless extdir?(curr_srcdir())
|
1270
1506
|
make 'distclean' if File.file?('Makefile')
|
1271
1507
|
end
|
1272
1508
|
|
1509
|
+
alias distclean_dir_data noop
|
1510
|
+
alias distclean_dir_conf noop
|
1511
|
+
alias distclean_dir_man noop
|
1512
|
+
|
1273
1513
|
#
|
1274
|
-
#
|
1514
|
+
# Traversing
|
1275
1515
|
#
|
1276
1516
|
|
1277
1517
|
def exec_task_traverse(task)
|
1278
1518
|
run_hook "pre-#{task}"
|
1279
1519
|
FILETYPES.each do |type|
|
1280
|
-
if config('without-ext') == 'yes'
|
1520
|
+
if type == 'ext' and config('without-ext') == 'yes'
|
1281
1521
|
$stderr.puts 'skipping ext/* by user option' if verbose?
|
1282
1522
|
next
|
1283
1523
|
end
|
@@ -1290,7 +1530,7 @@ class Installer
|
|
1290
1530
|
dive_into(rel) {
|
1291
1531
|
run_hook "pre-#{task}"
|
1292
1532
|
__send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '')
|
1293
|
-
|
1533
|
+
directories_of(curr_srcdir()).each do |d|
|
1294
1534
|
traverse task, "#{rel}/#{d}", mid
|
1295
1535
|
end
|
1296
1536
|
run_hook "post-#{task}"
|
@@ -1312,17 +1552,31 @@ class Installer
|
|
1312
1552
|
@currdir = File.dirname(rel)
|
1313
1553
|
end
|
1314
1554
|
|
1315
|
-
|
1555
|
+
def run_hook(id)
|
1556
|
+
path = [ "#{curr_srcdir()}/#{id}",
|
1557
|
+
"#{curr_srcdir()}/#{id}.rb" ].detect {|cand| File.file?(cand) }
|
1558
|
+
return unless path
|
1559
|
+
begin
|
1560
|
+
instance_eval File.read(path), path, 1
|
1561
|
+
rescue
|
1562
|
+
raise if $DEBUG
|
1563
|
+
setup_rb_error "hook #{path} failed:\n" + $!.message
|
1564
|
+
end
|
1565
|
+
end
|
1566
|
+
|
1567
|
+
end # class Installer
|
1316
1568
|
|
1317
1569
|
|
1570
|
+
class SetupError < StandardError; end
|
1571
|
+
|
1572
|
+
def setup_rb_error(msg)
|
1573
|
+
raise SetupError, msg
|
1574
|
+
end
|
1575
|
+
|
1318
1576
|
if $0 == __FILE__
|
1319
1577
|
begin
|
1320
|
-
|
1321
|
-
|
1322
|
-
else
|
1323
|
-
ToplevelInstaller.invoke
|
1324
|
-
end
|
1325
|
-
rescue
|
1578
|
+
ToplevelInstaller.invoke
|
1579
|
+
rescue SetupError
|
1326
1580
|
raise if $DEBUG
|
1327
1581
|
$stderr.puts $!.message
|
1328
1582
|
$stderr.puts "Try 'ruby #{$0} --help' for detailed usage."
|