#!/bin/bash

#########################################################
# Build script to build git for the locker.

LOCKERNAME=git
LOCKER=/mit/${LOCKERNAME}
GIT_DIR=$LOCKER/src/git.git

attach ${LOCKERNAME}

die() {
    echo "$@" 2>&1;
    if [ -n "$TMPDIR" ]; then
        if [ -n "$DRYRUN" ]; then
            echo "Dropping to a shell to investigate...";
            $SHELL
        fi
    fi
    exit 1;
}

usage () {
    echo "Usage: $0 [-n] [-s] [-S sysname] tree-ish"
    echo "Builds git from $GIT_DIR tree-ish"
    exit 2;
}

exittrap() { :; }
for sig in 1 2 13 15; do trap "exit $(($sig + 128))" $sig; done
trap 'exittrap' EXIT

DRYRUN=
SHARE=
ATHENA_SYS="${ATHENA_SYS:-$(machtype -S)}"
CHERRY_PICKS=""

set -- `getopt c:nsS: "$@"`
[ $? -eq 0 ] || usage

for opt
do
    case "$opt" in
        -c)
            CHERRY_PICKS="${CHERRY_PICKS} $2"; shift 2 ;;
        -n)
            DRYRUN=1; shift ;;
        -s)
            SHARE=1; shift ;;
        -S)
            ATHENA_SYS="$2"; shift 2 ;;
        --)
            shift; break ;;
    esac
done
TREEISH=$1

test -z "$TREEISH" && usage
test -z "$ATHENA_SYS" && die "No sysname specified or found. Use -S to specify a sysname."

if [ -z "$GIT" ]; then
    GIT=$LOCKER/bin/git
    if [ ! -x $GIT ]; then
        GIT=$(which git)
    else
        $GIT --help >/dev/null 2>/dev/null || GIT=$(which git)
    fi
fi
test -x "$GIT" || die "No git executable found."

if [ ! -x "$PYTHON_PATH" ]; then
    PYTHON_PATH=`which python`
    test -x "$PYTHON_PATH" || die "No python executable found."
fi
export PYTHON_PATH

if [ "$(uname)" = "SunOS" ]; then
    MAKE=/afs/sipb.mit.edu/project/git/builds/gmake-4.4/@sys/bin/make
    TAR=gtar
    SED=sed
else
    MAKE=make
    TAR=tar
    SED=sed
fi

aklog sipb

VERS=`$GIT --git-dir=$GIT_DIR describe $TREEISH`
if [ -z "$VERS" ]; then
    die "Git version not found"
fi

TMPDIR=$(mktemp -d /tmp/git-build-XXXXXX) || die "Unable to mktemp"

exittrap() { rm -rf "$TMPDIR"; }

(
    cd "$TMPDIR" || die "Unable to cd to $TMPDIR"
    $GIT clone -b $VERS -s $GIT_DIR .
    # Just in case the git we find can't check out a tag with -b
    $GIT checkout $VERS

    if [[ -n "$CHERRY_PICKS" ]]; then
        for commit in ${CHERRY_PICKS}; do
            if [[ -z "$($GIT branch --list HEAD --contains ${commit})" ]]; then
                echo "Cherry-picking ${commit}"
                $GIT cherry-pick "${commit}" || die "Failed to cherry-pick: ${commit}"
            else
                echo "Skipping cherry-pick of ${commit}: already present."
            fi
        done
    fi

    TARGET=$LOCKER/builds/git-$VERS
    PREFIX=$TARGET/common
    EPREFIX=$TARGET/$ATHENA_SYS

    opt_rpath="-Wl,-R"
    [ $(uname) = "SunOS" ] && opt_rpath="-R"

    echo "Building git version $VERS for $ATHENA_SYS."

    LOCKER_CURL=$LOCKER/curl/$ATHENA_SYS
    if [ -d $LOCKER_CURL ]; then
        CURL="--with-curl=${LOCKER_CURL}"
        CURL_CONFIG=${LOCKER_CURL}/bin/curl-config
        export CURL_CONFIG
    else
        CURL="--with-curl"
    fi

    LOCKER_ZLIB=$LOCKER/zlib/$ATHENA_SYS
    if [ -d $LOCKER_ZLIB ]; then
        ZLIB="--with-zlib=${LOCKER_ZLIB}"
        CPPFLAGS="${CPPFLAGS} -I${LOCKER_ZLIB}/include"
        LDFLAGS="${LDFLAGS} -L${LOCKER_ZLIB}/lib ${opt_rpath}${LOCKER_ZLIB}/lib"
    fi


    ATHENA_INCLUDES="/usr/athena/include"
    if [ -d $ATHENA_INCLUDES ]; then
        CPPFLAGS="${CPPFLAGS} -I${ATHENA_INCLUDES}"
    fi

    ATHENA_LIBS="/usr/athena/lib"
    if [ -d $ATHENA_LIBS ]; then
        LDFLAGS="${LDFLAGS} -L${ATHENA_LIBS} ${opt_rpath}${ATHENA_LIBS}"
    fi

    export CPPFLAGS
    export LDFLAGS

    autoconf || die "Unable to generate configure."
    ./configure --prefix=$PREFIX --exec-prefix=$EPREFIX $CURL $ZLIB

    # Ugly hack because the Solaris libc has gettext, but
    # /usr/athena/include/libintl.h is GNU libintl and that rewrites
    # gettext() and friends to libintl_gettext(), which is not. This
    # forces us to link the GNU libintl.so, which will come from
    # /usr/athena/lib. This is only relevant from v1.7.9 onward, and
    # does nothing for older versions.
    case "${ATHENA_SYS}" in
        sun4x_510)
            echo "LIBC_CONTAINS_LIBINTL=" >> config.mak
            ;;
    esac

    # Another ugly hack. git v2.35.0 included a weather balloon that
    # broke builds using c89. I really think this should be detected
    # during configure and tweaked as needed, but that may be too much
    # to ask. Force older systems to use c99. (Assumes gcc, which is
    # true for the limited cases here.)
    case "${ATHENA_SYS}" in
        amd64_fedora20|sun4x_510)
            echo "BASIC_CFLAGS += -std=gnu99" >> config.mak
            ;;
    esac

    CPUS=$(athinfo localhost cpuspeed | grep -c MHz)
    if [ "$CPUS" = 0 ]; then
        CPUS=1
    fi

    $MAKE -j$CPUS || die "make failed"
    if [ -n "$SHARE" ]; then
        $MAKE -j$CPUS ASCIIDOC8=yes ASCIIDOC_NO_ROFF=yes man || die "make man failed"
        $MAKE -j$CPUS ASCIIDOC8=yes ASCIIDOC_NO_ROFF=yes info || die "make info failed"
        $MAKE -j$CPUS ASCIIDOC8=yes ASCIIDOC_NO_ROFF=yes html || die "make html failed"
    fi

    if [ -n "$DRYRUN" ]; then
        echo "Build completed; Dropping to a shell..."
        $SHELL
    else
        $MAKE install || die "Install failed"
        # Symlinks to save space where possible
        (cd $EPREFIX/bin;
            core="../libexec/git-core"
            for bin in $(ls -1); do
                if [ -e "${core}/${bin}" ]; then
                    ln -sf "${core}/${bin}" "${bin}"
                fi
            done
        )

        # Now clean and rebuild gitweb how we actually want it.
        $MAKE gitweb-clean || die "cleaning gitweb failed"
        $MAKE GITWEB_CONFIG_SYSTEM=$LOCKER/etc/gitweb.conf \
              GITWEB_CONFIG_COMMON=$LOCKER/etc/gitweb.conf \
              bindir=$LOCKER/bin \
              install-gitweb gitwebdir=$PREFIX/share/gitweb || die "Install gitweb failed"
        (cd $PREFIX/share/gitweb;
            ln -s gitweb.cgi index.fcgi;
            $SED -i -E \
                 -e 's|"static/|"//git.scripts.mit.edu/static/|' \
                 -e 's|<link rel="stylesheet"|<link crossorigin="anonymous" rel="stylesheet"|' \
                 -e 's|\$len \+ ([45])|$len + $add_len + \1|' \
                 -e 's|(die_error\(400, "Invalid action parameter"\);)|undef \$action; \1|' \
                 gitweb.cgi
            cat >.htaccess <<EOF
<If "req('Host') == 'git.scripts.mit.edu'">
# If this is being served out of the git locker, let anyone add it to their site.
Header add Access-Control-Allow-Origin "*"
</If>
EOF
        )

        # Downgrade minimum perl version to v5.14; it was rudely bumped to v5.26 in git v2.48.0, and
        # that breaks scripts F20. This is a timebomb since at some point they'll actually use a
        # feature we don't have.
        (cd $PREFIX; $SED -i -E 's|^require v5.26;$|require v5.14;|' $(grep -rl '^require v5.26;$'))
        (cd $EPREFIX; $SED -i -E 's|^require v5.26;$|require v5.14;|' $(grep -rl '^require v5.26;$'))
        if [ -n "$SHARE" ]; then
            $MAKE install-man || die "Install man failed"
            $MAKE install-info || die "Install info failed"
            $MAKE install-html || die "Install html failed"
        fi
        (cd $EPREFIX; ln -s ../common/share .)
    fi

)

rm -rf "$TMPDIR"
exittrap() { :; }
