#!/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.



inherit default os envinfo hooks;
include uninterract output php-common-deploy string net;
include cartridge-common decrypt-passwd;


DESCRIPTION="Operations with VCS";
VERSION="1";
DEFAULT_ACTION="Usage";
$PROGRAM 'sed';
$PROGRAM 'wget';
$PROGRAM 'svn';
$PROGRAM 'grep';
$PROGRAM 'git';
$PROGRAM 'curl';
$PROGRAM 'awk';

VCS_CONFIG_DIR="/var/lib/jelastic/vcs";
VCS_LOG_DIR="/var/log/jelastic/vcs";
DEFAULT_LOGIN="__GUEST__";
USERS_CRONFILE="/var/spool/cron/$($AWK  -F ":" '{ print $1 }' <<< $DATA_OWNER )";
ROOT_CRONFILE="/var/spool/cron/root";
AUTOUPDATE_CRON_STRING="* * * * * jem vcs autoupdate";
REDEPLOY_CONF_FILE="/etc/jelastic/redeploy.conf";

BRANCH_NAME_FILTER="(\.\.|[[:space:]]|[\ []|[]\ ]|[\\@\,\"\'\|\~\^:\;\<\>\`\%\?\!\+\{\}\(\)]|\.$|\.lock$)";

GITSSH_SCRIPT="/var/lib/jelastic/libs/gitssh.sh"
export GIT_SSH=${GITSSH_SCRIPT};

export GIT_SSL_NO_VERIFY="true";
export NO_EXPECT="false";

[ -z "$VCS_UPDATE_LOG" ] && VCS_UPDATE_LOG="${VCS_LOG_DIR}/vcs_update.log";

[ "x${COMPUTE_TYPE}" == "xcartridge" ] && restoreEnvironmentVariables && {
    [ -f ${CARTRIDGE_HOME}/jelastic/jelastic.conf ] && source ${CARTRIDGE_HOME}/jelastic/jelastic.conf;
    WEBROOT="${Webroot_Path}";
}

function doUsage() {
    showUsageMessage;
}

##### Internal functions #####

function checkVCSDirectories(){
    [ ! -d  "$VCS_CONFIG_DIR" ] && mkdir -p "$VCS_CONFIG_DIR";
    [ ! -d  "$VCS_LOG_DIR" ] && mkdir -p "$VCS_LOG_DIR";
}

function recoverBrokenMountPoints(){
        local mount_points=$(mount | $GREP -o -P '(?<=deleted\)).*(?=type)');
        [ ! -z "$mount_points" ] && for mount_point in $mount_points
        do
        umount  "$mount_point";
        mount "$mount_point";
        done
        return 0;
}

function parseArguments() {

  while [ "$1" != "" ]; do
    case $1 in

      -n  | --project-name )      shift;
                                  PROJECT_NAME=$1;
                                  ;;
      -t  | --vcs-type )          shift;
                                  VCS_TYPE=$1;
                                  ;;
      -u  | --url )               shift;
                                  URL=$1;
                                  ;;
      -l  | --login )             shift;
                                  LOGIN=$1;
                                  ;;
      -p  | --password )          shift;
                                  PASSWORD=$1;
                                  ;;
      -b  | --branch )            shift;
                                  BRANCH=$1;
                                  ;;
      -o  | --old-project-name )  shift;
                                  OLD_PROJECT_NAME=$1;
                                  ;;
      -c  | --context )           shift;
                                  CONTEXT=$1;
                                  ;;
      -e  | --environment )       shift;
                                  ENVIRONMENT=$1;
                                  ;;
      -au | --autoupdate )        shift;
                                  AUTOUPDATE=$1;
                                  ;;
      -m  | --updateinverval )    shift;
                                  UPDATE_INTERVAL=$1;
                                  ;;
      -k  | --authkey )    shift;
                                  AUTHORIZATION_KEY_VAL="$1";
                                  ;;
      -r  | --autoresolveconflict)    shift;
                                   GIT_AUTORESOLVE_CONFLICT="$1";
                                  ;;
      -a | --atomicdeploy)      shift;
                                  ATOMIC_DEPLOY="$1";
                                  ;;
      --subdirectory )          shift;
                        BUILDDIR=$1;
                                ;;
    -g | --nodegroup )
            shift;
            NODE_GROUP=$1
        ;;
    --repohash )
            shift;
            REPO_HASH=$1
            ;;
    esac
    shift
  done
  PASSWORD=$(getPassword $PASSWORD);
  [ "x${COMPUTE_TYPE}" == "xapache-ruby" -o "x${COMPUTE_TYPE}" == "xnginx-ruby" ] || [ "x${COMPUTE_TYPE}" == "xcartridge" -a "x${Engine_Type}" == "xruby" ] && {
    [ "x${PROJECT_NAME}" == "xROOT" ] && [ ! -z ${OLD_PROJECT_NAME} ] && PROJECT_NAME=${OLD_PROJECT_NAME};
    [ ! -z "$PROJECT_NAME" ] && { bundle_type="${PROJECT_NAME}" ;  PROJECT_NAME="ROOT"; } ;
  }

  [ "${COMPUTE_TYPE}" == "nodejs" ] && { PROJECT_NAME="ROOT"; }
  [ -z "${ATOMIC_DEPLOY}" ] && { ATOMIC_DEPLOY="false"; }
}

function writeProjectConfig(){

  [ "x${COMPUTE_TYPE}" == "xapache-ruby" -o "x${COMPUTE_TYPE}" == "xnginx-ruby" ] || [ "x${COMPUTE_TYPE}" == "xcartridge" -a "x${Engine_Type}" == "xruby" ] && {
    echo "$bundle_type" > /var/lib/jelastic/env
    PROJECT_NAME="ROOT"
  }
  enableVCSLibrary;
  [ "x${COMPUTE_TYPE}" != "xmaven" ] && LAST_DEPLOYED_COMMIT=$(getLastRepoCommit);

  PROJECT_CONFIG="${VCS_CONFIG_DIR}/${PROJECT_NAME}.properties";

  echo "PROJECT_NAME=${PROJECT_NAME}" > $PROJECT_CONFIG;
  echo "VCS_TYPE=${VCS_TYPE}" >> $PROJECT_CONFIG;
  echo "URL=${URL}" >> $PROJECT_CONFIG;
  echo "LOGIN=${LOGIN}" >> $PROJECT_CONFIG;
  echo PASSWORD="'"${PASSWORD}"'" >> $PROJECT_CONFIG;
  echo "BRANCH=${BRANCH}" >> $PROJECT_CONFIG;
  echo "ENVIRONMENT=${ENVIRONMENT}" >> $PROJECT_CONFIG;
  echo "CONTEXT=${CONTEXT}" >> $PROJECT_CONFIG;
  echo "AUTOUPDATE=${AUTOUPDATE}" >> $PROJECT_CONFIG;
  echo "UPDATE_INTERVAL=${UPDATE_INTERVAL}" >> $PROJECT_CONFIG;
  local timestamp=`date +%s`;
  echo "LASTUPDATE=$timestamp" >> $PROJECT_CONFIG;
  echo "LAST_DEPLOYED_COMMIT=${LAST_DEPLOYED_COMMIT}" >> $PROJECT_CONFIG;
  echo "NEED_REDEPLOY=$NEED_REDEPLOY" >> $PROJECT_CONFIG;
  echo "GIT_AUTORESOLVE_CONFLICT=$GIT_AUTORESOLVE_CONFLICT" >> $PROJECT_CONFIG;
  echo "ATOMIC_DEPLOY=$ATOMIC_DEPLOY" >> $PROJECT_CONFIG;
  echo "NODE_GROUP=$NODE_GROUP" >> $PROJECT_CONFIG;
  echo "REPO_HASH=$REPO_HASH" >> $PROJECT_CONFIG;
  if [ -z "$AUTHORIZATION_KEY_VAL" ] ; then
    if [ -e ${VCS_CONFIG_DIR}/${PROJECT_NAME}.key ]; then
        echo "AUTHORIZATION_KEY=${VCS_CONFIG_DIR}/${PROJECT_NAME}.key" >> $PROJECT_CONFIG;
    else
        echo "AUTHORIZATION_KEY=" >> $PROJECT_CONFIG;
    fi
  else
    echo "AUTHORIZATION_KEY=${VCS_CONFIG_DIR}/${PROJECT_NAME}.key" >> $PROJECT_CONFIG;
    echo "$AUTHORIZATION_KEY_VAL" > "${VCS_CONFIG_DIR}/${PROJECT_NAME}".key
    chmod 600 "${VCS_CONFIG_DIR}/${PROJECT_NAME}".key
  fi
  [ -z "$BUILDDIR" ] || echo "BUILDDIR=$BUILDDIR" >> $PROJECT_CONFIG;
}

function readProjectConfig(){
  local project_to_read;
  [ "x${COMPUTE_TYPE}" == "xapache-ruby" -o "x${COMPUTE_TYPE}" == "xnginx-ruby" ] || [ "x${COMPUTE_TYPE}" == "xcartridge" -a "x${Engine_Type}" == "xruby" ] && {
    bundle_type=`cat /var/lib/jelastic/env`
    PROJECT_NAME="ROOT"
  }

  [ -z $1 ] && project_to_read=${PROJECT_NAME} || project_to_read="$1";
  if [ -e "${VCS_CONFIG_DIR}/${project_to_read}.properties" ] ; then
    source "${VCS_CONFIG_DIR}/${project_to_read}.properties";
    [ -z $VCS_TYPE ] && {
      return 1;
    }
    [ ! -z "$AUTHORIZATION_KEY" -a -f "$AUTHORIZATION_KEY" ] && { AUTHORIZATION_KEY_VAL=`cat $AUTHORIZATION_KEY`; export AUTHORIZATION_KEY; }
    [ -z "$GIT_AUTORESOLVE_CONFLICT" ] && GIT_AUTORESOLVE_CONFLICT=true ;
#    [ ! -z "$AUTHORIZATION_KEY" ] && {
#      export AUTHORIZATION_KEY;
#    }
  else
    #echo "Couldn't find project options!";
    return 1;
  fi
  return 0;
}

function enableVCSLibrary(){

  [ -z $VCS_TYPE ] && {
    echo "Unknown VCS type!";
    return 1;
  }

  case ${VCS_TYPE} in
    SVN)
      local vcslib="svn";
    ;;
    GIT)
      local vcslib="git";
    ;;
  esac
  include $vcslib;

}

function _deployLog(){
        echo -en "$(date) "$@ '\n' | tee -a "$DEPLOY_LOG" >> "$VCS_UPDATE_LOG";
}

##### External functions #####

function doCreateProject(){
  checkVCSDirectories;
  parseArguments "$@";

  isValidURL $URL || { writeJSONResponseErr "result=>4050" "message=>URL is not valid!"; return 1; };
  [ -n "$BRANCH" ] && {
        if [[ $BRANCH =~ $BRANCH_NAME_FILTER ]]; then
          writeJSONResponseErr "result=>4050" "message=>Branch name is not valid!";
          return 1;
        fi
  }
  local incorrect_login_regex="[~\!\#\$%^&\*\(\)\{\}\\\/=]";

  [[ $LOGIN  =~ $incorrect_login_regex ]] && { writeJSONResponseErr "result=>4053" "message=>Login is not valid!"; return 1; };
  [ -z $LOGIN ] && LOGIN="$DEFAULT_LOGIN";
  doEnableScheduler;
  writeProjectConfig && {
    [ ${COMPUTE_TYPE} == "apache-ruby" -o ${COMPUTE_TYPE} == "nginx-ruby" ] || [ "x${COMPUTE_TYPE}" == "xcartridge" -a "x${Engine_Type}" == "xruby" ] && {
    PROJECT_NAME=${bundle_type}; reloadServiceSilent "$SERVICE";
  } && [ ! -z $CONTEXT ] &&  [ ! -z $ENVIRONMENT ] && writeJSONResponseOut "result=>0" "message=>Project $PROJECT_NAME was successfully created" "project_name=>${PROJECT_NAME}" "vcs_type=>${VCS_TYPE}" "url=>${URL}" "login=>${LOGIN}" "branch=>${BRANCH}" "environment=>${ENVIRONMENT}" "context=>${CONTEXT}" "autoupdate=>${AUTOUPDATE}" "interval=>${UPDATE_INTERVAL}" "autoresolveconflict=>${GIT_AUTORESOLVE_CONFLICT}" || writeJSONResponseOut "result=>0" "message=>Project $PROJECT_NAME was successfully created" "project_name=>${PROJECT_NAME}" "vcs_type=>${VCS_TYPE}" "url=>${URL}" "login=>${LOGIN}" "branch=>${BRANCH}" "autoupdate=>${AUTOUPDATE}" "interval=>${UPDATE_INTERVAL}"  "autoresolveconflict=>${GIT_AUTORESOLVE_CONFLICT}" "atomic_deploy=>${ATOMIC_DEPLOY}"  "nodegroup=>${NODE_GROUP}"  "repohash=>${REPO_HASH}"; }  || { writeJSONResponseErr "result=>4001" "message=>Error while creating project config!"; return 1; };

}


function doDeleteProject(){
  parseArguments "$@";

  [ -z $PROJECT_NAME ] && {
    writeJSONResponseErr "result=>4005" "message=>You must specify project name!";
    return 1;
  }
  [ -d "${WEBROOT}/${PROJECT_NAME}" ] && rm -Rf ${WEBROOT}/${PROJECT_NAME};
  [[ "$PROJECT_NAME" == "ROOT" ]] && {
        rm -rf ${WEBROOT}/ROOT;
        cd ${WEBROOT}; ROOT_DIRS=$(ls ${WEBROOT} | $GREP "^ROOT_[0-9]\{4\}.[0-9]\{2\}.[0-9]\{2\}-[0-9]\{2\}.[0-9]\{2\}.[0-9]\{2\}$");
        rm -rf ${ROOT_DIRS} && _deployLog "Removing deprecated ROOT context directories ${ROOT_DIRS}";
        mkdir -p ${WEBROOT}/${PROJECT_NAME}; updateOwnership ${WEBROOT}/${PROJECT_NAME} > /dev/null 2>&1;
        [ -L ${WEBROOT}/../ROOT ] && {
                rm -f ${WEBROOT}/../ROOT;
                ln -s ${WEBROOT}/${PROJECT_NAME} ${WEBROOT}/../ROOT;
        }
  }
  [ -f "${VCS_CONFIG_DIR}/${PROJECT_NAME}.key" ] && rm -f "${VCS_CONFIG_DIR}/${PROJECT_NAME}.key";
  [ -f "${VCS_CONFIG_DIR}/${PROJECT_NAME}.properties" ] && rm -f "${VCS_CONFIG_DIR}/${PROJECT_NAME}.properties";
  writeJSONResponseOut "result=>0" "message=>Project $PROJECT_NAME was succesfully deleted";
  [ "`find ${VCS_CONFIG_DIR} -type f`" ] || doDisableScheduler;
  [ ${COMPUTE_TYPE} == "cartridge" ] && recoverBrokenMountPoints;
  removeHooks ${PROJECT_NAME} ;
}

function doUpdate(){
    parseArguments "$@";
    readProjectConfig || { writeJSONResponseErr "result=>4006" "message=>Error while reading project config!"; return 1; };
    enableVCSLibrary;
    applyHook ${PROJECT_NAME} preUpdate || { writeJSONResponseErr "result=>4127" "message=>Pre-update hook execution failed. See hooks log for details: ${HOOKS_LOG}"; return 1; };
    [ "x${COMPUTE_TYPE}" != "xmaven" ] && { applyHook ${PROJECT_NAME} preDeploy || { writeJSONResponseErr "result=>4125" "message=>Pre-deploy hook execution failed. See hooks log for details: ${HOOKS_LOG}"; return 1; }; }
    if [ "x${COMPUTE_TYPE}" == "xapache-php" -o "x${COMPUTE_TYPE}" == "xnginx-php" -o "x${COMPUTE_TYPE}" == "xlitespeed" -o "x${COMPUTE_TYPE}" == "xlemp" -o "x${COMPUTE_TYPE}" == "xllsmp" ] && [ "x${PROJECT_NAME}" == "xROOT" ] && [ "x${ATOMIC_DEPLOY}" == "xtrue" ]; then
        local NEXT_DIR=ROOT_`date +%Y.%m.%d-%H.%M.%S`;
        if [ -h ${WEBROOT}/ROOT ] ; then
            local CURRENT_DIR=`readlink ${WEBROOT}/ROOT | $GREP -o "ROOT_[0-9.-]*"`;
            [ ! -d ${WEBROOT}/${CURRENT_DIR} ] && CURRENT_DIR=`ls ${WEBROOT} | $GREP "^ROOT_[0-9]\{4\}.[0-9]\{2\}.[0-9]\{2\}-[0-9]\{2\}.[0-9]\{2\}.[0-9]\{2\}$" | tail -n1`;
            if [ -n "${CURRENT_DIR}" ]; then
                local PREVIOUS_DIR=`ls ${WEBROOT} | $GREP "^ROOT_[0-9]\{4\}.[0-9]\{2\}.[0-9]\{2\}-[0-9]\{2\}.[0-9]\{2\}.[0-9]\{2\}$" | $GREP -v "$CURRENT_DIR" | head -1`;
            else
                local PREVIOUS_DIR=`ls ${WEBROOT} | $GREP "^ROOT_[0-9]\{4\}.[0-9]\{2\}.[0-9]\{2\}-[0-9]\{2\}.[0-9]\{2\}.[0-9]\{2\}$" | head -1`;
            fi
        else
            CURRENT_DIR=`ls ${WEBROOT} | $GREP "^ROOT_[0-9]\{4\}.[0-9]\{2\}.[0-9]\{2\}-[0-9]\{2\}.[0-9]\{2\}.[0-9]\{2\}$" | tail -n1`
            [ -n "${CURRENT_DIR}" ] && { ln -sfT "${WEBROOT}/${CURRENT_DIR}" ${WEBROOT}/ROOT && _deployLog "Swithing the ROOT context to ${CURRENT_DIR}"; updateOwnership ${WEBROOT}/ROOT; }
        fi
        if [[ -d ${WEBROOT}/ROOT && ! -h ${WEBROOT}/ROOT ]] ; then
            if [ "$UID" == '0' ]; then
                chown -R ${DATA_OWNER} ${WEBROOT}/ROOT;
            fi 
            mv -f ${WEBROOT}/ROOT ${WEBROOT}/$NEXT_DIR && _deployLog "Copying content of the ROOT directory to $NEXT_DIR";
        fi
        if [ -z "${PREVIOUS_DIR}" ] ;then
            local DIR_AMOUNT=`ls ${WEBROOT} | $GREP "^ROOT_[0-9]\{4\}.[0-9]\{2\}.[0-9]\{2\}-[0-9]\{2\}.[0-9]\{2\}.[0-9]\{2\}$" | wc -l`;
            [ ${DIR_AMOUNT} -gt 1 ]  && PREVIOUS_DIR=`ls ${WEBROOT} | $GREP "^ROOT_[0-9]\{4\}.[0-9]\{2\}.[0-9]\{2\}-[0-9]\{2\}.[0-9]\{2\}.[0-9]\{2\}$" | tail -n2 | head -1`;
        fi
        [ -n "${PREVIOUS_DIR}" ] && rm -rf ${WEBROOT}/${PREVIOUS_DIR} && _deployLog "Removing old deprecated context directory ${PREVIOUS_DIR}";
        if [ -n "${CURRENT_DIR}" ] ;then
            if [ "$UID" == '0' ]; then
                chown -R ${DATA_OWNER} ${WEBROOT}/${CURRENT_DIR};
            fi
            if which rsync &>>/dev/null; then 
                rsync -alrp --inplace --quiet --ignore-errors ${WEBROOT}/${CURRENT_DIR}/ ${WEBROOT}/${NEXT_DIR} 2>&1;
                local result=$?;
                if [ $result -ne 0 ]; then
                    writeJSONResponseErr "result=>4075" "message=>Rsync error code $result (probably because of unsufficient disk space)" && _deployLog "Cannot move application from ${CURRENT_DIR} to ${NEXT_DIR} (probably beca
use of unsufficient disk space). rsync exit code is $result";
                    return 1;
                else
                    _deployLog "Copying application files from ${CURRENT_DIR} to ${NEXT_DIR} - successful";
                fi    
            else
                cp -rf ${WEBROOT}/${CURRENT_DIR}/ ${WEBROOT}/${NEXT_DIR} 2>&1;
                if [ $? -ne 0 ]; then
                    writeJSONResponseErr "result=>4075" "message=>No free diskspace" && _deployLog "Not enough disk space. Cannot move application from ${CURRENT_DIR} to ${NEXT_DIR}";
                    return 1;
                else
                    _deployLog "Copying application files from ${CURRENT_DIR} to ${NEXT_DIR}"
                fi
            fi
        fi
        J_OLD_PROJECT_NAME="${PROJECT_NAME}";
        PROJECT_NAME="${NEXT_DIR}"
        if [ -d "${WEBROOT}/${PROJECT_NAME}/.$(toLowerCase ${VCS_TYPE})" ] ; then
            updateProject 2>>"$VCS_UPDATE_LOG"
            result=$?
            updateOwnership ${WEBROOT}/${PROJECT_NAME};
            if [[ $result == 0 ]]; then
                ln -sfT "${WEBROOT}/${PROJECT_NAME}" ${WEBROOT}/ROOT && _deployLog "Switching the document root to new context directory ${PROJECT_NAME}";
                updateOwnership ${WEBROOT}/ROOT;
                [ -z "${J_OLD_PROJECT_NAME}" ] || { PROJECT_NAME="${J_OLD_PROJECT_NAME}"; writeProjectConfig; }
            else
                if [[ $result == 2 ]]; then
                    writeJSONResponseErr "result=>4211" "message=>Token required";
                else
                    writeJSONResponseErr "result=>4000" "message=>Authentication failed or url is incorrect";
                fi
                return 1;
            fi
        else
            doCheckout
            result=$?
            if [[ $result == 2 ]]; then
                    writeJSONResponseErr "result=>4211" "message=>Token required";
                    die -q;
            elif [[ $result != 0 ]]; then
                writeJSONResponseErr "result=>4000" "message=>Authentication failed or url is incorrect";
                die -q;
            fi
            updateOwnership ${WEBROOT}/${PROJECT_NAME};
            ln -sfT "${WEBROOT}/${PROJECT_NAME}" ${WEBROOT}/ROOT && _deployLog "Switching the document root to new context directory ${PROJECT_NAME}"; updateOwnership ${WEBROOT}/ROOT;
            [ -z "${J_OLD_PROJECT_NAME}" ] || { PROJECT_NAME="${J_OLD_PROJECT_NAME}"; writeProjectConfig; }
        fi
    else
        if [ "x${PROJECT_NAME}" == "xROOT" ] && [ -L ${WEBROOT}/ROOT ]; then
            TARGET_DIR=`readlink ${WEBROOT}/ROOT | $GREP -o "ROOT_[0-9.-]*"`;
            [ ! -d ${WEBROOT}/${TARGET_DIR} ] && local TARGET_DIR=`ls ${WEBROOT} | $GREP "^ROOT_[0-9]\{4\}.[0-9]\{2\}.[0-9]\{2\}-[0-9]\{2\}.[0-9]\{2\}.[0-9]\{2\}$" | tail -n1`;
            rm -f ${WEBROOT}/ROOT;
            if [ -n "${TARGET_DIR}" ] ;then
                if [ ! -d ${WEBROOT}/ROOT ] ;then
                    mkdir ${WEBROOT}/ROOT;
                else
                    shopt -s dotglob;
                    rm -rf ${WEBROOT}/ROOT/* && _deployLog "Removing the content of current ROOT directory";
                    shopt -u dotglob;
                fi
		if [ "$UID" == '0' ]; then
                    chown -R ${DATA_OWNER} "${WEBROOT}/${TARGET_DIR}/";
                fi 
                shopt -s dotglob;
                set +f
                mv -f ${WEBROOT}/${TARGET_DIR}/* ${WEBROOT}/ROOT;
                if [ $? -ne 0 ]; then
                    shopt -u dotglob;
                    writeJSONResponseErr "result=>4075" "message=>No free diskspace" && _deployLog "Not enough disk space. Cannot move application to ROOT directory";
                    return 1;
                fi
                shopt -u dotglob;
            fi
            cd ${WEBROOT}; ROOT_DIRS=`ls ${WEBROOT} | $GREP "^ROOT_[0-9]\{4\}.[0-9]\{2\}.[0-9]\{2\}-[0-9]\{2\}.[0-9]\{2\}.[0-9]\{2\}$"`;
            rm -rf ${ROOT_DIRS} && _deployLog "Removing deprecated ROOT context directories ${ROOT_DIRS}"; cd  /;
        fi
        if [ -d "${WEBROOT}/${PROJECT_NAME}/.$(toLowerCase ${VCS_TYPE})" ] ; then
            updateProject 2>>"$VCS_UPDATE_LOG"
            result=$?
            updateOwnership ${WEBROOT}/${PROJECT_NAME};
            if [[ $result == 0 ]]; then
                writeProjectConfig;
            else
                if [[ $result == 2 ]]; then
                    writeJSONResponseErr "result=>4211" "message=>Token required";
                else
                    writeJSONResponseErr "result=>4000" "message=>Authentication failed or url is incorrect";
                fi
                return $result;
            fi
        else
            [ -d "${WEBROOT}/${PROJECT_NAME}" ] && rm -Rf "${WEBROOT}/${PROJECT_NAME}/";
            doCheckout
            result=$?
            if [[ $result == 2 ]]; then
                writeJSONResponseErr "result=>4211" "message=>Token required"; die -q;
            elif [[ $result != 0 ]]; then
                writeJSONResponseErr "result=>4000" "message=>Authentication failed or url is incorrect"; die -q;
            fi
            updateOwnership ${WEBROOT}/${PROJECT_NAME}; writeProjectConfig;
        fi
    fi
    [ "x${COMPUTE_TYPE}" != "xmaven" ]  && isFunction "setContext" && setContext ${PROJECT_NAME};
    [ "x${COMPUTE_TYPE}" == "xcartridge" ] && recoverBrokenMountPoints && service cartridge build >>  $ACTIONS_LOG  2>&1  && service cartridge deploy >> $ACTIONS_LOG  2>&1;
    applyHook ${PROJECT_NAME} postUpdate || { writeJSONResponseErr "result=>4128" "message=>Post-update hook execution failed. See hooks log for details: ${HOOKS_LOG}"; return 1; };
    [ "x${COMPUTE_TYPE}" != "xmaven" ] && { 
        applyHook ${PROJECT_NAME} postDeploy || {
            local hook_error_message="message=>Post-deploy hook execution failed. See hooks log for details: ${HOOKS_LOG}" 
            if [ "x${ATOMIC_DEPLOY}" == "xtrue" ]; then
                CURRENT_DIR=$(ls ${WEBROOT} | $GREP "^ROOT_[0-9]\{4\}.[0-9]\{2\}.[0-9]\{2\}-[0-9]\{2\}.[0-9]\{2\}.[0-9]\{2\}$" | tail -n1);
                PREVIOUS_DIR=$(ls -1 ${WEBROOT}  | grep "^ROOT_[0-9]\{4\}.[0-9]\{2\}.[0-9]\{2\}-[0-9]\{2\}.[0-9]\{2\}.[0-9]\{2\}$" | tail -n2|head -n 1);
                if [ -n "${PREVIOUS_DIR}" ]; then 
                    ln -sfT ${WEBROOT}/${PREVIOUS_DIR} ${WEBROOT}/ROOT && _deployLog "Switching the ROOT context back to ${PREVIOUS_DIR} directory due to failed postDeploy hook execution.";
                    chown -R ${DATA_OWNER} ${WEBROOT}/ROOT;
                    hook_error_message="${hook_error_message}. ROOT context now points to directory ${WEBROOT}/${PREVIOUS_DIR}."
                    if [ "${PREVIOUS_DIR}" != "${CURRENT_DIR}" ]; then
                        rm -rf ${WEBROOT}/${CURRENT_DIR}
                    fi
                fi
            fi 
            writeJSONResponseErr "result=>4126" "${hook_error_message}"; return 1; 
        }; 
    }
    writeJSONResponseOut "result=>0" "message=>Project updated successfully"; return 0; 
}

function doCallProjectUpdate(){
  local project_name="$1";
  local last_repo_commit=$(getLastRepoCommit $project_name);
  [ "x${last_repo_commit}" == "x${LAST_DEPLOYED_COMMIT}" ] && return 0;
  getInfraAddresses infraAddr;

  [[ -z "${CORE_ADDR}" ]] && {
    error "Cannot obtain core address";
    return 1;
  }

  $CURL "http://${CORE_ADDR}/JElastic/env/build/rest/builddeploy?appid=01234567890123456789012345678901&projectName=$project_name" &>>"$JEM_CALLS_LOG";
  LAST_DEPLOYED_COMMIT=$last_repo_commit;
  writeProjectConfig;
}


function doAutoUpdate(){
  NO_EXPECT="true";
  UPDATE_IS_OK="false";

  [ "`find ${VCS_CONFIG_DIR} -type f`" ] && {
    for project in $( ls ${VCS_CONFIG_DIR}/*.properties );
    do
        source ${project}
        enableVCSLibrary;
        [[ "x$AUTOUPDATE" == "xtrue" ]] && {
	    LastRemoteCommitVal=$(getLastRemoteCommit)
            [[ ${LAST_DEPLOYED_COMMIT} == $LastRemoteCommitVal ]] && continue ;
            [[ $LastRemoteCommitVal == "00000000000" ]] && continue ;
            local next_allowed_update=$(( $LASTUPDATE + $UPDATE_INTERVAL * 60 ));
            local current_timestamp=`date +%s`;
            [[ $next_allowed_update -lt $current_timestamp ]] && doUpdate >> $JEM_CALLS_LOG && UPDATE_IS_OK="true" && writeProjectConfig;
            [[ "x${COMPUTE_TYPE}" == "xmaven" ]] && [[ "x${UPDATE_IS_OK,,}" == "xtrue" ]] && doCallProjectUpdate $PROJECT_NAME;
        }

    done
  }
 return 0 ;
}

function doEnableScheduler(){
  if [ -f $REDEPLOY_CONF_FILE ]; then
    $GREP -q "^$ROOT_CRONFILE" $REDEPLOY_CONF_FILE || echo "$ROOT_CRONFILE" >> $REDEPLOY_CONF_FILE;
  fi
  [ -f $ROOT_CRONFILE ] && $GREP -q "\^$AUTOUPDATE_CRON_STRING"  $ROOT_CRONFILE || { echo "$AUTOUPDATE_CRON_STRING" >> $ROOT_CRONFILE; chmod 0644 $ROOT_CRONFILE; }
}

function doDisableScheduler(){
  [ -f $ROOT_CRONFILE ] && $SED -i "/$AUTOUPDATE_CRON_STRING/d" $ROOT_CRONFILE;
}

function doGetProject(){
  parseArguments "$@";
  readProjectConfig || { writeJSONResponseErr "result=>4006" "message=>Error while reading project config!"; return 1; };
  [ ${COMPUTE_TYPE} == "apache-ruby" -o ${COMPUTE_TYPE} == "nginx-ruby" ] || [ "x${COMPUTE_TYPE}" == "xcartridge" -a "x${Engine_Type}" == "xruby" ] && {
    PROJECT_NAME=${bundle_type}
  }
  VAL="project_name=>${PROJECT_NAME} vcs_type=>${VCS_TYPE} url=>${URL} login=>${LOGIN} branch=>${BRANCH} interval=>${UPDATE_INTERVAL} autoupdate=>${AUTOUPDATE} atomicdeploy=>${ATOMIC_DEPLOY}";
  [ ! -z "$CONTEXT" ] &&  [ ! -z "$ENVIRONMENT" ] && { VAL=$VAL" environment=>${ENVIRONMENT} context=>${CONTEXT}" ; }
  [ ! -z "$AUTHORIZATION_KEY_VAL" ] && { hash=`echo "$AUTHORIZATION_KEY_VAL" | md5sum | $AWK '{print $1}'`; VAL=$VAL" hash=>$hash"; }
  [ ! -z $GIT_AUTORESOLVE_CONFLICT ] && { VAL=$VAL" resolveconflict=>${GIT_AUTORESOLVE_CONFLICT}"; }
  [ ! -z "$BUILDDIR" ] && { VAL=$VAL" subdirectory=>${BUILDDIR}"; }
  [ ! -z "$NODE_GROUP" ] && { VAL=$VAL" nodegroup=>${NODE_GROUP}"; }
  [ ! -z "$REPO_HASH" ] && { VAL=$VAL" repohash=>${REPO_HASH}"; }
  writeJSONResponseOut "result=>0" ${VAL} ;
}

function doEditProject(){
  local repository_url_was_changed="false";
  parseArguments "$@";
  [ "${COMPUTE_TYPE}" == "apache-ruby" -o "${COMPUTE_TYPE}" == "nginx-ruby" ] || [ "x${COMPUTE_TYPE}" == "xcartridge" -a "x${Engine_Type}" == "xruby" ] && {
        OLD_PROJECT_NAME="ROOT"
  }
  CLEAN_KEY=0; CLEAN_PASSWORD=0;
  [ ! -z "$PASSWORD" ] && { # password was in  params, clean key
        CLEAN_KEY=1;
  }
  [ ! -z "$AUTHORIZATION_KEY_VAL" ]  && { # ssh key was in params, clean password
        CLEAN_PASSWORD=1;
        [ "$CLEAN_KEY" -eq 1 ] && { writeJSONResponseErr "result=>4017" "message=>Project edit failed"; return 1; }
  }
  [ -n "$BRANCH" ] && {
        if [[ $BRANCH =~ $BRANCH_NAME_FILTER ]]; then
          writeJSONResponseErr "result=>4050" "message=>Branch name is not valid!";
          return 1;
        fi
  }

  #[ ! -z $URL ]  &&  repository_url_was_changed="true";
  isValidURL $URL || { writeJSONResponseErr "result=>4050" "message=>URL is not valid!"; return 1; };
  readProjectConfig $OLD_PROJECT_NAME || { writeJSONResponseErr "result=>4006" "message=>Error while reading project config!"; return 1; };
  doEnableScheduler;
  [ ! -z "$URL" ] && OLDURL="$URL";
  [ ! -z "$PASSWORD" ] && OLDPASSWORD="$PASSWORD";
  [ ! -z "$LOGIN" ] && OLDLOGIN="$LOGIN";

  parseArguments "$@";
  [ "${COMPUTE_TYPE}" == "apache-ruby" -o "${COMPUTE_TYPE}" == "nginx-ruby" ] || [ "x${COMPUTE_TYPE}" == "xcartridge" -a "x${Engine_Type}" == "xruby" ] && {
        OLD_PROJECT_NAME="ROOT";
  }
  [ ! -z "$URL" ] && NEWURL=$URL;
  [ "x$OLDURL" != "x$NEWURL" -o "x$OLDPASSWORD" != "x$PASSWORD" -o "x$OLDLOGIN" != "x$LOGIN" ]  &&  repository_url_was_changed="true";
  [ "$CLEAN_KEY" -eq 1 ] && { AUTHORIZATION_KEY_VAL="" ; AUTHORIZATION_KEY=""; rm -rf "${VCS_CONFIG_DIR}/${PROJECT_NAME}.key"; }
  [ "$CLEAN_PASSWORD" -eq 1 ] && { PASSWORD=""; }
  if [ "x$repository_url_was_changed" ==  "xtrue" -a  -d "${WEBROOT}/${PROJECT_NAME}/.$(toLowerCase ${VCS_TYPE})" ] ; then
    enableVCSLibrary;
    vcsChangeUrl;
    changeUrlresult=$?;
  else
    changeUrlresult=0;
  fi

  ( [[ -n "${OLD_PROJECT_NAME}" ]] && [[ -n "${PROJECT_NAME}" ]] && [[ "$OLD_PROJECT_NAME" != "$PROJECT_NAME" ]] ) && {
    # doAction deploy rename -o $OLD_PROJECT_NAME -n $PROJECT_NAME > /dev/null 2>&1;
    if [ ! -d "${WEBROOT}/${PROJECT_NAME}/" ]; then
        if [ "x${COMPUTE_TYPE}" != "xmaven" ]; then
                mkdir "${WEBROOT}/${PROJECT_NAME}/";
        else
                [ -d "${WEBROOT}/${OLD_PROJECT_NAME}/" ] && mkdir "${WEBROOT}/${PROJECT_NAME}/";
        fi
    fi
    [ -d "${WEBROOT}/${PROJECT_NAME}/" ] && [ -d "${WEBROOT}/${OLD_PROJECT_NAME}/" ] && { renameContext $PROJECT_NAME $OLD_PROJECT_NAME ; } 
    [ "x${PROJECT_NAME}" != "xROOT" ] && ATOMIC_DEPLOY="false";
  }
  renameHooks $PROJECT_NAME $OLD_PROJECT_NAME;
  if [ "$changeUrlresult" -eq 0 ]; then
        writeProjectConfig ;
        writeProjectresult=$?;
  else
        writeProjectresult=-1;
  fi
  if [ "$writeProjectresult" -eq 0 -a "$changeUrlresult" -eq 0 ]; then
        if [ "x$OLD_PROJECT_NAME" !=  "x$PROJECT_NAME" -a -f "${VCS_CONFIG_DIR}/${OLD_PROJECT_NAME}.properties" ];then
          rm -f "${VCS_CONFIG_DIR}/${OLD_PROJECT_NAME}.properties";
        fi
        VAL="project_name=>${PROJECT_NAME} vcs_type=>${VCS_TYPE} url=>${URL} login=>${LOGIN} branch=>${BRANCH} resolveconflict=>${GIT_AUTORESOLVE_CONFLICT}";
    if [ ! -z "$CONTEXT" -a  ! -z "$ENVIRONMENT" ] ; then
                VAL=$VAL" environment=>${ENVIRONMENT} context=>${CONTEXT} autoupdate=>${AUTOUPDATE} interval=>${UPDATE_INTERVAL}" ;
        fi
        if [ ! -z "$AUTHORIZATION_KEY_VAL" ] ; then
                hash=`echo $AUTHORIZATION_KEY_VAL | md5sum | $AWK '{print $1}'`;
                VAL=$VAL" hash=>$hash";
        fi
        writeJSONResponseOut "result=>0" "message=>Project edited successfully" ${VAL} ;

  else
        writeJSONResponseErr "result=>4017" "message=>Project edit failed"
        return 1
 fi
}

function describeUpdate(){
    echo "Update project";
}

