ambevar-dotfiles/.shell.d/funs_pacman

472 lines
12 KiB
Bash

## -*- mode:sh -*- #
##==============================================================================
## Pacman Functions
##==============================================================================
## This function gets the pacman variables when necessary. Note: some functions
## uses pacman localized output. It should work in any case. You should always
## call _pacman_unset_vars in the end.
_pacman_set_vars()
{
local pacman_var_list="$(pacman -Qi tzdata | cut -f1 -d':')"
if [ -z "$pacman_var_list" ] ; then
echo "Could not get pacman's variables."
return 2
fi
pacman_name="$(echo "$pacman_var_list" | sed -n '1{p;q}')"
pacman_deps="$(echo "$pacman_var_list" | sed -n '7{p;q}')"
pacman_deps_none="$(pacman -Qi tzdata | sed -n '7{s/.*: //;p;q}')"
pacman_optdeps="$(echo "$pacman_var_list" | sed -n '8{p;q}')"
pacman_size="$(echo "$pacman_var_list" | sed -n '12{p;q}')"
}
_pacman_unset_vars()
{
unset pacman_name
unset pacman_deps
unset pacman_optdeps
unset pacman_size
}
## Get detailed file size list for the specified packages.
pacman-files()
{
_printhelp()
{
cat <<EOF
Usage: $1 [OPTIONS] PACKAGES
Display size of files in PACKAGES.
-h: Display this help.
-n: Sort by size.
EOF
}
local OPTION_SORT="cat"
while getopts ":hn" opt; do
case $opt in
h)
_printhelp "$0"
return 1
;;
n)
OPTION_SORT="sort -h"
;;
?)
_printhelp "$0"
return 1
;;
:)
echo "Missing argument."
echo "Use $0 -h for help."
return 1
;;
esac
done
shift $(($OPTIND - 1))
if [ $# -eq 0 ]; then
echo "Missing argument."
echo "Use $0 -h for help."
return 1
fi
du -bch $(pacman -Qlq "$@" | grep -v ".*/$" | sort -u) 2>/dev/null | eval ${OPTION_SORT}
}
[ "zsh" = "$SHELL_CURRENT" ] && compdef _pcc pacman-files
## Retrieve official packages list.
pacman-official()
{
# Alternative 'diff' verision.
# diff <(pacman -Qq | sort) <(pacman -Qmq | sort) --new-line-format='' --unchanged-group-format='%>'
comm -3 <(pacman -Qq | sort) <(pacman -Qmq | sort)
}
## Compare installed packages with list.
pacman-diff()
{
_printhelp()
{
cat <<EOF
Usage: $1 [-m|-e] [-q] FILE
Display packages included in FILE but not installed.
-e: Compare FILE to explicitly installed packages.
-h: Display this help.
-m: Compare FILE to foreign installed packages.
-q: Display installed packages not included in FILE.
EOF
}
local OPTION_EXPLICIT=""
local OPTION_FOREIGN=""
local OPTION_LOCAL="-1"
while getopts ":hmqe" opt; do
case $opt in
e)
OPTION_EXPLICIT="e"
;;
h)
_printhelp "$0"
return 1
;;
m)
OPTION_FOREIGN="m"
;;
q)
OPTION_LOCAL="-2"
;;
?)
_printhelp "$0"
return 1
;;
:)
echo "Missing argument."
echo "Use $0 -h for help."
return 1
;;
esac
done
shift $(($OPTIND - 1))
if [ $# -eq 0 ]; then
echo "Missing argument."
echo "Use $0 -h for help."
return 1
fi
comm -3 ${OPTION_LOCAL} <(pacman -Qq${OPTION_FOREIGN}${OPTION_EXPLICIT} | sort) <(sort "$*")
}
## Print specified package size and a grand total.
pacman-size()
{
_printhelp()
{
cat <<EOF
Usage: $1 [OPTIONS] PACKAGES
Display package size. Output contains no double and is alphabetically sorted. A
grand total is printed at the end. It will only work for repos packages by
default.
-h: Show this help.
-n: Output is sorted by size.
-q: Uses installed packages database instead of repos database. It speeds up queries and allows displaying size of local packages not available in repos.
EOF
}
local CMD="pacman -Si"
local SEP=": "
local TOTAL_SIZE=0
local SORT="sort -u -k3"
local SORT_SIZE="cat"
while getopts ":hnq" opt; do
case $opt in
h)
_printhelp "$0"
return 1
;;
n)
SORT_SIZE="sort -n"
;;
q)
CMD="pacman -Qi"
;;
?)
_printhelp "$0"
return 1
;;
:)
echo "Missing argument."
echo "Use $0 -h for help."
return 1
;;
esac
done
shift $(($OPTIND - 1))
if [ $# -eq 0 ]; then
echo "Missing argument."
echo "Use $0 -h for help."
return 1
fi
_pacman_set_vars
## We use external variable for awk to fit current locales.
local RESULT="$(eval "${CMD} $@" 2>/dev/null | awk -F "$SEP" -v filter="$pacman_size" -v pkg="$pacman_name" \
'$0 ~ pkg {pkgname=$2} $0 ~ filter {gsub(/\..*/,"") ; printf("%6s KiB %s\n", $2, pkgname)}' | eval "$SORT" | eval "$SORT_SIZE")"
echo "$RESULT"
## Print total size.
echo "$RESULT" | awk '{TOTAL=$1+TOTAL} END {printf("Total: %d KiB\n",TOTAL)}'
## One line version. Approximately same performance. Note the combinaion of
## 'tee' and >(awk ...) to write the detailed list to standard output and to
## pass it to awk.
# eval "${CMD} $@ 2>/dev/null" | awk -F "$SEP" -v filter="$pacman_size" -v pkg="$pacman_name" \
# '$0 ~ pkg {pkgname=$2} $0 ~ filter {gsub(/\..*/,"") ; printf("%6s KiB %s\n", $2, pkgname)}' | sort -u -k3 \
# | tee >(awk '{TOTAL=$1+TOTAL} END {printf("Total: %d KiB\n",TOTAL)}')
_pacman_unset_vars
}
[ "zsh" = "$SHELL_CURRENT" ] && compdef _pcc pacman-size
## Print deps list.
pacman-deps()
{
_printhelp()
{
cat <<EOF
Usage: $1 [-a|-h|-q] [-r] PACKAGES
Display package dependencies. Output contains no double and is alphabetically
sorted. It will only work for repos packages by default.
-a: Uses Yaourt queries instead of repos database. It slows down query but allow displaying size of any packages not available in repos.
-h: Show this help.
-r: Call function recursively.
-q: Uses installed packages database instead of repos database. It speeds up queries and allows displaying size of local packages not available in repos.
EOF
}
local CMD="pacman -Si"
local OPT_REC=0
local SEP=": "
## TODO: why is OPTIND messy if we do not set it as local?
local OPTIND
while getopts ":ahrq" opt; do
case $opt in
a)
CMD="yaourt -Si"
;;
h)
_printhelp "$0"
return 1
;;
r)
OPT_REC=1
;;
q)
CMD="pacman -Qi"
;;
?)
_printhelp "$0"
return 1
;;
:)
echo "Missing argument."
echo "Use $0 -h for help."
return 1
;;
esac
done
shift $(($OPTIND - 1))
if [ $# -eq 0 ]; then
echo "Missing argument."
echo "Use $0 -h for help."
return 1
fi
_pacman_set_vars
if [ $OPT_REC -eq 0 ]; then
eval "${CMD} $@ 2>/dev/null" | awk -F "$SEP" -v filter="$pacman_deps" '$0 ~ filter {gsub(/[>=<][^ ]*/,"",$2) ; gsub(/ +/,"\n",$2) ; print $2}' | sort -u
else
## Recursive dependencies.
## Store the complete DB into a variable to speed up access.
local FULLDEPLIST
FULLDEPLIST=$(eval "${CMD}" | grep "${pacman_name}\|${pacman_deps}" | sed -n "/${pacman_name}/{s/.*: \(.*\)/\1:/;h;n;s/${pacman_deps}.*: //;s/[>=<][^ ]*//g;H;x;s/\n//;p}")
## Note: using a table is important for Ksh/Zsh compatibility.
local DEPLIST
DEPLIST=()
## Check if argument $1 is in DEPLIST.
_not-in-array()
{
if [ ${#DEPLIST} -eq 0 ]; then
return 0
else
local j
for j in ${DEPLIST[*]}; do
if [ "$j" = "$1" ]; then
return 1
fi
done
return 0
fi
}
## This function calls recursively over the dependencies. It stops
## whenever a package has already be handled, or when it has no
## dependency. Note: 'grep | cut' is a little faster than 'sed' for
## simple stuff. Since it is a loop, it is quite a performance boost.
_pacman-deps-rec()
{
local SUBDEPLIST
SUBDEPLIST=()
for i ; do
SUBDEPLIST=(${SUBDEPLIST[*]} $(echo "$FULLDEPLIST" | grep "^$i\s*:" | cut -d':' -f2))
done
local i
for i in ${SUBDEPLIST[*]} ; do
if [ ! "$i" = "$pacman_deps_none" ] && _not-in-array "$i" ; then
DEPLIST=(${DEPLIST[*]} "$i")
_pacman-deps-rec "$i"
fi
done
}
local i
for i ; do
_pacman-deps-rec "$@"
done
## There might be duplicates, so we remove them with the '-u' parameter of sort.
sed 's/ /\n/g' <(echo "${DEPLIST[*]}") | sort -u
fi
_pacman_unset_vars
}
[ "zsh" = "$SHELL_CURRENT" ] && compdef _pcc pacman-deps
abs-fetch ()
{
_printhelp ()
{
cat <<EOF
Usage: $1 [-hfy] PACKAGES
Fetch PKGBUILDs from ABS-tree.
-f:\t\tOverwrite folder if it exists.
-h:\t\tDisplay this help.
-y:\t\tUse 'yaourt' to fetch data.
Noteworthy parameters:
\$(pacman-official)
\$(pacman -Qmq)
\$(pacman -Qq)
EOF
}
local DL_AGENT=0
local CP_AGENT="/bin/cp -rnv"
while getopts ":hfy" opt; do
case $opt in
h)
_printhelp "$0"
return 1
;;
f)
CP_AGENT="/bin/cp -rfv"
;;
y)
DL_AGENT=1
;;
?)
_printhelp "$0"
return 1
;;
:)
echo "Missing argument."
echo "Use $0 -h for help."
return 1
;;
esac
done
shift $(($OPTIND - 1))
if [ $# -eq 0 ]; then
echo "Missing argument."
echo "Use $0 -h for help."
return 1
fi
if [ $DL_AGENT -eq 0 ]; then
if [ ! -f /usr/bin/abs ]; then
echo "ABS needs to be installed."
return
fi
[ ! -d "/var/abs" ] && sudo abs
for i; do
eval "$CP_AGENT" /var/abs/*/$i .
done
return 0
fi
if [ $DL_AGENT -eq 1 ]; then
if [ ! -f /usr/bin/yaourt ]; then
echo "Yaourt needs to be installed."
return
fi
yaourt -G "$@"
return 0
fi
}
abs-build ()
{
for i; do
cd "$i"
mkdir "srcpkg"
SRCDEST="srcpkg" makepkg -rsc --nocheck --noconfirm
rm -r "srcpkg"
cd ..
done
}
abs-install ()
{
sudo sh -c '
echo "[$0]"
if [ "$0" = "sh" ]; then
for i in *; do
(cd "$i" && pacman --noconfirm -U *.pkg.tar.xz)
done
else
(cd "$0" && pacman --noconfirm -U *.pkg.tar.xz)
for i; do
(cd "$i" && pacman --noconfirm -U *.pkg.tar.xz)
done
fi
' "$@"
}
abs-clean ()
{
for i; do
cd "$i"
rm -rfv "src" "pkg" "srcpkg"
rm -rfv "*.pkg.tar.xz"
cd ..
done
}