Files
profile/profile.d/packages.sh
2026-05-06 18:27:19 +02:00

200 lines
6.5 KiB
Bash

#!/usr/bin/env bash
# ------------------------------------------------------------------------------
# Copyright (c) 2013-2026 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
# Protected by the BSD3 license. Please read bellow for details.
#
# * Redistribution and use in source and binary forms,
# * with or without modification, are permitted provided
# * that the following conditions are met:
# *
# * Redistributions of source code must retain the above
# * copyright notice, this list of conditions and the
# * following disclaimer.
# *
# * Redistributions in binary form must reproduce the above
# * copyright notice, this list of conditions and the following
# * disclaimer in the documentation and/or other materials
# * provided with the distribution.
# *
# * Neither the name of the copyright holder nor the names
# * of any other contributors may be used to endorse or
# * promote products derived from this software without
# * specific prior written permission.
# *
# * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
# * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
# * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# * OF SUCH DAMAGE.
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Detect the active package manager of the current distribution.
# Detection is based on /etc/os-release (ID / ID_LIKE), then falls back to
# checking available binaries in a fixed priority order.
# Echoes one of: apt dnf yum zypper pacman apk portage xbps nix
# Returns 1 if no known package manager could be identified.
get_pkgmgr()
{
local distro_id="" distro_like=""
if [[ -r /etc/os-release ]]; then
# shellcheck disable=SC1091
distro_id=$( . /etc/os-release 2>/dev/null; printf '%s' "${ID:-}" )
# shellcheck disable=SC1091
distro_like=$( . /etc/os-release 2>/dev/null; printf '%s' "${ID_LIKE:-}" )
fi
# Map distro IDs/families to a package manager.
# ID_LIKE is space-separated and may list multiple families.
local id
for id in $distro_id $distro_like; do
case "${id,,}" in
debian|ubuntu|linuxmint|raspbian|pop|kali|elementary|zorin|neon|parrot)
echo "apt"
return 0
;;
fedora)
echo "dnf"
return 0
;;
rhel|centos|rocky|almalinux|ol|scientific|amzn)
command -v dnf >/dev/null 2>&1 && { echo "dnf"; return 0; }
echo "yum"
return 0
;;
opensuse*|sles|sled)
echo "zypper"
return 0
;;
arch|manjaro|endeavouros|garuda|artix|cachyos)
echo "pacman"
return 0
;;
alpine)
echo "apk"
return 0
;;
gentoo)
echo "portage"
return 0
;;
void)
echo "xbps"
return 0
;;
nixos)
echo "nix"
return 0
;;
esac
done
# Fallback: check for binaries in priority order.
local bin
for bin in apt apt-get dnf yum zypper pacman apk emerge xbps-install nix-env; do
command -v "$bin" >/dev/null 2>&1 && {
case "$bin" in
apt-get) echo "apt" ;;
emerge) echo "portage" ;;
xbps-install) echo "xbps" ;;
nix-env) echo "nix" ;;
*) echo "$bin" ;;
esac
return 0
}
done
return 1
}
export -f get_pkgmgr
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# Look for a package within installed one
# Usage: pkgs <string>
pkgs()
{
local ignore_case=${PKGS_DEFAULT_IGNORE_CASE:-0}
local PARSED
PARSED=$(getopt -o hi --long help,ignore-case -n 'pkgs' -- "$@")
# shellcheck disable=SC2181 # getopt return code is checked immediately after
if [[ $? -ne 0 ]]; then
disp E "Invalid options, use \"pkgs --help\" to display usage."
return 1
fi
eval set -- "$PARSED"
while true; do
case "$1" in
-h|--help)
printf "pkgs: Look for an installed package by its name.\n\n"
printf "Usage: pkgs [options] <string>\n\n"
printf "Options:\n"
printf "\t-h, --help\tDisplay this help screen\n"
printf "\t-i, --ignore-case\tIgnore case distinctions\n"
return 0
;;
-i|--ignore-case)
ignore_case=1
shift
;;
--)
shift
break
;;
*)
disp E "Invalid option: $1"
return 1
;;
esac
done
local pkg="$1"
[[ -z "$pkg" ]] && {
disp E "Please specify a package name, without space, eventually partial."
return 1
}
# Build grep command
local grep_opt=""
(( ignore_case )) && grep_opt="-i"
local pkgmgr
pkgmgr=$(get_pkgmgr) || {
disp E "No usable package manager could be detected on this system."
return 2
}
local -a list_cmd
case "$pkgmgr" in
apt) list_cmd=(dpkg-query -l) ;;
dnf|yum|zypper) list_cmd=(rpm -qa) ;;
pacman) list_cmd=(pacman -Q) ;;
apk) list_cmd=(apk list --installed) ;;
portage) list_cmd=(qlist -I) ;;
xbps) list_cmd=(xbps-query -l) ;;
nix) list_cmd=(nix-env -q) ;;
*)
disp E "Package manager '$pkgmgr' is not supported by pkgs."
return 2
;;
esac
"${list_cmd[@]}" | grep ${grep_opt:+"$grep_opt"} "$pkg"
}
export -f pkgs
# ------------------------------------------------------------------------------
load_conf "packages"
# EOF