git_hooks 0.2.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.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Dirk Breuer
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,31 @@
1
+ = git-hooks
2
+
3
+ This is a small library which allows you to easily build Git hooks. The
4
+ interaction with Git is done through the Grit library, which allows a clean
5
+ and straight forward Ruby way of talking with Git.
6
+
7
+ == Config Example
8
+
9
+ :post_receive_hooks:
10
+ - :jabber:
11
+ :jid: JABBER_USERNAME
12
+ :password: JABBER_PASSWORD
13
+ :server: JABBER_SERVER
14
+ :recipients: [ "recipient@jabber.id" ]
15
+
16
+ - :pivotal_tracker:
17
+ :api_key: API_KEY
18
+
19
+ == Note on Patches/Pull Requests
20
+
21
+ * Fork the project.
22
+ * Make your feature addition or bug fix.
23
+ * Add tests for it. This is important so I don't break it in a
24
+ future version unintentionally.
25
+ * Commit, do not mess with rakefile, version, or history.
26
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
27
+ * Send me a pull request. Bonus points for topic branches.
28
+
29
+ == Copyright
30
+
31
+ Copyright (c) 2010 Dirk Breuer. See LICENSE for details.
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'git_hooks'
5
+
6
+ # will receive something like this: 034e985b8c1df2869aff99017b66600acb052617 462b4131bf6dd2fea41e3959b2b22380fd10be99 refs/heads/master
7
+
8
+ GitHooks::Logger.info "running hooks (#{File.basename(__FILE__)}) ..."
9
+
10
+ GitHooks.run_hook(:post_receive)
data/lib/git_hooks.rb ADDED
@@ -0,0 +1,30 @@
1
+ $:.unshift File.dirname(__FILE__) # For use/testing when no gem is installed
2
+
3
+ require 'active_support/core_ext/string'
4
+
5
+ require 'git_hooks/notifier'
6
+ require 'git_hooks/git_adapter'
7
+ require 'git_hooks/post_receive_hook'
8
+ require 'git_hooks/logger'
9
+ require 'git_hooks/utils'
10
+
11
+ module GitHooks
12
+
13
+ class <<self
14
+ attr_writer :config_file
15
+
16
+ def config
17
+ @config_instance ||= Utils::Config.new(config_file)
18
+ end
19
+
20
+ def config_file
21
+ @config_file || "~/.git_hooks_config"
22
+ end
23
+
24
+ def run_hook(name_of_hook, *args)
25
+ hook = "GitHooks::#{name_of_hook.to_s.camelize}Hook".constantize.new
26
+ hook.run(*args)
27
+ end
28
+ end
29
+
30
+ end
@@ -0,0 +1,68 @@
1
+ require 'grit'
2
+
3
+ module GitHooks
4
+ class GitAdapter
5
+ include Grit
6
+
7
+ class Commits
8
+ include Enumerable
9
+
10
+ attr_reader :ref_name, :repo_name
11
+
12
+ def initialize(commits, ref_name, repo)
13
+ @commits = commits
14
+ self.ref_name = ref_name
15
+ self.repo_name = repo
16
+ end
17
+
18
+ def each
19
+ @commits.each { |commit| yield commit }
20
+ end
21
+
22
+ def size
23
+ @commits.size
24
+ end
25
+
26
+ private
27
+
28
+ def ref_name=(ref_name)
29
+ @ref_name ||= ref_name.split("/").last
30
+ end
31
+
32
+ def repo_name=(repo)
33
+ return @repo if @repo
34
+
35
+ splitted_path = repo.path.split("/")
36
+ @repo_name = if (splitted_path.last =~ /\.git/) > 0
37
+ splitted_path.last.split(".").first
38
+ else
39
+ splitted_path[-2]
40
+ end
41
+ end
42
+
43
+ end
44
+
45
+ attr_reader :repo
46
+
47
+ def initialize
48
+ @repo = Repo.new(GitAdapter.find_git_root)
49
+ end
50
+
51
+ def find_commits_since_last_receive(prev_rev, current_rev, ref_name = 'master')
52
+ commits = repo.commits_between(prev_rev, current_rev)
53
+
54
+ return Commits.new(commits, ref_name, @repo)
55
+ end
56
+
57
+ def self.find_git_root
58
+ current_dir = Dir.pwd.split('/')
59
+ while current_dir.last !~ /\.git/
60
+ current_dir.pop
61
+ break if current_dir.empty?
62
+ end
63
+
64
+ return current_dir.join('/')
65
+ end
66
+
67
+ end
68
+ end
@@ -0,0 +1,23 @@
1
+ require 'logger'
2
+
3
+ module GitHooks
4
+ class Logger
5
+ include Singleton
6
+
7
+ class <<self
8
+ def method_missing(meth, *args, &blk)
9
+ if instance.logger.respond_to? meth
10
+ instance.logger.send(meth, *args)
11
+ else
12
+ super
13
+ end
14
+ end
15
+ end
16
+
17
+ attr_reader :logger
18
+
19
+ def initialize
20
+ @logger = ::Logger.new("/tmp/git_hooks.log")
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,2 @@
1
+ require 'git_hooks/notifier/jabber_client'
2
+ require 'git_hooks/notifier/tracker_client'
@@ -0,0 +1,99 @@
1
+ require 'xmpp4r'
2
+ require 'xmpp4r/roster'
3
+
4
+ module GitHooks
5
+ module Notifier
6
+ class JabberClient
7
+ include Jabber
8
+
9
+ class Buddy
10
+ attr_reader :jid
11
+
12
+ def initialize(jid, roster_reference)
13
+ @jid = Jabber::JID.new(jid)
14
+ @roster = roster_reference
15
+ end
16
+
17
+ def subscribed?
18
+ roster_item = @roster[jid]
19
+ if roster_item
20
+ return roster_item.subscription == :both ? true : false
21
+ end
22
+ end
23
+ end
24
+
25
+ def initialize(jabber_options)
26
+ @jabber_options = jabber_options
27
+ init_jabber_backend!
28
+ end
29
+
30
+ def create_recipients(recipients)
31
+ [recipients].flatten.map do |recipient|
32
+ recipient.is_a?(Buddy) ? recipient : Buddy.new(recipient, roster)
33
+ end
34
+ end
35
+
36
+ def buddies
37
+ roster.items.map { |roster_item| Buddy.new(roster_item.last.jid, roster) }
38
+ end
39
+
40
+ def roster
41
+ @roster ||= Roster::Helper.new(backend)
42
+ end
43
+
44
+ def self.deliver(options)
45
+ commits = options.delete(:commits)
46
+ recipients = options.delete(:recipients)
47
+
48
+ client_instance = new(options)
49
+ client_instance.deliver(commits, recipients)
50
+ end
51
+
52
+ def deliver(commits, recipients)
53
+ send_message_to create_message(commits), recipients
54
+ true
55
+ end
56
+
57
+ private unless $TESTING
58
+
59
+ def init_jabber_backend!
60
+ @backend = Client.new(JID.new(@jabber_options[:jid]))
61
+ @backend.connect(@jabber_options[:server])
62
+ @backend.auth(@jabber_options[:password])
63
+ end
64
+
65
+ def backend
66
+ @backend
67
+ end
68
+
69
+ def create_message(from_commits)
70
+ message = "[#{GitHooks::Utils.hostname}] #{from_commits.size} commits have been pushed to '#{from_commits.repo_name}' on '#{from_commits.ref_name}':\n"
71
+ from_commits.each do |commit|
72
+ message << "\t#{commit.id[0...5]}...: '#{commit.short_message}' by #{commit.author.name}\n"
73
+ end
74
+
75
+ message
76
+ end
77
+
78
+ def request_authorization_of(recipient)
79
+ request = Jabber::Presence.new
80
+ request.to = recipient.respond_to?(:jid) ? recipient.jid : recipient
81
+ request.type = :subscribe
82
+ backend.send request
83
+ end
84
+
85
+ def send_message_to(message, recipients)
86
+ create_recipients(recipients).each do |recipient|
87
+ subject = "Git commit notification"
88
+
89
+ request_authorization_of(recipient) unless recipient.subscribed?
90
+
91
+ msg = Message::new(recipient.jid, message).set_type(:normal).set_id('1').set_subject(subject)
92
+ GitHooks::Logger.debug "msg: #{msg}"
93
+ backend.send msg
94
+ end
95
+ end
96
+
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,45 @@
1
+ require 'curb'
2
+
3
+ module GitHooks
4
+ module Notifier
5
+ class TrackerClient
6
+
7
+ attr_reader :curl
8
+
9
+ def self.deliver(options)
10
+ commits = options.delete(:commits)
11
+
12
+ client_instance = new(options)
13
+ client_instance.deliver(commits)
14
+ end
15
+
16
+ def initialize(tracker_options)
17
+ @curl = Curl::Easy.new("http://www.pivotaltracker.com/services/v3/source_commits") do |curl|
18
+ curl.headers["X-TrackerToken"] = tracker_options[:api_key]
19
+ curl.headers["Content-type"] = "application/xml"
20
+ end
21
+ end
22
+
23
+ def deliver(commits)
24
+ create_payloads(commits) do |payload|
25
+ curl.http_post(payload)
26
+ end
27
+ end
28
+
29
+ def create_payloads(commits, &block)
30
+ payloads = commits.map do |commit|
31
+ <<-XML
32
+ <source_commit>
33
+ <message>#{commit.message}</message>
34
+ <author>#{commit.author.name}</author>
35
+ <commit_id>#{commit.id}</commit_id>
36
+ </source_commit>
37
+ XML
38
+ end
39
+
40
+ payloads.each(&block)
41
+ end
42
+
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,28 @@
1
+ module GitHooks
2
+ class PostReceiveHook
3
+
4
+ def initialize
5
+ @git_adapter = GitAdapter.new
6
+ end
7
+
8
+ def run(*args)
9
+ arguments = read_arguments_from_stdin
10
+ commits = @git_adapter.find_commits_since_last_receive(*arguments)
11
+
12
+ GitHooks.config.post_receive_hooks.each do |hook|
13
+ hook.hook_class.deliver(hook.options.merge(:commits => commits))
14
+ end
15
+ end
16
+
17
+ def read_arguments_from_stdin
18
+ arguments = []
19
+
20
+ while arguments << STDIN.gets
21
+ break if arguments.last.nil?
22
+ end
23
+
24
+ arguments.compact.first.split(" ")
25
+ end
26
+ end
27
+
28
+ end
@@ -0,0 +1,13 @@
1
+ require 'git_hooks/utils/config'
2
+
3
+ module GitHooks
4
+ module Utils
5
+
6
+ class <<self
7
+ def hostname
8
+ `hostname -s`.strip
9
+ end
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,57 @@
1
+ require 'yaml'
2
+
3
+ module GitHooks
4
+ module Utils
5
+
6
+ class Config
7
+
8
+ class HookWrapper
9
+
10
+ attr_reader :options
11
+
12
+ def initialize(options)
13
+ @hook_class_name = options.keys.first
14
+ @options = options.values.first
15
+ end
16
+
17
+ def hook_class
18
+ @hook_class ||= "GitHooks::Notifier::#{@hook_class_name.to_s.camelize}Client".constantize
19
+ end
20
+
21
+ end
22
+
23
+ attr_reader :config
24
+
25
+ def initialize(config_file)
26
+ @config = if config_file.respond_to?(:read)
27
+ YAML.load(config_file.read)
28
+ else
29
+ YAML.load_file(File.expand_path(config_file))
30
+ end
31
+ rescue Errno::ENOENT
32
+ GitHooks::Logger.error("Config File '#{config_file}' couldn't be loaded!")
33
+ raise "Config File '#{config_file}' couldn't be loaded!"
34
+ end
35
+
36
+ def method_missing(hook_name, *args, &blk)
37
+ if hook_definitions = config[hook_name]
38
+
39
+ hooks = hook_definitions.map { |hook_definition| HookWrapper.new(hook_definition) }
40
+ instance_variable_set("@#{hook_name}", hooks)
41
+
42
+ instance_eval <<-RUBY
43
+ def #{hook_name}
44
+ @#{hook_name}
45
+ end
46
+ RUBY
47
+
48
+ send(hook_name)
49
+ else
50
+ super
51
+ end
52
+ end
53
+
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,74 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Utils" do
4
+
5
+ describe "Config" do
6
+
7
+ it "should have read from a config file located in the home directory" do
8
+ File.should_receive(:expand_path).with("~/.git_hooks_config").and_return(path_to_config = "/Users/dbreuer/.git_hooks_config")
9
+ YAML.should_receive(:load_file).with(path_to_config).and_return({:post_receive_hooks => [{:jabber => {:jid => "jabber@example.com", :password => "password"}}]})
10
+
11
+ config_instance = GitHooks::Utils::Config.new("~/.git_hooks_config")
12
+ end
13
+
14
+ it "should alternatively init the config from a YAML StringIO" do
15
+ config_yaml = StringIO.new <<-YAML
16
+ :post_receive_hooks:
17
+ - :jabber:
18
+ :jid: JABBER_USERNAME
19
+ :password: JABBER_PASSWORD
20
+ :server: JABBER_SERVER
21
+ :recipients:
22
+ :group: [ "recipient@jabber.id" ]
23
+
24
+ - :pivotal_tracker:
25
+ :api_key: API_KEY
26
+ YAML
27
+
28
+ config_instance = GitHooks::Utils::Config.new(config_yaml)
29
+ config_instance.config.should be_a_kind_of(Hash)
30
+ end
31
+
32
+ it "should return all available hooks as an array of hook wrapper classes" do
33
+ GitHooks.config.post_receive_hooks.each do |hook|
34
+ hook.should be_a_kind_of(GitHooks::Utils::Config::HookWrapper)
35
+ end
36
+ end
37
+
38
+ describe "HookWrapper" do
39
+
40
+ before(:each) do
41
+ hook_options = {
42
+ :jabber => {
43
+ :jid => "jabber@example.com",
44
+ :password => "password",
45
+ :recipients => [
46
+ "bender.rodriguez@planetexpress.com"
47
+ ]
48
+ }
49
+ }
50
+
51
+ @hook_wrapper = GitHooks::Utils::Config::HookWrapper.new(hook_options)
52
+ end
53
+
54
+ it "should know its backing class" do
55
+ @hook_wrapper.hook_class.should == GitHooks::Notifier::JabberClient
56
+ end
57
+
58
+ it "should know the options for this hook" do
59
+ expected_options = {
60
+ :jid => "jabber@example.com",
61
+ :password => "password",
62
+ :recipients => [
63
+ "bender.rodriguez@planetexpress.com"
64
+ ]
65
+ }
66
+
67
+ @hook_wrapper.options.should == expected_options
68
+ end
69
+
70
+ end
71
+
72
+ end
73
+
74
+ end
@@ -0,0 +1,28 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "GitAdapter" do
4
+ it "should initialize with a Grit repository" do
5
+ GitHooks::GitAdapter.should_receive(:find_git_root)
6
+ Grit::Repo.should_receive(:new)
7
+
8
+ git_adapter = GitHooks::GitAdapter.new
9
+ end
10
+
11
+ it "should find the Git root directory based on the current directory" do
12
+ git_adapter = GitHooks::GitAdapter.new
13
+ commits = git_adapter.find_commits_since_last_receive("7eb08614", "58c3455c")
14
+ commits.size.should be(2)
15
+ commits.ref_name.should == "master"
16
+ commits.repo_name.should =~ /(git_hooks|workspace)/
17
+ end
18
+
19
+ it "should find commits since last commit" do
20
+ Dir.should_receive(:pwd).and_return("/srv/example.com/git/repositories/git_hooks.git/hooks")
21
+ git_root = GitHooks::GitAdapter.find_git_root
22
+ git_root.should == "/srv/example.com/git/repositories/git_hooks.git"
23
+
24
+ Dir.should_receive(:pwd).and_return("/home/dbreuer/projects/git_hooks/.git/hooks")
25
+ git_root = GitHooks::GitAdapter.find_git_root
26
+ git_root.should == "/home/dbreuer/projects/git_hooks/.git"
27
+ end
28
+ end
@@ -0,0 +1,22 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "GitHooks" do
4
+
5
+ it "should run a hook identified by a symbol" do
6
+ post_receive_hook_mock = mock("PostReceiveHook")
7
+ post_receive_hook_mock.should_receive(:run)
8
+ GitHooks::PostReceiveHook.should_receive(:new).and_return(post_receive_hook_mock)
9
+
10
+ GitHooks.run_hook(:post_receive)
11
+ end
12
+
13
+ it "should provide access to a config instance" do
14
+ GitHooks.config.should be_a_kind_of(GitHooks::Utils::Config)
15
+ end
16
+
17
+ it "should provide a setter for the config file path" do
18
+ GitHooks.config_file = "/path/to/config.yml"
19
+ GitHooks.config_file.should == "/path/to/config.yml"
20
+ end
21
+
22
+ end
@@ -0,0 +1,122 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "JabberClient" do
4
+
5
+ describe "Buddy" do
6
+
7
+ it "should have a JID and a roster reference" do
8
+ buddy = GitHooks::Notifier::JabberClient::Buddy.new("lela.starr@jabber.org", mock("RosterMock"))
9
+ buddy.jid.should be_a_kind_of(Jabber::JID)
10
+ end
11
+
12
+ it "should should know if already subscribed" do
13
+ roster_mock = mock("RosterMock")
14
+
15
+ roster_mock.should_receive(:[]).with(Jabber::JID.new("lela.starr@jabber.org")).and_return(mock("RosterItemMock", :subscription => :both))
16
+ buddy = GitHooks::Notifier::JabberClient::Buddy.new("lela.starr@jabber.org", roster_mock)
17
+ buddy.subscribed?.should be(true)
18
+
19
+ roster_mock.should_receive(:[]).with(Jabber::JID.new("lela.starr@jabber.org")).and_return(mock("RosterItemMock", :subscription => :none))
20
+ buddy = GitHooks::Notifier::JabberClient::Buddy.new("lela.starr@jabber.org", roster_mock)
21
+ buddy.subscribed?.should be(false)
22
+ end
23
+
24
+ end
25
+
26
+ before(:each) do
27
+ @jabber_client_opts = GitHooks.config.post_receive_hooks.first.options
28
+ end
29
+
30
+ it "should initialize with a XMPP client" do
31
+ Jabber::JID.should_receive(:new).and_return(jid_mock = mock("JIDMock"))
32
+ Jabber::Client.should_receive(:new).with(jid_mock).and_return(client_mock = mock("ClientMock"))
33
+ client_mock.should_receive(:connect).with("JABBER_SERVER")
34
+ client_mock.should_receive(:auth)
35
+
36
+ jabber_client = GitHooks::Notifier::JabberClient.new(@jabber_client_opts)
37
+ end
38
+
39
+ it "should transform a collection of Jabber IDs to Buddy objects" do
40
+ GitHooks::Notifier::JabberClient.any_instance.stubs(:init_jabber_backend!)
41
+ jabber_client = GitHooks::Notifier::JabberClient.new(@jabber_client_opts)
42
+ jabber_client.should_receive(:roster)
43
+
44
+
45
+ jabber_client.create_recipients(["bender.rodriguez@planetexpress.com"]).each do |buddy|
46
+ buddy.should be_a_kind_of(GitHooks::Notifier::JabberClient::Buddy)
47
+ end
48
+ end
49
+
50
+ it "should not transform recipients that are already Buddy objects" do
51
+ GitHooks::Notifier::JabberClient.any_instance.stubs(:init_jabber_backend!)
52
+ jabber_client = GitHooks::Notifier::JabberClient.new(@jabber_client_opts)
53
+ jabber_client.should_receive(:roster)
54
+
55
+ buddy = GitHooks::Notifier::JabberClient::Buddy.new("fry@planetexpress.com", nil)
56
+
57
+ jabber_client.create_recipients(["bender.rodriguez@planetexpress.com", buddy]).each do |buddy|
58
+ buddy.should be_a_kind_of(GitHooks::Notifier::JabberClient::Buddy)
59
+ end
60
+ end
61
+
62
+ it "should have a list of buddies" do
63
+ GitHooks::Notifier::JabberClient.any_instance.stubs(:init_jabber_backend!)
64
+ jabber_client = GitHooks::Notifier::JabberClient.new(@jabber_client_opts)
65
+ jabber_client.should_receive(:roster).
66
+ at_least(2).times.
67
+ and_return(roster_mock = mock("RosterMock"))
68
+
69
+ GitHooks::Notifier::JabberClient::Buddy.should_receive(:new).
70
+ with("lela.starr@jabber.org", roster_mock).
71
+ and_return(lela_starr = mock("BuddyMock"))
72
+
73
+ roster_mock.should_receive(:items).
74
+ and_return({:jabber_internal => mock("RosterItem", :jid => "lela.starr@jabber.org")})
75
+
76
+ jabber_client.buddies.should == [lela_starr]
77
+ end
78
+
79
+ it "should create a message out of a bunch of commits" do
80
+ GitHooks::Notifier::JabberClient.any_instance.stubs(:init_jabber_backend!)
81
+ jabber_client = GitHooks::Notifier::JabberClient.new(@jabber_client_opts)
82
+
83
+ commit = mock("CommitMock")
84
+ commit.should_receive(:id).and_return("c1be3c82cafc755754ee2247ec8dae1e6a64857f")
85
+ commit.should_receive(:short_message).and_return("This was a simple test commit.")
86
+ commit.should_receive(:author).and_return(mock("Author", :name => "Dirk Breuer"))
87
+
88
+ commits = mock("CommitsMock")
89
+ commits.should_receive(:ref_name).and_return("master")
90
+ commits.should_receive(:repo_name).and_return("git_hooks")
91
+ commits.should_receive(:each).and_yield(commit)
92
+ commits.should_receive(:size).and_return(1)
93
+
94
+ jabber_client.create_message(commits)
95
+ end
96
+
97
+ it "should request a recipient for authorization if she is not a subscribed buddy" do
98
+ GitHooks::Notifier::JabberClient.any_instance.stubs(:init_jabber_backend!)
99
+ jabber_client = GitHooks::Notifier::JabberClient.new(@jabber_client_opts)
100
+ jabber_client.should_receive(:backend).and_return(mock("JabberBackend", :send => true))
101
+
102
+ jabber_client.should_receive(:roster).and_return(roster_mock = mock("RosterMock"))
103
+
104
+ GitHooks::Notifier::JabberClient::Buddy.should_receive(:new).
105
+ with("lela.starr@jabber.org", roster_mock).
106
+ and_return(buddy = mock("BuddyMock", :subscribed? => false, :jid => "lela.starr@jabber.org"))
107
+
108
+ jabber_client.should_receive(:request_authorization_of).with(buddy)
109
+
110
+ jabber_client.send_message_to "My testing message", "lela.starr@jabber.org"
111
+ end
112
+
113
+ it "should send the notification based on the given options" do
114
+ GitHooks::Notifier::JabberClient.any_instance.stubs(:init_jabber_backend!)
115
+ jabber_client = GitHooks::Notifier::JabberClient.new(@jabber_client_opts)
116
+ commits = [mock("Commit")]
117
+ jabber_client.should_receive(:create_message).with(commits).and_return(message = "Message")
118
+ jabber_client.should_receive(:send_message_to).with(message, "lela.starr@jabber.org")
119
+ jabber_client.deliver(commits, "lela.starr@jabber.org")
120
+ end
121
+
122
+ end
@@ -0,0 +1,37 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "PostReceiveHook" do
4
+
5
+ it "should should read arguments given by Git from stdin" do
6
+ STDIN.expects(:gets).times(2).returns("old_sha new_sha refs/head/master\n").then.returns(nil)
7
+
8
+ post_receive_hook = GitHooks::PostReceiveHook.new
9
+ arguments = post_receive_hook.read_arguments_from_stdin
10
+ arguments.should == ["old_sha", "new_sha", "refs/head/master"]
11
+ end
12
+
13
+ it "should promote the received commits to all registered post_receive hooks" do
14
+ post_receive_hook = GitHooks::PostReceiveHook.new
15
+
16
+ post_receive_hook.should_receive(:read_arguments_from_stdin).
17
+ and_return(["old_sha", "new_sha", "refs/head/master"])
18
+
19
+ GitHooks::GitAdapter.any_instance.
20
+ expects(:find_commits_since_last_receive).
21
+ with("old_sha", "new_sha", "refs/head/master").
22
+ returns(commits = [mock("Commit")])
23
+
24
+ jabber_hook = mock("HookMock")
25
+ jabber_hook.should_receive(:hook_class).and_return(GitHooks::Notifier::JabberClient)
26
+ jabber_hook.should_receive(:options).and_return({:other_jabber_option => "Option"})
27
+
28
+ post_receive_hooks = [jabber_hook]
29
+
30
+ GitHooks.config.should_receive(:post_receive_hooks).and_return(post_receive_hooks)
31
+
32
+ GitHooks::Notifier::JabberClient.should_receive(:deliver).with({:other_jabber_option => "Option", :commits => commits})
33
+
34
+ post_receive_hook.run
35
+ end
36
+
37
+ end
@@ -0,0 +1,28 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+ require 'spec/autorun'
4
+ require 'mocha'
5
+
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
8
+
9
+ $TESTING = true
10
+
11
+ require 'git_hooks'
12
+
13
+ # init the config class with testing config
14
+ config_yaml = StringIO.new <<-YAML
15
+ :post_receive_hooks:
16
+ - :jabber:
17
+ :jid: JABBER_USERNAME
18
+ :password: JABBER_PASSWORD
19
+ :server: JABBER_SERVER
20
+ :recipients: [ "recipient@jabber.id" ]
21
+
22
+ - :pivotal_tracker:
23
+ :api_key: API_KEY
24
+ YAML
25
+ GitHooks.config_file = config_yaml
26
+
27
+ Spec::Runner.configure do |config|
28
+ end
@@ -0,0 +1,68 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "TrackerClient" do
4
+
5
+ before(:each) do
6
+ @tracker_options = { :api_key => "MY_API_KEY" }
7
+ end
8
+
9
+ it "should create a pivotal tracker ready payload for each passed commit" do
10
+ commit = mock("CommitMock")
11
+ commit.should_receive(:id).and_return("SHA_ID")
12
+ commit.should_receive(:message).and_return("[#1234] Commit Message")
13
+ commit.should_receive(:author).and_return(mock("AuthorMock", :name => "Seras Victoria"))
14
+
15
+ expected_payload = <<-XML
16
+ <source_commit>
17
+ <message>[#1234] Commit Message</message>
18
+ <author>Seras Victoria</author>
19
+ <commit_id>SHA_ID</commit_id>
20
+ </source_commit>
21
+ XML
22
+
23
+ client = GitHooks::Notifier::TrackerClient.new(@tracker_options)
24
+ client.create_payloads([commit]) do |payload|
25
+ payload.should == expected_payload
26
+ end
27
+ end
28
+
29
+ it "should send commit messages to pivotal tracker" do
30
+ commits = [mock("CommitMock")]
31
+ payload = "some test payload"
32
+ curl = mock("CurlMock")
33
+ curl.should_receive(:http_post).with(payload)
34
+
35
+ client = GitHooks::Notifier::TrackerClient.new(@tracker_options)
36
+ client.should_receive(:create_payloads).with(commits).and_yield(payload)
37
+ client.should_receive(:curl).and_return(curl)
38
+
39
+ client.deliver(commits)
40
+ end
41
+
42
+ it "should initialize client with a curb client ready to post to pivotal tracker" do
43
+ curb = mock("CurbMock")
44
+ headers = {}
45
+ curb.should_receive(:headers).twice.and_return(headers)
46
+
47
+ Curl::Easy.should_receive(:new).with("http://www.pivotaltracker.com/services/v3/source_commits").and_yield(curb)
48
+
49
+ client = GitHooks::Notifier::TrackerClient.new(@tracker_options)
50
+
51
+ headers["X-TrackerToken"].should == @tracker_options[:api_key]
52
+ headers["Content-type"].should == "application/xml"
53
+ end
54
+
55
+ it "should provide class level deliver methods" do
56
+ deliver_options = {
57
+ :commits => [mock("CommitMock")],
58
+ :api_key => "MY_API_KEY"
59
+ }
60
+
61
+ client = mock("TrackerClientMock")
62
+ client.should_receive(:deliver).with(deliver_options[:commits])
63
+ GitHooks::Notifier::TrackerClient.should_receive(:new).with({:api_key => "MY_API_KEY"}).and_return(client)
64
+
65
+ GitHooks::Notifier::TrackerClient.deliver(deliver_options)
66
+ end
67
+
68
+ end
@@ -0,0 +1,9 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Utils" do
4
+
5
+ it "should find out the hostname" do
6
+ GitHooks::Utils.hostname.should_not be(nil)
7
+ end
8
+
9
+ end
metadata ADDED
@@ -0,0 +1,163 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: git_hooks
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 2
8
+ - 0
9
+ version: 0.2.0
10
+ platform: ruby
11
+ authors:
12
+ - Dirk Breuer
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-05-10 00:00:00 +02:00
18
+ default_executable: hook-post-receive
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: grit
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 2
29
+ - 0
30
+ - 0
31
+ version: 2.0.0
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: xmpp4r
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ - 5
44
+ version: "0.5"
45
+ type: :runtime
46
+ version_requirements: *id002
47
+ - !ruby/object:Gem::Dependency
48
+ name: curb
49
+ prerelease: false
50
+ requirement: &id003 !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ segments:
55
+ - 0
56
+ - 7
57
+ - 1
58
+ version: 0.7.1
59
+ type: :runtime
60
+ version_requirements: *id003
61
+ - !ruby/object:Gem::Dependency
62
+ name: activesupport
63
+ prerelease: false
64
+ requirement: &id004 !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ segments:
69
+ - 3
70
+ - 0
71
+ - 0
72
+ - beta
73
+ version: 3.0.0.beta
74
+ type: :runtime
75
+ version_requirements: *id004
76
+ - !ruby/object:Gem::Dependency
77
+ name: rspec
78
+ prerelease: false
79
+ requirement: &id005 !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ segments:
84
+ - 1
85
+ - 2
86
+ - 9
87
+ version: 1.2.9
88
+ type: :development
89
+ version_requirements: *id005
90
+ - !ruby/object:Gem::Dependency
91
+ name: mocha
92
+ prerelease: false
93
+ requirement: &id006 !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ segments:
98
+ - 0
99
+ - 9
100
+ - 8
101
+ version: 0.9.8
102
+ type: :development
103
+ version_requirements: *id006
104
+ description: The goal is to provide a pluggable hook infrastructure, where you can easily use different hooks for different purposes.
105
+ email: dirk.breuer@gmail.com
106
+ executables:
107
+ - hook-post-receive
108
+ extensions: []
109
+
110
+ extra_rdoc_files:
111
+ - LICENSE
112
+ - README.rdoc
113
+ files:
114
+ - README.rdoc
115
+ - lib/git_hooks.rb
116
+ - lib/git_hooks/git_adapter.rb
117
+ - lib/git_hooks/logger.rb
118
+ - lib/git_hooks/notifier.rb
119
+ - lib/git_hooks/notifier/jabber_client.rb
120
+ - lib/git_hooks/notifier/tracker_client.rb
121
+ - lib/git_hooks/post_receive_hook.rb
122
+ - lib/git_hooks/utils.rb
123
+ - lib/git_hooks/utils/config.rb
124
+ - LICENSE
125
+ has_rdoc: true
126
+ homepage: http://github.com/railsbros/git-hooks
127
+ licenses: []
128
+
129
+ post_install_message:
130
+ rdoc_options:
131
+ - --charset=UTF-8
132
+ require_paths:
133
+ - lib
134
+ required_ruby_version: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ segments:
139
+ - 0
140
+ version: "0"
141
+ required_rubygems_version: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ segments:
146
+ - 0
147
+ version: "0"
148
+ requirements: []
149
+
150
+ rubyforge_project:
151
+ rubygems_version: 1.3.6
152
+ signing_key:
153
+ specification_version: 3
154
+ summary: A small Gem to provide various Git-Hooks based on Grit.
155
+ test_files:
156
+ - spec/config_spec.rb
157
+ - spec/git_adapter_spec.rb
158
+ - spec/git_hooks_spec.rb
159
+ - spec/jabber_client_spec.rb
160
+ - spec/post_receive_hook_spec.rb
161
+ - spec/spec_helper.rb
162
+ - spec/tracker_client_spec.rb
163
+ - spec/utils_spec.rb