#!/bin/sh # Скрипт для отображения дерева зависимостей пакета в FreeBSD show_usage() { echo "Использование: $0 [-s] <имя пакета>" echo "Опции:" echo " -s Показывать системные зависимости как 'системная зависимость'" echo "Примеры:" echo " $0 nano # Полное дерево зависимостей" echo " $0 -s nano # Скрыть системные пакеты" exit 1 } # Переменные по умолчанию SHOW_SYSTEM_DETAILS=true PKG_NAME="" # Разбор аргументов командной строки while getopts "s" opt; do case $opt in s) SHOW_SYSTEM_DETAILS=false ;; \?) show_usage ;; esac done # Сдвигаем аргументы, чтобы получить имя пакета shift $((OPTIND - 1)) # Проверка наличия имени пакета if [ $# -eq 0 ]; then show_usage fi PKG_NAME="$1" # Проверка установлен ли пакет if ! pkg info "$PKG_NAME" > /dev/null 2>&1; then echo "Пакет '$PKG_NAME' не найден или не установлен" exit 1 fi # Функция для проверки, является ли пакет системным # Системные пакеты начинаются с FreeBSD- и содержат версию is_system_package() { local pkg="$1" # Проверяем, начинается ли имя с FreeBSD- if echo "$pkg" | grep -q "^FreeBSD-"; then # Проверяем, содержит ли версию (цифры после последнего дефиса) #if echo "$pkg" | grep -q -- '-[0-9][0-9.]*$'; then # return 0 # Это системный пакет #fi return 0 fi return 1 # Не системный пакет } # Функция для очистки имени пакета (удаляем версию и скобки с библиотеками) clean_pkg_name() { local pkg="$1" # Удаляем все после первого пробела (включая скобки с библиотеками) echo "$pkg" | awk '{print $1}' } # Функция для получения зависимостей пакета get_deps() { local pkg="$1" pkg info -d $(clean_pkg_name "$pkg") 2>/dev/null | tail -n +2 | sed 's/^[[:space:]]*//' | \ while read -r dep_line; do # Пропускаем пустые строки [ -z "$dep_line" ] && continue # Очищаем имя пакета local clean_dep=$(clean_pkg_name "$dep_line") # Проверяем, существует ли пакет if pkg info "$clean_dep" > /dev/null 2>&1; then echo "$dep_line" else # Если пакет не найден, пытаемся получить базовое имя # (для FreeBSD-clibs-15.0 -> FreeBSD-clibs) local base_name=$(echo "$clean_dep" | sed 's/-[0-9].*//') if [ -n "$base_name" ] && pkg info "$base_name" > /dev/null 2>&1; then echo "$dep_line" else # Если не удалось найти, выводим оригинальное имя echo "$dep_line" fi fi done } # Рекурсивная функция для отображения дерева show_tree() { local pkg="$1" local indent="$2" local is_last="$3" local processed_pkgs="$4" # Список уже обработанных пакетов # Проверяем, не обрабатывали ли мы уже этот пакет в данной ветке if echo "$processed_pkgs" | grep -q "^$pkg$"; then # Пакет уже был обработан - выводим информацию о циклической зависимости if [ "$is_last" = "true" ]; then echo "${indent} └── [циклическая зависимость: $pkg]" else echo "${indent}│ └── [циклическая зависимость: $pkg]" fi return fi # Добавляем текущий пакет в список обработанных if [ -z "$processed_pkgs" ]; then processed_pkgs="$pkg" else processed_pkgs="$processed_pkgs $pkg" fi # Определяем префиксы для отображения if [ "$is_last" = "true" ]; then local prefix="└── " local next_indent="$indent " else local prefix="├── " local next_indent="$indent│ " fi # Выводим имя пакета или "системная зависимость" if [ "$SHOW_SYSTEM_DETAILS" = "true" ] || ! is_system_package "$pkg"; then echo "${indent}${prefix}${pkg}" else echo "${indent}${prefix}системная зависимость" # Для системных зависимостей не показываем дальнейшее дерево, если не включен детальный режим if [ "$SHOW_SYSTEM_DETAILS" = "false" ]; then return fi fi # Получаем зависимости текущего пакета local deps deps=$(get_deps "$pkg") if [ -z "$deps" ]; then # Если зависимостей нет if [ "$is_last" = "true" ]; then echo "${indent} └── (нет зависимостей)" else echo "${indent}│ └── (нет зависимостей)" fi else # Обрабатываем зависимости local count=0 local total=$(echo "$deps" | wc -l) echo "$deps" | while read -r dep; do count=$((count + 1)) # Пропускаем системные зависимости, если они не в детальном режиме if [ "$SHOW_SYSTEM_DETAILS" = "false" ] && is_system_package "$dep"; then # Если это последняя зависимость и она системная if [ $count -eq $total ]; then echo "${next_indent}└── системная зависимость" else # echo "${next_indent}├── системная зависимость" fi continue fi if [ $count -eq $total ]; then # Последняя зависимость show_tree "$dep" "$next_indent" "true" "$processed_pkgs" else # Не последняя зависимость show_tree "$dep" "$next_indent" "false" "$processed_pkgs" fi done fi } # Основная часть скрипта echo "======= Дерево зависимостей пакета $PKG_NAME =======" #if [ "$SHOW_SYSTEM_DETAILS" = "false" ]; then # echo "Режим: системные зависимости скрыты" #fi show_tree "$PKG_NAME" "" "true" ""