#!/bin/bash # # $Id: prtsweep,v 1.2 2003/12/17 21:17:02 opel Exp $ # (c) 2002, 2003 by Martin Opel # Revised 2021 by John McQuah # # 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