Files
alr-repo/validate-alr.sh

273 lines
10 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# Валидатор для alr.sh файлов в репозитории ALR
# Проверяет синтаксис и структуру пакетов
set -e
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Глобальные счетчики
declare -g errors=0
declare -g warnings=0
# Функция для вывода ошибок
error() {
echo -e "${RED}[ERROR]${NC} $1"
((errors++))
}
# Функция для вывода предупреждений
warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
((warnings++))
}
# Функция для вывода успешных проверок
success() {
echo -e "${GREEN}[OK]${NC} $1"
}
# Проверка одного alr.sh файла
check_alr_file() {
local file="$1"
local pkg_dir=$(dirname "$file")
local pkg_name=$(basename "$pkg_dir")
echo "Проверка пакета: $pkg_name"
# 1. Проверка синтаксиса bash
if ! bash -n "$file" 2>/dev/null; then
error "$pkg_name: синтаксические ошибки в alr.sh"
return 1
fi
# Загружаем файл в изолированной среде для проверки
{
# Определяем заглушки для функций ALR
srcdir="/tmp/alr-validate-src"
pkgdir="/tmp/alr-validate-pkg"
scriptdir="$pkg_dir"
# Заглушки для функций установки
install() { :; }
install-desktop() { :; }
install-license() { :; }
# Загружаем файл
source "$file" 2>/dev/null || {
error "$pkg_name: не удалось загрузить alr.sh"
return 1
}
# 2. Проверка обязательных полей
local required_fields=(name version release desc maintainer)
for field in "${required_fields[@]}"; do
if [[ -z "${!field}" ]]; then
error "$pkg_name: отсутствует обязательное поле '$field'"
fi
done
# 3. Проверка формата версии
# Поддерживаемые форматы:
# - стандартный: 1.2.3, 1.0.0-alpha1
# - git версии: git
# - release префикс: release-1.2.3
# - версии с r префиксом: r20250906.ff1bee31
if [[ ! "$version" =~ ^([0-9]+(\.[0-9]+)*([a-zA-Z0-9._-]+)?|git|release-[0-9]+(\.[0-9]+)*([a-zA-Z0-9._-]+)?|r[0-9]{8}\.[a-z0-9]+)$ ]]; then
# Не выводим предупреждения для git пакетов
if [[ ! "$pkg_name" =~ -git$ ]]; then
warning "$pkg_name: необычный формат версии '$version'"
fi
fi
# 4. Проверка формата release
if [[ ! "$release" =~ ^[0-9]+$ ]]; then
error "$pkg_name: release должен быть числом, получено '$release'"
fi
# 5. Проверка наличия функций
# Определяем тип пакета: мульти-пакет если name объявлен как массив с несколькими элементами
# Проверяем, объявлен ли name как массив в исходном файле
local is_multipackage=false
if grep -q "^name=(" "$file"; then
# Если в файле есть name=( значит это массив
if [[ "${#name[@]}" -gt 1 ]]; then
is_multipackage=true
fi
fi
if [[ "$is_multipackage" == true ]]; then
# Мульти-пакет - проверяем функции с префиксами
for subpkg in "${name[@]}"; do
# Проверяем наличие meta функции
if ! declare -F "meta_${subpkg}" >/dev/null 2>&1; then
warning "$pkg_name: отсутствует функция meta_${subpkg}()"
fi
# Проверяем наличие package функции
if ! declare -F "package_${subpkg}" >/dev/null 2>&1; then
warning "$pkg_name: отсутствует функция package_${subpkg}()"
fi
# Проверяем наличие files функции
if ! declare -F "files_${subpkg}" >/dev/null 2>&1; then
error "$pkg_name: отсутствует функция files_${subpkg}()"
fi
done
else
# Обычный (моно)пакет - проверяем обычные функции
# Проверяем наличие функции package() или build()
if ! declare -F package >/dev/null 2>&1; then
if ! declare -F build >/dev/null 2>&1; then
warning "$pkg_name: отсутствуют функции package() и build()"
fi
fi
# Проверяем наличие функции files()
if ! declare -F files >/dev/null 2>&1; then
error "$pkg_name: отсутствует функция files()"
fi
fi
# 6. Проверка архитектур
if [[ -n "${architectures[*]}" ]]; then
for arch in "${architectures[@]}"; do
if [[ ! "$arch" =~ ^(amd64|arm64|arm6|386|riscv64|aarch64|all)$ ]]; then
warning "$pkg_name: неизвестная архитектура '$arch'"
fi
done
fi
# 7. Проверка источников и контрольных сумм
if [[ -n "${sources[*]}" ]]; then
if [[ -z "${checksums[*]}" ]]; then
warning "$pkg_name: sources определены, но checksums отсутствуют"
elif [[ "${#sources[@]}" -ne "${#checksums[@]}" ]]; then
if [[ "${checksums[0]}" != "SKIP" ]]; then
error "$pkg_name: количество sources (${#sources[@]}) не совпадает с checksums (${#checksums[@]})"
fi
fi
fi
# 8. Проверка, что функции не вызывают явные ошибки
# Создаем временные директории для тестирования
mkdir -p "$srcdir" "$pkgdir"
# Пробуем выполнить функции в dry-run режиме
if declare -F build >/dev/null 2>&1; then
# Переопределяем команды, которые могут быть опасными
curl() { echo "curl $*" >/dev/null; }
wget() { echo "wget $*" >/dev/null; }
git() { echo "git $*" >/dev/null; }
make() { echo "make $*" >/dev/null; }
cmake() { echo "cmake $*" >/dev/null; }
pip() { echo "pip $*" >/dev/null; }
npm() { echo "npm $*" >/dev/null; }
cargo() { echo "cargo $*" >/dev/null; }
tar() { echo "tar $*" >/dev/null; }
unzip() { echo "unzip $*" >/dev/null; }
cd() { builtin cd "$@" 2>/dev/null || :; }
export -f curl wget git make cmake pip npm cargo tar unzip cd
# Пробуем выполнить build в режиме проверки синтаксиса
if ! bash -c "source '$file' && declare -f build | bash -n" 2>/dev/null; then
warning "$pkg_name: синтаксические ошибки в функции build()"
fi
fi
if declare -F package >/dev/null 2>&1; then
if ! bash -c "source '$file' && declare -f package | bash -n" 2>/dev/null; then
warning "$pkg_name: синтаксические ошибки в функции package()"
fi
fi
if declare -F files >/dev/null 2>&1; then
if ! bash -c "source '$file' && declare -f files | bash -n" 2>/dev/null; then
warning "$pkg_name: синтаксические ошибки в функции files()"
fi
fi
# Очистка
rm -rf "$srcdir" "$pkgdir" 2>/dev/null || true
} 2>/dev/null || true
}
# Главная функция
main() {
local check_all=false
local files_to_check=()
# Парсим аргументы
while [[ $# -gt 0 ]]; do
case "$1" in
--all)
check_all=true
shift
;;
*)
files_to_check+=("$1")
shift
;;
esac
done
# Если указан флаг --all, проверяем все alr.sh файлы
if [[ "$check_all" == true ]]; then
echo "Проверка всех alr.sh файлов в репозитории..."
while IFS= read -r file; do
check_alr_file "$file"
echo "---"
done < <(find . -name "alr.sh" -type f | grep -v "^\./\." | sort)
else
# Проверяем только указанные файлы или измененные в git
if [[ ${#files_to_check[@]} -eq 0 ]]; then
# Получаем список измененных alr.sh файлов из git
while IFS= read -r file; do
if [[ -f "$file" ]] && [[ "$(basename "$file")" == "alr.sh" ]]; then
files_to_check+=("$file")
fi
done < <(git diff --cached --name-only)
fi
if [[ ${#files_to_check[@]} -eq 0 ]]; then
echo "Нет alr.sh файлов для проверки"
exit 0
fi
for file in "${files_to_check[@]}"; do
if [[ -f "$file" ]]; then
check_alr_file "$file"
echo "---"
fi
done
fi
# Итоговая статистика
echo ""
if [[ $errors -gt 0 ]]; then
echo -e "${RED}Найдено ошибок: $errors${NC}"
fi
if [[ $warnings -gt 0 ]]; then
echo -e "${YELLOW}Найдено предупреждений: $warnings${NC}"
fi
if [[ $errors -gt 0 ]]; then
echo -e "${RED}Проверка не пройдена!${NC}"
exit 1
elif [[ $warnings -gt 0 ]]; then
echo -e "${YELLOW}Проверка пройдена с предупреждениями${NC}"
exit 0
else
echo -e "${GREEN}Все проверки пройдены успешно!${NC}"
exit 0
fi
}
main "$@"