#!/usr/bin/env python3
#
# Install source packages to ~/opt/local.
#
# This script assumes that all source package dependencies are already
# installed.

import sys
import os
import subprocess
import filecmp
import shutil

b2 = shutil.which('b2')
if not b2:
    b2 = shutil.which('bjam')
if not b2:
    print('warning: Boost.Build was not found, skipping source packages that require it.')


def emulate_backtick(args):
    try:
        output = subprocess.check_output(args, universal_newlines=True).rstrip('\n')
    except Exception:
        output = ''

    return output


def git_clone_update_pull_ff_only(url, directory):
    """Clone, update, and pull --ff-only the given url to the given
    directory.

    """
    if not os.path.exists(directory):
        command = ['git', 'clone', '--recurse-submodules', url, directory]
        subprocess.check_call(command)

    command = ['git', '-C', directory, 'pull', '--ff-only', '--recurse-submodules', '--prune', '--all']
    subprocess.check_call(command)
    command = ['git', '-C', directory, 'submodule', 'init']
    subprocess.check_call(command)
    command = ['git', '-C', directory, 'submodule', 'update', '--init', '--recursive']
    subprocess.check_call(command)


def install_git_svn_update_externals(basedir):
    git_clone_update_pull_ff_only(
        'https://github.com/tee3/git-svn-update-externals.git',
        os.path.join(basedir, 'src', 'git-svn-update-externals'))

    source = os.path.join(basedir, 'src', 'git-svn-update-externals', 'git-svn-update-externals')
    target = os.path.join(basedir, 'bin', 'git-svn-update-externals')

    if os.path.exists(target):
        if not filecmp.cmp(target, source, False):
            yn = input('%s is different than %s.  Overwrite anyway? (y/n): ' % (source, target))
            if yn == 'y':
                os.remove(target)

    if not os.path.exists(target):
        if hasattr(os, 'symlink'):
            os.symlink(source, target)
        else:
            shutil.copyfile(source, target)


def install_boost(basedir):
    boostdir = os.path.join(basedir, 'src', 'boost', 'boost.git')

    git_clone_update_pull_ff_only(
        'https://github.com/boostorg/boost.git',
        boostdir)

    command = ['git', '-C', boostdir, 'clean', '-d', '-x', '-f']
    subprocess.check_call(command)

    if sys.platform.startswith('win32'):
        command = [os.path.join(boostdir, 'bootstrap.bat')]
    else:
        command = [os.path.join(boostdir, 'bootstrap.sh')]
    subprocess.check_call(command, cwd=boostdir)


def install_commands_to_compilation_database(basedir):
    if not b2:
        return

    sourcedir = os.path.join(basedir, 'src', 'commands_to_compilation_database')

    git_clone_update_pull_ff_only(
        'https://github.com/tee3/commands_to_compilation_database.git',
        sourcedir)

    command = [
        b2,
        'install',
        '--prefix=' + basedir
    ]
    subprocess.check_call(command, cwd=sourcedir)


# requires HOME.
if 'HOME' not in os.environ or os.environ['HOME'] == '':
    print('error: HOME is not set, aborting.')
    sys.exit(1)
HOME = os.environ['HOME']

# default the prefix to ~/opt/local
prefix = os.path.join(HOME, 'opt', 'local')

if __name__ == '__main__':
    r = 0

    # install desired source packages
    install_commands_to_compilation_database(prefix)
    install_git_svn_update_externals(prefix)
    install_boost(prefix)

    sys.exit(r)
