#!/bin/bash
#
# build_openshift_origin.sh
#
#   This script will build all opensource components using tito and mock on a 
#   local machine in order to create a "cleanly built" repository. Attempting
#   to mimic having an actual build system the best we can.
# 
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4

f_ctrl_c() {
    printf "\n*** Exiting ***\n"
    exit $?
}
     
# trap int (ctrl-c)
trap f_ctrl_c SIGINT

# Make sure not to run as root because mock won't build as root and
# it's just generally a good idea to avoid running things as root 
# unless we really need to.
if [[ $EUID -eq 0 ]]; then
    printf "ERROR: Script can not be run as root\n"
fi

##### "Global" variables

# sibling_dirs
# 
# This is an array of what will be considered as sibling directories
# currently this consists of directories that are meant to share a 
# parent directory and be clones of the following git repositories:
#
# https://github.com/openshift/origin-server.git
# https://github.com/openshift/rhc.git
sibling_dirs=( "rhc" "origin-server" )

# arrays to hold information about failed builds
declare -a failed_builds
declare -a failed_builds_paths

# ignore_packages
#
# Array of packages known to contain code that is still under heavy
# development, is not ready for general consumption, and is known
# to fail to build.
ignore_packages=(
    "rubygem-openshift-origin-container-libvirt"
    "rubygem-openshift-origin-gear-placement"
)

f_help() {
cat <<EOF
Usage: $(basename $0) [-m mock_config] [-s srpm_dir] [-r origin_release] [-c] [-h]
    -m  mock_config
        mock config name, example: epel-6-x86_64-openshift-nightly
    -r  origin_release
        OpenShift Origin Release to build, available options:
            v4
            nightly 
    -s  srpm_dir
        directory to hold intermediate srpms generated by tito to be fed to
        mockchain for building
            Default: /tmp/origin-srpms/
    -c
        clean the srpm_dir of all it's current files
    -h
        this help menu

EOF
  exit 1
}

# Slight sanity checking
if ! tito build -h &> /dev/null; then
    printf "ERROR: tito doesn't appear to be installed"
fi

if ! mock --version &> /dev/null; then
  printf "ERROR: mock not installed or not in current \$PATH\n"
  exit 2
fi

if [[ -z "$1" ]]; then
  f_help
fi

while getopts ":hm:s:cr:" opt; do
    case $opt in
        h)
            f_help
            exit 0
            ;;
        m)
            mock_config="$OPTARG"
            ;;
        s)
            srpm_dir="$OPTARG"
            ;;
        r)
            origin_release="$OPTARG"
            ;;
        c)
            clean_srpm_dir="true"
            ;;
        *)
            printf "ERROR: INVALID ARG $OPTARG\n"
            f_help
            ;;
    esac
done

# Verify that the user has provided a mock config
if [[ -z "$mock_config" ]]; then
    printf "ERROR: must provide a mock config to build against \n"
    f_help
fi

# Make sure we have a valid option for release to build
if [[ -z "$origin_release" ]]; then
    printf "ERROR: must profive an origin_release to build \n"
    f_help
else
    if [[ "$origin_release" != "v4" ]] && 
       [[ "$origin_release" != "nightly" ]]; then
        printf "ERROR: invalid origin_release provided\n"
        f_help
    fi
fi

# If the $srpm_dir string is zero length, user didn't provide one
# so use the defaults
if [[ -z "$srpm_dir" ]]; then
    srpm_dir="/tmp/origin-srpms"
fi

# If the $srpm_dir does not exist, create it
if ! [[ -d "$srpm_dir" ]]; then
    mkdir -p $srpm_dir
fi

# If the user has specified to clean the $srpm_dir, clean it out
if [[ -n "$clean_srpm_dir" ]]; then
    # This is potentially dangerous, but this can't be run as root
    # so it's mildly safe.
    rm -fr $srpm_dir/*
fi
    
# Run throught he siblings and build srpms
for d in ${sibling_dirs[@]}
do
    if [[ ! -d ../$d ]]; then
        printf "ERROR: Directory $d not a sibling of current directory\n"
        exit 4
    fi
    pushd ../$d
        for i in $(find . -name *.spec)
        do
            # Check to make sure this isn't a package we should ignore
            # During the build.
            # 
            # We're effectively concatenating the members of the
            # $ignore_packages array into a "Here String" to then 
            # grep and find out if current $i (minus the '.spec') 
            # matches that line. This looks a little odd but it
            # seemed like a better option than nesting a loop.
            spec=$(basename $i)
            if ! grep ${spec%\.spec} <<<"$( echo ${ignore_packages[*]} )" &> /dev/null; then
                pushd $(dirname $i)
                    if [[ "$origin_release" == "nightly" ]]; then
                        tito build \
                            --srpm \
                            --test \
                            -o $srpm_dir
                    else 
                        tito build \
                            --srpm \
                            -o $srpm_dir
                    fi
                    
                    if [[ $? -ne 0 ]]; then
                        failed_builds+=( "$(basename $i)" )
                        failed_builds_paths+=( "$(dirname $i)" )
                    fi
                popd
            fi
        done
    popd
done

# Report on the results of the SRPM build tasks, this would be nicer if we 
# were only handling building on Fedora and RHEL/CentOS7 but the version of
# bash in RHEL/CentOS6 can't handle associative arrays with they key as a
# command substitution like: my_ary["$(basename /tmp/foo.sh)"]="value"
if [[ -z $failed_builds ]]; then
    printf "SRPM Build: SUCCESS\n"
else
    printf "SRPM Build: FAILURE\nThe following packages failed to build:\n"
    for f in ${failed_builds[@]}
    do
        printf "${f%.spec}\n"
    done
    printf "\nThese packages can be found in their respective directories:\n"
    for d in ${failed_builds_paths[@]}
    do
        printf "$d\n"
    done
fi

# Run the mockchain build
mockchain -r $mock_config --recurse $srpm_dir/*.src.rpm  
