imp3 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +23 -0
- data/LICENSE +20 -0
- data/README.rdoc +129 -0
- data/Rakefile +55 -0
- data/VERSION +1 -0
- data/bin/imp3 +63 -0
- data/lib/imp3/cli.rb +208 -0
- data/lib/imp3.rb +5 -0
- data/test/helper.rb +11 -0
- data/test/test_normalization.rb +16 -0
- metadata +116 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Víctor Martínez
|
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
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
== DESCRIPTION
|
2
|
+
|
3
|
+
iMp3 is an application for batch processing and fixing common issues when dealing with a large iTunes library
|
4
|
+
|
5
|
+
== REQUIREMENTS
|
6
|
+
|
7
|
+
* Mac OS X 10.6
|
8
|
+
* iTunes 9
|
9
|
+
|
10
|
+
== INSTALL
|
11
|
+
|
12
|
+
sudo gem install imp3
|
13
|
+
|
14
|
+
== SYNOPSIS
|
15
|
+
|
16
|
+
Application for batch processing and fixing common issues when dealing with a large iTunes library
|
17
|
+
|
18
|
+
Commands:
|
19
|
+
fix genres Tags all tracks genres using last.fm
|
20
|
+
fix misspelled-artists Fixes misspelled artist names
|
21
|
+
help Display global or [command] help documentation.
|
22
|
+
stats genres Lists all genres tagged in iTunes
|
23
|
+
|
24
|
+
Global Options:
|
25
|
+
-h, --help Display help documentation
|
26
|
+
-v, --version Display version information
|
27
|
+
-t, --trace Display backtrace when an error occurs
|
28
|
+
|
29
|
+
== FEATURES
|
30
|
+
|
31
|
+
$ imp3 genres fetch
|
32
|
+
53% |=============............| Tagging track 911DA9F96A9D7003 with genre 'sludge'
|
33
|
+
|
34
|
+
$ imp3 artists misspelled
|
35
|
+
Misspelled artist name scan complete.
|
36
|
+
|
37
|
+
What is the correct artist name for L'Antietam
|
38
|
+
1. L'Antietam
|
39
|
+
2. L'antietam
|
40
|
+
3. (Skip)
|
41
|
+
? 1
|
42
|
+
Tagging track 851744AFF27C75D1 with artist name 'L'Antietam'
|
43
|
+
|
44
|
+
177 artists.
|
45
|
+
1479 tracks.
|
46
|
+
1 tracks tagged.
|
47
|
+
0 requests.
|
48
|
+
0 errors.
|
49
|
+
|
50
|
+
$ imp3 genres ignore-add singer-songwriter
|
51
|
+
Genre 'singer-songwriter' added to ignore list
|
52
|
+
|
53
|
+
$ imp3 genres ignore-list
|
54
|
+
+-------------------+
|
55
|
+
| Genre |
|
56
|
+
+-------------------+
|
57
|
+
| singer-songwriter |
|
58
|
+
| polish |
|
59
|
+
| swedish |
|
60
|
+
+-------------------+
|
61
|
+
|
62
|
+
$ imp3 genres list
|
63
|
+
+-------------------+--------+
|
64
|
+
| Genre | Tracks |
|
65
|
+
+-------------------+--------+
|
66
|
+
| screamo | 398 |
|
67
|
+
| post-rock | 252 |
|
68
|
+
| hardcore | 116 |
|
69
|
+
| post-hardcore | 81 |
|
70
|
+
| sludge | 72 |
|
71
|
+
| indie | 67 |
|
72
|
+
| rock | 58 |
|
73
|
+
| math-rock | 44 |
|
74
|
+
| thrashcore | 38 |
|
75
|
+
| emo | 36 |
|
76
|
+
| electronic | 33 |
|
77
|
+
| crust | 32 |
|
78
|
+
| mathcore | 29 |
|
79
|
+
| post-metal | 26 |
|
80
|
+
| metalcore | 23 |
|
81
|
+
| punk | 21 |
|
82
|
+
| grindcore | 21 |
|
83
|
+
| crustcore | 15 |
|
84
|
+
| ska | 11 |
|
85
|
+
| indie-rock | 11 |
|
86
|
+
| deathcore | 10 |
|
87
|
+
| black-metal | 9 |
|
88
|
+
| experimental | 8 |
|
89
|
+
| ambient | 7 |
|
90
|
+
| emo-violence | 6 |
|
91
|
+
| death-metal | 5 |
|
92
|
+
| pop-punk | 5 |
|
93
|
+
| swedish | 3 |
|
94
|
+
| psychedelic | 3 |
|
95
|
+
| pop | 2 |
|
96
|
+
| polish | 2 |
|
97
|
+
| punk-rock | 1 |
|
98
|
+
| acoustic | 1 |
|
99
|
+
| post-punk | 1 |
|
100
|
+
+-------------------+--------+
|
101
|
+
|
102
|
+
== TODO
|
103
|
+
|
104
|
+
* Issue solver: Misspelled album names
|
105
|
+
* Issue solver: Lower-cased track names
|
106
|
+
* Issue solver: Same artist, different genre
|
107
|
+
* Issue solver: Fetch missing album art using images.google.com
|
108
|
+
* Issue solver: Duplicate tracks
|
109
|
+
* Issue solver: Remove sort artist (I personally hate this feature)
|
110
|
+
* Switch to only process current iTunes selection
|
111
|
+
* Switch to skip/force already processed tracks
|
112
|
+
* Cache last.fm requests
|
113
|
+
* Windows support through Win32OLE
|
114
|
+
* (your feature request here)
|
115
|
+
* ...
|
116
|
+
|
117
|
+
== Note on Patches/Pull Requests
|
118
|
+
|
119
|
+
* Fork the project.
|
120
|
+
* Make your feature addition or bug fix.
|
121
|
+
* Add tests for it. This is important so I don't break it in a
|
122
|
+
future version unintentionally.
|
123
|
+
* Commit, do not mess with rakefile, version, or history.
|
124
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
125
|
+
* Send me a pull request. Bonus points for topic branches.
|
126
|
+
|
127
|
+
== LICENSE
|
128
|
+
|
129
|
+
Copyright (c) 2010 Víctor Martínez. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'lib/imp3'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'jeweler'
|
7
|
+
Jeweler::Tasks.new do |gem|
|
8
|
+
gem.name = "imp3"
|
9
|
+
gem.summary = %Q{Application for batch processing and fixing common issues when dealing with a large iTunes library}
|
10
|
+
gem.description = %Q{An application for batch processing and fixing common issues when dealing with a large iTunes library}
|
11
|
+
gem.email = "knoopx@gmail.com"
|
12
|
+
gem.homepage = "http://github.com/knoopx/imp3"
|
13
|
+
gem.authors = ["Víctor Martínez"]
|
14
|
+
gem.add_dependency('commander', '~> 4.0.2')
|
15
|
+
gem.add_dependency('terminal-table', '~> 1.4.2')
|
16
|
+
gem.add_dependency('nokogiri', '~> 1.4.1')
|
17
|
+
gem.add_dependency('pbosetti-rubyosa', '~> 0.5.3')
|
18
|
+
gem.add_dependency('friendly_id', '~> 2.3.3')
|
19
|
+
end
|
20
|
+
Jeweler::GemcutterTasks.new
|
21
|
+
rescue LoadError
|
22
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
23
|
+
end
|
24
|
+
|
25
|
+
require 'rake/testtask'
|
26
|
+
Rake::TestTask.new(:test) do |test|
|
27
|
+
test.libs << 'lib' << 'test'
|
28
|
+
test.pattern = 'test/**/test_*.rb'
|
29
|
+
test.verbose = false
|
30
|
+
end
|
31
|
+
|
32
|
+
begin
|
33
|
+
require 'rcov/rcovtask'
|
34
|
+
Rcov::RcovTask.new do |test|
|
35
|
+
test.libs << 'test'
|
36
|
+
test.pattern = 'test/**/test_*.rb'
|
37
|
+
test.verbose = true
|
38
|
+
end
|
39
|
+
rescue LoadError
|
40
|
+
task :rcov do
|
41
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
task :test => :check_dependencies
|
46
|
+
|
47
|
+
task :default => :test
|
48
|
+
|
49
|
+
require 'rake/rdoctask'
|
50
|
+
Rake::RDocTask.new do |rdoc|
|
51
|
+
rdoc.rdoc_dir = 'rdoc'
|
52
|
+
rdoc.title = "imp3 #{IMP3::VERSION}"
|
53
|
+
rdoc.rdoc_files.include('README.rdoc')
|
54
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
55
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.1
|
data/bin/imp3
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
4
|
+
$LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')))
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require "lib/imp3"
|
8
|
+
require 'commander/import'
|
9
|
+
|
10
|
+
program :name, 'imp3'
|
11
|
+
program :version, IMP3::VERSION
|
12
|
+
program :description, 'Application for batch processing and fixing common issues when dealing with a large iTunes library'
|
13
|
+
program :help_formatter, :compact
|
14
|
+
|
15
|
+
default_command :help
|
16
|
+
|
17
|
+
command "genres list" do |c|
|
18
|
+
c.syntax = 'genres list'
|
19
|
+
c.description = 'Lists all genres tagged in iTunes'
|
20
|
+
c.when_called do |args, options|
|
21
|
+
IMP3::CLI.new.genres_list
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
command "genres fetch" do |c|
|
26
|
+
c.syntax = 'genres fetch'
|
27
|
+
c.description = 'Fetch and tag track genres from last.fm top tag'
|
28
|
+
c.when_called do |args, options|
|
29
|
+
IMP3::CLI.new.genres_tag
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
command "genres ignore-add" do |c|
|
34
|
+
c.syntax = 'genres ignore-add GENRE'
|
35
|
+
c.description = 'Ignore specified genre so is no longer used and the next one is taken for tagging tracks'
|
36
|
+
c.when_called do |args, options|
|
37
|
+
IMP3::CLI.new.genres_ignore_add(args.first)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
command "genres ignore-del" do |c|
|
42
|
+
c.syntax = 'genres ignore-del GENRE'
|
43
|
+
c.description = 'Ignore specified genre so is no longer used and the next one is taken for tagging tracks'
|
44
|
+
c.when_called do |args, options|
|
45
|
+
IMP3::CLI.new.genres_ignore_del(args.first)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
command "genres ignore-list" do |c|
|
50
|
+
c.syntax = 'genres ignore-list'
|
51
|
+
c.description = 'Lists all ignored genres'
|
52
|
+
c.when_called do |args, options|
|
53
|
+
IMP3::CLI.new.genres_ignore_list
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
command "artists misspelled" do |c|
|
58
|
+
c.syntax = 'artists misspelled'
|
59
|
+
c.description = 'Fix misspelled artist names'
|
60
|
+
c.when_called do |args, options|
|
61
|
+
IMP3::CLI.new.artists_misspelled
|
62
|
+
end
|
63
|
+
end
|
data/lib/imp3/cli.rb
ADDED
@@ -0,0 +1,208 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
require 'open-uri'
|
3
|
+
require 'nokogiri'
|
4
|
+
require 'terminal-table/import'
|
5
|
+
require 'active_support'
|
6
|
+
require 'friendly_id/slug_string'
|
7
|
+
require 'rbosa'
|
8
|
+
require 'pp'
|
9
|
+
require 'commander/user_interaction'
|
10
|
+
|
11
|
+
OSA.utf8_strings = true
|
12
|
+
|
13
|
+
class IMP3::CLI
|
14
|
+
CONFIG_FILE = File.expand_path(File.join("~", ".imp3"))
|
15
|
+
|
16
|
+
def genres_tag
|
17
|
+
artist_genres = {}
|
18
|
+
tagged, requests, errors = 0, 0, 0
|
19
|
+
|
20
|
+
progress_bar tracks do |track, bar|
|
21
|
+
normalized_artist_name = track.artist.normalize
|
22
|
+
|
23
|
+
begin
|
24
|
+
unless artist_genres.has_key?(normalized_artist_name)
|
25
|
+
requests += 1
|
26
|
+
bar.refresh(:title => "Quering last.fm for '#{track.artist}'")
|
27
|
+
tags = Nokogiri(open("http://ws.audioscrobbler.com/1.0/artist/#{URI.escape(CGI.escape(track.artist))}/toptags.xml")).search("//toptags/tag/name").map{|t| t.text.normalize }.uniq
|
28
|
+
tags = tags - config[:ignore_genres] if config[:ignore_genres]
|
29
|
+
artist_genres[normalized_artist_name] = tags.first
|
30
|
+
end
|
31
|
+
rescue => e
|
32
|
+
errors += 1
|
33
|
+
bar.refresh(:title => e)
|
34
|
+
artist_genres[normalized_artist_name] = nil
|
35
|
+
end
|
36
|
+
|
37
|
+
if (artist_genres.has_key?(normalized_artist_name) and not artist_genres[normalized_artist_name].nil?)
|
38
|
+
tagged += 1
|
39
|
+
bar.increment(:title => "Tagging track #{track.persistent_id} with genre '#{artist_genres[normalized_artist_name]}'")
|
40
|
+
track.genre = ""
|
41
|
+
track.genre = artist_genres[normalized_artist_name]
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
summary(:tracks_tagged => tagged, :requests => requests, :errors => errors)
|
46
|
+
end
|
47
|
+
|
48
|
+
def genres_list
|
49
|
+
genres = {}
|
50
|
+
tracks.each do |track|
|
51
|
+
genres[track.genre] ||= 0
|
52
|
+
genres[track.genre] += 1
|
53
|
+
end
|
54
|
+
|
55
|
+
genre_table = table do |t|
|
56
|
+
t.headings = 'Genre', 'Tracks'
|
57
|
+
genres.sort{|a, b| b[1] <=> a[1]}.each do |g, c|
|
58
|
+
t << [g, c]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
puts genre_table
|
63
|
+
summary
|
64
|
+
end
|
65
|
+
|
66
|
+
def genres_ignore_add(genre)
|
67
|
+
raise "Please specify a genre" unless genre
|
68
|
+
genre.strip!
|
69
|
+
config[:ignore_genres] ||= []
|
70
|
+
config[:ignore_genres] << genre unless config[:ignore_genres].include?(genre)
|
71
|
+
save_config
|
72
|
+
puts "Genre '#{genre}' added to ignore list"
|
73
|
+
end
|
74
|
+
|
75
|
+
def genres_ignore_del(genre)
|
76
|
+
raise "Please specify a genre" unless genre
|
77
|
+
genre.strip!
|
78
|
+
config[:ignore_genres].delete(genre) if config[:ignore_genres].include?(genre)
|
79
|
+
save_config
|
80
|
+
puts "Genre '#{genre}' deleted from ignore list"
|
81
|
+
end
|
82
|
+
|
83
|
+
def genres_ignore_list
|
84
|
+
if config[:ignore_genres].any?
|
85
|
+
genre_table = table do |t|
|
86
|
+
t.headings = 'Genre'
|
87
|
+
config[:ignore_genres].each do |g|
|
88
|
+
t << [g]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
puts genre_table
|
92
|
+
else
|
93
|
+
puts "No ignored genres."
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def artists_misspelled
|
98
|
+
artist_choices = {}
|
99
|
+
tagged = 0
|
100
|
+
|
101
|
+
progress_bar artists, :complete_message => "Misspelled artist name scan complete." do |artist, bar|
|
102
|
+
bar.increment :title => "Scanning artist '#{artist}'"
|
103
|
+
normalized_artist_name = artist.normalized_without_words
|
104
|
+
artist_choices[normalized_artist_name] ||= []
|
105
|
+
artist_choices[normalized_artist_name] << artist.strip unless artist_choices[normalized_artist_name].include?(artist)
|
106
|
+
end
|
107
|
+
|
108
|
+
artist_names = {}
|
109
|
+
tracks.each do |track|
|
110
|
+
normalized_artist_name = track.artist.normalized_without_words
|
111
|
+
unless artist_names.has_key?(normalized_artist_name)
|
112
|
+
if artist_choices[normalized_artist_name] && artist_choices[normalized_artist_name].size > 1
|
113
|
+
puts
|
114
|
+
artist_name = choose("What is the correct artist name for #{track.artist}", *(artist_choices[normalized_artist_name] << :"(Skip)"))
|
115
|
+
artist_names[normalized_artist_name] = artist_name
|
116
|
+
else
|
117
|
+
artist_names[normalized_artist_name] = track.artist
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
unless artist_names[normalized_artist_name].eql?(:"(Skip)") or track.artist.eql?(artist_names[normalized_artist_name])
|
122
|
+
tagged += 1
|
123
|
+
puts "Tagging track #{track.persistent_id} with artist name '#{artist_names[normalized_artist_name]}'"
|
124
|
+
track.artist = ""
|
125
|
+
track.artist = artist_names[normalized_artist_name]
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
summary :tracks_tagged => tagged
|
130
|
+
end
|
131
|
+
|
132
|
+
protected
|
133
|
+
|
134
|
+
def itunes
|
135
|
+
@itunes ||= OSA.app('iTunes')
|
136
|
+
end
|
137
|
+
|
138
|
+
def library
|
139
|
+
@library ||= itunes.sources.find {|s| s.kind == OSA::ITunes::ESRC::LIBRARY }.playlists[0]
|
140
|
+
end
|
141
|
+
|
142
|
+
def tracks
|
143
|
+
@tracks ||= library.tracks
|
144
|
+
end
|
145
|
+
|
146
|
+
def artists
|
147
|
+
@artists ||= tracks.map{|t| t.artist}.uniq.sort
|
148
|
+
end
|
149
|
+
|
150
|
+
def config
|
151
|
+
return @config if @config
|
152
|
+
if File.exist?(CONFIG_FILE)
|
153
|
+
begin
|
154
|
+
@config = YAML.load_file(CONFIG_FILE)
|
155
|
+
rescue
|
156
|
+
raise "Unable to read config file #{CONFIG_FILE}"
|
157
|
+
end
|
158
|
+
else
|
159
|
+
@config = { :ignore_genres => [] }
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def save_config
|
164
|
+
File.new(CONFIG_FILE, "w+").write(config.to_yaml)
|
165
|
+
end
|
166
|
+
|
167
|
+
def summary(opts = {})
|
168
|
+
puts
|
169
|
+
puts "#{opts[:artist] || tracks.map{|t| t.artist}.uniq.size} artists."
|
170
|
+
puts "#{opts[:tracks] || tracks.size} tracks."
|
171
|
+
puts "#{opts[:tracks_tagged] || 0} tracks tagged."
|
172
|
+
puts "#{opts[:requests] || 0} requests."
|
173
|
+
puts "#{opts[:errors] || 0} errors."
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
class String
|
178
|
+
STRIP_WORDS = %w(the a of in)
|
179
|
+
|
180
|
+
def strip_meaningless_words
|
181
|
+
string = self
|
182
|
+
STRIP_WORDS.each do |w|
|
183
|
+
string = string.gsub(/\b#{w}\b/i, '')
|
184
|
+
end
|
185
|
+
string.strip
|
186
|
+
end
|
187
|
+
|
188
|
+
def normalized_without_words
|
189
|
+
self.strip_meaningless_words.normalize
|
190
|
+
end
|
191
|
+
|
192
|
+
def normalize
|
193
|
+
FriendlyId::SlugString.new(self).normalize!.approximate_ascii!.to_s
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def progress_bar arr, options = {:format => ":percent_complete% |:progress_bar| :title"}, &block
|
198
|
+
bar = ProgressBar.new arr.size, options
|
199
|
+
bar.show
|
200
|
+
arr.each { |v| yield(v, bar) }
|
201
|
+
end
|
202
|
+
|
203
|
+
class Commander::UI::ProgressBar
|
204
|
+
def refresh(tokens)
|
205
|
+
@tokens.merge! tokens if tokens.is_a? Hash
|
206
|
+
show
|
207
|
+
end
|
208
|
+
end
|
data/lib/imp3.rb
ADDED
data/test/helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestNormalization < Test::Unit::TestCase
|
4
|
+
def test_normalization
|
5
|
+
fixtures = {
|
6
|
+
"the fall of troy" => "fall-troy",
|
7
|
+
"The Fall of Troy" => "fall-troy",
|
8
|
+
"Daïtro" => "daitro",
|
9
|
+
"té" => "te"
|
10
|
+
}
|
11
|
+
|
12
|
+
fixtures.each do |string, expected|
|
13
|
+
assert_equal expected, string.normalized_without_words
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: imp3
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- "V\xC3\xADctor Mart\xC3\xADnez"
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-03-14 00:00:00 +01:00
|
13
|
+
default_executable: imp3
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: commander
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ~>
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 4.0.2
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: terminal-table
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.4.2
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: nokogiri
|
37
|
+
type: :runtime
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.4.1
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: pbosetti-rubyosa
|
47
|
+
type: :runtime
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.5.3
|
54
|
+
version:
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: friendly_id
|
57
|
+
type: :runtime
|
58
|
+
version_requirement:
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ~>
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: 2.3.3
|
64
|
+
version:
|
65
|
+
description: An application for batch processing and fixing common issues when dealing with a large iTunes library
|
66
|
+
email: knoopx@gmail.com
|
67
|
+
executables:
|
68
|
+
- imp3
|
69
|
+
extensions: []
|
70
|
+
|
71
|
+
extra_rdoc_files:
|
72
|
+
- LICENSE
|
73
|
+
- README.rdoc
|
74
|
+
files:
|
75
|
+
- .document
|
76
|
+
- .gitignore
|
77
|
+
- LICENSE
|
78
|
+
- README.rdoc
|
79
|
+
- Rakefile
|
80
|
+
- VERSION
|
81
|
+
- bin/imp3
|
82
|
+
- lib/imp3.rb
|
83
|
+
- lib/imp3/cli.rb
|
84
|
+
- test/helper.rb
|
85
|
+
- test/test_normalization.rb
|
86
|
+
has_rdoc: true
|
87
|
+
homepage: http://github.com/knoopx/imp3
|
88
|
+
licenses: []
|
89
|
+
|
90
|
+
post_install_message:
|
91
|
+
rdoc_options:
|
92
|
+
- --charset=UTF-8
|
93
|
+
require_paths:
|
94
|
+
- lib
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: "0"
|
100
|
+
version:
|
101
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: "0"
|
106
|
+
version:
|
107
|
+
requirements: []
|
108
|
+
|
109
|
+
rubyforge_project:
|
110
|
+
rubygems_version: 1.3.5
|
111
|
+
signing_key:
|
112
|
+
specification_version: 3
|
113
|
+
summary: Application for batch processing and fixing common issues when dealing with a large iTunes library
|
114
|
+
test_files:
|
115
|
+
- test/helper.rb
|
116
|
+
- test/test_normalization.rb
|