mathgl 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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