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.
Files changed (55) hide show
  1. data/HISTORY +47 -3
  2. data/MANIFEST +49 -16
  3. data/README.rdoc +148 -0
  4. data/bin/setup.rb +1 -5
  5. data/lib/setup.rb +2 -2
  6. data/lib/setup/base.rb +143 -0
  7. data/lib/setup/command.rb +218 -114
  8. data/lib/setup/compiler.rb +69 -0
  9. data/lib/setup/configuration.rb +822 -0
  10. data/lib/setup/constants.rb +12 -0
  11. data/lib/setup/{rubyver.rb → core_ext.rb} +0 -0
  12. data/lib/setup/documentor.rb +149 -0
  13. data/lib/setup/installer.rb +363 -0
  14. data/lib/setup/project.rb +68 -0
  15. data/lib/setup/rake.rb +44 -45
  16. data/lib/setup/session.rb +233 -0
  17. data/lib/setup/tester.rb +92 -0
  18. data/lib/setup/uninstaller.rb +76 -0
  19. data/meta/active +1 -0
  20. data/meta/collection +1 -0
  21. data/meta/{abstract → description} +0 -0
  22. data/meta/{package → name} +0 -0
  23. data/meta/repository +1 -0
  24. data/meta/ruby +3 -0
  25. data/meta/version +1 -1
  26. data/script/bstrap +5 -0
  27. data/script/bundle +64 -0
  28. data/script/setup +1338 -0
  29. data/script/test +3 -0
  30. data/test/cases/installer.rb +28 -0
  31. data/test/features/config.feature +16 -0
  32. data/test/features/document.feature +2 -0
  33. data/test/features/install.feature +72 -0
  34. data/test/features/make.feature +18 -0
  35. data/test/features/step_definitions/common_steps.rb +34 -0
  36. data/test/features/step_definitions/config_steps.rb +24 -0
  37. data/test/features/step_definitions/env.rb +37 -0
  38. data/test/features/step_definitions/install_steps.rb +75 -0
  39. data/test/features/step_definitions/setup_steps.rb +30 -0
  40. data/test/features/step_definitions/uninstall_steps.rb +8 -0
  41. data/test/features/test.feature +2 -0
  42. data/test/features/uninstall.feature +13 -0
  43. data/test/fixtures/faux-project/bin/faux +3 -0
  44. data/test/fixtures/faux-project/ext/faux/extconf.rb +12 -0
  45. data/test/fixtures/faux-project/ext/faux/faux.c +24 -0
  46. data/test/fixtures/faux-project/lib/faux.rb +1 -0
  47. metadata +58 -29
  48. data/README +0 -106
  49. data/RELEASE +0 -41
  50. data/lib/setup/build.rb +0 -2
  51. data/lib/setup/config.rb +0 -452
  52. data/lib/setup/error.rb +0 -4
  53. data/lib/setup/install.rb +0 -1007
  54. data/meta/setup/metaconfig.rb +0 -3
  55. data/test/test_installer.rb +0 -139
@@ -0,0 +1,12 @@
1
+ module Setup
2
+
3
+ #
4
+ META_EXTENSION_DIR = '.setup'
5
+
6
+ #
7
+ FILETYPES = %w( bin lib ext data etc man doc )
8
+
9
+ #
10
+ INSTALL_RECORD = 'InstalledFiles' #'.cache/setup/installedfiles'
11
+
12
+ end
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
+