mathgl 0.1.0 → 0.1.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 88f676dd949dc3aad0984447f5a44be418f235a4
4
- data.tar.gz: 7884864681617c80757b14e494c0cf5ebf0f7841
3
+ metadata.gz: f5435d0d7cb9f28e8478dbec91d1bdc9a2ac3b68
4
+ data.tar.gz: f1dd7211b22c511a0d73abda123c2e742475c8cd
5
5
  SHA512:
6
- metadata.gz: e4fdc6f900da1cdd5e7df788d559bd83a59d2679fdd28350fa41f5c0cc77c39fa6a7097388c6508805266e50db4f76556c69e69b7bb099eea240efe656574bb4
7
- data.tar.gz: 226c6f868654dca0b0cafdc916667c31352c6f4ba2ab518bd4e9ea4eb8c45ee94b0d00eadcb971be88f80c7e3f506b6328fa0da1b9410a4dfd09ad53abd14967
6
+ metadata.gz: f0a651682c339c2febb56e2277986843c005a3ea0127ed4486bb07386c9f2205d5ec6ca87341e77b9ebfffeffbde3c038e0b0b44e5a2e791516202db02265f52
7
+ data.tar.gz: 2103e6ee774658c8419ce5141e78c5ccbec28e3b7089eeef1c8c69d5008c4e414e8f4cb48ed5b3e33827300506642f68e59704e261bc71a1f604bfdceb2f751c
data/.gitignore CHANGED
@@ -5,6 +5,8 @@
5
5
  .yardoc
6
6
  Gemfile.lock
7
7
  InstalledFiles
8
+ SetupConfig
9
+ SetupReceipt
8
10
  _yardoc
9
11
  coverage
10
12
  doc/
data/README.md CHANGED
@@ -61,6 +61,12 @@ Display a plot on Qt window:
61
61
  qt = MathGL::MglQT.new(&prc)
62
62
  qt.run
63
63
 
64
+ ## Version
65
+
66
+ - MathGL 2.3.3
67
+ - Ruby 2.3.0
68
+ - CentOS 7.2
69
+
64
70
  ## Contributing
65
71
 
66
72
  1. Fork it
@@ -6,10 +6,13 @@ require "mkmf"
6
6
  # --with-mathgl-lib=path
7
7
 
8
8
  dir_config("mathgl")
9
- exit unless have_header("mgl2/type.h")
10
- exit unless have_header("mgl2/data.h")
11
- exit unless have_header("mgl2/mgl.h")
12
- exit unless have_library("mgl")
9
+ # check C++ header
10
+ with_cflags("-x c++ -lstdc++") do
11
+ exit unless have_header("mgl2/type.h")
12
+ exit unless have_header("mgl2/data.h")
13
+ exit unless have_header("mgl2/mgl.h")
14
+ exit unless have_library("mgl")
15
+ end
13
16
  $objs = ["mathgl.o"]
14
17
  if have_header("mgl2/qt.h") && have_library("mgl-qt")
15
18
  $objs << "qt.o"
@@ -0,0 +1,38 @@
1
+ $ diff -u ~/2015/src/mathgl-2.3.2/lang/mathgl.i ruby-mathgl/ext/mathgl/mathgl.i
2
+ --- /home/masa/2015/src/mathgl-2.3.2/lang/mathgl.i 2015-02-02 20:13:21.000000000 +0900
3
+ +++ ruby-mathgl/ext/mathgl/mathgl.i 2015-05-09 18:57:29.798078188 +0900
4
+ @@ -21,13 +21,23 @@
5
+ ***************************************************************************/
6
+
7
+
8
+ +#ifdef SWIGRUBY
9
+ +%module MathGL
10
+ +#else
11
+ %module mathgl
12
+ +#endif
13
+ +
14
+ #ifdef SWIGOCTAVE
15
+ %feature("autodoc", 1);
16
+ #endif // SWIGOCTAVE
17
+
18
+ +#ifdef SWIGRUBY
19
+ +%feature("autodoc", 2);
20
+ +#endif
21
+ +
22
+ %ignore operator!;
23
+ %ignore operator=;
24
+ +%ignore operator!=;
25
+ %ignore *::operator=;
26
+ %ignore *::operator+=;
27
+ %ignore *::operator-=;
28
+ @@ -87,6 +97,10 @@
29
+ %apply (int DIM1, int DIM2, int DIM3, double* IN_ARRAY3) {(int rows, int cols, int slc, const double* d)};
30
+ #endif
31
+
32
+ +#ifdef SWIGRUBY
33
+ +%include "rubymgl.i"
34
+ +#endif
35
+ +
36
+ %include "type.i"
37
+ %include "data.i"
38
+ %include "mgl.i"
@@ -1,3 +1,3 @@
1
1
  module MathGL
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
data/setup.rb CHANGED
@@ -1,1588 +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
- 'rb-dir' => 'rbdir',
285
- 'so-dir' => 'sodir',
286
- 'data-dir' => 'datadir',
287
- 'ruby-path' => 'rubypath',
288
- 'ruby-prog' => 'rubyprog',
289
- 'ruby' => 'rubyprog',
290
- 'make-prog' => 'makeprog',
291
- 'make' => 'makeprog'
292
- }
293
-
294
- def fixup
295
- ALIASES.each do |ali, name|
296
- @table[ali] = @table[name]
297
- end
298
- @items.freeze
299
- @table.freeze
300
- @options_re = /\A--(#{@table.keys.join('|')})(?:=(.*))?\z/
301
- end
302
-
303
- def parse_opt(opt)
304
- m = @options_re.match(opt) or setup_rb_error "config: unknown option #{opt}"
305
- m.to_a[1,2]
306
- end
307
-
308
- def dllext
309
- @rbconfig['DLEXT']
310
- end
311
-
312
- def value_config?(name)
313
- lookup(name).value?
314
- end
315
-
316
- class Item
317
- def initialize(name, template, default, desc)
318
- @name = name.freeze
319
- @template = template
320
- @value = default
321
- @default = default
322
- @description = desc
323
- end
324
-
325
- attr_reader :name
326
- attr_reader :description
327
-
328
- attr_accessor :default
329
- alias help_default default
330
-
331
- def help_opt
332
- "--#{@name}=#{@template}"
333
- end
334
-
335
- def value?
336
- true
86
+ def extensions
87
+ @extensions ||= extconfs.collect{ |f| File.dirname(f) }
337
88
  end
338
-
339
- def value
340
- @value
89
+ def compiles?
90
+ !extensions.empty?
341
91
  end
342
-
343
- def resolve(table)
344
- @value.gsub(%r<\$([^/]+)>) { table[$1] }
92
+ def yardopts
93
+ Dir.glob(File.join(rootdir, '.yardopts')).first
345
94
  end
346
-
347
- def set(val)
348
- @value = check(val)
95
+ def document
96
+ Dir.glob(File.join(rootdir, '.document')).first
349
97
  end
350
-
351
- private
352
-
353
- def check(val)
354
- setup_rb_error "config: --#{name} requires argument" unless val
355
- 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
356
106
  end
357
107
  end
358
-
359
- class BoolItem < Item
360
- def config_type
361
- 'bool'
362
- end
363
-
364
- def help_opt
365
- "--#{@name}"
366
- end
367
-
368
- private
369
-
370
- def check(val)
371
- return 'yes' unless val
372
- case val
373
- when /\Ay(es)?\z/i, /\At(rue)?\z/i then 'yes'
374
- 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?
375
156
  else
376
- 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
377
167
  end
378
168
  end
379
- end
380
-
381
- class PathItem < Item
382
- def config_type
383
- 'path'
384
- end
385
-
386
- private
387
-
388
- def check(path)
389
- setup_rb_error "config: --#{@name} requires argument" unless path
390
- 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.')
391
196
  end
392
- end
393
-
394
- class ProgramItem < Item
395
- def config_type
396
- 'program'
197
+ def show
198
+ puts configuration
397
199
  end
398
- end
399
-
400
- class SelectItem < Item
401
- def initialize(name, selection, default, desc)
402
- super
403
- @ok = selection.split('/')
200
+ def project
201
+ @project ||= Project.new
404
202
  end
405
-
406
- def config_type
407
- 'select'
203
+ def configuration
204
+ @configuration ||= Configuration.new
408
205
  end
409
-
410
- private
411
-
412
- def check(val)
413
- unless @ok.include?(val.strip)
414
- 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}"
415
224
  end
416
- val.strip
225
+ line = "- " * 35
226
+ line[0..str.size+3] = str
227
+ io.puts("\n- - #{line}\n\n")
417
228
  end
418
229
  end
419
-
420
- class ExecItem < Item
421
- def initialize(name, selection, desc, &block)
422
- super name, selection, nil, desc
423
- @ok = selection.split('/')
424
- @action = block
425
- end
426
-
427
- def config_type
428
- 'exec'
429
- end
430
-
431
- def value?
432
- 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
433
247
  end
434
-
435
- def resolve(table)
436
- 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
437
254
  end
438
-
439
- undef set
440
-
441
- def evaluate(val, table)
442
- v = val.strip.downcase
443
- unless @ok.include?(v)
444
- 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
445
276
  end
446
- @action.call v, table
447
277
  end
448
- end
449
-
450
- class PackageSelectionItem < Item
451
- def initialize(name, template, default, help_default, desc)
452
- super name, template, default, desc
453
- @help_default = help_default
454
- end
455
-
456
- attr_reader :help_default
457
-
458
- def config_type
459
- 'package'
460
- end
461
-
462
- private
463
-
464
- def check(val)
465
- unless File.dir?("packages/#{val}")
466
- setup_rb_error "config: no such package: #{val}"
467
- end
468
- 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)
469
282
  end
470
- end
471
-
472
- class MetaConfigEnvironment
473
- def initialize(config, installer)
474
- @config = config
475
- @installer = installer
476
- end
477
-
478
- def config_names
479
- @config.names
480
- end
481
-
482
- def config?(name)
483
- @config.key?(name)
484
- end
485
-
486
- def bool_config?(name)
487
- @config.lookup(name).config_type == 'bool'
488
- end
489
-
490
- def path_config?(name)
491
- @config.lookup(name).config_type == 'path'
492
- end
493
-
494
- def value_config?(name)
495
- @config.lookup(name).config_type != 'exec'
496
- end
497
-
498
- def add_config(item)
499
- @config.add item
500
- end
501
-
502
- def add_bool_config(name, default, desc)
503
- @config.add BoolItem.new(name, 'yes/no', default ? 'yes' : 'no', desc)
504
- end
505
-
506
- def add_path_config(name, default, desc)
507
- @config.add PathItem.new(name, 'path', default, desc)
508
- end
509
-
510
- def set_config_default(name, default)
511
- @config.lookup(name).default = default
512
- end
513
-
514
- def remove_config(name)
515
- @config.remove(name)
516
- end
517
-
518
- # For only multipackage
519
- def packages
520
- raise '[setup.rb fatal] multi-package metaconfig API packages() called for single-package; contact application package vendor' unless @installer
521
- @installer.packages
522
- end
523
-
524
- # For only multipackage
525
- def declare_packages(list)
526
- raise '[setup.rb fatal] multi-package metaconfig API declare_packages() called for single-package; contact application package vendor' unless @installer
527
- @installer.packages = list
283
+ def force_remove_file(path)
284
+ begin
285
+ remove_file(path)
286
+ rescue
287
+ end
528
288
  end
529
- end
530
-
531
- end # class ConfigTable
532
-
533
-
534
- # This module requires: #verbose?, #no_harm?
535
- module FileOperations
536
-
537
- def mkdir_p(dirname, prefix = nil)
538
- dirname = prefix + File.expand_path(dirname) if prefix
539
- $stderr.puts "mkdir -p #{dirname}" if verbose?
540
- return if no_harm?
541
-
542
- # Does not check '/', it's too abnormal.
543
- dirs = File.expand_path(dirname).split(%r<(?=/)>)
544
- if /\A[a-z]:\z/i =~ dirs[0]
545
- disk = dirs.shift
546
- dirs[0] = disk + dirs[0]
547
- end
548
- dirs.each_index do |idx|
549
- path = dirs[0..idx].join('')
550
- 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)
551
297
  end
552
298
  end
553
-
554
- def rm_f(path)
555
- $stderr.puts "rm -f #{path}" if verbose?
556
- return if no_harm?
557
- force_remove_file path
558
- end
559
-
560
- def rm_rf(path)
561
- $stderr.puts "rm -rf #{path}" if verbose?
562
- return if no_harm?
563
- remove_tree path
299
+ class Error < StandardError
564
300
  end
565
-
566
- def remove_tree(path)
567
- if File.symlink?(path)
568
- remove_file path
569
- elsif File.dir?(path)
570
- remove_tree0 path
571
- else
572
- 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
315
+ end
316
+ def compile
317
+ extdirs.each do |dir|
318
+ Dir.chdir(dir) do
319
+ make
320
+ end
321
+ end
322
+ end
323
+ def clean
324
+ extdirs.each do |dir|
325
+ Dir.chdir(dir) do
326
+ make('clean')
327
+ end
328
+ end
329
+ end
330
+ def distclean
331
+ extdirs.each do |dir|
332
+ Dir.chdir(dir) do
333
+ make('distclean')
334
+ end
335
+ end
336
+ end
337
+ def extdirs
338
+ Dir['ext/**/*/{MANIFEST,extconf.rb}'].map do |f|
339
+ File.dirname(f)
340
+ end.uniq
341
+ end
342
+ def make(task=nil)
343
+ return unless File.exist?('Makefile')
344
+ bash(*[config.makeprog, task].compact)
573
345
  end
574
346
  end
575
-
576
- def remove_tree0(path)
577
- Dir.foreach(path) do |ent|
578
- next if ent == '.'
579
- next if ent == '..'
580
- entpath = "#{path}/#{ent}"
581
- if File.symlink?(entpath)
582
- remove_file entpath
583
- elsif File.dir?(entpath)
584
- remove_tree0 entpath
347
+ end
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("=")
585
401
  else
586
- force_remove_file entpath
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)
587
424
  end
588
425
  end
589
- begin
590
- Dir.rmdir path
591
- rescue Errno::ENOTEMPTY
592
- # directory may not be empty
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
438
+ end
593
439
  end
594
- end
595
-
596
- def move_file(src, dest)
597
- force_remove_file dest
598
- begin
599
- File.rename src, dest
600
- rescue
601
- File.open(dest, 'wb') {|f|
602
- f.write File.binread(src)
603
- }
604
- File.chmod File.stat(src).mode, dest
605
- File.unlink src
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
606
458
  end
607
- end
608
-
609
- def force_remove_file(path)
610
- begin
611
- remove_file path
612
- rescue
459
+ attr_accessor :reset
460
+ def base_bindir
461
+ @base_bindir ||= subprefix('bindir')
613
462
  end
614
- end
615
-
616
- def remove_file(path)
617
- File.chmod 0777, path
618
- File.unlink path
619
- end
620
-
621
- def install(from, dest, mode, prefix = nil)
622
- $stderr.puts "install #{from} #{dest}" if verbose?
623
- return if no_harm?
624
-
625
- realdest = prefix ? prefix + File.expand_path(dest) : dest
626
- realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest)
627
- str = File.binread(from)
628
- if diff?(str, realdest)
629
- verbose_off {
630
- rm_f realdest if File.exist?(realdest)
631
- }
632
- File.open(realdest, 'wb') {|f|
633
- f.write str
634
- }
635
- File.chmod mode, realdest
636
-
637
- File.open("#{objdir_root()}/InstalledFiles", 'a') {|f|
638
- if prefix
639
- f.puts realdest.sub(prefix, '')
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'
503
+ else
504
+ raise Error, "bad config: use type=(std|site|home) [#{val}]"
505
+ end
506
+ end
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']
513
+ end
514
+ def prefix=(path)
515
+ @prefix = pathname(path)
516
+ end
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]
640
623
  else
641
- f.puts realdest
624
+ 'make'
642
625
  end
643
- }
626
+ )
644
627
  end
645
- end
646
-
647
- def diff?(new_content, path)
648
- return true unless File.exist?(path)
649
- new_content != File.binread(path)
650
- end
651
-
652
- def command(*args)
653
- $stderr.puts args.join(' ') if verbose?
654
- system(*args) or raise RuntimeError,
655
- "system(#{args.map{|a| a.inspect }.join(' ')}) failed"
656
- end
657
-
658
- def ruby(*args)
659
- command config('rubyprog'), *args
660
- end
661
-
662
- def make(task = nil)
663
- command(*[config('makeprog'), task].compact)
664
- end
665
-
666
- def extdir?(dir)
667
- File.exist?("#{dir}/MANIFEST") or File.exist?("#{dir}/extconf.rb")
668
- end
669
-
670
- def files_of(dir)
671
- Dir.open(dir) {|d|
672
- return d.select {|ent| File.file?("#{dir}/#{ent}") }
673
- }
674
- end
675
-
676
- DIR_REJECT = %w( . .. CVS SCCS RCS CVS.adm .svn )
677
-
678
- def directories_of(dir)
679
- Dir.open(dir) {|d|
680
- return d.select {|ent| File.dir?("#{dir}/#{ent}") } - DIR_REJECT
681
- }
682
- end
683
-
684
- end
685
-
686
-
687
- # This module requires: #srcdir_root, #objdir_root, #relpath
688
- module HookScriptAPI
689
-
690
- def get_config(key)
691
- @config[key]
692
- end
693
-
694
- alias config get_config
695
-
696
- # obsolete: use metaconfig to change configuration
697
- def set_config(key, val)
698
- @config[key] = val
699
- end
700
-
701
- #
702
- # srcdir/objdir (works only in the package directory)
703
- #
704
-
705
- def curr_srcdir
706
- "#{srcdir_root()}/#{relpath()}"
707
- end
708
-
709
- def curr_objdir
710
- "#{objdir_root()}/#{relpath()}"
711
- end
712
-
713
- def srcfile(path)
714
- "#{curr_srcdir()}/#{path}"
715
- end
716
-
717
- def srcexist?(path)
718
- File.exist?(srcfile(path))
719
- end
720
-
721
- def srcdirectory?(path)
722
- File.dir?(srcfile(path))
723
- end
724
-
725
- def srcfile?(path)
726
- File.file?(srcfile(path))
727
- end
728
-
729
- def srcentries(path = '.')
730
- Dir.open("#{curr_srcdir()}/#{path}") {|d|
731
- return d.to_a - %w(. ..)
732
- }
733
- end
734
-
735
- def srcfiles(path = '.')
736
- srcentries(path).select {|fname|
737
- File.file?(File.join(curr_srcdir(), path, fname))
738
- }
739
- end
740
-
741
- def srcdirectories(path = '.')
742
- srcentries(path).select {|fname|
743
- File.dir?(File.join(curr_srcdir(), path, fname))
744
- }
745
- end
746
-
747
- end
748
-
749
-
750
- class ToplevelInstaller
751
-
752
- Version = '3.4.1'
753
- Copyright = 'Copyright (c) 2000-2005 Minero Aoki'
754
-
755
- TASKS = [
756
- [ 'all', 'do config, setup, then install' ],
757
- [ 'config', 'saves your configurations' ],
758
- [ 'show', 'shows current configuration' ],
759
- [ 'setup', 'compiles ruby extentions and others' ],
760
- [ 'install', 'installs files' ],
761
- [ 'test', 'run all tests in test/' ],
762
- [ 'clean', "does `make clean' for each extention" ],
763
- [ 'distclean',"does `make distclean' for each extention" ]
764
- ]
765
-
766
- def ToplevelInstaller.invoke
767
- config = ConfigTable.new(load_rbconfig())
768
- config.load_standard_entries
769
- config.load_multipackage_entries if multipackage?
770
- config.fixup
771
- klass = (multipackage?() ? ToplevelInstallerMulti : ToplevelInstaller)
772
- klass.new(File.dirname($0), config).invoke
773
- end
774
-
775
- def ToplevelInstaller.multipackage?
776
- File.dir?(File.dirname($0) + '/packages')
777
- end
778
-
779
- def ToplevelInstaller.load_rbconfig
780
- if arg = ARGV.detect {|arg| /\A--rbconfig=/ =~ arg }
781
- ARGV.delete(arg)
782
- load File.expand_path(arg.split(/=/, 2)[1])
783
- $".push 'rbconfig.rb'
784
- else
785
- require 'rbconfig'
786
- end
787
- if defined? ::RbConfig
788
- ::RbConfig::CONFIG
789
- else
790
- ::Config::CONFIG
628
+ def makeprog=(command)
629
+ @makeprog = command
791
630
  end
792
- end
793
-
794
- def initialize(ardir_root, config)
795
- @ardir = File.expand_path(ardir_root)
796
- @config = config
797
- # cache
798
- @valid_task_re = nil
799
- end
800
-
801
- def config(key)
802
- @config[key]
803
- end
804
-
805
- def inspect
806
- "#<#{self.class} #{__id__()}>"
807
- end
808
-
809
- def invoke
810
- run_metaconfigs
811
- case task = parsearg_global()
812
- when nil, 'all'
813
- parsearg_config
814
- init_installers
815
- exec_config
816
- exec_setup
817
- exec_install
818
- else
819
- case task
820
- when 'config', 'test'
821
- ;
822
- when 'clean', 'distclean'
823
- @config.load_savefile if File.exist?(@config.savefile)
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
824
643
  else
825
- @config.load_savefile
644
+ raise Error, "bad config: use SHEBANG=(all|ruby|never) [#{val}]"
826
645
  end
827
- __send__ "parsearg_#{task}"
828
- init_installers
829
- __send__ "exec_#{task}"
830
646
  end
831
- end
832
-
833
- def run_metaconfigs
834
- @config.load_script "#{@ardir}/metaconfig"
835
- end
836
-
837
- def init_installers
838
- @installer = Installer.new(@config, @ardir, File.expand_path('.'))
839
- end
840
-
841
- #
842
- # Hook Script API bases
843
- #
844
-
845
- def srcdir_root
846
- @ardir
847
- end
848
-
849
- def objdir_root
850
- '.'
851
- end
852
-
853
- def relpath
854
- '.'
855
- end
856
-
857
- #
858
- # Option Parsing
859
- #
860
-
861
- def parsearg_global
862
- while arg = ARGV.shift
863
- case arg
864
- when /\A\w+\z/
865
- setup_rb_error "invalid task: #{arg}" unless valid_task?(arg)
866
- return arg
867
- when '-q', '--quiet'
868
- @config.verbose = false
869
- when '--verbose'
870
- @config.verbose = true
871
- when '--help'
872
- print_usage $stdout
873
- exit 0
874
- when '--version'
875
- puts "#{File.basename($0)} version #{Version}"
876
- exit 0
877
- when '--copyright'
878
- puts Copyright
879
- exit 0
880
- else
881
- setup_rb_error "unknown global option '#{arg}'"
647
+ def no_ext
648
+ @no_ext
649
+ end
650
+ def no_ext=(val)
651
+ @no_ext = boolean(val)
652
+ end
653
+ def no_test
654
+ @no_test
655
+ end
656
+ def no_test=(val)
657
+ @no_test = boolean(val)
658
+ end
659
+ def no_doc
660
+ @no_doc
661
+ end
662
+ def no_doc=(val)
663
+ @no_doc = boolean(val)
664
+ end
665
+ def no_ri
666
+ @no_ri
667
+ end
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)
882
684
  end
685
+ h
883
686
  end
884
- nil
885
- end
886
-
887
- def valid_task?(t)
888
- valid_task_re() =~ t
889
- end
890
-
891
- def valid_task_re
892
- @valid_task_re ||= /\A(?:#{TASKS.map {|task,desc| task }.join('|')})\z/
893
- end
894
-
895
- def parsearg_no_options
896
- unless ARGV.empty?
897
- task = caller(0).first.slice(%r<`parsearg_(\w+)'>, 1)
898
- setup_rb_error "#{task}: unknown options: #{ARGV.join(' ')}"
687
+ def to_s
688
+ to_yaml.sub(/\A---\s*\n/,'')
899
689
  end
900
- end
901
-
902
- alias parsearg_show parsearg_no_options
903
- alias parsearg_setup parsearg_no_options
904
- alias parsearg_test parsearg_no_options
905
- alias parsearg_clean parsearg_no_options
906
- alias parsearg_distclean parsearg_no_options
907
-
908
- def parsearg_config
909
- evalopt = []
910
- set = []
911
- @config.config_opt = []
912
- while i = ARGV.shift
913
- if /\A--?\z/ =~ i
914
- @config.config_opt = ARGV.dup
915
- break
916
- end
917
- name, value = *@config.parse_opt(i)
918
- if @config.value_config?(name)
919
- @config[name] = value
920
- else
921
- evalopt.push [name, value]
690
+ def to_yaml(*args)
691
+ to_h.to_yaml(*args)
692
+ end
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))
922
697
  end
923
- set.push name
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
924
704
  end
925
- evalopt.each do |name, value|
926
- @config.lookup(name).evaluate value, @config
705
+ def exist?
706
+ File.exist?(CONFIG_FILE)
927
707
  end
928
- # Check if configuration is valid
929
- set.each do |n|
930
- @config[n] if @config.value_config?(n)
708
+ private
709
+ def pathname(path)
710
+ path.gsub(%r<\\$([^/]+)>){ self[$1] }
931
711
  end
932
- end
933
-
934
- def parsearg_install
935
- @config.no_harm = false
936
- @config.install_prefix = ''
937
- while a = ARGV.shift
938
- case a
939
- when '--no-harm'
940
- @config.no_harm = true
941
- when /\A--prefix=/
942
- path = a.split(/=/, 2)[1]
943
- path = File.expand_path(path) unless path[0,1] == '/'
944
- @config.install_prefix = path
712
+ def boolean(val, name=nil)
713
+ case val
714
+ when true, false, nil
715
+ val
945
716
  else
946
- setup_rb_error "install: unknown option #{a}"
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
947
725
  end
948
726
  end
949
- end
950
-
951
- def print_usage(out)
952
- out.puts 'Typical Installation Procedure:'
953
- out.puts " $ ruby #{File.basename $0} config"
954
- out.puts " $ ruby #{File.basename $0} setup"
955
- out.puts " # ruby #{File.basename $0} install (may require root privilege)"
956
- out.puts
957
- out.puts 'Detailed Usage:'
958
- out.puts " ruby #{File.basename $0} <global option>"
959
- out.puts " ruby #{File.basename $0} [<global options>] <task> [<task options>]"
960
-
961
- fmt = " %-24s %s\n"
962
- out.puts
963
- out.puts 'Global options:'
964
- out.printf fmt, '-q,--quiet', 'suppress message outputs'
965
- out.printf fmt, ' --verbose', 'output messages verbosely'
966
- out.printf fmt, ' --help', 'print this message'
967
- out.printf fmt, ' --version', 'print version and quit'
968
- out.printf fmt, ' --copyright', 'print copyright and quit'
969
- out.puts
970
- out.puts 'Tasks:'
971
- TASKS.each do |name, desc|
972
- out.printf fmt, name, desc
973
- end
974
-
975
- fmt = " %-24s %s [%s]\n"
976
- out.puts
977
- out.puts 'Options for CONFIG or ALL:'
978
- @config.each do |item|
979
- out.printf fmt, item.help_opt, item.description, item.help_default
980
- end
981
- out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',"running ruby's"
982
- out.puts
983
- out.puts 'Options for INSTALL:'
984
- out.printf fmt, '--no-harm', 'only display what to do if given', 'off'
985
- out.printf fmt, '--prefix=path', 'install path prefix', ''
986
- out.puts
987
- end
988
-
989
- #
990
- # Task Handlers
991
- #
992
-
993
- def exec_config
994
- @installer.exec_config
995
- @config.save # must be final
996
- end
997
-
998
- def exec_setup
999
- @installer.exec_setup
1000
- end
1001
-
1002
- def exec_install
1003
- @installer.exec_install
1004
- end
1005
-
1006
- def exec_test
1007
- @installer.exec_test
1008
- end
1009
-
1010
- def exec_show
1011
- @config.each do |i|
1012
- printf "%-20s %s\n", i.name, i.value if i.value?
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
1013
744
  end
1014
- end
1015
-
1016
- def exec_clean
1017
- @installer.exec_clean
1018
- end
1019
-
1020
- def exec_distclean
1021
- @installer.exec_distclean
1022
- end
1023
-
1024
- end # class ToplevelInstaller
1025
-
1026
-
1027
- class ToplevelInstallerMulti < ToplevelInstaller
1028
-
1029
- include FileOperations
1030
-
1031
- def initialize(ardir_root, config)
1032
- super
1033
- @packages = directories_of("#{@ardir}/packages")
1034
- raise 'no package exists' if @packages.empty?
1035
- @root_installer = Installer.new(@config, @ardir, File.expand_path('.'))
1036
- end
1037
-
1038
- def run_metaconfigs
1039
- @config.load_script "#{@ardir}/metaconfig", self
1040
- @packages.each do |name|
1041
- @config.load_script "#{@ardir}/packages/#{name}/metaconfig"
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
1042
791
  end
1043
- end
1044
-
1045
- attr_reader :packages
1046
-
1047
- def packages=(list)
1048
- raise 'package list is empty' if list.empty?
1049
- list.each do |name|
1050
- raise "directory packages/#{name} does not exist"\
1051
- unless File.dir?("#{@ardir}/packages/#{name}")
1052
- end
1053
- @packages = list
1054
- end
1055
-
1056
- def init_installers
1057
- @installers = {}
1058
- @packages.each do |pack|
1059
- @installers[pack] = Installer.new(@config,
1060
- "#{@ardir}/packages/#{pack}",
1061
- "packages/#{pack}")
1062
- end
1063
- with = extract_selection(config('with'))
1064
- without = extract_selection(config('without'))
1065
- @selected = @installers.keys.select {|name|
1066
- (with.empty? or with.include?(name)) \
1067
- and not without.include?(name)
1068
- }
1069
- end
1070
-
1071
- def extract_selection(list)
1072
- a = list.split(/,/)
1073
- a.each do |name|
1074
- setup_rb_error "no such package: #{name}" unless @installers.key?(name)
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
1075
809
  end
1076
- a
1077
- end
1078
-
1079
- def print_usage(f)
1080
- super
1081
- f.puts 'Inluded packages:'
1082
- f.puts ' ' + @packages.sort.join(' ')
1083
- f.puts
1084
- end
1085
-
1086
- #
1087
- # Task Handlers
1088
- #
1089
-
1090
- def exec_config
1091
- run_hook 'pre-config'
1092
- each_selected_installers {|inst| inst.exec_config }
1093
- run_hook 'post-config'
1094
- @config.save # must be final
1095
- end
1096
-
1097
- def exec_setup
1098
- run_hook 'pre-setup'
1099
- each_selected_installers {|inst| inst.exec_setup }
1100
- run_hook 'post-setup'
1101
- end
1102
-
1103
- def exec_install
1104
- run_hook 'pre-install'
1105
- each_selected_installers {|inst| inst.exec_install }
1106
- run_hook 'post-install'
1107
- end
1108
-
1109
- def exec_test
1110
- run_hook 'pre-test'
1111
- each_selected_installers {|inst| inst.exec_test }
1112
- run_hook 'post-test'
1113
- end
1114
-
1115
- def exec_clean
1116
- rm_f @config.savefile
1117
- run_hook 'pre-clean'
1118
- each_selected_installers {|inst| inst.exec_clean }
1119
- run_hook 'post-clean'
1120
- end
1121
-
1122
- def exec_distclean
1123
- rm_f @config.savefile
1124
- run_hook 'pre-distclean'
1125
- each_selected_installers {|inst| inst.exec_distclean }
1126
- run_hook 'post-distclean'
1127
- end
1128
-
1129
- #
1130
- # lib
1131
- #
1132
-
1133
- def each_selected_installers
1134
- Dir.mkdir 'packages' unless File.dir?('packages')
1135
- @selected.each do |pack|
1136
- $stderr.puts "Processing the package `#{pack}' ..." if verbose?
1137
- Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}")
1138
- Dir.chdir "packages/#{pack}"
1139
- yield @installers[pack]
1140
- Dir.chdir '../..'
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
1141
826
  end
1142
- end
1143
-
1144
- def run_hook(id)
1145
- @root_installer.run_hook id
1146
- end
1147
-
1148
- # module FileOperations requires this
1149
- def verbose?
1150
- @config.verbose?
1151
- end
1152
-
1153
- # module FileOperations requires this
1154
- def no_harm?
1155
- @config.no_harm?
1156
- end
1157
-
1158
- end # class ToplevelInstallerMulti
1159
-
1160
-
1161
- class Installer
1162
-
1163
- FILETYPES = %w( bin lib ext data conf man )
1164
-
1165
- include FileOperations
1166
- include HookScriptAPI
1167
-
1168
- def initialize(config, srcroot, objroot)
1169
- @config = config
1170
- @srcdir = File.expand_path(srcroot)
1171
- @objdir = File.expand_path(objroot)
1172
- @currdir = '.'
1173
- end
1174
-
1175
- def inspect
1176
- "#<#{self.class} #{File.basename(@srcdir)}>"
1177
- end
1178
-
1179
- def noop(rel)
1180
- end
1181
-
1182
- #
1183
- # Hook Script API base methods
1184
- #
1185
-
1186
- def srcdir_root
1187
- @srcdir
1188
- end
1189
-
1190
- def objdir_root
1191
- @objdir
1192
- end
1193
-
1194
- def relpath
1195
- @currdir
1196
- end
1197
-
1198
- #
1199
- # Config Access
1200
- #
1201
-
1202
- # module FileOperations requires this
1203
- def verbose?
1204
- @config.verbose?
1205
- end
1206
-
1207
- # module FileOperations requires this
1208
- def no_harm?
1209
- @config.no_harm?
1210
- end
1211
-
1212
- def verbose_off
1213
- begin
1214
- save, @config.verbose = @config.verbose?, false
1215
- yield
1216
- ensure
1217
- @config.verbose = save
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
1218
870
  end
1219
- end
1220
-
1221
- #
1222
- # TASK config
1223
- #
1224
-
1225
- def exec_config
1226
- exec_task_traverse 'config'
1227
- end
1228
-
1229
- alias config_dir_bin noop
1230
- alias config_dir_lib noop
1231
-
1232
- def config_dir_ext(rel)
1233
- extconf if extdir?(curr_srcdir())
1234
- end
1235
-
1236
- alias config_dir_data noop
1237
- alias config_dir_conf noop
1238
- alias config_dir_man noop
1239
-
1240
- def extconf
1241
- ruby "#{curr_srcdir()}/extconf.rb", *@config.config_opt
1242
- end
1243
-
1244
- #
1245
- # TASK setup
1246
- #
1247
-
1248
- def exec_setup
1249
- exec_task_traverse 'setup'
1250
- end
1251
-
1252
- def setup_dir_bin(rel)
1253
- files_of(curr_srcdir()).each do |fname|
1254
- update_shebang_line "#{curr_srcdir()}/#{fname}"
871
+ def directory?(path)
872
+ File.directory?(path)
1255
873
  end
1256
- end
1257
-
1258
- alias setup_dir_lib noop
1259
-
1260
- def setup_dir_ext(rel)
1261
- make if extdir?(curr_srcdir())
1262
- end
1263
-
1264
- alias setup_dir_data noop
1265
- alias setup_dir_conf noop
1266
- alias setup_dir_man noop
1267
-
1268
- def update_shebang_line(path)
1269
- return if no_harm?
1270
- return if config('shebang') == 'never'
1271
- old = Shebang.load(path)
1272
- if old
1273
- $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
1274
- new = new_shebang(old)
1275
- return if new.to_s == old.to_s
1276
- else
1277
- return unless config('shebang') == 'all'
1278
- new = Shebang.new(config('rubypath'))
1279
- end
1280
- $stderr.puts "updating shebang: #{File.basename(path)}" if verbose?
1281
- open_atomic_writer(path) {|output|
1282
- File.open(path, 'rb') {|f|
1283
- f.gets if old # discard
1284
- output.puts new.to_s
1285
- output.print f.read
1286
- }
1287
- }
1288
- end
1289
-
1290
- def new_shebang(old)
1291
- if /\Aruby/ =~ File.basename(old.cmd)
1292
- Shebang.new(config('rubypath'), old.args)
1293
- elsif File.basename(old.cmd) == 'env' and old.args.first == 'ruby'
1294
- Shebang.new(config('rubypath'), old.args[1..-1])
1295
- else
1296
- return old unless config('shebang') == 'all'
1297
- Shebang.new(config('rubypath'))
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
1298
879
  end
1299
- end
1300
-
1301
- def open_atomic_writer(path, &block)
1302
- tmpfile = File.basename(path) + '.tmp'
1303
- begin
1304
- File.open(tmpfile, 'wb', &block)
1305
- File.rename tmpfile, File.basename(path)
1306
- ensure
1307
- File.unlink tmpfile if File.exist?(tmpfile)
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
1308
888
  end
1309
- end
1310
-
1311
- class Shebang
1312
- def Shebang.load(path)
1313
- line = nil
1314
- File.open(path) {|f|
1315
- line = f.gets
1316
- }
1317
- return nil unless /\A#!/ =~ line
1318
- parse(line)
1319
- end
1320
-
1321
- def Shebang.parse(line)
1322
- cmd, *args = *line.strip.sub(/\A\#!/, '').split(' ')
1323
- new(cmd, args)
1324
- end
1325
-
1326
- def initialize(cmd, args = [])
1327
- @cmd = cmd
1328
- @args = args
1329
- end
1330
-
1331
- attr_reader :cmd
1332
- attr_reader :args
1333
-
1334
- def to_s
1335
- "#! #{@cmd}" + (@args.empty? ? '' : " #{@args.join(' ')}")
889
+ def dllext
890
+ config.dlext
1336
891
  end
1337
- end
1338
-
1339
- #
1340
- # TASK install
1341
- #
1342
-
1343
- def exec_install
1344
- rm_f 'InstalledFiles'
1345
- exec_task_traverse 'install'
1346
- end
1347
-
1348
- def install_dir_bin(rel)
1349
- install_files targetfiles(), "#{config('bindir')}/#{rel}", 0755
1350
- end
1351
-
1352
- def install_dir_lib(rel)
1353
- install_files libfiles(), "#{config('rbdir')}/#{rel}", 0644
1354
- end
1355
-
1356
- def install_dir_ext(rel)
1357
- return unless extdir?(curr_srcdir())
1358
- install_files rubyextentions('.'),
1359
- "#{config('sodir')}/#{File.dirname(rel)}",
1360
- 0555
1361
- end
1362
-
1363
- def install_dir_data(rel)
1364
- install_files targetfiles(), "#{config('datadir')}/#{rel}", 0644
1365
- end
1366
-
1367
- def install_dir_conf(rel)
1368
- # FIXME: should not remove current config files
1369
- # (rename previous file to .old/.org)
1370
- install_files targetfiles(), "#{config('sysconfdir')}/#{rel}", 0644
1371
- end
1372
-
1373
- def install_dir_man(rel)
1374
- install_files targetfiles(), "#{config('mandir')}/#{rel}", 0644
1375
- end
1376
-
1377
- def install_files(list, dest, mode)
1378
- mkdir_p dest, @config.install_prefix
1379
- list.each do |fname|
1380
- install fname, dest, mode, @config.install_prefix
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
1381
897
  end
1382
- end
1383
-
1384
- def libfiles
1385
- glob_reject(%w(*.y *.output), targetfiles())
1386
- end
1387
-
1388
- def rubyextentions(dir)
1389
- ents = glob_select("*.#{@config.dllext}", targetfiles())
1390
- if ents.empty?
1391
- setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first"
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
1392
1041
  end
1393
- ents
1394
- end
1395
-
1396
- def targetfiles
1397
- mapdir(existfiles() - hookfiles())
1398
- end
1399
-
1400
- def mapdir(ents)
1401
- ents.map {|ent|
1402
- if File.exist?(ent)
1403
- then ent # objdir
1404
- else "#{curr_srcdir()}/#{ent}" # srcdir
1405
- end
1406
- }
1407
- end
1408
-
1409
- # picked up many entries from cvs-1.11.1/src/ignore.c
1410
- JUNK_FILES = %w(
1411
- core RCSLOG tags TAGS .make.state
1412
- .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb
1413
- *~ *.old *.bak *.BAK *.orig *.rej _$* *$
1414
-
1415
- *.org *.in .*
1416
- )
1417
-
1418
- def existfiles
1419
- glob_reject(JUNK_FILES, (files_of(curr_srcdir()) | files_of('.')))
1420
- end
1421
-
1422
- def hookfiles
1423
- %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt|
1424
- %w( config setup install clean ).map {|t| sprintf(fmt, t) }
1425
- }.flatten
1426
- end
1427
-
1428
- def glob_select(pat, ents)
1429
- re = globs2re([pat])
1430
- ents.select {|ent| re =~ ent }
1431
- end
1432
-
1433
- def glob_reject(pats, ents)
1434
- re = globs2re(pats)
1435
- ents.reject {|ent| re =~ ent }
1436
- end
1437
-
1438
- GLOB2REGEX = {
1439
- '.' => '\.',
1440
- '$' => '\$',
1441
- '#' => '\#',
1442
- '*' => '.*'
1443
- }
1444
-
1445
- def globs2re(pats)
1446
- /\A(?:#{
1447
- pats.map {|pat| pat.gsub(/[\.\$\#\*]/) {|ch| GLOB2REGEX[ch] } }.join('|')
1448
- })\z/
1449
- end
1450
-
1451
- #
1452
- # TASK test
1453
- #
1454
-
1455
- TESTDIR = 'test'
1456
-
1457
- def exec_test
1458
- unless File.directory?('test')
1459
- $stderr.puts 'no test in this package' if verbose?
1460
- return
1461
- end
1462
- $stderr.puts 'Running tests...' if verbose?
1463
- begin
1464
- require 'test/unit'
1465
- rescue LoadError
1466
- setup_rb_error 'test/unit cannot loaded. You need Ruby 1.8 or later to invoke this task.'
1467
- end
1468
- runner = Test::Unit::AutoRunner.new(true)
1469
- runner.to_run << TESTDIR
1470
- runner.run
1471
- end
1472
-
1473
- #
1474
- # TASK clean
1475
- #
1476
-
1477
- def exec_clean
1478
- exec_task_traverse 'clean'
1479
- rm_f @config.savefile
1480
- rm_f 'InstalledFiles'
1481
- end
1482
-
1483
- alias clean_dir_bin noop
1484
- alias clean_dir_lib noop
1485
- alias clean_dir_data noop
1486
- alias clean_dir_conf noop
1487
- alias clean_dir_man noop
1488
-
1489
- def clean_dir_ext(rel)
1490
- return unless extdir?(curr_srcdir())
1491
- make 'clean' if File.file?('Makefile')
1492
- end
1493
-
1494
- #
1495
- # TASK distclean
1496
- #
1497
-
1498
- def exec_distclean
1499
- exec_task_traverse 'distclean'
1500
- rm_f @config.savefile
1501
- rm_f 'InstalledFiles'
1502
- end
1503
-
1504
- alias distclean_dir_bin noop
1505
- alias distclean_dir_lib noop
1506
-
1507
- def distclean_dir_ext(rel)
1508
- return unless extdir?(curr_srcdir())
1509
- make 'distclean' if File.file?('Makefile')
1510
- end
1511
-
1512
- alias distclean_dir_data noop
1513
- alias distclean_dir_conf noop
1514
- alias distclean_dir_man noop
1515
-
1516
- #
1517
- # Traversing
1518
- #
1519
-
1520
- def exec_task_traverse(task)
1521
- run_hook "pre-#{task}"
1522
- FILETYPES.each do |type|
1523
- if type == 'ext' and config('without-ext') == 'yes'
1524
- $stderr.puts 'skipping ext/* by user option' if verbose?
1525
- next
1526
- end
1527
- traverse task, type, "#{task}_dir_#{type}"
1528
- end
1529
- run_hook "post-#{task}"
1530
- end
1531
-
1532
- def traverse(task, rel, mid)
1533
- dive_into(rel) {
1534
- run_hook "pre-#{task}"
1535
- __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '')
1536
- directories_of(curr_srcdir()).each do |d|
1537
- traverse task, "#{rel}/#{d}", mid
1538
- end
1539
- run_hook "post-#{task}"
1540
- }
1541
1042
  end
1542
-
1543
- def dive_into(rel)
1544
- return unless File.dir?("#{@srcdir}/#{rel}")
1545
-
1546
- dir = File.basename(rel)
1547
- Dir.mkdir dir unless File.dir?(dir)
1548
- prevdir = Dir.pwd
1549
- Dir.chdir dir
1550
- $stderr.puts '---> ' + rel if verbose?
1551
- @currdir = rel
1552
- yield
1553
- Dir.chdir prevdir
1554
- $stderr.puts '<--- ' + rel if verbose?
1555
- @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
1556
1074
  end
1557
-
1558
- def run_hook(id)
1559
- path = [ "#{curr_srcdir()}/#{id}",
1560
- "#{curr_srcdir()}/#{id}.rb" ].detect {|cand| File.file?(cand) }
1561
- return unless path
1562
- begin
1563
- instance_eval File.read(path), path, 1
1564
- rescue
1565
- raise if $DEBUG
1566
- 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
+ )
1567
1119
  end
1568
1120
  end
1569
-
1570
- end # class Installer
1571
-
1572
-
1573
- class SetupError < StandardError; end
1574
-
1575
- def setup_rb_error(msg)
1576
- raise SetupError, msg
1577
1121
  end
1578
-
1579
- if $0 == __FILE__
1580
- begin
1581
- ToplevelInstaller.invoke
1582
- rescue SetupError
1583
- raise if $DEBUG
1584
- $stderr.puts $!.message
1585
- $stderr.puts "Try 'ruby #{$0} --help' for detailed usage."
1586
- 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
1587
1293
  end
1588
1294
  end
1295
+ Setup::Command.run