#!/usr/bin/env python
from collections import namedtuple
import json
import os
import os.path
import sys

# GoSpec is a specifier for a downloadable (.tar.gz) release of Go.
GoSpec = namedtuple("GoSpec", "version os arch sha sha_algorithm")

# List of versions of go to generate manta files for
versions = [
    #GoSpec("1.4",   "linux", "amd64", "cd82abcb0734f82f7cf2d576c9528cebdafac4c6", "1"),
    #GoSpec("1.4.1", "linux", "amd64", "3e871200e13c0b059b14866d428910de0a4c51ed", "1"),
    #GoSpec("1.4.2", "linux", "amd64", "5020af94b52b65cc9b6f11d50a67e4bae07b0aff", "1"),
    #GoSpec("1.4.3", "linux", "amd64", "332b64236d30a8805fc8dd8b3a269915b4c507fe", "1"),
    #GoSpec("1.5",   "linux", "amd64", "5817fa4b2252afdb02e11e8b9dc1d9173ef3bd5a", "1"),
    #GoSpec("1.5.1", "linux", "amd64", "46eecd290d8803887dec718c691cc243f2175fe0", "1"),
    #GoSpec("1.5.2", "linux", "amd64", "cae87ed095e8d94a81871281d35da7829bd1234e", "1"),
    GoSpec("1.5.3", "linux", "amd64", "43afe0c5017e502630b1aea4d44b8a7f059bf60d7f29dfd58db454d4e4e0ae53", "256"),
    GoSpec("1.6",   "linux", "amd64", "5470eac05d273c74ff8bac7bef5bad0b5abbd1c4052efbdbc8db45332e836b0b", "256"),
    GoSpec("1.7.1", "linux", "amd64", "43ad621c9b014cde8db17393dc108378d37bc853aa351a6c74bf6432c1bbd182", "256"),
]


def go_identifier_string(spec):
    return "go{v}.{os}-{arch}".format(v=spec.version, os=spec.os, arch=spec.arch)


def echolog(spec, msg):
    return "echo '{spec}: {msg}'".format(spec=go_identifier_string(spec), msg=msg)


def generate(gospec):
    ''' Create a dictionary of Manta build instructions. '''
    return {
        "image": "ubuntu:precise",
        "mount": "/go/src/code.justin.tv/common/chitin",
        "env": [
            "GOPATH=/go/src/code.justin.tv/common/chitin/Godeps/_workspace:/go",
            "PATH=/usr/local/go/bin:$PATH"
        ],
        "setup": [
            download_go(gospec),
            "tar -C /usr/local -xzf go.tar.gz"
        ],
        "build": [
            echolog(gospec, "Checking that code matches go fmt"),
            # This is a little wordy, but go fmt doesn't exit with a
            # nonzero code - we need to check whether it printed any
            # output.
            """nonfmt=$(go fmt ./...)
            if [ -n "${nonfmt}" ]; then
                echo "${nonfmt}" | sed -e 's/^/non-gofmt-code: /'
                false
            fi""",

            echolog(gospec, "Running go vet"),
            go_vet_conditionally(gospec),

            echolog(gospec, "Running go test"),
            "go test ./...",

            echolog(gospec, "Running go test -race"),
            "go test -race ./...",
        ],
    }


def download_go(spec):
    ''' Generate a command which will download go at a particular version for an os, and check its checksum. '''
    template = "wget -q -O go.tar.gz http://storage.googleapis.com/golang/{pkg}.tar.gz && echo '{sha}  go.tar.gz' | sha{sha_alg}sum --check"
    return template.format(
        pkg=go_identifier_string(spec),
        sha=spec.sha,
        sha_alg=spec.sha_algorithm,
    )


def go_vet_conditionally(spec):
    # go vet doesn't ship with go 1.4.3 :(
    # see https://github.com/golang/go/issues/12883
    if spec.version == '1.4.3':
        return "echo 'Skipping go vet, since it does not ship with go 1.4.3'"
    else:
        return "go vet ./..."



def manta_filename(spec):
    return "mantas/manta.{pkg}.json".format(pkg=go_identifier_string(spec))


def write_manta_file(spec):
    with open(manta_filename(spec), "w") as f:
        json.dump(generate(spec), f, indent=2)


def write_jenkins_groovy(specs):
    # Instead of using .format here, I've just concatenated strings to
    # avoid the gnarliness of escaping all the curly braces.

    steps = ["shell 'manta -proxy -f _build/{0}'".format(manta_filename(s)) for s in specs]
    steps = "\n".join(steps)

    jenkins_groovy = """
    job {
	name "common-chitin"
	using 'TEMPLATE-autobuild'
	scm {
            git {
		remote {
			github 'common/chitin', 'ssh', 'git-aws.internal.justin.tv'
			credentials 'git-aws-read-key'
		}
		clean true
	    }
	}
	steps {
""" + steps + """
	}
    }

    job {
	name 'common-chitin-deploy'
	using 'TEMPLATE-deploy'
	steps {
	}
    }
    """

    with open("../jenkins.groovy", "w") as f:
        f.write(jenkins_groovy)


def abort(msg):
    print "FATAL: " + msg
    sys.exit(1)


def ensure_working_directory():
    '''Abort if the script is not being run from its directory on disk '''
    cwd = os.getcwd()
    file_dir = os.path.abspath(os.path.dirname(__file__))
    if not cwd == file_dir:
        abort("""
mantamaker.py should only be run from within its directory on disk:
    {want}
It seems to be running from here though:
    {have}""".format(want=file_dir, have=cwd))


def main():
    ensure_working_directory()
    for spec in versions:
        write_manta_file(spec)
    write_jenkins_groovy(versions)


if __name__ == '__main__':
    main()
