#!/usr/bin/env python
import git, os, datetime, tempfile, stat, sys
import PyRSS2Gen as pyrss

NUM_POSTS = 100
RSS_PATH = "/srv/git/commits.rss"

# Ignore repositories with paths beginning like this: 
IGNORE = [ "/srv/git/mirrors/", "/srv/git/scripts/", "/srv/git/priv/" ]

DEBUG = len(sys.argv) > 1
if DEBUG:
    print "Debug mode"
    RSS_PATH = "/srv/git/commits-test.rss"

def list_repos():
    "Generate the paths of all the repositories"
    for root, dirs, files in os.walk("/srv/git"):
        if root[-4:] == ".git":

            skip = False
            for i in IGNORE:
                if root[0:len(i)] == i:
                    skip = True
                    break

            if skip:
                continue

            yield root

def commit_date_compare(x,y):
    x = x[1]
    y = y[1]

    if x.committed_date > y.committed_date:
        return -1

    if x.committed_date == y.committed_date:
        return 0

    if x.committed_date < y.committed_date:
        return 1

def commit_get_repo(c):
    "Give the shortname for the repository that the given commit is in"
    path = c.repo.working_dir
    prefix = "/srv/git/"
    return path[len(prefix):]

def get_commit_url(c):
    "Get the cgit URL for the given commit"
    name = commit_get_repo(c)
    return "https://www.studentrobotics.org/cgit/%s/commit/?id=%s" % (name, c.sha)

def get_repo_cgit_url(c):
    "Get the cgit URL for the repo of the given commit"
    return "https://www.studentrobotics.org/cgit/%s" % commit_get_repo(c)

def sanitise_str(s):
    return unicode( s, "utf-8").encode( "ascii", "backslashreplace" )

def create_diffstat(c):
    "Return HTML string containing a diffstat of the given commit."
    stat = c.stats.files

    s = "<pre>"
    s += "%i file(s) affected:\n" % len(stat)

    for fname, changes in stat.iteritems():
        s += """%(insertions)i+/%(deletions)i-: %(fname)s\n""" % {
            "fname": fname,
            "insertions": changes["insertions"],
            "deletions": changes["deletions"] }

    s += "</pre>"
    return s

def get_ignore_list(repodir):
    igpath = os.path.join( repodir, "rss-branch-ignore" )

    if os.path.exists(igpath):
        f = open( igpath, "r" )
        ig = [x.strip() for x in f.readlines()]
        f.close()
        return ig

    return []

commits = []

for repodir in list_repos():
    repo = git.Repo(repodir)
    iglist = get_ignore_list(repodir)

    for branch in repo.branches:
        if branch.name in iglist:
            "Skip branches in the ignore list"
            continue

        commits += [ (branch.name, x) for x in repo.iter_commits( branch.name,
                                                                  max_count = NUM_POSTS ) ]

        # Sort the list
        commits.sort( cmp = commit_date_compare )

        # Truncate
        commits = commits[:NUM_POSTS]

items = []
for branch, commit in commits:
    # Truncate the commit message to create the first line
    msg = commit.message
    nl = msg.find("\n")
    if nl != -1:
        msg = msg[:nl]
    msg = msg[:80]

    data = { "author": sanitise_str(commit.author.name),
             "repo": commit_get_repo( commit ),
             "hash": commit.sha[0:12],
             # First line of the commit message, truncated to 80 chars
             "title": msg,
             "branch" : branch }

    desc = """<p>Commit <b><a href="%(commiturl)s">%(hash)s</a></b> to <a href="%(repourl)s">%(reponame)s</a> by %(user)s.</p>
<pre>%(msg)s</pre>
%(diffstat)s
""" % { "commiturl": get_commit_url(commit),
        "repourl": get_repo_cgit_url(commit),
        "hash": commit.sha,
        "reponame": commit_get_repo(commit),
        "user": sanitise_str(commit.author.name),
        "msg" : sanitise_str( commit.message ),
        "diffstat" : create_diffstat(commit) }
                          
    item = pyrss.RSSItem(
        title = "%(repo)s(%(branch)s) - %(author)s: %(title)s" % data,
        link = get_commit_url( commit ),
        description = desc,

        # Convert the time.struct_time to a datetime
        pubDate = datetime.datetime.fromtimestamp( commit.committed_date ),

        guid = pyrss.Guid( get_commit_url(commit) ) )

    items.append(item)

rss = pyrss.RSS2(
    title = "Student Robotics Git Commits",
    link = "http://git.studentrobotics.org/",
    description = "The last %i commits to the Student Robotics Repositories" % NUM_POSTS,
    lastBuildDate = datetime.datetime.now(),
    items = items )

rss.write_xml( open(RSS_PATH, "w") )
