#!/usr/bin/env ruby # # An example hook script for the post-receive event # # This script is run after receive-pack has accepted a pack and the # repository has been updated. It is passed arguments in through stdin # in the form # # For example: # aa453216d1b3e49e7f6f98441fa56946ddcd6a20 68f7abf4e6f922807889f52bc043ecd31b79f814 refs/heads/master # This class is based on git contrib script post-receive-email BREAKOUT_ROOT = ENV["BREAKOUT_ROOT"] || "/u/apps/breakout/current" $:.unshift(BREAKOUT_ROOT + '/lib') require "rubygems" require "activesupport" require File.join(BREAKOUT_ROOT, "config", "environments", "user_environment") require "inifile" require "changesets_client" class GitPostReceiveHook attr_accessor :old_rev, :new_rev, :ref, :debug cattr_accessor :secret, :spaces_tool_id # Limit commits count in push LIMIT_COUNT = 100 NULL_COMMIT_RE = /^0{40}$/ def initialize(old_rev, new_rev, ref) self.old_rev = old_rev self.new_rev = new_rev self.ref = ref self.debug = false end def go put_line '/' @change_type = if @old_rev =~ NULL_COMMIT_RE :create elsif @new_rev =~ NULL_COMMIT_RE :delete else :update end old_rev_type = new_rev_type = "" old_rev_type = `git cat-file -t #{@old_rev}`.chomp if @change_type != :create new_rev_type = `git cat-file -t #{@new_rev}`.chomp if @change_type != :delete if @debug put_line p @ref, @old_rev, @new_rev, @change_type, new_rev_type, old_rev_type end rev, rev_type = if @change_type == :create || @chage_type == :update [@new_rev, new_rev_type] else [@old_rev, old_rev_type] end if @ref =~ /^refs\/heads\/(.+)$/ @branch = $1 if @change_type == :create if old_rev_type == "" # New branch put_line '+' commits = load_commits @new_rev send_logs commits elsif new_rev_type == "" # branch delete put_line '-' end elsif @change_type == :update commits = load_commits "#{@old_rev}..#{@new_rev}" send_logs commits end else raise "Not Implemented! TODO" end end def send_logs(logs) parsed_logs = parse_pretty_logs(logs) parsed_logs.each do |hash| params = { "tool_id" => 2, "spaces_tool_id" => @@spaces_tool_id, "secret_key" => @@secret, "username" => hash[:email], "comment" => hash[:comment], "external_id" => hash[:commit] } p params if debug begin ChangesetsClient.post(params) rescue Timeout::Error => e # Maybe we will serialize to disk and try later ? rescue => e1 p e1 end end end def load_commits(treeish) run "git rev-parse --not --branches | grep -v $(git rev-parse #{@branch}) | git rev-list --max-count=#{LIMIT_COUNT} --reverse --pretty --stdin #{treeish}" end def parse_pretty_logs(logs) rez = [] commit = {} logs.each_line do |line| if line =~ /^commit ([0-9a-f]+)/i if commit.size > 0 rez << commit commit = {} end commit[:commit] = $1 elsif line =~ /^Author: (.+)$/i name, email = $1.split '<' email.tr! '>', '' commit[:name] = name.strip commit[:email] = email.strip elsif line =~ /^Date: (.+)$/i commit[:date] = $1.strip elsif line =~ /^\s{4}/ commit[:comment] ||= "" commit[:comment] << line.strip << "\n" end end # push last commit rez << commit if commit.size > 0 rez end def run(cmd) puts "$ #{cmd}" if @debug `#{cmd}` end def put_line(char = '*') puts char * 80 if @debug end end if __FILE__ == $0 config = IniFile.new("breakout.ini") GitPostReceiveHook.secret = config["breakout"]["secretKey"] GitPostReceiveHook.spaces_tool_id = config["breakout"]["space_tool_id"] loop do line = $stdin.read break if !line || line.length == 0 line.chomp old_rev, new_rev, ref = line.split(/ /, 3) gpr = GitPostReceiveHook.new(old_rev.chomp, new_rev.chomp, ref.chomp) gpr.debug = true if config['git'] && config['git']['debug'] gpr.go end end