Oshuma-pingfm 1.0.0

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.
@@ -0,0 +1,159 @@
1
+ # $Id$
2
+
3
+ require File.join(File.dirname(__FILE__), %w[spec_helper])
4
+
5
+ describe Pingfm::Client, " with expected results" do
6
+
7
+ before(:each) do
8
+ @client = Pingfm::Client.new('a','b')
9
+ @params = {'api_key' => 'a', 'user_app_key' => 'b'}
10
+ end
11
+
12
+ it "should validate keys successfully" do
13
+ init_ok_response 'user.validate'
14
+
15
+ uri = URI.parse "#{Pingfm::API_URL}/#{@service_type}"
16
+
17
+ # mock the http call
18
+ http_resp = mock('response')
19
+ http_resp.should_receive(:body).and_return(@response)
20
+ Net::HTTP.should_receive(:post_form).with(uri, @params).and_return(http_resp)
21
+
22
+ # call and verify
23
+ result = @client.validate
24
+ result.should_not be_empty
25
+ result['status'].should_not be_nil
26
+ result['status'].should eql('OK')
27
+ end
28
+
29
+ it "should list the user's services properly" do
30
+ init_service_response
31
+
32
+ uri = URI.parse "#{Pingfm::API_URL}/#{@service_type}"
33
+
34
+ # mock the http call
35
+ http_resp = mock('response')
36
+ http_resp.should_receive(:body).and_return(@response)
37
+ Net::HTTP.should_receive(:post_form).with(uri, @params).and_return(http_resp)
38
+
39
+ # call and verify
40
+ result = @client.services
41
+ result.should_not be_empty
42
+ result['status'].should_not be_nil
43
+ result['status'].should eql('OK')
44
+ result['services'].should_not be_nil
45
+ result['services'].should_not be_empty
46
+ result['services'].length.should eql(2)
47
+ result['services'].first['id'].should eql('twitter')
48
+ end
49
+
50
+ it "should list the user's custom triggers" do
51
+ init_trigger_response
52
+
53
+ uri = URI.parse "#{Pingfm::API_URL}/#{@service_type}"
54
+
55
+ # mock the http call
56
+ http_resp = mock('response')
57
+ http_resp.should_receive(:body).and_return(@response)
58
+ Net::HTTP.should_receive(:post_form).with(uri, @params).and_return(http_resp)
59
+
60
+ # call and verify
61
+ result = @client.triggers
62
+ result.should_not be_empty
63
+ result['status'].should_not be_nil
64
+ result['status'].should eql('OK')
65
+ result['triggers'].should_not be_nil
66
+ result['triggers'].should_not be_empty
67
+ result['triggers'].length.should eql(2)
68
+ result['triggers'].first['id'].should eql('twt')
69
+ end
70
+
71
+ it "should list the user's recent posts" do
72
+ init_latest_response
73
+
74
+ uri = URI.parse "#{Pingfm::API_URL}/#{@service_type}"
75
+ @params.merge!('limit'=>5,'order'=>'DESC')
76
+
77
+ # mock the http call
78
+ http_resp = mock('response')
79
+ http_resp.should_receive(:body).and_return(@response)
80
+ Net::HTTP.should_receive(:post_form).with(uri, @params).and_return(http_resp)
81
+
82
+ # call and verify
83
+ result = @client.latest(5)
84
+ result.should_not be_empty
85
+ result['status'].should_not be_nil
86
+ result['status'].should eql('OK')
87
+ result['messages'].should_not be_nil
88
+ result['messages'].should_not be_empty
89
+ result['messages'].length.should eql(3)
90
+ result['messages'].first['id'].should eql('12345')
91
+ end
92
+
93
+ it "should post a message to the service" do
94
+ init_ok_response 'user.post'
95
+
96
+ uri = URI.parse "#{Pingfm::API_URL}/#{@service_type}"
97
+ @params.merge!('body' => 'foo', 'title' => '',
98
+ 'post_method' => 'default', 'service' => '',
99
+ 'debug' => 0)
100
+
101
+ # mock the http call
102
+ http_resp = mock('response')
103
+ http_resp.should_receive(:body).and_return(@response)
104
+ Net::HTTP.should_receive(:post_form).with(uri, @params).and_return(http_resp)
105
+
106
+ # call and verify
107
+ result = @client.post('foo')
108
+ result.should_not be_empty
109
+ result['status'].should_not be_nil
110
+ result['status'].should eql('OK')
111
+ end
112
+
113
+ it "should post a message to the service using a trigger" do
114
+ init_ok_response 'user.tpost'
115
+
116
+ uri = URI.parse "#{Pingfm::API_URL}/#{@service_type}"
117
+ @params.merge!('body' => 'foo', 'title' => '',
118
+ 'trigger' => 'twt', 'debug' => 0)
119
+
120
+ # mock the http call
121
+ http_resp = mock('response')
122
+ http_resp.should_receive(:body).and_return(@response)
123
+ Net::HTTP.should_receive(:post_form).with(uri, @params).and_return(http_resp)
124
+
125
+ # call and verify
126
+ result = @client.tpost('foo','twt')
127
+ result.should_not be_empty
128
+ result['status'].should_not be_nil
129
+ result['status'].should eql('OK')
130
+ end
131
+
132
+ end
133
+
134
+ describe Pingfm::Client, " with error messages" do
135
+ before(:each) do
136
+ @client = Pingfm::Client.new('a','b')
137
+ @params = {'api_key' => 'a', 'user_app_key' => 'b'}
138
+ end
139
+
140
+ it "should handle a failed validate cleanly" do
141
+ init_fail_response 'user.validate'
142
+
143
+ uri = URI.parse "#{Pingfm::API_URL}/#{@service_type}"
144
+
145
+ # mock the http call
146
+ http_resp = mock('response')
147
+ http_resp.should_receive(:body).and_return(@response)
148
+ Net::HTTP.should_receive(:post_form).with(uri, @params).and_return(http_resp)
149
+
150
+ # call and verify
151
+ result = @client.validate
152
+ result.should_not be_empty
153
+ result['status'].should_not be_nil
154
+ result['status'].should eql('FAIL')
155
+ result['message'].should_not be_nil
156
+ end
157
+ end
158
+
159
+ # EOF
@@ -0,0 +1,130 @@
1
+ # $Id$
2
+
3
+ require File.expand_path(
4
+ File.join(File.dirname(__FILE__), %w[.. lib pingfm]))
5
+
6
+ # Spec::Runner.configure do |config|
7
+ # == Mock Framework
8
+ #
9
+ # RSpec uses it's own mocking framework by default. If you prefer to
10
+ # use mocha, flexmock or RR, uncomment the appropriate line:
11
+ #
12
+ # config.mock_with :mocha
13
+ # config.mock_with :flexmock
14
+ # config.mock_with :rr
15
+ # end
16
+
17
+ def init_ok_response(service_type)
18
+ @service_type = service_type
19
+ @response = <<EOXML
20
+ <?xml version="1.0"?>
21
+ <rsp status="OK">
22
+ <transaction>12345</transaction>
23
+ <method>#{@service_type}</method>
24
+ </rsp>
25
+ EOXML
26
+ end
27
+
28
+ def init_fail_response(service_type)
29
+ @service_type = service_type
30
+ @response = <<EOXML
31
+ <?xml version="1.0"?>
32
+ <rsp status="FAIL">
33
+ <transaction>12345</transaction>
34
+ <method>#{@service_type}</method>
35
+ <message>You suck</message>
36
+ </rsp>
37
+ EOXML
38
+ end
39
+
40
+ def init_service_response
41
+ @service_type = 'user.services'
42
+ @response = <<EOXML
43
+ <?xml version="1.0"?>
44
+ <rsp status="OK">
45
+ <transaction>12345</transaction>
46
+ <method>user.services</method>
47
+ <services>
48
+ <service id="twitter" name="Twitter">
49
+ <trigger>@tt</trigger>
50
+ <url>http://twitter.com/</url>
51
+ <icon>http://p.ping.fm/static/icons/twitter.png</icon>
52
+ <methods>microblog,status</methods>
53
+ </service>
54
+ <service id="facebook" name="Facebook">
55
+ <trigger>@fb</trigger>
56
+ <url>http://www.facebook.com/</url>
57
+ <icon>http://p.ping.fm/static/icons/facebook.png</icon>
58
+ <methods>status</methods>
59
+ </service>
60
+ </services>
61
+ </rsp>
62
+ EOXML
63
+ end
64
+
65
+ def init_trigger_response
66
+ @service_type = 'user.triggers'
67
+ @response = <<EOXML
68
+ <?xml version="1.0"?>
69
+ <rsp status="OK">
70
+ <transaction>12345</transaction>
71
+ <method>user.triggers</method>
72
+ <triggers>
73
+ <trigger id="twt" method="microblog">
74
+ <services>
75
+ <service id="twitter" name="Twitter"/>
76
+ </services>
77
+ </trigger>
78
+ <trigger id="fb" method="status">
79
+ <services>
80
+ <service id="facebook" name="Facebook"/>
81
+ </services>
82
+ </trigger>
83
+ </triggers>
84
+ </rsp>
85
+ EOXML
86
+ end
87
+
88
+ def init_latest_response
89
+ @service_type = 'user.latest'
90
+ @response = <<EOXML
91
+ <?xml version="1.0"?>
92
+ <rsp status="OK">
93
+ <transaction>12345</transaction>
94
+ <method>user.latest</method>
95
+ <messages>
96
+ <message id="12345" method="blog">
97
+ <date rfc="Tue, 15 Apr 2008 13:56:18 -0500" unix="1234567890" />
98
+ <services>
99
+ <service id="blogger" name="Blogger"/>
100
+ </services>
101
+ <content>
102
+ <title>SnVzdCBoYW5naW4nIG91dCE=</title>
103
+ <body>R29pbmcgdG8gdGhlIHN0b3JlLg==</body>
104
+ </content>
105
+ </message>
106
+ <message id="12345" method="microblog">
107
+ <date rfc="Tue, 15 Apr 2008 13:56:18 -0500" unix="1234567890" />
108
+ <services>
109
+ <service id="twitter" name="Twitter"/>
110
+ </services>
111
+ <content>
112
+ <body>R29pbmcgdG8gdGhlIHN0b3JlLg==</body>
113
+ </content>
114
+ </message>
115
+ <message id="12345" method="status">
116
+ <date rfc="Tue, 15 Apr 2008 13:56:18 -0500" unix="1234567890" />
117
+ <services>
118
+ <service id="twitter" name="Twitter"/>
119
+ <service id="facebook" name="Facebook"/>
120
+ </services>
121
+ <content>
122
+ <body>aXMgdGVzdGluZyBQaW5nLmZtIQ==</body>
123
+ </content>
124
+ </message>
125
+ </messages>
126
+ </rsp>
127
+ EOXML
128
+ end
129
+
130
+ # EOF
data/tasks/ann.rake ADDED
@@ -0,0 +1,81 @@
1
+ # $Id$
2
+
3
+ begin
4
+ require 'bones/smtp_tls'
5
+ rescue LoadError
6
+ require 'net/smtp'
7
+ end
8
+ require 'time'
9
+
10
+ namespace :ann do
11
+
12
+ # A prerequisites task that all other tasks depend upon
13
+ task :prereqs
14
+
15
+ file PROJ.ann.file do
16
+ ann = PROJ.ann
17
+ puts "Generating #{ann.file}"
18
+ File.open(ann.file,'w') do |fd|
19
+ fd.puts("#{PROJ.name} version #{PROJ.version}")
20
+ fd.puts(" by #{Array(PROJ.authors).first}") if PROJ.authors
21
+ fd.puts(" #{PROJ.url}") if PROJ.url.valid?
22
+ fd.puts(" (the \"#{PROJ.release_name}\" release)") if PROJ.release_name
23
+ fd.puts
24
+ fd.puts("== DESCRIPTION")
25
+ fd.puts
26
+ fd.puts(PROJ.description)
27
+ fd.puts
28
+ fd.puts(PROJ.changes.sub(%r/^.*$/, '== CHANGES'))
29
+ fd.puts
30
+ ann.paragraphs.each do |p|
31
+ fd.puts "== #{p.upcase}"
32
+ fd.puts
33
+ fd.puts paragraphs_of(PROJ.readme_file, p).join("\n\n")
34
+ fd.puts
35
+ end
36
+ fd.puts ann.text if ann.text
37
+ end
38
+ end
39
+
40
+ desc "Create an announcement file"
41
+ task :announcement => ['ann:prereqs', PROJ.ann.file]
42
+
43
+ desc "Send an email announcement"
44
+ task :email => ['ann:prereqs', PROJ.ann.file] do
45
+ ann = PROJ.ann
46
+ from = ann.email[:from] || PROJ.email
47
+ to = Array(ann.email[:to])
48
+
49
+ ### build a mail header for RFC 822
50
+ rfc822msg = "From: #{from}\n"
51
+ rfc822msg << "To: #{to.join(',')}\n"
52
+ rfc822msg << "Subject: [ANN] #{PROJ.name} #{PROJ.version}"
53
+ rfc822msg << " (#{PROJ.release_name})" if PROJ.release_name
54
+ rfc822msg << "\n"
55
+ rfc822msg << "Date: #{Time.new.rfc822}\n"
56
+ rfc822msg << "Message-Id: "
57
+ rfc822msg << "<#{"%.8f" % Time.now.to_f}@#{ann.email[:domain]}>\n\n"
58
+ rfc822msg << File.read(ann.file)
59
+
60
+ params = [:server, :port, :domain, :acct, :passwd, :authtype].map do |key|
61
+ ann.email[key]
62
+ end
63
+
64
+ params[3] = PROJ.email if params[3].nil?
65
+
66
+ if params[4].nil?
67
+ STDOUT.write "Please enter your e-mail password (#{params[3]}): "
68
+ params[4] = STDIN.gets.chomp
69
+ end
70
+
71
+ ### send email
72
+ Net::SMTP.start(*params) {|smtp| smtp.sendmail(rfc822msg, from, to)}
73
+ end
74
+ end # namespace :ann
75
+
76
+ desc 'Alias to ann:announcement'
77
+ task :ann => 'ann:announcement'
78
+
79
+ CLOBBER << PROJ.ann.file
80
+
81
+ # EOF
data/tasks/bones.rake ADDED
@@ -0,0 +1,21 @@
1
+ # $Id$
2
+
3
+ if HAVE_BONES
4
+
5
+ namespace :bones do
6
+
7
+ desc 'Show the PROJ open struct'
8
+ task :debug do |t|
9
+ atr = if t.application.top_level_tasks.length == 2
10
+ t.application.top_level_tasks.pop
11
+ end
12
+
13
+ if atr then Bones::Debug.show_attr(PROJ, atr)
14
+ else Bones::Debug.show PROJ end
15
+ end
16
+
17
+ end # namespace :bones
18
+
19
+ end # HAVE_BONES
20
+
21
+ # EOF
data/tasks/gem.rake ADDED
@@ -0,0 +1,126 @@
1
+ # $Id$
2
+
3
+ require 'rake/gempackagetask'
4
+
5
+ namespace :gem do
6
+
7
+ PROJ.gem._spec = Gem::Specification.new do |s|
8
+ s.name = PROJ.name
9
+ s.version = PROJ.version
10
+ s.summary = PROJ.summary
11
+ s.authors = Array(PROJ.authors)
12
+ s.email = PROJ.email
13
+ s.homepage = Array(PROJ.url).first
14
+ s.rubyforge_project = PROJ.rubyforge.name
15
+
16
+ s.description = PROJ.description
17
+
18
+ PROJ.gem.dependencies.each do |dep|
19
+ s.add_dependency(*dep)
20
+ end
21
+
22
+ s.files = PROJ.gem.files
23
+ s.executables = PROJ.gem.executables.map {|fn| File.basename(fn)}
24
+ s.extensions = PROJ.gem.files.grep %r/extconf\.rb$/
25
+
26
+ s.bindir = 'bin'
27
+ dirs = Dir["{#{PROJ.libs.join(',')}}"]
28
+ s.require_paths = dirs unless dirs.empty?
29
+
30
+ incl = Regexp.new(PROJ.rdoc.include.join('|'))
31
+ excl = PROJ.rdoc.exclude.dup.concat %w[\.rb$ ^(\.\/|\/)?ext]
32
+ excl = Regexp.new(excl.join('|'))
33
+ rdoc_files = PROJ.gem.files.find_all do |fn|
34
+ case fn
35
+ when excl; false
36
+ when incl; true
37
+ else false end
38
+ end
39
+ s.rdoc_options = PROJ.rdoc.opts + ['--main', PROJ.rdoc.main]
40
+ s.extra_rdoc_files = rdoc_files
41
+ s.has_rdoc = true
42
+
43
+ if test ?f, PROJ.test.file
44
+ s.test_file = PROJ.test.file
45
+ else
46
+ s.test_files = PROJ.test.files.to_a
47
+ end
48
+
49
+ # Do any extra stuff the user wants
50
+ PROJ.gem.extras.each do |msg, val|
51
+ case val
52
+ when Proc
53
+ val.call(s.send(msg))
54
+ else
55
+ s.send "#{msg}=", val
56
+ end
57
+ end
58
+ end # Gem::Specification.new
59
+
60
+ # A prerequisites task that all other tasks depend upon
61
+ task :prereqs
62
+
63
+ desc 'Show information about the gem'
64
+ task :debug => 'gem:prereqs' do
65
+ puts PROJ.gem._spec.to_ruby
66
+ end
67
+
68
+ pkg = Rake::PackageTask.new(PROJ.name, PROJ.version) do |pkg|
69
+ pkg.need_tar = PROJ.gem.need_tar
70
+ pkg.need_zip = PROJ.gem.need_zip
71
+ pkg.package_files += PROJ.gem._spec.files
72
+ end
73
+ Rake::Task['gem:package'].instance_variable_set(:@full_comment, nil)
74
+
75
+ gem_file = if PROJ.gem._spec.platform == Gem::Platform::RUBY
76
+ "#{pkg.package_name}.gem"
77
+ else
78
+ "#{pkg.package_name}-#{PROJ.gem._spec.platform}.gem"
79
+ end
80
+
81
+ desc "Build the gem file #{gem_file}"
82
+ task :package => ['gem:prereqs', "#{pkg.package_dir}/#{gem_file}"]
83
+
84
+ file "#{pkg.package_dir}/#{gem_file}" => [pkg.package_dir] + PROJ.gem._spec.files do
85
+ when_writing("Creating GEM") {
86
+ Gem::Builder.new(PROJ.gem._spec).build
87
+ verbose(true) {
88
+ mv gem_file, "#{pkg.package_dir}/#{gem_file}"
89
+ }
90
+ }
91
+ end
92
+
93
+ desc 'Install the gem'
94
+ task :install => [:clobber, 'gem:package'] do
95
+ sh "#{SUDO} #{GEM} install --local pkg/#{PROJ.gem._spec.full_name}"
96
+
97
+ # use this version of the command for rubygems > 1.0.0
98
+ #sh "#{SUDO} #{GEM} install --no-update-sources pkg/#{PROJ.gem._spec.full_name}"
99
+ end
100
+
101
+ desc 'Uninstall the gem'
102
+ task :uninstall do
103
+ installed_list = Gem.source_index.find_name(PROJ.name)
104
+ if installed_list and installed_list.collect { |s| s.version.to_s}.include?(PROJ.version) then
105
+ sh "#{SUDO} #{GEM} uninstall --version '#{PROJ.version}' --ignore-dependencies --executables #{PROJ.name}"
106
+ end
107
+ end
108
+
109
+ desc 'Reinstall the gem'
110
+ task :reinstall => [:uninstall, :install]
111
+
112
+ desc 'Cleanup the gem'
113
+ task :cleanup do
114
+ sh "#{SUDO} #{GEM} cleanup #{PROJ.gem._spec.name}"
115
+ end
116
+
117
+ end # namespace :gem
118
+
119
+ desc 'Alias to gem:package'
120
+ task :gem => 'gem:package'
121
+
122
+ task :clobber => 'gem:clobber_package'
123
+
124
+ remove_desc_for_task %w(gem:clobber_package)
125
+
126
+ # EOF
data/tasks/git.rake ADDED
@@ -0,0 +1,41 @@
1
+ # $Id$
2
+
3
+ if HAVE_GIT
4
+
5
+ namespace :git do
6
+
7
+ # A prerequisites task that all other tasks depend upon
8
+ task :prereqs
9
+
10
+ desc 'Show tags from the Git repository'
11
+ task :show_tags => 'git:prereqs' do |t|
12
+ puts %x/git tag/
13
+ end
14
+
15
+ desc 'Create a new tag in the Git repository'
16
+ task :create_tag => 'git:prereqs' do |t|
17
+ v = ENV['VERSION'] or abort 'Must supply VERSION=x.y.z'
18
+ abort "Versions don't match #{v} vs #{PROJ.version}" if v != PROJ.version
19
+
20
+ tag = "%s-%s" % [PROJ.name, PROJ.version]
21
+ msg = "Creating tag for #{PROJ.name} version #{PROJ.version}"
22
+
23
+ puts "Creating Git tag '#{tag}'"
24
+ unless system "git tag -a -m '#{msg}' #{tag}"
25
+ abort "Tag creation failed"
26
+ end
27
+
28
+ if %x/git remote/ =~ %r/^origin\s*$/
29
+ unless system "git push origin #{tag}"
30
+ abort "Could not push tag to remote Git repository"
31
+ end
32
+ end
33
+ end
34
+
35
+ end # namespace :git
36
+
37
+ task 'gem:release' => 'git:create_tag'
38
+
39
+ end # if HAVE_GIT
40
+
41
+ # EOF
@@ -0,0 +1,49 @@
1
+ # $Id$
2
+
3
+ require 'find'
4
+
5
+ namespace :manifest do
6
+
7
+ desc 'Verify the manifest'
8
+ task :check do
9
+ fn = PROJ.manifest_file + '.tmp'
10
+ files = manifest_files
11
+
12
+ File.open(fn, 'w') {|fp| fp.puts files}
13
+ lines = %x(#{DIFF} -du #{PROJ.manifest_file} #{fn}).split("\n")
14
+ if HAVE_FACETS_ANSICODE and ENV.has_key?('TERM')
15
+ lines.map! do |line|
16
+ case line
17
+ when %r/^(-{3}|\+{3})/; nil
18
+ when %r/^@/; Console::ANSICode.blue line
19
+ when %r/^\+/; Console::ANSICode.green line
20
+ when %r/^\-/; Console::ANSICode.red line
21
+ else line end
22
+ end
23
+ end
24
+ puts lines.compact
25
+ rm fn rescue nil
26
+ end
27
+
28
+ desc 'Create a new manifest'
29
+ task :create do
30
+ files = manifest_files
31
+ unless test(?f, PROJ.manifest_file)
32
+ files << PROJ.manifest_file
33
+ files.sort!
34
+ end
35
+ File.open(PROJ.manifest_file, 'w') {|fp| fp.puts files}
36
+ end
37
+
38
+ task :assert do
39
+ files = manifest_files
40
+ manifest = File.read(PROJ.manifest_file).split($/)
41
+ raise "ERROR: #{PROJ.manifest_file} is out of date" unless files == manifest
42
+ end
43
+
44
+ end # namespace :manifest
45
+
46
+ desc 'Alias to manifest:check'
47
+ task :manifest => 'manifest:check'
48
+
49
+ # EOF
data/tasks/notes.rake ADDED
@@ -0,0 +1,28 @@
1
+ # $Id$
2
+
3
+ if HAVE_BONES
4
+
5
+ desc "Enumerate all annotations"
6
+ task :notes do |t|
7
+ id = if t.application.top_level_tasks.length > 1
8
+ t.application.top_level_tasks.slice!(1..-1).join(' ')
9
+ end
10
+ Bones::AnnotationExtractor.enumerate(
11
+ PROJ, PROJ.notes.tags.join('|'), id, :tag => true)
12
+ end
13
+
14
+ namespace :notes do
15
+ PROJ.notes.tags.each do |tag|
16
+ desc "Enumerate all #{tag} annotations"
17
+ task tag.downcase.to_sym do |t|
18
+ id = if t.application.top_level_tasks.length > 1
19
+ t.application.top_level_tasks.slice!(1..-1).join(' ')
20
+ end
21
+ Bones::AnnotationExtractor.enumerate(PROJ, tag, id)
22
+ end
23
+ end
24
+ end
25
+
26
+ end # if HAVE_BONES
27
+
28
+ # EOF
@@ -0,0 +1,39 @@
1
+ # $Id$
2
+
3
+ # This file does not define any rake tasks. It is used to load some project
4
+ # settings if they are not defined by the user.
5
+
6
+ PROJ.rdoc.exclude << "^#{Regexp.escape(PROJ.manifest_file)}$"
7
+ PROJ.exclude << ["^#{Regexp.escape(PROJ.ann.file)}$",
8
+ "^#{Regexp.escape(PROJ.rdoc.dir)}/",
9
+ "^#{Regexp.escape(PROJ.rcov.dir)}/"]
10
+
11
+ flatten_arrays = lambda do |this,os|
12
+ os.instance_variable_get(:@table).each do |key,val|
13
+ next if key == :dependencies
14
+ case val
15
+ when Array; val.flatten!
16
+ when OpenStruct; this.call(this,val)
17
+ end
18
+ end
19
+ end
20
+ flatten_arrays.call(flatten_arrays,PROJ)
21
+
22
+ PROJ.changes ||= paragraphs_of(PROJ.history_file, 0..1).join("\n\n")
23
+
24
+ PROJ.description ||= paragraphs_of(PROJ.readme_file, 'description').join("\n\n")
25
+
26
+ PROJ.summary ||= PROJ.description.split("\n\n").first
27
+
28
+ PROJ.gem.files ||=
29
+ if test(?f, PROJ.manifest_file)
30
+ files = File.readlines(PROJ.manifest_file).map {|fn| fn.chomp.strip}
31
+ files.delete ''
32
+ files
33
+ else [] end
34
+
35
+ PROJ.gem.executables ||= PROJ.gem.files.find_all {|fn| fn =~ %r/^bin/}
36
+
37
+ PROJ.rdoc.main ||= PROJ.readme_file
38
+
39
+ # EOF