#!/usr/bin/env python

import argparse
import os
import os.path
import shutil
import subprocess
import sys


class BuildError(Exception):

    def __init__(self,
                 string=None,
                 path=None,
                 inferior_error=None):
        self.m_string = string
        self.m_path = path
        self.m_inferior_error = inferior_error

    def __str__(self):
        if self.m_path and self.m_string:
            return "Build error: %s (referring to %s)" % (
                self.m_string, self.m_path)
        if self.m_path:
            return "Build error (referring to %s)" % (self.m_path)
        if self.m_string:
            return "Build error: %s" % (self.m_string)
        return "Build error"


class LLDBBuildBot:

    def __init__(
            self,
            build_directory_path,
            log_path,
            lldb_repository_url="http://llvm.org/svn/llvm-project/lldb/trunk",
            llvm_repository_url="http://llvm.org/svn/llvm-project/llvm/trunk",
            clang_repository_url="http://llvm.org/svn/llvm-project/cfe/trunk",
            revision=None):
        self.m_build_directory_path = os.path.abspath(build_directory_path)
        self.m_log_path = os.path.abspath(log_path)
        self.m_lldb_repository_url = lldb_repository_url
        self.m_llvm_repository_url = llvm_repository_url
        self.m_clang_repository_url = clang_repository_url
        self.m_revision = revision
        self.m_log_stream = None

    def Setup(self):
        if os.path.exists(self.m_build_directory_path):
            raise BuildError(
                string="Build directory exists",
                path=self.m_build_directory_path)
        if os.path.exists(self.m_log_path):
            raise BuildError(string="Log file exists", path=self.m_log_path)
        self.m_log_stream = open(self.m_log_path, 'w')
        os.mkdir(self.m_build_directory_path)

    def Checkout(self):
        os.chdir(self.m_build_directory_path)

        cmdline_prefix = []

        if self.m_revision is not None:
            cmdline_prefix = ["svn", "-r %s" % (self.m_revision), "co"]
        else:
            cmdline_prefix = ["svn", "co"]

        returncode = subprocess.call(
            cmdline_prefix + [
                self.m_lldb_repository_url,
                "lldb"],
            stdout=self.m_log_stream,
            stderr=self.m_log_stream)
        if returncode != 0:
            raise BuildError(string="Couldn't checkout LLDB")

        os.chdir("lldb")

        returncode = subprocess.call(
            cmdline_prefix + [
                self.m_llvm_repository_url,
                "llvm.checkout"],
            stdout=self.m_log_stream,
            stderr=self.m_log_stream)

        if returncode != 0:
            raise BuildError(string="Couldn't checkout LLVM")

        os.symlink("llvm.checkout", "llvm")

        os.chdir("llvm/tools")

        returncode = subprocess.call(
            cmdline_prefix + [
                self.m_clang_repository_url,
                "clang"],
            stdout=self.m_log_stream,
            stderr=self.m_log_stream)

        if returncode != 0:
            raise BuildError(string="Couldn't checkout Clang")

    def Build(self):
        os.chdir(self.m_build_directory_path)
        os.chdir("lldb/llvm")

        returncode = subprocess.call(["./configure",
                                      "--disable-optimized",
                                      "--enable-assertions",
                                      "--enable-targets=x86,x86_64,arm"],
                                     stdout=self.m_log_stream,
                                     stderr=self.m_log_stream)

        if returncode != 0:
            raise BuildError(string="Couldn't configure LLVM/Clang")

        returncode = subprocess.call(["make"],
                                     stdout=self.m_log_stream,
                                     stderr=self.m_log_stream)

        if returncode != 0:
            raise BuildError(string="Couldn't build LLVM/Clang")

        os.chdir(self.m_build_directory_path)
        os.chdir("lldb")

        returncode = subprocess.call(["xcodebuild",
                                      "-project", "lldb.xcodeproj",
                                      "-target", "lldb-tool",
                                      "-configuration", "Debug",
                                      "-arch", "x86_64",
                                      "LLVM_CONFIGURATION=Debug+Asserts",
                                      "OBJROOT=build"],
                                     stdout=self.m_log_stream,
                                     stderr=self.m_log_stream)

        if returncode != 0:
            raise BuildError(string="Couldn't build LLDB")

    def Test(self):
        os.chdir(self.m_build_directory_path)
        os.chdir("lldb/test")

        returncode = subprocess.call(["./dotest.py", "-t"],
                                     stdout=self.m_log_stream,
                                     stderr=self.m_log_stream)

    def Takedown(self):
        os.chdir("/tmp")
        self.m_log_stream.close()
        shutil.rmtree(self.m_build_directory_path)

    def Run(self):
        self.Setup()
        self.Checkout()
        self.Build()
        # self.Test()
        self.Takedown()


def GetArgParser():
    parser = argparse.ArgumentParser(
        description="Try to build LLDB/LLVM/Clang and run the full test suite.")
    parser.add_argument(
        "--build-path",
        "-b",
        required=True,
        help="A (nonexistent) path to put temporary build products into",
        metavar="path")
    parser.add_argument(
        "--log-file",
        "-l",
        required=True,
        help="The name of a (nonexistent) log file",
        metavar="file")
    parser.add_argument(
        "--revision",
        "-r",
        required=False,
        help="The LLVM revision to use",
        metavar="N")
    return parser

parser = GetArgParser()
arg_dict = vars(parser.parse_args())

build_bot = LLDBBuildBot(build_directory_path=arg_dict["build_path"],
                         log_path=arg_dict["log_file"],
                         revision=arg_dict["revision"])

try:
    build_bot.Run()
except BuildError as err:
    print err
