diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..1579d56 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,30 @@ +repos: + - repo: local + hooks: + - id: validate-alr-packages + name: Validate ALR packages + entry: ./validate-alr.sh + language: script + files: ^[^/]+/alr\.sh$ + pass_filenames: true + description: "Проверка синтаксиса и структуры alr.sh файлов" + + - id: check-alr-syntax + name: Check bash syntax in alr.sh + entry: bash -n + language: system + files: ^[^/]+/alr\.sh$ + description: "Проверка синтаксиса bash в alr.sh файлах" + + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: trailing-whitespace + exclude: '\.patch$' + - id: end-of-file-fixer + exclude: '\.patch$' + - id: check-yaml + - id: check-added-large-files + args: ['--maxkb=1000'] + - id: check-executables-have-shebangs + - id: check-shebang-scripts-are-executable \ No newline at end of file diff --git a/appmenu-gtk-module/80-appmenu-gtk-module.sh b/appmenu-gtk-module/80-appmenu-gtk-module.sh deleted file mode 100644 index 2782c4c..0000000 --- a/appmenu-gtk-module/80-appmenu-gtk-module.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh - -if [ -n "$GTK_MODULES" ]; then - GTK_MODULES="${GTK_MODULES}:appmenu-gtk-module" -else - GTK_MODULES="appmenu-gtk-module" -fi - -if [ -z "$UBUNTU_MENUPROXY" ]; then - UBUNTU_MENUPROXY=1 -fi - -export GTK_MODULES -export UBUNTU_MENUPROXY diff --git a/appmenu-gtk-module/alr.sh b/appmenu-gtk-module/alr.sh deleted file mode 100644 index 7d18740..0000000 --- a/appmenu-gtk-module/alr.sh +++ /dev/null @@ -1,37 +0,0 @@ -name="appmenu-gtk-module" -version='24.05' -release='1' -desc="Application Menu GTK+ Module." -homepage="https://gitlab.com/vala-panel-project/vala-panel-appmenu/" -maintainer_ru='Евгений Храмов ' -architectures=('amd64') -license=('LGPL-3.0-only') -provides=('appmenu-gtk-module') -conflicts=('appmenu-gtk-module') - -build_deps=( - 'git' - 'gtk2-devel' - 'gtk3-devel' - 'meson' -) - -optdepends=('gtk2: GTK2 module' - 'gtk3: GTK3 module') - -sources=("git+https://gitlab.com/vala-panel-project/vala-panel-appmenu#tag=$version") -checksums=('SKIP') - -_app_id="org.$pkgname.CoolerControl" - -build() { - meson build vala-panel-appmenu/subprojects/$name \ - --prefix=/usr - ninja -C build -} - -package() { - DESTDIR="$pkgdir" ninja install -C build - install -Dm755 $scriptdir/80-appmenu-gtk-module.sh -t "$pkgdir"/etc/X11/xinit/xinitrc.d/ -} - diff --git a/validate-alr.sh b/validate-alr.sh new file mode 100755 index 0000000..2ff938a --- /dev/null +++ b/validate-alr.sh @@ -0,0 +1,273 @@ +#!/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 "$@" \ No newline at end of file