Blame progit/hooks/files/progit_hook_tickets.py

Pierre-Yves Chibon a3d1b1
#! /usr/bin/env python2
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon a3d1b1
"""Progit specific hook to update tickets stored in the database based on
Pierre-Yves Chibon a3d1b1
the information pushed in the tickets git repository.
Pierre-Yves Chibon a3d1b1
"""
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon c7f9fa
import json
Pierre-Yves Chibon a3d1b1
import os
Pierre-Yves Chibon a3d1b1
import re
Pierre-Yves Chibon a3d1b1
import sys
Pierre-Yves Chibon a3d1b1
import subprocess
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon a3d1b1
# We need to access the database
Pierre-Yves Chibon a3d1b1
if 'PROGIT_CONFIG' not in os.environ \
Pierre-Yves Chibon a3d1b1
        and os.path.exists('/etc/progit/progit.cfg'):
Pierre-Yves Chibon a3d1b1
    print 'Using configuration file `/etc/progit/progit.cfg`'
Pierre-Yves Chibon a3d1b1
    os.environ['PROGIT_CONFIG'] = '/etc/progit/progit.cfg'
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon a3d1b1
sys.path.insert(0, os.path.expanduser('~/repos/gitrepo/progit'))
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon c7f9fa
import progit.lib.git
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon a3d1b1
def read_git_output(args, input=None, keepends=False, **kw):
Pierre-Yves Chibon a3d1b1
    """Read the output of a Git command."""
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon a3d1b1
    return read_output(['git'] + args, input=input, keepends=keepends, **kw)
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon a3d1b1
def read_git_lines(args, keepends=False, **kw):
Pierre-Yves Chibon a3d1b1
    """Return the lines output by Git command.
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon a3d1b1
    Return as single lines, with newlines stripped off."""
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon a3d1b1
    return read_git_output(args, keepends=True, **kw).splitlines(keepends)
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon a3d1b1
def read_output(cmd, input=None, keepends=False, **kw):
Pierre-Yves Chibon a3d1b1
    if input:
Pierre-Yves Chibon a3d1b1
        stdin = subprocess.PIPE
Pierre-Yves Chibon a3d1b1
    else:
Pierre-Yves Chibon a3d1b1
        stdin = None
Pierre-Yves Chibon a3d1b1
    p = subprocess.Popen(
Pierre-Yves Chibon a3d1b1
        cmd, stdin=stdin, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kw
Pierre-Yves Chibon a3d1b1
        )
Pierre-Yves Chibon a3d1b1
    (out, err) = p.communicate(input)
Pierre-Yves Chibon a3d1b1
    retcode = p.wait()
Pierre-Yves Chibon a3d1b1
    if retcode:
Pierre-Yves Chibon a3d1b1
        print 'ERROR: %s =-- %s' % (cmd, retcode)
Pierre-Yves Chibon a3d1b1
    if not keepends:
Pierre-Yves Chibon a3d1b1
        out = out.rstrip('\n\r')
Pierre-Yves Chibon a3d1b1
    return out
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon a3d1b1
def get_files_to_load(new_commits_list):
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon c7f9fa
    print 'Files changed by new commits:\n'
Pierre-Yves Chibon a3d1b1
    file_list = []
Pierre-Yves Chibon c7f9fa
    new_commits_list.reverse()
Pierre-Yves Chibon c7f9fa
    for commit in new_commits_list:
Pierre-Yves Chibon c7f9fa
        filenames = read_git_lines(
Pierre-Yves Chibon c7f9fa
            ['diff-tree', '--no-commit-id', '--name-only', '-r', commit],
Pierre-Yves Chibon c7f9fa
            keepends=False)
Pierre-Yves Chibon c7f9fa
        for line in filenames:
Pierre-Yves Chibon c7f9fa
            if line.strip():
Pierre-Yves Chibon c7f9fa
                file_list.append(line.strip())
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon a3d1b1
    return file_list
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon a3d1b1
def get_commits_id(fromrev, torev):
Pierre-Yves Chibon a3d1b1
    ''' Retrieve the list commit between two revisions and return the list
Pierre-Yves Chibon a3d1b1
    of their identifier.
Pierre-Yves Chibon a3d1b1
    '''
Pierre-Yves Chibon a5e463
    cmd = ['rev-list', '%s...%s' % (torev, fromrev)]
Pierre-Yves Chibon c7f9fa
    if set(fromrev) == set('0'):
Pierre-Yves Chibon c7f9fa
        cmd = ['rev-list', '%s' % torev]
Pierre-Yves Chibon c7f9fa
    output = read_git_lines(cmd)
Pierre-Yves Chibon c7f9fa
    return output
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon a3d1b1
def get_repo_name():
Pierre-Yves Chibon a3d1b1
    ''' Return the name of the git repo based on its path.
Pierre-Yves Chibon a3d1b1
    '''
Pierre-Yves Chibon a3d1b1
    repo = os.path.basename(os.getcwd()).split('.git')[0]
Pierre-Yves Chibon a3d1b1
    return repo
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon c7f9fa
def get_username():
Pierre-Yves Chibon c7f9fa
    ''' Return the username of the git repo based on its path.
Pierre-Yves Chibon c7f9fa
    '''
Pierre-Yves Chibon c7f9fa
    username = None
Pierre-Yves Chibon c7f9fa
    repo = os.path.abspath(os.path.join(os.getcwd(), '..'))
Pierre-Yves Chibon c7f9fa
    if progit.APP.config['TICKETS_FOLDER'] in repo:
Pierre-Yves Chibon c7f9fa
        username = repo.split(progit.APP.config['TICKETS_FOLDER'])[1]
Pierre-Yves Chibon c7f9fa
    return username
Pierre-Yves Chibon c7f9fa
Pierre-Yves Chibon c7f9fa
Pierre-Yves Chibon a3d1b1
def run_as_post_receive_hook():
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon a3d1b1
    file_list = set()
Pierre-Yves Chibon a3d1b1
    for line in sys.stdin:
Pierre-Yves Chibon a3d1b1
        print line
Pierre-Yves Chibon a3d1b1
        (oldrev, newrev, refname) = line.strip().split(' ', 2)
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon a3d1b1
        print '  -- Old rev'
Pierre-Yves Chibon a3d1b1
        print oldrev
Pierre-Yves Chibon a3d1b1
        print '  -- New rev'
Pierre-Yves Chibon a3d1b1
        print newrev
Pierre-Yves Chibon a3d1b1
        print '  -- Ref name'
Pierre-Yves Chibon a3d1b1
        print refname
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon c7f9fa
        tmp = set(get_files_to_load(get_commits_id(oldrev, newrev)))
Pierre-Yves Chibon c7f9fa
        file_list = file_list.union(tmp)
Pierre-Yves Chibon c7f9fa
Pierre-Yves Chibon c7f9fa
    reponame = get_repo_name()
Pierre-Yves Chibon c7f9fa
    username = get_username()
Pierre-Yves Chibon c7f9fa
    print 'repo:', reponame, username
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon a3d1b1
    for filename in file_list:
Pierre-Yves Chibon a3d1b1
        print 'To load: %s' % filename
Pierre-Yves Chibon c7f9fa
        data = ''.join(read_git_lines(['show', 'HEAD:%s' % filename]))
Pierre-Yves Chibon c7f9fa
        if data:
Pierre-Yves Chibon c7f9fa
            data = json.loads(data)
Pierre-Yves Chibon c7f9fa
        if data:
Pierre-Yves Chibon c7f9fa
            progit.lib.git.update_ticket_from_git(
Pierre-Yves Chibon c7f9fa
                progit.SESSION,
Pierre-Yves Chibon c7f9fa
                reponame=reponame,
Pierre-Yves Chibon c7f9fa
                username=username,
Pierre-Yves Chibon c7f9fa
                issue_uid=filename,
Pierre-Yves Chibon c7f9fa
                json_data=data)
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon a3d1b1
def main(args):
Pierre-Yves Chibon c7f9fa
    run_as_post_receive_hook()
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon a3d1b1
Pierre-Yves Chibon a3d1b1
if __name__ == '__main__':
Pierre-Yves Chibon a3d1b1
    main(sys.argv[1:])