Files

191 lines
7.2 KiB
Bash
Executable File

#!/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" ""