| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712 | 
							- #!/usr/bin/env bash
 
- # -*- coding: utf-8; mode: sh indent-tabs-mode: nil -*-
 
- # SPDX-License-Identifier: AGPL-3.0-or-later
 
- # shellcheck disable=SC2059,SC1117
 
- ADMIN_NAME="${ADMIN_NAME:-$(git config user.name)}"
 
- ADMIN_NAME="${ADMIN_NAME:-$USER}"
 
- ADMIN_EMAIL="${ADMIN_EMAIL:-$(git config user.email)}"
 
- ADMIN_EMAIL="${ADMIN_EMAIL:-$USER@$(hostname)}"
 
- if [[ -z "${REPO_ROOT}" ]]; then
 
-     REPO_ROOT=$(dirname "${BASH_SOURCE[0]}")
 
-     while [ -h "${REPO_ROOT}" ] ; do
 
-         REPO_ROOT=$(readlink "${REPO_ROOT}")
 
-     done
 
-     REPO_ROOT=$(cd "${REPO_ROOT}/.." && pwd -P )
 
- fi
 
- if [[ -z ${TEMPLATES} ]]; then
 
-     TEMPLATES="${REPO_ROOT}/utils/templates"
 
- fi
 
- if [[ -z "$CACHE" ]]; then
 
-     CACHE="${REPO_ROOT}/cache"
 
- fi
 
- if [[ -z "$SYSTEMD_UNITS" ]]; then
 
-     SYSTEMD_UNITS="/lib/systemd/system"
 
- fi
 
- if [[ -z ${DIFF_CMD} ]]; then
 
-     DIFF_CMD="diff -u"
 
-     if command -v colordiff >/dev/null;  then
 
-         DIFF_CMD="colordiff -u"
 
-     fi
 
- fi
 
- DOT_CONFIG="${DOT_CONFIG:-${REPO_ROOT}/.config}"
 
- source_dot_config() {
 
-     if [[ ! -e "$DOT_CONFIG" ]]; then
 
-         info_msg "installing $DOT_CONFIG"
 
-         cp "$(dirname "${BASH_SOURCE[0]}")/dot_config" "$DOT_CONFIG"
 
-         if [[ ! -z ${SUDO_USER} ]]; then
 
-             chown "${SUDO_USER}:${SUDO_USER}" "$DOT_CONFIG"
 
-         fi
 
-     fi
 
-     # shellcheck disable=SC1090
 
-     source "${REPO_ROOT}/.config"
 
- }
 
- sudo_or_exit() {
 
-     # usage: sudo_or_exit
 
-     if [ ! "$(id -u)" -eq 0 ];  then
 
-         err_msg "this command requires root (sudo) privilege!" >&2
 
-         exit 42
 
-     fi
 
- }
 
- required_commands() {
 
-     # usage:  requires_commands [cmd1 ...]
 
-     local exit_val=0
 
-     while [ ! -z "$1" ]; do
 
-         if ! command -v "$1" &>/dev/null; then
 
-             err_msg "missing command $1"
 
-             exit_val=42
 
-         fi
 
-         shift
 
-     done
 
-     return $exit_val
 
- }
 
- rst_title() {
 
-     # usage: rst_title <header-text> [part|chapter|section]
 
-     case ${2-chapter} in
 
-         part)     printf "\n${1//?/=}\n$1\n${1//?/=}\n";;
 
-         chapter)  printf "\n${1}\n${1//?/=}\n";;
 
-         section)  printf "\n${1}\n${1//?/-}\n";;
 
-         *)
 
-             err_msg "invalid argument '${2}' in line $(caller)"
 
-             return 42
 
-             ;;
 
-     esac
 
- }
 
- if command -v fmt >/dev/null; then
 
-     export FMT="fmt -u"
 
- else
 
-     export FMT="cat"
 
- fi
 
- rst_para() {
 
-     # usage:  RST_INDENT=1 rst_para "lorem ipsum ..."
 
-     local prefix=''
 
-     if ! [[ -z $RST_INDENT ]] && [[ $RST_INDENT -gt 0 ]]; then
 
-         prefix="$(for i in $(seq 1 "$RST_INDENT"); do printf "  "; done)"
 
-         echo -en "\n$*\n" | $FMT | prefix_stdout "$prefix"
 
-     else
 
-         echo -en "\n$*\n" | $FMT
 
-     fi
 
- }
 
- err_msg()  { echo -e "ERROR: $*" >&2; }
 
- warn_msg() { echo -e "WARN:  $*" >&2; }
 
- info_msg() { echo -e "INFO:  $*"; }
 
- clean_stdin() {
 
-     if [[ $(uname -s) != 'Darwin' ]]; then
 
-         while read -r -n1 -t 0.1; do : ; done
 
-     fi
 
- }
 
- wait_key(){
 
-     # usage: waitKEY [<timeout in sec>]
 
-     clean_stdin
 
-     local _t=$1
 
-     local msg="${MSG:-** press any [KEY] to continue **}"
 
-     [[ ! -z $FORCE_TIMEOUT ]] && _t=$FORCE_TIMEOUT
 
-     [[ ! -z $_t ]] && _t="-t $_t"
 
-     # shellcheck disable=SC2086
 
-     read -r -s -n1 $_t -p "$msg"
 
-     echo
 
-     clean_stdin
 
- }
 
- ask_yn() {
 
-     # usage: ask_yn <prompt-text> [Ny|Yn] [<timeout in sec>]
 
-     local EXIT_YES=0 # exit status 0 --> successful
 
-     local EXIT_NO=1  # exit status 1 --> error code
 
-     local _t=$3
 
-     [[ ! -z $FORCE_TIMEOUT ]] && _t=$FORCE_TIMEOUT
 
-     [[ ! -z $_t ]] && _t="-t $_t"
 
-     case "${2}" in
 
-         Yn)
 
-             local exit_val=${EXIT_YES}
 
-             local choice="[YES/no]"
 
-             local default="Yes"
 
-             ;;
 
-         *)
 
-             local exit_val=${EXIT_NO}
 
-             local choice="[NO/yes]"
 
-             local default="No"
 
-             ;;
 
-     esac
 
-     echo
 
-     while true; do
 
-         clean_stdin
 
-         printf "$1 ${choice} "
 
-         # shellcheck disable=SC2086
 
-         read -r -n1 $_t
 
-         if [[ -z $REPLY ]]; then
 
-             printf "$default\n"; break
 
-         elif [[ $REPLY =~ ^[Yy]$ ]]; then
 
-             exit_val=${EXIT_YES}
 
-             printf "\n"
 
-             break
 
-         elif [[ $REPLY =~ ^[Nn]$ ]]; then
 
-             exit_val=${EXIT_NO}
 
-             printf "\n"
 
-             break
 
-         fi
 
-         _t=""
 
-         err_msg "invalid choice"
 
-     done
 
-     clean_stdin
 
-     return $exit_val
 
- }
 
- tee_stderr () {
 
-     # usage::
 
-     #   tee_stderr 1 <<EOF | python -i
 
-     #   print("hello")
 
-     #   EOF
 
-     #   ...
 
-     #   >>> print("hello")
 
-     #    hello
 
-     local _t="0";
 
-     if [[ ! -z $1 ]] ; then _t="$1"; fi
 
-     (while read -r line; do
 
-          # shellcheck disable=SC2086
 
-          sleep $_t
 
-          echo -e "$line" >&2
 
-          echo "$line"
 
-     done)
 
- }
 
- prefix_stdout () {
 
-     # usage: <cmd> | prefix_stdout [prefix]
 
-     local prefix="  | "
 
-     if [[ ! -z $1 ]] ; then prefix="$1"; fi
 
-     # shellcheck disable=SC2162
 
-     (while IFS= read line; do
 
-         echo -e "${prefix}$line"
 
-     done)
 
- }
 
- append_line() {
 
-     # usage: append_line <line> <file>
 
-     #
 
-     # Append line if not exists, create file if not exists. E.g::
 
-     #
 
-     #     append_line 'source ~/.foo' ~/bashrc
 
-     local LINE=$1
 
-     local FILE=$2
 
-     grep -qFs -- "$LINE" "$FILE" || echo "$LINE" >> "$FILE"
 
- }
 
- cache_download() {
 
-     # usage: cache_download <url> <local-filename>
 
-     local exit_value=0
 
-     if [[ ! -z ${SUDO_USER} ]]; then
 
-         sudo -u "${SUDO_USER}" mkdir -p "${CACHE}"
 
-     else
 
-         mkdir -p "${CACHE}"
 
-     fi
 
-     if [[ -f "${CACHE}/$2" ]] ; then
 
-         info_msg "already cached: $1"
 
-         info_msg "  --> ${CACHE}/$2"
 
-     fi
 
-     if [[ ! -f "${CACHE}/$2" ]]; then
 
-         info_msg "caching: $1"
 
-         info_msg "  --> ${CACHE}/$2"
 
-         if [[ ! -z ${SUDO_USER} ]]; then
 
-             sudo -u "${SUDO_USER}" wget --progress=bar -O "${CACHE}/$2" "$1" ; exit_value=$?
 
-         else
 
-             wget --progress=bar -O "${CACHE}/$2" "$1" ; exit_value=$?
 
-         fi
 
-         if [[ $exit_value = 0 ]]; then
 
-             err_msg "failed to download: $1"
 
-         fi
 
-     fi
 
- }
 
- choose_one() {
 
-     # usage:
 
-     #
 
-     #   DEFAULT_SELECT= 2 \
 
-     #     choose_one <name> "your selection?" "Coffee" "Coffee with milk"
 
-     local default=${DEFAULT_SELECT-1}
 
-     local REPLY
 
-     local env_name=$1 && shift
 
-     local choice=$1;
 
-     local max="${#@}"
 
-     local _t
 
-     [[ ! -z $FORCE_TIMEOUT ]] && _t=$FORCE_TIMEOUT
 
-     [[ ! -z $_t ]] && _t="-t $_t"
 
-     list=("$@")
 
-     echo -e "Menu::"
 
-     for ((i=1; i<= $((max -1)); i++)); do
 
-         if [[ "$i" == "$default" ]]; then
 
-             echo -e "  $i.) ${list[$i]} [default]"
 
-         else
 
-             echo -e "  $i.) ${list[$i]}"
 
-         fi
 
-     done
 
-     while true; do
 
-         clean_stdin
 
-         printf "$1 [$default] "
 
-         if (( 10 > max )); then
 
-             # shellcheck disable=SC2086
 
-             read -r -n1 $_t
 
-         else
 
-             # shellcheck disable=SC2086,SC2229
 
-             read -r $_t
 
-         fi
 
-         # selection fits
 
-         [[ $REPLY =~ ^-?[0-9]+$ ]] && (( REPLY > 0 )) && (( REPLY < max )) && break
 
-         # take default
 
-         [[ -z $REPLY ]] && REPLY=$default && break
 
-         _t=""
 
-         err_msg "invalid choice"
 
-     done
 
-     eval "$env_name"='${list[${REPLY}]}'
 
-     echo
 
-     clean_stdin
 
- }
 
- install_template() {
 
-     # usage:
 
-     #
 
-     #     install_template [--no-eval] [--variant=<name>] \
 
-     #                      {file} [{owner} [{group} [{chmod}]]]
 
-     #
 
-     # E.g. the origin of variant 'raw' of /etc/updatedb.conf is::
 
-     #
 
-     #    ${TEMPLATES}/etc/updatedb.conf:raw
 
-     #
 
-     # To install variant 'raw' of /etc/updatedb.conf without evaluated
 
-     # replacements you can use::
 
-     #
 
-     #    install_template --variant=raw --no-eval \
 
-     #                     /etc/updatedb.conf root root 644
 
-     local _reply=""
 
-     local do_eval=1
 
-     local variant=""
 
-     local pos_args=("$0")
 
-     for i in "$@"; do
 
-         case $i in
 
-             --no-eval) do_eval=0; shift ;;
 
-             --variant=*) variant=":${i#*=}"; shift ;;
 
-             *) pos_args+=("$i") ;;
 
-         esac
 
-     done
 
-     local dst="${pos_args[1]}"
 
-     local template_origin="${TEMPLATES}${dst}${variant}"
 
-     local template_file="${TEMPLATES}${dst}"
 
-     local owner="${pos_args[2]-$(id -un)}"
 
-     local group="${pos_args[3]-$(id -gn)}"
 
-     local chmod="${pos_args[4]-644}"
 
-     info_msg "install (eval=$do_eval): ${dst}"
 
-     [[ ! -z $variant ]] && info_msg "variant: ${variant}"
 
-     if [[ ! -f "${template_origin}" ]] ; then
 
-         err_msg "${template_origin} does not exists"
 
-         err_msg "... can't install $dst"
 
-         wait_key 30
 
-         return 42
 
-     fi
 
-     if [[ "$do_eval" == "1" ]]; then
 
-         template_file="${CACHE}${dst}${variant}"
 
-         info_msg "BUILD template ${template_file}"
 
-         if [[ ! -z ${SUDO_USER} ]]; then
 
-             sudo -u "${SUDO_USER}" mkdir -p "$(dirname "${template_file}")"
 
-         else
 
-             mkdir -p "$(dirname "${template_file}")"
 
-         fi
 
-         # shellcheck disable=SC2086
 
-         eval "echo \"$(cat ${template_origin})\"" > "${template_file}"
 
-         if [[ ! -z ${SUDO_USER} ]]; then
 
-             chown "${SUDO_USER}:${SUDO_USER}" "${template_file}"
 
-         fi
 
-     else
 
-         template_file=$template_origin
 
-     fi
 
-     mkdir -p "$(dirname "${dst}")"
 
-     if [[ ! -f "${dst}" ]]; then
 
-         info_msg "install: ${template_file}"
 
-         sudo -H install -v -o "${owner}" -g "${group}" -m "${chmod}" \
 
-              "${template_file}" "${dst}" | prefix_stdout
 
-         return $?
 
-     fi
 
-     if [[ -f "${dst}" ]] && cmp --silent "${template_file}" "${dst}" ; then
 
-         info_msg "file ${dst} allready installed"
 
-         return 0
 
-     fi
 
-     info_msg "diffrent file ${dst} allready exists on this host"
 
-     while true; do
 
-         choose_one _reply "choose next step with file $dst" \
 
-                    "replace file" \
 
-                    "leave file unchanged" \
 
-                    "interactiv shell" \
 
-                    "diff files"
 
-         case $_reply in
 
-             "replace file")
 
-                 info_msg "install: ${template_file}"
 
-                 sudo -H install -v -o "${owner}" -g "${group}" -m "${chmod}" \
 
-                      "${template_file}" "${dst}" | prefix_stdout
 
-                 break
 
-                 ;;
 
-             "leave file unchanged")
 
-                 break
 
-                 ;;
 
-             "interactiv shell")
 
-                 echo "// edit ${dst} to your needs"
 
-                 echo "// exit with CTRL-D"
 
-                 sudo -H -u "${owner}" -i
 
-                 $DIFF_CMD "${dst}" "${template_file}"
 
-                 echo
 
-                 echo "did you edit file ..."
 
-                 printf "  ${template_file}"
 
-                 if ask_yn "... to your needs?"; then
 
-                     break
 
-                 fi
 
-                 ;;
 
-             "diff files")
 
-                 $DIFF_CMD "${dst}" "${template_file}" | prefix_stdout
 
-         esac
 
-     done
 
- }
 
- service_is_available() {
 
-     # usage:  service_is_available <URL>
 
-     local URL="$1"
 
-     if [[ -z $URL ]]; then
 
-         err_msg "service_is_available: missing arguments"
 
-         return 42
 
-     fi
 
-     http_code=$(curl -H 'Cache-Control: no-cache' \
 
-          --silent -o /dev/null --head --write-out '%{http_code}' --insecure \
 
-          "${URL}")
 
-     exit_val=$?
 
-     if [[ $exit_val = 0 ]]; then
 
-         info_msg "got $http_code from ${URL}"
 
-     fi
 
-     case "$http_code" in
 
-         404|410|423) exit_val=$http_code;;
 
-     esac
 
-     return $exit_val
 
- }
 
- # Apache
 
- # ------
 
- # FIXME: Arch Linux & RHEL should be added
 
- if [[ -z "${APACHE_SITES_AVAILABE}" ]]; then
 
-     APACHE_SITES_AVAILABE="/etc/apache2/sites-available"
 
- fi
 
- apache_is_installed() {
 
-     (command -v apachectl \
 
-         && command -v a2ensite \
 
-         && command -v a2dissite ) &>/dev/null
 
- }
 
- apache_reload() {
 
-     info_msg "reload apache .."
 
-     echo
 
-     sudo -H apachectl configtest
 
-     sudo -H service apache2 force-reload
 
- }
 
- apache_install_site() {
 
-     # usage:  apache_install_site [<template option> ...] <mysite.conf>
 
-     #
 
-     # <template option>:   see install_template
 
-     local template_opts=()
 
-     local pos_args=("$0")
 
-     for i in "$@"; do
 
-         case $i in
 
-             -*) template_opts+=("$i");;
 
-             *)  pos_args+=("$i");;
 
-         esac
 
-     done
 
-     install_template "${template_opts[@]}" \
 
-                      "${APACHE_SITES_AVAILABE}/${pos_args[1]}" \
 
-                      root root 644
 
-     apache_enable_site "${pos_args[1]}"
 
-     info_msg "installed apache site: ${pos_args[1]}"
 
- }
 
- apache_remove_site() {
 
-     # usage:  apache_remove_site <mysite.conf>
 
-     info_msg "remove apache site: $1"
 
-     apache_dissable_site "$1"
 
-     rm -f "${APACHE_SITES_AVAILABE}/$1"
 
- }
 
- apache_enable_site() {
 
-     # usage:  apache_enable_site <mysite.conf>
 
-     info_msg "enable apache site: $1"
 
-     sudo -H a2ensite -q "$1"
 
-     apache_reload
 
- }
 
- apache_dissable_site() {
 
-     # usage:  apache_disable_site <mysite.conf>
 
-     info_msg "disable apache site: $1"
 
-     sudo -H a2dissite -q "$1"
 
-     apache_reload
 
- }
 
- # uWSGI
 
- # -----
 
- uWSGI_SETUP="${uWSGI_SETUP:=/etc/uwsgi}"
 
- uWSGI_restart() {
 
-     # usage:  uWSGI_restart()
 
-     info_msg "restart uWSGI service"
 
-     systemctl restart uwsgi
 
- }
 
- uWSGI_app_available() {
 
-     # usage:  uWSGI_app_available <myapp.ini>
 
-     local CONF="$1"
 
-     if [[ -z $CONF ]]; then
 
-         err_msg "uWSGI_app_available: missing arguments"
 
-         return 42
 
-     fi
 
-     [[ -f "${uWSGI_SETUP}/apps-available/${CONF}" ]]
 
- }
 
- uWSGI_install_app() {
 
-     # usage:  uWSGI_install_app [<template option> ...] <myapp.ini>
 
-     #
 
-     # <template option>:  see install_template
 
-     local pos_args=("$0")
 
-     for i in "$@"; do
 
-         case $i in
 
-             -*) template_opts+=("$i");;
 
-             *)  pos_args+=("$i");;
 
-         esac
 
-     done
 
-     install_template "${template_opts[@]}" \
 
-                      "${uWSGI_SETUP}/apps-available/${pos_args[1]}" \
 
-                      root root 644
 
-     uWSGI_enable_app "${pos_args[1]}"
 
-     uWSGI_restart
 
-     info_msg "installed uWSGI app: ${pos_args[1]}"
 
- }
 
- uWSGI_remove_app() {
 
-     # usage:  uWSGI_remove_app <myapp.ini>
 
-     local CONF="$1"
 
-     info_msg "remove uWSGI app: ${CONF}"
 
-     uWSGI_disable_app "${CONF}"
 
-     uWSGI_restart
 
-     rm -f "${uWSGI_SETUP}/apps-available/${CONF}"
 
- }
 
- uWSGI_app_enabled() {
 
-     # usage:  uWSGI_app_enabled <myapp.ini>
 
-     local CONF="$1"
 
-     if [[ -z $CONF ]]; then
 
-         err_msg "uWSGI_app_enabled: missing arguments"
 
-         return 42
 
-     fi
 
-     [[ -f "${uWSGI_SETUP}/apps-enabled/${CONF}" ]]
 
- }
 
- # shellcheck disable=SC2164
 
- uWSGI_enable_app() {
 
-     # usage:   uWSGI_enable_app <myapp.ini>
 
-     local CONF="$1"
 
-     if [[ -z $CONF ]]; then
 
-         err_msg "uWSGI_enable_app: missing arguments"
 
-         return 42
 
-     fi
 
-     pushd "${uWSGI_SETUP}/apps-enabled" >/dev/null
 
-     rm -f "$CONF"
 
-     # shellcheck disable=SC2226
 
-     ln -s "../apps-available/${CONF}"
 
-     info_msg "enabled uWSGI app: ${CONF} (restart uWSGI required)"
 
-     popd >/dev/null
 
- }
 
- uWSGI_disable_app() {
 
-     # usage:   uWSGI_disable_app <myapp.ini>
 
-     local CONF="$1"
 
-     if [[ -z $CONF ]]; then
 
-         err_msg "uWSGI_enable_app: missing arguments"
 
-         return 42
 
-     fi
 
-     rm -f "${uWSGI_SETUP}/apps-enabled/${CONF}"
 
-     # FIXME: restart uwsgi service won't stop wsgi forked processes of user searx.
 
-     # I had to kill them manually here ...
 
-     pkill -f "${uWSGI_SETUP}/apps-enabled/${CONF}" -9
 
-     info_msg "disabled uWSGI app: ${CONF} (restart uWSGI required)"
 
- }
 
- # distro's package manager
 
- # ------------------------
 
- #
 
- # FIXME: Arch Linux & RHEL should be added
 
- #
 
- pkg_install() {
 
-     # usage: TITEL='install foobar' pkg_install foopkg barpkg
 
-     rst_title "${TITLE:-installation of packages}" section
 
-     echo -en "\npackage(s)::\n\n  $*\n" | $FMT
 
-     if ! ask_yn "Should packages be installed?" Yn 30; then
 
-         return 42
 
-     fi
 
-     # shellcheck disable=SC2068
 
-     apt-get install -y $@
 
- }
 
- pkg_remove() {
 
-     # usage: TITEL='remove foobar' pkg_remove foopkg barpkg
 
-     rst_title "${TITLE:-remove packages}" section
 
-     echo -en "\npackage(s)::\n\n  $*\n" | $FMT
 
-     if ! ask_yn "Should packages be removed (purge)?" Yn 30; then
 
-         return 42
 
-     fi
 
-     apt-get purge --autoremove --ignore-missing -y "$@"
 
- }
 
- pkg_is_installed() {
 
-     # usage: pkg_is_install foopkg || pkg_install foopkg
 
-     dpkg -l "$1" &> /dev/null
 
-     return $?
 
- }
 
- # git tooling
 
- # -----------
 
- # shellcheck disable=SC2164
 
- git_clone() {
 
-     # usage:
 
-     #
 
-     #    git_clone <url> <name> [<branch> [<user>]]
 
-     #    git_clone <url> <path> [<branch> [<user>]]
 
-     #
 
-     #  First form uses $CACHE/<name> as destination folder, second form clones
 
-     #  into <path>.  If repository is allready cloned, pull from <branch> and
 
-     #  update working tree (if needed, the caller has to stash local changes).
 
-     #
 
-     #    git clone https://github.com/asciimoo/searx searx-src origin/master searxlogin
 
-     #
 
-     local url="$1"
 
-     local dest="$2"
 
-     local branch="$3"
 
-     local user="$4"
 
-     local bash_cmd="bash"
 
-     local remote="origin"
 
-     if [[ ! "${dest:0:1}" = "/" ]]; then
 
-         dest="$CACHE/$dest"
 
-     fi
 
-     [[ -z $branch ]] && branch=master
 
-     [[ -z $user ]] && [[ ! -z "${SUDO_USER}" ]] && user="${SUDO_USER}"
 
-     [[ ! -z $user ]] && bash_cmd="sudo -H -u $user -i"
 
-     if [[ -d "${dest}" ]] ; then
 
-         info_msg "already cloned: $dest"
 
- 	tee_stderr 0.1 <<EOF | $bash_cmd 2>&1 |  prefix_stdout "  |$user| "
 
- cd "${dest}"
 
- git checkout -m -B "$branch" --track "$remote/$branch"
 
- git pull --all
 
- EOF
 
-     else
 
-         info_msg "clone into: $dest"
 
- 	tee_stderr 0.1 <<EOF | $bash_cmd 2>&1 |  prefix_stdout "  |$user| "
 
- mkdir -p "$(dirname "$dest")"
 
- cd "$(dirname "$dest")"
 
- git clone --branch "$branch" --origin "$remote" "$url" "$(basename "$dest")"
 
- EOF
 
-     fi
 
- }
 
 
  |