cruxports/prt-utils/prtsweep

316 lines
8.5 KiB
Bash

#!/bin/bash
#
# $Id: prtsweep,v 1.2 2003/12/17 21:17:02 opel Exp $
# (c) 2002, 2003 by Martin Opel <martin at obbl-net dot de>
# Revised 2021 by John McQuah <jmcquah at disroot dot org>
#
# May be redistributed and modified under the terms of the GPL
# only usable with CRUX Linux, version 1.0 or higher
#
# USE AT YOUR OWN RISK
#
# This script scans your supfiles in /etc/ports to find out your port
# directories and then scans all ports for old files, which are not part
# of the source-array in the Pkgfile and are not pkgfiles (name#version...).
# All these old files are removed. For details see "man 1 prtsweep".
#
info() {
echo -e "=======> $@"
}
msg() {
echo -e "+ $@"
}
error() {
info "ERROR: $@"
}
interrupted() {
info "exiting..."
exit 1
}
getportdirs() {
cat /etc/ports/*.{httpup,rsync} 2>/dev/null \
| awk -F= '$1=="destination" || $1=="ROOT_DIR" {print $2}'
}
remove() {
item=$1
if [ -f "$item" ]; then
if [ "$dryrun" = "1" ]; then
msg "removing file $item (dryrun)"
else
msg "removing file $item"
rm "$item"
fi
elif [ -d "$item" ]; then
if [ "$dryrun" = "1" ]; then
msg "removing directory $item (dryrun)"
else
msg "removing directory $item"
rm -r "$item"
fi
fi
}
removeemptydir() {
# called if the directory lacks a Pkgfile. Still need to check whether
# it is actually empty.
local baggage
baggage=(`find $1`)
if [ ${#baggage[@]} -eq 1 ]; then
remove $1
else
info "files still remaining in port directory '$1'!"
info "okay to remove them? (y/n)"
read CONSENT
if [ "$CONSENT" = "y" ]; then
for (( f=1; f<${#baggage[@]}; f++ )); do
remove ${baggage[$f]}
done
fi
fi
}
inlist() {
local excode
item=$1
shift
list="$@"
excode=1 # assume not in the list until proven otherwise
while [ "$#" -gt 0 ]; do
if [ "$item" = "$1" ]; then
excode=0
break
else
shift
fi
done
return $excode
}
PWD_filename() {
if [[ $1 =~ ^(http|https|ftp|file)://.*/(.+) ]]; then
echo "${BASH_REMATCH[2]}"
else
echo $1
fi
}
remote_filename() {
if [[ $1 =~ ^(http|https|ftp|file)://.*/(.+) ]]; then
echo "/remote/path/${BASH_REMATCH[2]}"
else
echo $1
fi
}
nsweep() {
dir=$1
reset_keepfiles
local printedpwd="false"
local name version source renames pkgfiles packagename packagepath subdir
if [ ! -d $dir ]; then
error "'`pwd`/$dir' is not a directory!"
usage
fi
if [ ! -f $dir/Pkgfile ]; then
info `pwd`/$dir
msg "no Pkgfile found, empty port '$dir'."
if [ "$delete" = "1" ]; then
removeemptydir $dir
else
msg "use '-d' to remove empty directories."
fi
return
fi
echo "sweeping the directory for port $dir"
# read the port information from its Pkgfile and save the results in a bash array.
# This loop assumes that renaming is only applied to files downloaded over http or ftp,
# not under version control systems like rsync or httpup. To preserve this information,
# an arbitrary URI scheme is prepended before the desired filename.
pkgfiles=(`( . $dir/Pkgfile; PKGLOC=$(eval "printf '%s' $PKGGLOB"); \
PKGFILE=$(eval "printf '%s' $BLTGLOB"); \
for (( p=0; p<${#source[@]}; p++ )); do \
[ -n "${renames[$p]}" -a "${renames[$p]}" != "SKIP" ] && source[$p]="ftp://somehost/${renames[$p]}"; \
done; echo "$PKGLOC/$PKGFILE"; \
printf '%s ' "${source[@]}" )`)
cd $dir
# (new feature in v0.5) remove the package too, if the user requests it with the "-p" flag
if [ "$pkgtoo" != "1" ]; then
packagename=`basename ${pkgfiles[0]}`
packagepath=`dirname ${pkgfiles[0]}`
if [ "${packagepath:0:1}" = "/" ]; then
KEEP_FILES="${KEEP_FILES} $packagename"
elif [ "${packagepath:0:1}" != "/" ]; then
subdir=$(echo $PKGLOC | sed "s|/.*||")
KEEP_FILES="${KEEP_FILES} $subdir"
fi
fi
# Now that we're safely out of the nested subshell, the URI scheme can be replaced.
# Make the new value match the `ls -A` output unless the user has requested
# removal of source files too.
if [ "$rmsources" = 1 ]; then
for (( p=1; p<${#pkgfiles[@]}; p++ )); do
pkgfiles[$p]=`remote_filename ${pkgfiles[$p]}`
done
else
for (( p=1; p<${#pkgfiles[@]}; p++ )); do
pkgfiles[$p]=`PWD_filename ${pkgfiles[$p]}`
done
fi
unset pkgfiles[0]
for f in `ls -A`; do
if [[ ! ${KEEP_FILES} =~ "$f" ]] && ! inlist "$f" ${pkgfiles[@]}; then
if [ "$printedpwd" = "false" ]; then
printedpwd="true"
info `pwd`
fi
remove $f
fi
done
cd - &>/dev/null
}
reset_keepfiles() {
KEEP_FILES="Pkgfile README pre-install post-install
.footprint .signature .32bit .nostrip"
}
getoptions() {
while [ "$1" = "-a" -o "$1" = "-d" -o "$1" = "-n" -o "$1" = "-p" -o "$1" = "-s" -o "$1" = "-q" ]; do
if [ "$1" = "-q" ]; then
quiet=1
shift
elif [ "$1" = "-s" ]; then
rmsources=1
shift
elif [ "$1" = "-p" ]; then
pkgtoo=1
shift
elif [ "$1" = "-n" ]; then
dryrun=1
shift
elif [ "$1" = "-d" ]; then
delete=1
shift
elif [ "$1" = "-a" ]; then
auto=1
shift
fi
done
ports="$@"
if [ -z "$ports" -a "$auto" != "1" ]; then
echo "You must explicitly call for automatic mode (-a) if you"
echo "do not provide the paths of ports you want cleaned."
usage
elif [ -n "$ports" -a "$auto" = "1" ]; then
echo "Automatic mode (-a) is incompatible with providing an"
echo "explicit list of ports to clean."
usage
fi
}
usage() {
echo
echo "Usage: prtsweep [-a] [-d] [-n] [-s] [-p] [-q] [PORTDIR ...]"
echo
exit 1
}
do_sweep() {
if [ -z "$ports" -a "$auto" = "1" ]; then
for portdir in $collections; do
echo $portdir
cd $portdir
for dir in *; do
test -d $dir && nsweep $dir
done
done
elif [ -n "$ports" -a "$auto" != "1" ]; then
for dir in $ports; do
test -d $dir && nsweep $dir
done
else
usage
fi
exit 0
}
info_portsgiven() {
echo "$0 will not touch anything outside of the portdirs given on the command line,"
echo "but it looks like the debris from building your ports might be lying around somewhere else."
echo "Consider following up with another script."
echo "Press enter to continue."
read ACKNOWLEDGE
}
info_auto() {
echo "$0 will not touch anything outside of"
printf '%s\n' $collections
echo "but it looks like the debris from building your ports might be lying around somewhere else."
echo "Consider following up with another script."
echo "Press enter to continue."
read ACKNOWLEDGE
}
# Main work happens below
trap "interrupted" SIGHUP SIGINT SIGQUIT SIGTERM
getoptions $@
# First determine the directories that have been configured for downloads and built packages.
if [ -f /etc/pkgmk.conf ]; then
SRCGLOB=$(grep PKGMK_SOURCE_DIR /etc/pkgmk.conf | sed "s/[\t w]*#.*//; s/.*=//")
PKGGLOB=$(grep PKGMK_PACKAGE_DIR /etc/pkgmk.conf | sed "s/[\t w]*#.*//; s/.*=//")
COMPRESSION_MODE=$(grep COMPRESSION_MODE /etc/pkgmk.conf | sed "s/[\t w]*#.*//; s/.*=//")
fi
# No custom setting for compression mode means that pkgmk falls back to the default, gzip.
[ -n "$COMPRESSION_MODE" ] || COMPRESSION_MODE="gz"
BLTGLOB='$name#$version-$release.pkg.tar.$COMPRESSION_MODE'
# Layouts 1 and 2: If all ports share a common directory (either for the sources or for
# the built packages), then this script might need to be supplemented by further cleaning.
# Suppress the warning if option -q (quiet mode) was given.
collections=`getportdirs`
if [ "$quiet" != "1" ]; then
if [ -n "$SRCGLOB" ] && echo "${SRCGLOB}" | grep -q -v '\$name'; then
if [ -n "$ports" ]; then
info_portsgiven
elif [ "$auto" = 1 ]; then
info_auto
fi
do_sweep
fi
if [ -n "$PKGGLOB" ] && echo "${PKGGLOB}" | grep -q -v '\$name'; then
if [ -n "$ports" ]; then
info_portsgiven
elif [ "$auto" = 1 ]; then
info_auto
fi
do_sweep
fi
fi
# Layout 3: the admin has left either PKGMK_SOURCE_DIR or PKGMK_PACKAGE_DIR at its default,
# or has defined at least one of them in terms of the port name. Do the sweep
# without issuing a warning (The option -q is not applicable for this layout).
do_sweep