matthewgarysmith-rubypodder 1.0.1

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.
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