#! /usr/bin/python

import errno
import getopt
import jenkinsapi.api
import os
import re
import StringIO
from subprocess import Popen, PIPE, STDOUT
import sys
import tempfile
import time
import urllib2
import zipfile

CHUNKSIZE=64*1024

verbose = False

def mkdir_p(path):
    try:
        os.makedirs(path)
    except OSError as exc: # Python >2.5
        if exc.errno == errno.EEXIST:
            pass
        else: raise

opts, args = getopt.getopt(sys.argv[1:], "Vv:d:faib")

version = destination = 'unset'
update_frags = False
update_api_docs = False
installers = True
binaries = True

for (option, value) in opts:
    if option == '-v':
        version = value
    elif option == '-V':
        verbose = True
    elif option == '-d':
        destination = value
    elif option == '-f':
        update_frags = True
    elif option == '-a':
        update_api_docs = True
    elif option == '-i':
        installers = False
    elif option == '-b':
        binaries = False


# Not ready yet
update_api_docs = False

if version == 'unset':
    print "Usage: " + sys.argv[0] + " -v VERSION [-d DESTINATION]"
    sys.exit(1)

default_dest = "/mcs/globus.org/ftppub"
if (destination is 'unset') and (os.stat(default_dest) is not None):
    destination = default_dest

branch_version = "GT" + "".join(version.split(".")[0:2])
build_kickoff = branch_version + "-ALL"


# Create root of distribution point
[major, minor, point] = version.split(".")
destination_version_root = destination + \
    "/gt%s/%s.%s/%s.%s.%s" %(major, major, minor, major, minor, point)

for tree in ["installers/repo", "installers/src", "packages/rpm", "packages/deb", "packages/src"]:
    mkdir_p(destination_version_root + "/" + tree)

jenkins = jenkinsapi.api.Jenkins("http://builds.globus.org")
for name,job in jenkins.get_jobs():
    print "Processing " + name
    if name.startswith(branch_version + "-DEB") or name.startswith(branch_version + "-UBUNTU"):
        build = job.get_last_completed_build()
        if build.is_good():
            if "-DEB" in name:
                debtype = "debian"
                debver = name[name.find("DEB")+3:]
            elif "-UBUNTU" in name:
                debtype="ubuntu"
                debver = name[name.find("UBUNTU")+6:]
            else:
                print "Unknown debian type for " + name
                sys.exit(1)

            debian_repo_dir = os.path.join(destination_version_root,
                "packages", "deb", debtype, debver)

            print "Fetching artifacts for repo " + debtype + " " + debver
            for artifact in ['changes', 'conf', 'db', 'dists', 'pool']:
                zipdatafile = zipfile.ZipFile(
                    StringIO.StringIO(
                        urllib2.urlopen(
                            build.baseurl +
                            "artifact/packaging/repo/" + artifact + "/*zip*/" +
                            artifact + ".zip").read()))
                zipdatafile.extractall(debian_repo_dir)

    elif name.startswith(branch_version + "-RPM"):
        # There is no way in the API to detect disabled jobs, so we'll just
        # ignore ones which have never been built
        if job.get_build_dict().keys() == []:
            continue
        build = job.get_last_completed_build()

        if build.is_good():
            if "RPMCENTOS" in name:
                rpmtype = "centos"
            elif "RPMFED" in name:
                rpmtype = "fedora"
            elif "RPMRHEL" in name:
                rpmtype = "redhat"
            elif "RPMSL" in name:
                rpmtype = "sl"
            elif "RPMSUSE" in name:
                rpmtype = "sles"
            else:
                print "Unknown rpm type for " + name
                sys.exit(1)

            print "Fetching RPM artifacts for " + name

            zipdatafile = zipfile.ZipFile(
                StringIO.StringIO(
                    urllib2.urlopen(
                        build.baseurl +
                            "artifact/packaging/rpmbuild/repo/" + rpmtype +
                            "/*zip*/" + rpmtype + ".zip").read()))
            rpm_repo_dir = os.path.join(destination_version_root,
                "packages", "rpm")
            zipdatafile.extractall(rpm_repo_dir)

            if name == branch_version + "-RPMCENTOS5":
                srpmdir = os.path.join(
                        destination_version_root,
                        "packages",
                        "rpm",
                        "centos",
                        "5",
                        "SRPMS")
                srcpackagedir = os.path.join(destination_version_root,
                    "packages", "src")
                for srpm in os.listdir(srpmdir):
                    if srpm.endswith(".src.rpm"):
                        p1 = Popen(["rpm2cpio", srpm], cwd=srpmdir, stdout=PIPE)
                        p2 = Popen(["cpio", "-i", "*.tar.gz", "*.tgz"],
                            stdin=p1.stdout, stdout=PIPE, stderr=STDOUT, 
                            cwd=srcpackagedir)
                        output = p2.communicate()
    elif name.startswith(branch_version + "-INSTALLER"):
        # The GTXX-INSTALLER job generates a new source installer along with
        # its checksums. It also generates new documentation frags that we
        # check into the doc cvs if requested by command-line options
        print "Fetching source installer"
        source_installer_dir = os.path.join(destination_version_root,
            "installers", "src")
        build = job.get_last_completed_build()
        if build.is_good():
            artifacts = build.get_artifact_dict()
            for f in artifacts.keys():
                if "installer.tar.gz" in f:
                    artifact = urllib2.urlopen(artifacts[f].url)
                    artifact_out = file(os.path.join(source_installer_dir, artifacts[f].filename), "wb", CHUNKSIZE)
                    chunk = artifact.read(CHUNKSIZE)
                    while chunk:
                        artifact_out.write(chunk)
                        chunk = artifact.read(CHUNKSIZE)
                    artifact_out.close()
                    artifact.close()
            # TODO: update the frags in cvs based on these frags
    else:
        pass
