autoload 0.1.0 → 0.2.0

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