#!/bin/bash

# Copyright: 2023 Virtuozzo International GmbH

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

# http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

[ -n "${GITLIB_VERSION:-}" ] && return 0;
GITLIB_VERSION="0.1";

inherit os;
include output uninterract;

function prepareUrl(){
    local repo_proto=$(echo $URL | $SED -nre 's/(.*):\/\/(.*)/\1/p');
    local host_and_uri=$(echo $URL | $SED -re 's/(.*:\/\/)(.*)/\2/');

    AUTH=$($SED -e 's/\%/%25/g' -e 's/\^/%5E/g'  -e 's/\!/%21/g' -e 's/\#/%23/g' -e 's/\$/%24/g'\
                     -e 's/\&/%26/g' -e "s/'/%27/g" -e 's/(/%28/g' -e 's/)/%29/g' -e 's/\*/%2A/g'\
                     -e 's/\+/%2B/g' -e 's/\,/%2C/g' -e 's/\:/%3A/g' -e 's/\;/%3B/g' -e 's/\=/%3D/g'\
                     -e 's/\?/%3F/g' -e 's/\@/%40/g' -e 's/\[/%5B/g' -e 's/\]/%5D/g' <<< "${LOGIN}");

    [ ! -z "$PASSWORD" ] && {
    AUTH=${AUTH}:$($SED -e 's/\%/%25/g' -e 's/\^/%5E/g'  -e 's/\!/%21/g' -e 's/\#/%23/g' -e 's/\$/%24/g'\
                     -e 's/\&/%26/g' -e "s/'/%27/g" -e 's/(/%28/g' -e 's/)/%29/g' -e 's/\*/%2A/g'\
                     -e 's/\+/%2B/g' -e 's/\,/%2C/g' -e 's/\:/%3A/g' -e 's/\;/%3B/g' -e 's/\=/%3D/g' -e 's/\//%2F/g' -e 's/\\./%2E/g'\
                     -e 's/\?/%3F/g' -e 's/\@/%40/g' -e 's/\[/%5B/g' -e 's/\]/%5D/g' <<< "${PASSWORD}");
    }

    [ ! -z "$repo_proto" ] && {
        preparedUrl="$repo_proto://${AUTH}@${host_and_uri}";
    } || {
        preparedUrl="${AUTH}@${host_and_uri}";
    }
}

function updateSubmodules(){
    if [ -f "${WEBROOT}/${PROJECT_NAME}/.gitmodules" ]; then
       cd "${WEBROOT}/${PROJECT_NAME}"; runNonInterractive "$GIT  submodule update --init --recursive" >> $JEM_CALLS_LOG 2>&1; return $?;
    else
        return 0;
    fi
}

function doCheckout(){
    [ ! -z "$WEBROOT" ] && { set -f; rm -Rf "${WEBROOT}/${PROJECT_NAME}"; set +f; }

    if [[ "$LOGIN" != "__GUEST__"  ]] ; then
        prepareUrl;
        runNonInterractive "$GIT clone ${preparedUrl} ${WEBROOT}/${PROJECT_NAME}" >> $JEM_CALLS_LOG 2>&1;
        result=$?; [ $result -ne 0 ] && return $result;
        [ "x$GIT_AUTORESOLVE_CONFLICT" == "xtrue" ] && {
            echo -n "$(date) " >> ${VCS_AUTORESOLVE_LOG};
            cd "${WEBROOT}/${PROJECT_NAME}" && $GIT --git-dir="${WEBROOT}/${PROJECT_NAME}/.git" reset --hard HEAD >> ${VCS_AUTORESOLVE_LOG} 2>>${VCS_AUTORESOLVE_LOG} && cd - > /dev/null 2>&1;
        }
        [ ! -z $BRANCH ] && cd  "${WEBROOT}/${PROJECT_NAME}" &&  $GIT checkout $BRANCH > /dev/null 2>&1 && cd - >> $JEM_CALLS_LOG 2>&1;       ###### we removed --git-dir directive because of bug in GIT
        REPO_PATH=$(dirname ${URL})
        cd "${WEBROOT}/${PROJECT_NAME}" && submodule_list=($($GIT submodule | $AWK '{print $2}'))
        for submodule_name in "${submodule_list[@]}"; do
                submodule_url=$($GIT config -f .gitmodules --get submodule."${submodule_name}".url)
                if [[ "$submodule_url" == "${REPO_PATH}"* ]]; then
                        URL=$submodule_url;
                        prepareUrl;
                        $GIT config submodule."${submodule_name}".url ${preparedUrl};
                fi
        done
        [ $result -ne 0 ] && return $result;
        updateSubmodules || return $?;
    else
        if [ "x$NO_EXPECT" == "xtrue" ] ; then
            $GIT clone "$URL" "${WEBROOT}/${PROJECT_NAME}" >> "$VCS_UPDATE_LOG"  2>&1;
        else
            runNonInterractive "$GIT clone $URL ${WEBROOT}/${PROJECT_NAME}" > /dev/null 2>&1;
            result=$?; [ $result -ne 0 ] && return $result;
        fi
        updateSubmodules || return $?;
        [ "x$GIT_AUTORESOLVE_CONFLICT" == "xtrue" ] && {
            echo -n "$(date) " >> ${VCS_AUTORESOLVE_LOG};
            cd "${WEBROOT}/${PROJECT_NAME}" && $GIT --git-dir="${WEBROOT}/${PROJECT_NAME}/.git" reset --hard HEAD  >> ${VCS_AUTORESOLVE_LOG} 2>>${VCS_AUTORESOLVE_LOG} && cd - > /dev/null 2>&1;
        }
        [ ! -z $BRANCH ] && cd  "${WEBROOT}/${PROJECT_NAME}" &&  $GIT checkout $BRANCH > /dev/null 2>&1 && cd - > /dev/null 2>&1;      ###### we removed --git-dir directive because of bug in GIT
        [ "${COMPUTE_TYPE}" == "apache-ruby" -o "${COMPUTE_TYPE}" ==  "nginx-ruby" ] && {
            inherit ruby-common;
            bundleInstall;
            reloadServiceSilent ${SERVICE} ;
        } || return 0;
    fi
    return 0;
}

function updateProject(){
    prepareUrl;
    [ -d "${WEBROOT}/${PROJECT_NAME}" ] && cd "${WEBROOT}/${PROJECT_NAME}";
    [ "x$GIT_AUTORESOLVE_CONFLICT" == "xtrue" ] && {
            echo -n "$(date) " >> ${VCS_AUTORESOLVE_LOG};
               $GIT --git-dir="${WEBROOT}/${PROJECT_NAME}/.git" reset --hard HEAD  >> ${VCS_AUTORESOLVE_LOG} 2>>${VCS_AUTORESOLVE_LOG};
    }
    echo -n $(date +%D.%k:%M:%S.%N) >> "$VCS_UPDATE_LOG" 2>&1;
    runNonInterractive "$GIT --git-dir=${WEBROOT}/${PROJECT_NAME}/.git pull --rebase"  > /dev/null 2>&1;
    result=$?;
    [ $result -eq 2 ] && return $result;
    [ $result -ne 0 ] && {
        grep -q 'refusing to merge unrelated histories' <<< $ERR_HANDLER && $GIT --git-dir=${WEBROOT}/${PROJECT_NAME}/.git reset --hard origin >> "$VCS_UPDATE_LOG" 2>&1 &&
        runNonInterractive "$GIT --git-dir=${WEBROOT}/${PROJECT_NAME}/.git pull"  > /dev/null 2>&1;
        result=$?;
            grep -q 'Not committing merge' <<< $ERR_HANDLER && $GIT --git-dir=${WEBROOT}/${PROJECT_NAME}/.git reset --hard origin >> "$VCS_UPDATE_LOG" 2>&1 &&
            runNonInterractive "$GIT --git-dir=${WEBROOT}/${PROJECT_NAME}/.git pull --rebase"  > /dev/null 2>&1;
            result=$?;

        [ $result -ne 0 ] && return $result;
    }
    updateSubmodules || return $?;
    cd "${WEBROOT}/${PROJECT_NAME}" && runNonInterractive  "$GIT  gc" > /dev/null 2>&1;
    result=$?; [ $result -ne 0 ] && return $result;
    [ ! -z "$BRANCH" ] && [ "$($GIT --git-dir="${WEBROOT}/${PROJECT_NAME}/.git" branch | $GREP "$BRANCH" | cut -d" " -f1)" != "*" ] && $GIT --git-dir="${WEBROOT}/${PROJECT_NAME}/.git" checkout "$BRANCH"  >> "$VCS_UPDATE_LOG" 2>&1;

    [ "${COMPUTE_TYPE}" == "apache-ruby" -o "${COMPUTE_TYPE}" ==  "nginx-ruby" ] && {
        [ -f "${WEBROOT}/ROOT/Gemfile" ] &&  {
                inherit ruby-common;
                bundleInstall;
                reloadServiceSilent ${SERVICE} ;
        }
    }
    return 0;
}

function getLastRepoCommit(){
    [ -e ${WEBROOT}/${PROJECT_NAME}/.git ] && local last_repo_commit=$($GIT --git-dir=${WEBROOT}/${PROJECT_NAME}/.git rev-parse HEAD 2>/dev/null)
    [ -z $last_repo_commit ] && LAST_DEPLOYED_COMMIT="00000000000";
    echo $last_repo_commit;
}

function getLastRemoteCommit(){
    readProjectConfig;
    preparedUrl="${URL}";

    if [[ "$LOGIN" != "__GUEST__"  ]] ; then
        prepareUrl;
    fi

    if [ "x${LOGIN}" == "xgit" ]; then
        URL=$($SED -e 's/git:\/\///g' -e 's/ssh:\/\///g' <<< "${URL}");    
        last_remote=$(git ls-remote git@$URL $BRANCH 2>/dev/null);
        result=$?;
    else
        last_remote=$(git ls-remote $preparedUrl $BRANCH 2>/dev/null);
        result=$?;
    fi

    if [ $result -eq 0 ] ;then
        last_remote_commit=$(echo $last_remote | $AWK '{print $1}' );
    else
        echo $last_remote | sed -re "s/${AUTH}//" >> "$VCS_UPDATE_LOG"
        last_remote_commit="00000000000";
    fi

    [ -z $last_remote_commit ] && last_remote_commit="00000000000";
    echo $last_remote_commit;
}

function vcsChangeUrl(){
    if [[ "$LOGIN" != "__GUEST__"  ]] ; then
        prepareUrl;
    else
        preparedUrl=$NEWURL ;
    fi
    cd ${WEBROOT}/${PROJECT_NAME}/
    $GIT --git-dir="${WEBROOT}/${PROJECT_NAME}/.git" remote set-url origin "$preparedUrl" >> "$VCS_UPDATE_LOG"  2>&1
    $GIT fetch --all >> "$VCS_UPDATE_LOG" 2>&1
    $GIT reset --hard HEAD >> "$VCS_UPDATE_LOG" 2>&1
    result=$?;
    cd - >/dev/null 2>&1
    return $result;
}
