setup 4.2.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/HISTORY +47 -3
- data/MANIFEST +49 -16
- data/README.rdoc +148 -0
- data/bin/setup.rb +1 -5
- data/lib/setup.rb +2 -2
- data/lib/setup/base.rb +143 -0
- data/lib/setup/command.rb +218 -114
- data/lib/setup/compiler.rb +69 -0
- data/lib/setup/configuration.rb +822 -0
- data/lib/setup/constants.rb +12 -0
- data/lib/setup/{rubyver.rb → core_ext.rb} +0 -0
- data/lib/setup/documentor.rb +149 -0
- data/lib/setup/installer.rb +363 -0
- data/lib/setup/project.rb +68 -0
- data/lib/setup/rake.rb +44 -45
- data/lib/setup/session.rb +233 -0
- data/lib/setup/tester.rb +92 -0
- data/lib/setup/uninstaller.rb +76 -0
- data/meta/active +1 -0
- data/meta/collection +1 -0
- data/meta/{abstract → description} +0 -0
- data/meta/{package → name} +0 -0
- data/meta/repository +1 -0
- data/meta/ruby +3 -0
- data/meta/version +1 -1
- data/script/bstrap +5 -0
- data/script/bundle +64 -0
- data/script/setup +1338 -0
- data/script/test +3 -0
- data/test/cases/installer.rb +28 -0
- data/test/features/config.feature +16 -0
- data/test/features/document.feature +2 -0
- data/test/features/install.feature +72 -0
- data/test/features/make.feature +18 -0
- data/test/features/step_definitions/common_steps.rb +34 -0
- data/test/features/step_definitions/config_steps.rb +24 -0
- data/test/features/step_definitions/env.rb +37 -0
- data/test/features/step_definitions/install_steps.rb +75 -0
- data/test/features/step_definitions/setup_steps.rb +30 -0
- data/test/features/step_definitions/uninstall_steps.rb +8 -0
- data/test/features/test.feature +2 -0
- data/test/features/uninstall.feature +13 -0
- data/test/fixtures/faux-project/bin/faux +3 -0
- data/test/fixtures/faux-project/ext/faux/extconf.rb +12 -0
- data/test/fixtures/faux-project/ext/faux/faux.c +24 -0
- data/test/fixtures/faux-project/lib/faux.rb +1 -0
- metadata +58 -29
- data/README +0 -106
- data/RELEASE +0 -41
- data/lib/setup/build.rb +0 -2
- data/lib/setup/config.rb +0 -452
- data/lib/setup/error.rb +0 -4
- data/lib/setup/install.rb +0 -1007
- data/meta/setup/metaconfig.rb +0 -3
- data/test/test_installer.rb +0 -139
data/lib/setup/error.rb
DELETED
data/lib/setup/install.rb
DELETED
@@ -1,1007 +0,0 @@
|
|
1
|
-
require 'optparse'
|
2
|
-
require 'setup/config'
|
3
|
-
|
4
|
-
# TODO: we need to abort install if tests fail (check return code of TESTER)
|
5
|
-
# We will also need to add a force install option then to by pass failed tests.
|
6
|
-
#
|
7
|
-
# TODO: Generate rdocs... Package developer may want to deactivate this. How?
|
8
|
-
#
|
9
|
-
# TODO: Should be using Rdoc programmatically, but load issue arose and an error
|
10
|
-
# was being generated on ri generation. Reverting back to shelling out for now.
|
11
|
-
|
12
|
-
# The name of the package, used to install docs in system doc/ruby-{name}/ location.
|
13
|
-
# The information must be provided in a file called meta/package.
|
14
|
-
PACKAGE =(
|
15
|
-
if file = Dir["{meta,.meta}/package"].first
|
16
|
-
File.read(file).strip
|
17
|
-
else
|
18
|
-
nil
|
19
|
-
end
|
20
|
-
)
|
21
|
-
|
22
|
-
# A ruby script that instructs setup how to run tests, located at meta/setup/test.rb
|
23
|
-
# If the tests fail, the script should exit with a fail status (eg. -1).
|
24
|
-
TESTER = Dir.glob('{meta,.meta}/setup/test{,rc}.rb', File::FNM_CASEFOLD).first
|
25
|
-
|
26
|
-
# A ruby script that instructs setup how to generate docs, located at meta/setup/doc.rb
|
27
|
-
# NOTE: Docs must be generate into the doc/ for them to be installed.
|
28
|
-
DOCTOR = Dir.glob('{meta,.meta}/setup/doc{,rc}.rb', File::FNM_CASEFOLD).first
|
29
|
-
|
30
|
-
|
31
|
-
module Setup
|
32
|
-
|
33
|
-
# Installer class handles the actual install procedure,
|
34
|
-
# as well as the other tasks, such as testing.
|
35
|
-
|
36
|
-
class Installer
|
37
|
-
|
38
|
-
MANIFEST = '.cache/setup/installedfiles'
|
39
|
-
|
40
|
-
FILETYPES = %w( bin lib ext data etc man doc )
|
41
|
-
|
42
|
-
# Configuration
|
43
|
-
attr :config
|
44
|
-
|
45
|
-
attr_writer :no_harm
|
46
|
-
attr_writer :verbose
|
47
|
-
attr_writer :quiet
|
48
|
-
|
49
|
-
attr_accessor :install_prefix
|
50
|
-
attr_accessor :install_no_test
|
51
|
-
|
52
|
-
# New Installer.
|
53
|
-
def initialize(config=nil) #:yield:
|
54
|
-
srcroot = '.'
|
55
|
-
objroot = '.'
|
56
|
-
|
57
|
-
@config = config || ConfigTable.new
|
58
|
-
|
59
|
-
@srcdir = File.expand_path(srcroot)
|
60
|
-
@objdir = File.expand_path(objroot)
|
61
|
-
@currdir = '.'
|
62
|
-
|
63
|
-
self.quiet = ENV['quiet'] if ENV['quiet']
|
64
|
-
self.verbose = ENV['verbose'] if ENV['verbose']
|
65
|
-
self.no_harm = ENV['nowrite'] if ENV['nowrite']
|
66
|
-
|
67
|
-
yield(self) if block_given?
|
68
|
-
end
|
69
|
-
|
70
|
-
#
|
71
|
-
def inspect
|
72
|
-
"#<#{self.class} #{File.basename(@srcdir)}>"
|
73
|
-
end
|
74
|
-
|
75
|
-
# Are we running an installation?
|
76
|
-
def installation?; @installation; end
|
77
|
-
def installation!; @installation = true; end
|
78
|
-
|
79
|
-
def no_harm? ; @no_harm ; end
|
80
|
-
def verbose? ; @verbose ; end
|
81
|
-
def quiet? ; @quiet ; end
|
82
|
-
|
83
|
-
def verbose_off #:yield:
|
84
|
-
begin
|
85
|
-
save, @verbose = verbose?, false
|
86
|
-
yield
|
87
|
-
ensure
|
88
|
-
@verbose = save
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
#
|
93
|
-
def report_header(phase)
|
94
|
-
return if quiet?
|
95
|
-
#center = " "
|
96
|
-
#c = (center.size - phase.size) / 2
|
97
|
-
#center[c,phase.size] = phase.to_s.upcase
|
98
|
-
line = '- ' * 4 + ' -' * 24
|
99
|
-
#c = (line.size - phase.size) / 2
|
100
|
-
line[5,phase.size] = " #{phase.to_s.upcase} "
|
101
|
-
puts "\n" + line + "\n\n"
|
102
|
-
end
|
103
|
-
|
104
|
-
# Added these for future use in simplificaiton of design.
|
105
|
-
|
106
|
-
def extensions
|
107
|
-
@extensions ||= Dir['ext/**/extconf.rb']
|
108
|
-
end
|
109
|
-
|
110
|
-
def compiles?
|
111
|
-
!extensions.empty?
|
112
|
-
end
|
113
|
-
|
114
|
-
#
|
115
|
-
def noop(rel); end
|
116
|
-
|
117
|
-
##
|
118
|
-
# Hook Script API bases
|
119
|
-
#
|
120
|
-
|
121
|
-
def srcdir_root
|
122
|
-
@srcdir
|
123
|
-
end
|
124
|
-
|
125
|
-
def objdir_root
|
126
|
-
@objdir
|
127
|
-
end
|
128
|
-
|
129
|
-
def relpath
|
130
|
-
@currdir
|
131
|
-
end
|
132
|
-
|
133
|
-
##
|
134
|
-
# Task all
|
135
|
-
#
|
136
|
-
|
137
|
-
def exec_all
|
138
|
-
exec_config
|
139
|
-
exec_setup
|
140
|
-
exec_test
|
141
|
-
exec_doc
|
142
|
-
exec_install
|
143
|
-
end
|
144
|
-
|
145
|
-
##
|
146
|
-
# TASK config
|
147
|
-
#
|
148
|
-
|
149
|
-
def exec_config
|
150
|
-
report_header('config')
|
151
|
-
config.env_config
|
152
|
-
config.save_config
|
153
|
-
config.show if verbose?
|
154
|
-
puts("Configuration saved.") unless quiet?
|
155
|
-
exec_task_traverse 'config'
|
156
|
-
end
|
157
|
-
|
158
|
-
alias config_dir_bin noop
|
159
|
-
alias config_dir_lib noop
|
160
|
-
|
161
|
-
def config_dir_ext(rel)
|
162
|
-
extconf if extdir?(curr_srcdir())
|
163
|
-
end
|
164
|
-
|
165
|
-
alias config_dir_data noop
|
166
|
-
alias config_dir_etc noop
|
167
|
-
alias config_dir_man noop
|
168
|
-
alias config_dir_doc noop
|
169
|
-
|
170
|
-
def extconf
|
171
|
-
ruby "#{curr_srcdir()}/extconf.rb", config.extconfopt
|
172
|
-
end
|
173
|
-
|
174
|
-
##
|
175
|
-
# TASK show
|
176
|
-
#
|
177
|
-
|
178
|
-
def exec_show
|
179
|
-
config.show
|
180
|
-
end
|
181
|
-
|
182
|
-
##
|
183
|
-
# TASK setup
|
184
|
-
#
|
185
|
-
# FIXME: Update shebang on install rather than before.
|
186
|
-
def exec_setup
|
187
|
-
report_header('setup')
|
188
|
-
exec_task_traverse 'setup'
|
189
|
-
puts "Ok."
|
190
|
-
end
|
191
|
-
|
192
|
-
def setup_dir_bin(rel)
|
193
|
-
files_of(curr_srcdir()).each do |fname|
|
194
|
-
update_shebang_line "#{curr_srcdir()}/#{fname}" # MOVE TO INSTALL (BUT HOW?)
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
alias setup_dir_lib noop
|
199
|
-
|
200
|
-
def setup_dir_ext(rel)
|
201
|
-
make if extdir?(curr_srcdir())
|
202
|
-
end
|
203
|
-
|
204
|
-
alias setup_dir_data noop
|
205
|
-
alias setup_dir_etc noop
|
206
|
-
alias setup_dir_man noop
|
207
|
-
alias setup_dir_doc noop
|
208
|
-
|
209
|
-
def update_shebang_line(path)
|
210
|
-
return if no_harm?
|
211
|
-
return if config.shebang == 'never'
|
212
|
-
old = Shebang.load(path)
|
213
|
-
if old
|
214
|
-
if old.args.size > 1
|
215
|
-
$stderr.puts "warning: #{path}"
|
216
|
-
$stderr.puts "Shebang line has too many args."
|
217
|
-
$stderr.puts "It is not portable and your program may not work."
|
218
|
-
end
|
219
|
-
new = new_shebang(old)
|
220
|
-
return if new.to_s == old.to_s
|
221
|
-
else
|
222
|
-
return unless config.shebang == 'all'
|
223
|
-
new = Shebang.new(config.rubypath)
|
224
|
-
end
|
225
|
-
$stderr.puts "updating shebang: #{File.basename(path)}" if verbose?
|
226
|
-
open_atomic_writer(path) {|output|
|
227
|
-
File.open(path, 'rb') {|f|
|
228
|
-
f.gets if old # discard
|
229
|
-
output.puts new.to_s
|
230
|
-
output.print f.read
|
231
|
-
}
|
232
|
-
}
|
233
|
-
end
|
234
|
-
|
235
|
-
def new_shebang(old)
|
236
|
-
if /\Aruby/ =~ File.basename(old.cmd)
|
237
|
-
Shebang.new(config.rubypath, old.args)
|
238
|
-
elsif File.basename(old.cmd) == 'env' and old.args.first == 'ruby'
|
239
|
-
Shebang.new(config.rubypath, old.args[1..-1])
|
240
|
-
else
|
241
|
-
return old unless config.shebang == 'all'
|
242
|
-
Shebang.new(config.rubypath)
|
243
|
-
end
|
244
|
-
end
|
245
|
-
|
246
|
-
def open_atomic_writer(path, &block)
|
247
|
-
tmpfile = File.basename(path) + '.tmp'
|
248
|
-
begin
|
249
|
-
File.open(tmpfile, 'wb', &block)
|
250
|
-
File.rename tmpfile, File.basename(path)
|
251
|
-
ensure
|
252
|
-
File.unlink tmpfile if File.exist?(tmpfile)
|
253
|
-
end
|
254
|
-
end
|
255
|
-
|
256
|
-
class Shebang
|
257
|
-
def Shebang.load(path)
|
258
|
-
line = nil
|
259
|
-
File.open(path) {|f|
|
260
|
-
line = f.gets
|
261
|
-
}
|
262
|
-
return nil unless /\A#!/ =~ line
|
263
|
-
parse(line)
|
264
|
-
end
|
265
|
-
|
266
|
-
def Shebang.parse(line)
|
267
|
-
cmd, *args = *line.strip.sub(/\A\#!/, '').split(' ')
|
268
|
-
new(cmd, args)
|
269
|
-
end
|
270
|
-
|
271
|
-
def initialize(cmd, args = [])
|
272
|
-
@cmd = cmd
|
273
|
-
@args = args
|
274
|
-
end
|
275
|
-
|
276
|
-
attr_reader :cmd
|
277
|
-
attr_reader :args
|
278
|
-
|
279
|
-
def to_s
|
280
|
-
"#! #{@cmd}" + (@args.empty? ? '' : " #{@args.join(' ')}")
|
281
|
-
end
|
282
|
-
end
|
283
|
-
|
284
|
-
##
|
285
|
-
# TASK test
|
286
|
-
#
|
287
|
-
# Complexities arise in trying to figure out what test framework
|
288
|
-
# is used, and how to run tests. To simplify the process, this
|
289
|
-
# simply looks for a script in meta/setup called testrc.rb,
|
290
|
-
# or just test.rb.
|
291
|
-
#
|
292
|
-
def exec_test
|
293
|
-
return if install_no_test
|
294
|
-
file = TESTER
|
295
|
-
if file
|
296
|
-
report_header('test')
|
297
|
-
ruby(file)
|
298
|
-
end
|
299
|
-
#puts "Ok." unless quiet?
|
300
|
-
end
|
301
|
-
|
302
|
-
### DEPRECATED
|
303
|
-
#def exec_test
|
304
|
-
#runner = config.testrunner
|
305
|
-
#case runner
|
306
|
-
#when 'testrb' # TODO: needs work
|
307
|
-
# opt = []
|
308
|
-
# opt << " -v" if verbose?
|
309
|
-
# opt << " --runner #{runner}"
|
310
|
-
# if File.file?('test/suite.rb')
|
311
|
-
# notests = false
|
312
|
-
# opt << "test/suite.rb"
|
313
|
-
# else
|
314
|
-
# notests = Dir["test/**/*.rb"].empty?
|
315
|
-
# lib = ["lib"] + config.extensions.collect{ |d| File.dirname(d) }
|
316
|
-
# opt << "-I" + lib.join(':')
|
317
|
-
# opt << Dir["test/**/{test,tc}*.rb"]
|
318
|
-
# end
|
319
|
-
# opt = opt.flatten.join(' ').strip
|
320
|
-
# # run tests
|
321
|
-
# if notests
|
322
|
-
# $stderr.puts 'no test in this package' if verbose?
|
323
|
-
# else
|
324
|
-
# cmd = "testrb #{opt}"
|
325
|
-
# $stderr.puts cmd if verbose?
|
326
|
-
# system cmd #config.ruby "-S testrb", opt
|
327
|
-
# end
|
328
|
-
#else # autorunner
|
329
|
-
# unless File.directory?('test')
|
330
|
-
# $stderr.puts 'no test in this package' if verbose?
|
331
|
-
# return
|
332
|
-
# end
|
333
|
-
# begin
|
334
|
-
# require 'test/unit'
|
335
|
-
# rescue LoadError
|
336
|
-
# setup_rb_error 'test/unit cannot loaded. You need Ruby 1.8 or later to invoke this task.'
|
337
|
-
# end
|
338
|
-
# lib = ["lib"] + config.extensions.collect{ |d| File.dirname(d) }
|
339
|
-
# lib.each{ |l| $LOAD_PATH << l }
|
340
|
-
# autorunner = Test::Unit::AutoRunner.new(true)
|
341
|
-
# autorunner.to_run << 'test'
|
342
|
-
# autorunner.run
|
343
|
-
#end
|
344
|
-
#end
|
345
|
-
|
346
|
-
# MAYBE: We could traverse and run each test independently (?)
|
347
|
-
#def test_dir_test
|
348
|
-
#end
|
349
|
-
|
350
|
-
##
|
351
|
-
# TASK doc
|
352
|
-
|
353
|
-
def exec_doc
|
354
|
-
return if config.withoutdoc?
|
355
|
-
report_header('doc')
|
356
|
-
if file = DOCTOR
|
357
|
-
ruby(file)
|
358
|
-
else
|
359
|
-
exec_rdoc
|
360
|
-
end
|
361
|
-
exec_ri
|
362
|
-
end
|
363
|
-
|
364
|
-
# Generate rdocs.
|
365
|
-
#
|
366
|
-
# NOT USED YET B/C WE WOULD HAVE TO KNOW THE NAME OF THE PROJECT
|
367
|
-
# TO DO THIS CORRECTLY. (WHERE DO WE GET THAT?)
|
368
|
-
#
|
369
|
-
# Answer: meta/package or .meta/package
|
370
|
-
#
|
371
|
-
def exec_rdoc
|
372
|
-
main = Dir.glob("README{,.*}", File::FNM_CASEFOLD).first
|
373
|
-
|
374
|
-
if File.exist?('.document')
|
375
|
-
files = File.read('.document').split("\n")
|
376
|
-
files.reject!{ |l| l =~ /^\s*[#]/ || l !~ /\S/ }
|
377
|
-
files.collect!{ |f| f.strip }
|
378
|
-
else
|
379
|
-
files = []
|
380
|
-
files << main if main
|
381
|
-
files << 'lib' if File.directory?('lib')
|
382
|
-
files << 'ext' if File.directory?('ext')
|
383
|
-
end
|
384
|
-
|
385
|
-
checkfiles = (files + files.map{ |f| Dir[File.join(f,'*','**')] }).flatten.uniq
|
386
|
-
if FileUtils.uptodate?('doc/rdoc', checkfiles)
|
387
|
-
puts "RDocs look uptodate."
|
388
|
-
return
|
389
|
-
end
|
390
|
-
|
391
|
-
output = 'doc/rdoc'
|
392
|
-
title = (PACKAGE.capitalize + " API").strip
|
393
|
-
template = config.doctemplate || 'html'
|
394
|
-
|
395
|
-
opt = []
|
396
|
-
opt << "-U"
|
397
|
-
opt << "-q" #if quiet?
|
398
|
-
opt << "--op=#{output}"
|
399
|
-
#opt << "--template=#{template}"
|
400
|
-
opt << "--title=#{title}"
|
401
|
-
opt << "--main=#{main}" if main
|
402
|
-
#opt << "--debug"
|
403
|
-
opt << files
|
404
|
-
|
405
|
-
opt = opt.flatten
|
406
|
-
|
407
|
-
cmd = "rdoc " + opt.join(' ')
|
408
|
-
|
409
|
-
if no_harm?
|
410
|
-
puts cmd
|
411
|
-
else
|
412
|
-
begin
|
413
|
-
system(cmd)
|
414
|
-
#require 'rdoc/rdoc'
|
415
|
-
#::RDoc::RDoc.new.document(opt)
|
416
|
-
puts "Ok rdoc." unless quiet?
|
417
|
-
rescue Exception
|
418
|
-
puts "Fail rdoc."
|
419
|
-
puts "Command was: '#{cmd}'"
|
420
|
-
puts "Proceeding with install anyway."
|
421
|
-
end
|
422
|
-
end
|
423
|
-
end
|
424
|
-
|
425
|
-
# Generate ri documentation.
|
426
|
-
|
427
|
-
def exec_ri
|
428
|
-
case config.installdirs
|
429
|
-
when 'std'
|
430
|
-
output = "--ri-system"
|
431
|
-
when 'site'
|
432
|
-
output = "--ri-site"
|
433
|
-
when 'home'
|
434
|
-
output = "--ri"
|
435
|
-
else
|
436
|
-
abort "bad config: sould not be possible -- installdirs = #{config.installdirs}"
|
437
|
-
end
|
438
|
-
|
439
|
-
if File.exist?('.document')
|
440
|
-
files = File.read('.document').split("\n")
|
441
|
-
files.reject!{ |l| l =~ /^\s*[#]/ || l !~ /\S/ }
|
442
|
-
files.collect!{ |f| f.strip }
|
443
|
-
else
|
444
|
-
files = []
|
445
|
-
files << 'lib' if File.directory?('lib')
|
446
|
-
files << 'ext' if File.directory?('ext')
|
447
|
-
end
|
448
|
-
|
449
|
-
opt = []
|
450
|
-
opt << "-U"
|
451
|
-
opt << "-q" #if quiet?
|
452
|
-
#opt << "-D" #if $DEBUG
|
453
|
-
opt << output
|
454
|
-
opt << files
|
455
|
-
|
456
|
-
opt = opt.flatten
|
457
|
-
|
458
|
-
cmd = "rdoc " + opt.join(' ')
|
459
|
-
|
460
|
-
if no_harm?
|
461
|
-
puts cmd
|
462
|
-
else
|
463
|
-
# Generate in system location specified
|
464
|
-
begin
|
465
|
-
system(cmd)
|
466
|
-
#require 'rdoc/rdoc'
|
467
|
-
#::RDoc::RDoc.new.document(opt)
|
468
|
-
puts "Ok ri." unless quiet?
|
469
|
-
rescue Exception
|
470
|
-
puts "Fail ri."
|
471
|
-
puts "Command was: '#{cmd}'"
|
472
|
-
puts "Proceeding with install anyway."
|
473
|
-
end
|
474
|
-
# Now in local directory
|
475
|
-
#opt = []
|
476
|
-
#opt << "-U"
|
477
|
-
#opt << "--ri --op 'doc/ri'"
|
478
|
-
#opt << files
|
479
|
-
#opt = opt.flatten
|
480
|
-
#::RDoc::RDoc.new.document(opt)
|
481
|
-
end
|
482
|
-
end
|
483
|
-
|
484
|
-
##
|
485
|
-
# TASK install
|
486
|
-
#
|
487
|
-
|
488
|
-
def exec_install
|
489
|
-
report_header('install')
|
490
|
-
installation! # we are installing
|
491
|
-
#rm_f MANIFEST # we'll append rather then delete!
|
492
|
-
exec_task_traverse 'install'
|
493
|
-
$stderr.puts "Done.\n\n" unless quiet?
|
494
|
-
end
|
495
|
-
|
496
|
-
def install_dir_bin(rel)
|
497
|
-
install_files targetfiles(), "#{config.bindir}/#{rel}", 0755
|
498
|
-
end
|
499
|
-
|
500
|
-
def install_dir_lib(rel)
|
501
|
-
install_files libfiles(), "#{config.rbdir}/#{rel}", 0644
|
502
|
-
end
|
503
|
-
|
504
|
-
def install_dir_ext(rel)
|
505
|
-
return unless extdir?(curr_srcdir())
|
506
|
-
install_files rubyextentions('.'),
|
507
|
-
"#{config.sodir}/#{File.dirname(rel)}", 0555
|
508
|
-
end
|
509
|
-
|
510
|
-
def install_dir_data(rel)
|
511
|
-
install_files targetfiles(), "#{config.datadir}/#{rel}", 0644
|
512
|
-
end
|
513
|
-
|
514
|
-
def install_dir_etc(rel)
|
515
|
-
# FIXME: should not remove current config files
|
516
|
-
# (rename previous file to .old/.org)
|
517
|
-
install_files targetfiles(), "#{config.sysconfdir}/#{rel}", 0644
|
518
|
-
end
|
519
|
-
|
520
|
-
def install_dir_man(rel)
|
521
|
-
install_files targetfiles(), "#{config.mandir}/#{rel}", 0644
|
522
|
-
end
|
523
|
-
|
524
|
-
# doc installs to directory named: "ruby-#{package}"
|
525
|
-
def install_dir_doc(rel)
|
526
|
-
return if config.withoutdoc?
|
527
|
-
return unless PACKAGE
|
528
|
-
dir = "#{config.docdir}/ruby-#{PACKAGE}/#{rel}" # "#{config.docdir}/#{rel}"
|
529
|
-
install_files targetfiles(), dir, 0644
|
530
|
-
end
|
531
|
-
|
532
|
-
def install_files(list, dest, mode)
|
533
|
-
mkdir_p dest, install_prefix
|
534
|
-
list.each do |fname|
|
535
|
-
install fname, dest, mode, install_prefix
|
536
|
-
end
|
537
|
-
end
|
538
|
-
|
539
|
-
def libfiles
|
540
|
-
glob_reject(%w(*.y *.output), targetfiles())
|
541
|
-
end
|
542
|
-
|
543
|
-
def rubyextentions(dir)
|
544
|
-
ents = glob_select("*.#{dllext}", targetfiles())
|
545
|
-
if ents.empty?
|
546
|
-
setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first"
|
547
|
-
end
|
548
|
-
ents
|
549
|
-
end
|
550
|
-
|
551
|
-
def dllext
|
552
|
-
ConfigTable::RBCONFIG['DLEXT']
|
553
|
-
end
|
554
|
-
|
555
|
-
def targetfiles
|
556
|
-
mapdir(existfiles() - hookfiles())
|
557
|
-
end
|
558
|
-
|
559
|
-
def mapdir(ents)
|
560
|
-
ents.map {|ent|
|
561
|
-
if File.exist?(ent)
|
562
|
-
then ent # objdir
|
563
|
-
else "#{curr_srcdir()}/#{ent}" # srcdir
|
564
|
-
end
|
565
|
-
}
|
566
|
-
end
|
567
|
-
|
568
|
-
# picked up many entries from cvs-1.11.1/src/ignore.c
|
569
|
-
JUNK_FILES = %w(
|
570
|
-
core RCSLOG tags TAGS .make.state
|
571
|
-
.nse_depinfo #* .#* cvslog.* ,* .del-* *.olb
|
572
|
-
*~ *.old *.bak *.BAK *.orig *.rej _$* *$
|
573
|
-
|
574
|
-
*.org *.in .*
|
575
|
-
)
|
576
|
-
|
577
|
-
def existfiles
|
578
|
-
glob_reject(JUNK_FILES, (files_of(curr_srcdir()) | files_of('.')))
|
579
|
-
end
|
580
|
-
|
581
|
-
def hookfiles
|
582
|
-
%w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt|
|
583
|
-
%w( etc setup install clean ).map {|t| sprintf(fmt, t) }
|
584
|
-
}.flatten
|
585
|
-
end
|
586
|
-
|
587
|
-
def glob_select(pat, ents)
|
588
|
-
re = globs2re([pat])
|
589
|
-
ents.select {|ent| re =~ ent }
|
590
|
-
end
|
591
|
-
|
592
|
-
def glob_reject(pats, ents)
|
593
|
-
re = globs2re(pats)
|
594
|
-
ents.reject {|ent| re =~ ent }
|
595
|
-
end
|
596
|
-
|
597
|
-
GLOB2REGEX = {
|
598
|
-
'.' => '\.',
|
599
|
-
'$' => '\$',
|
600
|
-
'#' => '\#',
|
601
|
-
'*' => '.*'
|
602
|
-
}
|
603
|
-
|
604
|
-
def globs2re(pats)
|
605
|
-
/\A(?:#{
|
606
|
-
pats.map {|pat| pat.gsub(/[\.\$\#\*]/) {|ch| GLOB2REGEX[ch] } }.join('|')
|
607
|
-
})\z/
|
608
|
-
end
|
609
|
-
|
610
|
-
##
|
611
|
-
# TASK uninstall
|
612
|
-
#
|
613
|
-
|
614
|
-
def exec_uninstall
|
615
|
-
paths = File.read(MANIFEST).split("\n")
|
616
|
-
dirs, files = paths.partition{ |f| File.dir?(f) }
|
617
|
-
|
618
|
-
remove = []
|
619
|
-
files.uniq.each do |file|
|
620
|
-
next if /^\#/ =~ file # skip comments
|
621
|
-
remove << file if File.exist?(file)
|
622
|
-
end
|
623
|
-
|
624
|
-
if verbose? && !no_harm?
|
625
|
-
puts remove.collect{ |f| "rm #{f}" }.join("\n")
|
626
|
-
ans = ask("Continue?", "yN")
|
627
|
-
case ans
|
628
|
-
when 'y', 'Y', 'yes'
|
629
|
-
else
|
630
|
-
return # abort?
|
631
|
-
end
|
632
|
-
end
|
633
|
-
|
634
|
-
remove.each do |file|
|
635
|
-
rm_f(file)
|
636
|
-
end
|
637
|
-
|
638
|
-
dirs.each do |dir|
|
639
|
-
# okay this is over kill, but playing it safe...
|
640
|
-
empty = Dir[File.join(dir,'*')].empty?
|
641
|
-
begin
|
642
|
-
if no_harm?
|
643
|
-
$stderr.puts "rmdir #{dir}"
|
644
|
-
else
|
645
|
-
rmdir(dir) if empty
|
646
|
-
end
|
647
|
-
rescue Errno::ENOTEMPTY
|
648
|
-
$stderr.puts "may not be empty -- #{dir}" if verbose?
|
649
|
-
end
|
650
|
-
end
|
651
|
-
|
652
|
-
rm_f(MANIFEST)
|
653
|
-
end
|
654
|
-
|
655
|
-
##
|
656
|
-
# TASK clean
|
657
|
-
#
|
658
|
-
|
659
|
-
def exec_clean
|
660
|
-
exec_task_traverse 'clean'
|
661
|
-
rm_f ConfigTable::CONFIGFILE
|
662
|
-
#rm_f MANIFEST # only on clobber!
|
663
|
-
end
|
664
|
-
|
665
|
-
alias clean_dir_bin noop
|
666
|
-
alias clean_dir_lib noop
|
667
|
-
alias clean_dir_data noop
|
668
|
-
alias clean_dir_etc noop
|
669
|
-
alias clean_dir_man noop
|
670
|
-
alias clean_dir_doc noop
|
671
|
-
|
672
|
-
def clean_dir_ext(rel)
|
673
|
-
return unless extdir?(curr_srcdir())
|
674
|
-
make 'clean' if File.file?('Makefile')
|
675
|
-
end
|
676
|
-
|
677
|
-
##
|
678
|
-
# TASK distclean
|
679
|
-
#
|
680
|
-
|
681
|
-
def exec_distclean
|
682
|
-
exec_task_traverse 'distclean'
|
683
|
-
rm_f ConfigTable::CONFIGFILE
|
684
|
-
rm_f MANIFEST
|
685
|
-
end
|
686
|
-
|
687
|
-
alias distclean_dir_bin noop
|
688
|
-
alias distclean_dir_lib noop
|
689
|
-
|
690
|
-
def distclean_dir_ext(rel)
|
691
|
-
return unless extdir?(curr_srcdir())
|
692
|
-
make 'distclean' if File.file?('Makefile')
|
693
|
-
end
|
694
|
-
|
695
|
-
alias distclean_dir_data noop
|
696
|
-
alias distclean_dir_etc noop
|
697
|
-
alias distclean_dir_man noop
|
698
|
-
|
699
|
-
def distclean_dir_doc(rel)
|
700
|
-
#rm_rf('rdoc') if File.directory?('rdoc') # RDOC HERE
|
701
|
-
end
|
702
|
-
|
703
|
-
##
|
704
|
-
# Traversing
|
705
|
-
#
|
706
|
-
|
707
|
-
def exec_task_traverse(task)
|
708
|
-
run_hook "pre-#{task}"
|
709
|
-
FILETYPES.each do |type|
|
710
|
-
if type == 'ext' and config.withoutext? #== 'yes'
|
711
|
-
$stderr.puts 'skipping ext/* by user option' if verbose?
|
712
|
-
next
|
713
|
-
end
|
714
|
-
traverse task, type, "#{task}_dir_#{type}"
|
715
|
-
end
|
716
|
-
run_hook "post-#{task}"
|
717
|
-
end
|
718
|
-
|
719
|
-
def traverse(task, rel, mid)
|
720
|
-
dive_into(rel) {
|
721
|
-
run_hook "pre-#{task}"
|
722
|
-
__send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '')
|
723
|
-
directories_of(curr_srcdir()).each do |d|
|
724
|
-
traverse task, "#{rel}/#{d}", mid
|
725
|
-
end
|
726
|
-
run_hook "post-#{task}"
|
727
|
-
}
|
728
|
-
end
|
729
|
-
|
730
|
-
#
|
731
|
-
def dive_into(rel)
|
732
|
-
return unless File.dir?("#{@srcdir}/#{rel}")
|
733
|
-
|
734
|
-
dir = File.basename(rel)
|
735
|
-
Dir.mkdir dir unless File.dir?(dir)
|
736
|
-
prevdir = Dir.pwd
|
737
|
-
Dir.chdir dir
|
738
|
-
$stderr.puts '---> ' + rel if verbose?
|
739
|
-
@currdir = rel
|
740
|
-
yield
|
741
|
-
Dir.chdir prevdir
|
742
|
-
$stderr.puts '<--- ' + rel if verbose?
|
743
|
-
@currdir = File.dirname(rel)
|
744
|
-
end
|
745
|
-
|
746
|
-
#
|
747
|
-
def run_hook(id)
|
748
|
-
path = [ "#{curr_srcdir()}/#{id}",
|
749
|
-
"#{curr_srcdir()}/#{id}.rb" ].detect {|cand| File.file?(cand) }
|
750
|
-
return unless path
|
751
|
-
begin
|
752
|
-
instance_eval File.read(path), path, 1
|
753
|
-
rescue
|
754
|
-
raise if $DEBUG
|
755
|
-
setup_rb_error "hook #{path} failed:\n" + $!.message
|
756
|
-
end
|
757
|
-
end
|
758
|
-
|
759
|
-
##
|
760
|
-
# File Operations
|
761
|
-
#
|
762
|
-
# This module requires: #verbose?, #no_harm?
|
763
|
-
|
764
|
-
def binread(fname)
|
765
|
-
File.open(fname, 'rb'){ |f|
|
766
|
-
return f.read
|
767
|
-
}
|
768
|
-
end
|
769
|
-
|
770
|
-
def mkdir_p(dirname, prefix = nil)
|
771
|
-
dirname = prefix + File.expand_path(dirname) if prefix
|
772
|
-
$stderr.puts "mkdir -p #{dirname}" if verbose?
|
773
|
-
return if no_harm?
|
774
|
-
|
775
|
-
# Does not check '/', it's too abnormal.
|
776
|
-
dirs = File.expand_path(dirname).split(%r<(?=/)>)
|
777
|
-
if /\A[a-z]:\z/i =~ dirs[0]
|
778
|
-
disk = dirs.shift
|
779
|
-
dirs[0] = disk + dirs[0]
|
780
|
-
end
|
781
|
-
dirs.each_index do |idx|
|
782
|
-
path = dirs[0..idx].join('')
|
783
|
-
Dir.mkdir path unless File.dir?(path)
|
784
|
-
record_installation(path) # also record directories made
|
785
|
-
end
|
786
|
-
end
|
787
|
-
|
788
|
-
def rm_f(path)
|
789
|
-
$stderr.puts "rm -f #{path}" if verbose?
|
790
|
-
return if no_harm?
|
791
|
-
force_remove_file path
|
792
|
-
end
|
793
|
-
|
794
|
-
def rm_rf(path)
|
795
|
-
$stderr.puts "rm -rf #{path}" if verbose?
|
796
|
-
return if no_harm?
|
797
|
-
remove_tree path
|
798
|
-
end
|
799
|
-
|
800
|
-
def rmdir(path)
|
801
|
-
$stderr.puts "rmdir #{path}" if verbose?
|
802
|
-
return if no_harm?
|
803
|
-
Dir.rmdir path
|
804
|
-
end
|
805
|
-
|
806
|
-
def remove_tree(path)
|
807
|
-
if File.symlink?(path)
|
808
|
-
remove_file path
|
809
|
-
elsif File.dir?(path)
|
810
|
-
remove_tree0 path
|
811
|
-
else
|
812
|
-
force_remove_file path
|
813
|
-
end
|
814
|
-
end
|
815
|
-
|
816
|
-
def remove_tree0(path)
|
817
|
-
Dir.foreach(path) do |ent|
|
818
|
-
next if ent == '.'
|
819
|
-
next if ent == '..'
|
820
|
-
entpath = "#{path}/#{ent}"
|
821
|
-
if File.symlink?(entpath)
|
822
|
-
remove_file entpath
|
823
|
-
elsif File.dir?(entpath)
|
824
|
-
remove_tree0 entpath
|
825
|
-
else
|
826
|
-
force_remove_file entpath
|
827
|
-
end
|
828
|
-
end
|
829
|
-
begin
|
830
|
-
Dir.rmdir path
|
831
|
-
rescue Errno::ENOTEMPTY
|
832
|
-
# directory may not be empty
|
833
|
-
end
|
834
|
-
end
|
835
|
-
|
836
|
-
def move_file(src, dest)
|
837
|
-
force_remove_file dest
|
838
|
-
begin
|
839
|
-
File.rename src, dest
|
840
|
-
rescue
|
841
|
-
File.open(dest, 'wb') {|f|
|
842
|
-
f.write binread(src)
|
843
|
-
}
|
844
|
-
File.chmod File.stat(src).mode, dest
|
845
|
-
File.unlink src
|
846
|
-
end
|
847
|
-
end
|
848
|
-
|
849
|
-
def force_remove_file(path)
|
850
|
-
begin
|
851
|
-
remove_file path
|
852
|
-
rescue
|
853
|
-
end
|
854
|
-
end
|
855
|
-
|
856
|
-
def remove_file(path)
|
857
|
-
File.chmod 0777, path
|
858
|
-
File.unlink path
|
859
|
-
end
|
860
|
-
|
861
|
-
def install(from, dest, mode, prefix = nil)
|
862
|
-
$stderr.puts "install #{from} #{dest}" if verbose?
|
863
|
-
return if no_harm?
|
864
|
-
|
865
|
-
realdest = prefix ? prefix + File.expand_path(dest) : dest
|
866
|
-
realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest)
|
867
|
-
str = binread(from)
|
868
|
-
if diff?(str, realdest)
|
869
|
-
verbose_off {
|
870
|
-
rm_f realdest if File.exist?(realdest)
|
871
|
-
}
|
872
|
-
File.open(realdest, 'wb') {|f|
|
873
|
-
f.write str
|
874
|
-
}
|
875
|
-
File.chmod mode, realdest
|
876
|
-
|
877
|
-
if prefix
|
878
|
-
path = realdest.sub(prefix, '')
|
879
|
-
else
|
880
|
-
path = realdest
|
881
|
-
end
|
882
|
-
|
883
|
-
record_installation(path)
|
884
|
-
end
|
885
|
-
end
|
886
|
-
|
887
|
-
def record_installation(path)
|
888
|
-
FileUtils.mkdir_p(File.dirname("#{objdir_root()}/#{MANIFEST}"))
|
889
|
-
File.open("#{objdir_root()}/#{MANIFEST}", 'a') do |f|
|
890
|
-
f.puts(path)
|
891
|
-
end
|
892
|
-
end
|
893
|
-
|
894
|
-
def diff?(new_content, path)
|
895
|
-
return true unless File.exist?(path)
|
896
|
-
new_content != binread(path)
|
897
|
-
end
|
898
|
-
|
899
|
-
def command(*args)
|
900
|
-
$stderr.puts args.join(' ') if verbose?
|
901
|
-
system(*args) or raise RuntimeError,
|
902
|
-
"system(#{args.map{|a| a.inspect }.join(' ')}) failed"
|
903
|
-
end
|
904
|
-
|
905
|
-
def ruby(*args)
|
906
|
-
command config.rubyprog, *args
|
907
|
-
end
|
908
|
-
|
909
|
-
def make(task = nil)
|
910
|
-
command(*[config.makeprog, task].compact)
|
911
|
-
end
|
912
|
-
|
913
|
-
def extdir?(dir)
|
914
|
-
File.exist?("#{dir}/MANIFEST") or File.exist?("#{dir}/extconf.rb")
|
915
|
-
end
|
916
|
-
|
917
|
-
def files_of(dir)
|
918
|
-
Dir.open(dir) {|d|
|
919
|
-
return d.select {|ent| File.file?("#{dir}/#{ent}") }
|
920
|
-
}
|
921
|
-
end
|
922
|
-
|
923
|
-
DIR_REJECT = %w( . .. CVS SCCS RCS CVS.adm .svn )
|
924
|
-
|
925
|
-
def directories_of(dir)
|
926
|
-
Dir.open(dir) {|d|
|
927
|
-
return d.select {|ent| File.dir?("#{dir}/#{ent}") } - DIR_REJECT
|
928
|
-
}
|
929
|
-
end
|
930
|
-
|
931
|
-
# Ask a question of the user.
|
932
|
-
def ask(question, answers=nil)
|
933
|
-
$stdout << "#{question}"
|
934
|
-
$stdout << " [#{answers}] " if answers
|
935
|
-
until inp = $stdin.gets ; sleep 1 ; end
|
936
|
-
inp.strip
|
937
|
-
end
|
938
|
-
|
939
|
-
##
|
940
|
-
# Hook Script API
|
941
|
-
#
|
942
|
-
# These require: #srcdir_root, #objdir_root, #relpath
|
943
|
-
#
|
944
|
-
|
945
|
-
#
|
946
|
-
def get_config(key)
|
947
|
-
config[key]
|
948
|
-
end
|
949
|
-
|
950
|
-
# obsolete: use metaconfig to change configuration
|
951
|
-
# TODO: what to do with?
|
952
|
-
def set_config(key, val)
|
953
|
-
config[key] = val
|
954
|
-
end
|
955
|
-
|
956
|
-
# srcdir/objdir (works only in the package directory)
|
957
|
-
#
|
958
|
-
# TODO: Since package directory has been deprecated these
|
959
|
-
# probably can be worked out of the system. ?
|
960
|
-
|
961
|
-
#
|
962
|
-
def curr_srcdir
|
963
|
-
"#{srcdir_root()}/#{relpath()}"
|
964
|
-
end
|
965
|
-
|
966
|
-
def curr_objdir
|
967
|
-
"#{objdir_root()}/#{relpath()}"
|
968
|
-
end
|
969
|
-
|
970
|
-
def srcfile(path)
|
971
|
-
"#{curr_srcdir()}/#{path}"
|
972
|
-
end
|
973
|
-
|
974
|
-
def srcexist?(path)
|
975
|
-
File.exist?(srcfile(path))
|
976
|
-
end
|
977
|
-
|
978
|
-
def srcdirectory?(path)
|
979
|
-
File.dir?(srcfile(path))
|
980
|
-
end
|
981
|
-
|
982
|
-
def srcfile?(path)
|
983
|
-
File.file?(srcfile(path))
|
984
|
-
end
|
985
|
-
|
986
|
-
def srcentries(path = '.')
|
987
|
-
Dir.open("#{curr_srcdir()}/#{path}") {|d|
|
988
|
-
return d.to_a - %w(. ..)
|
989
|
-
}
|
990
|
-
end
|
991
|
-
|
992
|
-
def srcfiles(path = '.')
|
993
|
-
srcentries(path).select {|fname|
|
994
|
-
File.file?(File.join(curr_srcdir(), path, fname))
|
995
|
-
}
|
996
|
-
end
|
997
|
-
|
998
|
-
def srcdirectories(path = '.')
|
999
|
-
srcentries(path).select {|fname|
|
1000
|
-
File.dir?(File.join(curr_srcdir(), path, fname))
|
1001
|
-
}
|
1002
|
-
end
|
1003
|
-
|
1004
|
-
end
|
1005
|
-
|
1006
|
-
end
|
1007
|
-
|