Skip to content
This repository
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

executable file 71 lines (57 sloc) 2.07 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
#!/usr/bin/env python
"""
Get a git project's authors (ordered by most contributions).
"""

import re
import subprocess
from operator import itemgetter

from django.utils import six

re_line = re.compile(six.b(r'(\d+)\s+(\d+)\s+[^<]+$'))
re_author = re.compile(six.b(r'.+<(.+)>$'))


def get_authors(exclude_primary_author=True):
    git_log = subprocess.Popen(
        ["git", "log", "--format=%aN <%aE>", "--numstat"],
        stdout=subprocess.PIPE)

    output = git_log.communicate()[0]

    authors = {}
    author = None
    for line in output.splitlines():
        match = re_line.match(line)
        if not match:
            if line:
                author = line
            continue
        authors[author] = authors.get(author, 0) + max([
            int(num) for num in match.groups()])

    # Combine duplicate authors (by email).
    emails = {}
    for author, changes in list(authors.items()):
        match = re_author.match(author)
        if not match:
            continue
        author_emails = match.group(1)
        for email in author_emails.split(six.b(',')):
            if six.b('@') not in email:
                continue
            if email in emails:
                remove_author = emails[email]
                if remove_author not in authors:
                    continue
                if changes < authors[remove_author]:
                    author, remove_author = remove_author, author
                authors[author] = authors[author] + authors[remove_author]
                del authors[remove_author]
            else:
                emails[email] = author

    # Sort authors list.
    list_authors = sorted(authors.items(), key=itemgetter(1), reverse=True)

    total = float(sum(authors.values()))

    if exclude_primary_author:
        top_author = list_authors.pop(0)
        total -= top_author[1]

    return [
        (author.decode(), changes, changes / total * 100)
        for author, changes in list_authors]


if __name__ == '__main__':
    for author, changes, percent in get_authors():
        print(author)
Something went wrong with that request. Please try again.