473 lines
13 KiB
Bash
473 lines
13 KiB
Bash
## -*- mode:sh -*- #
|
|
##==============================================================================
|
|
## Pacman Functions
|
|
##==============================================================================
|
|
|
|
## TODO: completion does not work as is. It requires pacman arguments like -S or
|
|
## -Q. There should be a way to use it.
|
|
# if [ "zsh" = "$SHELL_CURRENT" ]; then
|
|
# compdef _pacman pacman-deps
|
|
# if [ "bash" = "$SHELL_CURRENT" ]; then
|
|
# complete -o default -o nospace -F _pacman pacman-deps
|
|
# fi
|
|
|
|
## 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()
|
|
{
|
|
echo "Synopsis:"
|
|
echo -e " $1 [-n] PACKAGES"
|
|
echo
|
|
echo "Usage:"
|
|
echo -e " default:\tDisplay file size of PACKAGES."
|
|
echo -e " -h:\t\tDisplay this help."
|
|
echo -e " -n:\t\tSort by size."
|
|
}
|
|
|
|
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
|
|
|
|
local RESULT_HUMAN="$(du -bh $(pacman -Qlq "$@" | grep -v ".*/$" | sort -u) | eval ${OPTION_SORT})"
|
|
local RESULT="$(du -b $(pacman -Qlq "$@" | grep -v ".*/$" | sort -u))"
|
|
echo "${RESULT_HUMAN}"
|
|
|
|
echo "$RESULT" | awk -F "[[:alpha:]]" '{TOTAL=$1+TOTAL} END {printf("Total: %d KiB\n",TOTAL/1024)}'
|
|
}
|
|
|
|
## 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()
|
|
{
|
|
echo "Synopsis:"
|
|
echo -e " $1 [-m|-e] [-q] FILE"
|
|
echo
|
|
echo "Usage:"
|
|
echo -e " default:\tDisplay packages included in FILE but not installed."
|
|
echo -e " -e:\t\tCompare FILE to explicitly installed packages."
|
|
echo -e " -h:\t\tDisplay this help."
|
|
echo -e " -m:\t\tCompare FILE to foreign installed packages."
|
|
echo -e " -q:\t\tDisplay installed packages not included in FILE."
|
|
}
|
|
|
|
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()
|
|
{
|
|
echo "Synopsis:"
|
|
echo -e " $1 [-a|-h|-n|-q] PACKAGES"
|
|
echo -e " Arguments MUST be set before package list."
|
|
echo
|
|
echo "Usage:"
|
|
echo -e " default:\tDisplay 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."
|
|
echo -e " -h:\t\tShow this help."
|
|
echo -e " -n:\t\tOutput is sorted by size."
|
|
echo -e " -q:\t\tUses installed packages database instead of repos database. It speeds up queries and allows displaying size of local packages not available in repos."
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
## Print deps list.
|
|
pacman-deps()
|
|
{
|
|
_printhelp()
|
|
{
|
|
echo "Synopsis:"
|
|
echo -e " $1 [-a|-h|-q] [-r] PACKAGES"
|
|
echo -e " Arguments MUST be set before package list."
|
|
echo
|
|
echo "Usage:"
|
|
echo -e " default:\tDisplay package dependencies. Output contains no double and is alphabetically sorted. It will only work for repos packages by default."
|
|
echo -e " -a:\t\tUses Yaourt queries instead of repos database. It slows down query but allow displaying size of any packages not available in repos."
|
|
echo -e " -h:\t\tShow this help."
|
|
echo -e " -r:\t\tCall function recursively."
|
|
echo -e " -q:\t\tUses installed packages database instead of repos database. It speeds up queries and allows displaying size of local packages not available in repos."
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
abs-fetch ()
|
|
{
|
|
_printhelp ()
|
|
{
|
|
echo "Synopsis:"
|
|
echo -e " $1 [-hfy] PACKAGES"
|
|
echo
|
|
echo "Usage:"
|
|
echo -e " default:\tFetch PKGBUILDs from ABS-tree"
|
|
echo -e " -f:\t\tOverwrite folder if it exists."
|
|
echo -e " -h:\t\tDisplay this help."
|
|
echo -e " -y:\t\tUse 'yaourt' to fetch data."
|
|
echo
|
|
echo 'Noteworthy parameters:'
|
|
echo '* $(pacman-official)'
|
|
echo '* $(pacman -Qmq)'
|
|
echo '* $(pacman -Qq)'
|
|
}
|
|
|
|
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
|
|
}
|