531 lines
19 KiB
Bash
Executable File
531 lines
19 KiB
Bash
Executable File
#!/bin/sh
|
||
# calista-manager - Менеджер компонентов Calista OS
|
||
|
||
# Конфигурация
|
||
SYSTEM_DIR="/calista"
|
||
REGISTRY_FILE="$SYSTEM_DIR/registry.db"
|
||
GPROXY_SCRIPT="/usr/local/bin/gproxy" # Путь к gproxy скрипту
|
||
GPROXY_CACHE=/calista/cache/gproxy/
|
||
|
||
# Цвета
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m' # No Color
|
||
|
||
# Логирование
|
||
log() {
|
||
echo -e "${GREEN}[+]${NC} $1"
|
||
}
|
||
|
||
error() {
|
||
echo -e "${RED}[!]${NC} $1" >&2
|
||
}
|
||
|
||
warn() {
|
||
echo -e "${YELLOW}[*]${NC} $1"
|
||
}
|
||
|
||
info() {
|
||
echo -e "${BLUE}[i]${NC} $1"
|
||
}
|
||
|
||
# Запись в лог реестра
|
||
log_to_registry() {
|
||
TYPE="$1"
|
||
USER="${SUDO_USER:-$USER}"
|
||
DETAILS="$2"
|
||
|
||
sqlite3 "$REGISTRY_FILE" "INSERT INTO calista_log (type, user, details) VALUES ('$TYPE', '$USER', '$DETAILS');" 2>/dev/null
|
||
}
|
||
|
||
# Проверка инициализации реестра
|
||
check_init() {
|
||
if [ ! -f "$REGISTRY_FILE" ]; then
|
||
error "Реестр не найден: $REGISTRY_FILE"
|
||
error "Сначала инициализируйте реестр Calista"
|
||
exit 1
|
||
fi
|
||
|
||
if [ ! -x "$GPROXY_SCRIPT" ]; then
|
||
error "Не найден gproxy скрипт: $GPROXY_SCRIPT"
|
||
error "Поместите calista-proxy.sh в текущий каталог"
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
# Проверка наличия компонента в реестре
|
||
is_installed() {
|
||
COMP_ID="$1"
|
||
RESULT=$(sqlite3 "$REGISTRY_FILE" "SELECT COUNT(*) FROM components WHERE name = '$COMP_ID';" 2>/dev/null)
|
||
[ "$RESULT" -gt 0 ] 2>/dev/null
|
||
}
|
||
|
||
# Добавление компонента в реестр
|
||
add_to_registry() {
|
||
COMP_ID="$1"
|
||
VERSION="$2"
|
||
SOURCE="$3"
|
||
DESCRIPTION="$4"
|
||
INSTALLED_AT=$(date '+%Y-%m-%d %H:%M:%S')
|
||
|
||
# Проверяем, существует ли уже компонент
|
||
EXISTS=$(sqlite3 "$REGISTRY_FILE" "SELECT COUNT(*) FROM components WHERE name = '$COMP_ID';" 2>/dev/null)
|
||
|
||
if [ "$EXISTS" -gt 0 ] 2>/dev/null; then
|
||
# Обновляем существующий компонент
|
||
sqlite3 "$REGISTRY_FILE" "UPDATE components SET
|
||
version = '$VERSION',
|
||
source = '$SOURCE',
|
||
description = '$DESCRIPTION',
|
||
installed_at = '$INSTALLED_AT'
|
||
WHERE name = '$COMP_ID';" 2>/dev/null
|
||
|
||
log_to_registry "info" "Компонент $COMP_ID обновлен до версии $VERSION"
|
||
info "Компонент '$COMP_ID' обновлен в реестре"
|
||
else
|
||
# Добавляем новый компонент
|
||
sqlite3 "$REGISTRY_FILE" "INSERT INTO components (name, version, source, description, installed_at)
|
||
VALUES ('$COMP_ID', '$VERSION', '$SOURCE', '$DESCRIPTION', '$INSTALLED_AT');" 2>/dev/null
|
||
|
||
log_to_registry "info" "Компонент $COMP_ID версии $VERSION установлен"
|
||
info "Компонент '$COMP_ID' добавлен в реестр"
|
||
fi
|
||
}
|
||
|
||
# Удаление компонента из реестра
|
||
remove_from_registry() {
|
||
COMP_ID="$1"
|
||
|
||
sqlite3 "$REGISTRY_FILE" "DELETE FROM components WHERE name = '$COMP_ID';" 2>/dev/null
|
||
log_to_registry "info" "Компонент $COMP_ID удален из реестра"
|
||
}
|
||
|
||
# Получение информации о компоненте из gproxy
|
||
get_component_info() {
|
||
COMP_ID="$1"
|
||
VERSION="$2"
|
||
|
||
# Получаем компонент через gproxy
|
||
if [ "$VERSION" = "latest" ]; then
|
||
"$GPROXY_SCRIPT" get "$COMP_ID"
|
||
else
|
||
"$GPROXY_SCRIPT" get "$COMP_ID" "$VERSION"
|
||
fi
|
||
}
|
||
|
||
# Установка из Git
|
||
install_from_git() {
|
||
COMP_ID="$1"
|
||
VERSION="$2"
|
||
|
||
log "Установка компонента '$COMP_ID' версии '$VERSION' из Git"
|
||
|
||
# Проверяем не установлен ли уже
|
||
if is_installed "$COMP_ID"; then
|
||
warn "Компонент '$COMP_ID' уже установлен"
|
||
# Получаем текущую версию
|
||
CURRENT_VERSION=$(sqlite3 "$REGISTRY_FILE" "SELECT version FROM components WHERE name = '$COMP_ID';" 2>/dev/null)
|
||
info "Текущая версия: $CURRENT_VERSION"
|
||
echo "Переустановить? (y/N): "
|
||
read -r answer
|
||
if [ "$answer" != "y" ] && [ "$answer" != "Y" ]; then
|
||
echo "Установка отменена"
|
||
return 1
|
||
fi
|
||
fi
|
||
|
||
# Получаем компонент через gproxy
|
||
info "Загрузка компонента через gproxy..."
|
||
gproxy set-repo ssh://git@gitlab.svsptech.ru:5598/svsptech/calista-components.git
|
||
OUTPUT=$(get_component_info "$COMP_ID" "$VERSION")
|
||
|
||
if echo "$OUTPUT" | grep -q "склонирован в:"; then
|
||
# Извлекаем путь из вывода gproxy
|
||
REPO_PATH="$GPROXY_CACHE$COMP_ID"
|
||
|
||
if [ -d "$REPO_PATH" ]; then
|
||
log "Компонент загружен в: $REPO_PATH"
|
||
|
||
# Ищем файл build
|
||
if [ -x "$REPO_PATH/build" ]; then
|
||
info "Запуск скрипта сборки..."
|
||
cd "$REPO_PATH"
|
||
if ./build; then
|
||
log "Сборка завершена успешно"
|
||
|
||
# Получаем описание компонента
|
||
DESC="Компонент $COMP_ID"
|
||
if [ -f "README.md" ]; then
|
||
DESC=$(head -1 "README.md" 2>/dev/null | cut -c -100)
|
||
elif [ -f "description.txt" ]; then
|
||
DESC=$(head -1 "description.txt" 2>/dev/null | cut -c -100)
|
||
fi
|
||
|
||
# Экранируем кавычки для SQL
|
||
DESC=$(echo "$DESC" | sed "s/'/''/g")
|
||
|
||
# Добавляем в реестр
|
||
add_to_registry "$COMP_ID" "$VERSION" "git" "$DESC"
|
||
|
||
# Очищаем кэш gproxy
|
||
info "Очистка кэша gproxy..."
|
||
"$GPROXY_SCRIPT" clean
|
||
|
||
log "Компонент '$COMP_ID' успешно установлен"
|
||
else
|
||
error "Ошибка сборки компонента"
|
||
log_to_registry "error" "Ошибка сборки компонента $COMP_ID"
|
||
cd - >/dev/null
|
||
return 1
|
||
fi
|
||
cd - >/dev/null
|
||
else
|
||
warn "Файл build не найден или не исполняемый"
|
||
info "Попытка найти альтернативные скрипты..."
|
||
|
||
# Проверяем другие возможные скрипты
|
||
INSTALLED=false
|
||
for script in install.sh setup.sh configure.sh; do
|
||
if [ -x "$REPO_PATH/$script" ]; then
|
||
info "Найден скрипт: $script"
|
||
cd "$REPO_PATH"
|
||
if ./"$script"; then
|
||
log "Установка завершена успешно"
|
||
|
||
# Получаем описание
|
||
DESC="Компонент $COMP_ID"
|
||
if [ -f "README.md" ]; then
|
||
DESC=$(head -1 "README.md" 2>/dev/null | cut -c -100)
|
||
fi
|
||
|
||
# Экранируем кавычки для SQL
|
||
DESC=$(echo "$DESC" | sed "s/'/''/g")
|
||
|
||
add_to_registry "$COMP_ID" "$VERSION" "git" "$DESC"
|
||
"$GPROXY_SCRIPT" clean
|
||
log "Компонент '$COMP_ID' успешно установлен"
|
||
INSTALLED=true
|
||
cd - >/dev/null
|
||
break
|
||
fi
|
||
cd - >/dev/null
|
||
fi
|
||
done
|
||
|
||
if [ "$INSTALLED" = false ]; then
|
||
error "Не найден скрипт установки"
|
||
return 1
|
||
fi
|
||
fi
|
||
else
|
||
error "Не удалось определить путь к загруженному компоненту"
|
||
log_to_registry "error" "Не удалось определить путь к компоненту $COMP_ID"
|
||
return 1
|
||
fi
|
||
else
|
||
error "Не удалось загрузить компонент через gproxy"
|
||
echo "Вывод gproxy: $OUTPUT"
|
||
log_to_registry "error" "Не удалось загрузить компонент $COMP_ID через gproxy"
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# Установка локального компонента (заглушка)
|
||
install_local() {
|
||
COMP_ID="$1"
|
||
VERSION="$2"
|
||
|
||
warn "Локальная установка компонентов пока не реализована"
|
||
echo "Идентификатор: $COMP_ID"
|
||
echo "Версия: $VERSION"
|
||
echo "Функционал в разработке..."
|
||
return 1
|
||
}
|
||
|
||
# Команда установки
|
||
cmd_install() {
|
||
if [ -z "$1" ]; then
|
||
echo "Использование: $0 install <component-id> [version] [source]" >&2
|
||
echo " source: git (по умолчанию) или local" >&2
|
||
echo " version: номер версии или 'latest' (по умолчанию)" >&2
|
||
exit 1
|
||
fi
|
||
|
||
check_init
|
||
|
||
COMP_ID="$1"
|
||
VERSION="${2:-latest}"
|
||
SOURCE="${3:-git}"
|
||
|
||
case "$SOURCE" in
|
||
git)
|
||
install_from_git "$COMP_ID" "$VERSION"
|
||
;;
|
||
local)
|
||
install_local "$COMP_ID" "$VERSION"
|
||
;;
|
||
*)
|
||
error "Неизвестный источник: $SOURCE"
|
||
echo "Допустимые значения: git, local" >&2
|
||
exit 1
|
||
;;
|
||
esac
|
||
}
|
||
|
||
# Команда списка установленных компонентов
|
||
cmd_list() {
|
||
check_init
|
||
|
||
# Проверяем количество компонентов
|
||
COUNT=$(sqlite3 "$REGISTRY_FILE" "SELECT COUNT(*) FROM components;" 2>/dev/null)
|
||
|
||
if [ "$COUNT" -eq 0 ] 2>/dev/null; then
|
||
echo "Нет установленных компонентов"
|
||
return 0
|
||
fi
|
||
|
||
echo "Установленные компоненты:"
|
||
echo "========================="
|
||
echo ""
|
||
|
||
# Получаем и выводим список компонентов
|
||
sqlite3 "$REGISTRY_FILE" "SELECT name, version, source, description, installed_at FROM components ORDER BY name;" 2>/dev/null | while IFS='|' read -r id version source desc installed; do
|
||
if [ -n "$id" ]; then
|
||
echo "Компонент: $id"
|
||
echo " Версия: ${version:-не указана}"
|
||
echo " Описание: ${desc:-нет описания}"
|
||
echo " Источник: ${source:-не указан}"
|
||
echo " Установлен: ${installed:-неизвестно}"
|
||
echo ""
|
||
fi
|
||
done
|
||
|
||
echo "Всего компонентов: $COUNT"
|
||
}
|
||
|
||
# Команда информации о компоненте
|
||
cmd_info() {
|
||
if [ -z "$1" ]; then
|
||
echo "Использование: $0 info <component-id>" >&2
|
||
exit 1
|
||
fi
|
||
|
||
check_init
|
||
COMP_ID="$1"
|
||
|
||
if is_installed "$COMP_ID"; then
|
||
echo "Информация о компоненте: $COMP_ID"
|
||
echo "================================"
|
||
|
||
# Получаем информацию из реестра
|
||
sqlite3 "$REGISTRY_FILE" "SELECT name, version, source, description, installed_at FROM components WHERE name = '$COMP_ID';" 2>/dev/null | while IFS='|' read -r id version source desc installed; do
|
||
echo "Идентификатор: $id"
|
||
echo "Версия: ${version:-не указана}"
|
||
echo "Описание: ${desc:-нет описания}"
|
||
echo "Источник: ${source:-не указан}"
|
||
echo "Дата установки: ${installed:-неизвестно}"
|
||
done
|
||
else
|
||
echo "Компонент '$COMP_ID' не установлен"
|
||
|
||
# Предлагаем установить
|
||
echo ""
|
||
info "Для установки компонента используйте:"
|
||
echo " $0 install $COMP_ID"
|
||
fi
|
||
}
|
||
|
||
# Команда обновления списка компонентов
|
||
cmd_update() {
|
||
check_init
|
||
log "Обновление списка компонентов через gproxy..."
|
||
"$GPROXY_SCRIPT" update
|
||
log_to_registry "info" "Список компонентов обновлен через gproxy"
|
||
}
|
||
|
||
# Команда показа версий компонента из репозитория
|
||
cmd_versions() {
|
||
if [ -z "$1" ]; then
|
||
echo "Использование: $0 versions <component-id>" >&2
|
||
exit 1
|
||
fi
|
||
|
||
check_init
|
||
COMP_ID="$1"
|
||
|
||
# Проверяем, установлен ли компонент
|
||
if is_installed "$COMP_ID"; then
|
||
CURRENT_VERSION=$(sqlite3 "$REGISTRY_FILE" "SELECT version FROM components WHERE name = '$COMP_ID';" 2>/dev/null)
|
||
info "Текущая установленная версия: $CURRENT_VERSION"
|
||
fi
|
||
|
||
echo ""
|
||
warn "Получение доступных версий для $COMP_ID..."
|
||
info "Для просмотра доступных версий используйте gproxy напрямую:"
|
||
echo " $GPROXY_SCRIPT list"
|
||
echo ""
|
||
info "Или установите последнюю версию:"
|
||
echo " $0 install $COMP_ID latest"
|
||
}
|
||
|
||
# Команда удаления компонента
|
||
cmd_remove() {
|
||
if [ -z "$1" ]; then
|
||
echo "Использование: $0 remove <component-id>" >&2
|
||
exit 1
|
||
fi
|
||
|
||
check_init
|
||
COMP_ID="$1"
|
||
|
||
if is_installed "$COMP_ID"; then
|
||
# Получаем информацию о компоненте
|
||
info "Информация о компоненте:"
|
||
cmd_info "$COMP_ID"
|
||
echo ""
|
||
|
||
warn "Вы уверены, что хотите удалить компонент '$COMP_ID'?"
|
||
echo "Это действие удалит запись из реестра (файлы компонента останутся)"
|
||
echo "Продолжить? (y/N): "
|
||
read -r answer
|
||
|
||
if [ "$answer" = "y" ] || [ "$answer" = "Y" ]; then
|
||
remove_from_registry "$COMP_ID"
|
||
log "Компонент '$COMP_ID' удален из реестра"
|
||
warn "Файлы компонента не были удалены"
|
||
else
|
||
echo "Удаление отменено"
|
||
fi
|
||
else
|
||
echo "Компонент '$COMP_ID' не установлен"
|
||
fi
|
||
}
|
||
|
||
# Команда очистки логов
|
||
cmd_clean_logs() {
|
||
check_init
|
||
|
||
DAYS="${1:-30}"
|
||
info "Очистка логов старше $DAYS дней..."
|
||
|
||
sqlite3 "$REGISTRY_FILE" "DELETE FROM calista_log WHERE timestamp < datetime('now', '-$DAYS days');" 2>/dev/null
|
||
|
||
DELETED=$(sqlite3 "$REGISTRY_FILE" "SELECT changes();" 2>/dev/null)
|
||
log "Удалено $DELETED записей из лога"
|
||
log_to_registry "info" "Очищены логи старше $DAYS дней"
|
||
}
|
||
|
||
# Команда просмотра логов
|
||
cmd_logs() {
|
||
check_init
|
||
|
||
LIMIT="${1:-20}"
|
||
|
||
echo "Последние $LIMIT записей лога:"
|
||
echo "==============================="
|
||
echo ""
|
||
|
||
sqlite3 "$REGISTRY_FILE" "SELECT timestamp, type, user, details FROM calista_log ORDER BY timestamp DESC LIMIT $LIMIT;" 2>/dev/null | while IFS='|' read -r timestamp type user details; do
|
||
case "$type" in
|
||
"error")
|
||
echo -e "${RED}[$timestamp]${NC} [$type] $user: $details"
|
||
;;
|
||
"info")
|
||
echo -e "${GREEN}[$timestamp]${NC} [$type] $user: $details"
|
||
;;
|
||
*)
|
||
echo "[$timestamp] [$type] $user: $details"
|
||
;;
|
||
esac
|
||
done
|
||
}
|
||
|
||
# Команда помощи
|
||
cmd_help() {
|
||
echo "Calista Component Manager"
|
||
echo "========================="
|
||
echo "Команды:"
|
||
echo " install <id> [version] [source] - Установить компонент"
|
||
echo " (source: git или local, по умолчанию git)"
|
||
echo " list - Показать установленные компоненты"
|
||
echo " info <id> - Информация об установленном компоненте"
|
||
echo " remove <id> - Удалить компонент из реестра"
|
||
echo " update - Обновить список компонентов из репозитория"
|
||
echo " versions <id> - Показать доступные версии компонента"
|
||
echo " logs [limit] - Показать последние записи лога (по умолчанию 20)"
|
||
echo " clean-logs [days] - Очистить старые логи (по умолчанию старше 30 дней)"
|
||
echo " help - Показать эту справку"
|
||
echo ""
|
||
echo "Примеры:"
|
||
echo " $0 install cpm v1.0.0 git"
|
||
echo " $0 install calista-graphics-legacy latest"
|
||
echo " $0 list"
|
||
echo " $0 info cpm"
|
||
echo " $0 remove cpm"
|
||
echo " $0 logs 50"
|
||
echo " $0 clean-logs 60"
|
||
echo ""
|
||
echo "Путь к реестру: $REGISTRY_FILE"
|
||
echo ""
|
||
echo "Для работы с репозиторием компонентов сначала настройте gproxy:"
|
||
echo " $GPROXY_SCRIPT set-repo <ваш-git-репозиторий>"
|
||
echo " $0 update"
|
||
}
|
||
|
||
# Главная функция
|
||
main() {
|
||
case "$1" in
|
||
install)
|
||
cmd_install "$2" "$3" "$4"
|
||
;;
|
||
list)
|
||
cmd_list
|
||
;;
|
||
info)
|
||
cmd_info "$2"
|
||
;;
|
||
remove)
|
||
cmd_remove "$2"
|
||
;;
|
||
update)
|
||
cmd_update
|
||
;;
|
||
versions)
|
||
cmd_versions "$2"
|
||
;;
|
||
logs)
|
||
cmd_logs "$2"
|
||
;;
|
||
clean-logs)
|
||
cmd_clean_logs "$2"
|
||
;;
|
||
help|--help|-h)
|
||
cmd_help
|
||
;;
|
||
*)
|
||
if [ -z "$1" ]; then
|
||
cmd_help
|
||
else
|
||
error "Неизвестная команда: $1"
|
||
echo "Используйте: $0 help" >&2
|
||
exit 1
|
||
fi
|
||
;;
|
||
esac
|
||
}
|
||
|
||
# Проверка root прав для установки
|
||
if [ "$(id -u)" -ne 0 ] && [ "$1" = "install" ]; then
|
||
warn "Для установки компонентов рекомендуется запускать от root"
|
||
echo "Продолжить? (y/N): "
|
||
read -r answer
|
||
if [ "$answer" != "y" ] && [ "$answer" != "Y" ]; then
|
||
exit 1
|
||
fi
|
||
fi
|
||
|
||
# Запуск
|
||
main "$@"
|