happygiraffe-svenbot 0.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/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ Copyright (C) 2008 by Dominic Mitchell
2
+
3
+ Redistribution and use in source and binary forms, with or without
4
+ modification, are permitted provided that the following conditions
5
+ are met:
6
+
7
+ 1. Redistributions of source code must retain the above copyright
8
+ notice, this list of conditions and the following disclaimer.
9
+ 2. Redistributions in binary form must reproduce the above copyright
10
+ notice, this list of conditions and the following disclaimer in the
11
+ documentation and/or other materials provided with the distribution.
12
+
13
+ THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16
+ ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23
+ SUCH DAMAGE.
data/Manifest ADDED
@@ -0,0 +1,19 @@
1
+ bin/svenbot
2
+ bin/svenbot-notify
3
+ lib/svenbot/bot.rb
4
+ lib/svenbot/commit.rb
5
+ lib/svenbot/message.rb
6
+ lib/svenbot/repo.rb
7
+ lib/svenbot/user.rb
8
+ lib/svenbot/user_manager.rb
9
+ LICENSE
10
+ Rakefile
11
+ README.textile
12
+ svenbot.gemspec
13
+ test/svenbot/bot_test.rb
14
+ test/svenbot/commit_test.rb
15
+ test/svenbot/message_test.rb
16
+ test/svenbot/repo_test.rb
17
+ test/svenbot/user_manager_test.rb
18
+ test/svenbot/user_test.rb
19
+ Manifest
data/README.textile ADDED
@@ -0,0 +1,7 @@
1
+ h1. svenbot
2
+
3
+ Svenbot is a very simple Jabber bot. It listens to commits through a subversion hook and sends out messages to anybody who has registered an interest in such things.
4
+
5
+ h3. TODO
6
+
7
+ * Only send out notifications to available people.
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/clean'
4
+ require 'rake/rdoctask'
5
+
6
+ gem 'echoe'
7
+ require 'echoe'
8
+
9
+ Echoe.new("svenbot", "0.0.1") do |p|
10
+ p.author = 'Dominic Mitchell'
11
+ p.email = 'dom@happygiraffe.net'
12
+ p.url = 'http://github.com/happygiraffe/svenbot'
13
+ p.description = 'A jabber bot for subversion commits.'
14
+ p.need_zip = true
15
+ p.ignore_pattern = /^(pkg|doc|nbproject)|\.git/
16
+ p.retain_gemspec = true
17
+ end
data/bin/svenbot ADDED
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/ruby
2
+ #
3
+ # Fire up a new svenbot.
4
+
5
+ require 'svenbot/bot'
6
+ require 'svenbot/commit'
7
+ require 'svenbot/repo'
8
+ require 'yaml'
9
+
10
+ gem 'xmpp4r-simple'
11
+ require 'xmpp4r-simple'
12
+
13
+ Jabber::debug = true if ENV['JABBER_DEBUG']
14
+
15
+ repo = Svenbot::Repo.new(ARGV[0])
16
+ if !File.directory?(repo.dir)
17
+ warn "repo '#{repo.dir}' does not exist"
18
+ exit 1
19
+ end
20
+ repo.make_meta_dir
21
+
22
+ bot = Svenbot::Bot.new(repo)
23
+
24
+ commits = []
25
+ Thread.new do
26
+ sock_path = "#{repo.meta_dir}/sock"
27
+ # XXX Check for currently running svnbot
28
+ File.delete(sock_path) if File.exist?(sock_path)
29
+ sock = UNIXServer.new sock_path
30
+ loop do
31
+ s1 = sock.accept
32
+ msg = s1.recvfrom(256)[0]
33
+ # XXX A thread safe queue would be good.
34
+ commits << Svenbot::Commit.from(repo, msg)
35
+ end
36
+ end
37
+
38
+ config = YAML.load_file("#{repo.meta_dir}/config.yml")
39
+
40
+ xmpp = Jabber::Simple.new(config[:connect_jid], config[:connect_password])
41
+ loop do
42
+ xmpp.received_messages do |msg|
43
+ case msg.body
44
+ when /^quit\b/
45
+ xmpp.deliver(msg.from, "bye bye")
46
+ xmpp.disconnect
47
+ exit
48
+ else
49
+ result = bot.dispatch_cmd(msg)
50
+ xmpp.deliver(result.to, result)
51
+ end
52
+ end
53
+ while !commits.empty?
54
+ bot.commit_messages(commits.shift).each do |msg|
55
+ xmpp.deliver(msg.to, msg)
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/ruby
2
+ #
3
+ # Send a message to the bot.
4
+
5
+ require 'socket'
6
+ require 'svenbot/repo'
7
+
8
+ repo = Svenbot::Repo.new(ARGV[0])
9
+ rev = ARGV[1]
10
+
11
+ sock = UNIXSocket.open "#{repo.meta_dir}/sock"
12
+ sock.send rev, 0
13
+ sock.close
@@ -0,0 +1,66 @@
1
+ require 'svenbot/message'
2
+ require 'svenbot/user_manager'
3
+
4
+ module Svenbot
5
+ class Bot
6
+ include Message
7
+
8
+ def initialize(repo)
9
+ @repo = repo
10
+ @user_manager = UserManager.new
11
+ end
12
+
13
+ def dispatch_cmd(msg)
14
+ cmd, args = msg.body.split(' ', 2)
15
+ method = "cmd_#{cmd}".to_sym
16
+ if self.class.method_defined? method
17
+ return self.send(method, msg.from, args)
18
+ else
19
+ return html_message("unknown command '#{cmd}'").set_to(msg.from)
20
+ end
21
+ end
22
+
23
+ def cmd_help(jid, unused)
24
+ commands = self.class.public_instance_methods.grep(/^cmd_/).
25
+ collect { |m| m.sub( /^cmd_/, '' ) }.sort.join(', ')
26
+ return html_message("available commands: #{commands}").set_to(jid)
27
+ end
28
+
29
+ def cmd_register(jid, path)
30
+ @user_manager.register jid, path
31
+ paths = @user_manager.paths_for jid
32
+ msg = "You will get commits for: #{paths.join(', ')}"
33
+ return html_message(msg).set_to(jid)
34
+ end
35
+
36
+
37
+ # Return a list of paths you are interested in commits for.
38
+ def cmd_list(jid, unused)
39
+ paths = @user_manager.paths_for(jid)
40
+ if paths.empty?
41
+ msg = 'You are not listening to any commits'
42
+ else
43
+ msg = "You are listening for commits to: #{paths.join(', ')}"
44
+ end
45
+ return html_message(msg).set_to(jid)
46
+ end
47
+
48
+ # Remove messages about commits to a certain +path+. If not specified,
49
+ # +path+ defaults to "/".
50
+ def cmd_unregister(jid, path)
51
+ @user_manager.unregister jid, path
52
+ msg = "You will no longer get commits for: #{path}"
53
+ return html_message(msg).set_to(jid)
54
+ end
55
+
56
+ # Return a list of messages to send out for +commit+.
57
+ def commit_messages(commit)
58
+ msg = "#{commit.user} committed #{commit.id}: #{commit.message}"
59
+ @user_manager.users_for(commit.path_prefix).collect do |jid|
60
+ html_message(msg).set_to(jid)
61
+ end
62
+ end
63
+
64
+ end
65
+
66
+ end
@@ -0,0 +1,44 @@
1
+ module Svenbot
2
+ # Representation of a commit message
3
+ class Commit
4
+ # Identifier for this commit
5
+ attr_reader :id
6
+ # Who made this commit?
7
+ attr_reader :user
8
+ # What part of the repository did this affect?
9
+ attr_reader :path_prefix
10
+ # Why was this commit made?
11
+ attr_reader :message
12
+
13
+ # Create a new commit.
14
+ def initialize(id, user, path_prefix, message)
15
+ @id = id
16
+ @user = user
17
+ @path_prefix = path_prefix
18
+ @message = message
19
+ end
20
+
21
+ # Populate a new commit object from a repository
22
+ def self.from(repo, id)
23
+ user = `svnlook author '#{repo.dir}' -r '#{id}'`.chomp
24
+ message = `svnlook log '#{repo.dir}' -r '#{id}'`.chomp
25
+ paths = `svnlook changed '#{repo.dir}' -r '#{id}'`.split(/\n/)
26
+ paths.collect! { |p| p.sub(/^..../, '').chomp }
27
+ return Commit.new(id, user, pick_prefix(paths), message)
28
+ end
29
+
30
+ private
31
+
32
+ # Work out the common prefix of these paths.
33
+ # http://newsgroups.derkeiler.com/Archive/Comp/comp.lang.ruby/2007-08/msg00370.html
34
+ def self.pick_prefix(paths)
35
+ # A list of indexes of differing characters in a & b.
36
+ s = []
37
+ a, b = paths.max.split(//), paths.min.split(//)
38
+ # Note the index of each character that differs.
39
+ a.each_with_index{ |val,i| s << i if val != b[i] }
40
+ # Extract from the first char to the first differing char.
41
+ return (0...s[0]).collect { |j| a[j] }.join
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,21 @@
1
+ require 'rubygems'
2
+
3
+ gem 'xmpp4r'
4
+ require 'xmpp4r/message'
5
+ require 'xmpp4r/xhtml/html'
6
+
7
+ module Svenbot
8
+ # A factory for messages.
9
+ module Message
10
+ # Create a Jabber::Message with both HTML and text body. Pass in a
11
+ # string of HTML.
12
+ def html_message(contents)
13
+ msg = Jabber::Message.new
14
+ msg.type = :chat
15
+ html = Jabber::XHTML::HTML.new(contents)
16
+ msg.add(html)
17
+ msg.body = html.to_text
18
+ return msg
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,23 @@
1
+ module Svenbot
2
+ # A subversion repository on the filesystem.
3
+ class Repo
4
+ # The directory the repository lives in.
5
+ attr_reader :dir
6
+
7
+ # Create a new Repo.
8
+ def initialize(dir)
9
+ @dir = dir
10
+ end
11
+
12
+ # Return a directory within the repository for use by svenbot. Defaults
13
+ # to a subdirectory "svenbot".
14
+ def meta_dir
15
+ return "#{dir}/svenbot"
16
+ end
17
+
18
+ # Create the meta directory if needed.
19
+ def make_meta_dir
20
+ Dir.mkdir(meta_dir) unless File.directory?(meta_dir)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,26 @@
1
+ module Svenbot
2
+ # A user who wishes to receive notifications about commits.
3
+ class User
4
+ # The jabber ID of the user.
5
+ attr_accessor :jid
6
+ # A list of paths that the user wishes to be notified about.
7
+ attr_accessor :paths
8
+
9
+ # Create a new user +jid+ with no paths to monitor.
10
+ def initialize(jid)
11
+ @jid = jid
12
+ @paths = []
13
+ end
14
+
15
+ # Add a path to the list monitored.
16
+ def <<(path)
17
+ @paths << path
18
+ return self
19
+ end
20
+
21
+ # Remove a path from the list monitored.
22
+ def delete(path)
23
+ @paths.delete path
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,80 @@
1
+ require 'set'
2
+ require 'svenbot/user'
3
+
4
+ module Svenbot
5
+ # Keep state tracking who is interested in what commits. Users can register
6
+ # or unregister for paths. Commits to those paths will result in a message
7
+ # being emitted.
8
+ class UserManager
9
+ # A hash of registered users.
10
+ attr_reader :users
11
+ # A hash of paths we are interested in, and which users map to them.
12
+ attr_reader :paths
13
+
14
+ # Create a new UserManager instance
15
+ def initialize
16
+ @users = {}
17
+ @paths = {}
18
+ end
19
+
20
+ # Register +jid+ as interested in commits to +path+. If path isn't
21
+ # specified, default to "everything" (i.e. "/")
22
+ def register(jid, path)
23
+ user = get_user(jid)
24
+ user << path
25
+ add_path_for_user path, user
26
+ end
27
+
28
+ # Remove messages about commits to a certain +path+.
29
+ def unregister(jid, path)
30
+ user = @users.delete jid
31
+ remove_path_for_user path, user if user
32
+ end
33
+
34
+ # Return a sorted list of paths that +jid+ has registered.
35
+ def paths_for(jid)
36
+ get_user(jid).paths.sort
37
+ end
38
+
39
+ # Return a sorted list of jids that have registered an interest in +path+
40
+ def users_for(path)
41
+ interested = Set.new
42
+ while path != "/"
43
+ interested.merge users_for_path(path)
44
+ path = File.dirname path
45
+ end
46
+ # Be nice to get rid of this special case.
47
+ interested.merge users_for_path(path)
48
+ # Return jids, as User is an impl detail
49
+ return interested.collect { |u| u.jid }.sort
50
+ end
51
+
52
+ private
53
+
54
+ # Return an existing user or create a new one.
55
+ def get_user(jid)
56
+ @users[jid] ||= User.new(jid)
57
+ end
58
+
59
+ # Fill in the reverse mapping so we know which paths are of interest to
60
+ # which users.
61
+ def add_path_for_user(path, user)
62
+ @paths[path] ||= Set.new
63
+ @paths[path] << user
64
+ end
65
+
66
+ # Remove user from a given path. If there are no further users listening
67
+ # for a given path, remove the whole path.
68
+ def remove_path_for_user(path, user)
69
+ if @paths[path]
70
+ @paths[path].delete user
71
+ @paths.delete path if @paths[path].empty?
72
+ end
73
+ end
74
+
75
+ # Return a list of users for a given path.
76
+ def users_for_path(path)
77
+ @paths[path] || Set.new
78
+ end
79
+ end
80
+ end
data/svenbot.gemspec ADDED
@@ -0,0 +1,36 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{svenbot}
5
+ s.version = "0.0.1"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Dominic Mitchell"]
9
+ s.date = %q{2008-12-24}
10
+ s.description = %q{A jabber bot for subversion commits.}
11
+ s.email = %q{dom@happygiraffe.net}
12
+ s.executables = ["svenbot", "svenbot-notify"]
13
+ s.extra_rdoc_files = ["bin/svenbot", "bin/svenbot-notify", "lib/svenbot/bot.rb", "lib/svenbot/commit.rb", "lib/svenbot/message.rb", "lib/svenbot/repo.rb", "lib/svenbot/user.rb", "lib/svenbot/user_manager.rb", "LICENSE", "README.textile"]
14
+ s.files = ["bin/svenbot", "bin/svenbot-notify", "lib/svenbot/bot.rb", "lib/svenbot/commit.rb", "lib/svenbot/message.rb", "lib/svenbot/repo.rb", "lib/svenbot/user.rb", "lib/svenbot/user_manager.rb", "LICENSE", "Rakefile", "README.textile", "svenbot.gemspec", "test/svenbot/bot_test.rb", "test/svenbot/commit_test.rb", "test/svenbot/message_test.rb", "test/svenbot/repo_test.rb", "test/svenbot/user_manager_test.rb", "test/svenbot/user_test.rb", "Manifest"]
15
+ s.has_rdoc = true
16
+ s.homepage = %q{http://github.com/happygiraffe/svenbot}
17
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Svenbot", "--main", "README.textile"]
18
+ s.require_paths = ["lib"]
19
+ s.rubyforge_project = %q{svenbot}
20
+ s.rubygems_version = %q{1.3.1}
21
+ s.summary = %q{A jabber bot for subversion commits.}
22
+ s.test_files = ["test/svenbot/bot_test.rb", "test/svenbot/commit_test.rb", "test/svenbot/message_test.rb", "test/svenbot/repo_test.rb", "test/svenbot/user_manager_test.rb", "test/svenbot/user_test.rb"]
23
+
24
+ if s.respond_to? :specification_version then
25
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
26
+ s.specification_version = 2
27
+
28
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
29
+ s.add_development_dependency(%q<echoe>, [">= 0"])
30
+ else
31
+ s.add_dependency(%q<echoe>, [">= 0"])
32
+ end
33
+ else
34
+ s.add_dependency(%q<echoe>, [">= 0"])
35
+ end
36
+ end
@@ -0,0 +1,97 @@
1
+ # To change this template, choose Tools | Templates
2
+ # and open the template in the editor.
3
+
4
+ $:.unshift File.join(File.dirname(__FILE__),'..','lib')
5
+
6
+ require 'test/unit'
7
+ require 'svenbot/bot'
8
+ require 'svenbot/message'
9
+ require 'svenbot/repo'
10
+ require 'tmpdir'
11
+
12
+
13
+
14
+ module Svenbot
15
+ class BotTest < Test::Unit::TestCase
16
+ include Message
17
+
18
+ attr_reader :bot
19
+
20
+ # Sample data
21
+ A_JID = 'me@example.com'
22
+ # More sample data
23
+ ANOTHER_JID = 'you@example.com'
24
+
25
+ def setup
26
+ @bot = Bot.new(Repo.new("#{Dir.tmpdir}/repo"))
27
+ end
28
+
29
+ def assert_message(expected_to, expected_body, msg)
30
+ assert_equal expected_to, msg.to.to_s
31
+ assert_equal expected_body, msg.body
32
+ end
33
+
34
+ def test_register_message
35
+ msg = bot.cmd_register A_JID, '/proj1'
36
+ assert_message A_JID, 'You will get commits for: /proj1', msg
37
+ end
38
+
39
+ def test_register_message_for_two_projects
40
+ msg = bot.cmd_register A_JID, '/proj1'
41
+ msg = bot.cmd_register A_JID, '/proj2'
42
+ assert_message A_JID, 'You will get commits for: /proj1, /proj2', msg
43
+ end
44
+
45
+ def test_unregister_message
46
+ msg = bot.cmd_register A_JID, '/proj1'
47
+ msg = bot.cmd_unregister A_JID, '/proj1'
48
+ assert_message A_JID, 'You will no longer get commits for: /proj1', msg
49
+ end
50
+
51
+ def test_list
52
+ msg = bot.cmd_register A_JID, '/proj1'
53
+ msg = bot.cmd_register A_JID, '/proj2'
54
+ msg = bot.cmd_list A_JID, nil
55
+ assert_message A_JID, 'You are listening for commits to: /proj1, /proj2', msg
56
+ end
57
+
58
+ def test_list_none
59
+ msg = bot.cmd_list A_JID, nil
60
+ assert_message A_JID, 'You are not listening to any commits', msg
61
+ end
62
+
63
+ def test_commit_messages
64
+ bot.cmd_register(A_JID, '/proj1')
65
+ c = Commit.new('12345', 'arthur', '/proj1', 'fix bug 42')
66
+ msgs = bot.commit_messages c
67
+ assert_equal 1, msgs.size
68
+ assert_message A_JID, 'arthur committed 12345: fix bug 42', msgs[0]
69
+ end
70
+
71
+ def test_commit_messages_understand_prefix
72
+ bot.cmd_register(A_JID, '/')
73
+ c = Commit.new('12345', 'arthur', '/proj1/README', 'fix bug 42')
74
+ msgs = bot.commit_messages c
75
+ assert_equal 1, msgs.size
76
+ assert_message A_JID, 'arthur committed 12345: fix bug 42', msgs[0]
77
+ end
78
+
79
+ def test_help
80
+ msg = bot.cmd_help(A_JID, nil)
81
+ assert_message A_JID, 'available commands: help, list, register, unregister', msg
82
+ end
83
+
84
+ def test_dispatch_cmd
85
+ in_msg = html_message('help').set_from(A_JID)
86
+ out_msg = bot.dispatch_cmd(in_msg)
87
+ assert_message A_JID, 'available commands: help, list, register, unregister', out_msg
88
+ end
89
+
90
+ def test_dispatch_cmd_unknown
91
+ in_msg = html_message('aardvark').set_from(A_JID)
92
+ out_msg = bot.dispatch_cmd(in_msg)
93
+ assert_message A_JID, "unknown command 'aardvark'", out_msg
94
+ end
95
+
96
+ end
97
+ end
@@ -0,0 +1,17 @@
1
+ $:.unshift File.join(File.dirname(__FILE__),'..','lib')
2
+
3
+ require 'test/unit'
4
+ require 'svenbot/commit'
5
+
6
+ module Svenbot
7
+ class CommitTest < Test::Unit::TestCase
8
+
9
+ def test_commit_fields
10
+ commit = Commit.new '12345', 'dom', '/proj1', 'I made this!'
11
+ assert_equal 'dom', commit.user
12
+ assert_equal '12345', commit.id
13
+ assert_equal '/proj1', commit.path_prefix
14
+ assert_equal 'I made this!', commit.message
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,19 @@
1
+ $:.unshift File.join(File.dirname(__FILE__),'..','lib')
2
+
3
+ require 'test/unit'
4
+ require 'svenbot/message'
5
+
6
+ module Svenbot
7
+ class MessageTest < Test::Unit::TestCase
8
+ include Message
9
+
10
+ def test_html_message
11
+ msg = html_message("hello <em>world</em>")
12
+ assert_equal :chat, msg.type
13
+ assert_equal "hello world", msg.body
14
+ assert_equal "<html xmlns='http://jabber.org/protocol/xhtml-im'><body " +
15
+ "xmlns='http://www.w3.org/1999/xhtml'>hello <em>world</em></body></html>",
16
+ msg.first_element('html').to_s
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,18 @@
1
+ # To change this template, choose Tools | Templates
2
+ # and open the template in the editor.
3
+
4
+ $:.unshift File.join(File.dirname(__FILE__),'..','lib')
5
+
6
+ require 'test/unit'
7
+ require 'svenbot/repo'
8
+
9
+ module Svenbot
10
+ class RepoTest < Test::Unit::TestCase
11
+ def test_dir
12
+ assert_equal('/tmp/repo', Repo.new('/tmp/repo').dir)
13
+ end
14
+ def test_meta_dir
15
+ assert_equal('/tmp/repo/svenbot', Repo.new('/tmp/repo').meta_dir)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,89 @@
1
+ $:.unshift File.join(File.dirname(__FILE__),'..','lib')
2
+
3
+ require 'test/unit'
4
+ require 'svenbot/commit'
5
+ require 'svenbot/user_manager'
6
+
7
+ module Svenbot
8
+ class UserManagerTest < Test::Unit::TestCase
9
+ attr_reader :um
10
+ # Sample data
11
+ A_JID = 'me@example.com'
12
+ # More sample data
13
+ ANOTHER_JID = 'you@example.com'
14
+
15
+ def setup
16
+ @um = UserManager.new
17
+ end
18
+
19
+ def test_register_user
20
+ um.register A_JID, '/'
21
+
22
+ assert_equal 1, um.users.size
23
+ assert_equal ['/'], um.users[A_JID].paths
24
+
25
+ assert_equal 1, um.paths.size
26
+ assert_equal [A_JID], um.paths['/'].collect { |u| u.jid }
27
+ end
28
+
29
+ def test_register_two_users_same_path
30
+ um.register A_JID, '/proj'
31
+ um.register ANOTHER_JID, '/proj'
32
+
33
+ assert_equal 2, um.users.size
34
+ assert_equal ['/proj'], um.users[A_JID].paths
35
+ assert_equal ['/proj'], um.users[ANOTHER_JID].paths
36
+
37
+ assert_equal 1, um.paths.size
38
+ assert_equal [A_JID, ANOTHER_JID], jids_for_path(um, '/proj').sort
39
+ end
40
+
41
+ def test_register_two_paths
42
+ um.register A_JID, '/proj1'
43
+ um.register A_JID, '/proj2'
44
+
45
+ assert_equal 1, um.users.size
46
+ assert_equal ['/proj1', '/proj2'], um.users[A_JID].paths
47
+
48
+ assert_equal 2, um.paths.size
49
+ assert_equal [A_JID], jids_for_path(um, '/proj1')
50
+ assert_equal [A_JID], jids_for_path(um, '/proj2')
51
+ end
52
+
53
+ def test_unregister
54
+ um.register A_JID, '/proj1'
55
+ um.unregister A_JID, '/proj1'
56
+
57
+ assert_equal 0, um.users.size
58
+ assert_equal 0, um.paths.size
59
+ end
60
+
61
+ def test_users_for_path
62
+ um.register(A_JID, '/proj1')
63
+ assert_equal [A_JID], um.users_for('/proj1')
64
+ end
65
+
66
+ def test_users_for_path_understands_prefixes
67
+ um.register(A_JID, '/')
68
+ assert_equal [A_JID], um.users_for('/proj1')
69
+ end
70
+
71
+ def test_users_for_path_with_multiple_users
72
+ um.register(A_JID, '/proj1')
73
+ um.register(ANOTHER_JID, '/proj1')
74
+ assert_equal [A_JID, ANOTHER_JID], um.users_for('/proj1')
75
+ end
76
+
77
+ def test_paths_for
78
+ um.register A_JID, '/proj1'
79
+ um.register A_JID, '/proj2'
80
+ assert_equal %w[ /proj1 /proj2 ], um.paths_for(A_JID).sort
81
+ end
82
+
83
+ private
84
+
85
+ def jids_for_path(bot, path)
86
+ bot.paths[path].collect { |u| u.jid }
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,32 @@
1
+ $:.unshift File.join(File.dirname(__FILE__),'..','lib')
2
+
3
+ require 'test/unit'
4
+ require 'svenbot/user'
5
+
6
+ module Svenbot
7
+ class UserTest < Test::Unit::TestCase
8
+ attr_reader :user
9
+
10
+ def setup
11
+ @user = User.new 'user@example.com'
12
+ end
13
+
14
+ def test_initialize
15
+ assert_equal 'user@example.com', user.jid
16
+ assert_equal [], user.paths
17
+ end
18
+
19
+ def test_add
20
+ # Should return itself
21
+ assert_equal user, user << '/project'
22
+ # Should have added to paths
23
+ assert_equal ['/project'], user.paths
24
+ end
25
+
26
+ def test_delete
27
+ user.paths = %w( /foo /bar )
28
+ user.delete '/bar'
29
+ assert_equal ['/foo'], user.paths
30
+ end
31
+ end
32
+ end
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: happygiraffe-svenbot
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Dominic Mitchell
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-12-24 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: echoe
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: "0"
23
+ version:
24
+ description: A jabber bot for subversion commits.
25
+ email: dom@happygiraffe.net
26
+ executables:
27
+ - svenbot
28
+ - svenbot-notify
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - bin/svenbot
33
+ - bin/svenbot-notify
34
+ - lib/svenbot/bot.rb
35
+ - lib/svenbot/commit.rb
36
+ - lib/svenbot/message.rb
37
+ - lib/svenbot/repo.rb
38
+ - lib/svenbot/user.rb
39
+ - lib/svenbot/user_manager.rb
40
+ - LICENSE
41
+ - README.textile
42
+ files:
43
+ - bin/svenbot
44
+ - bin/svenbot-notify
45
+ - lib/svenbot/bot.rb
46
+ - lib/svenbot/commit.rb
47
+ - lib/svenbot/message.rb
48
+ - lib/svenbot/repo.rb
49
+ - lib/svenbot/user.rb
50
+ - lib/svenbot/user_manager.rb
51
+ - LICENSE
52
+ - Rakefile
53
+ - README.textile
54
+ - svenbot.gemspec
55
+ - test/svenbot/bot_test.rb
56
+ - test/svenbot/commit_test.rb
57
+ - test/svenbot/message_test.rb
58
+ - test/svenbot/repo_test.rb
59
+ - test/svenbot/user_manager_test.rb
60
+ - test/svenbot/user_test.rb
61
+ - Manifest
62
+ has_rdoc: true
63
+ homepage: http://github.com/happygiraffe/svenbot
64
+ post_install_message:
65
+ rdoc_options:
66
+ - --line-numbers
67
+ - --inline-source
68
+ - --title
69
+ - Svenbot
70
+ - --main
71
+ - README.textile
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: "0"
79
+ version:
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: "1.2"
85
+ version:
86
+ requirements: []
87
+
88
+ rubyforge_project: svenbot
89
+ rubygems_version: 1.2.0
90
+ signing_key:
91
+ specification_version: 2
92
+ summary: A jabber bot for subversion commits.
93
+ test_files:
94
+ - test/svenbot/bot_test.rb
95
+ - test/svenbot/commit_test.rb
96
+ - test/svenbot/message_test.rb
97
+ - test/svenbot/repo_test.rb
98
+ - test/svenbot/user_manager_test.rb
99
+ - test/svenbot/user_test.rb