#!/usr/bin/env python

import os
import sys
import re
import subprocess

def retrieve_url_content(url):
    process = subprocess.Popen(['wget', url, '-O', '-'],
                               stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    (stdout, stderr) = process.communicate()
    return stdout


class CgitPatch:
    # Freedesktop-style git
    re_command_fdo = re.compile("(http.*)\/(\w+)\/\?id=(\w+)")

    # SourceForge-style git
    re_command_sf  = re.compile("(http.*)\?p=([\w\/\-]+);a=(\w+);h=(\w+)")

    def __init__(self, git_url):
        self._filename = None
        self._content = None
        self._content_lines = None
        self.commit_id = None
        self.package = None
        self.url = None

        m = CgitPatch.re_command_fdo.match(git_url)
        if m:
            base_url = m.group(1)
            command = m.group(2)
            self.commit_id = m.group(3)
            self.package = base_url.split('/').pop()
            self.url = git_url
            if command != 'patch':
                self.url = "%s/patch/?id=%s" %(base_url, self.commit_id)
            return

        m = CgitPatch.re_command_sf.match(git_url)
        if m:
            base_url = m.group(1)
            command = m.group(3)
            self.commit_id = m.group(4)
            self.package = base_url.split('/').pop()
            self.url = git_url
            if command != 'patch':
                self.url = "%s?p=%s;a=commit;h=%s" %(base_url, self.package, self.commit_id)
            return

        assert 1 == 0, "Unrecognized url form %s" %(git_url)

    @property
    def content(self):
        '''List of lines retrieved from the URL'''
        if self._content is None:
            self._content = retrieve_url_content(self.url)
        return self._content

    @property
    def content_lines(self):
        if self._content_lines is None:
            self._content_lines = self.content.split("\n")
        return self._content_lines

    def set_filename(self, filename):
        self._filename = filename
    def get_filename(self):
        if self._filename is None:
            for line in self.content_lines:
                if line[:8] == 'Subject:':
                    subject = re.sub(r' +', '_', line[9:]).lower()
                    self._filename = "%s.patch" %(re.sub(r'\W+', '', subject))
                    break

        # TODO: Check current directory for a series file; if it exists, then
        #       number the patch consecutively.
        return self._filename
    filename = property(get_filename, set_filename)

    def is_valid(self):
        if self.commit_id is None:
            return False
        for line in self.content_lines:
            if line[5:45] == self.commit_id:
                return True
        return False


if __name__ == '__main__':
    if len(sys.argv)<2:
        print "Usage: cgit-patch <url> [patch-filename]"
        sys.exit(1)

    url = sys.argv[1]
    patch = CgitPatch(url)
    if len(sys.argv)>2:
        patch.filename = sys.argv[2]

    if not patch.is_valid():
        sys.stderr.write("Error: Failed to download patch\n")
        sys.exit(1)

    file = open(patch.filename, 'w')
    file.write(patch.content)
    file.close()
    print patch.filename
