crypt-isaac 0.9.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE DELETED
@@ -1,26 +0,0 @@
1
- Copyright (c) 2004 - 2005 Kirk Haines (khaines@enigo.com)
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
13
-
14
- For details about the ISAAC algorithm itself, see:
15
-
16
- http://burtleburtle.net/bob/rand/isaac.html
17
-
18
-
19
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
-
data/README DELETED
@@ -1,78 +0,0 @@
1
- Crypt::ISAAC README
2
- ============
3
-
4
- ISAAC is a cryptographically secure PRNG for generating high quality random
5
- numbers. Detailed information about the algorithm can be found at:
6
-
7
- http://burtleburtle.net/bob/rand/isaac.html
8
-
9
- This is a pure Ruby implementation of the algorithm. It is reasonably fast for
10
- a pure Ruby implementation. On an 800Mhz PIII computer running Ruby 1.8.2,
11
- and while the machine is also serving as general desktop, the library seems to
12
- consistently generate between 15000 and 16000 random numbers per second.
13
-
14
- Ruby uses the Mersenne Twister as its PRNG, and while this the Twister is
15
- a fast PRNG that produces highly random numbers, it is not strong for
16
- cryptographic purposes, nor is it suitable when one needs multiple
17
- independent streams of random numbers. Crypt::ISAAC is suitable for either
18
- purpose.
19
-
20
-
21
- Requirements
22
- ------------
23
-
24
- * Ruby 1.8 (should also run on 1.6.x)
25
-
26
-
27
- Install
28
- -------
29
-
30
- If you have never installed Crypt::ISAAC, you may run the testsuite
31
- to confirm that it works with:
32
-
33
- # ruby setup.rb test
34
-
35
- If you already have a version of Crypt::ISAAC installed, but want to
36
- confirm this one before installing, run the test suite manually as
37
- follows:
38
-
39
- # ruby test/TC_ISAAC.rb local
40
-
41
- When you are ready to install Crypt::ISAAC, type:
42
-
43
- # ruby setup.rb install
44
-
45
- This one step will install Crypt::ISAAC in your Ruby SITELIB. To test
46
- the library after installation:
47
-
48
- # ruby setup.rb test
49
-
50
- Usage
51
- -----
52
-
53
- require 'crypt/ISAAC'
54
-
55
- rng = Crypt::ISAAC.new
56
-
57
- r1 = rng.rand() # returns a floating point between 0 and 1
58
- r2 = rnd.rand(1000) # returns an integer between 0 and 999
59
-
60
- rand() should work identically to the Kernel.rand().
61
-
62
- Enjoy it. Let me know if you find anything that can be improved or that
63
- needs to be fixed.
64
-
65
-
66
- License
67
- -------
68
-
69
- The Crypt::ISAAC library is licensed with an MIT style licence.
70
- See the LICENSE file for details. As for the ISAAC algorithm itself,
71
- see:
72
-
73
- http://burtleburtle.net/bob/rand/isaac.html
74
-
75
-
76
-
77
- Kirk Haines
78
- khaines@enigo.com
data/TODO DELETED
@@ -1,3 +0,0 @@
1
- * Add a C version of the ISAAC algorithm and make it possible to install
2
- the pure Ruby version and/or a version using a C extension for better
3
- performance.
data/VERSIONS DELETED
@@ -1,3 +0,0 @@
1
- * 0.9 Initial public release. Pure Ruby.
2
- * 0.9.1 Update to tweak a couple things and reorganize project struct.
3
- Now uses a Package based installer, or can be installed as a gem.
@@ -1,171 +0,0 @@
1
- module Crypt
2
-
3
- # ISAAC is a fast, strong random number generator. Details on the
4
- # algorithm can be found here: http://burtleburtle.net/bob/rand/isaac.html
5
- # This provides a consistent and capable algorithm for producing
6
- # independent streams of quality random numbers.
7
-
8
- class ISAAC
9
-
10
- attr_accessor :randrsl, :randcnt
11
- attr_accessor :mm, :aa, :bb, :cc
12
-
13
- # When a Crypt::ISAAC object is created, it needs to be seeded for
14
- # random number generation. If the system has a /dev/urandom file,
15
- # that will be used to do the seeding by default. If false is explictly
16
- # passed when creating the object, it will instead use /dev/random to
17
- # generate its seeds. Be warned that this may make for SLOW
18
- # initialization.
19
- # If the requested source (/dev/urandom or /dev/random) do not exist,
20
- # the system will fall back to a simplistic initialization mechanism
21
- # using the builtin Mersenne Twister PRNG.
22
-
23
- def initialize(noblock = true)
24
- @mm = []
25
- @randrsl = []
26
- # Best initialization of the generator would be by pulling
27
- # numbers from /dev/random.
28
- rnd_source = noblock ? '/dev/urandom' : '/dev/random'
29
- if (FileTest.exist? rnd_source)
30
- File.open(rnd_source,'r') do |r|
31
- 256.times do |t|
32
- z = r.read(4)
33
- x = z.unpack('V')[0]
34
- @randrsl[t] = x
35
- end
36
- end
37
- else
38
- # If urandom isn't available, the standard Ruby PRNG makes an
39
- # adequate fallback.
40
- 256.times do |t|
41
- @randrsl[t] = Kernel.rand(4294967295)
42
- end
43
- end
44
- randinit(true)
45
- nil
46
- end
47
-
48
- # Works just like the standard rand() function. If called with an
49
- # integer argument, rand() will return positive random number in
50
- # the range of 0 to (argument - 1). If called without an integer
51
- # argument, rand() returns a positive floating point number less than 1.
52
-
53
- def rand(*num)
54
- if (@randcnt == 1)
55
- isaac
56
- @randcnt = 256
57
- end
58
- @randcnt -= 1
59
- if num[0].to_i > 0
60
- @randrsl[@randcnt].modulo(num[0])
61
- else
62
- ".#{@randrsl[@randcnt]}".to_f
63
- end
64
- end
65
-
66
- def isaac
67
- i = 0
68
- x = 0
69
- y = 0
70
-
71
- @cc += 1
72
- @bb += @cc
73
- @bb & 0xffffffff
74
-
75
- while (i < 256) do
76
- x = @mm[i]
77
- @aa = (@mm[(i + 128) & 255] + (@aa^(@aa << 13)) ) & 0xffffffff
78
- @mm[i] = y = (@mm[(x>>2)&255] + @aa + @bb ) & 0xffffffff
79
- @randrsl[i] = @bb = (@mm[(y>>10)&255] + x ) & 0xffffffff
80
- i += 1
81
-
82
- x = @mm[i]
83
- @aa = (@mm[(i+128)&255] + (@aa^(0x03ffffff & (@aa >> 6))) ) & 0xffffffff
84
- @mm[i] = y = (@mm[(x>>2)&255] + @aa + @bb ) & 0xffffffff
85
- @randrsl[i] = @bb = (@mm[(y>>10)&255] + x ) & 0xffffffff
86
- i += 1
87
-
88
- x = @mm[i]
89
- @aa = (@mm[(i + 128)&255] + (@aa^(@aa << 2)) ) & 0xffffffff
90
- @mm[i] = y = (@mm[(x>>2)&255] + @aa + @bb ) & 0xffffffff
91
- @randrsl[i] = @bb = (@mm[(y>>10)&255] + x ) & 0xffffffff
92
- i += 1
93
-
94
- x = @mm[i]
95
- @aa = (@mm[(i+128)&255] + (@aa^(0x0000ffff & (@aa >> 16))) ) & 0xffffffff
96
- @mm[i] = y = (@mm[(x>>2)&255] + @aa + @bb ) & 0xffffffff
97
- @randrsl[i] = @bb = (@mm[(y>>10)&255] + x ) & 0xffffffff
98
- i += 1
99
- end
100
- end
101
-
102
- def randinit(flag)
103
- i = 0
104
- a = 0
105
- b = 0
106
- c = 0
107
- d = 0
108
- e = 0
109
- f = 0
110
- g = 0
111
- @aa = @bb = @cc = 0
112
- a = b = c = d = e = f = g = h = 0x9e3779b9
113
-
114
- while (i < 4) do
115
- a ^= b<<1; d += a; b += c
116
- b ^= 0x3fffffff & (c>>2); e += b; c += d
117
- c ^= d << 8; f += c; d += e
118
- d ^= 0x0000ffff & (e >> 16); g += d; e += f
119
- e ^= f << 10; h += e; f += g
120
- f ^= 0x0fffffff & (g >> 4); a += f; g += h
121
- g ^= h << 8; b += g; h += a
122
- h ^= 0x007fffff & (a >> 9); c += h; a += b
123
- i += 1
124
- end
125
-
126
- i = 0
127
- while (i < 256) do
128
- if (flag)
129
- a+=@randrsl[i ].to_i; b+=@randrsl[i+1].to_i;
130
- c+=@randrsl[i+2]; d+=@randrsl[i+3];
131
- e+=@randrsl[i+4]; f+=@randrsl[i+5];
132
- g+=@randrsl[i+6]; h+=@randrsl[i+7];
133
- end
134
-
135
- a^=b<<11; d+=a; b+=c;
136
- b^=0x3fffffff & (c>>2); e+=b; c+=d;
137
- c^=d<<8; f+=c; d+=e;
138
- d^=0x0000ffff & (e>>16); g+=d; e+=f;
139
- e^=f<<10; h+=e; f+=g;
140
- f^=0x0fffffff & (g>>4); a+=f; g+=h;
141
- g^=h<<8; b+=g; h+=a;
142
- h^=0x007fffff & (a>>9); c+=h; a+=b;
143
- @mm[i]=a;@mm[i+1]=b; @mm[i+2]=c; @mm[i+3]=d;
144
- @mm[i+4]=e; @mm[i+5]=f; @mm[i+6]=g; @mm[i+7]=h;
145
- i += 8
146
- end
147
-
148
- if flag
149
- i = 0
150
- while (i < 256)
151
- a+=@mm[i ]; b+=@mm[i+1]; c+=@mm[i+2]; d+=@mm[i+3];
152
- e+=@mm[i+4]; f+=@mm[i+5]; g+=@mm[i+6]; h+=@mm[i+7];
153
- a^=b<<11; d+=a; b+=c;
154
- b^=0x3fffffff & (c>>2); e+=b; c+=d;
155
- c^=d<<8; f+=c; d+=e;
156
- d^=0x0000ffff & (e>>16); g+=d; e+=f;
157
- e^=f<<10; h+=e; f+=g;
158
- f^=0x0fffffff & (g>>4); a+=f; g+=h;
159
- g^=h<<8; b+=g; h+=a;
160
- h^=0x007fffff & (a>>9); c+=h; a+=b;
161
- @mm[i ]=a; @mm[i+1]=b; @mm[i+2]=c; @mm[i+3]=d;
162
- @mm[i+4]=e; @mm[i+5]=f; @mm[i+6]=g; @mm[i+7]=h;
163
- i += 8
164
- end
165
- end
166
-
167
- isaac()
168
- @randcnt=256; # /* prepare to use the first set of results */
169
- end
170
- end
171
- end
data/setup.rb DELETED
@@ -1,596 +0,0 @@
1
- require 'rbconfig'
2
- require 'fileutils'
3
- require 'pp'
4
- require 'optparse'
5
- require 'yaml'
6
-
7
- module Package
8
-
9
- class SpecificationError < StandardError; end
10
- # forward declaration of the specification classes so we can keep all
11
- # constants here
12
- class PackageSpecification_1_0; end
13
- # Default semantics
14
- PackageSpecification = PackageSpecification_1_0
15
-
16
- #TODO: could get this collected automatically with Class#inherited etc
17
- SEMANTICS = { "1.0" => PackageSpecification_1_0 }
18
-
19
- KINDS = [
20
- :bin, :lib, :ext, :data, :conf, :doc
21
- ]
22
-
23
- #{{{ list of files to be ignored stolen from setup.rb
24
- mapping = { '.' => '\.', '$' => '\$', '#' => '\#', '*' => '.*' }
25
- ignore_files = %w[core RCSLOG tags TAGS .make.state .nse_depinfo
26
- #* .#* cvslog.* ,* .del-* *.olb *~ *.old *.bak *.BAK *.orig *.rej _$* *$
27
- *.org *.in .* ]
28
- #end of robbery
29
- IGNORE_FILES = ignore_files.map do |x|
30
- Regexp.new('\A' + x.gsub(/[\.\$\#\*]/){|c| mapping[c]} + '\z')
31
- end
32
-
33
- def self.config(name)
34
- # XXX use pathname
35
- prefix = Regexp.quote(Config::CONFIG["prefix"])
36
- exec_prefix = Regexp.quote(Config::CONFIG["exec_prefix"])
37
- Config::CONFIG[name].gsub(/\A\/?(#{prefix}|#{exec_prefix})\/?/, '')
38
- end
39
-
40
- SITE_DIRS = {
41
- :bin => config("bindir"),
42
- :lib => config("sitelibdir"),
43
- :ext => config("sitearchdir"),
44
- :data => config("datadir"),
45
- :conf => config("sysconfdir"),
46
- :doc => File.join(config("datadir"), "doc"),
47
- }
48
-
49
- VENDOR_DIRS = {
50
- :bin => config("bindir"),
51
- :lib => config("rubylibdir"),
52
- :ext => config("archdir"),
53
- :data => config("datadir"),
54
- :conf => config("sysconfdir"),
55
- :doc => File.join(config("datadir"), "doc"),
56
- }
57
-
58
- MODES = {
59
- :bin => 0755,
60
- :lib => 0644,
61
- :ext => 0755, # was: 0555,
62
- :data => 0644,
63
- :conf => 0644,
64
- :doc => 0644,
65
- }
66
-
67
-
68
- SETUP_OPTIONS = {:parse_cmdline => true, :load_conf => true, :run_tasks => true}
69
-
70
- def self.setup(version, options = {}, &instructions)
71
- prefixes = dirs = nil
72
- options = SETUP_OPTIONS.dup.update(options)
73
-
74
- if options[:load_conf] && File.exist?("config.save")
75
- config = YAML.load_file "config.save"
76
- prefixes = config[:prefixes]
77
- dirs = config[:dirs]
78
- end
79
-
80
- pkg = package_specification_with_semantics(version).new(prefixes, dirs)
81
- pkg.parse_command_line if options[:parse_cmdline]
82
- pkg.instance_eval(&instructions)
83
-
84
- pkg.run_tasks if options[:run_tasks]
85
-
86
- # pkg.install
87
- pkg
88
- end
89
-
90
- def self.package_specification_with_semantics(version)
91
- #XXX: implement the full x.y(.z)? semantics
92
- r = SEMANTICS[version]
93
- raise SpecificationError, "Unknown version #{version}." unless r
94
- r
95
- end
96
-
97
-
98
- module Actions
99
-
100
- class InstallFile
101
-
102
- attr_reader :source, :destination, :mode
103
-
104
- def initialize(source, destination, mode, options)
105
- @source = source
106
- @destination = destination
107
- @mode = mode
108
- @options = options
109
- end
110
-
111
- def install
112
- FileUtils.install @source, File.join(@options.destdir, @destination),
113
- {:verbose => @options.verbose,
114
- :noop => @options.noop, :mode => @mode }
115
- end
116
-
117
- def hash
118
- [@source.hash, @destination.hash].hash
119
- end
120
-
121
- def eql?(other)
122
- self.class == other.class &&
123
- @source == other.source &&
124
- @destination == other.destination &&
125
- @mode == other.mode
126
- end
127
-
128
- def <=>(other)
129
- FULL_ORDER[self, other] || self.destination <=> other.destination
130
- end
131
- end
132
-
133
- class MkDir
134
-
135
- attr_reader :directory
136
-
137
- def initialize(directory, options)
138
- @directory = directory
139
- @options = options
140
- end
141
-
142
- def install
143
- FileUtils.mkdir_p File.join(@options.destdir, @directory),
144
- {:verbose => @options.verbose,
145
- :noop => @options.noop }
146
- end
147
-
148
- def <=>(other)
149
- FULL_ORDER[self, other] || self.directory <=> other.directory
150
- end
151
- end
152
-
153
- class FixShebang
154
-
155
- attr_reader :destination
156
-
157
- def initialize(destination, options)
158
- @options = options
159
- @destination = destination
160
- end
161
-
162
- def install
163
- path = File.join(@options.destdir, @destination)
164
- fix_shebang(path)
165
- end
166
-
167
- # taken from rpa-base, originally based on setup.rb's
168
- # modify: #!/usr/bin/ruby
169
- # modify: #! /usr/bin/ruby
170
- # modify: #!ruby
171
- # not modify: #!/usr/bin/env ruby
172
- SHEBANG_RE = /\A\#!\s*\S*ruby\S*/
173
-
174
- #TODO allow the ruby-prog to be placed in the shebang line to be passed as
175
- # an option
176
- def fix_shebang(path)
177
- tmpfile = path + '.tmp'
178
- begin
179
- #XXX: needed at all?
180
- # it seems that FileUtils doesn't expose its default output
181
- # @fileutils_output = $stderr
182
- # we might want to allow this to be redirected.
183
- $stderr.puts "shebang:open #{tmpfile}" if @options.verbose
184
- unless @options.noop
185
- File.open(path) do |r|
186
- File.open(tmpfile, 'w', 0755) do |w|
187
- first = r.gets
188
- return unless SHEBANG_RE =~ first
189
- w.print first.sub(SHEBANG_RE, '#!' + Config::CONFIG['ruby-prog'])
190
- w.write r.read
191
- end
192
- end
193
- end
194
- FileUtils.mv(tmpfile, path, :verbose => @options.verbose,
195
- :noop => @options.noop)
196
- ensure
197
- FileUtils.rm_f(tmpfile, :verbose => @options.verbose,
198
- :noop => @options.noop)
199
- end
200
- end
201
-
202
- def <=>(other)
203
- FULL_ORDER[self, other] || self.destination <=> other.destination
204
- end
205
-
206
- def hash
207
- @destination.hash
208
- end
209
-
210
- def eql?(other)
211
- self.class == other.class && self.destination == other.destination
212
- end
213
- end
214
-
215
- order = [MkDir, InstallFile, FixShebang]
216
- FULL_ORDER = lambda do |me, other|
217
- a, b = order.index(me.class), order.index(other.class)
218
- if a && b
219
- (r = a - b) == 0 ? nil : r
220
- else
221
- -1 # arbitrary
222
- end
223
- end
224
-
225
- class ActionList < Array
226
-
227
- def directories!(options)
228
- dirnames = []
229
- map! { |d|
230
- if d.kind_of?(InstallFile) && !dirnames.include?(File.dirname(d.destination))
231
- dirnames << File.dirname(d.destination)
232
- [MkDir.new(File.dirname(d.destination), options), d]
233
- else
234
- d
235
- end
236
- }
237
- flatten!
238
- end
239
-
240
- def run(task)
241
- each { |action| action.__send__ task }
242
- end
243
- end
244
-
245
- end # module Actions
246
-
247
- Options = Struct.new(:noop, :verbose, :destdir)
248
-
249
- class PackageSpecification_1_0
250
-
251
- TASKS = %w[config setup install test show]
252
- # default options for translate(foo => bar)
253
- TRANSLATE_DEFAULT_OPTIONS = { :inherit => true }
254
-
255
- def self.declare_file_type(args, &handle_arg)
256
- str_arr_p = lambda{|x| Array === x && x.all?{|y| String === y}}
257
-
258
- # strict type checking --- we don't want this to be extended arbitrarily
259
- unless args.size == 1 && Hash === args.first &&
260
- args.first.all?{|f,r| [Proc, String, NilClass].include?(r.class) &&
261
- (String === f || str_arr_p[f])} or
262
- args.all?{|x| String === x || str_arr_p[x]}
263
- raise SpecificationError,
264
- "Unspecified semantics for the given arguments: #{args.inspect}"
265
- end
266
-
267
- if args.size == 1 && Hash === args.first
268
- args.first.to_a.each do |file, rename_info|
269
- if Array === file
270
- # ignoring boring files
271
- handle_arg.call(file, true, rename_info)
272
- else
273
- # we do want "boring" files given explicitly
274
- handle_arg.call([file], false, rename_info)
275
- end
276
- end
277
- else
278
- args.each do |a|
279
- if Array === a
280
- a.each{|file| handle_arg.call(file, true, nil)}
281
- else
282
- handle_arg.call(a, false, nil)
283
- end
284
- end
285
- end
286
- end
287
-
288
- #{{{ define the file tagging methods
289
- KINDS.each { |kind|
290
- define_method(kind) { |*args| # if this were 1.9 we could also take a block
291
- bin_callback = lambda do |kind_, type, dest, options|
292
- next if kind_ != :bin || type == :dir
293
- @actions << Actions::FixShebang.new(dest, options)
294
- end
295
- #TODO: refactor
296
- self.class.declare_file_type(args) do |files, ignore_p, opt_rename_info|
297
- files.each do |file|
298
- next if ignore_p && IGNORE_FILES.any?{|re| re.match(file)}
299
- add_file(kind, file, opt_rename_info, &bin_callback)
300
- end
301
- end
302
- }
303
- }
304
-
305
- def unit_test(*files)
306
- @unit_tests.concat files.flatten
307
- end
308
-
309
- attr_accessor :actions, :options
310
-
311
- def self.metadata(name)
312
- define_method(name) { |*args|
313
- if args.size == 1
314
- @metadata[name] = args.first
315
- end
316
- @metadata[name]
317
- }
318
- end
319
-
320
- metadata :name
321
- metadata :version
322
- metadata :author
323
-
324
-
325
- def translate_dir(kind, dir)
326
- replaced_dir_parts = dir.split(%r{/})
327
- kept_dir_parts = []
328
- loop do
329
- replaced_path = replaced_dir_parts.join("/")
330
- target, options = @translate[kind][replaced_path]
331
- options ||= TRANSLATE_DEFAULT_OPTIONS
332
- if target && (replaced_path == dir || options[:inherit])
333
- dir = (target != '' ? File.join(target, *kept_dir_parts) :
334
- File.join(*kept_dir_parts))
335
- break
336
- end
337
- break if replaced_dir_parts.empty?
338
- kept_dir_parts.unshift replaced_dir_parts.pop
339
- end
340
- dir
341
- end
342
-
343
- def add_file(kind, filename, new_filename_info, &callback)
344
- #TODO: refactor!!!
345
- if File.directory? filename #XXX setup.rb and rpa-base defined File.dir?
346
- # to cope with some win32 issue
347
- dir = filename.sub(/\A\.\//, "").sub(/\/\z/, "")
348
- dest = File.join(@prefixes[kind], @dirs[kind], translate_dir(kind, dir))
349
- @actions << Actions::MkDir.new(dest, @options)
350
- callback.call(kind, :dir, dest, @options) if block_given?
351
- else
352
- if new_filename_info
353
- case new_filename_info
354
- when Proc
355
- dest_name = new_filename_info.call(filename.dup)
356
- else
357
- dest_name = new_filename_info.dup
358
- end
359
- else
360
- dest_name = filename.dup
361
- end
362
-
363
- dirname = File.dirname(dest_name)
364
- dirname = "" if dirname == "."
365
- dest_name = File.join(translate_dir(kind, dirname), File.basename(dest_name))
366
-
367
- dest = File.join(@prefixes[kind], @dirs[kind], dest_name)
368
- @actions << Actions::InstallFile.new(filename, dest, MODES[kind], @options)
369
- callback.call(kind, :file, dest, @options) if block_given?
370
- end
371
- end
372
-
373
- def initialize(prefixes = nil, dirs = nil)
374
- @prefix = Config::CONFIG["prefix"].gsub(/\A\//, '')
375
- @translate = {}
376
- @prefixes = (prefixes || {}).dup
377
- KINDS.each { |kind|
378
- @prefixes[kind] = @prefix unless prefixes
379
- @translate[kind] = {}
380
- }
381
-
382
- @dirs = (dirs || {}).dup
383
- @dirs.update SITE_DIRS unless dirs
384
-
385
- @actions = Actions::ActionList.new
386
-
387
- @metadata = {}
388
- @unit_tests = []
389
-
390
- @options = Options.new
391
- @options.verbose = true
392
- @options.noop = false # XXX for testing
393
- @options.destdir = ''
394
-
395
- @tasks = []
396
- end
397
-
398
- def aoki
399
- (KINDS - [:ext]).each { |kind|
400
- translate(kind, kind.to_s => "", :inherit => true)
401
- __send__ kind, Dir["#{kind}/**/*"]
402
- }
403
- translate(:ext, "ext/*" => "", :inherit => true)
404
- ext Dir["ext/**/*.#{Config::CONFIG['DLEXT']}"]
405
- end
406
-
407
- def install
408
- puts "Installing #{name || "unknown package"} #{version}..." if options.verbose
409
-
410
- actions.uniq!
411
- actions.sort!
412
- actions.directories!(options)
413
-
414
- #pp self
415
-
416
- actions.run :install
417
- end
418
-
419
- def test
420
- unless @unit_tests.empty?
421
- puts "Testing #{name || "unknown package"} #{version}..." if options.verbose
422
- require 'test/unit'
423
- unless options.noop
424
- t = Test::Unit::AutoRunner.new(true)
425
- t.process_args(@unit_tests)
426
- t.run
427
- end
428
- end
429
- end
430
-
431
- def config
432
- File.open("config.save", "w") { |f|
433
- YAML.dump({:prefixes => @prefixes, :dirs => @dirs}, f)
434
- }
435
- end
436
-
437
- def show
438
- KINDS.each { |kind|
439
- puts "#{kind}\t#{File.join(options.destdir, @prefixes[kind], @dirs[kind])}"
440
- }
441
- end
442
-
443
- def translate(kind, additional_translations)
444
- default_opts = TRANSLATE_DEFAULT_OPTIONS.dup
445
- key_val_pairs = additional_translations.to_a
446
- option_pairs = key_val_pairs.select{|(k,v)| Symbol === k}
447
- default_opts.update(Hash[*option_pairs.flatten])
448
-
449
- (key_val_pairs - option_pairs).each do |key, val|
450
- add_translation(kind, key, val, default_opts)
451
- end
452
- end
453
-
454
- def add_translation(kind, src, dest, options)
455
- if is_glob?(src)
456
- dirs = expand_dir_glob(src)
457
- else
458
- dirs = [src]
459
- end
460
- dirs.each do |dirname|
461
- dirname = dirname.sub(%r{\A\./}, "").sub(%r{/\z}, "")
462
- @translate[kind].update({dirname => [dest, options]})
463
- end
464
- end
465
-
466
- def is_glob?(x)
467
- /(^|[^\\])[*?{\[]/.match(x)
468
- end
469
-
470
- def expand_dir_glob(src)
471
- Dir[src].select{|x| File.directory?(x)}
472
- end
473
-
474
- def clean_path(path)
475
- path.gsub(/\A\//, '').gsub(/\/+\Z/, '').squeeze("/")
476
- end
477
-
478
- def parse_command_line
479
- opts = OptionParser.new(nil, 24, ' ') { |opts|
480
- opts.banner = "Usage: setup.rb [options] [task]"
481
-
482
- opts.separator ""
483
- opts.separator "Tasks:"
484
- opts.separator " config configures paths"
485
- opts.separator " show shows paths"
486
- opts.separator " setup compiles ruby extentions and others XXX"
487
- opts.separator " install installs files"
488
- opts.separator " test runs unit tests"
489
-
490
-
491
- opts.separator ""
492
- opts.separator "Specific options:"
493
-
494
- opts.on "--prefix=PREFIX",
495
- "path prefix of target environment [#@prefix]" do |prefix|
496
- @prefix.replace clean_path(prefix) # Shared!
497
- end
498
-
499
- opts.separator ""
500
-
501
- KINDS.each { |kind|
502
- opts.on "--#{kind}prefix=PREFIX",
503
- "path prefix for #{kind} files [#{@prefixes[kind]}]" do |prefix|
504
- @prefixes[kind] = clean_path(prefix)
505
- end
506
- }
507
-
508
- opts.separator ""
509
-
510
- KINDS.each { |kind|
511
- opts.on "--#{kind}dir=PREFIX",
512
- "directory for #{kind} files [#{@dirs[kind]}]" do |prefix|
513
- @dirs[kind] = clean_path(prefix)
514
- end
515
- }
516
-
517
- opts.separator ""
518
-
519
- KINDS.each { |kind|
520
- opts.on "--#{kind}=PREFIX",
521
- "absolute directory for #{kind} files [#{File.join(@prefixes[kind], @dirs[kind])}]" do |prefix|
522
- @prefixes[kind] = clean_path(prefix)
523
- end
524
- }
525
-
526
- opts.separator ""
527
- opts.separator "Predefined path configurations:"
528
- opts.on "--site", "install into site-local directories (default)" do
529
- @dirs.update SITE_DIRS
530
- end
531
-
532
- opts.on "--vendor", "install into distribution directories (for packagers)" do
533
- @dirs.update VENDOR_DIRS
534
- end
535
-
536
- opts.separator ""
537
- opts.separator "General options:"
538
-
539
- opts.on "--destdir=DESTDIR",
540
- "install all files relative to DESTDIR (/)" do |destdir|
541
- @options.destdir = destdir
542
- end
543
-
544
- opts.on "--dry-run", "only display what to do if given [#{@options.noop}]" do
545
- @options.noop = true
546
- end
547
-
548
- opts.on "--no-harm", "only display what to do if given" do
549
- @options.noop = true
550
- end
551
-
552
- opts.on "--[no-]verbose", "output messages verbosely [#{@options.verbose}]" do |verbose|
553
- @options.verbose = verbose
554
- end
555
-
556
- opts.on_tail("-h", "--help", "Show this message") do
557
- puts opts
558
- exit
559
- end
560
- }
561
-
562
- opts.parse! ARGV
563
-
564
- if (ARGV - TASKS).empty? # Only existing tasks?
565
- @tasks = ARGV
566
- @tasks = ["install"] if @tasks.empty?
567
- else
568
- abort "Unknown task(s) #{(ARGV-TASKS).join ", "}."
569
- end
570
- end
571
-
572
- def run_tasks
573
- @tasks.each { |task| __send__ task }
574
- end
575
- end
576
-
577
- end # module Package
578
-
579
- #XXX incomplete setup.rb support for the hooks
580
- require 'rbconfig'
581
- def config(x)
582
- Config::CONFIG[x]
583
- end
584
-
585
- #{{{ small example
586
- if $0 == __FILE__
587
- Package.setup("1.0") {
588
- name "crypt-isaac"
589
-
590
- lib "lib/crypt-isaac.rb"
591
-
592
- unit_test Dir["test/TC*.rb"]
593
- }
594
- end
595
-
596
- # vim: sw=2 sts=2 et ts=8