Created
April 10, 2012 07:14
-
-
Save insoul/2348958 to your computer and use it in GitHub Desktop.
git commit hook for redmine
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
BASEDIR = ENV["HOME"] + "/.git_redmine" | |
require BASEDIR + "/git_redmine" | |
include GitRedmine::Hooks | |
exit commit_msg(ARGV[0]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#host: localhost | |
#access_key: 1234567890abcdefg1234567890abcdefg123456 | |
#port: 80 # default 80 | |
#verbose: true # default nil | |
#reqtrace: true # default nil |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
GIT_REDMINE=$HOME/.git_redmine | |
if [ -e $GIT_REDMINE ]; then | |
echo "git_redmine directory $GIT_REDMINE" | |
else | |
echo "ERROR: git_redmine directory $GIT_REDMINE not exists" | |
exit 1 | |
fi | |
if [ -e `pwd`/.git/hooks/commit-msg ]; then | |
echo 'ERROR: Already there is commit-msg hook' | |
echo ' Remove first .git/hooks/commit-msg file' | |
exit 1 | |
fi | |
if [ -e `pwd`/.git/hooks/post-commit ]; then | |
echo 'ERROR: Already there is post-commit hook' | |
echo ' Remove first .git/hooks/post-commit file' | |
exit 1 | |
fi | |
echo 'symlink to .git/hooks/commit-msg' | |
ln -s $GIT_REDMINE/commit-msg .git/hooks/commit-msg | |
echo 'symlink to .git/hooks/post-commit' | |
ln -s $GIT_REDMINE/post-commit .git/hooks/post-commit |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'rubygems' | |
require 'redminer' | |
require 'yaml' | |
module GitRedmine | |
class MessageFormatError < RuntimeError; end | |
class CommitLogError < RuntimeError; end | |
class DiffError < RuntimeError; end | |
class GitVersionError < RuntimeError; end | |
module Config | |
# host: Issue tracker host | |
# port: Issue tracker port # default 80 | |
# access_key: Issue tracker api access_key | |
# verbose: Trace error option # default false | |
CONFIG = YAML.load_file(File.dirname(__FILE__) + '/config.yml') rescue {} | |
def host; CONFIG["host"] end | |
def port; CONFIG["port"] || 80 end | |
def access_key; CONFIG["access_key"] end | |
def verbose; CONFIG["verbose"] end | |
def redmine | |
opts = {:port=>port, :verbose=>verbose, :reqtrace=>CONFIG["reqtrace"]} | |
@redmine ||= Redminer::Base.new(host, access_key, opts) | |
end | |
def redmine_url | |
ret = "http://#{host}" | |
ret << ":#{port}" if port != 80 | |
ret | |
end | |
end | |
module GitCommands | |
def backward_commit_hash(backward_number) | |
`git log -#{backward_number} --format='%H'`.split("\n").last | |
end | |
def last_commit_log | |
l = `git log -1 --format="%B"` | |
raise GitVersionError.new('git version ~> 1.7.9') if l =~ /%B/ | |
l | |
end | |
def diff_from(hash) | |
`git diff #{hash}..HEAD --stat` | |
end | |
def origin_path | |
remote = `git remote -v`.split("\n")[0] | |
return if remote.nil? | |
url = remote.split(" ")[1] | |
url = url.gsub(/.*@/, '').gsub(/\.git$/, '').gsub(':', '/') | |
url | |
end | |
end | |
class CommitMessage | |
include Config | |
attr_accessor :issue_id, :message | |
def issue_url | |
"#{redmine_url}/issues/#{issue_id}" | |
end | |
end | |
class InputCommitMessage < CommitMessage | |
def initialize(commit_msg_file) | |
@msg = "" | |
File.open(commit_msg_file) do |f| | |
while true | |
begin | |
@msg << f.readline | |
rescue EOFError | |
break | |
end | |
end | |
end | |
match = @msg.scan(/^@(\d+) (.*)/m) | |
match = @msg.scan(/^(\d+) (.*)/m) if match.empty? | |
match = @msg.scan(/^#{redmine_url}\/issues\/(\d+) (.*)/m) if match.empty? | |
if match.empty? | |
raise MessageFormatError.new("commit message format error\n\n#{@msg}") | |
end | |
msg = match[0][1] || "" | |
msg = msg.strip[1..-1] if msg.strip.start_with?($/) | |
msg = msg.split(/diff --git/)[0] || "" | |
# 원본 메시지가 @로 시작하는 경우 msg의 첫번째라인은 무시한다. | |
# redmine 제목이고 자동으로 붙여지기 때문. | |
msg = msg.split($/, 2)[1] || "" if @msg.start_with?("@") | |
# msg의 마지막이 redmine주소인 경우 제거한다. | |
msg = msg.gsub(/#{$/}#{redmine_url}\/issues\/\d+#{$/}*$/, '') | |
@issue_id = match[0][0].to_i | |
@message = msg | |
end | |
end | |
class RemakeCommitMessage < CommitMessage | |
include GitCommands | |
attr_accessor :hash | |
def initialize | |
@hash = backward_commit_hash(2) | |
res = last_commit_log | |
raise CommitLogError.new if res.length < 3 | |
self.parse(res) | |
end | |
def diff | |
df = diff_from(self.hash) | |
raise DiffError.new("cannot retrieve diff") if df.empty? | |
df | |
end | |
# commit is a InputCommitMessage instance | |
def self.remake(commit, issue) | |
remake_msg = "@#{commit.issue_id} #{issue.subject}" | |
unless commit.message.empty? | |
remake_msg << "\n#{commit.message}" | |
end | |
remake_msg << "\n\n#{redmine_url}/issues/#{issue.id}" | |
remake_msg | |
end | |
# res is a string of remade commit message | |
def parse(res) | |
res = res.split("\n") | |
@issue_id = res.delete_at(0).scan(/^@(\d+) /)[0][0] rescue nil | |
if @issue_id.nil? or @issue_id.empty? | |
raise MessageFormatError.new("cannot find issue id\n\n#{res}") | |
end | |
@issue_id = issue_id.to_i | |
issue_link = res.index { |ln| ln =~ /^http:\/\/#{host}/ } | |
unless issue_link.nil? | |
res.delete_at(issue_link) or | |
(res[its-1].strip.empty? and res.delete_at(issue_link-1)) | |
end | |
@message = res | |
end | |
def origin_url | |
path = origin_path | |
return if path.nil? | |
"http://#{path}/commit/#{hash}" | |
end | |
end | |
module Hooks | |
include GitCommands | |
include Config | |
def commit_msg(commit_msg_file) | |
puts 'Hook: commit-msg' | |
commit = InputCommitMessage.new(commit_msg_file) | |
issue = redmine.issue(commit.issue_id) | |
remake_msg = RemakeCommitMessage.remake(commit, issue) | |
File.open(commit_msg_file, 'w+') { |f| f << remake_msg } | |
ret = 0 | |
rescue MessageFormatError => e | |
error("Commit message format is not valid") | |
puts "Commit message format:" | |
puts " <issue id> <message>" | |
puts "Example:" | |
puts " 450 fix error" | |
puts " #{redmine_url}/issues/450 fix error" | |
ret = 1 | |
rescue => e | |
error(e.message) | |
ret = 1 | |
ensure | |
puts e.backtrace.join("\n") if verbose and defined?(e) and not e.nil? | |
ret | |
end | |
def post_commit | |
puts 'Hook: post-commit' | |
out = "Commit completed, " | |
commit = RemakeCommitMessage.new | |
issue = redmine.issue(commit.issue_id) | |
diff = commit.diff | |
diff = "<pre>#{diff}</pre>" | |
commit_link = commit.origin_url | |
commit_link = if commit_link | |
"commit:\"#{commit.hash[0..6]}\":#{commit.origin_url}" | |
else | |
"commit:#{commit.hash[0..6]}" | |
end | |
note = "#{commit.message}\n\n#{commit_link}\n#{diff}" | |
issue.update(note) | |
ret = 0 | |
rescue => e | |
warn("#{out}, But error occurred... #{e.message}") | |
ret = 1 | |
ensure | |
puts e.backtrace.join("\n") if verbose and defined?(e) and not e.nil? | |
ret | |
end | |
def error(msg) | |
puts "ERROR!\n\t#{msg}" | |
puts "\tWanna skip verification? use --no-verify option\n" | |
true | |
end | |
def warn(msg) | |
puts "WARNING!\n\t#{msg}\n" | |
true | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
gem install redminer | |
cd $HOME | |
git clone git://gist.github.com/2348958.git .git_redmine | |
chmod +x .git_redmine/commit-msg | |
chmod +x .git_redmine/post-commit | |
chmod +x .git_redmine/git_redmine | |
echo 'alias git_redmine=~/.git_redmine/git_redmine' >> .bash_profile | |
echo '' | |
echo 'Install git_redmine complete!!' | |
echo 'You must edit ~/.git_redmine/config.yml' | |
echo "Usage is run 'git_redmine' in git working copy" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
BASEDIR = ENV["HOME"] + "/.git_redmine" | |
require BASEDIR + "/git_redmine" | |
include GitRedmine::Hooks | |
exit post_commit |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment