pwrake 0.9.9.2 → 2.0.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.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/CHANGES_V2.md +90 -0
  4. data/{LICENSE.txt → MIT-LICENSE} +2 -3
  5. data/README +12 -0
  6. data/README.md +75 -52
  7. data/bin/gfwhere-pipe +23 -12
  8. data/bin/pwrake +22 -29
  9. data/bin/pwrake_branch +24 -0
  10. data/lib/pwrake/branch.rb +22 -0
  11. data/lib/pwrake/branch/branch.rb +213 -0
  12. data/lib/pwrake/branch/branch_application.rb +53 -0
  13. data/lib/pwrake/branch/fiber_queue.rb +36 -0
  14. data/lib/pwrake/branch/file_utils.rb +101 -0
  15. data/lib/pwrake/branch/shell.rb +231 -0
  16. data/lib/pwrake/{profiler.rb → branch/shell_profiler.rb} +28 -27
  17. data/lib/pwrake/branch/worker_communicator.rb +104 -0
  18. data/lib/pwrake/{gfarm_feature.rb → gfarm/gfarm_path.rb} +2 -100
  19. data/lib/pwrake/gfarm/gfarm_postprocess.rb +53 -0
  20. data/lib/pwrake/iomux/channel.rb +70 -0
  21. data/lib/pwrake/iomux/handler.rb +124 -0
  22. data/lib/pwrake/iomux/handler_set.rb +35 -0
  23. data/lib/pwrake/iomux/runner.rb +62 -0
  24. data/lib/pwrake/logger.rb +3 -150
  25. data/lib/pwrake/master.rb +30 -137
  26. data/lib/pwrake/master/fiber_pool.rb +69 -0
  27. data/lib/pwrake/master/idle_cores.rb +30 -0
  28. data/lib/pwrake/master/master.rb +345 -0
  29. data/lib/pwrake/master/master_application.rb +150 -0
  30. data/lib/pwrake/master/postprocess.rb +16 -0
  31. data/lib/pwrake/{graphviz.rb → misc/graphviz.rb} +0 -0
  32. data/lib/pwrake/{mcgp.rb → misc/mcgp.rb} +63 -42
  33. data/lib/pwrake/option/host_map.rb +158 -0
  34. data/lib/pwrake/option/option.rb +357 -0
  35. data/lib/pwrake/option/option_filesystem.rb +112 -0
  36. data/lib/pwrake/queue/locality_aware_queue.rb +158 -0
  37. data/lib/pwrake/queue/no_action_queue.rb +67 -0
  38. data/lib/pwrake/queue/queue_array.rb +366 -0
  39. data/lib/pwrake/queue/task_queue.rb +164 -0
  40. data/lib/pwrake/report.rb +1 -0
  41. data/lib/pwrake/report/parallelism.rb +9 -3
  42. data/lib/pwrake/report/report.rb +50 -103
  43. data/lib/pwrake/report/task_stat.rb +83 -0
  44. data/lib/pwrake/task/task_algorithm.rb +107 -0
  45. data/lib/pwrake/task/task_manager.rb +32 -0
  46. data/lib/pwrake/task/task_property.rb +98 -0
  47. data/lib/pwrake/task/task_rank.rb +48 -0
  48. data/lib/pwrake/task/task_wrapper.rb +296 -0
  49. data/lib/pwrake/version.rb +1 -1
  50. data/lib/pwrake/worker/executor.rb +169 -0
  51. data/lib/pwrake/worker/gfarm_directory.rb +90 -0
  52. data/lib/pwrake/worker/invoker.rb +199 -0
  53. data/lib/pwrake/worker/load.rb +14 -0
  54. data/lib/pwrake/worker/log_executor.rb +73 -0
  55. data/lib/pwrake/worker/shared_directory.rb +74 -0
  56. data/lib/pwrake/worker/worker_main.rb +14 -0
  57. data/lib/pwrake/worker/writer.rb +59 -0
  58. data/setup.rb +1212 -1502
  59. data/spec/003/Rakefile +2 -2
  60. data/spec/008/Rakefile +2 -1
  61. data/spec/009/Rakefile +1 -1
  62. data/spec/009/pwrake_conf.yaml +1 -3
  63. data/spec/hosts +0 -2
  64. data/spec/pwrake_spec.rb +9 -8
  65. metadata +50 -21
  66. data/lib/pwrake.rb +0 -19
  67. data/lib/pwrake/application.rb +0 -232
  68. data/lib/pwrake/counter.rb +0 -54
  69. data/lib/pwrake/file_utils.rb +0 -98
  70. data/lib/pwrake/gfwhere_pool.rb +0 -109
  71. data/lib/pwrake/host_list.rb +0 -88
  72. data/lib/pwrake/locality_aware_queue.rb +0 -413
  73. data/lib/pwrake/option.rb +0 -400
  74. data/lib/pwrake/rake_modify.rb +0 -14
  75. data/lib/pwrake/shell.rb +0 -186
  76. data/lib/pwrake/task_algorithm.rb +0 -475
  77. data/lib/pwrake/task_queue.rb +0 -633
  78. data/lib/pwrake/timer.rb +0 -22
@@ -0,0 +1,14 @@
1
+ require "thread"
2
+ require "pathname"
3
+ require "fileutils"
4
+ require "singleton"
5
+ require "forwardable"
6
+ require "logger"
7
+ require "timeout"
8
+
9
+ require "pwrake/worker/writer"
10
+ require "pwrake/worker/log_executor"
11
+ require "pwrake/worker/executor"
12
+ require "pwrake/worker/invoker"
13
+
14
+ require "pwrake/worker/shared_directory"
@@ -0,0 +1,73 @@
1
+ require "singleton"
2
+ require "forwardable"
3
+ require "logger"
4
+
5
+ module Pwrake
6
+
7
+ class DummyLogger
8
+ def method_missing(id,*args)
9
+ end
10
+ end
11
+
12
+ class LogExecutor
13
+ include Singleton
14
+ extend Forwardable
15
+
16
+ def_delegators :@logger, :debug, :info, :error, :fatal, :warn, :unknown
17
+ def_delegators :@logger, :debug?, :info?, :error?, :fatal?, :warn?, :unknown?
18
+ def_delegators :@logger, :level, :level=
19
+ def_delegators :@logger, :formatter, :formatter=
20
+ def_delegators :@logger, :datetime_format, :datetime_format=
21
+
22
+ def initialize
23
+ @level = ::Logger::DEBUG
24
+ #@logger = @logger_stderr = ::Logger.new($stderr)
25
+ @logger = @logger_stderr = DummyLogger.new
26
+ @logger.level = @level
27
+ end
28
+
29
+ attr_reader :path
30
+
31
+ def init(option)
32
+ @option = option
33
+ @log_dir = @option[:log_dir]
34
+ end
35
+
36
+ def opened?
37
+ @opened
38
+ end
39
+
40
+ def open(dir_class)
41
+ if @log_dir
42
+ @dir = dir_class.new
43
+ @dir.open
44
+ @path = @dir.log_path
45
+ fn = "worker-#{`hostname`.chomp}-#{Process.pid}.log"
46
+ @logfile = (@path + fn).to_s
47
+ ::FileUtils.mkdir_p(@path.to_s)
48
+ @logger = @logger_file = ::Logger.new(@logfile)
49
+ @opened = true
50
+ @logger.level = @level
51
+ @dir.open_messages.each{|m| @logger.info(m)}
52
+ end
53
+ end
54
+
55
+ def close
56
+ if @log_dir
57
+ @dir.close_messages.each{|m| @logger.info(m)}
58
+ @logger = @logger_stderr
59
+ @opened = false
60
+ @logger_file.close
61
+ @logger_file = nil
62
+ @dir.close
63
+ end
64
+ end
65
+
66
+ def join
67
+ end
68
+
69
+ def kill(sig)
70
+ end
71
+
72
+ end
73
+ end
@@ -0,0 +1,74 @@
1
+ require "pathname"
2
+
3
+ module Pwrake
4
+
5
+ class SharedDirectory
6
+
7
+ @@prefix = nil
8
+ @@work_dir = nil
9
+ @@log_dir = nil
10
+
11
+ def self.init(opts)
12
+ @@prefix = opts[:base_dir]
13
+ @@work_dir = opts[:work_dir]
14
+ @@log_dir = opts[:log_dir]
15
+ end
16
+
17
+ # instance methods
18
+
19
+ def initialize
20
+ @log = LogExecutor.instance
21
+ end
22
+
23
+ def home_path
24
+ Pathname.new(ENV['HOME'])
25
+ end
26
+
27
+ def open
28
+ @current_path = work_path
29
+ end
30
+
31
+ def open_messages
32
+ ["enter workdir: #{work_path}"]
33
+ end
34
+
35
+ def close
36
+ end
37
+
38
+ def close_messages
39
+ ["leave workdir: #{work_path}"]
40
+ end
41
+
42
+ def cd(d='')
43
+ if d==''
44
+ @current_path = home_path
45
+ else
46
+ pn = Pathname(d.sub(/^\$HOME\b/,ENV['HOME']))
47
+ if pn.relative?
48
+ pn = @current_path + pn
49
+ end
50
+ if !Dir.exist?(pn)
51
+ raise "Cannot chdir to #{pn}"
52
+ end
53
+ @current_path = pn.realpath
54
+ end
55
+ end
56
+
57
+ def current
58
+ @current_path.to_s
59
+ end
60
+
61
+ def work_path
62
+ home_path + @@work_dir
63
+ end
64
+
65
+ def work_dir
66
+ work_path.to_s
67
+ end
68
+
69
+ def log_path
70
+ work_path + @@log_dir
71
+ end
72
+
73
+ end
74
+ end
@@ -0,0 +1,14 @@
1
+ require "thread"
2
+ require "fileutils"
3
+
4
+ ncore = Marshal.load($stdin)
5
+ opts = Marshal.load($stdin)
6
+ begin
7
+ dc = Pwrake.const_get(opts[:shared_directory])
8
+ dc.init(opts)
9
+ Pwrake::Invoker.new(dc, ncore, opts).run
10
+ rescue => exc
11
+ log = Pwrake::LogExecutor.instance
12
+ log.error exc
13
+ log.error exc.backtrace.join("\n")
14
+ end
@@ -0,0 +1,59 @@
1
+ require "singleton"
2
+
3
+ module Pwrake
4
+
5
+ class Writer
6
+ include Singleton
7
+
8
+ def initialize
9
+ @out = $stdout
10
+ @mutex = Mutex.new
11
+ pipe_in, pipe_out = IO.pipe
12
+ Thread.new(pipe_in,"log:") do |pin,pre|
13
+ while s = pin.gets
14
+ s.chomp!
15
+ @out.puts pre+s
16
+ end
17
+ end
18
+ $stderr = pipe_out
19
+ end
20
+
21
+ def add_logger(log)
22
+ @log = log
23
+ end
24
+
25
+ def puts(s)
26
+ begin
27
+ @mutex.synchronize do
28
+ @out.print s+"\n"
29
+ end
30
+ @out.flush
31
+ rescue Errno::EPIPE
32
+ end
33
+ @log.info "<#{s}" if @log
34
+ end
35
+
36
+ def print(s)
37
+ begin
38
+ @mutex.synchronize do
39
+ @out.print s
40
+ end
41
+ @out.flush
42
+ rescue Errno::EPIPE
43
+ end
44
+ @log.info "<#{s}" if @log
45
+ end
46
+
47
+ def flush
48
+ begin
49
+ @out.flush
50
+ rescue
51
+ end
52
+ end
53
+
54
+ def dputs(s)
55
+ puts(s) if $DEBUG
56
+ end
57
+
58
+ end
59
+ end
data/setup.rb CHANGED
@@ -1,1585 +1,1295 @@
1
+ #!/usr/bin/env ruby
2
+ # Setup.rb v5.1.0
1
3
  #
2
- # setup.rb
4
+ # This is a stand-alone bundle of the setup.rb application.
5
+ # You can place it in your projects script/ directory, or
6
+ # call it 'setup.rb' and place it in your project's
7
+ # root directory (just like old times).
3
8
  #
4
- # Copyright (c) 2000-2005 Minero Aoki
9
+ # NOTE: As of version 5.1.0 this bundled rendition is also
10
+ # being used for the bin/setup.rb exe. Rather than the previous:
5
11
  #
6
- # This program is free software.
7
- # You can distribute/modify this program under the terms of
8
- # the GNU LGPL, Lesser General Public License version 2.1.
12
+ # require 'setup/command'
13
+ # Setup::Command.run
9
14
  #
10
-
11
- unless Enumerable.method_defined?(:map) # Ruby 1.4.6
12
- module Enumerable
13
- alias map collect
14
- end
15
+ # By doing so, +rvm+ should be able to use it across all rubies
16
+ # without issue and without needing to install it for each.
17
+ require 'yaml'
18
+ module Setup
19
+ VERSION = '5.2.0' #:erb: VERSION = '<%= version %>'
15
20
  end
16
-
17
- unless File.respond_to?(:read) # Ruby 1.6
18
- def File.read(fname)
19
- open(fname) {|f|
20
- return f.read
21
- }
21
+ class << File #:nodoc: all
22
+ unless respond_to?(:read) # Ruby 1.6 and less
23
+ def read(fname)
24
+ open(fname){ |f| return f.read }
25
+ end
26
+ end
27
+ def dir?(path)
28
+ directory?((path[-1,1] == '/') ? path : path + '/')
22
29
  end
23
30
  end
24
-
25
31
  unless Errno.const_defined?(:ENOTEMPTY) # Windows?
26
- module Errno
27
- class ENOTEMPTY
28
- # We do not raise this exception, implementation is not needed.
32
+ module Errno #:nodoc:
33
+ class ENOTEMPTY #:nodoc:
29
34
  end
30
35
  end
31
36
  end
32
-
33
- def File.binread(fname)
34
- open(fname, 'rb') {|f|
35
- return f.read
36
- }
37
+ module Setup
38
+ META_EXTENSION_DIR = '.setup'
39
+ FILETYPES = %w( bin lib ext data etc man doc )
40
+ INSTALL_RECORD = 'SetupReceipt'
41
+ CONFIG_FILE = 'SetupConfig'
37
42
  end
38
-
39
- # for corrupted Windows' stat(2)
40
- def File.dir?(path)
41
- File.directory?((path[-1,1] == '/') ? path : path + '/')
42
- end
43
-
44
-
45
- class ConfigTable
46
-
47
- include Enumerable
48
-
49
- def initialize(rbconfig)
50
- @rbconfig = rbconfig
51
- @items = []
52
- @table = {}
53
- # options
54
- @install_prefix = nil
55
- @config_opt = nil
56
- @verbose = true
57
- @no_harm = false
58
- end
59
-
60
- attr_accessor :install_prefix
61
- attr_accessor :config_opt
62
-
63
- attr_writer :verbose
64
-
65
- def verbose?
66
- @verbose
67
- end
68
-
69
- attr_writer :no_harm
70
-
71
- def no_harm?
72
- @no_harm
73
- end
74
-
75
- def [](key)
76
- lookup(key).resolve(self)
77
- end
78
-
79
- def []=(key, val)
80
- lookup(key).set val
81
- end
82
-
83
- def names
84
- @items.map {|i| i.name }
85
- end
86
-
87
- def each(&block)
88
- @items.each(&block)
89
- end
90
-
91
- def key?(name)
92
- @table.key?(name)
93
- end
94
-
95
- def lookup(name)
96
- @table[name] or setup_rb_error "no such config item: #{name}"
97
- end
98
-
99
- def add(item)
100
- @items.push item
101
- @table[item.name] = item
102
- end
103
-
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
109
- end
110
-
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
115
- end
116
-
117
- def savefile
118
- '.config'
119
- end
120
-
121
- def load_savefile
122
- begin
123
- File.foreach(savefile()) do |line|
124
- k, v = *line.split(/=/, 2)
125
- self[k] = v.strip
43
+ module Setup
44
+ class Project
45
+ ROOT_MARKER = '{.index,setup.rb,.setup,lib/}'
46
+ def initialize
47
+ @dotindex_file = find('.index')
48
+ @dotindex = YAML.load_file(@dotindex_file) if @dotindex_file
49
+ @name = nil
50
+ @version = nil
51
+ @loadpath = ['lib']
52
+ if @dotindex
53
+ @name = @dotindex['name']
54
+ @version = @dotindex['version']
55
+ @loadpath = (@dotindex['paths'] || {})['load']
56
+ else
57
+ if file = find('.setup/name')
58
+ @name = File.read(file).strip
59
+ end
60
+ if file = find('.setup/version')
61
+ @version = File.read(file).strip
62
+ end
63
+ if file = find('.setup/loadpath')
64
+ @loadpath = File.read(file).strip
65
+ end
126
66
  end
127
- rescue Errno::ENOENT
128
- setup_rb_error $!.message + "\n#{File.basename($0)} config first"
129
67
  end
130
- end
131
-
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
- }
139
- end
140
-
141
- def load_standard_entries
142
- standard_entries(@rbconfig).each do |ent|
143
- add ent
68
+ attr :dotindex
69
+ attr :name
70
+ attr :version
71
+ attr :loadpath
72
+ alias load_path loadpath
73
+ def rootdir
74
+ @rootdir ||= (
75
+ root = Dir.glob(File.join(Dir.pwd, ROOT_MARKER), File::FNM_CASEFOLD).first
76
+ if !root
77
+ raise Error, "not a project directory"
78
+ else
79
+ Dir.pwd
80
+ end
81
+ )
144
82
  end
145
- end
146
-
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
- }
191
-
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
197
-
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
83
+ def extconfs
84
+ @extconfs ||= Dir['ext/**/extconf.rb']
263
85
  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
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/
302
- end
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]
307
- end
308
-
309
- def dllext
310
- @rbconfig['DLEXT']
311
- end
312
-
313
- def value_config?(name)
314
- lookup(name).value?
315
- end
316
-
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
325
-
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?
337
- true
86
+ def extensions
87
+ @extensions ||= extconfs.collect{ |f| File.dirname(f) }
338
88
  end
339
-
340
- def value
341
- @value
89
+ def compiles?
90
+ !extensions.empty?
342
91
  end
343
-
344
- def resolve(table)
345
- @value.gsub(%r<\$([^/]+)>) { table[$1] }
92
+ def yardopts
93
+ Dir.glob(File.join(rootdir, '.yardopts')).first
346
94
  end
347
-
348
- def set(val)
349
- @value = check(val)
95
+ def document
96
+ Dir.glob(File.join(rootdir, '.document')).first
350
97
  end
351
-
352
- private
353
-
354
- def check(val)
355
- setup_rb_error "config: --#{name} requires argument" unless val
356
- val
98
+ def find(glob, flags=0)
99
+ case flags
100
+ when :casefold
101
+ flags = File::FNM_CASEFOLD
102
+ else
103
+ flags = flags.to_i
104
+ end
105
+ Dir.glob(File.join(rootdir, glob), flags).first
357
106
  end
358
107
  end
359
-
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'
108
+ end
109
+ module Setup
110
+ class Session
111
+ attr :options
112
+ def initialize(options={})
113
+ @options = options
114
+ self.io ||= StringIO.new # log instead ?
115
+ end
116
+ def io
117
+ @options[:io]
118
+ end
119
+ def io=(anyio)
120
+ @options[:io] = anyio
121
+ end
122
+ def trace?; @options[:trace]; end
123
+ def trace=(val)
124
+ @options[:trace] = val
125
+ end
126
+ def trial?; @options[:trial]; end
127
+ alias_method :dryrun?, :trial?
128
+ def trial=(val)
129
+ @options[:trial] = val
130
+ end
131
+ alias_method :dryrun=, :trial=
132
+ def quiet?; @options[:quiet]; end
133
+ def quiet=(val)
134
+ @options[:quiet] = val
135
+ end
136
+ def force?; @options[:force]; end
137
+ def force=(val)
138
+ @options[:force] = val
139
+ end
140
+ def compile?
141
+ configuration.compile? && project.compiles?
142
+ end
143
+ def all
144
+ config
145
+ compile
146
+ if configuration.test?
147
+ ok = test
148
+ exit 1 unless ok
149
+ end
150
+ install
151
+ end
152
+ def config
153
+ log_header('Preconfig')
154
+ if configuration.save_config
155
+ io.print "#{CONFIG_FILE} was saved. " unless quiet?
376
156
  else
377
- setup_rb_error "config: --#{@name} accepts only yes/no for argument"
157
+ io.print "#{CONFIG_FILE} is current. " unless quiet?
158
+ end
159
+ io.puts "Edit to customize configuration." unless quiet?
160
+ puts configuration if trace? && !quiet?
161
+ end
162
+ def compile
163
+ if compile?
164
+ log_header('Compile')
165
+ compiler.configure
166
+ compiler.compile
378
167
  end
379
168
  end
380
- end
381
-
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)
169
+ alias_method :make, :compile
170
+ alias_method :setup, :make
171
+ def install
172
+ log_header('Install')
173
+ installer.install
174
+ end
175
+ def test
176
+ return true unless tester.testable?
177
+ log_header('Test')
178
+ tester.test
179
+ end
180
+ def clean
181
+ log_header('Clean')
182
+ compiler.clean
183
+ end
184
+ def distclean
185
+ log_header('Distclean')
186
+ compiler.distclean
187
+ end
188
+ def uninstall
189
+ if !File.exist?(INSTALL_RECORD)
190
+ io.puts "Nothing is installed."
191
+ return
192
+ end
193
+ log_header('Uninstall')
194
+ uninstaller.uninstall
195
+ io.puts('Ok.')
392
196
  end
393
- end
394
-
395
- class ProgramItem < Item
396
- def config_type
397
- 'program'
197
+ def show
198
+ puts configuration
398
199
  end
399
- end
400
-
401
- class SelectItem < Item
402
- def initialize(name, selection, default, desc)
403
- super
404
- @ok = selection.split('/')
200
+ def project
201
+ @project ||= Project.new
405
202
  end
406
-
407
- def config_type
408
- 'select'
203
+ def configuration
204
+ @configuration ||= Configuration.new
409
205
  end
410
-
411
- private
412
-
413
- def check(val)
414
- unless @ok.include?(val.strip)
415
- setup_rb_error "config: use --#{@name}=#{@template} (#{val})"
206
+ def compiler
207
+ @compiler ||= Compiler.new(project, configuration, options)
208
+ end
209
+ def installer
210
+ @installer ||= Installer.new(project, configuration, options)
211
+ end
212
+ def tester
213
+ @tester ||= Tester.new(project, configuration, options)
214
+ end
215
+ def uninstaller
216
+ @uninstaller ||= Uninstaller.new(project, configuration, options)
217
+ end
218
+ def log_header(phase)
219
+ return if quiet?
220
+ if trial?
221
+ str = "#{phase.upcase} (trail run)"
222
+ else
223
+ str = "#{phase.upcase}"
416
224
  end
417
- val.strip
225
+ line = "- " * 35
226
+ line[0..str.size+3] = str
227
+ io.puts("\n- - #{line}\n\n")
418
228
  end
419
229
  end
420
-
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
230
+ end
231
+ module Setup
232
+ class Base
233
+ attr :project
234
+ attr :config
235
+ attr_accessor :trial
236
+ attr_accessor :trace
237
+ attr_accessor :quiet
238
+ attr_accessor :force
239
+ attr_accessor :io
240
+ def initialize(project, configuration, options={})
241
+ @project = project
242
+ @config = configuration
243
+ initialize_hooks
244
+ options.each do |k,v|
245
+ __send__("#{k}=", v) if respond_to?("#{k}=")
246
+ end
434
247
  end
435
-
436
- def resolve(table)
437
- setup_rb_error "$#{name()} wrongly used as option value"
248
+ def initialize_hooks
249
+ file = META_EXTENSION_DIR + "/#{self.class.name.downcase}.rb"
250
+ if File.exist?(file)
251
+ script = File.read(file)
252
+ (class << self; self; end).class_eval(script)
253
+ end
438
254
  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})"
255
+ def trial? ; @trial ; end
256
+ def trace? ; @trace ; end
257
+ def quiet? ; @quiet ; end
258
+ def force? ; @force ; end
259
+ def rootdir
260
+ project.rootdir
261
+ end
262
+ def bash(*args)
263
+ $stderr.puts args.join(' ') if trace?
264
+ system(*args) or raise RuntimeError, "system(#{args.map{|a| a.inspect }.join(' ')}) failed"
265
+ end
266
+ alias_method :command, :bash
267
+ def ruby(*args)
268
+ bash(config.rubyprog, *args)
269
+ end
270
+ def trace_off #:yield:
271
+ begin
272
+ save, @trace = trace?, false
273
+ yield
274
+ ensure
275
+ @trace = save
446
276
  end
447
- @action.call v, table
448
277
  end
449
- end
450
-
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
278
+ def rm_f(path)
279
+ io.puts "rm -f #{path}" if trace? or trial?
280
+ return if trial?
281
+ force_remove_file(path)
470
282
  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
283
+ def force_remove_file(path)
284
+ begin
285
+ remove_file(path)
286
+ rescue
287
+ end
529
288
  end
530
- end
531
-
532
- end # class ConfigTable
533
-
534
-
535
- # This module requires: #verbose?, #no_harm?
536
- module FileOperations
537
-
538
- def mkdir_p(dirname, prefix = nil)
539
- dirname = prefix + File.expand_path(dirname) if prefix
540
- $stderr.puts "mkdir -p #{dirname}" if verbose?
541
- return if no_harm?
542
-
543
- # Does not check '/', it's too abnormal.
544
- dirs = File.expand_path(dirname).split(%r<(?=/)>)
545
- if /\A[a-z]:\z/i =~ dirs[0]
546
- disk = dirs.shift
547
- dirs[0] = disk + dirs[0]
548
- end
549
- dirs.each_index do |idx|
550
- path = dirs[0..idx].join('')
551
- Dir.mkdir path unless File.dir?(path)
289
+ def remove_file(path)
290
+ File.chmod 0777, path
291
+ File.unlink(path)
292
+ end
293
+ def rmdir(path)
294
+ io.puts "rmdir #{path}" if trace? or trial?
295
+ return if trial?
296
+ Dir.rmdir(path)
552
297
  end
553
298
  end
554
-
555
- def rm_f(path)
556
- $stderr.puts "rm -f #{path}" if verbose?
557
- return if no_harm?
558
- force_remove_file path
559
- end
560
-
561
- def rm_rf(path)
562
- $stderr.puts "rm -rf #{path}" if verbose?
563
- return if no_harm?
564
- remove_tree path
299
+ class Error < StandardError
565
300
  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
301
+ end
302
+ module Setup
303
+ class Compiler < Base
304
+ def compiles?
305
+ !extdirs.empty?
306
+ end
307
+ def configure
308
+ extdirs.each do |dir|
309
+ Dir.chdir(dir) do
310
+ if File.exist?('extconf.rb') && !FileUtils.uptodate?('Makefile', ['extconf.rb'])
311
+ ruby("extconf.rb")
312
+ end
313
+ end
314
+ end
574
315
  end
575
- end
576
-
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
586
- else
587
- force_remove_file entpath
316
+ def compile
317
+ extdirs.each do |dir|
318
+ Dir.chdir(dir) do
319
+ make
320
+ end
588
321
  end
589
322
  end
590
- begin
591
- Dir.rmdir path
592
- rescue Errno::ENOTEMPTY
593
- # directory may not be empty
323
+ def clean
324
+ extdirs.each do |dir|
325
+ Dir.chdir(dir) do
326
+ make('clean')
327
+ end
328
+ end
594
329
  end
595
- end
596
-
597
- def move_file(src, dest)
598
- force_remove_file dest
599
- begin
600
- File.rename src, dest
601
- rescue
602
- File.open(dest, 'wb') {|f|
603
- f.write File.binread(src)
604
- }
605
- File.chmod File.stat(src).mode, dest
606
- File.unlink src
330
+ def distclean
331
+ extdirs.each do |dir|
332
+ Dir.chdir(dir) do
333
+ make('distclean')
334
+ end
335
+ end
607
336
  end
608
- end
609
-
610
- def force_remove_file(path)
611
- begin
612
- remove_file path
613
- rescue
337
+ def extdirs
338
+ Dir['ext/**/*/{MANIFEST,extconf.rb}'].map do |f|
339
+ File.dirname(f)
340
+ end.uniq
614
341
  end
615
- end
616
-
617
- def remove_file(path)
618
- File.chmod 0777, path
619
- File.unlink path
620
- end
621
-
622
- def install(from, dest, mode, prefix = nil)
623
- $stderr.puts "install #{from} #{dest}" if verbose?
624
- return if no_harm?
625
-
626
- realdest = prefix ? prefix + File.expand_path(dest) : dest
627
- realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest)
628
- str = File.binread(from)
629
- if diff?(str, realdest)
630
- verbose_off {
631
- rm_f realdest if File.exist?(realdest)
632
- }
633
- File.open(realdest, 'wb') {|f|
634
- f.write str
635
- }
636
- File.chmod mode, realdest
637
-
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
- }
342
+ def make(task=nil)
343
+ return unless File.exist?('Makefile')
344
+ bash(*[config.makeprog, task].compact)
645
345
  end
646
346
  end
647
-
648
- def diff?(new_content, path)
649
- return true unless File.exist?(path)
650
- new_content != File.binread(path)
651
- end
652
-
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"
657
- end
658
-
659
- def ruby(*args)
660
- command config('rubyprog'), *args
661
- end
662
-
663
- def make(task = nil)
664
- command(*[config('makeprog'), task].compact)
665
- end
666
-
667
- def extdir?(dir)
668
- File.exist?("#{dir}/MANIFEST") or File.exist?("#{dir}/extconf.rb")
669
- end
670
-
671
- def files_of(dir)
672
- Dir.open(dir) {|d|
673
- return d.select {|ent| File.file?("#{dir}/#{ent}") }
674
- }
675
- end
676
-
677
- DIR_REJECT = %w( . .. CVS SCCS RCS CVS.adm .svn )
678
-
679
- def directories_of(dir)
680
- Dir.open(dir) {|d|
681
- return d.select {|ent| File.dir?("#{dir}/#{ent}") } - DIR_REJECT
682
- }
683
- end
684
-
685
347
  end
686
-
687
-
688
- # This module requires: #srcdir_root, #objdir_root, #relpath
689
- module HookScriptAPI
690
-
691
- def get_config(key)
692
- @config[key]
693
- end
694
-
695
- alias config get_config
696
-
697
- # obsolete: use metaconfig to change configuration
698
- def set_config(key, val)
699
- @config[key] = val
700
- end
701
-
702
- #
703
- # srcdir/objdir (works only in the package directory)
704
- #
705
-
706
- def curr_srcdir
707
- "#{srcdir_root()}/#{relpath()}"
708
- end
709
-
710
- def curr_objdir
711
- "#{objdir_root()}/#{relpath()}"
712
- end
713
-
714
- def srcfile(path)
715
- "#{curr_srcdir()}/#{path}"
716
- end
717
-
718
- def srcexist?(path)
719
- File.exist?(srcfile(path))
720
- end
721
-
722
- def srcdirectory?(path)
723
- File.dir?(srcfile(path))
724
- end
725
-
726
- def srcfile?(path)
727
- File.file?(srcfile(path))
728
- end
729
-
730
- def srcentries(path = '.')
731
- Dir.open("#{curr_srcdir()}/#{path}") {|d|
732
- return d.to_a - %w(. ..)
733
- }
734
- end
735
-
736
- def srcfiles(path = '.')
737
- srcentries(path).select {|fname|
738
- File.file?(File.join(curr_srcdir(), path, fname))
739
- }
740
- end
741
-
742
- def srcdirectories(path = '.')
743
- srcentries(path).select {|fname|
744
- File.dir?(File.join(curr_srcdir(), path, fname))
745
- }
746
- end
747
-
748
- end
749
-
750
-
751
- class ToplevelInstaller
752
-
753
- Version = '3.4.1'
754
- Copyright = 'Copyright (c) 2000-2005 Minero Aoki'
755
-
756
- TASKS = [
757
- [ 'all', 'do config, setup, then install' ],
758
- [ 'config', 'saves your configurations' ],
759
- [ 'show', 'shows current configuration' ],
760
- [ 'setup', 'compiles ruby extentions and others' ],
761
- [ 'install', 'installs files' ],
762
- [ 'test', 'run all tests in test/' ],
763
- [ 'clean', "does `make clean' for each extention" ],
764
- [ 'distclean',"does `make distclean' for each extention" ]
765
- ]
766
-
767
- def ToplevelInstaller.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
774
- end
775
-
776
- def ToplevelInstaller.multipackage?
777
- File.dir?(File.dirname($0) + '/packages')
778
- end
779
-
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
790
-
791
- def initialize(ardir_root, config)
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]
800
- end
801
-
802
- def inspect
803
- "#<#{self.class} #{__id__()}>"
804
- end
805
-
806
- def invoke
807
- run_metaconfigs
808
- case task = parsearg_global()
809
- when nil, 'all'
810
- parsearg_config
811
- init_installers
812
- exec_config
813
- exec_setup
814
- exec_install
815
- else
816
- case task
817
- when 'config', 'test'
818
- ;
819
- when 'clean', 'distclean'
820
- @config.load_savefile if File.exist?(@config.savefile)
348
+ require 'rbconfig'
349
+ require 'fileutils'
350
+ require 'erb'
351
+ require 'yaml'
352
+ require 'shellwords'
353
+ module Setup
354
+ class Configuration
355
+ RBCONFIG = ::RbConfig::CONFIG
356
+ META_CONFIG_FILE = META_EXTENSION_DIR + '/metaconfig.rb'
357
+ def self.options
358
+ @@options ||= []
359
+ end
360
+ def self.option(name, *args) #type, description)
361
+ options << [name.to_s, *args] #type, description]
362
+ attr_accessor(name)
363
+ end
364
+ option :prefix , :path, 'path prefix of target environment'
365
+ option :bindir , :path, 'directory for commands'
366
+ option :libdir , :path, 'directory for libraries'
367
+ option :datadir , :path, 'directory for shared data'
368
+ option :mandir , :path, 'directory for man pages'
369
+ option :docdir , :path, 'directory for documentation'
370
+ option :rbdir , :path, 'directory for ruby scripts'
371
+ option :sodir , :path, 'directory for ruby extentions'
372
+ option :sysconfdir , :path, 'directory for system configuration files'
373
+ option :localstatedir , :path, 'directory for local state data'
374
+ option :libruby , :path, 'directory for ruby libraries'
375
+ option :librubyver , :path, 'directory for standard ruby libraries'
376
+ option :librubyverarch , :path, 'directory for standard ruby extensions'
377
+ option :siteruby , :path, 'directory for version-independent aux ruby libraries'
378
+ option :siterubyver , :path, 'directory for aux ruby libraries'
379
+ option :siterubyverarch , :path, 'directory for aux ruby binaries'
380
+ option :rubypath , :prog, 'path to set to #! line'
381
+ option :rubyprog , :prog, 'ruby program used for installation'
382
+ option :makeprog , :prog, 'make program to compile ruby extentions'
383
+ option :extconfopt , :opts, 'options to pass-thru to extconf.rb'
384
+ option :shebang , :pick, 'shebang line (#!) editing mode (all,ruby,never)'
385
+ option :no_test, :t , :bool, 'run pre-installation tests'
386
+ option :no_doc , :bool, 'install doc/ directory'
387
+ option :no_ext , :bool, 'compile/install ruby extentions'
388
+ option :install_prefix , :path, 'install to alternate root location'
389
+ option :root , :path, 'install to alternate root location'
390
+ option :installdirs , :pick, 'install location mode (site,std,home)' #, local)
391
+ option :type , :pick, 'install location mode (site,std,home)'
392
+ ::RbConfig::CONFIG.each do |key,val|
393
+ next if key == "configure_args"
394
+ name = key.to_s.downcase
395
+ define_method(name){ val }
396
+ end
397
+ config_args = Shellwords.shellwords(::RbConfig::CONFIG["configure_args"])
398
+ config_args.each do |ent|
399
+ if ent.index("=")
400
+ key, val = *ent.split("=")
821
401
  else
822
- @config.load_savefile
402
+ key, val = ent, true
403
+ end
404
+ name = key.downcase
405
+ name = name.sub(/^--/,'')
406
+ name = name.gsub(/-/,'_')
407
+ define_method(name){ val }
408
+ end
409
+ def options
410
+ self.class.options
411
+ end
412
+ def initialize(values={})
413
+ initialize_metaconfig
414
+ initialize_defaults
415
+ initialize_environment
416
+ initialize_configfile unless values[:reset]
417
+ values.each{ |k,v| __send__("#{k}=", v) }
418
+ yield(self) if block_given?
419
+ end
420
+ def initialize_metaconfig
421
+ if File.exist?(META_CONFIG_FILE)
422
+ script = File.read(META_CONFIG_FILE)
423
+ (class << self; self; end).class_eval(script)
823
424
  end
824
- __send__ "parsearg_#{task}"
825
- init_installers
826
- __send__ "exec_#{task}"
827
425
  end
828
- end
829
-
830
- def run_metaconfigs
831
- @config.load_script "#{@ardir}/metaconfig"
832
- end
833
-
834
- def init_installers
835
- @installer = Installer.new(@config, @ardir, File.expand_path('.'))
836
- end
837
-
838
- #
839
- # Hook Script API bases
840
- #
841
-
842
- def srcdir_root
843
- @ardir
844
- end
845
-
846
- def objdir_root
847
- '.'
848
- end
849
-
850
- def relpath
851
- '.'
852
- end
853
-
854
- #
855
- # Option Parsing
856
- #
857
-
858
- def parsearg_global
859
- while arg = ARGV.shift
860
- case arg
861
- when /\A\w+\z/
862
- setup_rb_error "invalid task: #{arg}" unless valid_task?(arg)
863
- return arg
864
- when '-q', '--quiet'
865
- @config.verbose = false
866
- when '--verbose'
867
- @config.verbose = true
868
- when '--help'
869
- print_usage $stdout
870
- exit 0
871
- when '--version'
872
- puts "#{File.basename($0)} version #{Version}"
873
- exit 0
874
- when '--copyright'
875
- puts Copyright
876
- exit 0
877
- else
878
- setup_rb_error "unknown global option '#{arg}'"
426
+ def initialize_defaults
427
+ self.type = 'site'
428
+ self.no_ri = true
429
+ self.no_test = true
430
+ self.no_doc = true
431
+ self.no_ext = false
432
+ end
433
+ def initialize_environment
434
+ options.each do |name, *args|
435
+ if value = ENV["RUBYSETUP_#{name.to_s.upcase}"]
436
+ __send__("#{name}=", value)
437
+ end
879
438
  end
880
439
  end
881
- nil
882
- end
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
891
-
892
- def parsearg_no_options
893
- unless ARGV.empty?
894
- task = caller(0).first.slice(%r<`parsearg_(\w+)'>, 1)
895
- setup_rb_error "#{task}: unknown options: #{ARGV.join(' ')}"
440
+ def initialize_configfile
441
+ if exist?
442
+ erb = ERB.new(File.read(CONFIG_FILE))
443
+ txt = erb.result(binding)
444
+ dat = YAML.load(txt)
445
+ dat.each do |k, v|
446
+ next if 'type' == k
447
+ next if 'installdirs' == k
448
+ k = k.gsub('-','_')
449
+ __send__("#{k}=", v)
450
+ end
451
+ if dat['type']
452
+ self.type = dat['type']
453
+ end
454
+ if dat['installdirs']
455
+ self.installdirs = dat['installdirs']
456
+ end
457
+ end
896
458
  end
897
- end
898
-
899
- alias parsearg_show parsearg_no_options
900
- alias parsearg_setup parsearg_no_options
901
- alias parsearg_test parsearg_no_options
902
- alias parsearg_clean parsearg_no_options
903
- alias parsearg_distclean parsearg_no_options
904
-
905
- def parsearg_config
906
- evalopt = []
907
- set = []
908
- @config.config_opt = []
909
- while i = ARGV.shift
910
- if /\A--?\z/ =~ i
911
- @config.config_opt = ARGV.dup
912
- break
913
- end
914
- name, value = *@config.parse_opt(i)
915
- if @config.value_config?(name)
916
- @config[name] = value
459
+ attr_accessor :reset
460
+ def base_bindir
461
+ @base_bindir ||= subprefix('bindir')
462
+ end
463
+ def base_libdir
464
+ @base_libdir ||= subprefix('libdir')
465
+ end
466
+ def base_datadir
467
+ @base_datadir ||= subprefix('datadir')
468
+ end
469
+ def base_mandir
470
+ @base_mandir ||= subprefix('mandir')
471
+ end
472
+ def base_docdir
473
+ @base_docdir || File.dirname(subprefix('docdir'))
474
+ end
475
+ def base_rubylibdir
476
+ @rubylibdir ||= subprefix('rubylibdir')
477
+ end
478
+ def base_rubyarchdir
479
+ @base_rubyarchdir ||= subprefix('archdir')
480
+ end
481
+ def base_sysconfdir
482
+ @base_sysconfdir ||= subprefix('sysconfdir')
483
+ end
484
+ def base_localstatedir
485
+ @base_localstatedir ||= subprefix('localstatedir')
486
+ end
487
+ def type
488
+ @type ||= 'site'
489
+ end
490
+ def type=(val)
491
+ @type = val
492
+ case val.to_s
493
+ when 'std', 'ruby'
494
+ @rbdir = librubyver #'$librubyver'
495
+ @sodir = librubyverarch #'$librubyverarch'
496
+ when 'site'
497
+ @rbdir = siterubyver #'$siterubyver'
498
+ @sodir = siterubyverarch #'$siterubyverarch'
499
+ when 'home'
500
+ self.prefix = File.join(home, '.local') # TODO: Use XDG
501
+ @rbdir = nil #'$libdir/ruby'
502
+ @sodir = nil #'$libdir/ruby'
917
503
  else
918
- evalopt.push [name, value]
504
+ raise Error, "bad config: use type=(std|site|home) [#{val}]"
919
505
  end
920
- set.push name
921
506
  end
922
- evalopt.each do |name, value|
923
- @config.lookup(name).evaluate value, @config
507
+ alias_method :installdirs, :type
508
+ alias_method :installdirs=, :type=
509
+ alias_method :install_prefix, :root
510
+ alias_method :install_prefix=, :root=
511
+ def prefix
512
+ @prefix ||= RBCONFIG['prefix']
924
513
  end
925
- # Check if configuration is valid
926
- set.each do |n|
927
- @config[n] if @config.value_config?(n)
514
+ def prefix=(path)
515
+ @prefix = pathname(path)
928
516
  end
929
- end
930
-
931
- def parsearg_install
932
- @config.no_harm = false
933
- @config.install_prefix = ''
934
- while a = ARGV.shift
935
- case a
936
- when '--no-harm'
937
- @config.no_harm = true
938
- when /\A--prefix=/
939
- path = a.split(/=/, 2)[1]
940
- path = File.expand_path(path) unless path[0,1] == '/'
941
- @config.install_prefix = path
517
+ def libruby
518
+ @libruby ||= RBCONFIG['prefix'] + "/lib/ruby"
519
+ end
520
+ def libruby=(path)
521
+ path = pathname(path)
522
+ @librubyver = librubyver.sub(libruby, path)
523
+ @librubyverarch = librubyverarch.sub(libruby, path)
524
+ @libruby = path
525
+ end
526
+ def librubyver
527
+ @librubyver ||= RBCONFIG['rubylibdir']
528
+ end
529
+ def librubyver=(path)
530
+ @librubyver = pathname(path)
531
+ end
532
+ def librubyverarch
533
+ @librubyverarch ||= RBCONFIG['archdir']
534
+ end
535
+ def librubyverarch=(path)
536
+ @librubyverarch = pathname(path)
537
+ end
538
+ def siteruby
539
+ @siteruby ||= RBCONFIG['sitedir']
540
+ end
541
+ def siteruby=(path)
542
+ path = pathname(path)
543
+ @siterubyver = siterubyver.sub(siteruby, path)
544
+ @siterubyverarch = siterubyverarch.sub(siteruby, path)
545
+ @siteruby = path
546
+ end
547
+ def siterubyver
548
+ @siterubyver ||= RBCONFIG['sitelibdir']
549
+ end
550
+ def siterubyver=(path)
551
+ @siterubyver = pathname(path)
552
+ end
553
+ def siterubyverarch
554
+ @siterubyverarch ||= RBCONFIG['sitearchdir']
555
+ end
556
+ def siterubyverarch=(path)
557
+ @siterubyverarch = pathname(path)
558
+ end
559
+ def bindir
560
+ @bindir || File.join(prefix, base_bindir)
561
+ end
562
+ def bindir=(path)
563
+ @bindir = pathname(path)
564
+ end
565
+ def libdir
566
+ @libdir || File.join(prefix, base_libdir)
567
+ end
568
+ def libdir=(path)
569
+ @libdir = pathname(path)
570
+ end
571
+ def datadir
572
+ @datadir || File.join(prefix, base_datadir)
573
+ end
574
+ def datadir=(path)
575
+ @datadir = pathname(path)
576
+ end
577
+ def mandir
578
+ @mandir || File.join(prefix, base_mandir)
579
+ end
580
+ def mandir=(path)
581
+ @mandir = pathname(path)
582
+ end
583
+ def docdir
584
+ @docdir || File.join(prefix, base_docdir)
585
+ end
586
+ def docdir=(path)
587
+ @docdir = pathname(path)
588
+ end
589
+ def rbdir
590
+ @rbdir || File.join(prefix, base_rubylibdir)
591
+ end
592
+ def sodir
593
+ @sodir || File.join(prefix, base_rubyarchdir)
594
+ end
595
+ def sysconfdir
596
+ @sysconfdir ||= base_sysconfdir
597
+ end
598
+ def sysconfdir=(path)
599
+ @sysconfdir = pathname(path)
600
+ end
601
+ def localstatedir
602
+ @localstatedir ||= base_localstatedir
603
+ end
604
+ def localstatedir=(path)
605
+ @localstatedir = pathname(path)
606
+ end
607
+ def rubypath
608
+ @rubypath ||= File.join(RBCONFIG['bindir'], RBCONFIG['ruby_install_name'] + RBCONFIG['EXEEXT'])
609
+ end
610
+ def rubypath=(path)
611
+ @rubypath = pathname(path)
612
+ end
613
+ def rubyprog
614
+ @rubyprog || rubypath
615
+ end
616
+ def rubyprog=(command)
617
+ @rubyprog = command
618
+ end
619
+ def makeprog
620
+ @makeprog ||= (
621
+ if arg = RBCONFIG['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg }
622
+ arg.sub(/'/, '').split(/=/, 2)[1]
623
+ else
624
+ 'make'
625
+ end
626
+ )
627
+ end
628
+ def makeprog=(command)
629
+ @makeprog = command
630
+ end
631
+ def extconfopt
632
+ @extconfopt ||= ''
633
+ end
634
+ def extconfopt=(string)
635
+ @extconfopt = string
636
+ end
637
+ def shebang
638
+ @shebang ||= 'ruby'
639
+ end
640
+ def shebang=(val)
641
+ if %w(all ruby never).include?(val)
642
+ @shebang = val
942
643
  else
943
- setup_rb_error "install: unknown option #{a}"
644
+ raise Error, "bad config: use SHEBANG=(all|ruby|never) [#{val}]"
944
645
  end
945
646
  end
946
- end
947
-
948
- def print_usage(out)
949
- out.puts 'Typical Installation Procedure:'
950
- out.puts " $ ruby #{File.basename $0} config"
951
- out.puts " $ ruby #{File.basename $0} setup"
952
- out.puts " # ruby #{File.basename $0} install (may require root privilege)"
953
- out.puts
954
- out.puts 'Detailed Usage:'
955
- out.puts " ruby #{File.basename $0} <global option>"
956
- out.puts " ruby #{File.basename $0} [<global options>] <task> [<task options>]"
957
-
958
- fmt = " %-24s %s\n"
959
- out.puts
960
- out.puts 'Global options:'
961
- out.printf fmt, '-q,--quiet', 'suppress message outputs'
962
- out.printf fmt, ' --verbose', 'output messages verbosely'
963
- out.printf fmt, ' --help', 'print this message'
964
- out.printf fmt, ' --version', 'print version and quit'
965
- out.printf fmt, ' --copyright', 'print copyright and quit'
966
- out.puts
967
- out.puts 'Tasks:'
968
- TASKS.each do |name, desc|
969
- out.printf fmt, name, desc
970
- end
971
-
972
- fmt = " %-24s %s [%s]\n"
973
- out.puts
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
977
- end
978
- out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',"running ruby's"
979
- out.puts
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', ''
983
- out.puts
984
- end
985
-
986
- #
987
- # Task Handlers
988
- #
989
-
990
- def exec_config
991
- @installer.exec_config
992
- @config.save # must be final
993
- end
994
-
995
- def exec_setup
996
- @installer.exec_setup
997
- end
998
-
999
- def exec_install
1000
- @installer.exec_install
1001
- end
1002
-
1003
- def exec_test
1004
- @installer.exec_test
1005
- end
1006
-
1007
- def exec_show
1008
- @config.each do |i|
1009
- printf "%-20s %s\n", i.name, i.value if i.value?
647
+ def no_ext
648
+ @no_ext
1010
649
  end
1011
- end
1012
-
1013
- def exec_clean
1014
- @installer.exec_clean
1015
- end
1016
-
1017
- def exec_distclean
1018
- @installer.exec_distclean
1019
- end
1020
-
1021
- end # class ToplevelInstaller
1022
-
1023
-
1024
- class ToplevelInstallerMulti < ToplevelInstaller
1025
-
1026
- include FileOperations
1027
-
1028
- def initialize(ardir_root, config)
1029
- super
1030
- @packages = directories_of("#{@ardir}/packages")
1031
- raise 'no package exists' if @packages.empty?
1032
- @root_installer = Installer.new(@config, @ardir, File.expand_path('.'))
1033
- end
1034
-
1035
- def run_metaconfigs
1036
- @config.load_script "#{@ardir}/metaconfig", self
1037
- @packages.each do |name|
1038
- @config.load_script "#{@ardir}/packages/#{name}/metaconfig"
650
+ def no_ext=(val)
651
+ @no_ext = boolean(val)
1039
652
  end
1040
- end
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
-
1053
- def init_installers
1054
- @installers = {}
1055
- @packages.each do |pack|
1056
- @installers[pack] = Installer.new(@config,
1057
- "#{@ardir}/packages/#{pack}",
1058
- "packages/#{pack}")
1059
- end
1060
- with = extract_selection(config('with'))
1061
- without = extract_selection(config('without'))
1062
- @selected = @installers.keys.select {|name|
1063
- (with.empty? or with.include?(name)) \
1064
- and not without.include?(name)
1065
- }
1066
- end
1067
-
1068
- def extract_selection(list)
1069
- a = list.split(/,/)
1070
- a.each do |name|
1071
- setup_rb_error "no such package: #{name}" unless @installers.key?(name)
653
+ def no_test
654
+ @no_test
1072
655
  end
1073
- a
1074
- end
1075
-
1076
- def print_usage(f)
1077
- super
1078
- f.puts 'Inluded packages:'
1079
- f.puts ' ' + @packages.sort.join(' ')
1080
- f.puts
1081
- end
1082
-
1083
- #
1084
- # Task Handlers
1085
- #
1086
-
1087
- def exec_config
1088
- run_hook 'pre-config'
1089
- each_selected_installers {|inst| inst.exec_config }
1090
- run_hook 'post-config'
1091
- @config.save # must be final
1092
- end
1093
-
1094
- def exec_setup
1095
- run_hook 'pre-setup'
1096
- each_selected_installers {|inst| inst.exec_setup }
1097
- run_hook 'post-setup'
1098
- end
1099
-
1100
- def exec_install
1101
- run_hook 'pre-install'
1102
- each_selected_installers {|inst| inst.exec_install }
1103
- run_hook 'post-install'
1104
- end
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
-
1112
- def exec_clean
1113
- rm_f @config.savefile
1114
- run_hook 'pre-clean'
1115
- each_selected_installers {|inst| inst.exec_clean }
1116
- run_hook 'post-clean'
1117
- end
1118
-
1119
- def exec_distclean
1120
- rm_f @config.savefile
1121
- run_hook 'pre-distclean'
1122
- each_selected_installers {|inst| inst.exec_distclean }
1123
- run_hook 'post-distclean'
1124
- end
1125
-
1126
- #
1127
- # lib
1128
- #
1129
-
1130
- def each_selected_installers
1131
- Dir.mkdir 'packages' unless File.dir?('packages')
1132
- @selected.each do |pack|
1133
- $stderr.puts "Processing the package `#{pack}' ..." if verbose?
1134
- Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}")
1135
- Dir.chdir "packages/#{pack}"
1136
- yield @installers[pack]
1137
- Dir.chdir '../..'
656
+ def no_test=(val)
657
+ @no_test = boolean(val)
1138
658
  end
1139
- end
1140
-
1141
- def run_hook(id)
1142
- @root_installer.run_hook id
1143
- end
1144
-
1145
- # module FileOperations requires this
1146
- def verbose?
1147
- @config.verbose?
1148
- end
1149
-
1150
- # module FileOperations requires this
1151
- def no_harm?
1152
- @config.no_harm?
1153
- end
1154
-
1155
- end # class ToplevelInstallerMulti
1156
-
1157
-
1158
- class Installer
1159
-
1160
- FILETYPES = %w( bin lib ext data conf man )
1161
-
1162
- include FileOperations
1163
- include HookScriptAPI
1164
-
1165
- def initialize(config, srcroot, objroot)
1166
- @config = config
1167
- @srcdir = File.expand_path(srcroot)
1168
- @objdir = File.expand_path(objroot)
1169
- @currdir = '.'
1170
- end
1171
-
1172
- def inspect
1173
- "#<#{self.class} #{File.basename(@srcdir)}>"
1174
- end
1175
-
1176
- def noop(rel)
1177
- end
1178
-
1179
- #
1180
- # Hook Script API base methods
1181
- #
1182
-
1183
- def srcdir_root
1184
- @srcdir
1185
- end
1186
-
1187
- def objdir_root
1188
- @objdir
1189
- end
1190
-
1191
- def relpath
1192
- @currdir
1193
- end
1194
-
1195
- #
1196
- # Config Access
1197
- #
1198
-
1199
- # module FileOperations requires this
1200
- def verbose?
1201
- @config.verbose?
1202
- end
1203
-
1204
- # module FileOperations requires this
1205
- def no_harm?
1206
- @config.no_harm?
1207
- end
1208
-
1209
- def verbose_off
1210
- begin
1211
- save, @config.verbose = @config.verbose?, false
1212
- yield
1213
- ensure
1214
- @config.verbose = save
659
+ def no_doc
660
+ @no_doc
1215
661
  end
1216
- end
1217
-
1218
- #
1219
- # TASK config
1220
- #
1221
-
1222
- def exec_config
1223
- exec_task_traverse 'config'
1224
- end
1225
-
1226
- alias config_dir_bin noop
1227
- alias config_dir_lib noop
1228
-
1229
- def config_dir_ext(rel)
1230
- extconf if extdir?(curr_srcdir())
1231
- end
1232
-
1233
- alias config_dir_data noop
1234
- alias config_dir_conf noop
1235
- alias config_dir_man noop
1236
-
1237
- def extconf
1238
- ruby "#{curr_srcdir()}/extconf.rb", *@config.config_opt
1239
- end
1240
-
1241
- #
1242
- # TASK setup
1243
- #
1244
-
1245
- def exec_setup
1246
- exec_task_traverse 'setup'
1247
- end
1248
-
1249
- def setup_dir_bin(rel)
1250
- files_of(curr_srcdir()).each do |fname|
1251
- update_shebang_line "#{curr_srcdir()}/#{fname}"
662
+ def no_doc=(val)
663
+ @no_doc = boolean(val)
1252
664
  end
1253
- end
1254
-
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)
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'))
665
+ def no_ri
666
+ @no_ri
1295
667
  end
1296
- end
1297
-
1298
- def open_atomic_writer(path, &block)
1299
- tmpfile = File.basename(path) + '.tmp'
1300
- begin
1301
- File.open(tmpfile, 'wb', &block)
1302
- File.rename tmpfile, File.basename(path)
1303
- ensure
1304
- File.unlink tmpfile if File.exist?(tmpfile)
668
+ def no_ri=(val)
669
+ @no_ri = boolean(val)
670
+ end
671
+ def compile?
672
+ !no_ext
673
+ end
674
+ def test?
675
+ !no_test
676
+ end
677
+ def doc?
678
+ !no_doc
679
+ end
680
+ def to_h
681
+ h = {}
682
+ options.each do |name, *args|
683
+ h[name.to_s] = __send__(name)
684
+ end
685
+ h
1305
686
  end
1306
- end
1307
-
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
1317
-
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
1330
-
1331
687
  def to_s
1332
- "#! #{@cmd}" + (@args.empty? ? '' : " #{@args.join(' ')}")
688
+ to_yaml.sub(/\A---\s*\n/,'')
1333
689
  end
1334
- end
1335
-
1336
- #
1337
- # TASK install
1338
- #
1339
-
1340
- def exec_install
1341
- rm_f 'InstalledFiles'
1342
- exec_task_traverse 'install'
1343
- end
1344
-
1345
- def install_dir_bin(rel)
1346
- install_files targetfiles(), "#{config('bindir')}/#{rel}", 0755
1347
- end
1348
-
1349
- def install_dir_lib(rel)
1350
- install_files libfiles(), "#{config('rbdir')}/#{rel}", 0644
1351
- end
1352
-
1353
- def install_dir_ext(rel)
1354
- return unless extdir?(curr_srcdir())
1355
- install_files rubyextentions('.'),
1356
- "#{config('sodir')}/#{File.dirname(rel)}",
1357
- 0555
1358
- end
1359
-
1360
- def install_dir_data(rel)
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
1372
- end
1373
-
1374
- def install_files(list, dest, mode)
1375
- mkdir_p dest, @config.install_prefix
1376
- list.each do |fname|
1377
- install fname, dest, mode, @config.install_prefix
690
+ def to_yaml(*args)
691
+ to_h.to_yaml(*args)
1378
692
  end
1379
- end
1380
-
1381
- def libfiles
1382
- glob_reject(%w(*.y *.output), targetfiles())
1383
- end
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"
693
+ def save_config
694
+ out = to_yaml
695
+ if not File.exist?(File.dirname(CONFIG_FILE))
696
+ FileUtils.mkdir_p(File.dirname(CONFIG_FILE))
697
+ end
698
+ if File.exist?(CONFIG_FILE)
699
+ txt = File.read(CONFIG_FILE)
700
+ return nil if txt == out
701
+ end
702
+ File.open(CONFIG_FILE, 'w'){ |f| f << out }
703
+ true
704
+ end
705
+ def exist?
706
+ File.exist?(CONFIG_FILE)
707
+ end
708
+ private
709
+ def pathname(path)
710
+ path.gsub(%r<\\$([^/]+)>){ self[$1] }
711
+ end
712
+ def boolean(val, name=nil)
713
+ case val
714
+ when true, false, nil
715
+ val
716
+ else
717
+ case val.to_s.downcase
718
+ when 'y', 'yes', 't', 'true'
719
+ true
720
+ when 'n', 'no', 'f', 'false'
721
+ false
722
+ else
723
+ raise Error, "bad config: use --#{name}=(yes|no) [\#{val}]"
724
+ end
725
+ end
726
+ end
727
+ def subprefix(path, with='')
728
+ val = RBCONFIG[path]
729
+ raise "Unknown path -- #{path}" if val.nil?
730
+ prefix = Regexp.quote(RBCONFIG['prefix'])
731
+ val.sub(/\A#{prefix}/, with)
732
+ end
733
+ def home
734
+ ENV['HOME'] || raise(Error, 'HOME is not set.')
735
+ end
736
+ end #class ConfigTable
737
+ end #module Setup
738
+ =begin
739
+ def inintialize_metaconfig
740
+ path = Dir.glob(METACONFIG_FILE).first
741
+ if path && File.file?(path)
742
+ MetaConfigEnvironment.new(self).instance_eval(File.read(path), path)
743
+ end
744
+ end
745
+ class MetaConfigEnvironment
746
+ def initialize(config) #, installer)
747
+ @config = config
748
+ end
749
+ def config_names
750
+ @config.descriptions.collect{ |n, t, d| n.to_s }
751
+ end
752
+ def config?(name)
753
+ @config.descriptions.find do |sym, type, desc|
754
+ sym.to_s == name.to_s
755
+ end
756
+ end
757
+ def bool_config?(name)
758
+ @config.descriptions.find do |sym, type, desc|
759
+ sym.to_s == name.to_s && type == :bool
760
+ end
761
+ end
762
+ def path_config?(name)
763
+ @config.descriptions.find do |sym, type, desc|
764
+ sym.to_s == name.to_s && type == :path
765
+ end
766
+ end
767
+ def value_config?(name)
768
+ @config.descriptions.find do |sym, type, desc|
769
+ sym.to_s == name.to_s && type != :prog
770
+ end
771
+ end
772
+ def add_config(name, default, desc)
773
+ @config.descriptions << [name.to_sym, nil, desc]
774
+ end
775
+ def add_bool_config(name, default, desc)
776
+ @config.descriptions << [name.to_sym, :bool, desc]
777
+ end
778
+ def add_path_config(name, default, desc)
779
+ @config.descriptions << [name.to_sym, :path, desc]
780
+ end
781
+ def set_config_default(name, default)
782
+ @config[name] = default
783
+ end
784
+ def remove_config(name)
785
+ item = @config.descriptions.find do |sym, type, desc|
786
+ sym.to_s == name.to_s
787
+ end
788
+ index = @config.descriptions.index(item)
789
+ @config.descriptions.delete(index)
790
+ end
791
+ end
792
+ =end
793
+ module Setup
794
+ class Installer < Base
795
+ def install_prefix
796
+ config.install_prefix
797
+ end
798
+ def install
799
+ Dir.chdir(rootdir) do
800
+ install_bin
801
+ install_ext
802
+ install_lib
803
+ install_data
804
+ install_man
805
+ install_doc
806
+ install_etc
807
+ prune_install_record
808
+ end
809
+ end
810
+ def install_bin
811
+ return unless directory?('bin')
812
+ report_transfer('bin', config.bindir)
813
+ files = files('bin')
814
+ install_files('bin', files, config.bindir, 0755)
815
+ end
816
+ def install_ext
817
+ return unless directory?('ext')
818
+ report_transfer('ext', config.sodir)
819
+ files = files('ext')
820
+ files = select_dllext(files)
821
+ files.each do |file|
822
+ name = File.join(File.dirname(File.dirname(file)), File.basename(file))
823
+ dest = destination(config.sodir, name)
824
+ install_file('ext', file, dest, 0555, install_prefix)
825
+ end
826
+ end
827
+ def install_lib
828
+ return unless directory?('lib')
829
+ report_transfer('lib', config.rbdir)
830
+ files = files('lib')
831
+ install_files('lib', files, config.rbdir, 0644)
832
+ end
833
+ def install_data
834
+ return unless directory?('data')
835
+ report_transfer('data', config.datadir)
836
+ files = files('data')
837
+ install_files('data', files, config.datadir, 0644)
838
+ end
839
+ def install_etc
840
+ return unless directory?('etc')
841
+ report_transfer('etc', config.sysconfdir)
842
+ files = files('etc')
843
+ install_files('etc', files, config.sysconfdir, 0644)
844
+ end
845
+ def install_man
846
+ return unless directory?('man')
847
+ report_transfer('man', config.mandir)
848
+ files = files('man')
849
+ install_files('man', files, config.mandir, 0644)
850
+ end
851
+ def install_doc
852
+ return unless config.doc?
853
+ return unless directory?('doc')
854
+ return unless project.name
855
+ dir = File.join(config.docdir, "ruby-#{project.name}")
856
+ report_transfer('doc', dir)
857
+ files = files('doc')
858
+ install_files('doc', files, dir, 0644)
859
+ end
860
+ private
861
+ def report_transfer(source, directory)
862
+ unless quiet?
863
+ if install_prefix
864
+ out = File.join(install_prefix, directory)
865
+ else
866
+ out = directory
867
+ end
868
+ io.puts "* #{source} -> #{out}"
869
+ end
870
+ end
871
+ def directory?(path)
872
+ File.directory?(path)
873
+ end
874
+ def files(dir)
875
+ files = Dir["#{dir}/**/*"]
876
+ files = files.select{ |f| File.file?(f) }
877
+ files = files.map{ |f| f.sub("#{dir}/", '') }
878
+ files
879
+ end
880
+ def select_dllext(files)
881
+ ents = files.select do |file|
882
+ File.extname(file) == ".#{dllext}"
883
+ end
884
+ if ents.empty? && !files.empty?
885
+ raise Error, "ruby extention not compiled: 'setup.rb compile' first"
886
+ end
887
+ ents
888
+ end
889
+ def dllext
890
+ config.dlext
891
+ end
892
+ def install_files(dir, list, dest, mode)
893
+ list.each do |fname|
894
+ rdest = destination(dest, fname)
895
+ install_file(dir, fname, rdest, mode, install_prefix)
896
+ end
897
+ end
898
+ def install_file(dir, from, dest, mode, prefix=nil)
899
+ mkdir_p(File.dirname(dest))
900
+ if trace? or trial?
901
+ io.puts "install #{dir}/#{from} #{dest}"
902
+ end
903
+ return if trial?
904
+ str = binread(File.join(dir, from))
905
+ if diff?(str, dest)
906
+ trace_off {
907
+ rm_f(dest) if File.exist?(dest)
908
+ }
909
+ File.open(dest, 'wb'){ |f| f.write(str) }
910
+ File.chmod(mode, dest)
911
+ end
912
+ record_installation(dest) # record file as installed
913
+ end
914
+ def mkdir_p(dirname) #, prefix=nil)
915
+ return if File.directory?(dirname)
916
+ io.puts "mkdir -p #{dirname}" if trace? or trial?
917
+ return if trial?
918
+ dirs = File.expand_path(dirname).split(%r<(?=/)>)
919
+ if /\A[a-z]:\z/i =~ dirs[0]
920
+ disk = dirs.shift
921
+ dirs[0] = disk + dirs[0]
922
+ end
923
+ dirs.each_index do |idx|
924
+ path = dirs[0..idx].join('')
925
+ unless File.dir?(path)
926
+ Dir.mkdir(path)
927
+ end
928
+ record_installation(path) # record directories made
929
+ end
930
+ end
931
+ def record_installation(path)
932
+ File.open(install_record, 'a') do |f|
933
+ f.puts(path)
934
+ end
935
+ end
936
+ def prune_install_record
937
+ entries = File.read(install_record).split("\n")
938
+ entries.uniq!
939
+ File.open(install_record, 'w') do |f|
940
+ f << entries.join("\n")
941
+ f << "\n"
942
+ end
943
+ end
944
+ def install_record
945
+ @install_record ||= (
946
+ file = INSTALL_RECORD
947
+ dir = File.dirname(file)
948
+ unless File.directory?(dir)
949
+ FileUtils.mkdir_p(dir)
950
+ end
951
+ file
952
+ )
953
+ end
954
+ def destination(dir, file)
955
+ dest = install_prefix ? File.join(install_prefix, File.expand_path(dir)) : dir
956
+ dest = File.join(dest, file) #if File.dir?(dest)
957
+ dest = File.expand_path(dest)
958
+ dest
959
+ end
960
+ def diff?(new_content, path)
961
+ return true unless File.exist?(path)
962
+ new_content != binread(path)
963
+ end
964
+ def binread(fname)
965
+ File.open(fname, 'rb') do |f|
966
+ return f.read
967
+ end
968
+ end
969
+ def install_shebang(files, dir)
970
+ files.each do |file|
971
+ path = File.join(dir, File.basename(file))
972
+ update_shebang_line(path)
973
+ end
974
+ end
975
+ def update_shebang_line(path)
976
+ return if trial?
977
+ return if config.shebang == 'never'
978
+ old = Shebang.load(path)
979
+ if old
980
+ if old.args.size > 1
981
+ $stderr.puts "warning: #{path}"
982
+ $stderr.puts "Shebang line has too many args."
983
+ $stderr.puts "It is not portable and your program may not work."
984
+ end
985
+ new = new_shebang(old)
986
+ return if new.to_s == old.to_s
987
+ else
988
+ return unless config.shebang == 'all'
989
+ new = Shebang.new(config.rubypath)
990
+ end
991
+ $stderr.puts "updating shebang: #{File.basename(path)}" if trace?
992
+ open_atomic_writer(path) do |output|
993
+ File.open(path, 'rb') do |f|
994
+ f.gets if old # discard
995
+ output.puts new.to_s
996
+ output.print f.read
997
+ end
998
+ end
999
+ end
1000
+ def new_shebang(old)
1001
+ if /\Aruby/ =~ File.basename(old.cmd)
1002
+ Shebang.new(config.rubypath, old.args)
1003
+ elsif File.basename(old.cmd) == 'env' and old.args.first == 'ruby'
1004
+ Shebang.new(config.rubypath, old.args[1..-1])
1005
+ else
1006
+ return old unless config.shebang == 'all'
1007
+ Shebang.new(config.rubypath)
1008
+ end
1009
+ end
1010
+ def open_atomic_writer(path, &block)
1011
+ tmpfile = File.basename(path) + '.tmp'
1012
+ begin
1013
+ File.open(tmpfile, 'wb', &block)
1014
+ File.rename tmpfile, File.basename(path)
1015
+ ensure
1016
+ File.unlink tmpfile if File.exist?(tmpfile)
1017
+ end
1018
+ end
1019
+ class Shebang
1020
+ def Shebang.load(path)
1021
+ line = nil
1022
+ File.open(path) {|f|
1023
+ line = f.gets
1024
+ }
1025
+ return nil unless /\A#!/ =~ line
1026
+ parse(line)
1027
+ end
1028
+ def Shebang.parse(line)
1029
+ cmd, *args = *line.strip.sub(/\A\#!/, '').split(' ')
1030
+ new(cmd, args)
1031
+ end
1032
+ def initialize(cmd, args = [])
1033
+ @cmd = cmd
1034
+ @args = args
1035
+ end
1036
+ attr_reader :cmd
1037
+ attr_reader :args
1038
+ def to_s
1039
+ "#! #{@cmd}" + (@args.empty? ? '' : " #{@args.join(' ')}")
1040
+ end
1389
1041
  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
-
1406
- # picked up many entries from cvs-1.11.1/src/ignore.c
1407
- JUNK_FILES = %w(
1408
- core RCSLOG tags TAGS .make.state
1409
- .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb
1410
- *~ *.old *.bak *.BAK *.orig *.rej _$* *$
1411
-
1412
- *.org *.in .*
1413
- )
1414
-
1415
- def existfiles
1416
- glob_reject(JUNK_FILES, (files_of(curr_srcdir()) | files_of('.')))
1417
- end
1418
-
1419
- def hookfiles
1420
- %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt|
1421
- %w( config setup install clean ).map {|t| sprintf(fmt, t) }
1422
- }.flatten
1423
- end
1424
-
1425
- def glob_select(pat, ents)
1426
- re = globs2re([pat])
1427
- ents.select {|ent| re =~ ent }
1428
- end
1429
-
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
1468
- end
1469
-
1470
- #
1471
- # TASK clean
1472
- #
1473
-
1474
- def exec_clean
1475
- exec_task_traverse 'clean'
1476
- rm_f @config.savefile
1477
- rm_f 'InstalledFiles'
1478
- end
1479
-
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
1485
-
1486
- def clean_dir_ext(rel)
1487
- return unless extdir?(curr_srcdir())
1488
- make 'clean' if File.file?('Makefile')
1489
- end
1490
-
1491
- #
1492
- # TASK distclean
1493
- #
1494
-
1495
- def exec_distclean
1496
- exec_task_traverse 'distclean'
1497
- rm_f @config.savefile
1498
- rm_f 'InstalledFiles'
1499
- end
1500
-
1501
- alias distclean_dir_bin noop
1502
- alias distclean_dir_lib noop
1503
-
1504
- def distclean_dir_ext(rel)
1505
- return unless extdir?(curr_srcdir())
1506
- make 'distclean' if File.file?('Makefile')
1507
- end
1508
-
1509
- alias distclean_dir_data noop
1510
- alias distclean_dir_conf noop
1511
- alias distclean_dir_man noop
1512
-
1513
- #
1514
- # Traversing
1515
- #
1516
-
1517
- def exec_task_traverse(task)
1518
- run_hook "pre-#{task}"
1519
- FILETYPES.each do |type|
1520
- if type == 'ext' and config('without-ext') == 'yes'
1521
- $stderr.puts 'skipping ext/* by user option' if verbose?
1522
- next
1523
- end
1524
- traverse task, type, "#{task}_dir_#{type}"
1525
- end
1526
- run_hook "post-#{task}"
1527
- end
1528
-
1529
- def traverse(task, rel, mid)
1530
- dive_into(rel) {
1531
- run_hook "pre-#{task}"
1532
- __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '')
1533
- directories_of(curr_srcdir()).each do |d|
1534
- traverse task, "#{rel}/#{d}", mid
1535
- end
1536
- run_hook "post-#{task}"
1537
- }
1538
1042
  end
1539
-
1540
- def dive_into(rel)
1541
- return unless File.dir?("#{@srcdir}/#{rel}")
1542
-
1543
- dir = File.basename(rel)
1544
- Dir.mkdir dir unless File.dir?(dir)
1545
- prevdir = Dir.pwd
1546
- Dir.chdir dir
1547
- $stderr.puts '---> ' + rel if verbose?
1548
- @currdir = rel
1549
- yield
1550
- Dir.chdir prevdir
1551
- $stderr.puts '<--- ' + rel if verbose?
1552
- @currdir = File.dirname(rel)
1043
+ end
1044
+ module Setup
1045
+ class Tester < Base
1046
+ RUBYSCRIPT = META_EXTENSION_DIR + '/test.rb'
1047
+ SHELLSCRIPT = META_EXTENSION_DIR + '/test.sh'
1048
+ DEPRECATED_RUBYSCRIPT = META_EXTENSION_DIR + '/testrc.rb'
1049
+ def testable?
1050
+ if File.exist?(DEPRECATED_RUBYSCRIPT)
1051
+ warn "Must use `.setup/test.rb' instead or `.setup/testrc.rb' to support testing."
1052
+ end
1053
+ return false if config.no_test
1054
+ return true if File.exist?(RUBYSCRIPT)
1055
+ return true if File.exist?(SHELLSCRIPT)
1056
+ false
1057
+ end
1058
+ def test
1059
+ return true unless testable?
1060
+ if File.exist?(RUBYSCRIPT)
1061
+ test_rubyscript
1062
+ elsif File.exist?(SHELLSCRIPT)
1063
+ test_shellscript
1064
+ else
1065
+ true
1066
+ end
1067
+ end
1068
+ def test_shellscript
1069
+ bash(SHELLSCRIPT)
1070
+ end
1071
+ def test_rubyscript
1072
+ ruby(RUBYSCRIPT)
1073
+ end
1553
1074
  end
1554
-
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
1075
+ end
1076
+ module Setup
1077
+ class Uninstaller < Base
1078
+ def uninstall
1079
+ return unless File.exist?(INSTALL_RECORD)
1080
+ files = []
1081
+ dirs = []
1082
+ paths.each do |path|
1083
+ dirs << path if File.dir?(path)
1084
+ files << path if File.file?(path)
1085
+ end
1086
+ if dirs.empty? && files.empty?
1087
+ io.outs "Nothing to remove."
1088
+ return
1089
+ end
1090
+ files.sort!{ |a,b| b.size <=> a.size }
1091
+ dirs.sort!{ |a,b| b.size <=> a.size }
1092
+ if !force? && !trial?
1093
+ puts (files + dirs).collect{ |f| "#{f}" }.join("\n")
1094
+ puts
1095
+ puts "Must use --force option to remove these files and directories that become empty."
1096
+ return
1097
+ end
1098
+ files.each do |file|
1099
+ rm_f(file)
1100
+ end
1101
+ dirs.each do |dir|
1102
+ entries = Dir.entries(dir)
1103
+ entries.delete('.')
1104
+ entries.delete('..')
1105
+ rmdir(dir) if entries.empty?
1106
+ end
1107
+ rm_f(INSTALL_RECORD)
1108
+ end
1109
+ private
1110
+ def paths
1111
+ @paths ||= (
1112
+ lines = File.read(INSTALL_RECORD).split(/\s*\n/)
1113
+ lines = lines.map{ |line| line.strip }
1114
+ lines = lines.uniq
1115
+ lines = lines.reject{ |line| line.empty? } # skip blank lines
1116
+ lines = lines.reject{ |line| line[0,1] == '#' } # skip blank lines
1117
+ lines
1118
+ )
1564
1119
  end
1565
1120
  end
1566
-
1567
- end # class Installer
1568
-
1569
-
1570
- class SetupError < StandardError; end
1571
-
1572
- def setup_rb_error(msg)
1573
- raise SetupError, msg
1574
1121
  end
1575
-
1576
- if $0 == __FILE__
1577
- begin
1578
- ToplevelInstaller.invoke
1579
- rescue SetupError
1580
- raise if $DEBUG
1581
- $stderr.puts $!.message
1582
- $stderr.puts "Try 'ruby #{$0} --help' for detailed usage."
1583
- exit 1
1122
+ require 'optparse'
1123
+ module Setup
1124
+ class Command
1125
+ def self.run(*argv)
1126
+ new.run(*argv)
1127
+ end
1128
+ def self.tasks
1129
+ @tasks ||= {}
1130
+ end
1131
+ def self.order
1132
+ @order ||= []
1133
+ end
1134
+ def self.task(name, description)
1135
+ tasks[name] = description
1136
+ order << name
1137
+ end
1138
+ task 'show' , "show current configuration"
1139
+ task 'all' , "config, compile and install"
1140
+ task 'config' , "save/customize configuration settings"
1141
+ task 'compile' , "compile ruby extentions"
1142
+ task 'test' , "run test suite"
1143
+ task 'install' , "install project files"
1144
+ task 'clean' , "does `make clean' for each extention"
1145
+ task 'distclean', "does `make distclean' for each extention"
1146
+ task 'uninstall', "uninstall previously installed files"
1147
+ def run(*argv)
1148
+ ARGV.replace(argv) unless argv.empty?
1149
+ task = ARGV.find{ |a| a !~ /^[-]/ }
1150
+ task = 'all' unless task
1151
+ unless task_names.include?(task)
1152
+ $stderr.puts "Not a valid task -- #{task}"
1153
+ exit 1
1154
+ end
1155
+ parser = OptionParser.new
1156
+ options = {}
1157
+ parser.banner = "Usage: #{File.basename($0)} [TASK] [OPTIONS]"
1158
+ optparse_header(parser, options)
1159
+ case task
1160
+ when 'config'
1161
+ optparse_config(parser, options)
1162
+ when 'compile'
1163
+ optparse_compile(parser, options)
1164
+ when 'install'
1165
+ optparse_install(parser, options)
1166
+ when 'all'
1167
+ optparse_all(parser, options)
1168
+ end
1169
+ optparse_common(parser, options)
1170
+ begin
1171
+ parser.parse!(ARGV)
1172
+ rescue OptionParser::InvalidOption
1173
+ $stderr.puts $!.to_s.capitalize
1174
+ exit 1
1175
+ end
1176
+ rootdir = session.project.rootdir
1177
+ print_header
1178
+ begin
1179
+ $stderr.puts "(#{RUBY_ENGINE} #{RUBY_VERSION} #{RUBY_PLATFORM})"
1180
+ rescue
1181
+ $stderr.puts "(#{RUBY_VERSION} #{RUBY_PLATFORM})"
1182
+ end
1183
+ begin
1184
+ session.__send__(task)
1185
+ rescue Error => err
1186
+ raise err if $DEBUG
1187
+ $stderr.puts $!.message
1188
+ $stderr.puts "Try 'setup.rb --help' for detailed usage."
1189
+ abort $!.message #exit 1
1190
+ end
1191
+ puts unless session.quiet?
1192
+ end
1193
+ def session
1194
+ @session ||= Session.new(:io=>$stdout)
1195
+ end
1196
+ def configuration
1197
+ @configuration ||= session.configuration
1198
+ end
1199
+ def optparse_header(parser, options)
1200
+ parser.banner = "USAGE: #{File.basename($0)} [command] [options]"
1201
+ end
1202
+ def optparse_all(parser, options)
1203
+ optparse_config(parser, options)
1204
+ optparse_compile(parser, options)
1205
+ optparse_install(parser, options) # TODO: why was this remarked out ?
1206
+ end
1207
+ def optparse_config(parser, options)
1208
+ parser.separator ""
1209
+ parser.separator "Configuration options:"
1210
+ configuration.options.each do |args|
1211
+ args = args.dup
1212
+ desc = args.pop
1213
+ type = args.pop
1214
+ name, shortcut = *args
1215
+ optname = name.to_s.gsub('_', '-')
1216
+ case type
1217
+ when :bool
1218
+ if optname.index('no-') == 0
1219
+ optname = "[no-]" + optname.sub(/^no-/, '')
1220
+ opts = shortcut ? ["-#{shortcut}", "--#{optname}", desc] : ["--#{optname}", desc]
1221
+ parser.on(*opts) do |val|
1222
+ configuration.__send__("#{name}=", !val)
1223
+ end
1224
+ else
1225
+ optname = "[no-]" + optname.sub(/^no-/, '')
1226
+ opts = shortcut ? ["-#{shortcut}", "--#{optname}", desc] : ["--#{optname}", desc]
1227
+ parser.on(*opts) do |val|
1228
+ configuration.__send__("#{name}=", val)
1229
+ end
1230
+ end
1231
+ else
1232
+ opts = shortcut ? ["-#{shortcut}", "--#{optname} #{type.to_s.upcase}", desc] :
1233
+ ["--#{optname} #{type.to_s.upcase}", desc]
1234
+ parser.on(*opts) do |val|
1235
+ configuration.__send__("#{name}=", val)
1236
+ end
1237
+ end
1238
+ end
1239
+ end
1240
+ def optparse_compile(parser, options)
1241
+ end
1242
+ def optparse_install(parser, options)
1243
+ parser.separator ''
1244
+ parser.separator 'Install options:'
1245
+ parser.on('--prefix PATH', 'install to alternate root location') do |val|
1246
+ configuration.install_prefix = val
1247
+ end
1248
+ parser.on('--type TYPE', "install location mode (site,std,home)") do |val|
1249
+ configuration.type = val
1250
+ end
1251
+ parser.on('-t', '--[no-]test', "run pre-installation tests") do |bool|
1252
+ configuration.test = bool
1253
+ end
1254
+ end
1255
+ def optparse_common(parser, options)
1256
+ parser.separator ""
1257
+ parser.separator "General options:"
1258
+ parser.on("-q", "--quiet", "Suppress output") do
1259
+ session.quiet = true
1260
+ end
1261
+ parser.on("-f", "--force", "Force operation") do
1262
+ session.force = true
1263
+ end
1264
+ parser.on("--trace", "--verbose", "Watch execution") do |val|
1265
+ session.trace = true
1266
+ end
1267
+ parser.on("--trial", "--no-harm", "Do not write to disk") do |val|
1268
+ session.trial = true
1269
+ end
1270
+ parser.on("--debug", "Turn on debug mode") do |val|
1271
+ $DEBUG = true
1272
+ end
1273
+ parser.separator ""
1274
+ parser.separator "Inform options:"
1275
+ parser.on_tail("-h", "--help", "display this help information") do
1276
+ puts parser
1277
+ exit
1278
+ end
1279
+ parser.on_tail("--version", "-v", "Show version") do
1280
+ puts File.basename($0) + ' v' + Setup::VERSION #Version.join('.')
1281
+ exit
1282
+ end
1283
+ parser.on_tail("--copyright", "Show copyright") do
1284
+ puts Setup::COPYRIGHT #opyright
1285
+ exit
1286
+ end
1287
+ end
1288
+ def task_names
1289
+ self.class.tasks.keys
1290
+ end
1291
+ def print_header
1292
+ end
1584
1293
  end
1585
1294
  end
1295
+ Setup::Command.run