rubygems-update 0.9.2 → 0.9.3

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.

Potentially problematic release.


This version of rubygems-update might be problematic. Click here for more details.

Files changed (53) hide show
  1. data/ChangeLog +60 -0
  2. data/lib/rubygems.rb +18 -15
  3. data/lib/rubygems/builder.rb +29 -23
  4. data/lib/rubygems/{cmd_manager.rb → command_manager.rb} +35 -24
  5. data/lib/rubygems/commands/build_command.rb +57 -0
  6. data/lib/rubygems/commands/cert_command.rb +83 -0
  7. data/lib/rubygems/commands/check_command.rb +74 -0
  8. data/lib/rubygems/commands/cleanup_command.rb +75 -0
  9. data/lib/rubygems/commands/contents_command.rb +66 -0
  10. data/lib/rubygems/commands/dependency_command.rb +105 -0
  11. data/lib/rubygems/commands/environment_command.rb +59 -0
  12. data/lib/rubygems/commands/help_command.rb +82 -0
  13. data/lib/rubygems/commands/install_command.rb +139 -0
  14. data/lib/rubygems/commands/list_command.rb +33 -0
  15. data/lib/rubygems/commands/outdated_command.rb +21 -0
  16. data/lib/rubygems/commands/pristine_command.rb +103 -0
  17. data/lib/rubygems/commands/query_command.rb +86 -0
  18. data/lib/rubygems/commands/rdoc_command.rb +75 -0
  19. data/lib/rubygems/commands/search_command.rb +35 -0
  20. data/lib/rubygems/commands/sources_command.rb +73 -0
  21. data/lib/rubygems/commands/specification_command.rb +58 -0
  22. data/lib/rubygems/commands/uninstall_command.rb +51 -0
  23. data/lib/rubygems/commands/unpack_command.rb +76 -0
  24. data/lib/rubygems/commands/update_command.rb +102 -0
  25. data/lib/rubygems/digest/digest_adapter.rb +40 -0
  26. data/lib/rubygems/digest/md5.rb +20 -0
  27. data/lib/rubygems/digest/sha1.rb +17 -0
  28. data/lib/rubygems/digest/sha2.rb +17 -0
  29. data/lib/rubygems/format.rb +1 -1
  30. data/lib/rubygems/gem_commands.rb +6 -1407
  31. data/lib/rubygems/gem_runner.rb +2 -2
  32. data/lib/rubygems/installer.rb +13 -5
  33. data/lib/rubygems/open-uri.rb +2 -2
  34. data/lib/rubygems/package.rb +13 -14
  35. data/lib/rubygems/rubygems_version.rb +1 -1
  36. data/lib/rubygems/source_index.rb +4 -4
  37. data/lib/rubygems/specification.rb +5 -0
  38. data/lib/rubygems/validator.rb +8 -8
  39. data/setup.rb +806 -588
  40. data/test/gemutilities.rb +2 -2
  41. data/test/test_builder.rb +15 -0
  42. data/test/test_check_command.rb +1 -1
  43. data/test/test_command.rb +1 -1
  44. data/test/test_gem_digest.rb +44 -0
  45. data/test/test_gem_outdated_command.rb +2 -1
  46. data/test/test_gem_sources_command.rb +11 -6
  47. data/test/test_installer.rb +1 -1
  48. data/test/test_open_uri.rb +14 -0
  49. data/test/test_parse_commands.rb +25 -25
  50. data/test/test_process_commands.rb +5 -5
  51. data/test/test_specific_extras.rb +1 -1
  52. data/test/test_validator.rb +3 -3
  53. metadata +30 -4
@@ -15,7 +15,7 @@ module Gem
15
15
  class GemRunner
16
16
 
17
17
  def initialize(options={})
18
- @cmd_manager_class = options[:command_manager] || Gem::CommandManager
18
+ @command_manager_class = options[:command_manager] || Gem::CommandManager
19
19
  @config_file_class = options[:config_file] || Gem::ConfigFile
20
20
  @doc_manager_class = options[:doc_manager] || Gem::DocManager
21
21
  end
@@ -23,7 +23,7 @@ module Gem
23
23
  # Run the gem command with the following arguments.
24
24
  def run(args)
25
25
  do_configuration(args)
26
- cmd = @cmd_manager_class.instance
26
+ cmd = @command_manager_class.instance
27
27
  cmd.command_names.each do |c|
28
28
  Command.add_specific_extra_args c, Array(Gem.configuration[c])
29
29
  end
@@ -84,7 +84,7 @@ module Gem
84
84
  end
85
85
  end
86
86
 
87
- raise Gem::FilePermissionError.new(install_dir) unless File.writable?(install_dir)
87
+ raise Gem::FilePermissionError.new(Pathname.new(install_dir).expand_path) unless File.writable?(install_dir)
88
88
 
89
89
  # Build spec dir.
90
90
  @directory = File.join(install_dir, "gems", format.spec.full_name).untaint
@@ -347,10 +347,9 @@ Results logged to #{File.join(Dir.pwd, 'gem_make.out')}
347
347
  # file:: [IO] The IO that contains the file data
348
348
  #
349
349
  def extract_files(directory, format)
350
- unless File.expand_path(directory) == directory then
351
- raise ArgumentError, "install directory %p not absolute" % directory
352
- end
353
-
350
+ directory = expand_and_validate(directory)
351
+ raise ArgumentError, "format required to extract from" if format.nil?
352
+
354
353
  format.file_entries.each do |entry, file_data|
355
354
  path = entry['path'].untaint
356
355
  if path =~ /\A\// then # for extra sanity
@@ -369,6 +368,15 @@ Results logged to #{File.join(Dir.pwd, 'gem_make.out')}
369
368
  end
370
369
  end
371
370
  end
371
+
372
+ private
373
+ def expand_and_validate(directory)
374
+ directory = Pathname.new(directory).expand_path
375
+ unless directory.absolute?
376
+ raise ArgumentError, "install directory %p not absolute" % directory
377
+ end
378
+ directory.to_str
379
+ end
372
380
  end # class Installer
373
381
 
374
382
  ##
@@ -4,7 +4,7 @@ require 'time'
4
4
 
5
5
  module Kernel
6
6
  private
7
- alias open_uri_original_open open # :nodoc:
7
+ alias rubygems_open_uri_original_open open # :nodoc:
8
8
 
9
9
  # makes possible to open various resources including URIs.
10
10
  # If the first argument respond to `open' method,
@@ -29,7 +29,7 @@ module Kernel
29
29
  (uri = URI.parse(name)).respond_to?(:open)
30
30
  uri.open(*rest, &block)
31
31
  else
32
- open_uri_original_open(name, *rest, &block)
32
+ rubygems_open_uri_original_open(name, *rest, &block)
33
33
  end
34
34
  end
35
35
  module_function :open
@@ -607,21 +607,20 @@ module Gem::Package
607
607
 
608
608
  # Return an IO stream for the zipped entry.
609
609
  #
610
- # If zlib is earlier than 1.2.1, then read the entry into memory
611
- # and create a string IO object from it. This avoids a "buffer
612
- # error" problem on windows when using an earlier version of zlib.
613
- # This problem has not been observed in versions of zlib 1.2.1 or
614
- # later. (Update: Kornelius Kalnbach has reported seeing it in
615
- # zlib 1.2.1, so the condition now provides the workaround for
616
- # 1.2.1 as well)
610
+ # NOTE: Originally this method used two approaches, Return a GZipReader
611
+ # directly, or read the GZipReader into a string and return a StringIO on
612
+ # the string. The string IO approach was used for versions of ZLib before
613
+ # 1.2.1 to avoid buffer errors on windows machines. Then we found that
614
+ # errors happened with 1.2.1 as well, so we changed the condition. Then
615
+ # we discovered errors occurred with versions as late as 1.2.3. At this
616
+ # point (after some benchmarking to show we weren't seriously crippling
617
+ # the unpacking speed) we threw our hands in the air and declared that
618
+ # this method would use the String IO approach on all platforms at all
619
+ # times. And that's the way it is.
617
620
  def zipped_stream(entry)
618
- if Zlib::ZLIB_VERSION <= '1.2.1'
619
- zis = Zlib::GzipReader.new entry
620
- dis = zis.read
621
- is = StringIO.new(dis)
622
- else
623
- is = Zlib::GzipReader.new entry
624
- end
621
+ zis = Zlib::GzipReader.new entry
622
+ dis = zis.read
623
+ is = StringIO.new(dis)
625
624
  ensure
626
625
  zis.finish if zis
627
626
  end
@@ -2,5 +2,5 @@
2
2
  # This file is auto-generated by build scripts.
3
3
  # See: rake update_version
4
4
  module Gem
5
- RubyGemsVersion = '0.9.2'
5
+ RubyGemsVersion = '0.9.3'
6
6
  end
@@ -6,9 +6,9 @@
6
6
 
7
7
  require 'rubygems/user_interaction'
8
8
  require 'rubygems/remote_fetcher'
9
+ require 'rubygems/digest/sha2'
9
10
 
10
11
  require 'forwardable'
11
- require 'digest/sha2'
12
12
  require 'time'
13
13
 
14
14
  module Gem
@@ -63,7 +63,7 @@ module Gem
63
63
  # List of directory paths (all ending in "../specifications").
64
64
  #
65
65
  def installed_spec_directories
66
- Gem.path.collect { |dir| File.join(dir, "specifications") }
66
+ Gem.path.collect { |dir| File.join(dir, "specifications") }
67
67
  end
68
68
 
69
69
  # Factory method to construct a source index instance for a
@@ -174,12 +174,12 @@ module Gem
174
174
  # The signature for the source index. Changes in the signature
175
175
  # indicate a change in the index.
176
176
  def index_signature
177
- Digest::SHA256.new(@gems.keys.sort.join(',')).to_s
177
+ Gem::SHA256.new.hexdigest(@gems.keys.sort.join(',')).to_s
178
178
  end
179
179
 
180
180
  # The signature for the given gem specification.
181
181
  def gem_signature(gem_full_name)
182
- Digest::SHA256.new(@gems[gem_full_name].to_yaml).to_s
182
+ Gem::SHA256.new.hexdigest(@gems[gem_full_name].to_yaml).to_s
183
183
  end
184
184
 
185
185
  def_delegators :@gems, :size, :length
@@ -508,6 +508,11 @@ module Gem
508
508
  File.join(installation_path, "gems", full_name)
509
509
  end
510
510
 
511
+ # The default (generated) file name of the gem.
512
+ def file_name
513
+ full_name + ".gem"
514
+ end
515
+
511
516
  # The root directory that the gem was installed into.
512
517
  #
513
518
  # return:: [String] the installation path
@@ -20,13 +20,13 @@ module Gem
20
20
  if(gem_data.size == 0) then
21
21
  raise VerificationError.new("Empty Gem file")
22
22
  end
23
- require 'md5'
24
- unless(gem_data =~ /MD5SUM/m)
25
- return # Don't worry about it...this sucks. Need to fix MD5 stuff for
26
- # new format
27
- # FIXME
23
+ require 'rubygems/digest/md5'
24
+ unless(gem_data =~ /MD5SUM/m)
25
+ return # Don't worry about it...this sucks. Need to fix MD5 stuff for
26
+ # new format
27
+ # FIXME
28
28
  end
29
- unless (MD5.md5(gem_data.gsub(/MD5SUM = "([a-z0-9]+)"/, "MD5SUM = \"" + ("F" * 32) + "\"")) == $1.to_s)
29
+ unless (Gem::MD5.hexdigest(gem_data.gsub(/MD5SUM = "([a-z0-9]+)"/, "MD5SUM = \"" + ("F" * 32) + "\"")) == $1.to_s)
30
30
  raise VerificationError.new("Invalid checksum for Gem file")
31
31
  end
32
32
  end
@@ -75,7 +75,7 @@ module Gem
75
75
  def alien
76
76
  require 'rubygems/installer'
77
77
  require 'find'
78
- require 'md5'
78
+ require 'rubygems/digest/md5'
79
79
  errors = {}
80
80
  Gem::SourceIndex.from_installed_gems.each do |gem_name, gem_spec|
81
81
  errors[gem_name] ||= []
@@ -97,7 +97,7 @@ module Gem
97
97
  # Found this file. Delete it from list
98
98
  installed_files.delete remove_leading_dot_dir(entry['path'])
99
99
  File.open(File.join(gem_directory, entry['path']), 'rb') do |f|
100
- unless MD5.md5(f.read).to_s == MD5.md5(data).to_s
100
+ unless Gem::MD5.hexdigest(f.read).to_s == Gem::MD5.hexdigest(data).to_s
101
101
  errors[gem_name] << ErrorData.new(entry['path'], "installed file doesn't match original from gem")
102
102
  end
103
103
  end
data/setup.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  #
2
2
  # setup.rb
3
3
  #
4
- # Copyright (c) 2000-2004 Minero Aoki
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
@@ -22,175 +22,67 @@ unless File.respond_to?(:read) # Ruby 1.6
22
22
  end
23
23
  end
24
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
+
25
33
  def File.binread(fname)
26
34
  open(fname, 'rb') {|f|
27
35
  return f.read
28
36
  }
29
37
  end
30
38
 
31
- # for corrupted windows stat(2)
39
+ # for corrupted Windows' stat(2)
32
40
  def File.dir?(path)
33
41
  File.directory?((path[-1,1] == '/') ? path : path + '/')
34
42
  end
35
43
 
36
44
 
37
- class SetupError < StandardError; end
38
-
39
- def setup_rb_error(msg)
40
- raise SetupError, msg
41
- end
42
-
43
- #
44
- # Config
45
- #
46
-
47
- if arg = ARGV.detect {|arg| /\A--rbconfig=/ =~ arg }
48
- ARGV.delete(arg)
49
- require arg.split(/=/, 2)[1]
50
- $".push 'rbconfig.rb'
51
- else
52
- require 'rbconfig'
53
- end
54
-
55
- def multipackage_install?
56
- FileTest.directory?(File.dirname($0) + '/packages')
57
- end
58
-
59
-
60
- class ConfigItem
61
- def initialize(name, template, default, desc)
62
- @name = name.freeze
63
- @template = template
64
- @value = default
65
- @default = default.dup.freeze
66
- @description = desc
67
- end
68
-
69
- attr_reader :name
70
- attr_reader :description
71
-
72
- attr_accessor :default
73
- alias help_default default
74
-
75
- def help_opt
76
- "--#{@name}=#{@template}"
77
- end
78
-
79
- def value
80
- @value
81
- end
82
-
83
- def eval(table)
84
- @value.gsub(%r<\$([^/]+)>) { table[$1] }
85
- end
86
-
87
- def set(val)
88
- @value = check(val)
89
- end
90
-
91
- private
92
-
93
- def check(val)
94
- setup_rb_error "config: --#{name} requires argument" unless val
95
- val
96
- end
97
- end
98
-
99
- class BoolItem < ConfigItem
100
- def config_type
101
- 'bool'
102
- end
103
-
104
- def help_opt
105
- "--#{@name}"
106
- end
107
-
108
- private
45
+ class ConfigTable
109
46
 
110
- def check(val)
111
- return 'yes' unless val
112
- unless /\A(y(es)?|n(o)?|t(rue)?|f(alse))\z/i =~ val
113
- setup_rb_error "config: --#{@name} accepts only yes/no for argument"
114
- end
115
- (/\Ay(es)?|\At(rue)/i =~ value) ? 'yes' : 'no'
116
- end
117
- end
118
-
119
- class PathItem < ConfigItem
120
- def config_type
121
- 'path'
122
- end
123
-
124
- private
47
+ include Enumerable
125
48
 
126
- def check(path)
127
- setup_rb_error "config: --#{@name} requires argument" unless path
128
- path[0,1] == '$' ? path : File.expand_path(path)
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
129
58
  end
130
- end
131
59
 
132
- class ProgramItem < ConfigItem
133
- def config_type
134
- 'program'
135
- end
136
- end
60
+ attr_accessor :install_prefix
61
+ attr_accessor :config_opt
137
62
 
138
- class SelectItem < ConfigItem
139
- def initialize(name, template, default, desc)
140
- super
141
- @ok = template.split('/')
142
- end
63
+ attr_writer :verbose
143
64
 
144
- def config_type
145
- 'select'
65
+ def verbose?
66
+ @verbose
146
67
  end
147
68
 
148
- private
69
+ attr_writer :no_harm
149
70
 
150
- def check(val)
151
- unless @ok.include?(val.strip)
152
- setup_rb_error "config: use --#{@name}=#{@template} (#{val})"
153
- end
154
- val.strip
71
+ def no_harm?
72
+ @no_harm
155
73
  end
156
- end
157
74
 
158
- class PackageSelectionItem < ConfigItem
159
- def initialize(name, template, default, help_default, desc)
160
- super name, template, default, desc
161
- @help_default = help_default
75
+ def [](key)
76
+ lookup(key).resolve(self)
162
77
  end
163
78
 
164
- attr_reader :help_default
165
-
166
- def config_type
167
- 'package'
79
+ def []=(key, val)
80
+ lookup(key).set val
168
81
  end
169
82
 
170
- private
171
-
172
- def check(val)
173
- unless File.dir?("packages/#{val}")
174
- setup_rb_error "config: no such package: #{val}"
175
- end
176
- val
83
+ def names
84
+ @items.map {|i| i.name }
177
85
  end
178
- end
179
-
180
- class ConfigTable_class
181
-
182
- def initialize(items)
183
- @items = items
184
- @table = {}
185
- items.each do |i|
186
- @table[i.name] = i
187
- end
188
- ALIASES.each do |ali, name|
189
- @table[ali] = @table[name]
190
- end
191
- end
192
-
193
- include Enumerable
194
86
 
195
87
  def each(&block)
196
88
  @items.each(&block)
@@ -201,7 +93,7 @@ class ConfigTable_class
201
93
  end
202
94
 
203
95
  def lookup(name)
204
- @table[name] or raise ArgumentError, "no such config item: #{name}"
96
+ @table[name] or setup_rb_error "no such config item: #{name}"
205
97
  end
206
98
 
207
99
  def add(item)
@@ -216,24 +108,24 @@ class ConfigTable_class
216
108
  item
217
109
  end
218
110
 
219
- def new
220
- dup()
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
221
115
  end
222
116
 
223
117
  def savefile
224
118
  '.config'
225
119
  end
226
120
 
227
- def load
121
+ def load_savefile
228
122
  begin
229
- t = dup()
230
123
  File.foreach(savefile()) do |line|
231
124
  k, v = *line.split(/=/, 2)
232
- t[k] = v.strip
125
+ self[k] = v.strip
233
126
  end
234
- t
235
127
  rescue Errno::ENOENT
236
- setup_rb_error $!.message + "#{File.basename($0)} config first"
128
+ setup_rb_error $!.message + "\n#{File.basename($0)} config first"
237
129
  end
238
130
  end
239
131
 
@@ -241,119 +133,151 @@ class ConfigTable_class
241
133
  @items.each {|i| i.value }
242
134
  File.open(savefile(), 'w') {|f|
243
135
  @items.each do |i|
244
- f.printf "%s=%s\n", i.name, i.value if i.value
136
+ f.printf "%s=%s\n", i.name, i.value if i.value? and i.value
245
137
  end
246
138
  }
247
- rescue Exception => e
248
- $stderr.puts "Exception thrown while trying to open #{savefile} in #{Dir.pwd}: #{e}... continuing"
249
139
  end
250
140
 
251
- def [](key)
252
- lookup(key).eval(self)
141
+ def load_standard_entries
142
+ standard_entries(@rbconfig).each do |ent|
143
+ add ent
144
+ end
253
145
  end
254
146
 
255
- def []=(key, val)
256
- lookup(key).set val
257
- end
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']}"
187
+ end
188
+ parameterize = lambda {|path|
189
+ path.sub(/\A#{Regexp.quote(c['prefix'])}/, '$prefix')
190
+ }
258
191
 
259
- end
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'
196
+ end
260
197
 
261
- c = ::Config::CONFIG
262
-
263
- rubypath = c['bindir'] + '/' + c['ruby_install_name']
264
-
265
- major = c['MAJOR'].to_i
266
- minor = c['MINOR'].to_i
267
- teeny = c['TEENY'].to_i
268
- version = "#{major}.#{minor}"
269
-
270
- # ruby ver. >= 1.4.4?
271
- newpath_p = ((major >= 2) or
272
- ((major == 1) and
273
- ((minor >= 5) or
274
- ((minor == 4) and (teeny >= 4)))))
275
-
276
- if c['rubylibdir']
277
- # V < 1.6.3
278
- _stdruby = c['rubylibdir']
279
- _siteruby = c['sitedir']
280
- _siterubyver = c['sitelibdir']
281
- _siterubyverarch = c['sitearchdir']
282
- elsif newpath_p
283
- # 1.4.4 <= V <= 1.6.3
284
- _stdruby = "$prefix/lib/ruby/#{version}"
285
- _siteruby = c['sitedir']
286
- _siterubyver = "$siteruby/#{version}"
287
- _siterubyverarch = "$siterubyver/#{c['arch']}"
288
- else
289
- # V < 1.4.4
290
- _stdruby = "$prefix/lib/ruby/#{version}"
291
- _siteruby = "$prefix/lib/ruby/#{version}/site_ruby"
292
- _siterubyver = _siteruby
293
- _siterubyverarch = "$siterubyver/#{c['arch']}"
294
- end
295
- libdir = '-* dummy libdir *-'
296
- stdruby = '-* dummy rubylibdir *-'
297
- siteruby = '-* dummy site_ruby *-'
298
- siterubyver = '-* dummy site_ruby version *-'
299
- parameterize = lambda {|path|
300
- path.sub(/\A#{Regexp.quote(c['prefix'])}/, '$prefix')\
301
- .sub(/\A#{Regexp.quote(libdir)}/, '$libdir')\
302
- .sub(/\A#{Regexp.quote(stdruby)}/, '$stdruby')\
303
- .sub(/\A#{Regexp.quote(siteruby)}/, '$siteruby')\
304
- .sub(/\A#{Regexp.quote(siterubyver)}/, '$siterubyver')
305
- }
306
- libdir = parameterize.call(c['libdir'])
307
- stdruby = parameterize.call(_stdruby)
308
- siteruby = parameterize.call(_siteruby)
309
- siterubyver = parameterize.call(_siterubyver)
310
- siterubyverarch = parameterize.call(_siterubyverarch)
311
-
312
- if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg }
313
- makeprog = arg.sub(/'/, '').split(/=/, 2)[1]
314
- else
315
- makeprog = 'make'
316
- end
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
264
+ end
265
+
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
317
275
 
318
- common_conf = [
319
- PathItem.new('prefix', 'path', c['prefix'],
320
- 'path prefix of target environment'),
321
- PathItem.new('bindir', 'path', parameterize.call(c['bindir']),
322
- 'the directory for commands'),
323
- PathItem.new('libdir', 'path', libdir,
324
- 'the directory for libraries'),
325
- PathItem.new('datadir', 'path', parameterize.call(c['datadir']),
326
- 'the directory for shared data'),
327
- PathItem.new('mandir', 'path', parameterize.call(c['mandir']),
328
- 'the directory for man pages'),
329
- PathItem.new('sysconfdir', 'path', parameterize.call(c['sysconfdir']),
330
- 'the directory for man pages'),
331
- PathItem.new('stdruby', 'path', stdruby,
332
- 'the directory for standard ruby libraries'),
333
- PathItem.new('siteruby', 'path', siteruby,
334
- 'the directory for version-independent aux ruby libraries'),
335
- PathItem.new('siterubyver', 'path', siterubyver,
336
- 'the directory for aux ruby libraries'),
337
- PathItem.new('siterubyverarch', 'path', siterubyverarch,
338
- 'the directory for aux ruby binaries'),
339
- PathItem.new('rbdir', 'path', '$siterubyver',
340
- 'the directory for ruby scripts'),
341
- PathItem.new('sodir', 'path', '$siterubyverarch',
342
- 'the directory for ruby extentions'),
343
- PathItem.new('rubypath', 'path', rubypath,
344
- 'the path to set to #! line'),
345
- ProgramItem.new('rubyprog', 'name', rubypath,
346
- 'the ruby program using for installation'),
347
- ProgramItem.new('makeprog', 'name', makeprog,
348
- 'the make program to compile ruby extentions'),
349
- SelectItem.new('shebang', 'all/ruby/never', 'ruby',
350
- 'shebang line (#!) editing mode'),
351
- BoolItem.new('without-ext', 'yes/no', 'no',
352
- 'does not compile/install ruby extentions')
353
- ]
354
- class ConfigTable_class # open again
355
276
  ALIASES = {
356
- 'std-ruby' => 'stdruby',
277
+ 'std-ruby' => 'librubyver',
278
+ 'stdruby' => 'librubyver',
279
+ 'rubylibdir' => 'librubyver',
280
+ 'archdir' => 'librubyverarch',
357
281
  'site-ruby-common' => 'siteruby', # For backward compatibility
358
282
  'site-ruby' => 'siterubyver', # For backward compatibility
359
283
  'bin-dir' => 'bindir',
@@ -367,78 +291,248 @@ class ConfigTable_class # open again
367
291
  'make-prog' => 'makeprog',
368
292
  'make' => 'makeprog'
369
293
  }
370
- end
371
- multipackage_conf = [
372
- PackageSelectionItem.new('with', 'name,name...', '', 'ALL',
373
- 'package names that you want to install'),
374
- PackageSelectionItem.new('without', 'name,name...', '', 'NONE',
375
- 'package names that you do not want to install')
376
- ]
377
- if multipackage_install?
378
- ConfigTable = ConfigTable_class.new(common_conf + multipackage_conf)
379
- else
380
- ConfigTable = ConfigTable_class.new(common_conf)
381
- end
382
-
383
-
384
- module MetaConfigAPI
385
294
 
386
- def eval_file_ifexist(fname)
387
- instance_eval File.read(fname), fname, 1 if File.file?(fname)
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/
388
302
  end
389
303
 
390
- def config_names
391
- ConfigTable.map {|i| i.name }
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]
392
307
  end
393
308
 
394
- def config?(name)
395
- ConfigTable.key?(name)
309
+ def dllext
310
+ @rbconfig['DLEXT']
396
311
  end
397
312
 
398
- def bool_config?(name)
399
- ConfigTable.lookup(name).config_type == 'bool'
313
+ def value_config?(name)
314
+ lookup(name).value?
400
315
  end
401
316
 
402
- def path_config?(name)
403
- ConfigTable.lookup(name).config_type == 'path'
404
- end
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
405
325
 
406
- def value_config?(name)
407
- case ConfigTable.lookup(name).config_type
408
- when 'bool', 'path'
326
+ attr_reader :name
327
+ attr_reader :description
328
+
329
+ attr_accessor :default
330
+ alias help_default default
331
+
332
+ def help_opt
333
+ "--#{@name}=#{@template}"
334
+ end
335
+
336
+ def value?
409
337
  true
410
- else
411
- false
338
+ end
339
+
340
+ def value
341
+ @value
342
+ end
343
+
344
+ def resolve(table)
345
+ @value.gsub(%r<\$([^/]+)>) { table[$1] }
346
+ end
347
+
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
412
357
  end
413
358
  end
414
359
 
415
- def add_config(item)
416
- ConfigTable.add item
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
417
380
  end
418
381
 
419
- def add_bool_config(name, default, desc)
420
- ConfigTable.add BoolItem.new(name, 'yes/no', default ? 'yes' : 'no', desc)
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
421
393
  end
422
394
 
423
- def add_path_config(name, default, desc)
424
- ConfigTable.add PathItem.new(name, 'path', default, desc)
395
+ class ProgramItem < Item
396
+ def config_type
397
+ 'program'
398
+ end
425
399
  end
426
400
 
427
- def set_config_default(name, default)
428
- ConfigTable.lookup(name).default = default
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
429
419
  end
430
420
 
431
- def remove_config(name)
432
- ConfigTable.remove(name)
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
433
449
  end
434
450
 
435
- end
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
436
456
 
457
+ attr_reader :help_default
437
458
 
438
- #
439
- # File Operations
440
- #
459
+ def config_type
460
+ 'package'
461
+ end
462
+
463
+ private
441
464
 
465
+ def check(val)
466
+ unless File.dir?("packages/#{val}")
467
+ setup_rb_error "config: no such package: #{val}"
468
+ end
469
+ val
470
+ end
471
+ end
472
+
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
530
+ end
531
+
532
+ end # class ConfigTable
533
+
534
+
535
+ # This module requires: #verbose?, #no_harm?
442
536
  module FileOperations
443
537
 
444
538
  def mkdir_p(dirname, prefix = nil)
@@ -446,7 +540,7 @@ module FileOperations
446
540
  $stderr.puts "mkdir -p #{dirname}" if verbose?
447
541
  return if no_harm?
448
542
 
449
- # does not check '/'... it's too abnormal case
543
+ # Does not check '/', it's too abnormal.
450
544
  dirs = File.expand_path(dirname).split(%r<(?=/)>)
451
545
  if /\A[a-z]:\z/i =~ dirs[0]
452
546
  disk = dirs.shift
@@ -458,49 +552,73 @@ module FileOperations
458
552
  end
459
553
  end
460
554
 
461
- def rm_f(fname)
462
- $stderr.puts "rm -f #{fname}" if verbose?
555
+ def rm_f(path)
556
+ $stderr.puts "rm -f #{path}" if verbose?
463
557
  return if no_harm?
464
-
465
- if File.exist?(fname) or File.symlink?(fname)
466
- File.chmod 0777, fname
467
- File.unlink fname
468
- end
558
+ force_remove_file path
469
559
  end
470
560
 
471
- def rm_rf(dn)
472
- $stderr.puts "rm -rf #{dn}" if verbose?
561
+ def rm_rf(path)
562
+ $stderr.puts "rm -rf #{path}" if verbose?
473
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
474
576
 
475
- Dir.chdir dn
476
- Dir.foreach('.') do |fn|
477
- next if fn == '.'
478
- next if fn == '..'
479
- if File.dir?(fn)
480
- verbose_off {
481
- rm_rf fn
482
- }
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
483
586
  else
484
- verbose_off {
485
- rm_f fn
486
- }
587
+ force_remove_file entpath
487
588
  end
488
589
  end
489
- Dir.chdir '..'
490
- Dir.rmdir dn
590
+ begin
591
+ Dir.rmdir path
592
+ rescue Errno::ENOTEMPTY
593
+ # directory may not be empty
594
+ end
491
595
  end
492
596
 
493
597
  def move_file(src, dest)
494
- File.unlink dest if File.exist?(dest)
598
+ force_remove_file dest
495
599
  begin
496
600
  File.rename src, dest
497
601
  rescue
498
- File.open(dest, 'wb') {|f| f.write File.binread(src) }
602
+ File.open(dest, 'wb') {|f|
603
+ f.write File.binread(src)
604
+ }
499
605
  File.chmod File.stat(src).mode, dest
500
606
  File.unlink src
501
607
  end
502
608
  end
503
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
+
504
622
  def install(from, dest, mode, prefix = nil)
505
623
  $stderr.puts "install #{from} #{dest}" if verbose?
506
624
  return if no_harm?
@@ -517,18 +635,13 @@ module FileOperations
517
635
  }
518
636
  File.chmod mode, realdest
519
637
 
520
- path = "#{objdir_root()}/InstalledFiles"
521
- begin
522
- File.open(path, 'a') {|f|
523
- if prefix
524
- f.puts realdest.sub(prefix, '')
525
- else
526
- f.puts realdest
527
- end
528
- }
529
- rescue Exception => e
530
- $stderr.puts "Exception thrown while trying to open #{path} in #{Dir.pwd}: #{e}... continuing"
531
- end
638
+ File.open("#{objdir_root()}/InstalledFiles", 'a') {|f|
639
+ if prefix
640
+ f.puts realdest.sub(prefix, '')
641
+ else
642
+ f.puts realdest
643
+ end
644
+ }
532
645
  end
533
646
  end
534
647
 
@@ -537,66 +650,42 @@ module FileOperations
537
650
  new_content != File.binread(path)
538
651
  end
539
652
 
540
- def command(str)
541
- $stderr.puts str if verbose?
542
- system str or raise RuntimeError, "'system #{str}' failed"
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"
543
657
  end
544
658
 
545
- def ruby(str)
546
- command config('rubyprog') + ' ' + str
659
+ def ruby(*args)
660
+ command config('rubyprog'), *args
547
661
  end
548
662
 
549
- def make(task = '')
550
- command config('makeprog') + ' ' + task
663
+ def make(task = nil)
664
+ command(*[config('makeprog'), task].compact)
551
665
  end
552
666
 
553
667
  def extdir?(dir)
554
- File.exist?(dir + '/MANIFEST')
668
+ File.exist?("#{dir}/MANIFEST") or File.exist?("#{dir}/extconf.rb")
555
669
  end
556
670
 
557
- def all_files_in(dirname)
558
- Dir.open(dirname) {|d|
559
- return d.select {|ent| File.file?("#{dirname}/#{ent}") }
671
+ def files_of(dir)
672
+ Dir.open(dir) {|d|
673
+ return d.select {|ent| File.file?("#{dir}/#{ent}") }
560
674
  }
561
675
  end
562
676
 
563
- REJECT_DIRS = %w(
564
- CVS SCCS RCS CVS.adm .svn
565
- )
677
+ DIR_REJECT = %w( . .. CVS SCCS RCS CVS.adm .svn )
566
678
 
567
- def all_dirs_in(dirname)
568
- Dir.open(dirname) {|d|
569
- return d.select {|n| File.dir?("#{dirname}/#{n}") } - %w(. ..) - REJECT_DIRS
679
+ def directories_of(dir)
680
+ Dir.open(dir) {|d|
681
+ return d.select {|ent| File.dir?("#{dir}/#{ent}") } - DIR_REJECT
570
682
  }
571
683
  end
572
684
 
573
685
  end
574
686
 
575
687
 
576
- #
577
- # Main Installer
578
- #
579
-
580
- module HookUtils
581
-
582
- def run_hook(name)
583
- try_run_hook "#{curr_srcdir()}/#{name}" or
584
- try_run_hook "#{curr_srcdir()}/#{name}.rb"
585
- end
586
-
587
- def try_run_hook(fname)
588
- return false unless File.file?(fname)
589
- begin
590
- instance_eval File.read(fname), fname, 1
591
- rescue
592
- setup_rb_error "hook #{fname} failed:\n" + $!.message
593
- end
594
- true
595
- end
596
-
597
- end
598
-
599
-
688
+ # This module requires: #srcdir_root, #objdir_root, #relpath
600
689
  module HookScriptAPI
601
690
 
602
691
  def get_config(key)
@@ -605,6 +694,7 @@ module HookScriptAPI
605
694
 
606
695
  alias config get_config
607
696
 
697
+ # obsolete: use metaconfig to change configuration
608
698
  def set_config(key, val)
609
699
  @config[key] = val
610
700
  end
@@ -613,10 +703,6 @@ module HookScriptAPI
613
703
  # srcdir/objdir (works only in the package directory)
614
704
  #
615
705
 
616
- #abstract srcdir_root
617
- #abstract objdir_root
618
- #abstract relpath
619
-
620
706
  def curr_srcdir
621
707
  "#{srcdir_root()}/#{relpath()}"
622
708
  end
@@ -638,7 +724,7 @@ module HookScriptAPI
638
724
  end
639
725
 
640
726
  def srcfile?(path)
641
- File.file? srcfile(path)
727
+ File.file?(srcfile(path))
642
728
  end
643
729
 
644
730
  def srcentries(path = '.')
@@ -664,8 +750,8 @@ end
664
750
 
665
751
  class ToplevelInstaller
666
752
 
667
- Version = '3.3.1'
668
- Copyright = 'Copyright (c) 2000-2004 Minero Aoki'
753
+ Version = '3.4.1'
754
+ Copyright = 'Copyright (c) 2000-2005 Minero Aoki'
669
755
 
670
756
  TASKS = [
671
757
  [ 'all', 'do config, setup, then install' ],
@@ -673,27 +759,44 @@ class ToplevelInstaller
673
759
  [ 'show', 'shows current configuration' ],
674
760
  [ 'setup', 'compiles ruby extentions and others' ],
675
761
  [ 'install', 'installs files' ],
762
+ [ 'test', 'run all tests in test/' ],
676
763
  [ 'clean', "does `make clean' for each extention" ],
677
764
  [ 'distclean',"does `make distclean' for each extention" ]
678
765
  ]
679
766
 
680
767
  def ToplevelInstaller.invoke
681
- instance().invoke
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
682
774
  end
683
775
 
684
- @singleton = nil
685
-
686
- def ToplevelInstaller.instance
687
- @singleton ||= new(File.dirname($0))
688
- @singleton
776
+ def ToplevelInstaller.multipackage?
777
+ File.dir?(File.dirname($0) + '/packages')
689
778
  end
690
779
 
691
- include MetaConfigAPI
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
692
790
 
693
- def initialize(ardir_root)
694
- @config = nil
695
- @options = { 'verbose' => true }
791
+ def initialize(ardir_root, config)
696
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]
697
800
  end
698
801
 
699
802
  def inspect
@@ -704,14 +807,20 @@ class ToplevelInstaller
704
807
  run_metaconfigs
705
808
  case task = parsearg_global()
706
809
  when nil, 'all'
707
- @config = load_config('config')
708
810
  parsearg_config
709
811
  init_installers
710
812
  exec_config
711
813
  exec_setup
712
814
  exec_install
713
815
  else
714
- @config = load_config(task)
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
715
824
  __send__ "parsearg_#{task}"
716
825
  init_installers
717
826
  __send__ "exec_#{task}"
@@ -719,25 +828,11 @@ class ToplevelInstaller
719
828
  end
720
829
 
721
830
  def run_metaconfigs
722
- eval_file_ifexist "#{@ardir}/metaconfig"
723
- end
724
-
725
- def load_config(task)
726
- case task
727
- when 'config'
728
- ConfigTable.new
729
- when 'clean', 'distclean'
730
- if File.exist?(ConfigTable.savefile)
731
- then ConfigTable.load
732
- else ConfigTable.new
733
- end
734
- else
735
- ConfigTable.load
736
- end
831
+ @config.load_script "#{@ardir}/metaconfig"
737
832
  end
738
833
 
739
834
  def init_installers
740
- @installer = Installer.new(@config, @options, @ardir, File.expand_path('.'))
835
+ @installer = Installer.new(@config, @ardir, File.expand_path('.'))
741
836
  end
742
837
 
743
838
  #
@@ -761,78 +856,89 @@ class ToplevelInstaller
761
856
  #
762
857
 
763
858
  def parsearg_global
764
- valid_task = /\A(?:#{TASKS.map {|task,desc| task }.join '|'})\z/
765
-
766
859
  while arg = ARGV.shift
767
860
  case arg
768
861
  when /\A\w+\z/
769
- setup_rb_error "invalid task: #{arg}" unless valid_task =~ arg
862
+ setup_rb_error "invalid task: #{arg}" unless valid_task?(arg)
770
863
  return arg
771
-
772
864
  when '-q', '--quiet'
773
- @options['verbose'] = false
774
-
775
- when '--verbose'
776
- @options['verbose'] = true
777
-
778
- when '-h', '--help'
865
+ @config.verbose = false
866
+ when '--verbose'
867
+ @config.verbose = true
868
+ when '--help'
779
869
  print_usage $stdout
780
870
  exit 0
781
-
782
- when '-v', '--version'
871
+ when '--version'
783
872
  puts "#{File.basename($0)} version #{Version}"
784
873
  exit 0
785
-
786
874
  when '--copyright'
787
875
  puts Copyright
788
876
  exit 0
789
-
790
877
  else
791
878
  setup_rb_error "unknown global option '#{arg}'"
792
879
  end
793
880
  end
794
-
795
881
  nil
796
882
  end
797
883
 
884
+ def valid_task?(t)
885
+ valid_task_re() =~ t
886
+ end
887
+
888
+ def valid_task_re
889
+ @valid_task_re ||= /\A(?:#{TASKS.map {|task,desc| task }.join('|')})\z/
890
+ end
798
891
 
799
892
  def parsearg_no_options
800
893
  unless ARGV.empty?
801
- setup_rb_error "#{task}: unknown options: #{ARGV.join ' '}"
894
+ task = caller(0).first.slice(%r<`parsearg_(\w+)'>, 1)
895
+ setup_rb_error "#{task}: unknown options: #{ARGV.join(' ')}"
802
896
  end
803
897
  end
804
898
 
805
899
  alias parsearg_show parsearg_no_options
806
900
  alias parsearg_setup parsearg_no_options
901
+ alias parsearg_test parsearg_no_options
807
902
  alias parsearg_clean parsearg_no_options
808
903
  alias parsearg_distclean parsearg_no_options
809
904
 
810
905
  def parsearg_config
811
- re = /\A--(#{ConfigTable.map {|i| i.name }.join('|')})(?:=(.*))?\z/
812
- @options['config-opt'] = []
813
-
906
+ evalopt = []
907
+ set = []
908
+ @config.config_opt = []
814
909
  while i = ARGV.shift
815
910
  if /\A--?\z/ =~ i
816
- @options['config-opt'] = ARGV.dup
911
+ @config.config_opt = ARGV.dup
817
912
  break
818
913
  end
819
- m = re.match(i) or setup_rb_error "config: unknown option #{i}"
820
- name, value = *m.to_a[1,2]
821
- @config[name] = value
914
+ name, value = *@config.parse_opt(i)
915
+ if @config.value_config?(name)
916
+ @config[name] = value
917
+ else
918
+ evalopt.push [name, value]
919
+ end
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)
822
928
  end
823
929
  end
824
930
 
825
931
  def parsearg_install
826
- @options['no-harm'] = false
827
- @options['install-prefix'] = ''
932
+ @config.no_harm = false
933
+ @config.install_prefix = ''
828
934
  while a = ARGV.shift
829
935
  case a
830
- when /\A--no-harm\z/
831
- @options['no-harm'] = true
832
- when /\A--prefix=(.*)\z/
833
- path = $1
936
+ when '--no-harm'
937
+ @config.no_harm = true
938
+ when /\A--prefix=/
939
+ path = a.split(/=/, 2)[1]
834
940
  path = File.expand_path(path) unless path[0,1] == '/'
835
- @options['install-prefix'] = path
941
+ @config.install_prefix = path
836
942
  else
837
943
  setup_rb_error "install: unknown option #{a}"
838
944
  end
@@ -854,8 +960,8 @@ class ToplevelInstaller
854
960
  out.puts 'Global options:'
855
961
  out.printf fmt, '-q,--quiet', 'suppress message outputs'
856
962
  out.printf fmt, ' --verbose', 'output messages verbosely'
857
- out.printf fmt, '-h,--help', 'print this message'
858
- out.printf fmt, '-v,--version', 'print version and quit'
963
+ out.printf fmt, ' --help', 'print this message'
964
+ out.printf fmt, ' --version', 'print version and quit'
859
965
  out.printf fmt, ' --copyright', 'print copyright and quit'
860
966
  out.puts
861
967
  out.puts 'Tasks:'
@@ -866,14 +972,14 @@ class ToplevelInstaller
866
972
  fmt = " %-24s %s [%s]\n"
867
973
  out.puts
868
974
  out.puts 'Options for CONFIG or ALL:'
869
- ConfigTable.each do |item|
975
+ @config.each do |item|
870
976
  out.printf fmt, item.help_opt, item.description, item.help_default
871
977
  end
872
978
  out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',"running ruby's"
873
979
  out.puts
874
980
  out.puts 'Options for INSTALL:'
875
981
  out.printf fmt, '--no-harm', 'only display what to do if given', 'off'
876
- out.printf fmt, '--prefix=path', 'install path prefix', '$prefix'
982
+ out.printf fmt, '--prefix=path', 'install path prefix', ''
877
983
  out.puts
878
984
  end
879
985
 
@@ -894,9 +1000,13 @@ class ToplevelInstaller
894
1000
  @installer.exec_install
895
1001
  end
896
1002
 
1003
+ def exec_test
1004
+ @installer.exec_test
1005
+ end
1006
+
897
1007
  def exec_show
898
- ConfigTable.each do |i|
899
- printf "%-20s %s\n", i.name, i.value
1008
+ @config.each do |i|
1009
+ printf "%-20s %s\n", i.name, i.value if i.value?
900
1010
  end
901
1011
  end
902
1012
 
@@ -908,36 +1018,45 @@ class ToplevelInstaller
908
1018
  @installer.exec_distclean
909
1019
  end
910
1020
 
911
- end
1021
+ end # class ToplevelInstaller
912
1022
 
913
1023
 
914
1024
  class ToplevelInstallerMulti < ToplevelInstaller
915
1025
 
916
- include HookUtils
917
- include HookScriptAPI
918
1026
  include FileOperations
919
1027
 
920
- def initialize(ardir)
1028
+ def initialize(ardir_root, config)
921
1029
  super
922
- @packages = all_dirs_in("#{@ardir}/packages")
1030
+ @packages = directories_of("#{@ardir}/packages")
923
1031
  raise 'no package exists' if @packages.empty?
1032
+ @root_installer = Installer.new(@config, @ardir, File.expand_path('.'))
924
1033
  end
925
1034
 
926
1035
  def run_metaconfigs
927
- eval_file_ifexist "#{@ardir}/metaconfig"
1036
+ @config.load_script "#{@ardir}/metaconfig", self
928
1037
  @packages.each do |name|
929
- eval_file_ifexist "#{@ardir}/packages/#{name}/metaconfig"
1038
+ @config.load_script "#{@ardir}/packages/#{name}/metaconfig"
930
1039
  end
931
1040
  end
932
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
+
933
1053
  def init_installers
934
1054
  @installers = {}
935
1055
  @packages.each do |pack|
936
- @installers[pack] = Installer.new(@config, @options,
1056
+ @installers[pack] = Installer.new(@config,
937
1057
  "#{@ardir}/packages/#{pack}",
938
1058
  "packages/#{pack}")
939
1059
  end
940
-
941
1060
  with = extract_selection(config('with'))
942
1061
  without = extract_selection(config('without'))
943
1062
  @selected = @installers.keys.select {|name|
@@ -961,21 +1080,6 @@ class ToplevelInstallerMulti < ToplevelInstaller
961
1080
  f.puts
962
1081
  end
963
1082
 
964
- #
965
- # multi-package metaconfig API
966
- #
967
-
968
- attr_reader :packages
969
-
970
- def declare_packages(list)
971
- raise 'package list is empty' if list.empty?
972
- list.each do |name|
973
- raise "directory packages/#{name} does not exist"\
974
- unless File.dir?("#{@ardir}/packages/#{name}")
975
- end
976
- @packages = list
977
- end
978
-
979
1083
  #
980
1084
  # Task Handlers
981
1085
  #
@@ -999,15 +1103,21 @@ class ToplevelInstallerMulti < ToplevelInstaller
999
1103
  run_hook 'post-install'
1000
1104
  end
1001
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
+
1002
1112
  def exec_clean
1003
- rm_f ConfigTable.savefile
1113
+ rm_f @config.savefile
1004
1114
  run_hook 'pre-clean'
1005
1115
  each_selected_installers {|inst| inst.exec_clean }
1006
1116
  run_hook 'post-clean'
1007
1117
  end
1008
1118
 
1009
1119
  def exec_distclean
1010
- rm_f ConfigTable.savefile
1120
+ rm_f @config.savefile
1011
1121
  run_hook 'pre-distclean'
1012
1122
  each_selected_installers {|inst| inst.exec_distclean }
1013
1123
  run_hook 'post-distclean'
@@ -1020,7 +1130,7 @@ class ToplevelInstallerMulti < ToplevelInstaller
1020
1130
  def each_selected_installers
1021
1131
  Dir.mkdir 'packages' unless File.dir?('packages')
1022
1132
  @selected.each do |pack|
1023
- $stderr.puts "Processing the package `#{pack}' ..." if @options['verbose']
1133
+ $stderr.puts "Processing the package `#{pack}' ..." if verbose?
1024
1134
  Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}")
1025
1135
  Dir.chdir "packages/#{pack}"
1026
1136
  yield @installers[pack]
@@ -1028,28 +1138,32 @@ class ToplevelInstallerMulti < ToplevelInstaller
1028
1138
  end
1029
1139
  end
1030
1140
 
1141
+ def run_hook(id)
1142
+ @root_installer.run_hook id
1143
+ end
1144
+
1145
+ # module FileOperations requires this
1031
1146
  def verbose?
1032
- @options['verbose']
1147
+ @config.verbose?
1033
1148
  end
1034
1149
 
1150
+ # module FileOperations requires this
1035
1151
  def no_harm?
1036
- @options['no-harm']
1152
+ @config.no_harm?
1037
1153
  end
1038
1154
 
1039
- end
1155
+ end # class ToplevelInstallerMulti
1040
1156
 
1041
1157
 
1042
1158
  class Installer
1043
1159
 
1044
- FILETYPES = %w( bin lib ext data )
1160
+ FILETYPES = %w( bin lib ext data conf man )
1045
1161
 
1046
- include HookScriptAPI
1047
- include HookUtils
1048
1162
  include FileOperations
1163
+ include HookScriptAPI
1049
1164
 
1050
- def initialize(config, opt, srcroot, objroot)
1165
+ def initialize(config, srcroot, objroot)
1051
1166
  @config = config
1052
- @options = opt
1053
1167
  @srcdir = File.expand_path(srcroot)
1054
1168
  @objdir = File.expand_path(objroot)
1055
1169
  @currdir = '.'
@@ -1059,6 +1173,9 @@ class Installer
1059
1173
  "#<#{self.class} #{File.basename(@srcdir)}>"
1060
1174
  end
1061
1175
 
1176
+ def noop(rel)
1177
+ end
1178
+
1062
1179
  #
1063
1180
  # Hook Script API base methods
1064
1181
  #
@@ -1076,23 +1193,25 @@ class Installer
1076
1193
  end
1077
1194
 
1078
1195
  #
1079
- # configs/options
1196
+ # Config Access
1080
1197
  #
1081
1198
 
1082
- def no_harm?
1083
- @options['no-harm']
1199
+ # module FileOperations requires this
1200
+ def verbose?
1201
+ @config.verbose?
1084
1202
  end
1085
1203
 
1086
- def verbose?
1087
- @options['verbose']
1204
+ # module FileOperations requires this
1205
+ def no_harm?
1206
+ @config.no_harm?
1088
1207
  end
1089
1208
 
1090
1209
  def verbose_off
1091
1210
  begin
1092
- save, @options['verbose'] = @options['verbose'], false
1211
+ save, @config.verbose = @config.verbose?, false
1093
1212
  yield
1094
1213
  ensure
1095
- @options['verbose'] = save
1214
+ @config.verbose = save
1096
1215
  end
1097
1216
  end
1098
1217
 
@@ -1104,22 +1223,19 @@ class Installer
1104
1223
  exec_task_traverse 'config'
1105
1224
  end
1106
1225
 
1107
- def config_dir_bin(rel)
1108
- end
1109
-
1110
- def config_dir_lib(rel)
1111
- end
1226
+ alias config_dir_bin noop
1227
+ alias config_dir_lib noop
1112
1228
 
1113
1229
  def config_dir_ext(rel)
1114
1230
  extconf if extdir?(curr_srcdir())
1115
1231
  end
1116
1232
 
1117
- def extconf
1118
- opt = @options['config-opt'].join(' ')
1119
- command "#{config('rubyprog')} #{curr_srcdir()}/extconf.rb #{opt}"
1120
- end
1233
+ alias config_dir_data noop
1234
+ alias config_dir_conf noop
1235
+ alias config_dir_man noop
1121
1236
 
1122
- def config_dir_data(rel)
1237
+ def extconf
1238
+ ruby "#{curr_srcdir()}/extconf.rb", *@config.config_opt
1123
1239
  end
1124
1240
 
1125
1241
  #
@@ -1131,39 +1247,90 @@ class Installer
1131
1247
  end
1132
1248
 
1133
1249
  def setup_dir_bin(rel)
1134
- all_files_in(curr_srcdir()).each do |fname|
1135
- adjust_shebang "#{curr_srcdir()}/#{fname}"
1250
+ files_of(curr_srcdir()).each do |fname|
1251
+ update_shebang_line "#{curr_srcdir()}/#{fname}"
1136
1252
  end
1137
1253
  end
1138
1254
 
1139
- def adjust_shebang(path)
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
1264
+
1265
+ def update_shebang_line(path)
1140
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
1297
+
1298
+ def open_atomic_writer(path, &block)
1141
1299
  tmpfile = File.basename(path) + '.tmp'
1142
1300
  begin
1143
- File.open(path, 'rb') {|r|
1144
- first = r.gets
1145
- return unless File.basename(config('rubypath')) == 'ruby'
1146
- return unless File.basename(first.sub(/\A\#!/, '').split[0]) == 'ruby'
1147
- $stderr.puts "adjusting shebang: #{File.basename(path)}" if verbose?
1148
- File.open(tmpfile, 'wb') {|w|
1149
- w.print first.sub(/\A\#!\s*\S+/, '#! ' + config('rubypath'))
1150
- w.write r.read
1151
- }
1152
- }
1153
- move_file tmpfile, File.basename(path)
1301
+ File.open(tmpfile, 'wb', &block)
1302
+ File.rename tmpfile, File.basename(path)
1154
1303
  ensure
1155
1304
  File.unlink tmpfile if File.exist?(tmpfile)
1156
1305
  end
1157
1306
  end
1158
1307
 
1159
- def setup_dir_lib(rel)
1160
- end
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
1161
1317
 
1162
- def setup_dir_ext(rel)
1163
- make if extdir?(curr_srcdir())
1164
- end
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
1165
1327
 
1166
- def setup_dir_data(rel)
1328
+ attr_reader :cmd
1329
+ attr_reader :args
1330
+
1331
+ def to_s
1332
+ "#! #{@cmd}" + (@args.empty? ? '' : " #{@args.join(' ')}")
1333
+ end
1167
1334
  end
1168
1335
 
1169
1336
  #
@@ -1176,63 +1343,77 @@ class Installer
1176
1343
  end
1177
1344
 
1178
1345
  def install_dir_bin(rel)
1179
- install_files collect_filenames_auto(), "#{config('bindir')}/#{rel}", 0755
1346
+ install_files targetfiles(), "#{config('bindir')}/#{rel}", 0755
1180
1347
  end
1181
1348
 
1182
1349
  def install_dir_lib(rel)
1183
- install_files ruby_scripts(), "#{config('rbdir')}/#{rel}", 0644
1350
+ install_files libfiles(), "#{config('rbdir')}/#{rel}", 0644
1184
1351
  end
1185
1352
 
1186
1353
  def install_dir_ext(rel)
1187
1354
  return unless extdir?(curr_srcdir())
1188
- install_files ruby_extentions('.'),
1355
+ install_files rubyextentions('.'),
1189
1356
  "#{config('sodir')}/#{File.dirname(rel)}",
1190
1357
  0555
1191
1358
  end
1192
1359
 
1193
1360
  def install_dir_data(rel)
1194
- install_files collect_filenames_auto(), "#{config('datadir')}/#{rel}", 0644
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
1195
1372
  end
1196
1373
 
1197
1374
  def install_files(list, dest, mode)
1198
- mkdir_p dest, @options['install-prefix']
1375
+ mkdir_p dest, @config.install_prefix
1199
1376
  list.each do |fname|
1200
- install fname, dest, mode, @options['install-prefix']
1377
+ install fname, dest, mode, @config.install_prefix
1201
1378
  end
1202
1379
  end
1203
1380
 
1204
- def ruby_scripts
1205
- collect_filenames_auto().select {|n| /\.rb\z/ =~ n }
1381
+ def libfiles
1382
+ glob_reject(%w(*.y *.output), targetfiles())
1206
1383
  end
1207
-
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
+
1208
1406
  # picked up many entries from cvs-1.11.1/src/ignore.c
1209
- reject_patterns = %w(
1407
+ JUNK_FILES = %w(
1210
1408
  core RCSLOG tags TAGS .make.state
1211
1409
  .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb
1212
1410
  *~ *.old *.bak *.BAK *.orig *.rej _$* *$
1213
1411
 
1214
1412
  *.org *.in .*
1215
1413
  )
1216
- mapping = {
1217
- '.' => '\.',
1218
- '$' => '\$',
1219
- '#' => '\#',
1220
- '*' => '.*'
1221
- }
1222
- REJECT_PATTERNS = Regexp.new('\A(?:' +
1223
- reject_patterns.map {|pat|
1224
- pat.gsub(/[\.\$\#\*]/) {|ch| mapping[ch] }
1225
- }.join('|') +
1226
- ')\z')
1227
-
1228
- def collect_filenames_auto
1229
- mapdir((existfiles() - hookfiles()).reject {|fname|
1230
- REJECT_PATTERNS =~ fname
1231
- })
1232
- end
1233
1414
 
1234
1415
  def existfiles
1235
- all_files_in(curr_srcdir()) | all_files_in('.')
1416
+ glob_reject(JUNK_FILES, (files_of(curr_srcdir()) | files_of('.')))
1236
1417
  end
1237
1418
 
1238
1419
  def hookfiles
@@ -1241,24 +1422,49 @@ class Installer
1241
1422
  }.flatten
1242
1423
  end
1243
1424
 
1244
- def mapdir(filelist)
1245
- filelist.map {|fname|
1246
- if File.exist?(fname) # objdir
1247
- fname
1248
- else # srcdir
1249
- File.join(curr_srcdir(), fname)
1250
- end
1251
- }
1425
+ def glob_select(pat, ents)
1426
+ re = globs2re([pat])
1427
+ ents.select {|ent| re =~ ent }
1252
1428
  end
1253
1429
 
1254
- def ruby_extentions(dir)
1255
- Dir.open(dir) {|d|
1256
- ents = d.select {|fname| /\.#{::Config::CONFIG['DLEXT']}\z/ =~ fname }
1257
- if ents.empty?
1258
- setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first"
1259
- end
1260
- return ents
1261
- }
1430
+ def glob_reject(pats, ents)
1431
+ re = globs2re(pats)
1432
+ ents.reject {|ent| re =~ ent }
1433
+ end
1434
+
1435
+ GLOB2REGEX = {
1436
+ '.' => '\.',
1437
+ '$' => '\$',
1438
+ '#' => '\#',
1439
+ '*' => '.*'
1440
+ }
1441
+
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
1262
1468
  end
1263
1469
 
1264
1470
  #
@@ -1267,53 +1473,51 @@ class Installer
1267
1473
 
1268
1474
  def exec_clean
1269
1475
  exec_task_traverse 'clean'
1270
- rm_f ConfigTable.savefile
1476
+ rm_f @config.savefile
1271
1477
  rm_f 'InstalledFiles'
1272
1478
  end
1273
1479
 
1274
- def clean_dir_bin(rel)
1275
- end
1276
-
1277
- def clean_dir_lib(rel)
1278
- end
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
1279
1485
 
1280
1486
  def clean_dir_ext(rel)
1281
1487
  return unless extdir?(curr_srcdir())
1282
1488
  make 'clean' if File.file?('Makefile')
1283
1489
  end
1284
1490
 
1285
- def clean_dir_data(rel)
1286
- end
1287
-
1288
1491
  #
1289
1492
  # TASK distclean
1290
1493
  #
1291
1494
 
1292
1495
  def exec_distclean
1293
1496
  exec_task_traverse 'distclean'
1294
- rm_f ConfigTable.savefile
1497
+ rm_f @config.savefile
1295
1498
  rm_f 'InstalledFiles'
1296
1499
  end
1297
1500
 
1298
- def distclean_dir_bin(rel)
1299
- end
1300
-
1301
- def distclean_dir_lib(rel)
1302
- end
1501
+ alias distclean_dir_bin noop
1502
+ alias distclean_dir_lib noop
1303
1503
 
1304
1504
  def distclean_dir_ext(rel)
1305
1505
  return unless extdir?(curr_srcdir())
1306
1506
  make 'distclean' if File.file?('Makefile')
1307
1507
  end
1308
1508
 
1509
+ alias distclean_dir_data noop
1510
+ alias distclean_dir_conf noop
1511
+ alias distclean_dir_man noop
1512
+
1309
1513
  #
1310
- # lib
1514
+ # Traversing
1311
1515
  #
1312
1516
 
1313
1517
  def exec_task_traverse(task)
1314
1518
  run_hook "pre-#{task}"
1315
1519
  FILETYPES.each do |type|
1316
- if config('without-ext') == 'yes' and type == 'ext'
1520
+ if type == 'ext' and config('without-ext') == 'yes'
1317
1521
  $stderr.puts 'skipping ext/* by user option' if verbose?
1318
1522
  next
1319
1523
  end
@@ -1326,7 +1530,7 @@ class Installer
1326
1530
  dive_into(rel) {
1327
1531
  run_hook "pre-#{task}"
1328
1532
  __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '')
1329
- all_dirs_in(curr_srcdir()).each do |d|
1533
+ directories_of(curr_srcdir()).each do |d|
1330
1534
  traverse task, "#{rel}/#{d}", mid
1331
1535
  end
1332
1536
  run_hook "post-#{task}"
@@ -1348,16 +1552,30 @@ class Installer
1348
1552
  @currdir = File.dirname(rel)
1349
1553
  end
1350
1554
 
1351
- end
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
1568
+
1569
+
1570
+ class SetupError < StandardError; end
1352
1571
 
1572
+ def setup_rb_error(msg)
1573
+ raise SetupError, msg
1574
+ end
1353
1575
 
1354
1576
  if $0 == __FILE__
1355
1577
  begin
1356
- if multipackage_install?
1357
- ToplevelInstallerMulti.invoke
1358
- else
1359
- ToplevelInstaller.invoke
1360
- end
1578
+ ToplevelInstaller.invoke
1361
1579
  rescue SetupError
1362
1580
  raise if $DEBUG
1363
1581
  $stderr.puts $!.message