Blob Blame Raw
#! /usr/bin/env python2


"""Progit specific hook to update tickets stored in the database based on
the information pushed in the tickets git repository.
"""

import json
import os
import re
import sys
import subprocess


# We need to access the database
if 'PROGIT_CONFIG' not in os.environ \
        and os.path.exists('/etc/progit/progit.cfg'):
    print 'Using configuration file `/etc/progit/progit.cfg`'
    os.environ['PROGIT_CONFIG'] = '/etc/progit/progit.cfg'

sys.path.insert(0, os.path.expanduser('~/repos/gitrepo/progit'))

import progit.lib.git

def read_git_output(args, input=None, keepends=False, **kw):
    """Read the output of a Git command."""

    return read_output(['git'] + args, input=input, keepends=keepends, **kw)


def read_git_lines(args, keepends=False, **kw):
    """Return the lines output by Git command.

    Return as single lines, with newlines stripped off."""

    return read_git_output(args, keepends=True, **kw).splitlines(keepends)


def read_output(cmd, input=None, keepends=False, **kw):
    if input:
        stdin = subprocess.PIPE
    else:
        stdin = None
    p = subprocess.Popen(
        cmd, stdin=stdin, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kw
        )
    (out, err) = p.communicate(input)
    retcode = p.wait()
    if retcode:
        print 'ERROR: %s =-- %s' % (cmd, retcode)
    if not keepends:
        out = out.rstrip('\n\r')
    return out


def get_files_to_load(new_commits_list):

    print 'Files changed by new commits:\n'
    file_list = []
    new_commits_list.reverse()
    for commit in new_commits_list:
        filenames = read_git_lines(
            ['diff-tree', '--no-commit-id', '--name-only', '-r', commit],
            keepends=False)
        for line in filenames:
            if line.strip():
                file_list.append(line.strip())

    return file_list


def get_commits_id(fromrev, torev):
    ''' Retrieve the list commit between two revisions and return the list
    of their identifier.
    '''
    cmd = ['rev-list', '%s...%s' % (torev, fromrev)]
    if set(fromrev) == set('0'):
        cmd = ['rev-list', '%s' % torev]
    output = read_git_lines(cmd)
    return output


def get_repo_name():
    ''' Return the name of the git repo based on its path.
    '''
    repo = os.path.basename(os.getcwd()).split('.git')[0]
    return repo


def get_username():
    ''' Return the username of the git repo based on its path.
    '''
    username = None
    repo = os.path.abspath(os.path.join(os.getcwd(), '..'))
    if progit.APP.config['TICKETS_FOLDER'] in repo:
        username = repo.split(progit.APP.config['TICKETS_FOLDER'])[1]
    return username


def run_as_post_receive_hook():

    file_list = set()
    for line in sys.stdin:
        print line
        (oldrev, newrev, refname) = line.strip().split(' ', 2)

        print '  -- Old rev'
        print oldrev
        print '  -- New rev'
        print newrev
        print '  -- Ref name'
        print refname

        tmp = set(get_files_to_load(get_commits_id(oldrev, newrev)))
        file_list = file_list.union(tmp)

    reponame = get_repo_name()
    username = get_username()
    print 'repo:', reponame, username

    for filename in file_list:
        print 'To load: %s' % filename
        data = ''.join(read_git_lines(['show', 'HEAD:%s' % filename]))
        if data:
            data = json.loads(data)
        if data:
            progit.lib.git.update_ticket_from_git(
                progit.SESSION,
                reponame=reponame,
                username=username,
                issue_uid=filename,
                json_data=data)


def main(args):
    run_as_post_receive_hook()


if __name__ == '__main__':
    main(sys.argv[1:])