blob: aa68300cafcafd497574f9214020d7b372729105 (
plain)
1 #!/bin/bash
2 #
3 # $Id: prtsweep,v 1.2 2003/12/17 21:17:02 opel Exp $
4 # (c) 2002, 2003 by Martin Opel <martin at obbl-net dot de>
5 # Revised 2021 by John McQuah <jmcquah at disroot dot org>
6 #
7 # May be redistributed and modified under the terms of the GPL
8 # only usable with CRUX Linux, version 1.0 or higher
9 #
10 # USE AT YOUR OWN RISK
11 #
12 # This script scans your supfiles in /etc/ports to find out your port
13 # directories and then scans all ports for old files, which are not part
14 # of the source-array in the Pkgfile and are not pkgfiles (name#version...).
15 # All these old files are removed. For details see "man 1 prtsweep".
16 #
17
18 info() {
19 echo -e "=======> $@"
20 }
21
22 msg() {
23 echo -e "+ $@"
24 }
25
26 error() {
27 info "ERROR: $@"
28 }
29
30 interrupted() {
31 info "exiting..."
32 exit 1
33 }
34
35 getportdirs() {
36 cat /etc/ports/*.{httpup,rsync} 2>/dev/null \
37 | awk -F= '$1=="destination" || $1=="ROOT_DIR" {print $2}'
38 }
39
40 remove() {
41 item=$1
42 if [ -f "$item" ]; then
43 if [ "$dryrun" = "1" ]; then
44 msg "removing file $item (dryrun)"
45 else
46 msg "removing file $item"
47 rm "$item"
48 fi
49 elif [ -d "$item" ]; then
50 if [ "$dryrun" = "1" ]; then
51 msg "removing directory $item (dryrun)"
52 else
53 msg "removing directory $item"
54 rm -r "$item"
55 fi
56 fi
57 }
58
59 removeemptydir() {
60 # called if the directory lacks a Pkgfile. Still need to check whether
61 # it is actually empty.
62 local baggage
63 baggage=(`find $1`)
64 if [ ${#baggage[@]} -eq 1 ]; then
65 remove $1
66 else
67 info "files still remaining in port directory '$1'!"
68 info "okay to remove them? (y/n)"
69 read CONSENT
70 if [ "$CONSENT" = "y" ]; then
71 for (( f=1; f<${#baggage[@]}; f++ )); do
72 remove ${baggage[$f]}
73 done
74 fi
75 fi
76 }
77
78 inlist() {
79 local excode
80 item=$1
81 shift
82 list="$@"
83 excode=1 # assume not in the list until proven otherwise
84
85 while [ "$#" -gt 0 ]; do
86 if [ "$item" = "$1" ]; then
87 excode=0
88 break
89 else
90 shift
91 fi
92 done
93
94 return $excode
95 }
96
97 PWD_filename() {
98 if [[ $1 =~ ^(http|https|ftp|file)://.*/(.+) ]]; then
99 echo "${BASH_REMATCH[2]}"
100 else
101 echo $1
102 fi
103 }
104
105 remote_filename() {
106 if [[ $1 =~ ^(http|https|ftp|file)://.*/(.+) ]]; then
107 echo "/remote/path/${BASH_REMATCH[2]}"
108 else
109 echo $1
110 fi
111 }
112
113 nsweep() {
114 dir=$1
115 reset_keepfiles
116 local printedpwd="false"
117 local name version source renames pkgfiles packagename packagepath subdir
118
119 if [ ! -d $dir ]; then
120 error "'`pwd`/$dir' is not a directory!"
121 usage
122 fi
123
124 if [ ! -f $dir/Pkgfile ]; then
125 info `pwd`/$dir
126 msg "no Pkgfile found, empty port '$dir'."
127 if [ "$delete" = "1" ]; then
128 removeemptydir $dir
129 else
130 msg "use '-d' to remove empty directories."
131 fi
132 return
133 fi
134
135 echo "sweeping the directory for port $dir"
136
137 # read the port information from its Pkgfile and save the results in a bash array.
138 # This loop assumes that renaming is only applied to files downloaded over http or ftp,
139 # not under version control systems like rsync or httpup. To preserve this information,
140 # an arbitrary URI scheme is prepended before the desired filename.
141 pkgfiles=(`( . $dir/Pkgfile; PKGLOC=$(eval "printf '%s' $PKGGLOB"); \
142 PKGFILE=$(eval "printf '%s' $BLTGLOB"); \
143 for (( p=0; p<${#source[@]}; p++ )); do \
144 [ -n "${renames[$p]}" -a "${renames[$p]}" != "SKIP" ] && source[$p]="ftp://somehost/${renames[$p]}"; \
145 done; echo "$PKGLOC/$PKGFILE"; \
146 printf '%s ' "${source[@]}" )`)
147
148 cd $dir
149 # (new feature in v0.5) remove the package too, if the user requests it with the "-p" flag
150 if [ "$pkgtoo" != "1" ]; then
151 packagename=`basename ${pkgfiles[0]}`
152 packagepath=`dirname ${pkgfiles[0]}`
153 if [ "${packagepath:0:1}" = "/" ]; then
154 KEEP_FILES="${KEEP_FILES} $packagename"
155 elif [ "${packagepath:0:1}" != "/" ]; then
156 subdir=$(echo $PKGLOC | sed "s|/.*||")
157 KEEP_FILES="${KEEP_FILES} $subdir"
158 fi
159 fi
160
161 # Now that we're safely out of the nested subshell, the URI scheme can be replaced.
162 # Make the new value match the `ls -A` output unless the user has requested
163 # removal of source files too.
164 if [ "$rmsources" = 1 ]; then
165 for (( p=1; p<${#pkgfiles[@]}; p++ )); do
166 pkgfiles[$p]=`remote_filename ${pkgfiles[$p]}`
167 done
168 else
169 for (( p=1; p<${#pkgfiles[@]}; p++ )); do
170 pkgfiles[$p]=`PWD_filename ${pkgfiles[$p]}`
171 done
172 fi
173
174 unset pkgfiles[0]
175 for f in `ls -A`; do
176 if [[ ! ${KEEP_FILES} =~ "$f" ]] && ! inlist "$f" ${pkgfiles[@]}; then
177 if [ "$printedpwd" = "false" ]; then
178 printedpwd="true"
179 info `pwd`
180 fi
181 remove $f
182 fi
183 done
184 cd - &>/dev/null
185 }
186
187 reset_keepfiles() {
188 KEEP_FILES="Pkgfile README pre-install post-install
189 .footprint .signature .32bit .nostrip"
190 }
191
192 getoptions() {
193 while [ "$1" = "-a" -o "$1" = "-d" -o "$1" = "-n" -o "$1" = "-p" -o "$1" = "-s" -o "$1" = "-q" ]; do
194 if [ "$1" = "-q" ]; then
195 quiet=1
196 shift
197 elif [ "$1" = "-s" ]; then
198 rmsources=1
199 shift
200 elif [ "$1" = "-p" ]; then
201 pkgtoo=1
202 shift
203 elif [ "$1" = "-n" ]; then
204 dryrun=1
205 shift
206 elif [ "$1" = "-d" ]; then
207 delete=1
208 shift
209 elif [ "$1" = "-a" ]; then
210 auto=1
211 shift
212 fi
213 done
214 ports="$@"
215
216 if [ -z "$ports" -a "$auto" != "1" ]; then
217 echo "You must explicitly call for automatic mode (-a) if you"
218 echo "do not provide the paths of ports you want cleaned."
219 usage
220 elif [ -n "$ports" -a "$auto" = "1" ]; then
221 echo "Automatic mode (-a) is incompatible with providing an"
222 echo "explicit list of ports to clean."
223 usage
224 fi
225
226 }
227
228 usage() {
229 echo
230 echo "Usage: prtsweep [-a] [-d] [-n] [-s] [-p] [-q] [PORTDIR ...]"
231 echo
232 exit 1
233 }
234
235 do_sweep() {
236 PKGGLOB=$(echo "$PKGGLOB" | sed 's/PortName/$name/')
237 BLTGLOB='$name#$version-$release.pkg.tar.$COMPRESSION_MODE'
238
239 if [ -z "$ports" -a "$auto" = "1" ]; then
240 for portdir in $collections; do
241 echo $portdir
242 cd $portdir
243 for dir in *; do
244 test -d $dir && nsweep $dir
245 done
246 done
247 elif [ -n "$ports" -a "$auto" != "1" ]; then
248 for dir in $ports; do
249 test -d $dir && nsweep $dir
250 done
251 else
252 usage
253 fi
254 exit 0
255 }
256
257 info_portsgiven() {
258 echo "$0 will not touch anything outside of the portdirs given on the command line,"
259 echo "but it looks like the debris from building your ports might be lying around somewhere else."
260 echo "Consider following up with another script."
261 echo "Press enter to continue."
262 read ACKNOWLEDGE
263 }
264
265 info_auto() {
266 echo "$0 will not touch anything outside of"
267 printf '%s\n' $collections
268 echo "but it looks like the debris from building your ports might be lying around somewhere else."
269 echo "Consider following up with another script."
270 echo "Press enter to continue."
271 read ACKNOWLEDGE
272 }
273
274 # Main work happens below
275 trap "interrupted" SIGHUP SIGINT SIGQUIT SIGTERM
276
277 getoptions $@
278
279 # First determine the directories that have been configured for downloads and built packages.
280 # Replace any references to $name so an unset shell variable won't cause information loss.
281 if [ -f /etc/pkgmk.conf ]; then
282 eval $(grep PKGMK_SOURCE_DIR /etc/pkgmk.conf | tail -n 1 | \
283 sed 's/PKGMK_SOURCE_DIR/SRCGLOB/; s/\$name/PortName/')
284 eval $(grep PKGMK_PACKAGE_DIR /etc/pkgmk.conf | tail -n 1 | \
285 sed 's/PKGMK_PACKAGE_DIR/PKGGLOB/; s/\$name/PortName/')
286 eval $(grep COMPRESSION_MODE /etc/pkgmk.conf | tail -n 1 | \
287 sed 's/PKGMK_//')
288 fi
289 # No custom setting for compression mode means that pkgmk falls back to the default, gzip.
290 [ -n "$COMPRESSION_MODE" ] || COMPRESSION_MODE="gz"
291
292 # Layouts 1 and 2: If all ports share a common directory (either for the sources or for
293 # the built packages), then this script might need to be supplemented by further cleaning.
294 # Suppress the warning if option -q (quiet mode) was given.
295 collections=`getportdirs`
296
297 if [ "$quiet" != "1" ]; then
298 if [ -n "$SRCGLOB" ] && echo "${SRCGLOB}" | grep -q -v 'PortName'; then
299 if [ -n "$ports" ]; then
300 info_portsgiven
301 elif [ "$auto" = 1 ]; then
302 info_auto
303 fi
304 do_sweep
305 fi
306 if [ -n "$PKGGLOB" ] && echo "${PKGGLOB}" | grep -q -v 'PortName'; then
307 if [ -n "$ports" ]; then
308 info_portsgiven
309 elif [ "$auto" = 1 ]; then
310 info_auto
311 fi
312 do_sweep
313 fi
314 fi
315
316 # Layout 3: the admin has left either PKGMK_SOURCE_DIR or PKGMK_PACKAGE_DIR at its default,
317 # or has defined at least one of them in terms of the port name. Do the sweep
318 # without issuing a warning (The option -q is not applicable for this layout).
319
320 do_sweep
|