333 lines
6.9 KiB
Bash
Executable file
333 lines
6.9 KiB
Bash
Executable file
#!/usr/bin/env sh
|
|
|
|
# set -x
|
|
|
|
# Allows to install software
|
|
|
|
# Find list of available installers in order of preference
|
|
# Read wanted packages and their availability
|
|
# Install packages per installer (after prompting)
|
|
|
|
# COMMON FUNCTIONS
|
|
|
|
# GLOBAL VARIABLES
|
|
|
|
# TODO Lock or temp folder
|
|
CACHE_DIR="${XDG_CACHE_DIR:-$HOME/.cache}/installSoftware"
|
|
INSTALLERS_DIR="${CACHE_DIR}/installers"
|
|
INSTALLERS_LIST="${CACHE_DIR}/installers.list"
|
|
|
|
# TODO Package groups
|
|
|
|
# INSTALLER SPECIFIC FUNCTIONS
|
|
|
|
# Test if available
|
|
available_pkgbuild() {
|
|
true
|
|
}
|
|
|
|
# Update the database
|
|
update_Rpacman() {
|
|
sudo pacman -Syu --noconfirm
|
|
}
|
|
|
|
update_Ryay() {
|
|
yay -Syu --noconfirm --devel
|
|
}
|
|
|
|
update_Rapt() {
|
|
# TODO non-interactive
|
|
sudo apt update -y
|
|
sudo apt upgrade -y
|
|
}
|
|
|
|
# Test if installed
|
|
|
|
installed_Rpacman() { # packageName
|
|
pacman -Qq "$1" &> /dev/null
|
|
}
|
|
|
|
installed_Ryay() { # package
|
|
installed_Rpacman "$@"
|
|
}
|
|
|
|
installed_pip() { # package
|
|
pip show "$@" > /dev/null
|
|
}
|
|
|
|
installed_makepkg() { # package
|
|
installed_Rpacman "$@"
|
|
}
|
|
|
|
installed_pkgbuild() { # package
|
|
installed_Rpacman "$@"
|
|
# TODO Might need all the systems package too
|
|
}
|
|
|
|
installed_Rapt() {
|
|
STATUS=$(mktemp)
|
|
LANG=C dpkg-query --status $1 &> $STATUS
|
|
installed=0
|
|
if [ $? == 0 ]; then
|
|
cat $STATUS | grep '^Status:' | grep ' installed' --quiet
|
|
if [ $? == 0 ]; then
|
|
installed=1
|
|
fi
|
|
fi
|
|
rm -f $STATUS > /dev/null
|
|
return $installed
|
|
}
|
|
|
|
# Test if available in the repositories
|
|
|
|
installable_aur() {
|
|
curl --fail --silent --head "https://aur.archlinux.org/packages/$@" > /dev/null
|
|
}
|
|
|
|
installable_Rpacman() {
|
|
pacman -Si "$1" &> /dev/null
|
|
}
|
|
|
|
installable_Ryay() {
|
|
# yay -Ss "$1" > /dev/null
|
|
installable_aur
|
|
}
|
|
|
|
installable_pkgbuild() {
|
|
installable_aur
|
|
}
|
|
|
|
installable_makepkg() {
|
|
installable_aur
|
|
}
|
|
|
|
# Tell if it hadles mutiple argument for install
|
|
|
|
multiinstall_pacman() {
|
|
true
|
|
}
|
|
|
|
multiinstall_pip() {
|
|
true
|
|
}
|
|
|
|
multiinstall_apt() {
|
|
true
|
|
}
|
|
|
|
# Really install
|
|
|
|
install_Rpacman() {
|
|
sudo pacman -S --needed --noconfirm $@
|
|
}
|
|
|
|
install_Ryay() {
|
|
yay -S --needed --noconfirm $@
|
|
}
|
|
|
|
install_Rapt() {
|
|
apt install -y $@
|
|
}
|
|
|
|
install_Rpip() {
|
|
sudo pip install $@
|
|
}
|
|
|
|
install_Upip() {
|
|
pip install --user $@
|
|
}
|
|
|
|
installable_Rmakepkg() {
|
|
old_pwd="$PWD"
|
|
TMP_DIR="$(mktemp -d /tmp/pkgbuild.XXXXXXXXXX)"
|
|
cd "$TMP_DIR"
|
|
wget "https://aur.archlinux.org/cgit/aur.git/snapshot/$1.tar.gz"
|
|
tar xzvf "$1.tar.gz"
|
|
cd "$1"
|
|
makepkg -si
|
|
cd "$old_pwd"
|
|
rm -rf "$TMP_DIR"
|
|
}
|
|
|
|
# GENERIC INSTALLER FUNCTIONS
|
|
|
|
installerCanonicalName() { # installerName
|
|
echo "${1:1}"
|
|
}
|
|
|
|
notImplementedFallback() { # command installerName
|
|
echo "[NIMPL] Not implemented: command $1_$2"
|
|
false
|
|
}
|
|
|
|
# Wrapper to run a command for an installer
|
|
commandInstaller() { # command installerName fallback args...
|
|
# echo "[DEBUG] commandInstaller $*"
|
|
command="$1"
|
|
installerName="$2"
|
|
fallback="$3"
|
|
shift; shift; shift
|
|
installerCName="$(installerCanonicalName "$installerName")"
|
|
if command -v "${command}_$installerName" > /dev/null
|
|
then
|
|
"${command}_$installerName" "$@"
|
|
elif command -v "${command}_$installerCName" > /dev/null
|
|
then
|
|
"${command}_$installerCName" "$@"
|
|
else
|
|
$fallback "$command" "$installerName" "$@"
|
|
fi
|
|
}
|
|
|
|
# INSTALLER LIST FUNCTIONS
|
|
|
|
availableInstallerFallback() { # command installerName
|
|
command -v "$(installerCanonicalName "$2")" > /dev/null
|
|
}
|
|
|
|
availableInstaller() { # installerName
|
|
commandInstaller "available" "$1" availableInstallerFallback
|
|
}
|
|
|
|
# Clears the list of installers to use
|
|
resetInstallers() {
|
|
rm -f "$INSTALLERS_LIST"
|
|
touch "$INSTALLERS_LIST"
|
|
rm -rf "$INSTALLERS_DIR"
|
|
mkdir -p "$INSTALLERS_DIR"
|
|
}
|
|
|
|
addInstaller() { # installername
|
|
if availableInstaller "$1"
|
|
then
|
|
echo "$1" >> "$INSTALLERS_LIST"
|
|
rm -f "$INSTALLERS_DIR/$1"
|
|
touch "$INSTALLERS_DIR/$1"
|
|
return 0
|
|
fi
|
|
return 1
|
|
}
|
|
|
|
|
|
listInstallers() {
|
|
cat "$INSTALLERS_LIST"
|
|
}
|
|
|
|
hasInstaller() { # installerName
|
|
[ -f "${INSTALLERS_DIR}/$1" ]
|
|
}
|
|
|
|
|
|
# Installers that install in the user directory
|
|
addUserInstallers() {
|
|
addInstaller Umakepkg
|
|
addInstaller Upip
|
|
addInstaller Upkgbuild
|
|
}
|
|
|
|
# Installers that install with the system package manager
|
|
addSystemInstallers() {
|
|
addInstaller Rapt
|
|
addInstaller Rpacman
|
|
addInstaller Ryay || addInstaller Rmakepkg
|
|
}
|
|
|
|
# Installers that install in the system root but not tracked with system package manager
|
|
addRootInstallers() {
|
|
addInstaller Rnode
|
|
addInstaller Rpip
|
|
addInstaller Rpkgbuild
|
|
|
|
}
|
|
|
|
# UPDATING INSTALLER DATABASES
|
|
|
|
updateInstallers() {
|
|
for installerName in $(listInstallers)
|
|
do
|
|
commandInstaller "update" "$installerName" true
|
|
done
|
|
}
|
|
|
|
# MARKING PACKAGES TO INSTALL
|
|
|
|
markPackage() { # installer package
|
|
# echo "[DEBUG] Marked $*"
|
|
echo "$2" >> "$INSTALLERS_DIR/$1"
|
|
}
|
|
|
|
# Test if a package is installed
|
|
installedPackage() { # package
|
|
for installerName in $(listInstallers)
|
|
do
|
|
if commandInstaller "installed" "$installerName" notImplementedFallback "$1"
|
|
then
|
|
return 0
|
|
fi
|
|
done
|
|
return 1
|
|
}
|
|
|
|
installablePackageBy() { # installer package
|
|
commandInstaller "installable" "$1" notImplementedFallback "$2"
|
|
}
|
|
|
|
# List packages to install by given installer
|
|
listPackagesForInstaller() { # installer
|
|
cat "$INSTALLERS_DIR/$1"
|
|
}
|
|
|
|
isToInstall() { # package
|
|
for installerName in $(listInstallers)
|
|
do
|
|
listPackagesForInstaller "$installerName" | grep -q "^$1\$" && return 0
|
|
done
|
|
return 1
|
|
}
|
|
|
|
# Mark package to installer list where available
|
|
tryPackage() { # packageNames
|
|
# If package is already installed or marked to install, skip
|
|
for package in "$@"
|
|
do
|
|
installedPackage "$package" && return 0
|
|
isToInstall "$package" && return 0
|
|
|
|
done
|
|
# For each installer
|
|
for installerName in $(listInstallers)
|
|
do
|
|
# For each name given
|
|
for package in "$@"
|
|
do
|
|
# Mark if name available to installer
|
|
if installablePackageBy "$installerName" "$package"
|
|
then
|
|
markPackage "$installerName" "$package"
|
|
return 0
|
|
fi
|
|
done
|
|
done
|
|
echo "[ERR] Cannot install package with aliases: $*"
|
|
return 1
|
|
}
|
|
alias i=tryPackage
|
|
|
|
installPackages() {
|
|
for installerName in $(listInstallers)
|
|
do
|
|
# If we can install multiple packages in one go
|
|
if commandInstaller "multiinstall" "$installerName" false
|
|
then
|
|
packages=$(listPackagesForInstaller "$installerName")
|
|
[ -z "$packages" ] && continue
|
|
commandInstaller "install" "$installerName" notImplementedFallback $packages
|
|
else
|
|
for packageName in $(listPackagesForInstaller "$installerName")
|
|
do
|
|
commandInstaller "install" "$installerName" notImplementedFallback "$packageName"
|
|
done
|
|
fi
|
|
done
|
|
}
|