ruby-mp3info 0.6.16 → 0.7

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.
@@ -1,5 +1,5 @@
1
- #!/usr/bin/env ruby1.9
2
- # coding:utf-8
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
3
 
4
4
  $:.unshift("lib/")
5
5
 
@@ -10,7 +10,7 @@ require "tempfile"
10
10
  require "zlib"
11
11
  require "yaml"
12
12
 
13
- system("which id3v2 > /dev/null") || raise("id3v2 not found")
13
+ GOT_ID3V2 = system("which id3v2 > /dev/null")
14
14
 
15
15
  class Mp3InfoTest < Test::Unit::TestCase
16
16
 
@@ -36,20 +36,7 @@ class Mp3InfoTest < Test::Unit::TestCase
36
36
  "genre" => 233
37
37
  }
38
38
 
39
- FIXTURES = YAML::load_file( File.join(File.dirname(__FILE__), "fixtures.yml") )
40
-
41
39
  def setup
42
- # Command to create a gzip'ed dummy MP3
43
- # $ dd if=/dev/zero bs=1024 count=15 | \
44
- # lame --quiet --preset cbr 128 -r -s 44.1 --bitwidth 16 - - | \
45
- # ruby -rbase64 -rzlib -ryaml -e 'print(Zlib::Deflate.deflate($stdin.read)'
46
- # vbr:
47
- # $ dd if=/dev/zero of=#{tempfile.path} bs=1024 count=30000 |
48
- # system("lame -h -v -b 112 -r -s 44.1 --bitwidth 16 - /tmp/vbr.mp3
49
- @valid_mp3, @valid_mp3_2_2, @vbr_mp3 = %w{empty_mp3 2_2_tagged vbr}.collect do |fixture_key|
50
- Zlib::Inflate.inflate(FIXTURES[fixture_key])
51
- end
52
-
53
40
  @tag = {
54
41
  "title" => "title",
55
42
  "artist" => "artist",
@@ -60,7 +47,7 @@ class Mp3InfoTest < Test::Unit::TestCase
60
47
  "genre_s" => "Blues",
61
48
  "tracknum" => 36
62
49
  }
63
- File.open(TEMP_FILE, "w") { |f| f.write(@valid_mp3) }
50
+ load_fixture_to_temp_file("empty_mp3")
64
51
  end
65
52
 
66
53
  def teardown
@@ -94,7 +81,7 @@ class Mp3InfoTest < Test::Unit::TestCase
94
81
  end
95
82
 
96
83
  def test_vbr_mp3_length
97
- File.open(TEMP_FILE, "w") { |f| f.write(@vbr_mp3) }
84
+ load_fixture_to_temp_file("vbr")
98
85
 
99
86
  Mp3Info.open(TEMP_FILE) do |info|
100
87
  assert(info.vbr)
@@ -145,8 +132,7 @@ class Mp3InfoTest < Test::Unit::TestCase
145
132
 
146
133
  def id3_test(tag_str, valid_tag)
147
134
  tag = "TAG" + tag_str
148
- File.open(TEMP_FILE, "w") do |f|
149
- f.write(@valid_mp3)
135
+ File.open(TEMP_FILE, "a") do |f|
150
136
  f.write(tag)
151
137
  end
152
138
  assert(Mp3Info.hastag1?(TEMP_FILE))
@@ -156,7 +142,7 @@ class Mp3InfoTest < Test::Unit::TestCase
156
142
  end
157
143
 
158
144
  def test_removetag2
159
- w = write_tag2_to_temp_file({"TIT2" => "sdfqdsf"})
145
+ w = write_tag2_to_temp_file("TIT2" => "sdfqdsf")
160
146
 
161
147
  assert( Mp3Info.hastag2?(TEMP_FILE) )
162
148
  Mp3Info.removetag2(TEMP_FILE)
@@ -200,7 +186,7 @@ class Mp3InfoTest < Test::Unit::TestCase
200
186
 
201
187
  def test_id3v2_version
202
188
  written_tag = write_tag2_to_temp_file(DUMMY_TAG2)
203
- assert_equal( "2.#{ID3v2::WRITE_VERSION}.0", written_tag.version )
189
+ assert_equal( "2.3.0", written_tag.version )
204
190
  end
205
191
 
206
192
  def test_id3v2_methods
@@ -214,38 +200,42 @@ class Mp3InfoTest < Test::Unit::TestCase
214
200
  end
215
201
 
216
202
  def test_id3v2_basic
217
- w = write_tag2_to_temp_file(DUMMY_TAG2)
218
- assert_equal(DUMMY_TAG2, w)
219
- id3v2_prog_test(DUMMY_TAG2, w)
203
+ written_tag = write_tag2_to_temp_file(DUMMY_TAG2)
204
+ assert_equal(DUMMY_TAG2, written_tag)
205
+ id3v2_prog_test(DUMMY_TAG2, written_tag)
220
206
  end
221
207
 
222
208
  #test the tag with the "id3v2" program
223
209
  def id3v2_prog_test(tag, written_tag)
224
- return if RUBY_PLATFORM =~ /win32/
225
- return if `which id3v2`.empty?
210
+ return unless GOT_ID3V2
226
211
  start = false
227
212
  id3v2_output = {}
228
- `id3v2 -l #{TEMP_FILE}`.split(/\n/).each do |line|
213
+ =begin
214
+ id3v2 tag info for test/test_mp3info.mp3:
215
+ COMM (Comments): (~)[ENG]:
216
+ test/test_mp3info.mp3: No ID3v1 tag
217
+ =end
218
+ raw_output = `id3v2 -l #{TEMP_FILE}`
219
+ raw_output.split(/\n/).each do |line|
229
220
  if line =~ /^id3v2 tag info/
230
221
  start = true
231
222
  next
232
223
  end
233
224
  next unless start
234
- k, v = /^(.{4}) \(.+\): (.+)$/.match(line)[1,2]
235
- case k
236
- #COMM (Comments): ()[spa]: fmg
237
- when "COMM"
238
- v.sub!(/\(\)\[.{3}\]: (.+)/, '\1')
225
+ if match = /^(.{4}) \(.+\): (.+)$/.match(line)
226
+ k, v = match[1, 2]
227
+ case k
228
+ #COMM (Comments): ()[spa]: fmg
229
+ when "COMM"
230
+ v.sub!(/\(\)\[.{3}\]: (.+)/, '\1')
231
+ end
232
+ id3v2_output[k] = v
239
233
  end
240
- id3v2_output[k] = v
241
234
  end
242
235
 
243
236
  assert_equal( id3v2_output, written_tag, "id3v2 program output doesn't match")
244
237
  end
245
238
 
246
- def test_id3v2_trash
247
- end
248
-
249
239
  def test_id3v2_complex
250
240
  tag = {}
251
241
  #ID3v2::TAGS.keys.each do |k|
@@ -262,16 +252,13 @@ class Mp3InfoTest < Test::Unit::TestCase
262
252
  assert_equal(tag, write_tag2_to_temp_file(tag))
263
253
  end
264
254
 
265
- def test_infinite_loop_on_seek_to_v2_end
266
-
267
- end
268
-
269
255
  def test_leading_char_gets_chopped
270
256
  tag2 = DUMMY_TAG2.dup
271
257
  tag2["WOAR"] = "http://foo.bar"
272
258
  w = write_tag2_to_temp_file(tag2)
273
259
  assert_equal("http://foo.bar", w["WOAR"])
274
260
 
261
+ return unless GOT_ID3V2
275
262
  system(%(id3v2 --WOAR "http://foo.bar" "#{TEMP_FILE}"))
276
263
 
277
264
  Mp3Info.open(TEMP_FILE) do |mp3|
@@ -280,7 +267,7 @@ class Mp3InfoTest < Test::Unit::TestCase
280
267
  end
281
268
 
282
269
  def test_reading2_2_tags
283
- File.open(TEMP_FILE, "w") { |f| f.write(@valid_mp3_2_2) }
270
+ load_fixture_to_temp_file("2_2_tagged")
284
271
 
285
272
  Mp3Info.open(TEMP_FILE) do |mp3|
286
273
  assert_equal "2.2.0", mp3.tag2.version
@@ -313,7 +300,8 @@ class Mp3InfoTest < Test::Unit::TestCase
313
300
  end
314
301
 
315
302
  def test_writing_universal_tag_from_2_2_tags
316
- File.open(TEMP_FILE, "w") { |f| f.write(@valid_mp3_2_2) }
303
+ load_fixture_to_temp_file("2_2_tagged")
304
+
317
305
  Mp3Info.open(TEMP_FILE) do |mp3|
318
306
  mp3.tag.artist = "toto"
319
307
  mp3.tag.comments = "comments"
@@ -352,7 +340,7 @@ class Mp3InfoTest < Test::Unit::TestCase
352
340
  Mp3Info.open(fn) do |mp3|
353
341
  mp3.tag.title = fn
354
342
  mp3.flush
355
- if RUBY_VERSION < "1.9.0"
343
+ if RUBY_VERSION[0..2] == "1.8"
356
344
  assert_equal fn, mp3.tag.title
357
345
  else
358
346
  assert_equal fn, mp3.tag.title.force_encoding("utf-8")
@@ -363,58 +351,6 @@ class Mp3InfoTest < Test::Unit::TestCase
363
351
  end
364
352
  end
365
353
 
366
- def test_validity_of_id3v2_options
367
- info = Mp3Info.new(TEMP_FILE)
368
- expected_hash = { :lang => "ENG", :encoding => "iso-8859-1" }
369
- assert_equal( expected_hash, info.tag2.options)
370
-
371
- assert_raises(ArgumentError) do
372
- Mp3Info.new(TEMP_FILE, :encoding => "bad encoding")
373
- end
374
- end
375
-
376
- def test_encoding_read
377
- Mp3Info.open(TEMP_FILE) do |mp3|
378
- mp3.tag2['TEST'] = "all\xe9"
379
- end
380
-
381
- Mp3Info.open(TEMP_FILE, :encoding => "utf-8") do |mp3|
382
- assert_equal "allé", mp3.tag2['TEST']
383
- end
384
-
385
- Mp3Info.open(TEMP_FILE, :encoding => "iso-8859-1") do |mp3|
386
- if RUBY_VERSION < "1.9.0"
387
- assert_equal "all\xe9", mp3.tag2['TEST']
388
- else
389
- assert_equal "all\xe9".force_encoding("binary"), mp3.tag2['TEST']
390
- end
391
- end
392
- end
393
-
394
- def test_encoding_write
395
- Mp3Info.open(TEMP_FILE, :encoding => 'utf-8') do |mp3|
396
- mp3.tag2['TEST'] = "all\xc3\xa9"
397
- end
398
-
399
- Mp3Info.open(TEMP_FILE, :encoding => "iso-8859-1") do |mp3|
400
- if RUBY_VERSION < "1.9.0"
401
- assert_equal "all\xe9", mp3.tag2['TEST']
402
- else
403
- assert_equal "all\xe9".force_encoding("iso-8859-1"), mp3.tag2['TEST']
404
- end
405
- end
406
- end
407
-
408
- =begin
409
- def test_should_raises_exception_when_writing_badly_encoded_frames
410
- assert_raises(Iconv::Failure) do
411
- Mp3Info.open(TEMP_FILE, :encoding => 'utf-8') do |mp3|
412
- mp3.tag2['TEST'] = "all\xc3"
413
- end
414
- end
415
- end
416
- =end
417
-
418
354
  def test_audio_content
419
355
  require "digest/md5"
420
356
 
@@ -441,7 +377,7 @@ class Mp3InfoTest < Test::Unit::TestCase
441
377
  end
442
378
 
443
379
  def test_audio_content_problematic
444
- File.open(TEMP_FILE, "w") { |f| f.write(FIXTURES["audio_content_fixture"]) }
380
+ load_fixture_to_temp_file("audio_content_fixture", false)
445
381
  Mp3Info.open(TEMP_FILE) do |mp3|
446
382
  expected_pos = 150
447
383
  audio_content_pos, audio_content_size = mp3.audio_content
@@ -452,9 +388,7 @@ class Mp3InfoTest < Test::Unit::TestCase
452
388
 
453
389
  def test_headerless_vbr_file
454
390
  mp3_length = 3
455
- # this will generate a 15 sec mp3 file (44100hz*16bit*2channels) = 60/4 = 15
456
- system("dd if=/dev/urandom bs=44100 count=#{mp3_length*4} 2>/dev/null | \
457
- lame -v -m s --vbr-new --preset 128 -r -s 44.1 --bitwidth 16 - - > #{TEMP_FILE} 2>/dev/null")
391
+ load_fixture_to_temp_file("small_vbr_mp3")
458
392
 
459
393
  Mp3Info.open(TEMP_FILE) do |mp3|
460
394
  assert mp3.vbr
@@ -555,6 +489,29 @@ class Mp3InfoTest < Test::Unit::TestCase
555
489
  io
556
490
  end
557
491
 
492
+ FIXTURES = YAML::load_file( File.join(File.dirname(__FILE__), "fixtures.yml") )
493
+
494
+ def load_fixture_to_temp_file(fixture_key, zlibed = true)
495
+ # Command to create a gzip'ed dummy MP3
496
+ # $ dd if=/dev/zero bs=1024 count=15 | \
497
+ # lame --quiet --preset cbr 128 -r -s 44.1 --bitwidth 16 - - | \
498
+ # ruby -rbase64 -rzlib -ryaml -e 'print(Zlib::Deflate.deflate($stdin.read)'
499
+ # vbr:
500
+ # $ dd if=/dev/zero of=#{tempfile.path} bs=1024 count=30000 |
501
+ # system("lame -h -v -b 112 -r -s 44.1 --bitwidth 16 - /tmp/vbr.mp3
502
+ #
503
+ # this will generate a #{mp3_length} sec mp3 file (44100hz*16bit*2channels) = 60/4 = 15
504
+ # system("dd if=/dev/urandom bs=44100 count=#{mp3_length*4} 2>/dev/null | \
505
+ # lame -v -m s --vbr-new --preset 128 -r -s 44.1 --bitwidth 16 - - > #{TEMP_FILE} 2>/dev/null")
506
+ content = FIXTURES[fixture_key]
507
+ if zlibed
508
+ content = Zlib::Inflate.inflate(content)
509
+ end
510
+
511
+ File.open(TEMP_FILE, "w") do |f|
512
+ f.write(content)
513
+ end
514
+ end
558
515
  =begin
559
516
 
560
517
  def test_encoder
metadata CHANGED
@@ -1,94 +1,86 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: ruby-mp3info
3
- version: !ruby/object:Gem::Version
4
- hash: 39
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.7'
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 6
9
- - 16
10
- version: 0.6.16
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Guillaume Pierronnet
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2011-11-10 00:00:00 Z
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
21
- name: hoe
12
+ date: 2012-03-02 00:00:00.000000000 +01:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rdoc
17
+ requirement: &79955210 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ~>
21
+ - !ruby/object:Gem::Version
22
+ version: '3.10'
23
+ type: :development
22
24
  prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
25
+ version_requirements: *79955210
26
+ - !ruby/object:Gem::Dependency
27
+ name: hoe
28
+ requirement: &79954780 !ruby/object:Gem::Requirement
24
29
  none: false
25
- requirements:
30
+ requirements:
26
31
  - - ~>
27
- - !ruby/object:Gem::Version
28
- hash: 23
29
- segments:
30
- - 2
31
- - 10
32
- version: "2.10"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.12'
33
34
  type: :development
34
- version_requirements: *id001
35
- description: |-
36
- ruby-mp3info read low-level informations and manipulate tags on
37
- mp3 files.
38
- email:
39
- - moumar@rubyforge.org
40
- executables: []
35
+ prerelease: false
36
+ version_requirements: *79954780
37
+ description: ! 'ruby-mp3info read low-level informations and manipulate tags on
41
38
 
39
+ mp3 files.'
40
+ email:
41
+ - guillaume.pierronnet@gmail.com
42
+ executables: []
42
43
  extensions: []
43
-
44
- extra_rdoc_files:
44
+ extra_rdoc_files:
45
45
  - History.txt
46
46
  - Manifest.txt
47
47
  - README.txt
48
- files:
48
+ files:
49
49
  - History.txt
50
50
  - Manifest.txt
51
51
  - README.txt
52
52
  - Rakefile
53
- - install.rb
54
53
  - lib/mp3info.rb
55
54
  - lib/mp3info/extension_modules.rb
56
55
  - lib/mp3info/id3v2.rb
57
56
  - test/test_ruby-mp3info.rb
58
57
  - .gemtest
58
+ has_rdoc: true
59
59
  homepage: http://github.com/moumar/ruby-mp3info
60
60
  licenses: []
61
-
62
61
  post_install_message:
63
- rdoc_options:
62
+ rdoc_options:
64
63
  - --main
65
64
  - README.txt
66
- require_paths:
65
+ require_paths:
67
66
  - lib
68
- required_ruby_version: !ruby/object:Gem::Requirement
67
+ required_ruby_version: !ruby/object:Gem::Requirement
69
68
  none: false
70
- requirements:
71
- - - ">="
72
- - !ruby/object:Gem::Version
73
- hash: 3
74
- segments:
75
- - 0
76
- version: "0"
77
- required_rubygems_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ! '>='
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
74
  none: false
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- hash: 3
83
- segments:
84
- - 0
85
- version: "0"
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
86
79
  requirements: []
87
-
88
80
  rubyforge_project: ruby-mp3info
89
- rubygems_version: 1.8.10
81
+ rubygems_version: 1.6.2
90
82
  signing_key:
91
83
  specification_version: 3
92
84
  summary: ruby-mp3info read low-level informations and manipulate tags on mp3 files.
93
- test_files:
85
+ test_files:
94
86
  - test/test_ruby-mp3info.rb
data/install.rb DELETED
@@ -1,1022 +0,0 @@
1
- #
2
- # This file is automatically generated. DO NOT MODIFY!
3
- #
4
- # install.rb
5
- #
6
- # Copyright (c) 2000-2002 Minero Aoki <aamine@loveruby.net>
7
- #
8
- # This program is free software.
9
- # You can distribute/modify this program under the terms of
10
- # the GNU Lesser General Public License version 2.
11
- #
12
-
13
- ### begin compat.rb
14
-
15
- unless Enumerable.instance_methods.include? 'inject'
16
- module Enumerable
17
- def inject( result )
18
- each do |i|
19
- result = yield(result, i)
20
- end
21
- result
22
- end
23
- end
24
- end
25
-
26
- def File.read_all( fname )
27
- File.open(fname, 'rb') {|f| return f.read }
28
- end
29
-
30
- def File.write( fname, str )
31
- File.open(fname, 'wb') {|f| f.write str }
32
- end
33
-
34
- ### end compat.rb
35
- ### begin config.rb
36
-
37
- if i = ARGV.index(/\A--rbconfig=/)
38
- file = $'
39
- ARGV.delete_at(i)
40
- require file
41
- else
42
- require 'rbconfig'
43
- end
44
-
45
-
46
- class ConfigTable
47
-
48
- c = ::Config::CONFIG
49
-
50
- rubypath = c['bindir'] + '/' + c['ruby_install_name']
51
-
52
- major = c['MAJOR'].to_i
53
- minor = c['MINOR'].to_i
54
- teeny = c['TEENY'].to_i
55
- version = "#{major}.#{minor}"
56
-
57
- # ruby ver. >= 1.4.4?
58
- newpath_p = ((major >= 2) or
59
- ((major == 1) and
60
- ((minor >= 5) or
61
- ((minor == 4) and (teeny >= 4)))))
62
-
63
- re = Regexp.new('\A' + Regexp.quote(c['prefix']))
64
- subprefix = lambda {|path|
65
- re === path and path.sub(re, '$prefix')
66
- }
67
-
68
- if c['rubylibdir']
69
- # V < 1.6.3
70
- stdruby = subprefix.call(c['rubylibdir'])
71
- siteruby = subprefix.call(c['sitedir'])
72
- versite = subprefix.call(c['sitelibdir'])
73
- sodir = subprefix.call(c['sitearchdir'])
74
- elsif newpath_p
75
- # 1.4.4 <= V <= 1.6.3
76
- stdruby = "$prefix/lib/ruby/#{version}"
77
- siteruby = subprefix.call(c['sitedir'])
78
- versite = siteruby + '/' + version
79
- sodir = "$site-ruby/#{c['arch']}"
80
- else
81
- # V < 1.4.4
82
- stdruby = "$prefix/lib/ruby/#{version}"
83
- siteruby = "$prefix/lib/ruby/#{version}/site_ruby"
84
- versite = siteruby
85
- sodir = "$site-ruby/#{c['arch']}"
86
- end
87
-
88
- DESCRIPTER = [
89
- [ 'prefix', [ c['prefix'],
90
- 'path',
91
- 'path prefix of target environment' ] ],
92
- [ 'std-ruby', [ stdruby,
93
- 'path',
94
- 'the directory for standard ruby libraries' ] ],
95
- [ 'site-ruby-common', [ siteruby,
96
- 'path',
97
- 'the directory for version-independent non-standard ruby libraries' ] ],
98
- [ 'site-ruby', [ versite,
99
- 'path',
100
- 'the directory for non-standard ruby libraries' ] ],
101
- [ 'bin-dir', [ '$prefix/bin',
102
- 'path',
103
- 'the directory for commands' ] ],
104
- [ 'rb-dir', [ '$site-ruby',
105
- 'path',
106
- 'the directory for ruby scripts' ] ],
107
- [ 'so-dir', [ sodir,
108
- 'path',
109
- 'the directory for ruby extentions' ] ],
110
- [ 'data-dir', [ '$prefix/share',
111
- 'path',
112
- 'the directory for shared data' ] ],
113
- [ 'ruby-path', [ rubypath,
114
- 'path',
115
- 'path to set to #! line' ] ],
116
- [ 'ruby-prog', [ rubypath,
117
- 'name',
118
- 'the ruby program using for installation' ] ],
119
- [ 'make-prog', [ 'make',
120
- 'name',
121
- 'the make program to compile ruby extentions' ] ],
122
- [ 'without-ext', [ 'no',
123
- 'yes/no',
124
- 'does not compile/install ruby extentions' ] ]
125
- ]
126
-
127
- SAVE_FILE = 'config.save'
128
-
129
- def ConfigTable.each_name( &block )
130
- keys().each(&block)
131
- end
132
-
133
- def ConfigTable.keys
134
- DESCRIPTER.collect {|k,*dummy| k }
135
- end
136
-
137
- def ConfigTable.each_definition( &block )
138
- DESCRIPTER.each(&block)
139
- end
140
-
141
- def ConfigTable.get_entry( name )
142
- name, ent = DESCRIPTER.assoc(name)
143
- ent
144
- end
145
-
146
- def ConfigTable.get_entry!( name )
147
- get_entry(name) or raise ArgumentError, "no such config: #{name}"
148
- end
149
-
150
- def ConfigTable.add_entry( name, vals )
151
- ConfigTable::DESCRIPTER.push [name,vals]
152
- end
153
-
154
- def ConfigTable.remove_entry( name )
155
- get_entry name or raise ArgumentError, "no such config: #{name}"
156
- DESCRIPTER.delete_if {|n,arr| n == name }
157
- end
158
-
159
- def ConfigTable.config_key?( name )
160
- get_entry(name) ? true : false
161
- end
162
-
163
- def ConfigTable.bool_config?( name )
164
- ent = get_entry(name) or return false
165
- ent[1] == 'yes/no'
166
- end
167
-
168
- def ConfigTable.value_config?( name )
169
- ent = get_entry(name) or return false
170
- ent[1] != 'yes/no'
171
- end
172
-
173
- def ConfigTable.path_config?( name )
174
- ent = get_entry(name) or return false
175
- ent[1] == 'path'
176
- end
177
-
178
-
179
- class << self
180
-
181
- alias newobj new
182
-
183
- def new
184
- c = newobj()
185
- c.__send__ :init
186
- c
187
- end
188
-
189
- def load
190
- c = newobj()
191
- raise InstallError, "#{File.basename $0} config first"\
192
- unless File.file? SAVE_FILE
193
- File.foreach(SAVE_FILE) do |line|
194
- k, v = line.split(/=/, 2)
195
- c.instance_eval {
196
- @table[k] = v.strip
197
- }
198
- end
199
- c
200
- end
201
-
202
- end
203
-
204
- def initialize
205
- @table = {}
206
- end
207
-
208
- def init
209
- DESCRIPTER.each do |k, (default, vname, desc, default2)|
210
- @table[k] = default
211
- end
212
- end
213
- private :init
214
-
215
- def save
216
- File.open(SAVE_FILE, 'w') {|f|
217
- @table.each do |k, v|
218
- f.printf "%s=%s\n", k, v if v
219
- end
220
- }
221
- end
222
-
223
- def []=( k, v )
224
- ConfigTable.config_key? k or raise InstallError, "unknown config option #{k}"
225
- if ConfigTable.path_config? k
226
- @table[k] = (v[0,1] != '$') ? File.expand_path(v) : v
227
- else
228
- @table[k] = v
229
- end
230
- end
231
-
232
- def []( key )
233
- @table[key] or return nil
234
- @table[key].gsub(%r<\$([^/]+)>) { self[$1] }
235
- end
236
-
237
- def set_raw( key, val )
238
- @table[key] = val
239
- end
240
-
241
- def get_raw( key )
242
- @table[key]
243
- end
244
-
245
- end
246
-
247
-
248
- class MetaConfigEnvironment
249
-
250
- def self.eval_file( file )
251
- return unless File.file? file
252
- new.instance_eval File.read_all(file), file, 1
253
- end
254
-
255
- private
256
-
257
- def config_names
258
- ConfigTable.keys
259
- end
260
-
261
- def config?( name )
262
- ConfigTable.config_key? name
263
- end
264
-
265
- def bool_config?( name )
266
- ConfigTable.bool_config? name
267
- end
268
-
269
- def value_config?( name )
270
- ConfigTable.value_config? name
271
- end
272
-
273
- def path_config?( name )
274
- ConfigTable.path_config? name
275
- end
276
-
277
- def add_config( name, argname, default, desc )
278
- ConfigTable.add_entry name,[default,argname,desc]
279
- end
280
-
281
- def add_path_config( name, default, desc )
282
- add_config name, 'path', default, desc
283
- end
284
-
285
- def add_bool_config( name, default, desc )
286
- add_config name, 'yes/no', default ? 'yes' : 'no', desc
287
- end
288
-
289
- def set_config_default( name, default )
290
- if bool_config? name
291
- ConfigTable.get_entry!(name)[0] = default ? 'yes' : 'no'
292
- else
293
- ConfigTable.get_entry!(name)[0] = default
294
- end
295
- end
296
-
297
- def remove_config( name )
298
- ent = ConfigTable.get_entry(name)
299
- ConfigTable.remove_entry name
300
- ent
301
- end
302
-
303
- end
304
-
305
- ### end config.rb
306
- ### begin fileop.rb
307
-
308
- module FileOperations
309
-
310
- def mkdir_p( dname, prefix = nil )
311
- dname = prefix + dname if prefix
312
- $stderr.puts "mkdir -p #{dname}" if verbose?
313
- return if no_harm?
314
-
315
- # does not check '/'... it's too abnormal case
316
- dirs = dname.split(%r<(?=/)>)
317
- if /\A[a-z]:\z/i === dirs[0]
318
- disk = dirs.shift
319
- dirs[0] = disk + dirs[0]
320
- end
321
- dirs.each_index do |idx|
322
- path = dirs[0..idx].join('')
323
- Dir.mkdir path unless dir? path
324
- end
325
- end
326
-
327
- def rm_f( fname )
328
- $stderr.puts "rm -f #{fname}" if verbose?
329
- return if no_harm?
330
-
331
- if File.exist? fname or File.symlink? fname
332
- File.chmod 0777, fname
333
- File.unlink fname
334
- end
335
- end
336
-
337
- def rm_rf( dn )
338
- $stderr.puts "rm -rf #{dn}" if verbose?
339
- return if no_harm?
340
-
341
- Dir.chdir dn
342
- Dir.foreach('.') do |fn|
343
- next if fn == '.'
344
- next if fn == '..'
345
- if dir? fn
346
- verbose_off {
347
- rm_rf fn
348
- }
349
- else
350
- verbose_off {
351
- rm_f fn
352
- }
353
- end
354
- end
355
- Dir.chdir '..'
356
- Dir.rmdir dn
357
- end
358
-
359
- def mv( src, dest )
360
- rm_f dest
361
- begin
362
- File.link src, dest
363
- rescue
364
- File.write dest, File.read_all(src)
365
- File.chmod File.stat(src).mode, dest
366
- end
367
- rm_f src
368
- end
369
-
370
- def install( from, dest, mode, prefix = nil )
371
- $stderr.puts "install #{from} #{dest}" if verbose?
372
- return if no_harm?
373
-
374
- realdest = prefix + dest if prefix
375
- if dir? realdest
376
- realdest += '/' + File.basename(from)
377
- end
378
- str = File.read_all(from)
379
- if diff? str, realdest
380
- verbose_off {
381
- rm_f realdest if File.exist? realdest
382
- }
383
- File.write realdest, str
384
- File.chmod mode, realdest
385
-
386
- File.open(objdir + '/InstalledFiles', 'a') {|f| f.puts realdest }
387
- end
388
- end
389
-
390
- def diff?( orig, targ )
391
- return true unless File.exist? targ
392
- orig != File.read_all(targ)
393
- end
394
-
395
- def command( str )
396
- $stderr.puts str if verbose?
397
- system str or raise RuntimeError, "'system #{str}' failed"
398
- end
399
-
400
- def ruby( str )
401
- command config('ruby-prog') + ' ' + str
402
- end
403
-
404
- def dir?( dname )
405
- # for corrupted windows stat()
406
- File.directory?((dname[-1,1] == '/') ? dname : dname + '/')
407
- end
408
-
409
- def all_files( dname )
410
- Dir.open(dname) {|d|
411
- return d.find_all {|n| File.file? "#{dname}/#{n}" }
412
- }
413
- end
414
-
415
- def all_dirs( dname )
416
- Dir.open(dname) {|d|
417
- return d.find_all {|n| dir? "#{dname}/#{n}" } - %w(. ..)
418
- }
419
- end
420
-
421
- end
422
-
423
- ### end fileop.rb
424
- ### begin base.rb
425
-
426
- class InstallError < StandardError; end
427
-
428
-
429
- class Installer
430
-
431
- Version = '3.1.3'
432
- Copyright = 'Copyright (c) 2000-2002 Minero Aoki'
433
-
434
-
435
- @toplevel = nil
436
-
437
- def self.declear_toplevel_installer( inst )
438
- @toplevel and
439
- raise ArgumentError, 'more than one toplevel installer decleared'
440
- @toplevel = inst
441
- end
442
-
443
- def self.toplevel_installer
444
- @toplevel
445
- end
446
-
447
-
448
- FILETYPES = %w( bin lib ext data )
449
-
450
- include FileOperations
451
-
452
- def initialize( config, opt, srcroot, objroot )
453
- @config = config
454
- @options = opt
455
- @srcdir = File.expand_path(srcroot)
456
- @objdir = File.expand_path(objroot)
457
- @currdir = '.'
458
- end
459
-
460
- def inspect
461
- "#<#{self.class} #{__id__}>"
462
- end
463
-
464
- #
465
- # configs/options
466
- #
467
-
468
- def get_config( key )
469
- @config[key]
470
- end
471
-
472
- alias config get_config
473
-
474
- def set_config( key, val )
475
- @config[key] = val
476
- end
477
-
478
- def no_harm?
479
- @options['no-harm']
480
- end
481
-
482
- def verbose?
483
- @options['verbose']
484
- end
485
-
486
- def verbose_off
487
- save, @options['verbose'] = @options['verbose'], false
488
- yield
489
- @options['verbose'] = save
490
- end
491
-
492
- #
493
- # srcdir/objdir
494
- #
495
-
496
- attr_reader :srcdir
497
- alias srcdir_root srcdir
498
- alias package_root srcdir
499
-
500
- def curr_srcdir
501
- "#{@srcdir}/#{@currdir}"
502
- end
503
-
504
- attr_reader :objdir
505
- alias objdir_root objdir
506
-
507
- def curr_objdir
508
- "#{@objdir}/#{@currdir}"
509
- end
510
-
511
- def srcfile( path )
512
- curr_srcdir + '/' + path
513
- end
514
-
515
- def srcexist?( path )
516
- File.exist? srcfile(path)
517
- end
518
-
519
- def srcdirectory?( path )
520
- dir? srcfile(path)
521
- end
522
-
523
- def srcfile?( path )
524
- File.file? srcfile(path)
525
- end
526
-
527
- def srcentries( path = '.' )
528
- Dir.open(curr_srcdir + '/' + path) {|d|
529
- return d.to_a - %w(. ..) - hookfilenames
530
- }
531
- end
532
-
533
- def srcfiles( path = '.' )
534
- srcentries(path).find_all {|fname|
535
- File.file? File.join(curr_srcdir, path, fname)
536
- }
537
- end
538
-
539
- def srcdirectories( path = '.' )
540
- srcentries(path).find_all {|fname|
541
- dir? File.join(curr_srcdir, path, fname)
542
- }
543
- end
544
-
545
- def dive_into( rel )
546
- return unless dir? "#{@srcdir}/#{rel}"
547
-
548
- dir = File.basename(rel)
549
- Dir.mkdir dir unless dir? dir
550
- save = Dir.pwd
551
- Dir.chdir dir
552
- $stderr.puts '---> ' + rel if verbose?
553
- @currdir = rel
554
- yield
555
- Dir.chdir save
556
- $stderr.puts '<--- ' + rel if verbose?
557
- @currdir = File.dirname(rel)
558
- end
559
-
560
- #
561
- # config
562
- #
563
-
564
- def exec_config
565
- exec_task_traverse 'config'
566
- end
567
-
568
- def config_dir_bin( rel )
569
- end
570
-
571
- def config_dir_lib( rel )
572
- end
573
-
574
- def config_dir_ext( rel )
575
- extconf if extdir? curr_srcdir
576
- end
577
-
578
- def extconf
579
- opt = @options['config-opt'].join(' ')
580
- command "#{config('ruby-prog')} #{curr_srcdir}/extconf.rb #{opt}"
581
- end
582
-
583
- def config_dir_data( rel )
584
- end
585
-
586
- #
587
- # setup
588
- #
589
-
590
- def exec_setup
591
- exec_task_traverse 'setup'
592
- end
593
-
594
- def setup_dir_bin( relpath )
595
- all_files(curr_srcdir).each do |fname|
596
- add_rubypath "#{curr_srcdir}/#{fname}"
597
- end
598
- end
599
-
600
- SHEBANG_RE = /\A\#!\s*\S*ruby\S*/
601
-
602
- def add_rubypath( path )
603
- $stderr.puts %Q<set #! line to "\#!#{config('ruby-path')}" for #{path} ...> if verbose?
604
- return if no_harm?
605
-
606
- tmpfile = File.basename(path) + '.tmp'
607
- begin
608
- File.open(path) {|r|
609
- File.open(tmpfile, 'w') {|w|
610
- first = r.gets
611
- return unless SHEBANG_RE === first # reject '/usr/bin/env ruby'
612
-
613
- w.print first.sub(SHEBANG_RE, '#!' + config('ruby-path'))
614
- w.write r.read
615
- } }
616
- mv tmpfile, File.basename(path)
617
- ensure
618
- rm_f tmpfile if File.exist? tmpfile
619
- end
620
- end
621
-
622
- def setup_dir_lib( relpath )
623
- end
624
-
625
- def setup_dir_ext( relpath )
626
- make if extdir?(curr_srcdir)
627
- end
628
-
629
- def make
630
- command config('make-prog')
631
- end
632
-
633
- def setup_dir_data( relpath )
634
- end
635
-
636
- #
637
- # install
638
- #
639
-
640
- def exec_install
641
- exec_task_traverse 'install'
642
- end
643
-
644
- def install_dir_bin( rel )
645
- install_files targfiles, config('bin-dir') + '/' + rel, 0755
646
- end
647
-
648
- def install_dir_lib( rel )
649
- install_files targfiles, config('rb-dir') + '/' + rel, 0644
650
- end
651
-
652
- def install_dir_ext( rel )
653
- install_dir_ext_main File.dirname(rel) if extdir?(curr_srcdir)
654
- end
655
-
656
- def install_dir_ext_main( rel )
657
- install_files allext('.'), config('so-dir') + '/' + rel, 0555
658
- end
659
-
660
- def install_dir_data( rel )
661
- install_files targfiles, config('data-dir') + '/' + rel, 0644
662
- end
663
-
664
- def install_files( list, dest, mode )
665
- mkdir_p dest, @options['install-prefix']
666
- list.each do |fname|
667
- install fname, dest, mode, @options['install-prefix']
668
- end
669
- end
670
-
671
- def targfiles
672
- (targfilenames() - hookfilenames()).collect {|fname|
673
- File.exist?(fname) ? fname : File.join(curr_srcdir(), fname)
674
- }
675
- end
676
-
677
- def targfilenames
678
- [ curr_srcdir(), '.' ].inject([]) {|ret, dir|
679
- ret | all_files(dir)
680
- }
681
- end
682
-
683
- def hookfilenames
684
- %w( pre-%s post-%s pre-%s.rb post-%s.rb ).collect {|fmt|
685
- %w( config setup install clean ).collect {|t| sprintf fmt, t }
686
- }.flatten
687
- end
688
-
689
- def allext( dir )
690
- _allext(dir) or raise InstallError,
691
- "no extention exists: Have you done 'ruby #{$0} setup' ?"
692
- end
693
-
694
- DLEXT = /\.#{ ::Config::CONFIG['DLEXT'] }\z/
695
-
696
- def _allext( dir )
697
- Dir.open(dir) {|d|
698
- return d.find_all {|fname| DLEXT === fname }
699
- }
700
- end
701
-
702
- #
703
- # clean
704
- #
705
-
706
- def exec_clean
707
- exec_task_traverse 'clean'
708
- rm_f 'config.save'
709
- rm_f 'InstalledFiles'
710
- end
711
-
712
- def clean_dir_bin( rel )
713
- end
714
-
715
- def clean_dir_lib( rel )
716
- end
717
-
718
- def clean_dir_ext( rel )
719
- clean
720
- end
721
-
722
- def clean
723
- command config('make-prog') + ' clean' if File.file? 'Makefile'
724
- end
725
-
726
- def clean_dir_data( rel )
727
- end
728
-
729
- #
730
- # lib
731
- #
732
-
733
- def exec_task_traverse( task )
734
- run_hook 'pre-' + task
735
- FILETYPES.each do |type|
736
- if config('without-ext') == 'yes' and type == 'ext'
737
- $stderr.puts 'skipping ext/* by user option' if verbose?
738
- next
739
- end
740
- traverse task, type, task + '_dir_' + type
741
- end
742
- run_hook 'post-' + task
743
- end
744
-
745
- def traverse( task, rel, mid )
746
- dive_into(rel) {
747
- run_hook 'pre-' + task
748
- __send__ mid, rel.sub(%r_\A.*?(?:/|\z)_, '')
749
- all_dirs(curr_srcdir).each do |d|
750
- traverse task, rel + '/' + d, mid
751
- end
752
- run_hook 'post-' + task
753
- }
754
- end
755
-
756
- def run_hook( name )
757
- try_run_hook curr_srcdir + '/' + name or
758
- try_run_hook curr_srcdir + '/' + name + '.rb'
759
- end
760
-
761
- def try_run_hook( fname )
762
- return false unless File.file? fname
763
-
764
- env = self.dup
765
- begin
766
- env.instance_eval File.read_all(fname), fname, 1
767
- rescue
768
- raise InstallError, "hook #{fname} failed:\n" + $!.message
769
- end
770
- true
771
- end
772
-
773
- def extdir?( dir )
774
- File.exist? dir + '/MANIFEST'
775
- end
776
-
777
- end
778
-
779
- ### end base.rb
780
- ### begin toplevel.rb
781
-
782
- class ToplevelInstaller < Installer
783
-
784
- TASKS = [
785
- [ 'config', 'saves your configurations' ],
786
- [ 'show', 'shows current configuration' ],
787
- [ 'setup', 'compiles extention or else' ],
788
- [ 'install', 'installs files' ],
789
- [ 'clean', "does `make clean' for each extention" ]
790
- ]
791
-
792
-
793
- def initialize( root )
794
- super nil, {'verbose' => true}, root, '.'
795
- Installer.declear_toplevel_installer self
796
- end
797
-
798
-
799
- def execute
800
- run_metaconfigs
801
-
802
- case task = parsearg_global()
803
- when 'config'
804
- @config = ConfigTable.new
805
- else
806
- @config = ConfigTable.load
807
- end
808
- parsearg_TASK task
809
-
810
- exectask task
811
- end
812
-
813
-
814
- def run_metaconfigs
815
- MetaConfigEnvironment.eval_file "#{srcdir_root()}/#{metaconfig()}"
816
- end
817
-
818
- def metaconfig
819
- 'metaconfig'
820
- end
821
-
822
-
823
- def exectask( task )
824
- if task == 'show'
825
- exec_show
826
- else
827
- try task
828
- end
829
- end
830
-
831
- def try( task )
832
- $stderr.printf "#{File.basename $0}: entering %s phase...\n", task if verbose?
833
- begin
834
- __send__ 'exec_' + task
835
- rescue
836
- $stderr.printf "%s failed\n", task
837
- raise
838
- end
839
- $stderr.printf "#{File.basename $0}: %s done.\n", task if verbose?
840
- end
841
-
842
- #
843
- # processing arguments
844
- #
845
-
846
- def parsearg_global
847
- task_re = /\A(?:#{TASKS.collect {|i| i[0] }.join '|'})\z/
848
-
849
- while arg = ARGV.shift
850
- case arg
851
- when /\A\w+\z/
852
- task_re === arg or raise InstallError, "wrong task: #{arg}"
853
- return arg
854
-
855
- when '-q', '--quiet'
856
- @options['verbose'] = false
857
-
858
- when '--verbose'
859
- @options['verbose'] = true
860
-
861
- when '-h', '--help'
862
- print_usage $stdout
863
- exit 0
864
-
865
- when '-v', '--version'
866
- puts "#{File.basename $0} version #{Version}"
867
- exit 0
868
-
869
- when '--copyright'
870
- puts Copyright
871
- exit 0
872
-
873
- else
874
- raise InstallError, "unknown global option '#{arg}'"
875
- end
876
- end
877
-
878
- raise InstallError, "No task or global option given.
879
- Typical installation procedure is:
880
- $ ruby #{File.basename $0} config
881
- $ ruby #{File.basename $0} setup
882
- # ruby #{File.basename $0} install (may require root privilege)
883
- "
884
- end
885
-
886
-
887
- def parsearg_TASK( task )
888
- mid = "parsearg_#{task}"
889
- if respond_to? mid, true
890
- __send__ mid
891
- else
892
- ARGV.empty? or
893
- raise InstallError, "#{task}: unknown options: #{ARGV.join ' '}"
894
- end
895
- end
896
-
897
- def parsearg_config
898
- re = /\A--(#{ConfigTable.keys.join '|'})(?:=(.*))?\z/
899
- @options['config-opt'] = []
900
-
901
- while i = ARGV.shift
902
- if /\A--?\z/ === i
903
- @options['config-opt'] = ARGV.dup
904
- break
905
- end
906
- m = re.match(i) or raise InstallError, "config: unknown option #{i}"
907
- name, value = m.to_a[1,2]
908
- if value
909
- if ConfigTable.bool_config?(name)
910
- /\A(y(es)?|n(o)?|t(rue)?|f(alse))\z/i === value or raise InstallError, "config: --#{name} allows only yes/no for argument"
911
- value = (/\Ay(es)?|\At(rue)/i === value) ? 'yes' : 'no'
912
- end
913
- else
914
- ConfigTable.bool_config?(name) or raise InstallError, "config: --#{name} requires argument"
915
- value = 'yes'
916
- end
917
- @config[name] = value
918
- end
919
- end
920
-
921
- def parsearg_install
922
- @options['no-harm'] = false
923
- @options['install-prefix'] = ''
924
- while a = ARGV.shift
925
- case a
926
- when /\A--no-harm\z/
927
- @options['no-harm'] = true
928
- when /\A--prefix=(.*)\z/
929
- path = $1
930
- path = File.expand_path(path) unless path[0,1] == '/'
931
- @options['install-prefix'] = path
932
- else
933
- raise InstallError, "install: unknown option #{a}"
934
- end
935
- end
936
- end
937
-
938
-
939
- def print_usage( out )
940
- out.puts 'Typical Installation Procedure:'
941
- out.puts " $ ruby #{File.basename $0} config"
942
- out.puts " $ ruby #{File.basename $0} setup"
943
- out.puts " # ruby #{File.basename $0} install (may require root privilege)"
944
- out.puts
945
- out.puts 'Detailed Usage:'
946
- out.puts " ruby #{File.basename $0} <global option>"
947
- out.puts " ruby #{File.basename $0} [<global options>] <task> [<task options>]"
948
-
949
- fmt = " %-20s %s\n"
950
- out.puts
951
- out.puts 'Global options:'
952
- out.printf fmt, '-q,--quiet', 'suppress message outputs'
953
- out.printf fmt, ' --verbose', 'output messages verbosely'
954
- out.printf fmt, '-h,--help', 'print this message'
955
- out.printf fmt, '-v,--version', 'print version and quit'
956
- out.printf fmt, ' --copyright', 'print copyright and quit'
957
-
958
- out.puts
959
- out.puts 'Tasks:'
960
- TASKS.each do |name, desc|
961
- out.printf " %-10s %s\n", name, desc
962
- end
963
-
964
- out.puts
965
- out.puts 'Options for config:'
966
- ConfigTable.each_definition do |name, (default, arg, desc, default2)|
967
- out.printf " %-20s %s [%s]\n",
968
- '--'+ name + (ConfigTable.bool_config?(name) ? '' : '='+arg),
969
- desc,
970
- default2 || default
971
- end
972
- out.printf " %-20s %s [%s]\n",
973
- '--rbconfig=path', 'your rbconfig.rb to load', "running ruby's"
974
-
975
- out.puts
976
- out.puts 'Options for install:'
977
- out.printf " %-20s %s [%s]\n",
978
- '--no-harm', 'only display what to do if given', 'off'
979
- out.printf " %-20s %s [%s]\n",
980
- '--prefix', 'install path prefix', '$prefix'
981
-
982
- out.puts
983
- end
984
-
985
- #
986
- # config
987
- #
988
-
989
- def exec_config
990
- super
991
- @config.save
992
- end
993
-
994
- #
995
- # show
996
- #
997
-
998
- def exec_show
999
- ConfigTable.each_name do |k|
1000
- v = @config.get_raw(k)
1001
- if not v or v.empty?
1002
- v = '(not specified)'
1003
- end
1004
- printf "%-10s %s\n", k, v
1005
- end
1006
- end
1007
-
1008
- end
1009
-
1010
- ### end toplevel.rb
1011
-
1012
- if $0 == __FILE__
1013
- begin
1014
- installer = ToplevelInstaller.new(File.dirname($0))
1015
- installer.execute
1016
- rescue
1017
- raise if $DEBUG
1018
- $stderr.puts $!.message
1019
- $stderr.puts "Try 'ruby #{$0} --help' for detailed usage."
1020
- exit 1
1021
- end
1022
- end