#!/usr/bin/env bash
#
#   Script name: repo-manager
#   Description: Script for managing repository UBLinux
#   GitLab: https://gitlab.ublinux.ru/
#   Author: Dmitry Razumov asmeron@ublinux.ru
#   Contributors: UBLinux Development Team <support@ublinux.ru>
#
#   Copyright (c) 2021-2024 UBLinux <support@ublinux.ru>
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 2 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program.  If not, see <http://www.gnu.org/licenses/>.

VERSION_SCRIPT=1.8

shopt -s extglob

#################################
###   :::   C O L O R S   :::   #
#################################
set_color(){
#http://abload.de/img/bash-color-chartmxjbp.png
    export BBC=$'\e[1;34m'
    export RBC=$'\e[1;31m'
    export WBC=$'\e[1m'
    export EC=$'\e[0m'

    export txtblk='\033[0;30m' # Black - Regular
    export txtred='\033[0;31m' # Red                    # prompt: error color
    export txtgrn='\033[0;32m' # Green                  # prompt: success color
    export txtylw='\033[0;33m' # Yellow                 # prompt: waring color
    export txtblu='\033[0;34m' # Blue                   
    export txtpur='\033[0;35m' # Purple
    export txtcyn='\033[0;36m' # Cyan                   # prompt: info color
    export txtwht='\033[0;37m' # White
    export bldblk='\033[1;30m' # Black - Bold
    export bldred='\033[1;31m' # Red                    # prompt: bold error color
    export bldgrn='\033[1;32m' # Green                  # prompt: bold success color
    export bldylw="\033[1;33m" # Yellow                 # prompt: bold warning color
    export bldblu='\033[1;34m' # Blue                           
    export bldpur='\033[1;35m' # Purple
    export bldcyn="\033[1;36m" # Cyan                   # prompt: bold info color
    export bldwht="\033[1;37m" # White                  # prompt: bold default color

    export undblk='\033[4;30m' # Black - Underline
    export undred='\033[4;31m' # Red

    export bakblk='\033[40m'   # Black - Background
    export bakred='\033[41m'   # Red
    export badgrn='\033[42m'   # Green

    export txtrst='\033[0m'    # Text Reset             # prompt: default color
}

# Check command availability
has_command(){ command -v $1 &> /dev/null; }
    
# echo like ... with flag type and display message colors
prompt(){
    if [[ -z ${QUIET} ]]; then
        case ${1} in
            -s  | --success)      shift; echo -e "${txtgrn}${@}${txtrst}" ;;                            # print success message
            -sq | --success-quit) shift; echo -e "${txtgrn}${@}${txtrst}"; exit 1 ;;                    # print success message
            -e  | --error)        shift; echo -e "${txtred}ERROR:${@}${txtrst}" ;;                      # print error message
            -eq | --error-quit)   shift; echo -e "${txtred}ERROR:${@}${txtrst}"; exit 1 ;;              # print error message
            -w  | --warning)      shift; echo -e "${txtylw}WARNING:${bldwht}${@}${txtrst}" ;;           # print warning message
            -wq | --warning-quit) shift; echo -e "${txtylw}WARNING:${bldwht}${@}${txtrst}"; exit 1 ;;   # print warning message
            -i  | --info)         shift; echo -e "${txtcyn}INFO:${txtcyn}${@}${txtrst}" ;;              # print info message
            -iq | --info-quit)    shift; echo -e "${txtcyn}INFO:${txtcyn}${@}${txtrst}"; exit 1 ;;      # print info message
            *)                    echo -e "$@" ;;                                                       # print all message
        esac
    else
        case ${1} in
            -s  | --success)      true ;;       # print success message
            -sq | --success-quit) exit 1 ;;     # print success message
            -e  | --error)        true ;;       # print error message
            -eq | --error-quit)   exit 1 ;;     # print error message
            -w  | --warning)      true ;;       # print warning message
            -wq | --warning-quit) exit 1 ;;     # print warning message
            -i  | --info)         true ;;       # print info message
            -iq | --info-quit)    exit 1 ;;     # print info message
            *)                    true ;;       # print all message
        esac
    fi
}

usage_version(){
    printf "%s  %s\n" "${0##*/}" "version: ${VERSION_SCRIPT}"
}

usage() {
  cat <<EOF
Usage: ${0##*/} <command> <options...> <package> <packages...>
Version: ${VERSION_SCRIPT}
Manage packages for UBLinux repository

Package Commands:
  create	Create new path repository
  add		Add packages to the repository db
  move		Move packages from repository [a] to repository [b]
  remove        Remove packages from the repository db
  verify	Verify packages from the repository db
  show		Show package from the repository
Meta Commands:
  help          Show this help

Options for all command: 
  -d, --dir=<path>  	  	Path to the repository root
    <path>
   *.	  			Current path, default
  -r, --repo=<name_repo>	Name of the repository to move packages to
    <name_repo>			  
   *ublinux	  		Default name repository
  -a, --arch=<arch>		Package architecture in the repository
   *x86_64 			Architecture x86_64, default
    i386			Architecture i386
    i586			Architecture i586
    arm				Architecture arm
      --nocolor    		Disable color
  -q, --quiet      		Quiet mode
  -h, --help            	Show this help
  -V, --version                 Show package version

Options for add, move, remove command:
  <package>			Package name. Always only the last parameter
    .				Only command: add. If '.' set, then all pakages from current directory *.${EXT_MASK}.* are moved to the repository
    [empty]			Only command: add. If not set, then all pakages from path root repository *.${EXT_MASK}.* are moved to the repository DB
  -e, --ext=<ext>		Package archive extension
    <ext>			Manual package archive extension
   *pkg.tar.zst 		Default package archive extension
  -E, --ext-db=<ext_db>		Database extension, allow: tar | tar.gz | tar.bz2 | *tar.xz | tar.Z
    <ext_db>			Manual database extension
   *tar.xz 			Default database extension
  -S, --sign-repo=<sign>	Signature of the repository builder for the database

Options for verify command:
  <package>			Package name. Always only the last parameter
    .				If '.', then check the repository database signature
    [empty]			If not set, then all pakages from path root repository check the signature

Options for add, move command:
  -o, --only-db			Modify only database, without copy/move package files
  -s, --sign-pkg=<sign>		Signature of the package builder for the database
  -f, --force-replace  		Force to replace the packages, even if it is already in the database

Options for only move command:
  -R, --repo-src=<name_repo>	Name of the repository where the packages will be moved from

Options for only show command:
      --package-db		Show packages only from database
      --package-file		Show packages only from the file system that are not in the database

Examples:
repo-manager add -r ublinux --sign-repo ublinux@mail.com
repo-manager add -d /mnt/repository/2204 -r ublinux --sign-repo ublinux@mail.com --sign-pkg ublinux-package@mail.com
repo-manager add -d /mnt/repository/2204 -r ublinux --sign-repo ublinux@mail.com /tmp/package-1/ 
repo-manager move -d /mnt/repository/2204 -R ublinux-test -r ublinux
repo-manager move -d /mnt/repository/2204 -R ublinux-test -r ublinux pamac-aur libpamac-aur
repo-manager remove -d /mnt/repository/2204 -r ublinux-testing pamac-tray-icon-plasma libpamac-aur-11.3.0-0-x86_64.pkg.tar.zst
repo-manager remove -d /mnt/repository/2204 -r ublinux --sign-repo ublinux@mail.com systemd-250.3-4-x86_64.pkg.tar.zst
repo-manager remove -d /mnt/repository/2204 -r ublinux --sign-repo ublinux@mail.com systemd-resolvconf systemd-sysvcompat
repo-manager verify -d /mnt/repository/2204 -r ublinux pamac-tray-icon-plasma libpamac-aur-11.3.0-0-x86_64.pkg.tar.zst
repo-manager show -d /mnt/repository/2204 -r ublinux 
EOF
exit 0
}

arguments() {
# Pre-process options to:
# - expand -xyz into -x -y -z
# - expand --longopt=arg into --longopt arg
    local ARGV=()
    local END_OF_OPT=
    while [[ $# -gt 0 ]]; do
	arg="$1"; shift
	case "${END_OF_OPT}${arg}" in
	    -p) 	ARGV+=("${arg}"); END_OF_OPT=1 ;;
	    --) 	ARGV+=("${arg}"); END_OF_OPT=1 ;;
	    --*=*)	ARGV+=("${arg%%=*}" "${arg#*=}") ;;
	    --*) 	ARGV+=("${arg}") ;;
	    -*) 	for i in $(seq 2 ${#arg}); do ARGV+=("-${arg:i-1:1}"); done ;;
	    *)		ARGV+=("${arg}") ;;
	esac
    done
    # Apply pre-processed options
    set -- "${ARGV[@]}"
    # Parse options
    local END_OF_OPT=
    local POSITIONAL_ARGS=()
    [[ -z $@ ]] && usage && exit 0
    while [[ $# -gt 0 ]]; do
	case "${END_OF_OPT}${1}" in
	    create)    		  COMMAND="create" ;;
	    add)      		  COMMAND="add" ;;
	    move)      		  COMMAND="move" ;;
	    remove)    		  COMMAND="remove" ;;
	    verify)    		  COMMAND="verify" ;;
	    show)    		  COMMAND="show" ;;
	    -r | --repo)	  shift; REPO="$1" ;;
	    -R | --repo-src)	  shift; REPO_SRC="$1" ;;
	    -d | --dir)	 	  shift; PATH_ROOT_REPO="$1" ;;
	    -a | --arch)	  shift; ARCH="$1" ;;
	    -e | --ext)    	  shift; EXT="$1" ;;
	    -E | --ext-db)	  shift; EXT_DB="$1" ;;
	    -s | --sign-pkg) 	  shift; SIGN_PKG="$1" ;;
	    -S | --sign-repo) 	  shift; SIGN_REPO="--sign --key $1" ;;
	    -f | --force-replace) unset ONLYNEW ;;
	    -o | --only-db) 	  ONLY_DB=yes ;;
	    -p | --packages)      END_OF_OPT=1 ;;
	         --package-db)    SHOW_PACKAGE_DB=yes ;;
	         --package-file)  SHOW_PACKAGE_FILE=yes ;;
            -q | --quiet)         QUIET="--quiet"; QUIET_SYSTEMCTL="--quiet"; QUIET_ARG="-q" ;;
                 --nocolor)       NOCOLOR="--nocolor" ;;
 	    -V | --version)	  usage_version; exit 0 ;;
	    -h | --help | help)	  usage ;;
	    --stdin)        	  READ_STDIN=1 ;;
	    --)             	  END_OF_OPT=1 ;;
	    -*|--*)         	  prompt -w "Unrecognized argument, skiped: $1" >&2  ;;
	    *)              	  POSITIONAL_ARGS+=("$1") ;;
	esac
	shift
    done
# Restore positional parameters
    set -- "${POSITIONAL_ARGS[@]}"
    PACKAGES="$@"
    PACKAGES=${PACKAGES//,/ }
    [[ -z ${COMMAND} && -z ${PATH_ROOT_REPO} ]] && usage
    [[ -n ${SIGN_REPO} ]] || VERIFY="--verify"
    [[ -z ${SHOW_PACKAGE_DB} && -z ${SHOW_PACKAGE_FILE} ]] && SHOW_PACKAGE_DB=yes && SHOW_PACKAGE_FILE=yes
}

realpath_packages_list(){
# Пробежаться по указанным файлам, если каталог, то из него выбрать все пакеты, если просто файл, то добавить реальный путь до файла
    local ARG_PACKAGES=$@
    # Проверяем на наличие каталогов
    local PACKAGES_LOCAL=
    for PACKAGE_FILE in ${ARG_PACKAGES}; do
	local SELECT_PACKAGE=
	if [[ -d ${PACKAGE_FILE} ]]; then
	# Если каталог
	    #SELECT_PACKAGE="$(ls -1 ${PACKAGE_FILE}/*.${EXT_MASK}.*[!sig] | xargs realpath 2>/dev/null) "
	    SELECT_PACKAGE=$(ls -1vr ${PACKAGE_FILE}/*.${EXT_MASK}.*[!sig] 2>/dev/null | sed -En 's/.*\/((.*)-([^-]+)-([^-]+)-[^-]+\.pkg\.tar\.[[:alnum:]]+)/\2|\1/p' | awk -F '|' '!prefixes[$1]++ {print $2}') #'
	else
	    SELECT_PACKAGE=${PACKAGE_FILE}
	fi
	[[ ${SELECT_PACKAGE} != "" ]] && PACKAGES_LOCAL+="${SELECT_PACKAGE}"$'\n' || prompt -w "Not found the package: ${SELECT_PACKAGE}"
    done
    ARG_PACKAGES="${PACKAGES_LOCAL}"
    # Проверяем файлы
    local PACKAGES_LOCAL=
    for PACKAGE_FILE in ${ARG_PACKAGES}; do
	local SELECT_PACKAGE=
	if [[ -L ${PACKAGE_FILE} ]]; then 
	# Если симлинк существуют
	    # Проверка на битую ссылку вместо пакета
	    readlink -qe ${PACKAGE_FILE} &>/dev/null || prompt -e "Package file a broken symlink: ${PACKAGE_FILE}"
	    [[ -e ${PACKAGE_FILE} ]] && SELECT_PACKAGE="${PACKAGE_FILE}" || prompt -e "Package file not exist: $(realpath ${PACKAGE_FILE})"
	elif [[ -e ${PACKAGE_FILE} ]]; then 
	# Если файл существуют
	    SELECT_PACKAGE=${PACKAGE_FILE}
	else
	# Если часть файл найдена
	    SELECT_PACKAGE=$(ls -1vr ./${PACKAGE_FILE}*.${EXT_MASK}.*[!sig] 2>/dev/null | sed -En 's/.*\/((.*)-([^-]+)-([^-]+)-[^-]+\.pkg\.tar\.[[:alnum:]]+)/\2|\1/p' | awk -F '|' '!prefixes[$1]++ {print $2}') #'
	fi
	[[ ${SELECT_PACKAGE} != "" ]] && PACKAGES_LOCAL+="${SELECT_PACKAGE}"$'\n' || prompt -w "Not found the package: ${PACKAGE_FILE}"
    done
    [[ ${PACKAGES_LOCAL} != @(""|" ") ]] && PACKAGES=${PACKAGES_LOCAL} || { unset PACKAGES; prompt -wq "There are no select packages!"; }
}

move_to_repo() {
# Копируем файлы в pool хранилища и симлинки в указанный репозиторий
    [[ -n $@ ]] || return 1
    local PACKAGES=$@
    PACKAGES_REPO=
    for PACKAGE_FILE in ${PACKAGES}; do
	if [[ -z ${ONLY_DB} ]]; then
	    # Проверка на наличие пакета в пуле и его копирование
    	    if [[ -z ${ONLYNEW} || ! -e ${PATH_ROOT_REPO}/pool/overlay/${PACKAGE_FILE##*/} ]]; then
    		#prompt -i "Copy packages to the pool : ${PACKAGE_FILE##*/}"
    		[[ -e ${PACKAGE_FILE} ]] && cp -f "${PACKAGE_FILE}" -t "${PATH_ROOT_REPO}/pool/overlay/" || prompt -i "Package is not a file: ${PACKAGE_FILE##*/}"
    		[[ -e ${PACKAGE_FILE}.sig ]] && cp -f "${PACKAGE_FILE}.sig" -t "${PATH_ROOT_REPO}/pool/overlay/" || rm -f "${PATH_ROOT_REPO}/pool/overlay/${PACKAGE_FILE##*/}.sig"
	    else 
		prompt -i "Package already exists in the pool, skip copying the package: ${PACKAGE_FILE##*/}"
	    fi
	    # Проверка на наличие правильного симлинка в репозитории на пакет в пуле и его создание
    	    if [[ -z ${ONLYNEW} || $(realpath ${PATH_ROOT_REPO}/pool/overlay)/${PACKAGE_FILE##*/} != $(realpath ${PATH_DB_REPO}/${PACKAGE_FILE##*/}) ]]; then
    		#prompt -i "Make a symlink to the repository for the package : ${PACKAGE_FILE##*/}"
		rm -f "${PATH_DB_REPO}/${PACKAGE_FILE##*/}"
		[[ -e ${PATH_ROOT_REPO}/pool/overlay/${PACKAGE_FILE##*/} ]] && ln -fsr "${PATH_ROOT_REPO}/pool/overlay/${PACKAGE_FILE##*/}" "${PATH_DB_REPO}/${PACKAGE_FILE##*/}"
		[[ -e ${PATH_ROOT_REPO}/pool/overlay/${PACKAGE_FILE##*/}.sig ]] && ln -fsr "${PATH_ROOT_REPO}/pool/overlay/${PACKAGE_FILE##*/}.sig" "${PATH_DB_REPO}/${PACKAGE_FILE##*/}.sig" \
		|| rm -f "${PATH_DB_REPO}/${PACKAGE_FILE##*/}.sig"
	    else 
		prompt -i "Package symlink allready exist in repository, skip the package : ${PACKAGE_FILE##*/}"
	    fi
	    # Проверка на наличие подписи пакета в пуле и в репозитории и её создание	
	    if [[ -n ${SIGN_PKG} ]]; then
		[[ -e ${PATH_ROOT_REPO}/pool/overlay/${PACKAGE_FILE##*/}.sig ]] && rm -f "${PATH_ROOT_REPO}/pool/overlay/${PACKAGE_FILE##*/}.sig"
		[[ ! -e ${PATH_ROOT_REPO}/pool/overlay/${PACKAGE_FILE##*/}.sig ]] && sign_package "${PATH_ROOT_REPO}/pool/overlay/${PACKAGE_FILE##*/}"
		[[ -e ${PATH_DB_REPO}/${PACKAGE_FILE##*/}.sig ]] && rm -f "${PATH_DB_REPO}/${PACKAGE_FILE##*/}.sig"
		[[ ! -e ${PATH_DB_REPO}/${PACKAGE_FILE##*/}.sig ]] && ln -fsr "${PATH_ROOT_REPO}/pool/overlay/${PACKAGE_FILE##*/}.sig" "${PATH_DB_REPO}/${PACKAGE_FILE##*/}.sig"
	    fi
	fi
	PACKAGES_REPO+="${PATH_DB_REPO}/${PACKAGE_FILE##*/} "
    done
}

trim_name_pkg() {
# В списке пакетов убрать из имён служебную информацию, оставить только имена
    [[ -n $@ ]] || return 1
    local PACKAGES_LOCAL=$@
    local TRIM_PACKAGES=
    for PACKAGE_FILE in ${PACKAGES_LOCAL}; do
    	[[ ${PACKAGE_FILE} =~ ${EXT_MASK} ]] && TRIM_PACKAGES+="${PACKAGE_FILE%-*-*-*.${EXT_MASK}.*}"$'\n' || TRIM_PACKAGES+="${PACKAGE_FILE} "
    done
    PACKAGES_SHORT=${TRIM_PACKAGES}
}

sign_package() {
    local FILE_PKG=$1
    if [[ -f ${FILE_PKG} ]]; then
	# touch -amht '198101010000' systemd-250.3-4-x86_64.pkg.tar.zst
	gpg --detach-sign --local-user ${SIGN_PKG} "${FILE_PKG}"
	touch -am -r "${FILE_PKG}" "${FILE_PKG}.sig"
    else
	prompt -e "Provide a package for signed and try again."
    fi
}

verify_sign_package(){
    local FILE_PKG=$1
    if [[ -e ${FILE_PKG} ]]; then
	gpg --verify "${FILE_PKG}".sig "${FILE_PKG}"
    else
	prompt -e "Provide a package for signed and try again."
    fi
}

show_repo_packages(){
    TAR_OPT="tf"
    FILE_DB=$(realpath ${PATH_DB_REPO}/${REPO}.db)
    if [[ ${FILE_DB} =~ .gz$ ]]; then TAR_OPT+="z"
    elif [[ ${FILE_DB} =~ .bz2$ ]]; then TAR_OPT+="j"
    elif [[ ${FILE_DB} =~ .xz$ ]]; then TAR_OPT+="J"
    elif [[ ${FILE_DB} =~ .Z$ ]]; then TAR_OPT+="Z"
    fi
    PACKAGES_DB=$(tar ${TAR_OPT} ${FILE_DB} 2>/dev/null | sed -En 's/([^\/]+)\/.*/\1/p' | sort -Vu) #'
    PACKAGES_FILE=$(ls -1vr ${PATH_DB_REPO}/*.${EXT_MASK}.*[!sig] 2>/dev/null | sed -En 's/.*\/((.*)-([^-]+)-([^-]+)-[^-]+\.pkg\.tar\.[[:alnum:]]+)/\2|\1/p' | awk -F '|' '!prefixes[$1]++ {print $2}') #'
    local TEXT_LIST=
    local TEXT_LIST_DB=
    local TEXT_LIST_NOFILE=
    local TEXT_LIST_FILE=
    [[ -n ${SHOW_PACKAGE_DB} ]] && for SELECT_PACKAGE_DB in ${PACKAGES_DB}; do
	if [[ ${PACKAGES_FILE} =~ ($'\n'|^)+("${SELECT_PACKAGE_DB}"-[^-$'\n']+'.'"${EXT_MASK}"'.'[^-$'\n']+)($'\n'|$)+ ]]; then
	    TEXT_LIST_DB+="${SELECT_PACKAGE_DB%-*-*}|${BASH_REMATCH[2]}"$'\n'
	else
	    TEXT_LIST_NOFILE+="${SELECT_PACKAGE_DB%-*-*}|-"$'\n'
	fi
    done
    [[ -n ${SHOW_PACKAGE_FILE} ]] && for SELECT_PACKAGE_FILE in ${PACKAGES_FILE}; do
	if [[ ${PACKAGES_DB} =~ ($'\n'|^)+"${SELECT_PACKAGE_FILE%-*}"($'\n'|$)+ ]]; then
	    true
	else
	    TEXT_LIST_FILE+="-|${SELECT_PACKAGE_FILE}"$'\n'
	fi
    done
    TEXT_LIST=${TEXT_LIST_FILE}$'\n'${TEXT_LIST_NOFILE}$'\n'${TEXT_LIST_DB}
    local COLUMN_OPT=
    [[ -n ${QUIET} ]] && COLUMN_OPT="--table-noheadings"
    column ${COLUMN_OPT} --separator '|' --table --table-columns "PACKAGE NAME","PACKAGE FILE" --table-order "PACKAGE NAME" <<< "${TEXT_LIST}"
}


  #################
 ####	MAIN  ####
#################


    PKGNAME=${0##*/}
    PATH_WORK=${PWD}
    # PACKAGES хранить полные имена файлов пакетов, каталогов или короткие если явно указано в командной строке
    PACKAGES=
    # PACKAGES_REPO хранит полные пути с именами файлов пакетов из всех каталогов и файлов указанных в командной строке
    PACKAGES_REPO=
    # PACKAGES_SHORT хранит имена пакетов без суфиксов и расширений
    PACKAGES_SHORT=
    SIGN_REPO=
    SIGN_PKG=
    PATH_ROOT_REPO="."
    ARCH="x86_64"
    # Allow DB extension: tar | tar.gz | tar.bz2 | tar.xz | tar.Z
    EXT_DB="tar.xz"
    EXT_MASK="pkg.tar"
    EXT="pkg.tar.zst"
    REPO="ublinux"
    # if null ${ONLYNEW} then reset and new DB
    ONLYNEW="--new"

    REQUEST_ARGS=()
    arguments "$@"
    set -- "${REQUEST_ARGS[@]}"

    [[ -n ${NOCOLOR} ]] || set_color
    PATH_DB_REPO="${PATH_ROOT_REPO}/${REPO}/${ARCH}"
    PATH_DB_REPO=${PATH_DB_REPO//\/\//\/}
    [[ ! -d ${PATH_DB_REPO} ]] && prompt -w "Path to the repository root not exist (arg: -d, --dir), created ./ !" && mkdir -p ${PATH_DB_REPO} ${PATH_ROOT_REPO}/pool/overlay/

    if [[ ${COMMAND} == "create" ]]; then
	[[ -n ${REPO} ]] && mkdir -p ${PATH_ROOT_REPO}/${REPO}
    elif [[ ${COMMAND} == "add" ]]; then
	if [[ ${PACKAGES} == "." ]]; then 
	# Если в имени пакета указана "." , то включить все пакеты текущей папки
	    true
	elif [[ -z ${PACKAGES} ]]; then 
	# Если не указаны пакеты, то добавить в базу все новые пакеты из каталога репозитория
	    PACKAGES=${PATH_DB_REPO}
	    cd ${PATH_DB_REPO}
	fi
	realpath_packages_list "${PACKAGES}"
	prompt -i "Add assigned packages to '${REPO}' repository:\n   ${PACKAGES//$'\n'/$'\n'   }"
	move_to_repo ${PACKAGES}
	if [[ ${PACKAGES_REPO} != "" ]]; then
	    [[ -z ${SIGN_REPO} ]] && rm -f ${PATH_DB_REPO}/${REPO}.{db,files}{,.tar.*}.sig
	    repo-add ${QUIET} ${VERIFY} ${ONLYNEW} --prevent-downgrade ${SIGN_REPO} ${PATH_DB_REPO}/${REPO}.db.${EXT_DB} ${PACKAGES_REPO}
	else
	    prompt -wq "No packages selected !"
	fi
    elif [[ ${COMMAND} == "move" ]]; then
	[[ -z ${REPO_SRC} ]] && prompt -wq "The source repository is not set!"
	PATH_DB_REPO_SRC="${PATH_ROOT_REPO}/${REPO_SRC}/${ARCH}"
	if [[ ${PACKAGES} == "." ]]; then 
	    true
	elif [[ -z ${PACKAGES} ]]; then 
	    PACKAGES="${PATH_DB_REPO_SRC}"
	else
	    true
	fi
	# Переместить пакеты в новый репозиторий
	cd "${PATH_DB_REPO_SRC}"
	realpath_packages_list "${PACKAGES}"
	prompt -i "Add assigned packages to '${REPO}' repository:\n   ${PACKAGES//$'\n'/$'\n'   }"
	[[ -z ${ONLY_DB} ]] && for PACKAGE_FILE in ${PACKAGES}; do
	    [[ -e ${PATH_DB_REPO_SRC}/${PACKAGE_FILE} ]] && mv -f -t "${PATH_DB_REPO}" "${PATH_DB_REPO_SRC}/${PACKAGE_FILE}"
	    [[ -e ${PATH_DB_REPO_SRC}/${PACKAGE_FILE}.sig ]] && mv -f -t "${PATH_DB_REPO}" "${PATH_DB_REPO_SRC}/${PACKAGE_FILE}.sig"
	done
	# Добавить пакеты в новый репозиторий
	cd ${PATH_DB_REPO}
	repo-add ${QUIET} ${VERIFY} ${ONLYNEW} --prevent-downgrade ${SIGN_REPO} ${PATH_DB_REPO}/${REPO}.db.${EXT_DB} ${PACKAGES}
	# Удалить пакет из исходного репозитория
	cd "${PATH_DB_REPO_SRC}"
	trim_name_pkg ${PACKAGES}
	prompt -i "Remove packages from current db '${PATH_DB_REPO_SRC}/':\n   ${PACKAGES_SHORT//$'\n'/$'\n'   }"
	repo-remove ${QUIET} ${VERIFY} ${SIGN_REPO} ${PATH_DB_REPO_SRC}/${REPO_SRC}.db.${EXT_DB} ${PACKAGES_SHORT}
    elif [[ ${COMMAND} == "remove" ]]; then
	if [[ ${PACKAGES} == "." ]]; then 
	    true
	elif [[ -z ${PACKAGES} ]]; then 
	    PACKAGES="${PATH_DB_REPO}"
	fi
	realpath_packages_list "${PACKAGES}"
	trim_name_pkg ${PACKAGES}
	prompt -i "Remove packages from repository '${PATH_DB_REPO}/':\n   ${PACKAGES_SHORT//$'\n'/$'\n'   }"
	if [[ ${PACKAGES_SHORT} != "" ]]; then
	    repo-remove ${QUIET} ${VERIFY} ${SIGN_REPO} ${PATH_DB_REPO}/${REPO}.db.${EXT_DB} ${PACKAGES_SHORT}; STATUS=$?
	    [[ ${STATUS} -eq 0 ]] && [[ -z ${ONLY_DB} ]] && for PKG_SHORTNAME in ${PACKAGES_SHORT}; do
    		rm -f ${PATH_DB_REPO}/${PKG_SHORTNAME}-*-*-*.${EXT_MASK}.*
	    done
	    [[ ${STATUS} -eq 0 ]] && [[ -z ${SIGN_REPO} ]] && rm -f ${PATH_DB_REPO}/${REPO}.{db,files}{,.tar.*}.sig
	else
	    prompt -wq "No packages selected !"
	fi
    elif [[ ${COMMAND} == "verify" ]]; then
	if [[ ${PACKAGES} == "." ]]; then
	# Проверить подпись базы данных
	    prompt -i "Verify sign database '${PATH_DB_REPO}/' repository"
	    PACKAGES=$(ls -1vr ${PATH_DB_REPO}/${REPO}.db.tar.*[!(.sig|.old)] ${PATH_DB_REPO}/${REPO}.files.tar.*[!(.sig|.old)] 2>/dev/null | sed -En 's/.*\/(.*)/\1/p')
	    [[ ${PACKAGES} == @(""|".")  ]] && prompt -eq "Files '${REPO}.db.tar.*' and '${REPO}.files.tar.*' from '${PATH_DB_REPO}/' repository not found !"
	elif [[ -z ${PACKAGES} ]]; then
	# Проверить подпись всех пакетов хранящихся в указанном репозитории 
	    PACKAGES="${PATH_DB_REPO}"
	    realpath_packages_list ${PACKAGES}
	else
	# Проверить перечень пакетов и/или каталогов с пакетами и/или части имени пакета (если не найден)
	    cd "${PATH_DB_REPO}"
	    realpath_packages_list ${PACKAGES}
	fi
	prompt -i "Verify sign files from repository '${PATH_DB_REPO}/':\n   ${PACKAGES//$'\n'/$'\n'   }"
        for PKG_NAME in ${PACKAGES}; do
    	    prompt -i "Verify sign file: ${PKG_NAME}"
    	    verify_sign_package "${PATH_DB_REPO}/${PKG_NAME}"
	done
    elif [[ ${COMMAND} == "show" ]]; then
	show_repo_packages
    else
	usage
    fi
