Skip to content

Instantly share code, notes, and snippets.

@slucero
Created November 5, 2015 20:10
Show Gist options
  • Save slucero/6807c6cf57a801ce92b4 to your computer and use it in GitHub Desktop.
Save slucero/6807c6cf57a801ce92b4 to your computer and use it in GitHub Desktop.
A Git hook for prepending commit messages with an issue number found in the current working branch. It's organized for use with the https://github.com/icefox/git-hooks project for managing git hooks.
#! /usr/bin/env ruby
# ~/.git_hooks/lib/issue_numbers.rb
$issue_pattern = /\d{5}(?=-)/
#require 'git'
#g = Git.open(working_dir, :log => Logger.new(STDOUT))
# TODO: Break out separate Branch class
class Commit
attr_accessor :git_root, :merge_branch, :current_branch,
:current_issue
def initialize
@related_issues = []
# Determine relevant git directories
@git_root = %x{git rev-parse --show-toplevel}.chomp
@git_dir = "#{@git_root}/.git"
# Examine current branches
@current_branch = get_branch_name(%x{git symbolic-ref HEAD})
@current_issue = Commit.parse_issue_number(@current_branch)
add_related_issue(@current_issue) unless @current_issue.nil?
if is_merge?
@merge_branch = parse_merge_branch
@merge_issue = Commit.parse_issue_number(@merge_branch)
add_related_issue(@merge_issue) unless @merge_issue.nil?
end
end
def self.parse_issue_number(str)
match = $issue_pattern.match(str)
unless match.nil?
match.to_s
end
end
def add_related_issue(issue)
@related_issues << issue
end
# TODO: Resolve why this isn't picking up the initial merge state
def is_merge?
File.exists? "#{@git_dir}/MERGE_HEAD"
end
def parse_merge_branch
merge_hash = %x{cat '#{@git_dir}/MERGE_HEAD'}
get_branch_name(merge_hash)
end
def get_branch_name(hash)
ref = %x{git describe --all --exact-match #{hash}}.chomp
if $?
return ref.gsub('heads/', '')
else
return nil
end
end
def commit_prefix
prefix = ""
@related_issues.each do |issue|
prefix << "[##{issue}]"
end
prefix << ' ' unless @related_issues.empty?
end
end
#! /usr/bin/env ruby
# ~/.git_hooks/prepare-commit-msg/prepend-issue-number
# --------------------------------------------------------------------------------
# Git hook script to search merge commits for possible issue numbers and prepend them
# in a standardized flag at the beginning of the commit message.
#
# Currently the script only searches for 5 digit number sequences and prepends those
# to the commit message on the assumption it's the branch number. In the case of most
# merges this issue number is expected to come from the branch name being merged.
# --------------------------------------------------------------------------------
require_relative '../lib/issue_numbers.rb'
require 'tempfile'
# Return description of the task if --about flag is provided.
if ARGV[0] == '--about' then
puts "Insert the issue number in the merge commit message if available in branch name."
exit
end
msg_file = ARGV[0]
commit_type = ARGV[1]
# TODO: Check for pre-existing issue tags
def prepend_issue_prefix(prefix, msg_file)
# Compile full commit message in a temporary file to avoid
# potential memory leaks from loading a large file into memory
temp = Tempfile.open('tmp_msg') { |tf|
# Print prefix at the beginning
tf.print(prefix);
# Read and merge the existing file
tf.print(File.read(msg_file));
# Return the temp file for the move step
tf
}
# Replace the original file with the newly merged file
FileUtils.move(temp.path(), msg_file)
end
# Parse the issue number from the branch name in the default commit message
def fetch_commit_msg(msg_file)
File.open(msg_file) do |handle|
msg = handle.readline
Commit.parse_issue_number(msg)
end
end
c = Commit.new
# Special handling for merges
if commit_type == 'merge'
# We only need special handling if the lib isn't picking it up
unless c.is_merge?
issue = fetch_commit_msg(msg_file)
c.add_related_issue(issue) unless issue.nil?
end
end
prefix = c.commit_prefix
unless prefix.nil? || prefix.empty?
prepend_issue_prefix(prefix, msg_file)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment