happygiraffe-svenbot 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +23 -0
- data/Manifest +19 -0
- data/README.textile +7 -0
- data/Rakefile +17 -0
- data/bin/svenbot +58 -0
- data/bin/svenbot-notify +13 -0
- data/lib/svenbot/bot.rb +66 -0
- data/lib/svenbot/commit.rb +44 -0
- data/lib/svenbot/message.rb +21 -0
- data/lib/svenbot/repo.rb +23 -0
- data/lib/svenbot/user.rb +26 -0
- data/lib/svenbot/user_manager.rb +80 -0
- data/svenbot.gemspec +36 -0
- data/test/svenbot/bot_test.rb +97 -0
- data/test/svenbot/commit_test.rb +17 -0
- data/test/svenbot/message_test.rb +19 -0
- data/test/svenbot/repo_test.rb +18 -0
- data/test/svenbot/user_manager_test.rb +89 -0
- data/test/svenbot/user_test.rb +32 -0
- metadata +99 -0
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
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
|
data/bin/svenbot-notify
ADDED
data/lib/svenbot/bot.rb
ADDED
@@ -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
|
data/lib/svenbot/repo.rb
ADDED
@@ -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
|
data/lib/svenbot/user.rb
ADDED
@@ -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
|