subtrigger 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/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Arjan van der Gaag
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,56 @@
1
+ = subtrigger
2
+
3
+ Subtrigger is a tiny tool for firing callback methods based on triggers in subversion log messages. This allows you to send out e-mail notifications after a commit, or take some other action based on keywords in Subversion's log messages.
4
+
5
+ Here's a quick example:
6
+
7
+ # use as post-commit hook in /path/to/repo/hooks
8
+ require 'subtrigger'
9
+ Subtrigger.on(/log: (\w+)/) { |matches, repo|
10
+ puts "#{repo.author} committed #{matches[0]} in revision #{repo.revision}"
11
+ }.run(*ARGV)
12
+
13
+ == Documentation
14
+
15
+ See the inline API documentation for descriptions and usage examples.
16
+
17
+ == Credits
18
+
19
+ Author:: Arjan van der Gaag
20
+ E-mail:: arjan@arjanvandergaag.nl
21
+ URL:: http://arjanvandergaag.nl
22
+ Source:: http://github.com/avdgaag/subtrigger
23
+
24
+ == Note on Patches/Pull Requests
25
+
26
+ * Fork the project.
27
+ * Make your feature addition or bug fix.
28
+ * Add tests for it. This is important so I don't break it in a
29
+ future version unintentionally.
30
+ * Commit, do not mess with rakefile, version, or history.
31
+ (if you want to have your own version, that is fine but bump version in a
32
+ commit by itself I can ignore when I pull)
33
+ * Send me a pull request. Bonus points for topic branches.
34
+
35
+ == Copyright
36
+
37
+ Copyright (c) 2010 Arjan van der Gaag
38
+
39
+ Permission is hereby granted, free of charge, to any person obtaining
40
+ a copy of this software and associated documentation files (the
41
+ "Software"), to deal in the Software without restriction, including
42
+ without limitation the rights to use, copy, modify, merge, publish,
43
+ distribute, sublicense, and/or sell copies of the Software, and to
44
+ permit persons to whom the Software is furnished to do so, subject to
45
+ the following conditions:
46
+
47
+ The above copyright notice and this permission notice shall be
48
+ included in all copies or substantial portions of the Software.
49
+
50
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
51
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
52
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
53
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
54
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
55
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
56
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,53 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "subtrigger"
8
+ gem.summary = %Q{Create post-commit triggers for Subversion commit messages}
9
+ gem.description = %Q{This gem allows you to create simple Ruby triggers for Subversion commit messages, responding to keywords in your log messages to send e-mails, deploy sites or do whatever you need.}
10
+ gem.email = "arjan@arjanvandergaag.nl"
11
+ gem.homepage = "http://github.com/avdgaag/subtrigger"
12
+ gem.authors = ["Arjan van der Gaag"]
13
+ gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
14
+ gem.add_development_dependency "mocha", ">= 0"
15
+ end
16
+ Jeweler::GemcutterTasks.new
17
+ rescue LoadError
18
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
19
+ end
20
+
21
+ require 'rake/testtask'
22
+ Rake::TestTask.new(:test) do |test|
23
+ test.libs << 'lib' << 'test'
24
+ test.pattern = 'test/**/test_*.rb'
25
+ test.verbose = true
26
+ end
27
+
28
+ begin
29
+ require 'rcov/rcovtask'
30
+ Rcov::RcovTask.new do |test|
31
+ test.libs << 'test'
32
+ test.pattern = 'test/**/test_*.rb'
33
+ test.verbose = true
34
+ end
35
+ rescue LoadError
36
+ task :rcov do
37
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
38
+ end
39
+ end
40
+
41
+ task :test => :check_dependencies
42
+
43
+ task :default => :test
44
+
45
+ require 'rake/rdoctask'
46
+ Rake::RDocTask.new do |rdoc|
47
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
48
+
49
+ rdoc.rdoc_dir = 'rdoc'
50
+ rdoc.title = "subtrigger #{version}"
51
+ rdoc.rdoc_files.include('README*')
52
+ rdoc.rdoc_files.include('lib/**/*.rb')
53
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.0
data/bin/subtrigger ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/local/bin/env ruby
2
+ $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
3
+ require 'subtrigger'
4
+ Subtrigger.run(*ARGV)
@@ -0,0 +1,56 @@
1
+ module Subtrigger
2
+ # = E-mail notifications
3
+ #
4
+ # Sometimes you want to send notification e-mails after the hook has fired
5
+ # to inform developers or yourself of some event. This class is a simple
6
+ # wrapper around the standard +sendmail+ program.
7
+ #
8
+ # == Usage example
9
+ #
10
+ # Email.new(:to => 'john@cleese.com',
11
+ # :from => 'eric@idle.com',
12
+ # :subject => 'Fired',
13
+ # :body => 'Your post-commit hook has just fired').send
14
+ #
15
+ # If +sendmail+ can not be found on your system an exception will be raised.
16
+ #--
17
+ # TODO: Use a hash of options rather than plain arguments.
18
+ class Email
19
+ attr_accessor :from, :to, :subject, :body, :development
20
+
21
+ # Sets up a new message and tries to find +sendmail+ on your system.
22
+ def initialize(options = {})
23
+ @to = options[:to]
24
+ @from = options[:from]
25
+ @subject = options[:subject]
26
+ @body = options[:body]
27
+ @development = options[:development] || false
28
+ @sendmail = `which sendmail`.strip
29
+ raise 'Could not find sendmail; aborting.' if @sendmail.nil?
30
+ end
31
+
32
+ # Tries to use +sendmail+ to send the message.
33
+ def send
34
+ message = header + "\n" + body
35
+ unless development
36
+ fd = open("|#{@sendmail} #{@to}", "w")
37
+ fd.print(message)
38
+ fd.close
39
+ end
40
+ message
41
+ end
42
+
43
+ private
44
+
45
+ def header
46
+ <<-EOS
47
+ To: #{@to}
48
+ From: #{@from}
49
+ Subject: [svn] #{@subject}
50
+ MIME-version: 1.0
51
+ Content-Type: text/plain; charset=UTF-8
52
+ Content-Transfer-Encoding: 8bit
53
+ EOS
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,124 @@
1
+ module Subtrigger
2
+ # = Subversion repostitory wrapper
3
+ #
4
+ # Use this class to get to the information for a specific commit in a
5
+ # specific subversion repository. This is a simple wrapper around the
6
+ # +svnlook+ command.
7
+ #
8
+ # This class will look for +svn+ and +svnlook+ on your system and will raise
9
+ # an exception when it can not be found.
10
+ #
11
+ # == Usage example
12
+ #
13
+ # repo = Repository.new('/path/to/repo', 5540)
14
+ # repo.author # => 'Graham'
15
+ # repo.message # => 'Added copyright information to the readme'
16
+ # repo.changed_projects do |p|
17
+ # puts p # => a changed directory above a trunk, branches or tags
18
+ # end
19
+ #
20
+ class Repository
21
+ attr_reader :path, :revision
22
+
23
+ # Initialize a new wrapper around a repository at a given revision.
24
+ #
25
+ # This will try to find the +svn+ executable on your system and raise
26
+ # an exception when it cannot be found.
27
+ #
28
+ # Exceptions will also be raised when the repository path can not be
29
+ # found or the revision is not numeric.
30
+ def initialize(path, revision)
31
+ raise "Repository '#{path}' not found" unless File.directory?(path)
32
+ raise "Invalid revision number '#{revision}'" unless revision.to_i > 0
33
+ @path = path
34
+ @revision = revision.to_i
35
+ @svn_path = `which svn`.strip
36
+ raise 'Could not locate svn' if @svn_path.nil?
37
+ end
38
+
39
+ # Return the path to the current repository. If given an extra string,
40
+ # that will be appended to the path.
41
+ #
42
+ # Example:
43
+ #
44
+ # repo.path # => '/path/to/repo'
45
+ # repo.path('mydir') # => '/path/to/repo/mydir'
46
+ #
47
+ def path(subpath = nil)
48
+ return File.join(@path, subpath) unless subpath.nil?
49
+ @path
50
+ end
51
+
52
+ # Returns the information from <tt>svnlook changed</tt>.
53
+ def changed
54
+ @changed ||= look_at('changed')
55
+ end
56
+
57
+ # Yields all directories above a changed trunk, branches or tags directory.
58
+ #
59
+ # Assuming a project layout like this:
60
+ #
61
+ # [root]
62
+ # |- project1
63
+ # |- project2
64
+ # |- group1
65
+ # `- project3
66
+ # |- branches
67
+ # |- tags
68
+ # `- trunk
69
+ #
70
+ # Then committing to <tt>group1/project3/trunk</tt> will yield both
71
+ # <tt>group1/project3/trunk</tt> and <tt>project3</tt>.
72
+ def changed_projects #:yields: full_path, project_path
73
+ (@dirs_changed ||= look_at('dirs-changed')).split("\n").each do |dir|
74
+ yield dir, $1 if dir =~ /([\w\-\.]+)\/(?:trunk|branches|tags)/
75
+ end
76
+ end
77
+
78
+ # Returns the HEAD revision number (<tt>svnlook youngest</tt>)
79
+ def head
80
+ @head ||= look_at('youngest')
81
+ end
82
+
83
+ # Returns the author of the last commit.
84
+ def author
85
+ @author ||= get_line_from_info(0)
86
+ end
87
+
88
+ # Returns the log message of the last commit.
89
+ def message
90
+ @message ||= get_line_from_info(3)
91
+ end
92
+
93
+ # Returns the date from the last commit.
94
+ def date
95
+ @date ||= get_line_from_info(1)
96
+ end
97
+
98
+ # Runs an arbitrary +svn+ command and returns its results.
99
+ def exec(command)
100
+ command = "#{@svn_path} #{command}"
101
+ `#{command}`
102
+ end
103
+
104
+ private
105
+
106
+ # Execute a +svnlook+ command for the current repository and revision.
107
+ def look_at(subcommand)
108
+ `#{File.join(File.dirname(@svn_path), 'svnlook')} #{subcommand} #{@path} -r #{@revision}`
109
+ end
110
+
111
+ # Get the contents of a line from the <tt>svnlook info</tt> output, which
112
+ # looks like this:
113
+ #
114
+ # Author name
115
+ # Commit date
116
+ # Log message length
117
+ # Log message
118
+ #
119
+ def get_line_from_info(n)
120
+ @info ||= look_at('info')
121
+ @info.split("\n")[n]
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,60 @@
1
+ module Subtrigger
2
+ # = Call blocks on a matching pattern
3
+ #
4
+ # This is a framework for combining pairs of matchers and callbacks to run
5
+ # on a commit message. You can define a trigger which this class will
6
+ # apply to a log message.
7
+ #
8
+ # == Example usage
9
+ #
10
+ # Trigger.define(/foo/) do |matches, repo|
11
+ # puts "Someone used 'foo' in his commit message"
12
+ # end
13
+ #
14
+ # When the above trigger is defined and somebody makes a commit message
15
+ # containing +foo+ the block will be called. +matches+ contains any
16
+ # captured regular expression groups, +repo+ is a +Repository+ object for
17
+ # the current repository revision.
18
+ #
19
+ # You can define as many triggers as you like. When no triggers are found
20
+ # an exception will be raised. When no trigger applies, it will quit
21
+ # silently.
22
+ class Trigger
23
+ class << self
24
+ @triggers = {}
25
+
26
+ # Run all available triggers on the given Repository object.
27
+ def run(repo)
28
+ raise 'No suitable triggers found.' if @triggers.nil?
29
+ @triggers.each_pair do |pattern, block|
30
+ new(pattern, repo, &block)
31
+ end
32
+ end
33
+
34
+ def triggers
35
+ @triggers ||= {}
36
+ end
37
+
38
+ def reset
39
+ @triggers = {}
40
+ end
41
+
42
+ # Create a new Trigger object and add it to the stack.
43
+ def define(pattern, &block)
44
+ (@triggers ||= {})[pattern] = block;
45
+ end
46
+ end
47
+
48
+ def initialize(pattern, repo, &block)
49
+ @pattern, @repo, @callback = pattern, repo, block
50
+ parse
51
+ end
52
+
53
+ private
54
+
55
+ # Scan the commit message and fire the callback if it matches.
56
+ def parse
57
+ @repo.message.scan(@pattern) { |match| @callback.call(match, @repo) }
58
+ end
59
+ end
60
+ end
data/lib/subtrigger.rb ADDED
@@ -0,0 +1,85 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+ # = Subtrigger
3
+ #
4
+ # Subtrigger is a tiny tool for firing callback methods based on triggers in
5
+ # subversion log messages.
6
+ #
7
+ # == Example
8
+ #
9
+ # When somebody makes a commit:
10
+ #
11
+ # r5410 "Added a sitemap to the website [deploy]"
12
+ # A /www.website.tld/trunk/sitemap.xml
13
+ #
14
+ # ...then you can trigger the deployment of that project to a staging server
15
+ # using a +Trigger+:
16
+ #
17
+ # Subtrigger.on(/\[deploy\]/) do |matches, repo|
18
+ # # do some smart stuff here
19
+ # end
20
+ #
21
+ # Your trigger has access to the captured groups in its regular expression
22
+ # matcher, and to all the <tt>svnlook</tt> information from the repository
23
+ # at the revision that fired the hook. This gives you access to changed paths,
24
+ # its author, date, etc.
25
+ #
26
+ # == E-mail notifications
27
+ #
28
+ # Subtrigger allows you to send notification e-mails to developers:
29
+ #
30
+ # # in your trigger:
31
+ # Subtrigger::Email.new(:to => "#{repo.author}@company.tld",
32
+ # :from => 'svn@company.tld',
33
+ # :subject => 'Trigger notification',
34
+ # :body => "Dear #{repo.author}, ...")
35
+ #
36
+ # == Usage
37
+ #
38
+ # This library is intended to be used as a Subversion post-commit hook.
39
+ # The best way to use it to create a post-commit hook file that requires this
40
+ # library, sets up one or more triggers and than fires the processing.
41
+ #
42
+ # Here's an example:
43
+ #
44
+ # #!/usr/local/bin/ruby
45
+ # require 'rubygems'
46
+ # require 'subtrigger'
47
+ # Subtrigger.on(/foo/) { |matches, repo|
48
+ # puts "#{repo.author} comitted foo!"
49
+ # }.on(/bar/) { |matches, repo|
50
+ # puts "#{repo.author} comitted bar!"
51
+ # }.run(*ARGV)
52
+ #
53
+ # Make sure your gems are installed and the correct permissions are set. Note
54
+ # that Subversion runs its hooks in an empty environment, with no PATH set,
55
+ # and you will also see no output.
56
+ module Subtrigger
57
+ # Output the version number for this gem by reading /VERSION
58
+ def self.version
59
+ File.read(File.join(File.dirname(__FILE__), *%w{.. VERSION}))
60
+ end
61
+
62
+ # This is the main spark in the program.
63
+ # It runs all available triggers on the repository object created with the
64
+ # two command line arguments: the path to the repository and its revision
65
+ # number.
66
+ #
67
+ # If an exception occurs, the program will quit with its error message.
68
+ def self.run(*args)
69
+ Trigger.run(Repository.new(*args))
70
+ rescue Exception => e
71
+ puts "Error: #{e}" and exit(1)
72
+ end
73
+
74
+ # Define a new +Trigger+ object -- shortcut method to
75
+ # <tt>Trigger#define</tt>. To enable method chaining this method returns
76
+ # itself.
77
+ def self.on(pattern, &block)
78
+ Trigger.define(pattern, &block)
79
+ self
80
+ end
81
+ end
82
+
83
+ require 'subtrigger/email'
84
+ require 'subtrigger/trigger'
85
+ require 'subtrigger/repository'
@@ -0,0 +1,69 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{subtrigger}
8
+ s.version = "0.2.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Arjan van der Gaag"]
12
+ s.date = %q{2010-02-18}
13
+ s.default_executable = %q{subtrigger}
14
+ s.description = %q{This gem allows you to create simple Ruby triggers for Subversion commit messages, responding to keywords in your log messages to send e-mails, deploy sites or do whatever you need.}
15
+ s.email = %q{arjan@arjanvandergaag.nl}
16
+ s.executables = ["subtrigger"]
17
+ s.extra_rdoc_files = [
18
+ "LICENSE",
19
+ "README.rdoc"
20
+ ]
21
+ s.files = [
22
+ ".document",
23
+ ".gitignore",
24
+ "LICENSE",
25
+ "README.rdoc",
26
+ "Rakefile",
27
+ "VERSION",
28
+ "bin/subtrigger",
29
+ "lib/subtrigger.rb",
30
+ "lib/subtrigger/email.rb",
31
+ "lib/subtrigger/repository.rb",
32
+ "lib/subtrigger/trigger.rb",
33
+ "subtrigger.gemspec",
34
+ "test/helper.rb",
35
+ "test/test_email.rb",
36
+ "test/test_repository.rb",
37
+ "test/test_subtrigger.rb",
38
+ "test/test_trigger.rb"
39
+ ]
40
+ s.homepage = %q{http://github.com/avdgaag/subtrigger}
41
+ s.rdoc_options = ["--charset=UTF-8"]
42
+ s.require_paths = ["lib"]
43
+ s.rubygems_version = %q{1.3.5}
44
+ s.summary = %q{Create post-commit triggers for Subversion commit messages}
45
+ s.test_files = [
46
+ "test/helper.rb",
47
+ "test/test_email.rb",
48
+ "test/test_repository.rb",
49
+ "test/test_subtrigger.rb",
50
+ "test/test_trigger.rb"
51
+ ]
52
+
53
+ if s.respond_to? :specification_version then
54
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
55
+ s.specification_version = 3
56
+
57
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
58
+ s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
59
+ s.add_development_dependency(%q<mocha>, [">= 0"])
60
+ else
61
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
62
+ s.add_dependency(%q<mocha>, [">= 0"])
63
+ end
64
+ else
65
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
66
+ s.add_dependency(%q<mocha>, [">= 0"])
67
+ end
68
+ end
69
+
data/test/helper.rb ADDED
@@ -0,0 +1,11 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+ require 'mocha'
5
+
6
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
7
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
8
+ require 'subtrigger'
9
+
10
+ class Test::Unit::TestCase
11
+ end
@@ -0,0 +1,39 @@
1
+ require 'helper'
2
+
3
+ class TestEmail < Test::Unit::TestCase
4
+ context 'with attributes' do
5
+ setup do
6
+ @email = Subtrigger::Email.new(
7
+ :to => 'to@to.com',
8
+ :from => 'from@from.com',
9
+ :subject => 'subject',
10
+ :body => 'body',
11
+ :development => true
12
+ )
13
+ @message = @email.send
14
+ end
15
+
16
+ should 'set all e-mail attributes' do
17
+ assert_equal('from@from.com', @email.from)
18
+ assert_equal('to@to.com', @email.to)
19
+ assert_equal('subject', @email.subject)
20
+ assert_equal('body', @email.body)
21
+ end
22
+
23
+ should 'use to address' do
24
+ assert_match(/From: from@from.com/, @message)
25
+ end
26
+
27
+ should 'use from address' do
28
+ assert_match(/To: to@to.com/, @message)
29
+ end
30
+
31
+ should 'use subject' do
32
+ assert_match(/Subject: \[svn\] subject/, @message)
33
+ end
34
+
35
+ should 'use message body' do
36
+ assert_match(/body/, @message)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,41 @@
1
+ require 'helper'
2
+
3
+ class TestRepository < Test::Unit::TestCase
4
+ should 'not work on non-existant repo' do
5
+ assert_raise(RuntimeError) { Subtrigger::Repository.new('foo', 'bar') }
6
+ end
7
+
8
+ context 'for a repository' do
9
+ setup do
10
+ File.stubs(:directory?).returns(true)
11
+ @r = Subtrigger::Repository.new('path/to/repo', 1)
12
+ end
13
+
14
+ should 'not work on illegal revision' do
15
+ assert_raise(RuntimeError) { Subtrigger::Repository.new('foo', 'bar') }
16
+ end
17
+
18
+ should 'expand path' do
19
+ assert_equal('path/to/repo/foo', @r.path('foo'))
20
+ end
21
+
22
+ should 'use svnlook info' do
23
+ @r.expects(:look_at).with('info').returns('Foo')
24
+ assert_equal('Foo', @r.author)
25
+ end
26
+
27
+ should 'yield changed directories' do
28
+ @r.expects(:look_at).with('dirs-changed').returns("www.project1.com/trunk\nsub/www.project2.com/tags/v1")
29
+ yieldings = [
30
+ ['www.project1.com/trunk', 'www.project1.com'],
31
+ ['sub/www.project2.com/tags/v1', 'www.project2.com']
32
+ ]
33
+ i = 0
34
+ @r.changed_projects do |path, project|
35
+ assert_equal(yieldings[i][0], path)
36
+ assert_equal(yieldings[i][1], project)
37
+ i += 1
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,34 @@
1
+ require 'helper'
2
+
3
+ class TestSubtrigger < Test::Unit::TestCase
4
+ context 'with a clean slate' do
5
+ setup do
6
+ Subtrigger::Trigger.reset
7
+ end
8
+
9
+ should 'output the version number' do
10
+ assert_match(/\d+\.\d+\.\d+/, Subtrigger.version)
11
+ end
12
+
13
+ should 'Create new Repository object' do
14
+ Subtrigger::Repository.expects(:new).with('foo', '1')
15
+ Subtrigger.run('foo', '1')
16
+ end
17
+
18
+ should 'Run all triggers' do
19
+ Subtrigger::Repository.stubs(:new).returns('foo')
20
+ Subtrigger::Trigger.expects(:run).with('foo')
21
+ Subtrigger.run('foo', '1')
22
+ end
23
+
24
+ should 'create a new trigger' do
25
+ assert_equal(0, Subtrigger::Trigger.triggers.size)
26
+ Subtrigger.on(/foo/) { |m,r| }
27
+ assert_equal(1, Subtrigger::Trigger.triggers.size)
28
+ end
29
+
30
+ should 'chain creation of triggers' do
31
+ assert_equal(Subtrigger, Subtrigger.on(/foo/) { |m,r| })
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,37 @@
1
+ require 'helper'
2
+
3
+ class TestTrigger < Test::Unit::TestCase
4
+ context 'in a clean state' do
5
+ setup do
6
+ Subtrigger::Trigger.reset
7
+ end
8
+
9
+ should 'define a new trigger' do
10
+ Subtrigger::Trigger.define(/foo/) { |m, r| raise 'bar' }
11
+ assert_equal(1, Subtrigger::Trigger.triggers.size)
12
+ end
13
+
14
+ should 'apply all triggers' do
15
+ i = 0
16
+ Subtrigger::Trigger.define(/foo/) { |m,r| i += 1 }
17
+ Subtrigger::Trigger.define(/o+/) { |m,r| i += 1 }
18
+ Subtrigger::Trigger.run(stub(:message => 'foo bar'))
19
+ assert_equal(2, i)
20
+ end
21
+
22
+ should 'ignore unmatching triggers' do
23
+ i = 0
24
+ Subtrigger::Trigger.define(/foo/) { |m,r| i += 1 }
25
+ Subtrigger::Trigger.define(/x+/) { |m,r| i += 1 }
26
+ Subtrigger::Trigger.run(stub(:message => 'foo bar'))
27
+ assert_equal(1, i)
28
+ end
29
+
30
+ should 'empty list of triggers' do
31
+ Subtrigger::Trigger.define(/foo/) { |m,r| }
32
+ assert_equal(1, Subtrigger::Trigger.triggers.size)
33
+ Subtrigger::Trigger.reset
34
+ assert_equal(0, Subtrigger::Trigger.triggers.size)
35
+ end
36
+ end
37
+ end
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: subtrigger
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Arjan van der Gaag
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-02-18 00:00:00 +01:00
13
+ default_executable: subtrigger
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: thoughtbot-shoulda
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: mocha
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ description: This gem allows you to create simple Ruby triggers for Subversion commit messages, responding to keywords in your log messages to send e-mails, deploy sites or do whatever you need.
36
+ email: arjan@arjanvandergaag.nl
37
+ executables:
38
+ - subtrigger
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - LICENSE
43
+ - README.rdoc
44
+ files:
45
+ - .document
46
+ - .gitignore
47
+ - LICENSE
48
+ - README.rdoc
49
+ - Rakefile
50
+ - VERSION
51
+ - bin/subtrigger
52
+ - lib/subtrigger.rb
53
+ - lib/subtrigger/email.rb
54
+ - lib/subtrigger/repository.rb
55
+ - lib/subtrigger/trigger.rb
56
+ - subtrigger.gemspec
57
+ - test/helper.rb
58
+ - test/test_email.rb
59
+ - test/test_repository.rb
60
+ - test/test_subtrigger.rb
61
+ - test/test_trigger.rb
62
+ has_rdoc: true
63
+ homepage: http://github.com/avdgaag/subtrigger
64
+ licenses: []
65
+
66
+ post_install_message:
67
+ rdoc_options:
68
+ - --charset=UTF-8
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: "0"
76
+ version:
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: "0"
82
+ version:
83
+ requirements: []
84
+
85
+ rubyforge_project:
86
+ rubygems_version: 1.3.5
87
+ signing_key:
88
+ specification_version: 3
89
+ summary: Create post-commit triggers for Subversion commit messages
90
+ test_files:
91
+ - test/helper.rb
92
+ - test/test_email.rb
93
+ - test/test_repository.rb
94
+ - test/test_subtrigger.rb
95
+ - test/test_trigger.rb