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
File without changes
|
@@ -0,0 +1,149 @@
|
|
1
|
+
require 'setup/base'
|
2
|
+
|
3
|
+
module Setup
|
4
|
+
|
5
|
+
#
|
6
|
+
class Documentor < Base
|
7
|
+
|
8
|
+
#
|
9
|
+
def document
|
10
|
+
return if config.no_doc
|
11
|
+
exec_ri
|
12
|
+
|
13
|
+
#if file = DOCSCRIPT
|
14
|
+
# ruby(file)
|
15
|
+
#else
|
16
|
+
# exec_rdoc
|
17
|
+
#end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Generate ri documentation.
|
21
|
+
#++
|
22
|
+
# TODO: call rdoc programmatically.
|
23
|
+
#--
|
24
|
+
def exec_ri
|
25
|
+
case config.type #installdirs
|
26
|
+
when 'std', 'ruby'
|
27
|
+
#output = "--ri-system" # no longer supported?
|
28
|
+
output = "--ri-site"
|
29
|
+
when 'site'
|
30
|
+
output = "--ri-site"
|
31
|
+
when 'home'
|
32
|
+
output = "--ri"
|
33
|
+
else
|
34
|
+
abort "bad config: should not be possible -- type=#{config.type}"
|
35
|
+
end
|
36
|
+
|
37
|
+
if File.exist?('.document')
|
38
|
+
files = File.read('.document').split("\n")
|
39
|
+
files.reject!{ |l| l =~ /^\s*[#]/ || l !~ /\S/ }
|
40
|
+
files.collect!{ |f| f.strip }
|
41
|
+
#elsif File.exist?('meta/loadpath')
|
42
|
+
else
|
43
|
+
files = []
|
44
|
+
files << 'lib' if File.directory?('lib')
|
45
|
+
files << 'ext' if File.directory?('ext')
|
46
|
+
end
|
47
|
+
|
48
|
+
opt = []
|
49
|
+
opt << "-U"
|
50
|
+
opt << "-q" #if quiet?
|
51
|
+
#opt << "-D" #if $DEBUG
|
52
|
+
opt << output
|
53
|
+
opt << files
|
54
|
+
|
55
|
+
opt = opt.flatten
|
56
|
+
|
57
|
+
cmd = "rdoc " + opt.join(' ')
|
58
|
+
|
59
|
+
if trial?
|
60
|
+
puts cmd
|
61
|
+
else
|
62
|
+
begin
|
63
|
+
success = system(cmd)
|
64
|
+
raise unless success
|
65
|
+
#require 'rdoc/rdoc'
|
66
|
+
#::RDoc::RDoc.new.document(opt)
|
67
|
+
io.puts "Ok ri." #unless quiet?
|
68
|
+
rescue Exception
|
69
|
+
$stderr.puts "ri generation failed"
|
70
|
+
$stderr.puts "command was: '#{cmd}'"
|
71
|
+
#$stderr.puts "proceeding with install..."
|
72
|
+
end
|
73
|
+
|
74
|
+
# Now in local directory
|
75
|
+
#opt = []
|
76
|
+
#opt << "-U"
|
77
|
+
#opt << "--ri --op 'doc/ri'"
|
78
|
+
#opt << files
|
79
|
+
#opt = opt.flatten
|
80
|
+
#::RDoc::RDoc.new.document(opt)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Generate rdocs.
|
85
|
+
#
|
86
|
+
# Needs <tt>meta/name</tt> or <tt>.meta/name</tt>.
|
87
|
+
#
|
88
|
+
# NOTE: This is not being used. It's here in case we decide
|
89
|
+
# to add this feature, though it is quite possible that
|
90
|
+
# we may never do so.
|
91
|
+
#
|
92
|
+
def exec_rdoc
|
93
|
+
main = Dir.glob("README{,.*}", File::FNM_CASEFOLD).first
|
94
|
+
|
95
|
+
if File.exist?('.document')
|
96
|
+
files = File.read('.document').split("\n")
|
97
|
+
files.reject!{ |l| l =~ /^\s*[#]/ || l !~ /\S/ }
|
98
|
+
files.collect!{ |f| f.strip }
|
99
|
+
else
|
100
|
+
files = []
|
101
|
+
files << main if main
|
102
|
+
files << 'lib' if File.directory?('lib')
|
103
|
+
files << 'ext' if File.directory?('ext')
|
104
|
+
end
|
105
|
+
|
106
|
+
checkfiles = (files + files.map{ |f| Dir[File.join(f,'*','**')] }).flatten.uniq
|
107
|
+
if FileUtils.uptodate?('doc/rdoc', checkfiles)
|
108
|
+
puts "RDocs look current."
|
109
|
+
return
|
110
|
+
end
|
111
|
+
|
112
|
+
output = 'doc/rdoc'
|
113
|
+
title = (PACKAGE.capitalize + " API").strip if PACKAGE
|
114
|
+
template = config.doctemplate || 'html'
|
115
|
+
|
116
|
+
opt = []
|
117
|
+
opt << "-U"
|
118
|
+
opt << "-q" #if quiet?
|
119
|
+
opt << "--op=#{output}"
|
120
|
+
#opt << "--template=#{template}"
|
121
|
+
opt << "--title=#{title}"
|
122
|
+
opt << "--main=#{main}" if main
|
123
|
+
#opt << "--debug"
|
124
|
+
opt << files
|
125
|
+
|
126
|
+
opt = opt.flatten
|
127
|
+
|
128
|
+
cmd = "rdoc " + opt.join(' ')
|
129
|
+
|
130
|
+
if trial?
|
131
|
+
puts cmd
|
132
|
+
else
|
133
|
+
begin
|
134
|
+
system(cmd)
|
135
|
+
#require 'rdoc/rdoc'
|
136
|
+
#::RDoc::RDoc.new.document(opt)
|
137
|
+
puts "Ok rdoc." unless quiet?
|
138
|
+
rescue Exception
|
139
|
+
puts "Fail rdoc."
|
140
|
+
puts "Command was: '#{cmd}'"
|
141
|
+
puts "Proceeding with install anyway."
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
|
@@ -0,0 +1,363 @@
|
|
1
|
+
require 'setup/base'
|
2
|
+
|
3
|
+
module Setup
|
4
|
+
|
5
|
+
# Installer class handles the actual install procedure.
|
6
|
+
#
|
7
|
+
# NOTE: This new version does not support per-directory hooks.
|
8
|
+
#
|
9
|
+
class Installer < Base
|
10
|
+
|
11
|
+
#
|
12
|
+
def install_prefix
|
13
|
+
config.install_prefix
|
14
|
+
end
|
15
|
+
#attr_accessor :install_prefix
|
16
|
+
|
17
|
+
# Install package.
|
18
|
+
def install
|
19
|
+
Dir.chdir(rootdir) do
|
20
|
+
install_bin
|
21
|
+
install_ext
|
22
|
+
install_lib
|
23
|
+
install_data
|
24
|
+
install_man
|
25
|
+
install_doc
|
26
|
+
install_etc
|
27
|
+
prune_install_record
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Install binaries (executables).
|
32
|
+
def install_bin
|
33
|
+
return unless directory?('bin')
|
34
|
+
report_transfer('bin', config.bindir)
|
35
|
+
#io.puts "* bin -> #{config.bindir}" unless quiet?
|
36
|
+
files = files('bin')
|
37
|
+
install_files('bin', files, config.bindir, 0755)
|
38
|
+
#install_shebang(files, config.bindir)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Install shared extension libraries.
|
42
|
+
def install_ext
|
43
|
+
return unless directory?('ext')
|
44
|
+
report_transfer('ext', config.sodir)
|
45
|
+
#io.puts "* ext -> #{config.sodir}" unless quiet?
|
46
|
+
files = files('ext')
|
47
|
+
files = select_dllext(files)
|
48
|
+
#install_files('ext', files, config.sodir, 0555)
|
49
|
+
files.each do |file|
|
50
|
+
name = File.join(File.dirname(File.dirname(file)), File.basename(file))
|
51
|
+
dest = destination(config.sodir, name)
|
52
|
+
install_file('ext', file, dest, 0555, install_prefix)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Install library files.
|
57
|
+
def install_lib
|
58
|
+
return unless directory?('lib')
|
59
|
+
report_transfer('lib', config.rbdir)
|
60
|
+
#io.puts "* lib -> #{config.rbdir}" unless quiet?
|
61
|
+
files = files('lib')
|
62
|
+
install_files('lib', files, config.rbdir, 0644)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Install shared data.
|
66
|
+
def install_data
|
67
|
+
return unless directory?('data')
|
68
|
+
report_transfer('data', config.datadir)
|
69
|
+
#io.puts "* data -> #{config.datadir}" unless quiet?
|
70
|
+
files = files('data')
|
71
|
+
install_files('data', files, config.datadir, 0644)
|
72
|
+
end
|
73
|
+
|
74
|
+
# Install configuration.
|
75
|
+
def install_etc
|
76
|
+
return unless directory?('etc')
|
77
|
+
report_transfer('etc', config.sysconfdir)
|
78
|
+
files = files('etc')
|
79
|
+
install_files('etc', files, config.sysconfdir, 0644)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Install manpages.
|
83
|
+
def install_man
|
84
|
+
return unless directory?('man')
|
85
|
+
report_transfer('man', config.mandir)
|
86
|
+
files = files('man')
|
87
|
+
install_files('man', files, config.mandir, 0644)
|
88
|
+
end
|
89
|
+
|
90
|
+
# Install documentation.
|
91
|
+
#
|
92
|
+
# TODO: The use of the project name in the doc directory
|
93
|
+
# should be set during the config phase. Define a seperate
|
94
|
+
# config method for it.
|
95
|
+
def install_doc
|
96
|
+
return unless config.doc?
|
97
|
+
return unless directory?('doc')
|
98
|
+
return unless project.name
|
99
|
+
dir = File.join(config.docdir, "ruby-{project.name}")
|
100
|
+
report_transfer('doc', dir)
|
101
|
+
#io.puts "* doc -> #{dir}" unless quiet?
|
102
|
+
files = files('doc')
|
103
|
+
install_files('doc', files, dir, 0644)
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
# Display the file transfer taking place.
|
109
|
+
def report_transfer(source, directory)
|
110
|
+
unless quiet?
|
111
|
+
if install_prefix
|
112
|
+
out = File.join(install_prefix, directory)
|
113
|
+
else
|
114
|
+
out = directory
|
115
|
+
end
|
116
|
+
io.puts "* #{source} -> #{out}"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# Comfirm a +path+ is a directory and exists.
|
121
|
+
def directory?(path)
|
122
|
+
File.directory?(path)
|
123
|
+
end
|
124
|
+
|
125
|
+
# Get a list of project files given a project subdirectory.
|
126
|
+
def files(dir)
|
127
|
+
files = Dir["#{dir}/**/*"]
|
128
|
+
files = files.select{ |f| File.file?(f) }
|
129
|
+
files = files.map{ |f| f.sub("#{dir}/", '') }
|
130
|
+
files
|
131
|
+
end
|
132
|
+
|
133
|
+
# Extract dynamic link libraries from all ext files.
|
134
|
+
def select_dllext(files)
|
135
|
+
ents = files.select do |file|
|
136
|
+
File.extname(file) == ".#{dllext}"
|
137
|
+
end
|
138
|
+
if ents.empty? && !files.empty?
|
139
|
+
raise Error, "ruby extention not compiled: 'setup.rb setup' first"
|
140
|
+
end
|
141
|
+
ents
|
142
|
+
end
|
143
|
+
|
144
|
+
# Dynamic link library extension for this system.
|
145
|
+
def dllext
|
146
|
+
config.dlext
|
147
|
+
#Configuration::RBCONFIG['DLEXT']
|
148
|
+
end
|
149
|
+
|
150
|
+
# Install project files.
|
151
|
+
def install_files(dir, list, dest, mode)
|
152
|
+
#mkdir_p(dest) #, install_prefix)
|
153
|
+
list.each do |fname|
|
154
|
+
rdest = destination(dest, fname)
|
155
|
+
install_file(dir, fname, rdest, mode, install_prefix)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
# Install a project file.
|
160
|
+
def install_file(dir, from, dest, mode, prefix=nil)
|
161
|
+
mkdir_p(File.dirname(dest))
|
162
|
+
|
163
|
+
if trace? or trial?
|
164
|
+
#to = prefix ? File.join(prefix, dir, from) : File.join(dir, from)
|
165
|
+
io.puts "install #{dir}/#{from} #{dest}"
|
166
|
+
end
|
167
|
+
|
168
|
+
return if trial?
|
169
|
+
|
170
|
+
str = binread(File.join(dir, from))
|
171
|
+
|
172
|
+
if diff?(str, dest)
|
173
|
+
trace_off {
|
174
|
+
rm_f(dest) if File.exist?(dest)
|
175
|
+
}
|
176
|
+
File.open(dest, 'wb'){ |f| f.write(str) }
|
177
|
+
File.chmod(mode, dest)
|
178
|
+
end
|
179
|
+
|
180
|
+
record_installation(dest) # record file as installed
|
181
|
+
end
|
182
|
+
|
183
|
+
# Install a directory.
|
184
|
+
#--
|
185
|
+
# TODO: Surely this can be simplified.
|
186
|
+
#++
|
187
|
+
def mkdir_p(dirname) #, prefix=nil)
|
188
|
+
#dirname = destination(dirname)
|
189
|
+
#dirname = File.join(prefix, File.expand_path(dirname)) if prefix
|
190
|
+
return if File.directory?(dirname)
|
191
|
+
|
192
|
+
io.puts "mkdir -p #{dirname}" if trace? or trial?
|
193
|
+
|
194
|
+
return if trial?
|
195
|
+
|
196
|
+
# Does not check '/', it's too abnormal.
|
197
|
+
dirs = File.expand_path(dirname).split(%r<(?=/)>)
|
198
|
+
if /\A[a-z]:\z/i =~ dirs[0]
|
199
|
+
disk = dirs.shift
|
200
|
+
dirs[0] = disk + dirs[0]
|
201
|
+
end
|
202
|
+
dirs.each_index do |idx|
|
203
|
+
path = dirs[0..idx].join('')
|
204
|
+
unless File.dir?(path)
|
205
|
+
Dir.mkdir(path)
|
206
|
+
end
|
207
|
+
record_installation(path) # record directories made
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
# Record that a file or directory was installed in the
|
212
|
+
# install record file.
|
213
|
+
def record_installation(path)
|
214
|
+
File.open(install_record, 'a') do |f|
|
215
|
+
f.puts(path)
|
216
|
+
end
|
217
|
+
#io.puts "installed #{path}" if trace?
|
218
|
+
end
|
219
|
+
|
220
|
+
# Remove duplicates from the install record.
|
221
|
+
def prune_install_record
|
222
|
+
entries = File.read(install_record).split("\n")
|
223
|
+
entries.uniq!
|
224
|
+
File.open(install_record, 'w') do |f|
|
225
|
+
f << entries.join("\n")
|
226
|
+
f << "\n"
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
# Get the install record file name, and ensure it's location
|
231
|
+
# is prepared (ie. make it's directory).
|
232
|
+
def install_record
|
233
|
+
@install_record ||= (
|
234
|
+
file = INSTALL_RECORD
|
235
|
+
dir = File.dirname(file)
|
236
|
+
unless File.directory?(dir)
|
237
|
+
FileUtils.mkdir_p(dir)
|
238
|
+
end
|
239
|
+
file
|
240
|
+
)
|
241
|
+
end
|
242
|
+
|
243
|
+
#realdest = prefix ? File.join(prefix, File.expand_path(dest)) : dest
|
244
|
+
#realdest = File.join(realdest, from) #if File.dir?(realdest) #File.basename(from)) if File.dir?(realdest)
|
245
|
+
|
246
|
+
# Determine actual destination including install_prefix.
|
247
|
+
def destination(dir, file)
|
248
|
+
dest = install_prefix ? File.join(install_prefix, File.expand_path(dir)) : dir
|
249
|
+
dest = File.join(dest, file) #if File.dir?(dest)
|
250
|
+
dest = File.expand_path(dest)
|
251
|
+
dest
|
252
|
+
end
|
253
|
+
|
254
|
+
# Is a current project file different from a previously
|
255
|
+
# installed file?
|
256
|
+
def diff?(new_content, path)
|
257
|
+
return true unless File.exist?(path)
|
258
|
+
new_content != binread(path)
|
259
|
+
end
|
260
|
+
|
261
|
+
# Binary read.
|
262
|
+
def binread(fname)
|
263
|
+
File.open(fname, 'rb') do |f|
|
264
|
+
return f.read
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
# TODO: The shebang updating needs some work.
|
269
|
+
#
|
270
|
+
# I beleive that on unix-based systems <tt>#!/usr/bin/env ruby</tt>
|
271
|
+
# is the appropriate shebang.
|
272
|
+
|
273
|
+
#
|
274
|
+
def install_shebang(files, dir)
|
275
|
+
files.each do |file|
|
276
|
+
path = File.join(dir, File.basename(file))
|
277
|
+
update_shebang_line(path)
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
#
|
282
|
+
def update_shebang_line(path)
|
283
|
+
return if trial?
|
284
|
+
return if config.shebang == 'never'
|
285
|
+
old = Shebang.load(path)
|
286
|
+
if old
|
287
|
+
if old.args.size > 1
|
288
|
+
$stderr.puts "warning: #{path}"
|
289
|
+
$stderr.puts "Shebang line has too many args."
|
290
|
+
$stderr.puts "It is not portable and your program may not work."
|
291
|
+
end
|
292
|
+
new = new_shebang(old)
|
293
|
+
return if new.to_s == old.to_s
|
294
|
+
else
|
295
|
+
return unless config.shebang == 'all'
|
296
|
+
new = Shebang.new(config.rubypath)
|
297
|
+
end
|
298
|
+
$stderr.puts "updating shebang: #{File.basename(path)}" if trace?
|
299
|
+
open_atomic_writer(path) do |output|
|
300
|
+
File.open(path, 'rb') do |f|
|
301
|
+
f.gets if old # discard
|
302
|
+
output.puts new.to_s
|
303
|
+
output.print f.read
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
#
|
309
|
+
def new_shebang(old)
|
310
|
+
if /\Aruby/ =~ File.basename(old.cmd)
|
311
|
+
Shebang.new(config.rubypath, old.args)
|
312
|
+
elsif File.basename(old.cmd) == 'env' and old.args.first == 'ruby'
|
313
|
+
Shebang.new(config.rubypath, old.args[1..-1])
|
314
|
+
else
|
315
|
+
return old unless config.shebang == 'all'
|
316
|
+
Shebang.new(config.rubypath)
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
#
|
321
|
+
def open_atomic_writer(path, &block)
|
322
|
+
tmpfile = File.basename(path) + '.tmp'
|
323
|
+
begin
|
324
|
+
File.open(tmpfile, 'wb', &block)
|
325
|
+
File.rename tmpfile, File.basename(path)
|
326
|
+
ensure
|
327
|
+
File.unlink tmpfile if File.exist?(tmpfile)
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
#
|
332
|
+
class Shebang
|
333
|
+
def Shebang.load(path)
|
334
|
+
line = nil
|
335
|
+
File.open(path) {|f|
|
336
|
+
line = f.gets
|
337
|
+
}
|
338
|
+
return nil unless /\A#!/ =~ line
|
339
|
+
parse(line)
|
340
|
+
end
|
341
|
+
|
342
|
+
def Shebang.parse(line)
|
343
|
+
cmd, *args = *line.strip.sub(/\A\#!/, '').split(' ')
|
344
|
+
new(cmd, args)
|
345
|
+
end
|
346
|
+
|
347
|
+
def initialize(cmd, args = [])
|
348
|
+
@cmd = cmd
|
349
|
+
@args = args
|
350
|
+
end
|
351
|
+
|
352
|
+
attr_reader :cmd
|
353
|
+
attr_reader :args
|
354
|
+
|
355
|
+
def to_s
|
356
|
+
"#! #{@cmd}" + (@args.empty? ? '' : " #{@args.join(' ')}")
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
end
|
361
|
+
|
362
|
+
end
|
363
|
+
|