setup 4.2.0 → 5.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 (55) hide show
  1. data/HISTORY +47 -3
  2. data/MANIFEST +49 -16
  3. data/README.rdoc +148 -0
  4. data/bin/setup.rb +1 -5
  5. data/lib/setup.rb +2 -2
  6. data/lib/setup/base.rb +143 -0
  7. data/lib/setup/command.rb +218 -114
  8. data/lib/setup/compiler.rb +69 -0
  9. data/lib/setup/configuration.rb +822 -0
  10. data/lib/setup/constants.rb +12 -0
  11. data/lib/setup/{rubyver.rb → core_ext.rb} +0 -0
  12. data/lib/setup/documentor.rb +149 -0
  13. data/lib/setup/installer.rb +363 -0
  14. data/lib/setup/project.rb +68 -0
  15. data/lib/setup/rake.rb +44 -45
  16. data/lib/setup/session.rb +233 -0
  17. data/lib/setup/tester.rb +92 -0
  18. data/lib/setup/uninstaller.rb +76 -0
  19. data/meta/active +1 -0
  20. data/meta/collection +1 -0
  21. data/meta/{abstract → description} +0 -0
  22. data/meta/{package → name} +0 -0
  23. data/meta/repository +1 -0
  24. data/meta/ruby +3 -0
  25. data/meta/version +1 -1
  26. data/script/bstrap +5 -0
  27. data/script/bundle +64 -0
  28. data/script/setup +1338 -0
  29. data/script/test +3 -0
  30. data/test/cases/installer.rb +28 -0
  31. data/test/features/config.feature +16 -0
  32. data/test/features/document.feature +2 -0
  33. data/test/features/install.feature +72 -0
  34. data/test/features/make.feature +18 -0
  35. data/test/features/step_definitions/common_steps.rb +34 -0
  36. data/test/features/step_definitions/config_steps.rb +24 -0
  37. data/test/features/step_definitions/env.rb +37 -0
  38. data/test/features/step_definitions/install_steps.rb +75 -0
  39. data/test/features/step_definitions/setup_steps.rb +30 -0
  40. data/test/features/step_definitions/uninstall_steps.rb +8 -0
  41. data/test/features/test.feature +2 -0
  42. data/test/features/uninstall.feature +13 -0
  43. data/test/fixtures/faux-project/bin/faux +3 -0
  44. data/test/fixtures/faux-project/ext/faux/extconf.rb +12 -0
  45. data/test/fixtures/faux-project/ext/faux/faux.c +24 -0
  46. data/test/fixtures/faux-project/lib/faux.rb +1 -0
  47. metadata +58 -29
  48. data/README +0 -106
  49. data/RELEASE +0 -41
  50. data/lib/setup/build.rb +0 -2
  51. data/lib/setup/config.rb +0 -452
  52. data/lib/setup/error.rb +0 -4
  53. data/lib/setup/install.rb +0 -1007
  54. data/meta/setup/metaconfig.rb +0 -3
  55. data/test/test_installer.rb +0 -139
@@ -0,0 +1,76 @@
1
+ require 'setup/base'
2
+
3
+ module Setup
4
+
5
+ # TODO: It would be nice to improve this such that
6
+ # files to be removed are taken out of the list of
7
+ # directories that may be removed when they become
8
+ # empty. That way the end-user can see an exact list
9
+ # before commiting to the uninstall (using --force).
10
+ #
11
+ class Uninstaller < Base
12
+
13
+ #
14
+ def uninstall
15
+ return unless File.exist?(INSTALL_RECORD)
16
+
17
+ files = []
18
+ dirs = []
19
+
20
+ paths.each do |path|
21
+ dirs << path if File.dir?(path)
22
+ files << path if File.file?(path)
23
+ end
24
+
25
+ if dirs.empty? && files.empty?
26
+ io.outs "Nothing to remove."
27
+ return
28
+ end
29
+
30
+ files.sort!{ |a,b| b.size <=> a.size }
31
+ dirs.sort!{ |a,b| b.size <=> a.size }
32
+
33
+ if !force? && !trial?
34
+ puts (files + dirs).collect{ |f| "#{f}" }.join("\n")
35
+ puts
36
+ puts "Must use --force option to remove these files and directories that become empty."
37
+ return
38
+ end
39
+
40
+ files.each do |file|
41
+ rm_f(file)
42
+ end
43
+
44
+ dirs.each do |dir|
45
+ entries = Dir.entries(dir)
46
+ entries.delete('.')
47
+ entries.delete('..')
48
+
49
+ #begin
50
+ rmdir(dir) if entries.empty?
51
+ #rescue Errno::ENOTEMPTY
52
+ # io.puts "not empty -- #{dir}"
53
+ #end
54
+ end
55
+
56
+ rm_f(INSTALL_RECORD)
57
+ end
58
+
59
+ private
60
+
61
+ # path list from install record
62
+ def paths
63
+ @paths ||= (
64
+ lines = File.read(INSTALL_RECORD).split(/\s*\n/)
65
+ lines = lines.map{ |line| line.strip }
66
+ lines = lines.uniq
67
+ lines = lines.reject{ |line| line.empty? } # skip blank lines
68
+ lines = lines.reject{ |line| line[0,1] == '#' } # skip blank lines
69
+ lines
70
+ )
71
+ end
72
+
73
+ end
74
+
75
+ end
76
+
@@ -0,0 +1 @@
1
+ false
@@ -0,0 +1 @@
1
+ proutils
File without changes
File without changes
@@ -0,0 +1 @@
1
+ git://github.com/proutils/setup.git
@@ -0,0 +1,3 @@
1
+ ---
2
+ - 1.8.6
3
+ - 1.8.7
@@ -1 +1 @@
1
- 4.2.0
1
+ 5.0.0
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift('lib')
3
+ require 'setup/command'
4
+ Setup::Command.run(*ARGV)
5
+
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ raise "Not the right place #{Dir.pwd}" unless File.directory?('lib')
4
+
5
+ #scripts = (Dir['lib/*.rb'] + Dir['lib/**/*']).uniq
6
+ #scripts = scripts.reject{ |f| File.directory?(f) }
7
+ # We don't want the rake helper.
8
+ #scripts = scripts - ["lib/setup/rake.rb"]
9
+ #scripts = scripts + ["bin/setup.rb"]
10
+
11
+ scripts = %w{
12
+ lib/setup.rb
13
+ lib/setup/core_ext.rb
14
+ lib/setup/constants.rb
15
+ lib/setup/project.rb
16
+ lib/setup/session.rb
17
+ lib/setup/base.rb
18
+ lib/setup/compiler.rb
19
+ lib/setup/configuration.rb
20
+ lib/setup/documentor.rb
21
+ lib/setup/installer.rb
22
+ lib/setup/tester.rb
23
+ lib/setup/uninstaller.rb
24
+ lib/setup/command.rb
25
+ bin/setup.rb
26
+ }
27
+
28
+ comment = <<-HERE
29
+ #
30
+ # Setup.rb, #{Time.now.strftime("%Y-%m-%d %H:%M:%S")}
31
+ #
32
+ # This is a stand-alone bundle of the setup.rb application.
33
+ # You can place it in your projects script/ directory, or
34
+ # rename it to 'setup.rb' and place it in your project's
35
+ # root directory (just like old times).
36
+ #
37
+ HERE
38
+
39
+ #
40
+ bundle = ""
41
+
42
+ # insert scripts
43
+ scripts.each do |script|
44
+ bundle << "\n\n# %-16s #{"#" * 60}\n\n" % File.basename(script)
45
+ bundle << File.read(script)
46
+ end
47
+
48
+ # remove setup requires
49
+ bundle.gsub!(/require\s+["']setup\/(.*?)["']\s*$/, '')
50
+
51
+ # remove blank lines
52
+ bundle.gsub!(/^\s*\n/, '')
53
+
54
+ # remove comments
55
+ bundle.gsub!(/^\s*\#.*?\n/, '')
56
+
57
+ # save
58
+ File.open('script/setup', 'w') do |f|
59
+ f << "#!/usr/bin/env ruby\n"
60
+ f << comment
61
+ f << bundle
62
+ end
63
+
64
+ FileUtils.chmod(0744, 'script/setup')
@@ -0,0 +1,1338 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Setup.rb, 2010-01-13 04:14:39
4
+ #
5
+ # This is a stand-alone bundle of the setup.rb application.
6
+ # You can place it in your projects script/ directory, or
7
+ # rename it to 'setup.rb' and place it in your project's
8
+ # root directory (just like old times).
9
+ #
10
+ module Setup
11
+ VERSION = '5.0.0'
12
+ end
13
+ class << File #:nodoc: all
14
+ unless respond_to?(:read) # Ruby 1.6 and less
15
+ def read(fname)
16
+ open(fname){ |f| return f.read }
17
+ end
18
+ end
19
+ def dir?(path)
20
+ directory?((path[-1,1] == '/') ? path : path + '/')
21
+ end
22
+ end
23
+ unless Errno.const_defined?(:ENOTEMPTY) # Windows?
24
+ module Errno #:nodoc:
25
+ class ENOTEMPTY #:nodoc:
26
+ end
27
+ end
28
+ end
29
+ module Setup
30
+ META_EXTENSION_DIR = '.setup'
31
+ FILETYPES = %w( bin lib ext data etc man doc )
32
+ INSTALL_RECORD = 'InstalledFiles' #'.cache/setup/installedfiles'
33
+ end
34
+ module Setup
35
+ class Project
36
+ ROOT_MARKER = '{setup.rb,script/setup,meta/,MANIFEST,lib/}'
37
+ def rootdir
38
+ @rootdir ||= (
39
+ root = Dir[File.join(Dir.pwd, ROOT_MARKER)].first
40
+ if !root
41
+ raise Error, "not a project directory"
42
+ else
43
+ Dir.pwd
44
+ end
45
+ )
46
+ end
47
+ def name
48
+ @name = (
49
+ if file = Dir["{script/setup,meta,.meta}/name"].first
50
+ File.read(file).strip
51
+ else
52
+ nil
53
+ end
54
+ )
55
+ end
56
+ def loadpath
57
+ @loadpath ||= (
58
+ if file = Dir.glob('{script/setup,meta,.meta}/loadpath').first
59
+ raw = File.read(file).strip.chomp(']')
60
+ raw.split(/[\n,]/).map do |e|
61
+ e.strip.sub(/^[\[-]\s*/,'')
62
+ end
63
+ else
64
+ nil
65
+ end
66
+ )
67
+ end
68
+ def extconfs
69
+ @extconfs ||= Dir['ext/**/extconf.rb']
70
+ end
71
+ def extensions
72
+ @extensions ||= extconfs.collect{ |f| File.dirname(f) }
73
+ end
74
+ def compiles?
75
+ !extensions.empty?
76
+ end
77
+ end
78
+ end
79
+ module Setup
80
+ class Session
81
+ attr :options
82
+ def initialize(options={})
83
+ @options = options
84
+ self.io ||= StringIO.new # log instead ?
85
+ end
86
+ def io
87
+ @options[:io]
88
+ end
89
+ def io=(anyio)
90
+ @options[:io] = anyio
91
+ end
92
+ def trace?; @options[:trace]; end
93
+ def trace=(val)
94
+ @options[:trace] = val
95
+ end
96
+ def trial?; @options[:trial]; end
97
+ def trial=(val)
98
+ @options[:trial] = val
99
+ end
100
+ def quiet?; @options[:quiet]; end
101
+ def quiet=(val)
102
+ @options[:quiet] = val
103
+ end
104
+ def force?; @options[:force]; end
105
+ def force=(val)
106
+ @options[:force] = val
107
+ end
108
+ def compile?
109
+ configuration.compile? && project.compiles?
110
+ end
111
+ def all
112
+ config
113
+ if compile?
114
+ make
115
+ end
116
+ if configuration.test?
117
+ ok = test
118
+ exit 1 unless ok
119
+ end
120
+ install
121
+ if configuration.ri?
122
+ document
123
+ end
124
+ end
125
+ def config
126
+ log_header('Configure')
127
+ if configuration.save_config
128
+ io.puts "Configuration saved." unless quiet?
129
+ else
130
+ io.puts "Configuration current." unless quiet?
131
+ end
132
+ puts configuration if trace? && !quiet?
133
+ compiler.configure if compile? #compiler.compiles?
134
+ end
135
+ def make
136
+ abort "must setup config first" unless configuration.exist?
137
+ log_header('Compile')
138
+ compiler.compile
139
+ end
140
+ alias_method :setup, :make
141
+ def install
142
+ abort "must setup config first" unless configuration.exist?
143
+ log_header('Install')
144
+ installer.install
145
+ end
146
+ def test
147
+ return true unless tester.testable?
148
+ log_header('Test')
149
+ tester.test
150
+ end
151
+ def document
152
+ log_header('Document')
153
+ documentor.document
154
+ end
155
+ def clean
156
+ log_header('Clean')
157
+ compiler.clean
158
+ end
159
+ def distclean
160
+ log_header('Distclean')
161
+ compiler.distclean
162
+ end
163
+ def uninstall
164
+ if !File.exist?(INSTALL_RECORD)
165
+ io.puts "Nothing is installed."
166
+ return
167
+ end
168
+ log_header('Uninstall')
169
+ uninstaller.uninstall
170
+ io.puts('Ok.')
171
+ end
172
+ def show
173
+ puts configuration
174
+ end
175
+ def project
176
+ @project ||= Project.new
177
+ end
178
+ def configuration
179
+ @configuration ||= Configuration.new
180
+ end
181
+ def compiler
182
+ @compiler ||= Compiler.new(project, configuration, options)
183
+ end
184
+ def installer
185
+ @installer ||= Installer.new(project, configuration, options)
186
+ end
187
+ def tester
188
+ @tester ||= Tester.new(project, configuration, options)
189
+ end
190
+ def documentor
191
+ @documentor ||= Documentor.new(project, configuration, options)
192
+ end
193
+ def uninstaller
194
+ @uninstaller ||= Uninstaller.new(project, configuration, options)
195
+ end
196
+ def log_header(phase)
197
+ return if quiet?
198
+ if trial?
199
+ str = "#{phase.upcase} (trail run)"
200
+ else
201
+ str = "#{phase.upcase}"
202
+ end
203
+ line = "- " * 35
204
+ line[0..str.size+3] = str
205
+ io.puts("\n- - #{line}\n\n")
206
+ end
207
+ end
208
+ end
209
+ module Setup
210
+ class Base
211
+ attr :project
212
+ attr :config
213
+ attr_accessor :trial
214
+ attr_accessor :trace
215
+ attr_accessor :quiet
216
+ attr_accessor :force
217
+ attr_accessor :io
218
+ def initialize(project, configuration, options={})
219
+ @project = project
220
+ @config = configuration
221
+ initialize_hooks
222
+ options.each do |k,v|
223
+ __send__("#{k}=", v) if respond_to?("#{k}=")
224
+ end
225
+ end
226
+ def initialize_hooks
227
+ file = META_EXTENSION_DIR + "/#{self.class.name.downcase}.rb"
228
+ if File.exist?(file)
229
+ script = File.read(file)
230
+ (class << self; self; end).class_eval(script)
231
+ end
232
+ end
233
+ def trial? ; @trial ; end
234
+ def trace? ; @trace ; end
235
+ def quiet? ; @quiet ; end
236
+ def force? ; @force ; end
237
+ def rootdir
238
+ project.rootdir
239
+ end
240
+ def bash(*args)
241
+ $stderr.puts args.join(' ') if trace?
242
+ system(*args) or raise RuntimeError, "system(#{args.map{|a| a.inspect }.join(' ')}) failed"
243
+ end
244
+ alias_method :command, :bash
245
+ def ruby(*args)
246
+ bash(config.rubyprog, *args)
247
+ end
248
+ def trace_off #:yield:
249
+ begin
250
+ save, @trace = trace?, false
251
+ yield
252
+ ensure
253
+ @trace = save
254
+ end
255
+ end
256
+ def rm_f(path)
257
+ io.puts "rm -f #{path}" if trace? or trial?
258
+ return if trial?
259
+ force_remove_file(path)
260
+ end
261
+ def force_remove_file(path)
262
+ begin
263
+ remove_file(path)
264
+ rescue
265
+ end
266
+ end
267
+ def remove_file(path)
268
+ File.chmod 0777, path
269
+ File.unlink(path)
270
+ end
271
+ def rmdir(path)
272
+ io.puts "rmdir #{path}" if trace? or trial?
273
+ return if trial?
274
+ Dir.rmdir(path)
275
+ end
276
+ end
277
+ class Error < StandardError
278
+ end
279
+ end
280
+ module Setup
281
+ class Compiler < Base
282
+ def compiles?
283
+ !extdirs.empty?
284
+ end
285
+ def configure
286
+ extdirs.each do |dir|
287
+ Dir.chdir(dir) do
288
+ if File.exist?('extconf.rb') && !FileUtils.uptodate?('Makefile', ['extconf.rb'])
289
+ ruby("extconf.rb")
290
+ end
291
+ end
292
+ end
293
+ end
294
+ def compile
295
+ extdirs.each do |dir|
296
+ Dir.chdir(dir) do
297
+ make
298
+ end
299
+ end
300
+ end
301
+ def clean
302
+ extdirs.each do |dir|
303
+ Dir.chdir(dir) do
304
+ make('clean')
305
+ end
306
+ end
307
+ end
308
+ def distclean
309
+ extdirs.each do |dir|
310
+ Dir.chdir(dir) do
311
+ make('distclean')
312
+ end
313
+ end
314
+ end
315
+ def extdirs
316
+ Dir['ext/**/*/{MANIFEST,extconf.rb}'].map do |f|
317
+ File.dirname(f)
318
+ end.uniq
319
+ end
320
+ def make(task=nil)
321
+ return unless File.exist?('Makefile')
322
+ bash(*[config.makeprog, task].compact)
323
+ end
324
+ end
325
+ end
326
+ require 'rbconfig'
327
+ require 'fileutils'
328
+ require 'erb'
329
+ require 'yaml'
330
+ module Setup
331
+ class Configuration
332
+ RBCONFIG = ::Config::CONFIG
333
+ CONFIG_FILE = 'SetupConfig' # '.cache/setup/config'
334
+ META_CONFIG_FILE = META_EXTENSION_DIR + '/configuration.rb'
335
+ def self.options
336
+ @@options ||= []
337
+ end
338
+ def self.option(name, *args) #type, description)
339
+ options << [name.to_s, *args] #type, description]
340
+ attr_accessor(name)
341
+ end
342
+ option :prefix , :path, 'path prefix of target environment'
343
+ option :bindir , :path, 'directory for commands'
344
+ option :libdir , :path, 'directory for libraries'
345
+ option :datadir , :path, 'directory for shared data'
346
+ option :mandir , :path, 'directory for man pages'
347
+ option :docdir , :path, 'directory for documentation'
348
+ option :rbdir , :path, 'directory for ruby scripts'
349
+ option :sodir , :path, 'directory for ruby extentions'
350
+ option :sysconfdir , :path, 'directory for system configuration files'
351
+ option :localstatedir , :path, 'directory for local state data'
352
+ option :libruby , :path, 'directory for ruby libraries'
353
+ option :librubyver , :path, 'directory for standard ruby libraries'
354
+ option :librubyverarch , :path, 'directory for standard ruby extensions'
355
+ option :siteruby , :path, 'directory for version-independent aux ruby libraries'
356
+ option :siterubyver , :path, 'directory for aux ruby libraries'
357
+ option :siterubyverarch , :path, 'directory for aux ruby binaries'
358
+ option :rubypath , :prog, 'path to set to #! line'
359
+ option :rubyprog , :prog, 'ruby program used for installation'
360
+ option :makeprog , :prog, 'make program to compile ruby extentions'
361
+ option :extconfopt , :opts, 'options to pass-thru to extconf.rb'
362
+ option :shebang , :pick, 'shebang line (#!) editing mode (all,ruby,never)'
363
+ option :no_test, :t , :bool, 'run pre-installation tests'
364
+ option :no_ri, :d , :bool, 'generate ri documentation'
365
+ option :no_doc, , :bool, 'install doc/ directory'
366
+ option :no_ext , :bool, 'compile/install ruby extentions'
367
+ option :install_prefix , :path, 'install to alternate root location'
368
+ option :root , :path, 'install to alternate root location'
369
+ option :installdirs , :pick, 'install location mode (site,std,home)' #, local)
370
+ option :type , :pick, 'install location mode (site,std,home)'
371
+ ::Config::CONFIG.each do |key,val|
372
+ next if key == "configure_args"
373
+ name = key.to_s.downcase
374
+ define_method(name){ val }
375
+ end
376
+ ::Config::CONFIG["configure_args"].each do |ent|
377
+ key, val = *ent.split("=")
378
+ name = key.downcase
379
+ name = name.sub(/^--/,'')
380
+ name = name.gsub(/-/,'_')
381
+ define_method(name){ val }
382
+ end
383
+ def options
384
+ self.class.options
385
+ end
386
+ def initialize(values={})
387
+ initialize_metaconfig
388
+ initialize_defaults
389
+ initialize_environment
390
+ initialize_configfile
391
+ values.each{ |k,v| __send__("#{k}=", v) }
392
+ yeild(self) if block_given?
393
+ end
394
+ def initialize_metaconfig
395
+ if File.exist?(META_CONFIG_FILE)
396
+ script = File.read(META_CONFIG_FILE)
397
+ (class << self; self; end).class_eval(script)
398
+ end
399
+ end
400
+ def initialize_defaults
401
+ self.type = 'site'
402
+ self.no_ri = true
403
+ self.no_test = true
404
+ self.no_doc = false
405
+ self.no_ext = false
406
+ end
407
+ def initialize_environment
408
+ options.each do |name, *args|
409
+ if value = ENV["RUBYSETUP_#{name.to_s.upcase}"]
410
+ __send__("#{name}=", value)
411
+ end
412
+ end
413
+ end
414
+ def initialize_configfile
415
+ if File.exist?(CONFIG_FILE)
416
+ erb = ERB.new(File.read(CONFIG_FILE))
417
+ txt = erb.result(binding)
418
+ dat = YAML.load(txt)
419
+ dat.each do |k, v|
420
+ next if 'type' == k
421
+ next if 'installdirs' == k
422
+ k = k.gsub('-','_')
423
+ __send__("#{k}=", v)
424
+ end
425
+ if dat['type']
426
+ self.type = dat['type']
427
+ end
428
+ if dat['installdirs']
429
+ self.installdirs = dat['installdirs']
430
+ end
431
+ end
432
+ end
433
+ def base_bindir
434
+ @base_bindir ||= subprefix('bindir')
435
+ end
436
+ def base_libdir
437
+ @base_libdir ||= subprefix('libdir')
438
+ end
439
+ def base_datadir
440
+ @base_datadir ||= subprefix('datadir')
441
+ end
442
+ def base_mandir
443
+ @base_mandir ||= subprefix('mandir')
444
+ end
445
+ def base_docdir
446
+ @base_docdir || File.dirname(subprefix('docdir'))
447
+ end
448
+ def base_rubylibdir
449
+ @rubylibdir ||= subprefix('rubylibdir')
450
+ end
451
+ def base_rubyarchdir
452
+ @base_rubyarchdir ||= subprefix('archdir')
453
+ end
454
+ def base_sysconfdir
455
+ @base_sysconfdir ||= subprefix('sysconfdir')
456
+ end
457
+ def base_localstatedir
458
+ @base_localstatedir ||= subprefix('localstatedir')
459
+ end
460
+ def type
461
+ @type ||= 'site'
462
+ end
463
+ def type=(val)
464
+ @type = val
465
+ case val.to_s
466
+ when 'std', 'ruby'
467
+ @rbdir = librubyver #'$librubyver'
468
+ @sodir = librubyverarch #'$librubyverarch'
469
+ when 'site'
470
+ @rbdir = siterubyver #'$siterubyver'
471
+ @sodir = siterubyverarch #'$siterubyverarch'
472
+ when 'home'
473
+ self.prefix = File.join(home, '.local') # TODO: Use XDG
474
+ @rbdir = nil #'$libdir/ruby'
475
+ @sodir = nil #'$libdir/ruby'
476
+ else
477
+ raise Error, "bad config: use type=(std|site|home) [#{val}]"
478
+ end
479
+ end
480
+ alias_method :installdirs, :type
481
+ alias_method :installdirs=, :type=
482
+ alias_method :install_prefix, :root
483
+ alias_method :install_prefix=, :root=
484
+ def prefix
485
+ @prefix ||= RBCONFIG['prefix']
486
+ end
487
+ def prefix=(path)
488
+ @prefix = pathname(path)
489
+ end
490
+ def libruby
491
+ @libruby ||= RBCONFIG['prefix'] + "/lib/ruby"
492
+ end
493
+ def libruby=(path)
494
+ path = pathname(path)
495
+ @librubyver = librubyver.sub(libruby, path)
496
+ @librubyverarch = librubyverarch.sub(libruby, path)
497
+ @libruby = path
498
+ end
499
+ def librubyver
500
+ @librubyver ||= RBCONFIG['rubylibdir']
501
+ end
502
+ def librubyver=(path)
503
+ @librubyver = pathname(path)
504
+ end
505
+ def librubyverarch
506
+ @librubyverarch ||= RBCONFIG['archdir']
507
+ end
508
+ def librubyverarch=(path)
509
+ @librubyverarch = pathname(path)
510
+ end
511
+ def siteruby
512
+ @siteruby ||= RBCONFIG['sitedir']
513
+ end
514
+ def siteruby=(path)
515
+ path = pathname(path)
516
+ @siterubyver = siterubyver.sub(siteruby, path)
517
+ @siterubyverarch = siterubyverarch.sub(siteruby, path)
518
+ @siteruby = path
519
+ end
520
+ def siterubyver
521
+ @siterubyver ||= RBCONFIG['sitelibdir']
522
+ end
523
+ def siterubyver=(path)
524
+ @siterubyver = pathname(path)
525
+ end
526
+ def siterubyverarch
527
+ @siterubyverarch ||= RBCONFIG['sitearchdir']
528
+ end
529
+ def siterubyverarch=(path)
530
+ @siterubyverarch = pathname(path)
531
+ end
532
+ def bindir
533
+ @bindir || File.join(prefix, base_bindir)
534
+ end
535
+ def bindir=(path)
536
+ @bindir = pathname(path)
537
+ end
538
+ def libdir
539
+ @libdir || File.join(prefix, base_libdir)
540
+ end
541
+ def libdir=(path)
542
+ @libdir = pathname(path)
543
+ end
544
+ def datadir
545
+ @datadir || File.join(prefix, base_datadir)
546
+ end
547
+ def datadir=(path)
548
+ @datadir = pathname(path)
549
+ end
550
+ def mandir
551
+ @mandir || File.join(prefix, base_mandir)
552
+ end
553
+ def mandir=(path)
554
+ @mandir = pathname(path)
555
+ end
556
+ def docdir
557
+ @docdir || File.join(prefix, base_docdir)
558
+ end
559
+ def docdir=(path)
560
+ @docdir = pathname(path)
561
+ end
562
+ def rbdir
563
+ @rbdir || File.join(prefix, base_rubylibdir)
564
+ end
565
+ def sodir
566
+ @sodir || File.join(prefix, base_rubyarchdir)
567
+ end
568
+ def sysconfdir
569
+ @sysconfdir ||= base_sysconfdir
570
+ end
571
+ def sysconfdir=(path)
572
+ @sysconfdir = pathname(path)
573
+ end
574
+ def localstatedir
575
+ @localstatedir ||= base_localstatedir
576
+ end
577
+ def localstatedir=(path)
578
+ @localstatedir = pathname(path)
579
+ end
580
+ def rubypath
581
+ @rubypath ||= File.join(RBCONFIG['bindir'], RBCONFIG['ruby_install_name'] + RBCONFIG['EXEEXT'])
582
+ end
583
+ def rubypath=(path)
584
+ @rubypath = pathname(path)
585
+ end
586
+ def rubyprog
587
+ @rubyprog || rubypath
588
+ end
589
+ def rubyprog=(command)
590
+ @rubyprog = command
591
+ end
592
+ def makeprog
593
+ @makeprog ||= (
594
+ if arg = RBCONFIG['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg }
595
+ arg.sub(/'/, '').split(/=/, 2)[1]
596
+ else
597
+ 'make'
598
+ end
599
+ )
600
+ end
601
+ def makeprog=(command)
602
+ @makeprog = command
603
+ end
604
+ def extconfopt
605
+ @extconfopt ||= ''
606
+ end
607
+ def extconfopt=(string)
608
+ @extconfopt = string
609
+ end
610
+ def shebang
611
+ @shebang ||= 'ruby'
612
+ end
613
+ def shebang=(val)
614
+ if %w(all ruby never).include?(val)
615
+ @shebang = val
616
+ else
617
+ raise Error, "bad config: use SHEBANG=(all|ruby|never) [#{val}]"
618
+ end
619
+ end
620
+ def no_ext
621
+ @no_ext
622
+ end
623
+ def no_ext=(val)
624
+ @no_ext = boolean(val)
625
+ end
626
+ def no_test
627
+ @no_test
628
+ end
629
+ def no_test=(val)
630
+ @no_test = boolean(val)
631
+ end
632
+ def no_doc
633
+ @no_doc
634
+ end
635
+ def no_doc=(val)
636
+ @no_doc = boolean(val)
637
+ end
638
+ def no_ri
639
+ @no_ri
640
+ end
641
+ def no_ri=(val)
642
+ @no_ri = boolean(val)
643
+ end
644
+ def compile?
645
+ !no_ext
646
+ end
647
+ def test?
648
+ !no_test
649
+ end
650
+ def ri?
651
+ !no_ri
652
+ end
653
+ def doc?
654
+ !no_doc
655
+ end
656
+ def to_h
657
+ h = {}
658
+ options.each do |name, *args|
659
+ h[name.to_s] = __send__(name)
660
+ end
661
+ h
662
+ end
663
+ def to_s
664
+ to_yaml.sub(/\A---\s*\n/,'')
665
+ end
666
+ def to_yaml(*args)
667
+ to_h.to_yaml(*args)
668
+ end
669
+ def save_config
670
+ out = to_yaml
671
+ if not File.exist?(File.dirname(CONFIG_FILE))
672
+ FileUtils.mkdir_p(File.dirname(CONFIG_FILE))
673
+ end
674
+ if File.exist?(CONFIG_FILE)
675
+ txt = File.read(CONFIG_FILE)
676
+ return nil if txt == out
677
+ end
678
+ File.open(CONFIG_FILE, 'w'){ |f| f << out }
679
+ true
680
+ end
681
+ def exist?
682
+ File.exist?(CONFIG_FILE)
683
+ end
684
+ private
685
+ def pathname(path)
686
+ path.gsub(%r<\\$([^/]+)>){ self[$1] }
687
+ end
688
+ def boolean(val, name=nil)
689
+ case val
690
+ when true, false, nil
691
+ val
692
+ else
693
+ case val.to_s.downcase
694
+ when 'y', 'yes', 't', 'true'
695
+ true
696
+ when 'n', 'no', 'f', 'false'
697
+ false
698
+ else
699
+ raise Error, "bad config: use --#{name}=(yes|no) [\#{val}]"
700
+ end
701
+ end
702
+ end
703
+ def subprefix(path, with='')
704
+ val = RBCONFIG[path]
705
+ raise "Unknown path -- #{path}" if val.nil?
706
+ prefix = Regexp.quote(RBCONFIG['prefix'])
707
+ val.sub(/\A#{prefix}/, with)
708
+ end
709
+ def home
710
+ ENV['HOME'] || raise(Error, 'HOME is not set.')
711
+ end
712
+ end #class ConfigTable
713
+ end #module Setup
714
+ =begin
715
+ def inintialize_metaconfig
716
+ path = Dir.glob(METACONFIG_FILE).first
717
+ if path && File.file?(path)
718
+ MetaConfigEnvironment.new(self).instance_eval(File.read(path), path)
719
+ end
720
+ end
721
+ class MetaConfigEnvironment
722
+ def initialize(config) #, installer)
723
+ @config = config
724
+ end
725
+ def config_names
726
+ @config.descriptions.collect{ |n, t, d| n.to_s }
727
+ end
728
+ def config?(name)
729
+ @config.descriptions.find do |sym, type, desc|
730
+ sym.to_s == name.to_s
731
+ end
732
+ end
733
+ def bool_config?(name)
734
+ @config.descriptions.find do |sym, type, desc|
735
+ sym.to_s == name.to_s && type == :bool
736
+ end
737
+ end
738
+ def path_config?(name)
739
+ @config.descriptions.find do |sym, type, desc|
740
+ sym.to_s == name.to_s && type == :path
741
+ end
742
+ end
743
+ def value_config?(name)
744
+ @config.descriptions.find do |sym, type, desc|
745
+ sym.to_s == name.to_s && type != :prog
746
+ end
747
+ end
748
+ def add_config(name, default, desc)
749
+ @config.descriptions << [name.to_sym, nil, desc]
750
+ end
751
+ def add_bool_config(name, default, desc)
752
+ @config.descriptions << [name.to_sym, :bool, desc]
753
+ end
754
+ def add_path_config(name, default, desc)
755
+ @config.descriptions << [name.to_sym, :path, desc]
756
+ end
757
+ def set_config_default(name, default)
758
+ @config[name] = default
759
+ end
760
+ def remove_config(name)
761
+ item = @config.descriptions.find do |sym, type, desc|
762
+ sym.to_s == name.to_s
763
+ end
764
+ index = @config.descriptions.index(item)
765
+ @config.descriptions.delete(index)
766
+ end
767
+ end
768
+ =end
769
+ module Setup
770
+ class Documentor < Base
771
+ def document
772
+ return if config.no_doc
773
+ exec_ri
774
+ end
775
+ def exec_ri
776
+ case config.type #installdirs
777
+ when 'std', 'ruby'
778
+ output = "--ri-site"
779
+ when 'site'
780
+ output = "--ri-site"
781
+ when 'home'
782
+ output = "--ri"
783
+ else
784
+ abort "bad config: should not be possible -- type=#{config.type}"
785
+ end
786
+ if File.exist?('.document')
787
+ files = File.read('.document').split("\n")
788
+ files.reject!{ |l| l =~ /^\s*[#]/ || l !~ /\S/ }
789
+ files.collect!{ |f| f.strip }
790
+ else
791
+ files = []
792
+ files << 'lib' if File.directory?('lib')
793
+ files << 'ext' if File.directory?('ext')
794
+ end
795
+ opt = []
796
+ opt << "-U"
797
+ opt << "-q" #if quiet?
798
+ opt << output
799
+ opt << files
800
+ opt = opt.flatten
801
+ cmd = "rdoc " + opt.join(' ')
802
+ if trial?
803
+ puts cmd
804
+ else
805
+ begin
806
+ success = system(cmd)
807
+ raise unless success
808
+ io.puts "Ok ri." #unless quiet?
809
+ rescue Exception
810
+ $stderr.puts "ri generation failed"
811
+ $stderr.puts "command was: '#{cmd}'"
812
+ end
813
+ end
814
+ end
815
+ def exec_rdoc
816
+ main = Dir.glob("README{,.*}", File::FNM_CASEFOLD).first
817
+ if File.exist?('.document')
818
+ files = File.read('.document').split("\n")
819
+ files.reject!{ |l| l =~ /^\s*[#]/ || l !~ /\S/ }
820
+ files.collect!{ |f| f.strip }
821
+ else
822
+ files = []
823
+ files << main if main
824
+ files << 'lib' if File.directory?('lib')
825
+ files << 'ext' if File.directory?('ext')
826
+ end
827
+ checkfiles = (files + files.map{ |f| Dir[File.join(f,'*','**')] }).flatten.uniq
828
+ if FileUtils.uptodate?('doc/rdoc', checkfiles)
829
+ puts "RDocs look current."
830
+ return
831
+ end
832
+ output = 'doc/rdoc'
833
+ title = (PACKAGE.capitalize + " API").strip if PACKAGE
834
+ template = config.doctemplate || 'html'
835
+ opt = []
836
+ opt << "-U"
837
+ opt << "-q" #if quiet?
838
+ opt << "--op=#{output}"
839
+ opt << "--title=#{title}"
840
+ opt << "--main=#{main}" if main
841
+ opt << files
842
+ opt = opt.flatten
843
+ cmd = "rdoc " + opt.join(' ')
844
+ if trial?
845
+ puts cmd
846
+ else
847
+ begin
848
+ system(cmd)
849
+ puts "Ok rdoc." unless quiet?
850
+ rescue Exception
851
+ puts "Fail rdoc."
852
+ puts "Command was: '#{cmd}'"
853
+ puts "Proceeding with install anyway."
854
+ end
855
+ end
856
+ end
857
+ end
858
+ end
859
+ module Setup
860
+ class Installer < Base
861
+ def install_prefix
862
+ config.install_prefix
863
+ end
864
+ def install
865
+ Dir.chdir(rootdir) do
866
+ install_bin
867
+ install_ext
868
+ install_lib
869
+ install_data
870
+ install_man
871
+ install_doc
872
+ install_etc
873
+ prune_install_record
874
+ end
875
+ end
876
+ def install_bin
877
+ return unless directory?('bin')
878
+ report_transfer('bin', config.bindir)
879
+ files = files('bin')
880
+ install_files('bin', files, config.bindir, 0755)
881
+ end
882
+ def install_ext
883
+ return unless directory?('ext')
884
+ report_transfer('ext', config.sodir)
885
+ files = files('ext')
886
+ files = select_dllext(files)
887
+ files.each do |file|
888
+ name = File.join(File.dirname(File.dirname(file)), File.basename(file))
889
+ dest = destination(config.sodir, name)
890
+ install_file('ext', file, dest, 0555, install_prefix)
891
+ end
892
+ end
893
+ def install_lib
894
+ return unless directory?('lib')
895
+ report_transfer('lib', config.rbdir)
896
+ files = files('lib')
897
+ install_files('lib', files, config.rbdir, 0644)
898
+ end
899
+ def install_data
900
+ return unless directory?('data')
901
+ report_transfer('data', config.datadir)
902
+ files = files('data')
903
+ install_files('data', files, config.datadir, 0644)
904
+ end
905
+ def install_etc
906
+ return unless directory?('etc')
907
+ report_transfer('etc', config.sysconfdir)
908
+ files = files('etc')
909
+ install_files('etc', files, config.sysconfdir, 0644)
910
+ end
911
+ def install_man
912
+ return unless directory?('man')
913
+ report_transfer('man', config.mandir)
914
+ files = files('man')
915
+ install_files('man', files, config.mandir, 0644)
916
+ end
917
+ def install_doc
918
+ return unless config.doc?
919
+ return unless directory?('doc')
920
+ return unless project.name
921
+ dir = File.join(config.docdir, "ruby-{project.name}")
922
+ report_transfer('doc', dir)
923
+ files = files('doc')
924
+ install_files('doc', files, dir, 0644)
925
+ end
926
+ private
927
+ def report_transfer(source, directory)
928
+ unless quiet?
929
+ if install_prefix
930
+ out = File.join(install_prefix, directory)
931
+ else
932
+ out = directory
933
+ end
934
+ io.puts "* #{source} -> #{out}"
935
+ end
936
+ end
937
+ def directory?(path)
938
+ File.directory?(path)
939
+ end
940
+ def files(dir)
941
+ files = Dir["#{dir}/**/*"]
942
+ files = files.select{ |f| File.file?(f) }
943
+ files = files.map{ |f| f.sub("#{dir}/", '') }
944
+ files
945
+ end
946
+ def select_dllext(files)
947
+ ents = files.select do |file|
948
+ File.extname(file) == ".#{dllext}"
949
+ end
950
+ if ents.empty? && !files.empty?
951
+ raise Error, "ruby extention not compiled: 'setup.rb setup' first"
952
+ end
953
+ ents
954
+ end
955
+ def dllext
956
+ config.dlext
957
+ end
958
+ def install_files(dir, list, dest, mode)
959
+ list.each do |fname|
960
+ rdest = destination(dest, fname)
961
+ install_file(dir, fname, rdest, mode, install_prefix)
962
+ end
963
+ end
964
+ def install_file(dir, from, dest, mode, prefix=nil)
965
+ mkdir_p(File.dirname(dest))
966
+ if trace? or trial?
967
+ io.puts "install #{dir}/#{from} #{dest}"
968
+ end
969
+ return if trial?
970
+ str = binread(File.join(dir, from))
971
+ if diff?(str, dest)
972
+ trace_off {
973
+ rm_f(dest) if File.exist?(dest)
974
+ }
975
+ File.open(dest, 'wb'){ |f| f.write(str) }
976
+ File.chmod(mode, dest)
977
+ end
978
+ record_installation(dest) # record file as installed
979
+ end
980
+ def mkdir_p(dirname) #, prefix=nil)
981
+ return if File.directory?(dirname)
982
+ io.puts "mkdir -p #{dirname}" if trace? or trial?
983
+ return if trial?
984
+ dirs = File.expand_path(dirname).split(%r<(?=/)>)
985
+ if /\A[a-z]:\z/i =~ dirs[0]
986
+ disk = dirs.shift
987
+ dirs[0] = disk + dirs[0]
988
+ end
989
+ dirs.each_index do |idx|
990
+ path = dirs[0..idx].join('')
991
+ unless File.dir?(path)
992
+ Dir.mkdir(path)
993
+ end
994
+ record_installation(path) # record directories made
995
+ end
996
+ end
997
+ def record_installation(path)
998
+ File.open(install_record, 'a') do |f|
999
+ f.puts(path)
1000
+ end
1001
+ end
1002
+ def prune_install_record
1003
+ entries = File.read(install_record).split("\n")
1004
+ entries.uniq!
1005
+ File.open(install_record, 'w') do |f|
1006
+ f << entries.join("\n")
1007
+ f << "\n"
1008
+ end
1009
+ end
1010
+ def install_record
1011
+ @install_record ||= (
1012
+ file = INSTALL_RECORD
1013
+ dir = File.dirname(file)
1014
+ unless File.directory?(dir)
1015
+ FileUtils.mkdir_p(dir)
1016
+ end
1017
+ file
1018
+ )
1019
+ end
1020
+ def destination(dir, file)
1021
+ dest = install_prefix ? File.join(install_prefix, File.expand_path(dir)) : dir
1022
+ dest = File.join(dest, file) #if File.dir?(dest)
1023
+ dest = File.expand_path(dest)
1024
+ dest
1025
+ end
1026
+ def diff?(new_content, path)
1027
+ return true unless File.exist?(path)
1028
+ new_content != binread(path)
1029
+ end
1030
+ def binread(fname)
1031
+ File.open(fname, 'rb') do |f|
1032
+ return f.read
1033
+ end
1034
+ end
1035
+ def install_shebang(files, dir)
1036
+ files.each do |file|
1037
+ path = File.join(dir, File.basename(file))
1038
+ update_shebang_line(path)
1039
+ end
1040
+ end
1041
+ def update_shebang_line(path)
1042
+ return if trial?
1043
+ return if config.shebang == 'never'
1044
+ old = Shebang.load(path)
1045
+ if old
1046
+ if old.args.size > 1
1047
+ $stderr.puts "warning: #{path}"
1048
+ $stderr.puts "Shebang line has too many args."
1049
+ $stderr.puts "It is not portable and your program may not work."
1050
+ end
1051
+ new = new_shebang(old)
1052
+ return if new.to_s == old.to_s
1053
+ else
1054
+ return unless config.shebang == 'all'
1055
+ new = Shebang.new(config.rubypath)
1056
+ end
1057
+ $stderr.puts "updating shebang: #{File.basename(path)}" if trace?
1058
+ open_atomic_writer(path) do |output|
1059
+ File.open(path, 'rb') do |f|
1060
+ f.gets if old # discard
1061
+ output.puts new.to_s
1062
+ output.print f.read
1063
+ end
1064
+ end
1065
+ end
1066
+ def new_shebang(old)
1067
+ if /\Aruby/ =~ File.basename(old.cmd)
1068
+ Shebang.new(config.rubypath, old.args)
1069
+ elsif File.basename(old.cmd) == 'env' and old.args.first == 'ruby'
1070
+ Shebang.new(config.rubypath, old.args[1..-1])
1071
+ else
1072
+ return old unless config.shebang == 'all'
1073
+ Shebang.new(config.rubypath)
1074
+ end
1075
+ end
1076
+ def open_atomic_writer(path, &block)
1077
+ tmpfile = File.basename(path) + '.tmp'
1078
+ begin
1079
+ File.open(tmpfile, 'wb', &block)
1080
+ File.rename tmpfile, File.basename(path)
1081
+ ensure
1082
+ File.unlink tmpfile if File.exist?(tmpfile)
1083
+ end
1084
+ end
1085
+ class Shebang
1086
+ def Shebang.load(path)
1087
+ line = nil
1088
+ File.open(path) {|f|
1089
+ line = f.gets
1090
+ }
1091
+ return nil unless /\A#!/ =~ line
1092
+ parse(line)
1093
+ end
1094
+ def Shebang.parse(line)
1095
+ cmd, *args = *line.strip.sub(/\A\#!/, '').split(' ')
1096
+ new(cmd, args)
1097
+ end
1098
+ def initialize(cmd, args = [])
1099
+ @cmd = cmd
1100
+ @args = args
1101
+ end
1102
+ attr_reader :cmd
1103
+ attr_reader :args
1104
+ def to_s
1105
+ "#! #{@cmd}" + (@args.empty? ? '' : " #{@args.join(' ')}")
1106
+ end
1107
+ end
1108
+ end
1109
+ end
1110
+ module Setup
1111
+ class Tester < Base
1112
+ RUBYSCRIPT = META_EXTENSION_DIR + '/testrc.rb'
1113
+ SHELLSCRIPT = 'script/test'
1114
+ def testable?
1115
+ return false if config.no_test
1116
+ return true if File.exist?(RUBYSCRIPT)
1117
+ return true if File.exist?(SHELLSCRIPT)
1118
+ false
1119
+ end
1120
+ def test
1121
+ return true if !testable?
1122
+ if File.exist?(RUBYSCRIPT)
1123
+ test_rubyscript
1124
+ elsif File.exist?(SHELLSCRIPT)
1125
+ test_shellscript
1126
+ end
1127
+ end
1128
+ def test_shellscript
1129
+ bash(SHELLSCRIPT)
1130
+ end
1131
+ def test_rubyscript
1132
+ ruby(RUBYSCRIPT)
1133
+ end
1134
+ end
1135
+ end
1136
+ module Setup
1137
+ class Uninstaller < Base
1138
+ def uninstall
1139
+ return unless File.exist?(INSTALL_RECORD)
1140
+ files = []
1141
+ dirs = []
1142
+ paths.each do |path|
1143
+ dirs << path if File.dir?(path)
1144
+ files << path if File.file?(path)
1145
+ end
1146
+ if dirs.empty? && files.empty?
1147
+ io.outs "Nothing to remove."
1148
+ return
1149
+ end
1150
+ files.sort!{ |a,b| b.size <=> a.size }
1151
+ dirs.sort!{ |a,b| b.size <=> a.size }
1152
+ if !force? && !trial?
1153
+ puts (files + dirs).collect{ |f| "#{f}" }.join("\n")
1154
+ puts
1155
+ puts "Must use --force option to remove these files and directories that become empty."
1156
+ return
1157
+ end
1158
+ files.each do |file|
1159
+ rm_f(file)
1160
+ end
1161
+ dirs.each do |dir|
1162
+ entries = Dir.entries(dir)
1163
+ entries.delete('.')
1164
+ entries.delete('..')
1165
+ rmdir(dir) if entries.empty?
1166
+ end
1167
+ rm_f(INSTALL_RECORD)
1168
+ end
1169
+ private
1170
+ def paths
1171
+ @paths ||= (
1172
+ lines = File.read(INSTALL_RECORD).split(/\s*\n/)
1173
+ lines = lines.map{ |line| line.strip }
1174
+ lines = lines.uniq
1175
+ lines = lines.reject{ |line| line.empty? } # skip blank lines
1176
+ lines = lines.reject{ |line| line[0,1] == '#' } # skip blank lines
1177
+ lines
1178
+ )
1179
+ end
1180
+ end
1181
+ end
1182
+ require 'optparse'
1183
+ module Setup
1184
+ class Command
1185
+ def self.run(*argv)
1186
+ new.run(*argv)
1187
+ end
1188
+ def self.tasks
1189
+ @tasks ||= {}
1190
+ end
1191
+ def self.order
1192
+ @order ||= []
1193
+ end
1194
+ def self.task(name, description)
1195
+ tasks[name] = description
1196
+ order << name
1197
+ end
1198
+ task 'all' , "config, setup, test, install"
1199
+ task 'config' , "saves your configuration"
1200
+ task 'show' , "show current configuration"
1201
+ task 'make' , "compile ruby extentions"
1202
+ task 'test' , "run test suite"
1203
+ task 'doc' , "generate ri documentation"
1204
+ task 'install' , "install project files"
1205
+ task 'uninstall', "uninstall previously installed files"
1206
+ task 'clean' , "does `make clean' for each extention"
1207
+ task 'distclean', "does `make distclean' for each extention"
1208
+ def run(*argv)
1209
+ ARGV.replace(argv) unless argv.empty?
1210
+ task = ARGV.find{ |a| a !~ /^[-]/ }
1211
+ task = 'all' unless task
1212
+ unless task_names.include?(task)
1213
+ $stderr.puts "Not a valid task -- #{task}"
1214
+ exit 1
1215
+ end
1216
+ parser = OptionParser.new
1217
+ options = {}
1218
+ parser.banner = "Usage: #{File.basename($0)} [TASK] [OPTIONS]"
1219
+ optparse_header(parser, options)
1220
+ case task
1221
+ when 'all'
1222
+ optparse_all(parser, options)
1223
+ when 'config'
1224
+ optparse_config(parser, options)
1225
+ when 'install'
1226
+ optparse_install(parser, options)
1227
+ end
1228
+ optparse_common(parser, options)
1229
+ begin
1230
+ parser.parse!(ARGV)
1231
+ rescue OptionParser::InvalidOption
1232
+ $stderr.puts $!.to_s.capitalize
1233
+ exit 1
1234
+ end
1235
+ rootdir = session.project.rootdir
1236
+ print_header
1237
+ begin
1238
+ session.__send__(task)
1239
+ rescue Error
1240
+ raise if $DEBUG
1241
+ $stderr.puts $!.message
1242
+ $stderr.puts "Try 'setup.rb --help' for detailed usage."
1243
+ exit 1
1244
+ end
1245
+ puts unless session.quiet?
1246
+ end
1247
+ def session
1248
+ @session ||= Session.new(:io=>$stdout)
1249
+ end
1250
+ def configuration
1251
+ @configuration ||= session.configuration
1252
+ end
1253
+ def optparse_header(parser, options)
1254
+ parser.banner = "USAGE: #{File.basename($0)} [command] [options]"
1255
+ end
1256
+ def optparse_all(parser, options)
1257
+ optparse_config(parser, options)
1258
+ end
1259
+ def optparse_config(parser, options)
1260
+ parser.separator ""
1261
+ parser.separator "Configuration options:"
1262
+ configuration.options.each do |args|
1263
+ args = args.dup
1264
+ desc = args.pop
1265
+ type = args.pop
1266
+ name, shortcut = *args
1267
+ optname = name.to_s.gsub('_', '-')
1268
+ case type
1269
+ when :bool
1270
+ if optname.index('no-') == 0
1271
+ optname = "[no-]" + optname.sub(/^no-/, '')
1272
+ opts = shortcut ? ["-#{shortcut}", "--#{optname}", desc] : ["--#{optname}", desc]
1273
+ parser.on(*opts) do |val|
1274
+ configuration.__send__("#{name}=", !val)
1275
+ end
1276
+ else
1277
+ optname = "[no-]" + optname.sub(/^no-/, '')
1278
+ opts = shortcut ? ["-#{shortcut}", "--#{optname}", desc] : ["--#{optname}", desc]
1279
+ parser.on(*opts) do |val|
1280
+ configuration.__send__("#{name}=", val)
1281
+ end
1282
+ end
1283
+ else
1284
+ opts = shortcut ? ["-#{shortcut}", "--#{optname} #{type.to_s.upcase}", desc] : ["--#{optname} #{type.to_s.upcase}", desc]
1285
+ parser.on(*opts) do |val|
1286
+ configuration.__send__("#{name}=", val)
1287
+ end
1288
+ end
1289
+ end
1290
+ end
1291
+ def optparse_install(parser, options)
1292
+ parser.separator ""
1293
+ parser.separator "Install options:"
1294
+ parser.on("--prefix PATH", "Installation prefix") do |val|
1295
+ configuration.install_prefix = val
1296
+ end
1297
+ end
1298
+ def optparse_common(parser, options)
1299
+ parser.separator ""
1300
+ parser.separator "General options:"
1301
+ parser.on("-q", "--quiet", "Suppress output") do
1302
+ session.quiet = true
1303
+ end
1304
+ parser.on("-f", "--force", "Force operation") do
1305
+ session.force = true
1306
+ end
1307
+ parser.on("--trace", "--verbose", "Watch execution") do |val|
1308
+ session.trace = true
1309
+ end
1310
+ parser.on("--trial", "--no-harm", "Do not write to disk") do |val|
1311
+ session.trial = true
1312
+ end
1313
+ parser.on("--debug", "Turn on debug mode") do |val|
1314
+ $DEBUG = true
1315
+ end
1316
+ parser.separator ""
1317
+ parser.separator "Inform options:"
1318
+ parser.on_tail("-h", "--help", "display this help information") do
1319
+ puts parser
1320
+ exit
1321
+ end
1322
+ parser.on_tail("--version", "-v", "Show version") do
1323
+ puts File.basename($0) + ' v' + Setup::VERSION #Version.join('.')
1324
+ exit
1325
+ end
1326
+ parser.on_tail("--copyright", "Show copyright") do
1327
+ puts Setup::COPYRIGHT #opyright
1328
+ exit
1329
+ end
1330
+ end
1331
+ def task_names
1332
+ self.class.tasks.keys
1333
+ end
1334
+ def print_header
1335
+ end
1336
+ end
1337
+ end
1338
+ Setup::Command.run