matthewgarysmith-rubypodder 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2007 Lex Miller
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 ADDED
@@ -0,0 +1,60 @@
1
+ = rubypodder - A podcast aggregator without an interface
2
+
3
+ This package contains rubypodder, a simple podcast receiver
4
+ inspired by bashpodder (http://en.wikipedia.org/wiki/BashPodder).
5
+
6
+ == Homepage
7
+
8
+ http://rubyforge.org/projects/rubypodder/
9
+
10
+ == Installation
11
+
12
+ rubypodder can be downloaded and installed with:
13
+ gem install rubypodder
14
+
15
+ == Quick Start
16
+
17
+ Type
18
+ rubypodder
19
+ When it finishes, you should see a ~/.rubypodder directory.
20
+ This should contain an example rp.conf configuration file with a feed in
21
+ it to get you started. If there were any podcasts to download in the feed
22
+ they will be in a directory named after the date (e.g. 2007-01-20).
23
+ You can see what happened by looking in rp.log.
24
+
25
+ == Running the rubypodder Test Suite
26
+
27
+ If you wish to run the unit tests that come with rubypodder:
28
+ gem check rubypodder --test
29
+ A message will be given if any of the tests fail.
30
+
31
+ === Uninstallation
32
+
33
+ To uninstall the rubypodder gem use:
34
+ gem uninstall rubypodder
35
+
36
+ == Configuration
37
+
38
+ Create a file
39
+ ~/.rubypodder/rp.conf
40
+ containing podcast feeds, one per line.
41
+
42
+ == Usage
43
+
44
+ Type
45
+ rubypodder
46
+
47
+ and if there are any podcast episodes from your feeds that have not yet
48
+ been downloaded, they will be downloaded into a "date" directory such as
49
+ ~/.rubypodder/2007-01-18/
50
+
51
+ A good idea is to use +crontab -e+ and add a line like
52
+ 0 5 * * * rubypodder
53
+ which will set up a cron job which will do this regularly.
54
+
55
+ == License
56
+
57
+ rubypodder is available under an MIT-style license.
58
+
59
+ :include: MIT-LICENSE
60
+
data/Rakefile ADDED
@@ -0,0 +1,32 @@
1
+ require 'rubygems'
2
+ Gem::manage_gems
3
+ require 'rake/gempackagetask'
4
+ spec = Gem::Specification.new do |s|
5
+ s.platform = Gem::Platform::RUBY
6
+ s.name = "rubypodder"
7
+ s.version = "1.0.0"
8
+ s.author = "Lex Miller"
9
+ s.email = "lex.miller @nospam@ gmail.com"
10
+ s.summary = "A podcast aggregator without an interface"
11
+ s.files = FileList['lib/*.rb', 'tests/*', 'Rakefile'].to_a
12
+ s.require_path = "lib"
13
+ s.bindir = "bin"
14
+ s.executables = ["rubypodder"]
15
+ s.default_executable = "rubypodder"
16
+ s.autorequire = "rubypodder"
17
+ s.add_dependency("rio")
18
+ s.add_dependency("rake")
19
+ s.add_dependency("mocha")
20
+ s.test_files = Dir.glob('tests/*.rb')
21
+ s.has_rdoc = true
22
+ s.extra_rdoc_files = ["README", "MIT-LICENSE"]
23
+ end
24
+ Rake::GemPackageTask.new(spec) do |pkg|
25
+ pkg.need_tar = true
26
+ end
27
+ task :default => "pkg/#{spec.name}-#{spec.version}.gem" do
28
+ puts "generated latest version"
29
+ end
30
+ task :test do
31
+ ruby "tests/ts_rubypodder.rb"
32
+ end
data/bin/rubypodder ADDED
@@ -0,0 +1,8 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
+ require 'rubypodder'
3
+ require 'optparse'
4
+ opts = OptionParser.new
5
+ opts.on("-v", "--version") { puts RubyPodder::Version; exit }
6
+ opts.on("-h", "--help") { puts opts.to_s + "See http://rubypodder.rubyforge.org/\n"; exit }
7
+ opts.parse(*ARGV)
8
+ RubyPodder.new.run
data/lib/rubypodder.rb ADDED
@@ -0,0 +1,155 @@
1
+ require 'rss/1.0'
2
+ require 'rss/2.0'
3
+ require 'net/http'
4
+ require 'uri'
5
+ require 'rubygems'
6
+ require 'rio'
7
+ require 'logger'
8
+ require 'ftools'
9
+
10
+ class File
11
+
12
+ def self.touch(fn)
13
+ File.open(fn, "w").close unless File.exist?(fn)
14
+ end
15
+
16
+ end
17
+
18
+ class RubyPodder
19
+
20
+ Version = 'rubypodder v1.0.0'
21
+
22
+ attr_reader :conf_file, :log_file, :done_file, :date_dir
23
+
24
+ def initialize(file_base="~/.rubypodder/rp")
25
+ @file_base = File.expand_path(file_base)
26
+ @rp_dir = File.dirname(@file_base)
27
+ @conf_file = @file_base + ".conf"
28
+ @log_file = @file_base + ".log"
29
+ @done_file = @file_base + ".done"
30
+ create_default_config_file
31
+ @log = Logger.new(@log_file)
32
+ File.touch @done_file
33
+ @date_dir = create_date_dir
34
+ end
35
+
36
+ def create_default_config_file
37
+ expanded_path = File.expand_path(@conf_file)
38
+ return if File.exists?(expanded_path)
39
+ make_dirname(expanded_path)
40
+ rio(expanded_path) < "http://downloads.bbc.co.uk/rmhttp/downloadtrial/radio4/thenowshow/rss.xml\n"
41
+ end
42
+
43
+ def make_dirname(full_filename)
44
+ dirname = File.dirname(full_filename)
45
+ File.makedirs dirname
46
+ end
47
+
48
+ def date_string(time)
49
+ time.strftime("%Y-%m-%d")
50
+ end
51
+
52
+ def create_date_dir
53
+ date_dir = File.join(@rp_dir, date_string(Time.now))
54
+ File.makedirs date_dir
55
+ date_dir
56
+ end
57
+
58
+ def read_feeds
59
+ #IO.readlines(@conf_file).each {|l| l.chomp!}
60
+ a = rio(@conf_file).chomp.readlines.reject {|i| i =~ /^#/}
61
+ end
62
+
63
+ def parse_rss(rss_source)
64
+ RSS::Parser.parse(rss_source, false)
65
+ end
66
+
67
+ def dest_file_name(url)
68
+ dest = File.join(@date_dir, File.basename(URI.parse(url).path))
69
+ dest = dest.gsub(/\s+/,'_').gsub('%20','_')
70
+ while File.exists? dest
71
+ ext = File.extname(dest)
72
+ name = File.basename(dest, ext)
73
+ name += "_00" unless name =~ /_\d+$/
74
+ name.succ!
75
+ dest = File.join(File.dirname(dest), name + ext)
76
+ end
77
+ return dest
78
+ end
79
+
80
+ def record_download(url, guid)
81
+ rio(@done_file) << "#{url}\n"
82
+ rio(@done_file) << "#{guid}\n"
83
+ end
84
+
85
+ def already_downloaded(url, guid)
86
+ previously_downloaded = [url.strip.downcase, guid.strip.downcase]
87
+ File.open(@done_file).detect do |line|
88
+ previously_downloaded.include?(line.strip.downcase)
89
+ end
90
+ end
91
+
92
+ def download(url, guid)
93
+ return if already_downloaded(url, guid)
94
+ @log.info(" Downloading: #{url}")
95
+ begin
96
+ file_name = dest_file_name(url)
97
+ rio(file_name) < rio(url)
98
+ rescue
99
+ @log.error(" Failed to download #{url}")
100
+ else
101
+ record_download(url, guid)
102
+ end
103
+ end
104
+
105
+ def download_all(items)
106
+ items.each do |item|
107
+ begin
108
+ guid = nil
109
+ if item.respond_to?(:guid) && item.guid.respond_to?(:content)
110
+ guid = item.guid.content
111
+ end
112
+ download(item.enclosure.url, guid)
113
+ rescue
114
+ @log.warn(" No media to download for this item")
115
+ end
116
+ end
117
+ end
118
+
119
+ def remove_dir_if_empty(dirname)
120
+ begin
121
+ Dir.rmdir(dirname)
122
+ rescue SystemCallError
123
+ @log.info("#{dirname} has contents, not removed")
124
+ else
125
+ @log.info("#{dirname} was empty, removed")
126
+ end
127
+ end
128
+
129
+ def run
130
+ @log.info("Starting (#{Version})")
131
+ read_feeds.each do |url|
132
+ begin
133
+ http_body = open(url, 'User-Agent' => 'Ruby-Wget').read
134
+ rescue
135
+ @log.error(" Can't read from #{url}")
136
+ next
137
+ end
138
+ begin
139
+ rss = parse_rss(http_body)
140
+ rescue
141
+ @log.error(" Can't parse this feed")
142
+ next
143
+ end
144
+ @log.info("Channel: #{rss.channel.title}")
145
+ download_all(rss.items)
146
+ end
147
+ remove_dir_if_empty(@date_dir)
148
+ @log.info("Finished")
149
+ end
150
+
151
+ end
152
+
153
+ if $0 == __FILE__
154
+ RubyPodder.new.run
155
+ end
@@ -0,0 +1,259 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
+ require 'test/unit'
3
+ require 'rubypodder'
4
+ require 'mocha'
5
+
6
+ class TC_RubyPodder < Test::Unit::TestCase
7
+
8
+ def setup
9
+ system("rm -rf " + "/tmp/test_rp.conf")
10
+ system("rm -rf " + "/tmp/test_rp.done")
11
+ File.open("/tmp/test_rp.conf", "w") do |file|
12
+ file.write("# This is just a comment\n")
13
+ file.write("http://downloads.bbc.co.uk/rmhttp/downloadtrial/radio4/thenowshow/rss.xml\n")
14
+ file.write("# This is just another comment\n")
15
+ file.write("http://www.guardian.co.uk/podcasts/comedy/rickygervais/mp3.xml\n")
16
+ end
17
+ @subdir = "/tmp/subdir"
18
+ system("rm -rf " + @subdir)
19
+ @rp = RubyPodder.new("/tmp/test_rp")
20
+ end
21
+
22
+ def teardown
23
+ system("rm -rf " + "/tmp/test_rp.conf")
24
+ system("rm -rf " + "/tmp/test_rp.done")
25
+ system("rm -rf " + "/tmp/test_rp.log")
26
+ system("rm -rf " + "/tmp/#{@rp.date_string(Time.now)}")
27
+ system("rm -rf " + @subdir)
28
+
29
+ end
30
+
31
+ def test_initialize_with_test_config_file
32
+ assert_kind_of(RubyPodder, @rp)
33
+ assert_equal("/tmp/test_rp.conf", @rp.conf_file)
34
+ assert_equal("/tmp/test_rp.log", @rp.log_file)
35
+ assert_equal("/tmp/test_rp.done", @rp.done_file)
36
+ end
37
+
38
+ def test_initialize_with_default_config_file
39
+ ENV['HOME'] = "/tmp"
40
+ @rp = RubyPodder.new()
41
+ assert_kind_of(RubyPodder, @rp)
42
+ assert_equal(ENV['HOME'] + "/.rubypodder/rp.conf", @rp.conf_file)
43
+ assert_equal(ENV['HOME'] + "/.rubypodder/rp.log", @rp.log_file)
44
+ assert_equal(ENV['HOME'] + "/.rubypodder/rp.done", @rp.done_file)
45
+ system("rm -rf " + "/tmp/.rubypodder")
46
+ end
47
+
48
+ def test_initialize_with_absent_config_file
49
+ file_base = "/tmp/test_rp"
50
+ file_conf = file_base + ".conf"
51
+ system("rm -rf " + file_conf)
52
+ @rp = RubyPodder.new(file_base)
53
+ assert(File.exists?(file_conf))
54
+ system("rm -rf " + file_conf)
55
+ end
56
+
57
+ def test_make_dirname_one_subdir
58
+ filename = @subdir + "/file"
59
+ @rp.make_dirname(filename)
60
+ assert(File.exists?(@subdir))
61
+ end
62
+
63
+ def test_make_dirname_many_subdir
64
+ subsubdirs = "/subsubdir/subsubsubdir"
65
+ filename = @subdir + subsubdirs + "/file"
66
+ @rp.make_dirname(filename)
67
+ assert(File.exists?(@subdir + subsubdirs))
68
+ end
69
+
70
+ def test_date_string
71
+ t = Time.gm(2006,"dec",18,21,0,0)
72
+ date_string = @rp.date_string(t)
73
+ assert_equal(date_string, "2006-12-18")
74
+ end
75
+
76
+ def test_initialize_with_absent_config_file_dir
77
+ file_base = @subdir + "/test_rp"
78
+ file_conf = file_base + ".conf"
79
+ @rp = RubyPodder.new(file_base)
80
+ assert(File.exists?(file_conf))
81
+ end
82
+
83
+ def test_initialize_creates_date_dir
84
+ file_base = @subdir + "/test_rp"
85
+ @rp = RubyPodder.new(file_base)
86
+ date_dir = @subdir + "/" + @rp.date_string(Time.now)
87
+ assert_equal(date_dir, @rp.date_dir)
88
+ assert(File.exists?(date_dir), "Subdirectory #{date_dir} not created")
89
+ end
90
+
91
+ def test_read_feeds
92
+ feed_list = @rp.read_feeds
93
+ assert_kind_of(Array, feed_list)
94
+ assert_equal(2, feed_list.length)
95
+ assert_equal("http://downloads.bbc.co.uk/rmhttp/downloadtrial/radio4/thenowshow/rss.xml", feed_list[0])
96
+ assert_equal("http://www.guardian.co.uk/podcasts/comedy/rickygervais/mp3.xml", feed_list[1])
97
+ end
98
+
99
+ def test_parse_rss
100
+ #rss_source = IO.read("test_feed.xml")
101
+ rss_source = <<-END_OF_STRING
102
+ <?xml version="1.0" encoding="utf-8"?>
103
+ <rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0">
104
+ <channel>
105
+ <lastBuildDate>Fri, 27 Oct 2006 16:50:15 +0100</lastBuildDate>
106
+ <title>The Ricky Gervais Show</title>
107
+ <itunes:author>Guardian Unlimited</itunes:author>
108
+ <link>http://www.guardian.co.uk/rickygervais</link>
109
+ <generator>Podcast Maker v1.2.4 - http://www.potionfactory.com/podcastmaker</generator>
110
+ <description>Ricky Gervais, Steve Merchant and Karl Pilkington are back yada yada</description>
111
+ <itunes:subtitle />
112
+ <itunes:summary>Ricky Gervais, Steve Merchant and Karl Pilkington are back yada yada</itunes:summary>
113
+ <language>en</language>
114
+ <copyright>Ricky Gervais, Steve Merchant, Karl Pilkington</copyright>
115
+ <itunes:owner>
116
+ <itunes:name>Glyn Hughes</itunes:name>
117
+ <itunes:email>glyn@rickygervais.com</itunes:email>
118
+ </itunes:owner>
119
+ <image>
120
+ <url>http://podcast.rickygervais.com/gu_p123_300_144.jpg</url>
121
+ <title>The Ricky Gervais Show</title>
122
+ <link>http://www.guardian.co.uk/rickygervais</link>
123
+ <width>144</width>
124
+ <height>144</height>
125
+ </image>
126
+ <itunes:image href="http://podcast.rickygervais.com/gu_p123_300.jpg" />
127
+ <category>Comedy</category>
128
+ <itunes:category text="Comedy" />
129
+ <itunes:keywords>Ricky, Gervais, Steve, Merchant, Karl, Pilkington</itunes:keywords>
130
+ <itunes:explicit>yes</itunes:explicit>
131
+ <item>
132
+ <title>The Podfather Part I - Halloween</title>
133
+ <itunes:author>Guardian Unlimited</itunes:author>
134
+ <description>The first of three specials from Ricky, Steve and Karl yada yada</description>
135
+ <itunes:subtitle>The first of three specials from Ricky, Steve and Karl yada yada</itunes:subtitle>
136
+ <itunes:summary />
137
+ <enclosure type="audio/mpeg" url="http://podcast.rickygervais.com/guspecials_halloween.mp3" length="15723925" />
138
+ <guid>http://podcast.rickygervais.com/guspecials_halloween.mp3</guid>
139
+ <pubDate>Tue, 31 Oct 2006 00:00:01 +0000</pubDate>
140
+ <category>Comedy</category>
141
+ <itunes:explicit>yes</itunes:explicit>
142
+ <itunes:duration>00:37:22</itunes:duration>
143
+ <itunes:keywords>Ricky, Gervais, Steve, Merchant, Karl, Pilkington</itunes:keywords>
144
+ </item>
145
+ </channel>
146
+ </rss>
147
+ END_OF_STRING
148
+ rss = @rp.parse_rss(rss_source)
149
+ assert_equal(1, rss.items.length)
150
+ assert_equal("http://podcast.rickygervais.com/guspecials_halloween.mp3", rss.items[0].enclosure.url)
151
+ end
152
+
153
+ def test_item_with_no_enclosure
154
+ rss_source = <<-END_OF_STRING
155
+ <?xml version="1.0" encoding="utf-8"?>
156
+ <rss>
157
+ <channel>
158
+ <title>The Ricky Gervais Show</title>
159
+ <item>
160
+ <title>The Podfather Part I - Halloween</title>
161
+ </item>
162
+ </channel>
163
+ </rss>
164
+ END_OF_STRING
165
+
166
+ # Code here to test that a run doesn't throw an exception if there is no enclosure.
167
+ # (Remove enclosure from the above test XML)
168
+ #
169
+ rss = @rp.parse_rss(rss_source)
170
+ assert_nothing_raised { @rp.download_all(rss.items) }
171
+ end
172
+
173
+ def test_dest_file_name(url)
174
+ correct_dest_file_name = @rp.date_dir + "/" + "podcast.mp3"
175
+ dest_file_name = @rp.dest_file_name("http://www.podcast.com/podcast.mp3")
176
+ assert_equal(correct_dest_file_name, dest_file_name)
177
+ dest_file_name = @rp.dest_file_name("http://www.podcast.com/subdir/podcast.mp3")
178
+ assert_equal(correct_dest_file_name, dest_file_name)
179
+ end
180
+
181
+ def test_download
182
+ @rp.download("http://www.google.com/index.html")
183
+ dest_file = @rp.date_dir + "/" + "index.html"
184
+ assert(File.exists?(dest_file))
185
+ assert(File.open(dest_file).grep(/google/))
186
+ end
187
+
188
+ def test_download_recorded
189
+ @rp.download("http://www.google.com/index.html")
190
+ assert(File.exists?(@rp.done_file))
191
+ assert(File.open(@rp.done_file).grep(/^http:\/\/www.google.com\/index.html$/))
192
+ end
193
+
194
+ def test_already_downloaded
195
+ url1 = "http://www.google.com/index.html"
196
+ assert(!@rp.already_downloaded(url1), "url1 should not be already downloaded before download of url1")
197
+ @rp.download(url1)
198
+ File.open( @rp.log_file ) do |f|
199
+ return if (f.any? { |line| line =~ /ERROR/ }) # Don't test this case if no internet connection
200
+ end
201
+ assert(@rp.already_downloaded(url1), "url1 should be already downloaded after download of url1")
202
+ url2 = "http://www.google.co.nz/index.html"
203
+ @rp.download(url2)
204
+ assert(@rp.already_downloaded(url2), "url2 should be already downloaded after download of url2")
205
+ assert(@rp.already_downloaded(url1), "url1 should still be already downloaded after download of url2")
206
+ end
207
+
208
+ def test_download_omits_done_items
209
+ dest_file = @rp.date_dir + "/" + "index.html"
210
+ system("rm -rf " + dest_file)
211
+ @rp.record_download("http://www.google.com/index.html")
212
+ @rp.download("http://www.google.com/index.html")
213
+ assert(!File.exists?(dest_file), "#{dest_file} should not be downloaded again if already recorded as done")
214
+ end
215
+
216
+ def test_download_error_is_logged
217
+ @rp.download("http://very.very.broken.url/oh/no/oh/dear.xml")
218
+ File.open( @rp.log_file ) do |f|
219
+ assert(f.any? { |line| line =~ /ERROR/ }, "Error in download should be logged")
220
+ end
221
+ end
222
+
223
+ def test_remove_dir_if_empty
224
+ system("mkdir -p " + @subdir)
225
+ @rp.remove_dir_if_empty(@subdir)
226
+ assert(!File.exists?(@subdir))
227
+ system("mkdir -p " + @subdir)
228
+ system("touch " + @subdir + "/fish")
229
+ @rp.remove_dir_if_empty(@subdir)
230
+ assert(File.exists?(@subdir))
231
+ end
232
+
233
+ def test_log_contains_version
234
+ File.open("/tmp/test_rp.conf", "w") { |file| file.write("# Empty config file\n") }
235
+ @rp = RubyPodder.new("/tmp/test_rp")
236
+ @rp.run
237
+ File.open( @rp.log_file ) do |f|
238
+ assert(f.any? { |line| line =~ /Starting.+#{RubyPodder::Version}/ }, "'Starting' log entry should contain '#{RubyPodder::Version}'")
239
+ end
240
+ end
241
+
242
+ def test_log_contains_error_for_unreadable_feed_url
243
+ File.open("/tmp/test_rp.conf", "w") { |file| file.write("http://very.very.broken.url/oh/no/oh/dear.xml\n") }
244
+ @rp = RubyPodder.new("/tmp/test_rp")
245
+ @rp.run
246
+ File.open( @rp.log_file ) do |f|
247
+ assert(f.any? { |line| line =~ /ERROR/ }, "Error in feed url should be logged")
248
+ end
249
+ end
250
+
251
+ def test_log_contains_error_for_unparsable_rss_source
252
+ @rp.stubs(:parse_rss).raises(RSS::NotWellFormedError, 'This is not well formed XML')
253
+ @rp.run
254
+ File.open( @rp.log_file ) do |f|
255
+ assert(f.any? { |line| line =~ /ERROR/ }, "Parse error in rss source should be logged")
256
+ end
257
+ end
258
+
259
+ end
@@ -0,0 +1,52 @@
1
+ require 'test/unit'
2
+
3
+ class StringStream < String
4
+ def write(message)
5
+ self.<< message
6
+ end
7
+ end
8
+
9
+ def wrap(&b)
10
+ raise "Expected block!" unless block_given?
11
+ s = StringStream.new
12
+ old = $stdout.clone
13
+ $stdout = s
14
+ b.call
15
+ $stdout = old
16
+ s
17
+ end
18
+
19
+ def last_log
20
+ log = '/tmp/.rubypodder/rp.log'
21
+ File.exists?(log) ? File.mtime('/tmp/.rubypodder/rp.log') : Time.at(0)
22
+ end
23
+
24
+ def exits_without_doing_anything(&b)
25
+ raise "Expected block!" unless block_given?
26
+ before = last_log
27
+ b.call
28
+ after = last_log
29
+ before == after
30
+ end
31
+
32
+ class TC_stdout < Test::Unit::TestCase
33
+ def setup
34
+ ENV['HOME'] = "/tmp"
35
+ @bindir = File.join(File.dirname(__FILE__), "..", "bin")
36
+ end
37
+
38
+ def teardown
39
+ system("rm -rf " + "/tmp/.rubypodder")
40
+ end
41
+
42
+ def test_version
43
+ assert_equal "rubypodder v1.0.0\n", wrap { puts `ruby #{@bindir}/rubypodder --version` }
44
+ assert exits_without_doing_anything { `ruby #{@bindir}/rubypodder --version` }, "--version doesn't exit immediately"
45
+ end
46
+
47
+ def test_help
48
+ assert_match %r{See http://rubypodder.rubyforge.org/}, wrap { puts `ruby #{@bindir}/rubypodder --help` }
49
+ assert exits_without_doing_anything { `ruby #{@bindir}/rubypodder --help` }, "--help doesn't exit immediately"
50
+ end
51
+
52
+ end
@@ -0,0 +1,4 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), "..", "tests")
2
+ require 'test/unit'
3
+ require 'tc_rubypodder.rb'
4
+ require 'tc_stdout.rb'
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: matthewgarysmith-rubypodder
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Lex Miller
8
+ autorequire: rubypodder
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-01-24 00:00:00 -08:00
13
+ default_executable: rubypodder
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rio
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: "0"
23
+ version:
24
+ - !ruby/object:Gem::Dependency
25
+ name: rake
26
+ version_requirement:
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ version: "0"
32
+ version:
33
+ - !ruby/object:Gem::Dependency
34
+ name: mocha
35
+ version_requirement:
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: "0"
41
+ version:
42
+ description:
43
+ email: lex.miller @nospam@ gmail.com
44
+ executables:
45
+ - rubypodder
46
+ extensions: []
47
+
48
+ extra_rdoc_files:
49
+ - README
50
+ - MIT-LICENSE
51
+ files:
52
+ - lib/rubypodder.rb
53
+ - tests/tc_rubypodder.rb
54
+ - tests/ts_rubypodder.rb
55
+ - tests/tc_stdout.rb
56
+ - Rakefile
57
+ - README
58
+ - MIT-LICENSE
59
+ has_rdoc: true
60
+ homepage:
61
+ post_install_message:
62
+ rdoc_options: []
63
+
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: "0"
71
+ version:
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: "0"
77
+ version:
78
+ requirements: []
79
+
80
+ rubyforge_project:
81
+ rubygems_version: 1.2.0
82
+ signing_key:
83
+ specification_version: 2
84
+ summary: A podcast aggregator without an interface
85
+ test_files:
86
+ - tests/tc_rubypodder.rb
87
+ - tests/tc_stdout.rb
88
+ - tests/ts_rubypodder.rb