pyre 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ == 0.1.0 / 2008-02-15
2
+
3
+ * 1 major enhancement
4
+ * Existence
@@ -0,0 +1,19 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ lib/pyre.rb
6
+ lib/pyre/campfire.rb
7
+ lib/pyre/room.rb
8
+ spec/pyre_spec.rb
9
+ spec/spec_helper.rb
10
+ tasks/annotations.rake
11
+ tasks/doc.rake
12
+ tasks/gem.rake
13
+ tasks/manifest.rake
14
+ tasks/post_load.rake
15
+ tasks/rubyforge.rake
16
+ tasks/setup.rb
17
+ tasks/spec.rake
18
+ tasks/svn.rake
19
+ tasks/test.rake
@@ -0,0 +1,67 @@
1
+ = pyre
2
+ by Christopher Shea
3
+ http://pyre.rubyforge.org/
4
+
5
+ == DESCRIPTION:
6
+
7
+ Pyre is a library for interacting with Campfire, the web-based group chat site from 37signals.
8
+
9
+ Pyre owes a great deal of debt to Tinder (http://tinder.rubyforge.org)
10
+
11
+ == FEATURES/PROBLEMS:
12
+
13
+ Features:
14
+ * Speak in a Campfire room!
15
+ * Paste in a Campfire room!
16
+ * More reliable determination of whether your login was successful than Tinder!
17
+
18
+ Problems:
19
+ * No public tests (I have them on my box, but you can't see them (passwords!))
20
+ * No listening (yet)
21
+
22
+ Patches awfully welcome.
23
+
24
+ == SYNOPSIS:
25
+
26
+ require 'rubygems'
27
+ require 'pyre'
28
+
29
+ campfire = Pyre::Campfire.new('pyre')
30
+ campfire.login('mycoolemail@example.com', 'anactualpassword')
31
+ room = campfire.find_room_by_name('Pyre Test')
32
+ room.speak('ZOMG! It works!') # automatically joins the room
33
+ room.leave
34
+ campfire.logout
35
+
36
+ == REQUIREMENTS:
37
+
38
+ * mechanize (WWW::Mechanize)
39
+
40
+ == INSTALL:
41
+
42
+ * sudo gem install pyre
43
+
44
+ == LICENSE:
45
+
46
+ (The MIT License)
47
+
48
+ Copyright (c) 2008
49
+
50
+ Permission is hereby granted, free of charge, to any person obtaining
51
+ a copy of this software and associated documentation files (the
52
+ 'Software'), to deal in the Software without restriction, including
53
+ without limitation the rights to use, copy, modify, merge, publish,
54
+ distribute, sublicense, and/or sell copies of the Software, and to
55
+ permit persons to whom the Software is furnished to do so, subject to
56
+ the following conditions:
57
+
58
+ The above copyright notice and this permission notice shall be
59
+ included in all copies or substantial portions of the Software.
60
+
61
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
62
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
63
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
64
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
65
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
66
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
67
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,20 @@
1
+ # Look in the tasks/setup.rb file for the various options that can be
2
+ # configured in this Rakefile. The .rake files in the tasks directory
3
+ # are where the options are used.
4
+
5
+ load 'tasks/setup.rb'
6
+
7
+ ensure_in_path 'lib'
8
+ require 'pyre'
9
+
10
+ task :default => 'spec:run'
11
+
12
+ PROJ.name = 'pyre'
13
+ PROJ.authors = 'Christopher Shea'
14
+ PROJ.email = 'chris@ruby.tie-rack.org'
15
+ PROJ.url = 'http://pyre.rubyforge.org'
16
+ PROJ.rubyforge_name = 'pyre'
17
+
18
+ PROJ.spec_opts << '--color'
19
+
20
+ depend_on('mechanize')
@@ -0,0 +1,24 @@
1
+ # Pyre: Because there isn't a real API for Campfire.
2
+ module Pyre
3
+ # :stopdoc:
4
+ VERSION = '0.1.0'
5
+ LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
6
+ PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
7
+ # :startdoc:
8
+
9
+ # Returns the version string for the library.
10
+ #
11
+ def self.version
12
+ VERSION
13
+ end
14
+ end
15
+
16
+ require 'uri'
17
+ begin
18
+ require 'mechanize'
19
+ rescue LoadError
20
+ require 'rubygems'
21
+ require 'mechanize'
22
+ end
23
+ require 'pyre/campfire'
24
+ require 'pyre/room'
@@ -0,0 +1,60 @@
1
+ module Pyre
2
+ # Pyre::Campfire is for general Campfire tasks. Logging in, logging out, and finding rooms.
3
+ class Campfire
4
+ attr_reader :subdomain, :uri, :agent
5
+
6
+ # Create a new Pyre::Campfire object.
7
+ # Pass in your subdomain and maybe some options.
8
+ # Of course, the only option is whether or not to use ssl.
9
+ # Pass along <tt>:ssl => true</tt> if you need it.
10
+ def initialize(subdomain, options={})
11
+ @subdomain = subdomain
12
+ protocol = 'http'
13
+ protocol << 's' if options[:ssl]
14
+ @uri = "#{protocol}://#{subdomain}.campfirenow.com"
15
+ @agent = WWW::Mechanize.new
16
+ end
17
+
18
+ # Login with the supplied credentials. Returns true on success.
19
+ def login(email, password)
20
+ page = @agent.get(@uri + '/login')
21
+ login_form = page.forms.first
22
+ login_form.fields.name('email_address').value = email
23
+ login_form.fields.name('password').value = password
24
+ @agent.submit(login_form)
25
+ logged_in?
26
+ end
27
+
28
+ # Log out. Returns true on success.
29
+ def logout
30
+ page = @agent.get(@uri + '/logout')
31
+ not logged_in?
32
+ end
33
+
34
+ def logged_in?
35
+ @agent.current_page.links.any? {|link| link.text == 'Logout'} rescue false
36
+ end
37
+
38
+ # Get a list of all the rooms as Pyre::Room objects.
39
+ def rooms
40
+ if logged_in?
41
+ @agent.get(@uri)
42
+ @rooms = @agent.current_page.parser.search('div[@id="rooms"]//h2').map do |h2|
43
+ name = h2.inner_text.strip
44
+ url = h2.at('a')[:href]
45
+ Pyre::Room.new(name, url, self)
46
+ end
47
+ end
48
+ end
49
+
50
+ # Know the name of the room you're looking for? Try it here.
51
+ def find_room_by_name(name)
52
+ @rooms ||= rooms
53
+ @rooms.detect {|room| room.name == name}
54
+ end
55
+
56
+ def inspect #:nodoc:
57
+ "#<#{self.class} \"#{@subdomain}\" \"#{uri}\">"
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,60 @@
1
+ module Pyre
2
+ # Pyre::Room is for interacting with a room!
3
+ class Room
4
+ attr_reader :name
5
+
6
+ def initialize(name, url, campfire) #:nodoc:
7
+ @name = name
8
+ @url = url
9
+ @campfire = campfire
10
+ end
11
+
12
+ # Enter the room. Returns true on success.
13
+ def join
14
+ @campfire.agent.get(@url)
15
+ joined?
16
+ end
17
+
18
+ # Leave the room. Returns true on success.
19
+ def leave
20
+ if joined?
21
+ leave = @campfire.agent.current_page.links.detect {|link| link.text == 'Leave'}
22
+ @campfire.agent.post(leave.uri)
23
+ not joined?
24
+ end
25
+ end
26
+
27
+ # If you're in the room right now.
28
+ def joined?
29
+ @campfire.agent.current_page.at('h1[@id="room_name"]').inner_text == @name rescue false
30
+ end
31
+
32
+ # Send +message+ to the room. Joins the room if necessary.
33
+ def speak(message)
34
+ result = submit_chat_form(message)
35
+ success = (result.uri.to_s == "#{@url}/speak")
36
+ join
37
+ success
38
+ end
39
+
40
+ # Paste +message+ to the room. Joins the room if necessary.
41
+ def paste(message)
42
+ result = submit_chat_form(message, 'paste' => 'true')
43
+ success = (result.links.detect {|link| link.text == 'View paste'} and result.uri.to_s == "#{@url}/speak")
44
+ join
45
+ success
46
+ end
47
+
48
+ def inspect #:nodoc:
49
+ "#<#{self.class} \"#{@name}\" \"#{@url}\">"
50
+ end
51
+
52
+ protected
53
+
54
+ def submit_chat_form(message, options={}) #:nodoc:
55
+ join unless joined?
56
+ speak_form = @campfire.agent.current_page.forms.detect {|form| form.form_node[:id] == 'chat_form'}
57
+ @campfire.agent.post(@url + '/speak', {'message' => message, 't' => Time.now.to_i.to_s}.merge(options))
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,8 @@
1
+ # $Id$
2
+
3
+ require File.join(File.dirname(__FILE__), %w[spec_helper])
4
+
5
+ describe Pyre do
6
+ end
7
+
8
+ # EOF
@@ -0,0 +1,17 @@
1
+ # $Id$
2
+
3
+ require File.expand_path(
4
+ File.join(File.dirname(__FILE__), %w[.. lib pyre]))
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
+ # EOF
@@ -0,0 +1,30 @@
1
+ # $Id$
2
+
3
+ if HAVE_BONES
4
+
5
+ desc "Enumerate all annotations"
6
+ task :notes do
7
+ Bones::AnnotationExtractor.enumerate(
8
+ PROJ, "OPTIMIZE|FIXME|TODO", :tag => true)
9
+ end
10
+
11
+ namespace :notes do
12
+ desc "Enumerate all OPTIMIZE annotations"
13
+ task :optimize do
14
+ Bones::AnnotationExtractor.enumerate(PROJ, "OPTIMIZE")
15
+ end
16
+
17
+ desc "Enumerate all FIXME annotations"
18
+ task :fixme do
19
+ Bones::AnnotationExtractor.enumerate(PROJ, "FIXME")
20
+ end
21
+
22
+ desc "Enumerate all TODO annotations"
23
+ task :todo do
24
+ Bones::AnnotationExtractor.enumerate(PROJ, "TODO")
25
+ end
26
+ end
27
+
28
+ end # if HAVE_BONES
29
+
30
+ # EOF
@@ -0,0 +1,49 @@
1
+ # $Id$
2
+
3
+ require 'rake/rdoctask'
4
+
5
+ namespace :doc do
6
+
7
+ desc 'Generate RDoc documentation'
8
+ Rake::RDocTask.new do |rd|
9
+ rd.main = PROJ.rdoc_main
10
+ rd.rdoc_dir = PROJ.rdoc_dir
11
+
12
+ incl = Regexp.new(PROJ.rdoc_include.join('|'))
13
+ excl = Regexp.new(PROJ.rdoc_exclude.join('|'))
14
+ files = PROJ.files.find_all do |fn|
15
+ case fn
16
+ when excl; false
17
+ when incl; true
18
+ else false end
19
+ end
20
+ rd.rdoc_files.push(*files)
21
+
22
+ title = "#{PROJ.name}-#{PROJ.version} Documentation"
23
+ title = "#{PROJ.rubyforge_name}'s " + title if PROJ.rubyforge_name != title
24
+
25
+ rd.options << "-t #{title}"
26
+ rd.options.concat(PROJ.rdoc_opts)
27
+ end
28
+
29
+ desc 'Generate ri locally for testing'
30
+ task :ri => :clobber_ri do
31
+ sh "#{RDOC} --ri -o ri ."
32
+ end
33
+
34
+ desc 'Remove ri products'
35
+ task :clobber_ri do
36
+ rm_r 'ri' rescue nil
37
+ end
38
+
39
+ end # namespace :doc
40
+
41
+ desc 'Alias to doc:rdoc'
42
+ task :doc => 'doc:rdoc'
43
+
44
+ desc 'Remove all build products'
45
+ task :clobber => %w(doc:clobber_rdoc doc:clobber_ri)
46
+
47
+ remove_desc_for_task %w(doc:clobber_rdoc doc:clobber_ri)
48
+
49
+ # EOF
@@ -0,0 +1,89 @@
1
+ # $Id$
2
+
3
+ require 'rake/gempackagetask'
4
+
5
+ namespace :gem do
6
+
7
+ PROJ.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.dependencies.each do |dep|
19
+ s.add_dependency(*dep)
20
+ end
21
+
22
+ s.files = PROJ.files
23
+ s.executables = PROJ.executables.map {|fn| File.basename(fn)}
24
+ s.extensions = PROJ.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.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.tests.to_a
47
+ end
48
+
49
+ # Do any extra stuff the user wants
50
+ # spec_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
59
+
60
+ desc 'Show information about the gem'
61
+ task :debug do
62
+ puts PROJ.spec.to_ruby
63
+ end
64
+
65
+ Rake::GemPackageTask.new(PROJ.spec) do |pkg|
66
+ pkg.need_tar = PROJ.need_tar
67
+ pkg.need_zip = PROJ.need_zip
68
+ end
69
+
70
+ desc 'Install the gem'
71
+ task :install => [:clobber, :package] do
72
+ sh "#{SUDO} #{GEM} install pkg/#{PROJ.spec.full_name}"
73
+ end
74
+
75
+ desc 'Uninstall the gem'
76
+ task :uninstall do
77
+ sh "#{SUDO} #{GEM} uninstall -v '#{PROJ.version}' -x #{PROJ.name}"
78
+ end
79
+
80
+ end # namespace :gem
81
+
82
+ desc 'Alias to gem:package'
83
+ task :gem => 'gem:package'
84
+
85
+ task :clobber => 'gem:clobber_package'
86
+
87
+ remove_desc_for_task %w(gem:clobber_package)
88
+
89
+ # EOF
@@ -0,0 +1,55 @@
1
+ # $Id$
2
+
3
+ require 'find'
4
+
5
+ namespace :manifest do
6
+
7
+ desc 'Verify the manifest'
8
+ task :check do
9
+ fn = 'Manifest.tmp'
10
+ files = []
11
+ exclude = Regexp.new(PROJ.exclude.join('|'))
12
+ Find.find '.' do |path|
13
+ path.sub! %r/^(\.\/|\/)/o, ''
14
+ next unless test ?f, path
15
+ next if path =~ exclude
16
+ files << path
17
+ end
18
+
19
+ File.open(fn, 'w') {|fp| fp.puts files.sort}
20
+ lines = %x(#{DIFF} -du Manifest.txt #{fn}).split("\n")
21
+ if HAVE_FACETS_ANSICODE and ENV.has_key?('TERM')
22
+ lines.map! do |line|
23
+ case line
24
+ when %r/^(-{3}|\+{3})/; nil
25
+ when %r/^@/; Console::ANSICode.blue line
26
+ when %r/^\+/; Console::ANSICode.green line
27
+ when %r/^\-/; Console::ANSICode.red line
28
+ else line end
29
+ end
30
+ end
31
+ puts lines.compact
32
+ rm fn rescue nil
33
+ end
34
+
35
+ desc 'Create a new manifest'
36
+ task :create do
37
+ fn = 'Manifest.txt'
38
+ files = []
39
+ exclude = Regexp.new(PROJ.exclude.join('|'))
40
+ Find.find '.' do |path|
41
+ path.sub! %r/^(\.\/|\/)/o, ''
42
+ next unless test ?f, path
43
+ next if path =~ exclude
44
+ files << path
45
+ end
46
+
47
+ files << fn unless test ?f, fn
48
+ File.open(fn, 'w') {|fp| fp.puts files.sort}
49
+ end
50
+ end # namespace :manifest
51
+
52
+ desc 'Alias to manifest:check'
53
+ task :manifest => 'manifest:check'
54
+
55
+ # EOF
@@ -0,0 +1,18 @@
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
+ unless PROJ.changes
7
+ PROJ.changes = paragraphs_of('History.txt', 0..1).join("\n\n")
8
+ end
9
+
10
+ unless PROJ.description
11
+ PROJ.description = paragraphs_of('README.txt', 'description').join("\n\n")
12
+ end
13
+
14
+ unless PROJ.summary
15
+ PROJ.summary = PROJ.description.split('.').first
16
+ end
17
+
18
+ # EOF
@@ -0,0 +1,57 @@
1
+ # $Id$
2
+
3
+ if PROJ.rubyforge_name && HAVE_RUBYFORGE
4
+
5
+ require 'rubyforge'
6
+ require 'rake/contrib/sshpublisher'
7
+
8
+ namespace :gem do
9
+ desc 'Package and upload to RubyForge'
10
+ task :release => [:clobber, :package] do |t|
11
+ v = ENV['VERSION'] or abort 'Must supply VERSION=x.y.z'
12
+ abort "Versions don't match #{v} vs #{PROJ.version}" if v != PROJ.version
13
+ pkg = "pkg/#{PROJ.spec.full_name}"
14
+
15
+ if $DEBUG then
16
+ puts "release_id = rf.add_release #{PROJ.rubyforge_name.inspect}, #{PROJ.name.inspect}, #{PROJ.version.inspect}, \"#{pkg}.tgz\""
17
+ puts "rf.add_file #{PROJ.rubyforge_name.inspect}, #{PROJ.name.inspect}, release_id, \"#{pkg}.gem\""
18
+ end
19
+
20
+ rf = RubyForge.new
21
+ puts 'Logging in'
22
+ rf.login
23
+
24
+ c = rf.userconfig
25
+ c['release_notes'] = PROJ.description if PROJ.description
26
+ c['release_changes'] = PROJ.changes if PROJ.changes
27
+ c['preformatted'] = true
28
+
29
+ files = [(PROJ.need_tar ? "#{pkg}.tgz" : nil),
30
+ (PROJ.need_zip ? "#{pkg}.zip" : nil),
31
+ "#{pkg}.gem"].compact
32
+
33
+ puts "Releasing #{PROJ.name} v. #{PROJ.version}"
34
+ rf.add_release PROJ.rubyforge_name, PROJ.name, PROJ.version, *files
35
+ end
36
+ end # namespace :gem
37
+
38
+
39
+ namespace :doc do
40
+ desc "Publish RDoc to RubyForge"
41
+ task :release => %w(doc:clobber_rdoc doc:rdoc) do
42
+ config = YAML.load(
43
+ File.read(File.expand_path('~/.rubyforge/user-config.yml'))
44
+ )
45
+
46
+ host = "#{config['username']}@rubyforge.org"
47
+ remote_dir = "/var/www/gforge-projects/#{PROJ.rubyforge_name}/"
48
+ remote_dir << PROJ.rdoc_remote_dir if PROJ.rdoc_remote_dir
49
+ local_dir = PROJ.rdoc_dir
50
+
51
+ Rake::SshDirPublisher.new(host, remote_dir, local_dir).upload
52
+ end
53
+ end # namespace :doc
54
+
55
+ end # if HAVE_RUBYFORGE
56
+
57
+ # EOF
@@ -0,0 +1,189 @@
1
+ # $Id$
2
+
3
+ require 'rubygems'
4
+ require 'rake'
5
+ require 'fileutils'
6
+ require 'ostruct'
7
+
8
+ PROJ = OpenStruct.new
9
+
10
+ PROJ.name = nil
11
+ PROJ.summary = nil
12
+ PROJ.description = nil
13
+ PROJ.changes = nil
14
+ PROJ.authors = nil
15
+ PROJ.email = nil
16
+ PROJ.url = nil
17
+ PROJ.version = ENV['VERSION'] || '0.0.0'
18
+ PROJ.rubyforge_name = nil
19
+ PROJ.exclude = %w(tmp$ bak$ ~$ CVS .svn/ ^pkg/ ^doc/)
20
+
21
+ # Rspec
22
+ PROJ.specs = FileList['spec/**/*_spec.rb']
23
+ PROJ.spec_opts = []
24
+
25
+ # Test::Unit
26
+ PROJ.tests = FileList['test/**/test_*.rb']
27
+ PROJ.test_file = 'test/all.rb'
28
+ PROJ.test_opts = []
29
+
30
+ # Rcov
31
+ PROJ.rcov_opts = ['--sort', 'coverage', '-T']
32
+
33
+ # Rdoc
34
+ PROJ.rdoc_opts = []
35
+ PROJ.rdoc_include = %w(^lib/ ^bin/ ^ext/ .txt$)
36
+ PROJ.rdoc_exclude = %w(extconf.rb$ ^Manifest.txt$)
37
+ PROJ.rdoc_main = 'README.txt'
38
+ PROJ.rdoc_dir = 'doc'
39
+ PROJ.rdoc_remote_dir = nil
40
+
41
+ # Extensions
42
+ PROJ.extensions = FileList['ext/**/extconf.rb']
43
+ PROJ.ruby_opts = %w(-w)
44
+ PROJ.libs = []
45
+ %w(lib ext).each {|dir| PROJ.libs << dir if test ?d, dir}
46
+
47
+ # Gem Packaging
48
+ PROJ.files =
49
+ if test ?f, 'Manifest.txt'
50
+ files = File.readlines('Manifest.txt').map {|fn| fn.chomp.strip}
51
+ files.delete ''
52
+ files
53
+ else [] end
54
+ PROJ.executables = PROJ.files.find_all {|fn| fn =~ %r/^bin/}
55
+ PROJ.dependencies = []
56
+ PROJ.need_tar = true
57
+ PROJ.need_zip = false
58
+
59
+ # File Annotations
60
+ PROJ.annotation_exclude = []
61
+ PROJ.annotation_extensions = %w(.txt .rb .erb) << ''
62
+
63
+ # Subversion Repository
64
+ PROJ.svn = false
65
+ PROJ.svn_root = nil
66
+ PROJ.svn_trunk = 'trunk'
67
+ PROJ.svn_tags = 'tags'
68
+ PROJ.svn_branches = 'branches'
69
+
70
+ # Load the other rake files in the tasks folder
71
+ rakefiles = Dir.glob('tasks/*.rake').sort
72
+ rakefiles.unshift(rakefiles.delete('tasks/post_load.rake')).compact!
73
+ import(*rakefiles)
74
+
75
+ # Setup some constants
76
+ WIN32 = %r/djgpp|(cyg|ms|bcc)win|mingw/ =~ RUBY_PLATFORM unless defined? WIN32
77
+
78
+ DEV_NULL = WIN32 ? 'NUL:' : '/dev/null'
79
+
80
+ def quiet( &block )
81
+ io = [STDOUT.dup, STDERR.dup]
82
+ STDOUT.reopen DEV_NULL
83
+ STDERR.reopen DEV_NULL
84
+ block.call
85
+ ensure
86
+ STDOUT.reopen io.first
87
+ STDERR.reopen io.last
88
+ end
89
+
90
+ DIFF = if WIN32 then 'diff.exe'
91
+ else
92
+ if quiet {system "gdiff", __FILE__, __FILE__} then 'gdiff'
93
+ else 'diff' end
94
+ end unless defined? DIFF
95
+
96
+ SUDO = if WIN32 then ''
97
+ else
98
+ if quiet {system 'which sudo'} then 'sudo'
99
+ else '' end
100
+ end
101
+
102
+ RCOV = WIN32 ? 'rcov.cmd' : 'rcov'
103
+ GEM = WIN32 ? 'gem.cmd' : 'gem'
104
+
105
+ %w(rcov spec/rake/spectask rubyforge bones facets/ansicode).each do |lib|
106
+ begin
107
+ require lib
108
+ Object.instance_eval {const_set "HAVE_#{lib.tr('/','_').upcase}", true}
109
+ rescue LoadError
110
+ Object.instance_eval {const_set "HAVE_#{lib.tr('/','_').upcase}", false}
111
+ end
112
+ end
113
+
114
+ # Reads a file at +path+ and spits out an array of the +paragraphs+
115
+ # specified.
116
+ #
117
+ # changes = paragraphs_of('History.txt', 0..1).join("\n\n")
118
+ # summary, *description = paragraphs_of('README.txt', 3, 3..8)
119
+ #
120
+ def paragraphs_of( path, *paragraphs )
121
+ title = String === paragraphs.first ? paragraphs.shift : nil
122
+ ary = File.read(path).delete("\r").split(/\n\n+/)
123
+
124
+ result = if title
125
+ tmp, matching = [], false
126
+ rgxp = %r/^=+\s*#{Regexp.escape(title)}/i
127
+ paragraphs << (0..-1) if paragraphs.empty?
128
+
129
+ ary.each do |val|
130
+ if val =~ rgxp
131
+ break if matching
132
+ matching = true
133
+ rgxp = %r/^=+/i
134
+ elsif matching
135
+ tmp << val
136
+ end
137
+ end
138
+ tmp
139
+ else ary end
140
+
141
+ result.values_at(*paragraphs)
142
+ end
143
+
144
+ # Adds the given gem _name_ to the current project's dependency list. An
145
+ # optional gem _version_ can be given. If omitted, the newest gem version
146
+ # will be used.
147
+ #
148
+ def depend_on( name, version = nil )
149
+ spec = Gem.source_index.find_name(name).last
150
+ version = spec.version.to_s if version.nil? and !spec.nil?
151
+
152
+ PROJ.dependencies << (version.nil? ? [name] : [name, ">= #{version}"])
153
+ end
154
+
155
+ # Adds the given arguments to the include path if they are not already there
156
+ #
157
+ def ensure_in_path( *args )
158
+ args.each do |path|
159
+ path = File.expand_path(path)
160
+ $:.unshift(path) if test(?d, path) and not $:.include?(path)
161
+ end
162
+ end
163
+
164
+ # Find a rake task using the task name and remove any description text. This
165
+ # will prevent the task from being displayed in the list of available tasks.
166
+ #
167
+ def remove_desc_for_task( names )
168
+ Array(names).each do |task_name|
169
+ task = Rake.application.tasks.find {|t| t.name == task_name}
170
+ next if task.nil?
171
+ task.instance_variable_set :@comment, nil
172
+ end
173
+ end
174
+
175
+ # Change working directories to _dir_, call the _block_ of code, and then
176
+ # change back to the original working directory (the current directory when
177
+ # this method was called).
178
+ #
179
+ def in_directory( dir, &block )
180
+ curdir = pwd
181
+ begin
182
+ cd dir
183
+ return block.call
184
+ ensure
185
+ cd curdir
186
+ end
187
+ end
188
+
189
+ # EOF
@@ -0,0 +1,43 @@
1
+ # $Id$
2
+
3
+ if HAVE_SPEC_RAKE_SPECTASK
4
+
5
+ namespace :spec do
6
+
7
+ desc 'Run all specs with basic output'
8
+ Spec::Rake::SpecTask.new(:run) do |t|
9
+ t.spec_opts = PROJ.spec_opts
10
+ t.spec_files = PROJ.specs
11
+ t.libs += PROJ.libs
12
+ end
13
+
14
+ desc 'Run all specs with text output'
15
+ Spec::Rake::SpecTask.new(:specdoc) do |t|
16
+ t.spec_opts = PROJ.spec_opts + ['--format', 'specdoc']
17
+ t.spec_files = PROJ.specs
18
+ t.libs += PROJ.libs
19
+ end
20
+
21
+ if HAVE_RCOV
22
+ desc 'Run all specs with RCov'
23
+ Spec::Rake::SpecTask.new(:rcov) do |t|
24
+ t.spec_opts = PROJ.spec_opts
25
+ t.spec_files = PROJ.specs
26
+ t.libs += PROJ.libs
27
+ t.rcov = true
28
+ t.rcov_opts = PROJ.rcov_opts + ['--exclude', 'spec']
29
+ end
30
+ end
31
+
32
+ end # namespace :spec
33
+
34
+ desc 'Alias to spec:run'
35
+ task :spec => 'spec:run'
36
+
37
+ task :clobber => 'spec:clobber_rcov' if HAVE_RCOV
38
+
39
+ remove_desc_for_task %w(spec:clobber_rcov)
40
+
41
+ end # if HAVE_SPEC_RAKE_SPECTASK
42
+
43
+ # EOF
@@ -0,0 +1,44 @@
1
+ # $Id$
2
+
3
+
4
+ if PROJ.svn and system("svn --version 2>&1 > #{DEV_NULL}")
5
+
6
+ unless PROJ.svn_root
7
+ info = %x/svn info ./
8
+ m = %r/^Repository Root:\s+(.*)$/.match(info)
9
+ PROJ.svn_root = (m.nil? ? '' : m[1])
10
+ end
11
+ PROJ.svn_root = File.join(PROJ.svn_root, PROJ.svn) if String === PROJ.svn
12
+
13
+ namespace :svn do
14
+
15
+ desc 'Show tags from the SVN repository'
16
+ task :show_tags do |t|
17
+ tags = %x/svn list #{File.join(PROJ.svn_root, PROJ.svn_tags)}/
18
+ tags.gsub!(%r/\/$/, '')
19
+ puts tags
20
+ end
21
+
22
+ desc 'Create a new tag in the SVN repository'
23
+ task :create_tag do |t|
24
+ v = ENV['VERSION'] or abort 'Must supply VERSION=x.y.z'
25
+ abort "Versions don't match #{v} vs #{PROJ.version}" if v != PROJ.version
26
+
27
+ trunk = File.join(PROJ.svn_root, PROJ.svn_trunk)
28
+ tag = "%s-%s" % [PROJ.name, PROJ.version]
29
+ tag = File.join(PROJ.svn_root, PROJ.svn_tags, tag)
30
+ msg = "Creating tag for #{PROJ.name} version #{PROJ.version}"
31
+
32
+ puts "Creating SVN tag '#{tag}'"
33
+ unless system "svn cp -m '#{msg}' #{trunk} #{tag}"
34
+ abort "Tag creation failed"
35
+ end
36
+ end
37
+
38
+ end # namespace :svn
39
+
40
+ task 'gem:release' => 'svn:create_tag'
41
+
42
+ end # if PROJ.svn
43
+
44
+ # EOF
@@ -0,0 +1,40 @@
1
+ # $Id$
2
+
3
+ require 'rake/testtask'
4
+
5
+ namespace :test do
6
+
7
+ Rake::TestTask.new(:run) do |t|
8
+ t.libs = PROJ.libs
9
+ t.test_files = if test ?f, PROJ.test_file then [PROJ.test_file]
10
+ else PROJ.tests end
11
+ t.ruby_opts += PROJ.ruby_opts
12
+ t.ruby_opts += PROJ.test_opts
13
+ end
14
+
15
+ if HAVE_RCOV
16
+ desc 'Run rcov on the unit tests'
17
+ task :rcov => :clobber_rcov do
18
+ opts = PROJ.rcov_opts.join(' ')
19
+ files = if test ?f, PROJ.test_file then [PROJ.test_file]
20
+ else PROJ.tests end
21
+ files = files.join(' ')
22
+ sh "#{RCOV} #{files} #{opts}"
23
+ end
24
+
25
+ desc 'Remove rcov products'
26
+ task :clobber_rcov do
27
+ rm_r 'coverage' rescue nil
28
+ end
29
+ end
30
+
31
+ end # namespace :test
32
+
33
+ desc 'Alias to test:run'
34
+ task :test => 'test:run'
35
+
36
+ task :clobber => 'test:clobber_rcov' if HAVE_RCOV
37
+
38
+ remove_desc_for_task %w(test:clobber_rcov)
39
+
40
+ # EOF
@@ -0,0 +1,53 @@
1
+ require 'test/unit'
2
+
3
+ require 'pyre'
4
+
5
+ class TestPyre < Test::Unit::TestCase
6
+ def setup
7
+ @pyre_campfire = Pyre::Campfire.new('pyre')
8
+ @pyre_email = 'bot@tie-rack.org'
9
+ @pyre_password = 'pyre99bts'
10
+ end
11
+
12
+ def login
13
+ @pyre_campfire.login(@pyre_email, @pyre_password)
14
+ end
15
+
16
+ def test_001_subdomain
17
+ assert_equal('pyre', @pyre_campfire.subdomain)
18
+ end
19
+
20
+ def test_002_uri
21
+ assert_equal('http://pyre.campfirenow.com', @pyre_campfire.uri)
22
+ end
23
+
24
+ def test_003_agent
25
+ assert_kind_of(WWW::Mechanize, @pyre_campfire.instance_variable_get('@agent'))
26
+ end
27
+
28
+ def test_004_login
29
+ assert_equal(false, @pyre_campfire.logged_in?)
30
+ login
31
+ assert(@pyre_campfire.logged_in?, 'Campfire#login failed.')
32
+ end
33
+
34
+ def test_005_login_fails_with_bad_credentials
35
+ assert_equal(false, @pyre_campfire.logged_in?)
36
+ @pyre_campfire.login('not an email', 'not a password')
37
+ assert_equal(false, @pyre_campfire.logged_in?, 'Campfire#login succeeded with bad credentials!')
38
+ end
39
+
40
+ def test_006_rooms
41
+ login
42
+ rooms = @pyre_campfire.rooms
43
+ assert_kind_of(Array, rooms)
44
+ assert_equal(false, rooms.empty?, 'Rooms returns an empty array.')
45
+ end
46
+
47
+ def test_007_logout
48
+ login
49
+ assert(@pyre_campfire.logged_in?, 'Campfire#login failed.')
50
+ @pyre_campfire.logout
51
+ assert_equal(false, @pyre_campfire.logged_in?, 'Campfire#logout failed!')
52
+ end
53
+ end
@@ -0,0 +1,42 @@
1
+ require 'test/unit'
2
+
3
+ require 'pyre'
4
+
5
+ class TestPyreRooms < Test::Unit::TestCase
6
+ def setup
7
+ @pyre_campfire = Pyre::Campfire.new('pyre')
8
+ @pyre_email = 'bot@tie-rack.org'
9
+ @pyre_password = 'pyre99bts'
10
+
11
+ @pyre_campfire.login(@pyre_email, @pyre_password)
12
+
13
+ @pyre_test = @pyre_campfire.find_room_by_name('Pyre Test')
14
+ end
15
+
16
+ def teardown
17
+ @pyre_campfire.logout
18
+ end
19
+
20
+ def test_001_find_room_by_name
21
+ assert_kind_of(Pyre::Room, @pyre_test)
22
+ end
23
+
24
+ def test_002_enter_and_leave_room
25
+ assert_equal(false, @pyre_test.joined?, 'Somehow in the room before joining!')
26
+ @pyre_test.join
27
+ assert(@pyre_test.joined?, 'Room#join failed')
28
+ @pyre_test.leave
29
+ assert_equal(false, @pyre_test.joined?, 'Room#leave failed!')
30
+ assert(@pyre_campfire.logged_in?, 'Room#leave did\'t redirect.')
31
+ end
32
+
33
+ def test_003_interact_with_room
34
+ @pyre_test.join
35
+ assert(@pyre_test.speak("I am speaking at #{Time.now}"))
36
+ assert(@pyre_test.joined?, 'Didn\'t return to room after speaking!')
37
+ assert(@pyre_test.paste("I am pasting\n at #{Time.now}"))
38
+ assert(@pyre_test.joined?, 'Didn\'t return to room after pasting!')
39
+ @pyre_test.leave
40
+ assert_equal(false, @pyre_test.joined?, 'Room#leave failed!')
41
+ end
42
+ end
@@ -0,0 +1,47 @@
1
+ require 'test/unit'
2
+
3
+ require 'pyre'
4
+
5
+ class TestPyreSSL < Test::Unit::TestCase
6
+ def setup
7
+ @qval_campfire = Pyre::Campfire.new('qval', :ssl => true)
8
+ @qval_email = 'chris@myqval.com'
9
+ @qval_password = 'd0rkc0ntr0l'
10
+
11
+ @qval_campfire.login(@qval_email, @qval_password)
12
+ end
13
+
14
+ def teardown
15
+ @qval_campfire.logout
16
+ end
17
+
18
+ def test_001_uri
19
+ assert_equal('https://qval.campfirenow.com', @qval_campfire.uri)
20
+ end
21
+
22
+ def test_002_rooms
23
+ rooms = @qval_campfire.rooms
24
+ assert_kind_of(Array, rooms)
25
+ assert_equal(false, rooms.empty?)
26
+ assert_kind_of(Pyre::Room, rooms.first)
27
+ end
28
+
29
+ def test_004_find_room_by_name
30
+ assert_not_nil(@qval_campfire.find_room_by_name('Qval Development'))
31
+ assert_nil(@qval_campfire.find_room_by_name('Chris is the new owner of Qval'))
32
+ end
33
+
34
+ def test_005_interact_with_room
35
+ tinder_test = @qval_campfire.find_room_by_name('Tinder Test')
36
+ assert_equal(true, tinder_test.join)
37
+ assert_equal(true, tinder_test.speak('Hello from the test suite!'))
38
+ tinder_test.leave
39
+ end
40
+
41
+ def test_006_paste
42
+ tinder_test = @qval_campfire.find_room_by_name('Tinder Test')
43
+ assert_equal(true, tinder_test.join)
44
+ assert_equal(true, tinder_test.paste("Two Liner\nat #{Time.now}"))
45
+ tinder_test.leave
46
+ end
47
+ end
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pyre
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Christopher Shea
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-02-16 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: mechanize
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.7.0
23
+ version:
24
+ description: Pyre is a library for interacting with Campfire, the web-based group chat site from 37signals. Pyre owes a great deal of debt to Tinder (http://tinder.rubyforge.org)
25
+ email: chris@ruby.tie-rack.org
26
+ executables: []
27
+
28
+ extensions: []
29
+
30
+ extra_rdoc_files:
31
+ - History.txt
32
+ - README.txt
33
+ files:
34
+ - History.txt
35
+ - Manifest.txt
36
+ - README.txt
37
+ - Rakefile
38
+ - lib/pyre.rb
39
+ - lib/pyre/campfire.rb
40
+ - lib/pyre/room.rb
41
+ - spec/pyre_spec.rb
42
+ - spec/spec_helper.rb
43
+ - tasks/annotations.rake
44
+ - tasks/doc.rake
45
+ - tasks/gem.rake
46
+ - tasks/manifest.rake
47
+ - tasks/post_load.rake
48
+ - tasks/rubyforge.rake
49
+ - tasks/setup.rb
50
+ - tasks/spec.rake
51
+ - tasks/svn.rake
52
+ - tasks/test.rake
53
+ has_rdoc: true
54
+ homepage: http://pyre.rubyforge.org
55
+ post_install_message:
56
+ rdoc_options:
57
+ - --main
58
+ - README.txt
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: "0"
66
+ version:
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: "0"
72
+ version:
73
+ requirements: []
74
+
75
+ rubyforge_project: pyre
76
+ rubygems_version: 1.0.1
77
+ signing_key:
78
+ specification_version: 2
79
+ summary: Pyre is a library for interacting with Campfire, the web-based group chat site from 37signals
80
+ test_files:
81
+ - test/test_pyre_private.rb
82
+ - test/test_pyre_rooms_private.rb
83
+ - test/test_ssl_private.rb