2 # I, Ian Kelling, follow the GNU license recommendations at
3 # https://www.gnu.org/licenses/license-recommendations.en.html. They
4 # recommend that small programs, < 300 lines, be licensed under the
5 # Apache License 2.0. This file contains or is part of one or more small
6 # programs. If a small program grows beyond 300 lines, I plan to switch
9 # Copyright 2024 Ian Kelling
11 # Licensed under the Apache License, Version 2.0 (the "License");
12 # you may not use this file except in compliance with the License.
13 # You may obtain a copy of the License at
15 # http://www.apache.org/licenses/LICENSE-2.0
17 # Unless required by applicable law or agreed to in writing, software
18 # distributed under the License is distributed on an "AS IS" BASIS,
19 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 # See the License for the specific language governing permissions and
21 # limitations under the License.
23 # basic yum/apt package manager abstraction, plus a few minor conveniences
24 if command -v yum
&> /dev
/null
; then
27 local s
; [[ $EUID != 0 ]] && s
=sudo
32 local s
; [[ $EUID != 0 ]] && s
=sudo
33 $s yum
-y install "$@"
37 local s
; [[ $EUID != 0 ]] && s
=sudo
40 # package remove/uninstall
42 local s
; [[ $EUID != 0 ]] && s
=sudo
43 $s yum autoremove
"$@"
45 # shellcheck disable=SC2120
47 local s
; [[ $EUID != 0 ]] && s
=sudo
48 $s yum
-y distro-sync full
"$@"
55 yum whatprovides \
*/$1
58 elif command -v apt-get
&>/dev
/null
; then
62 while fuser
/var
/lib
/dpkg
/lock
&>/dev
/null
; do
65 if (( i
> 300 )); then
66 echo "error: timed out waiting for /var/lib/dpkg/lock" >&2
73 if [[ $1 == -* ]]; then
79 if dpkg
-s -- "$@" |
& grep -Fx "Status: install ok installed" &>/dev
/null
; then
84 pp
() { # package policy
88 local s
; [[ $EUID != 0 ]] && s
=sudo
91 $s apt-get
--purge --auto-remove "$@"
99 local now t s f cachetime limittime
; [[ $EUID != 0 ]] && s
=sudo
100 # update package list if its more than an 2 hours old
101 f
=/var
/cache
/apt
/pkgcache.bin
103 cachetime
=$
(stat
-c %Y
$f )
108 limittime
=$
(( now
- 60*60*2 ))
109 for f
in /etc
/apt
/sources.list
/etc
/apt
/sources.list.d
/*.list
; do
112 if (( t
> limittime
)); then
117 if (( cachetime
> limittime
)); then
122 pcheck
"$@" ||
return 0
124 if [[ $
- != *i
* ]]; then
127 if [[ $EUID == 0 ]]; then
128 DEBIAN_FRONTEND
=noninteractive apt-get
-y install --purge --auto-remove "$@"
130 sudo DEBIAN_FRONTEND
=noninteractive apt-get
-y install --purge --auto-remove "$@"
137 pcheck
"$@" ||
return 0
140 local f
=/usr
/sbin
/policy-rc.d
141 if [[ $
- != *i
* ]]; then
144 if [[ $EUID == 0 ]]; then
145 dd of
=$f status
=none
<<EOF
150 DEBIAN_FRONTEND
=noninteractive apt-get
-y install --purge --auto-remove "$@" || ret
=$?
153 sudo
dd of
=$f status
=none
<<EOF
158 sudo DEBIAN_FRONTEND
=noninteractive apt-get
-y install --purge --auto-remove "$@" || ret
=$?
163 # package find description
165 # package name and descriptions
166 apt-cache search
"$@"
170 local s
; [[ $EUID != 0 ]] && s
=sudo
171 # nice aptitude search from emacs shell. package description width as
172 # wide as the screen, and package name field small aptitude
173 # manual can't figure out how wide emacs terminal is, of course
174 # it doesn't consult the $COLUMNS variable... and in a normal
175 # terminal, it makes the package name field ridiculously big
176 # also, remove that useless dash before the description
177 aptitude
-F "%c%a%M %p %$((COLUMNS - 30))d" -w $COLUMNS search
"$@"
180 local s
; [[ $EUID != 0 ]] && s
=sudo
183 if dpkg
-s -- "$arg" &>/dev
/null
; then
190 $s apt-get
-y remove
--purge --auto-remove "$@"
191 # seems slightly redundant, but it removes more stuff sometimes.
192 $s apt-get
-y autoremove
194 # shellcheck disable=SC2120
198 local s
; [[ $EUID != 0 ]] && s
=sudo
199 $s apt-get
-y dist-upgrade
--purge --auto-remove "$@"
200 $s apt-get
-y autoremove
204 if type -p aptitude
&>/dev
/null
; then
211 # -a = search all repos
221 # ucfq can tell us about config files which are not tracked
222 # with apt-file. but, for at least a few files I tested
223 # which are tracked with apt-file, ucfq doesn't show their
224 # package name. So, commenting this, waiting to find
225 # a config file only tracked by ucfq to see if it gives the
226 # package name and if I can identify this kind of file.
227 # if [[ $file == /* ]] && ! ucfq -w $file | grep ::: &>/dev/null; then
230 if [[ $file == /* ]]; then
234 arg
=(--filter-origins "$(positive-origins)")
236 if [[ $file == /* ]]; then
237 apt-file
"${arg[@]}" find -x /"$file"\$
238 update-alternatives
--list "$file" 2>/dev
/null
240 apt-file
"${arg[@]}" find -x "$file"\$
245 if dpkg
-s "$1" &>/dev
/null
; then
246 dpkg-query
-L $1 |
while read -r l
; do [[ -f $l ]] && printf "%s\n" "$l"; done
248 apt-file
-x list
"^$1$"
252 elif command -v pacman
&>/dev
/null
; then
257 pacaur
-S --noconfirm --needed --noedit "$@"
263 pacaur
-Rs --noconfirm "$@"
264 if p
=$
(pacaur
-Qdtq); then
270 aur
='https://aur.archlinux.org'
271 curl
-s $aur/"$(curl -s "$aur/rpc.php?
type=info
&arg
=$p" \
272 | jq -r .results.URLPath)" |
tar xz
277 local s
; [[ $EUID != 0 ]] && s
=sudo
280 curl
-s "https://www.archlinux.org/mirrorlist/\
281 ?country=US&protocol=https&ip_version=4&ip_version=6&use_mirror_status=on" \
282 |
sed -r 's/^[ #]*(Server *=)/\1/' > $x
283 if (( $
(stat
-c %s
$x ) > 10 )); then
284 $s cp $x /etc
/pacman.d
/mirrorlist
288 # shellcheck disable=SC2120
290 local s
; [[ $EUID != 0 ]] && s
=sudo
291 # file_time + 24 hours > current_time
292 if ! (( $
(stat
-c%Y
/etc
/pacman.d
/mirrorlist
) + 60*60*24 > $
(date +%s
) ))
296 pacaur
-Syu --noconfirm "$@"
306 if pacaur
-Qs "^$1$" &>/dev
/null
; then