9311038c4f0b616d6b7ad1837d25a413edbfb3ff
[distro-functions] / src / package-manager-abstractions
1 #!/bin/bash
2 # Copyright (C) 2014 Ian Kelling
3
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7
8 # http://www.apache.org/licenses/LICENSE-2.0
9
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 # basic yum/apt package manager abstraction, plus a few minor conveniences
17 if command -v yum &> /dev/null; then
18 # package manager
19 p() {
20 local s; [[ $EUID != 0 ]] && s=sudo
21 $s yum "$@"
22 }
23 # package install
24 pi() {
25 local s; [[ $EUID != 0 ]] && s=sudo
26 $s yum -y install "$@"
27 }
28 # package find
29 pf() {
30 local s; [[ $EUID != 0 ]] && s=sudo
31 $s yum search "$@"
32 }
33 # package remove/uninstall
34 pu() {
35 local s; [[ $EUID != 0 ]] && s=sudo
36 $s yum autoremove "$@"
37 }
38 pup() { # upgrade
39 local s; [[ $EUID != 0 ]] && s=sudo
40 $s yum -y distro-sync full "$@"
41 }
42 # package list info
43 pl() {
44 yum info "$@"
45 }
46 pfile() {
47 yum whatprovides \*/$1
48 }
49
50 elif command -v apt-get &>/dev/null; then
51 plock-wait() {
52 local i
53 i=0
54 while fuser /var/lib/dpkg/lock &>/dev/null; do
55 sleep 1
56 i=$(( i+1 ))
57 if (( i > 300 )); then
58 echo "error: timed out waiting for /var/lib/dpkg/lock" >&2
59 return 1
60 fi
61 done
62 }
63 pcheck() {
64 for arg; do
65 if [[ $1 == -* ]]; then
66 shift
67 else
68 break
69 fi
70 done
71 if dpkg -s -- "$@" |& grep -Fx "Status: install ok installed" &>/dev/null; then
72 return 1
73 fi
74 return 0
75 }
76 pp() { # package policy
77 apt-cache policy $@
78 }
79 p() {
80 local s; [[ $EUID != 0 ]] && s=sudo
81 case $1 in
82 install)
83 $s apt-get --purge --auto-remove "$@"
84 ;;
85 *)
86 $s apt-get "$@"
87 ;;
88 esac
89 }
90 pupdate() {
91 local s f; [[ $EUID != 0 ]] && s=sudo
92 # update package list if its more than an 2 hours old
93 f=/var/cache/apt/pkgcache.bin
94 if [[ ! -r $f ]] \
95 || (( $(( $(date +%s) - $(stat -c %Y $f ) )) > 60*60*2 )); then
96 $s apt-get update
97 fi
98 }
99 pi() {
100 pcheck "$@" || return 0
101 pupdate
102 local s; [[ $EUID != 0 ]] && s=sudo
103 if [[ $- != *i* ]]; then
104 echo pi "$@"
105 fi
106 $s $PI_PREFIX apt-get -y install --purge --auto-remove "$@"
107 }
108
109 pi-nostart() {
110 local ret=
111 pcheck "$@" || return 0
112 plock-wait
113 pupdate
114 local s; [[ $EUID != 0 ]] && s=sudo
115 local f=/usr/sbin/policy-rc.d
116 $s dd of=$f 2>/dev/null <<EOF
117 #!/bin/sh
118 exit 101
119 EOF
120 $s chmod +x $f
121 if [[ $- != *i* ]]; then
122 echo pi-nostart "$@"
123 fi
124 $s apt-get -y install --purge --auto-remove "$@" || ret=$?
125 $s rm $f
126 return $ret
127 }
128 pf() {
129 # package name and descriptions
130 apt-cache search "$@"
131 }
132 pff() {
133 local s; [[ $EUID != 0 ]] && s=sudo
134 # nice aptitude search from emacs shell. package description width as
135 # wide as the screen, and package name field small aptitude
136 # manual can't figure out how wide emacs terminal is, of course
137 # it doesn't consult the $COLUMNS variable... and in a normal
138 # terminal, it makes the package name field ridiculously big
139 # also, remove that useless dash before the description
140 aptitude -F "%c%a%M %p %$((COLUMNS - 30))d" -w $COLUMNS search "$@"
141 }
142 pu() {
143 local s; [[ $EUID != 0 ]] && s=sudo
144 local needed=false
145 for arg; do
146 if dpkg -s -- "$arg" &>/dev/null; then
147 needed=true
148 break
149 fi
150 done
151 $needed || return 0
152 plock-wait
153 $s apt-get -y remove --purge --auto-remove "$@"
154 # seems slightly redundant, but it removes more stuff sometimes.
155 $s apt-get -y autoremove
156 }
157 pup() { # upgrade
158 plock-wait
159 pupdate
160 local s; [[ $EUID != 0 ]] && s=sudo
161 $s apt-get -y dist-upgrade --purge --auto-remove "$@"
162 $s apt-get -y autoremove
163 if [[ -e /usr/sbin/checkrestart ]]; then
164 $s /usr/sbin/checkrestart -p
165 fi
166 }
167 # package info
168 pl() {
169 if type -p aptitude &>/dev/null; then
170 aptitude show "$@"
171 else
172 apt-cache show "$@"
173 fi
174 }
175 pfile() {
176 local file=$1
177 # ucfq can tell us about config files which are not tracked
178 # with apt-file. but, for at least a few files I tested
179 # which are tracked with apt-file, ucfq doesn't show their
180 # package name. So, commenting this, waiting to find
181 # a config file only tracked by ucfq to see if it gives the
182 # package name and if I can identify this kind of file.
183 # if [[ $file == /* ]] && ! ucfq -w $file | grep ::: &>/dev/null; then
184 # ucfq $file
185
186 if [[ $file == */* ]]; then
187 apt-file find -x "$file"\$
188 else
189 apt-file find -x /"$file"\$
190 update-alternatives --list "$file" 2>/dev/null
191 fi
192 }
193 pkgfiles() {
194 if dpkg -s "$1" &>/dev/null; then
195 dpkg-query -L $1
196 else
197 apt-file -x list "^$1$"
198 fi
199 }
200
201 elif command -v pacman &>/dev/null; then
202 p() {
203 pacaur "$@"
204 }
205 pi() {
206 pacaur -S --noconfirm --needed --noedit "$@"
207 }
208 pf() {
209 pacaur -Ss "$@"
210 }
211 pu() {
212 pacaur -Rs --noconfirm "$@"
213 if p=$(pacaur -Qdtq); then
214 pacaur -Rs $p
215 fi
216 }
217 aurex() {
218 p="$1"
219 aur='https://aur.archlinux.org'
220 curl -s $aur/$(curl -s "$aur/rpc.php?type=info&arg=$p" \
221 | jq -r .results.URLPath) | tar xz
222 cd "$p"
223
224 }
225 pmirror() {
226 local s; [[ $EUID != 0 ]] && s=sudo
227 local x=$(mktemp)
228 curl -s "https://www.archlinux.org/mirrorlist/\
229 ?country=US&protocol=https&ip_version=4&ip_version=6&use_mirror_status=on" \
230 | sed -r 's/^[ #]*(Server *=)/\1/' > $x
231 if (( $(stat -c %s $x ) > 10 )); then
232 $s cp $x /etc/pacman.d/mirrorlist
233 rm $x
234 fi
235 }
236 pup() { # upgrade
237 local s; [[ $EUID != 0 ]] && s=sudo
238 # file_time + 24 hours > current_time
239 if ! (( $(stat -c%Y /etc/pacman.d/mirrorlist) + 60*60*24 > $(date +%s) ))
240 then
241 pmirror
242 fi
243 pacaur -Syu --noconfirm "$@"
244 }
245 # package info
246 pl() {
247 pacaur -Si "$@"
248 }
249 pfile() {
250 pkgfile "$1"
251 }
252 pkgfiles() {
253 if pacaur -Qs "^$1$" &>/dev/null; then
254 pacman -Ql $1
255 else
256 pkgfile -l $1
257 fi
258 }
259 fi