#!/usr/bin/python
#
# 2012 patrick.atamaniuk@wibas.de
# requires python2.7
# requires pika, gitpython
# 
# sends github-json-api like push events
#


import sys,os,re
import time
import simplejson
import pika
from git import Repo

RABBITMQ_QUEUE = 'myownci.git.commit'
APP_ID = 'myownci.git.hooks.post-receive'

zero = re.compile(r'^0{40}')

class ConfigurationError(Exception): pass

class Gitaccess:
    def __init__(self):
        self.repo = Repo.init(".", bare=True)

    def get_config(self):
        self.reader = self.repo.config_reader()
# may raise ConfigParser.NoSectionError ConfigParser.NoOptionError 
        return {
          'hub_addr': self.reader.get('myownci', 'hub-addr'),
          'repository_id': self.reader.get('myownci', 'repository-id'),
          'project_configfile': self.reader.get('myownci', 'project-configfile')
        }

    def get_commitinfo(self, hexsha):
        commit = self.repo.commit(hexsha)
        return {
            'sha': hexsha,
            'author': {'name':commit.author.name, 'email':commit.author.email},
            'committer': {'name':commit.committer.name, 'email':commit.committer.email},
            'committed_date': commit.committed_date,
            'message': commit.message,
            'url': ''
        }
    def get_buildinfo(self, hexsha, filename):
        tree = self.repo.tree(hexsha)
        buildconfig = ''
        try:
            project_configfile = tree[filename]
            buildconfig = project_configfile.data_stream.read()
        except KeyError: #file not found in repo
            raise ConfigurationError
        return buildconfig

class Amqpadapter:
    def __init__(self):
        self.g = Gitaccess()
        self.config = self.g.get_config()

    def send(self, commit, data = None):
        for commit in data['commits']:
          commit.update(self.g.get_commitinfo(commit['sha']))
        data['buildconfig'] = self.g.get_buildinfo(data['head'], self.config['project_configfile'])
        data['repository_id'] = self.config['repository_id']

        connection = pika.BlockingConnection(pika.ConnectionParameters(
            host = self.config['hub_addr']))
        channel = connection.channel()

        channel.queue_declare(queue=RABBITMQ_QUEUE, durable=True)

        channel.basic_publish(exchange = '',
                      routing_key = RABBITMQ_QUEUE,
                      body = simplejson.dumps(data),
                      properties = pika.BasicProperties(
                        app_id = APP_ID,
                        content_type = 'application/json',
                        timestamp = time.time(),
                        delivery_mode = 2, # make message persistent
                        headers = {}
                     ))
        connection.close()
        print " [ok] Notified CI."

def main():
    commits = []
    old = ''
    new = ''
    for line in sys.stdin.readlines():
        (old, new, ref) = line.strip().split(" ")[:3]
        if zero.match(new): continue 
        if old == new: continue
        commits.append({'sha':new})
    Amqpadapter().send(new, { 
        'ref': ref,
        'size': len(commits),
        'head': new,
        'commits': commits })

if __name__ == '__main__':
  try:
    main()
  except Exception, e:
    print("CI notify: An error has occured: %s" %repr(e))
    #raise
sys.exit(0)
