views:

332

answers:

2

I am running into a problem when running the follow python script on the server looking for commit information for the push making sure it follows a particular syntax, I am unable to get input from the user which is why the username and password are hard coded. I am now also unable to get the list of commit message that occurred before this particular push.

#!/usr/bin/python

import SOAPpy 
import getpass 
import datetime
import sys
import re
import logging
import os


def login(x,y):
    try:
        auth = soap.login(x, y)
        return auth
    except:
          sys.exit( "Invalid username or password")

def getIssue(auth,issue):
    try:
        issue = soap.getIssue(auth, issue)
    except:
        sys.exit("No issue of that type found : Make sure all PRs are vaild jira PRs")

def git_get_commit_msg(commit_id):
    return get_shell_cmd_output("git rev-list --pretty --max-count=1 " + commit_id)

def git_get_last_commit_id():
    return get_shell_cmd_output("git log --pretty=format:%H -1")

def getCommitText():
    commit_msg_filename = sys.argv[1]
    try:
        commit_msg_text = open(commit_msg_filename).read()
        return commit_msg_text
    except:
        sys.exit("Could not read commit message")

def git_get_array_of_commit_ids(start_id, end_id):
    output = get_shell_cmd_output("git rev-list " + start_id + ".." + end_id)
    if output == "":
        return None
    commit_id_array = string.split(output, '\n')
    return commit_id_array

def get_shell_cmd_output(cmd):
    try:
        proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
        return proc.stdout.read().rstrip('\n')
    except KeyboardInterrupt:
        logging.info("... interrupted")

    except Exception, e:
        logging.error("Failed trying to execute '%s'", cmd)

def findpattern(commit_msg):
    pattern = re.compile("\w\w*-\d\d*")
    group = pattern.findall(commit_msg)
    print group
    found = len(group)
    found =0
    issues = 0
    for match in group:
            auth = soap.login(jirauser,passwd)
            getIssue(auth,match)
            issues = issues + 1
            found+=1
    if found ==0:
        sys.exit("No issue patterns found.")

    print "Retrieved issues: " + str(issues)  

def update():
    print sys.argv[2]
    print sys.argv[3]
    old_commit_id = sys.argv[2]
    new_commit_id = sys.argv[3]
    commit_id_array = git_get_array_of_commit_ids(old_commit_id, new_commit_id)
    for commit_id in commit_id_array:
        commit_text = git_get_commit_msg(commit_id)
        findpattern(commit_text)

soap = SOAPpy.WSDL.Proxy('some url')
# this line if for repointing the input from dev/null
#sys.stdin = open('/dev/tty', 'r') # this fails horribly.
#ask user for input
#jirauser = raw_inp
#("Username for jira: ")
jirauser = "username"
passwd = "987654321"
#passwd = getpass.getpass("Password for %s: " % jirauser)
login(jirauser,passwd)
#commit_msg = getCommitText()
#findpattern(commit_msg)
update()

The intended goal of this code is to check the commits made locally, and to parse through them for the intended pattern, as well as checking the in jira if that PR exists. it is a server side hook that get activated on a push to the repository.

Any tips on writing python hooks would be appreciated. Please and thank you.

+1  A: 

I suggest that you have a look at gitorious (http://gitorious.org/gitorious). They use ssh to handle authentication and rights management (getting the username given by ssh). They also have some hooks on git repositories. I guess it could help to see how they are processing git hooks using ruby.

Scharron
+1  A: 

By the time your update hook fires, the server has the new commits: the question is whether your hook will allow the ref in question to move. What information from the local (sending) repository do you want?

For the credentials issue, funnel everyone through a single user. For example, GitHub does it with the git user, which is why their SSH URLs begin with [email protected]:.... Then in ~git/.ssh/authorized_keys, associate a username with each key. Note that the following should be on a single line but is wrapped for presentation purposes.

no-agent-forwarding,no-port-forwarding,no-pty,no-X11-forwarding,
command="env myuser=gbgcoll /usr/bin/git-shell -c \"${SSH_ORIGINAL_COMMAND:-}\""
ssh-rsa AAAAB...

Now to see who's trying to do the update, your hook examines the $myuser environment variable.

This doesn't give you each user's Jira credentials. To solve that issue, create a dummy Jira account that has read-only access to everything, and hardcode that Jira account's credentials in your hook. This allows you to verify that a given PR exists.

Greg Bacon