Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
executable file 194 lines (180 sloc) 5.2 KB
#!/bin/sh
set -e
usage() {
cat <<EOF
usage: `basename "$0"` [OPTIONS] [CABALDIR [ARCH-OS-ghc-VERSION]]
A script to help automate the process of removing unregistered Cabal packages.
As a precautionary measure, the script does not actually remove the packages
unless '-r' is specified. It is highly recommended to run this command
without '-r' first to make sure it doesn't remove anything important.
Note: packages whose name and version coincide with those of a
globally-installed package are not detected.
For a tutorial, see:
https://rufflewind.com/2015-02-01/cabal-gc
Options:
-h, --help Display this help
-r, --remove Remove the unregistered packages. It is highly
recommended to run this command without '-r' first to make
sure it doesn't remove anything important.
Arguments:
CABALDIR Path to the Cabal directory (default if empty: \$HOME/.cabal).
ARCH Architecture (e.g. x86_64)
OS Operating system (e.g. linux)
VERSION Version of GHC (e.g. 7.8.4)
EOF
}
# parse arguments
unset cabaldir
unset subdir
unset remove
parse=t
for arg
do
if [ "$parse" ]
then
case $arg in
-h|--help)
usage
exit 0;;
-r|--remove)
remove=t
continue;;
--)
parse=
continue;;
-*)
usage >&2
exit 1;;
esac
fi
if [ -z "${cabaldir+x}" ]
then
cabaldir=$arg
elif [ -z "${subdir+x}" ]
then
subdir=$arg
else
usage >&2
exit 1
fi
done
# detect reasonable defaults for cabaldir
if [ -z "$cabaldir" ]
then
if [ "$CABAL_SANDBOX_CONFIG" ]
then
if [ ! -f "$CABAL_SANDBOX_CONFIG" ]
then
prog=`basename "$0"`
printf >&2 '%s: cannot read: %s\n' "$prog" "$CABAL_SANDBOX_CONFIG"
printf >&2 '%s: note: CABAL_SANDBOX_CONFIG is set\n' "$prog"
exit 1
fi
filter='^[[:space:]]*prefix:'
pattern='s/^[[:space:]]*prefix:[[:space:]]*\(.*\)[[:space:]]*$/\1/'
cabaldir=`grep "$filter" "$CABAL_SANDBOX_CONFIG" | sed "$pattern"`
if [ ! -d "$cabaldir" ]
then
prog=`basename "$0"`
printf >&2 '%s: does not exist: %s\n' "$prog" "$cabaldir"
printf >&2 '%s: note: CABAL_SANDBOX_CONFIG is set\n' "$prog"
exit 1
fi
elif [ "$HOME" ] && [ -d "$HOME/.cabal" ]
then
cabaldir=$HOME/.cabal
elif [ "$APPDATA" ] && [ -d "$APPDATA/cabal" ]
then
cabaldir=$APPDATA/cabal
else
prog=`basename "$0"`
printf >&2 '%s: failed to detect Cabal directory\n' "$prog"
printf >&2 '%s: must specify CABALDIR argument \n' "$prog"
exit 1
fi
elif [ ! -d "$cabaldir" ]
then
prog=`basename "$0"`
printf >&2 '%s: directory does not exist: %s\n' "$prog" "$cabaldir"
exit 1
fi
# detect reasonable defaults for subdir
if [ -z "${subdir+x}" ]
then
pattern='s/.*[^0-9.]\([0-9]\{1,\}\(\.[0-9]\{1,\}\)*\).*/\1/'
version=`ghc --version | sed "$pattern"`
if [ -z "$version" ]
then
prog=`basename "$0"`
printf >&2 '%s: failed to detect version of GHC\n' "$prog"
printf >&2 '%s: must specify VERSION argument \n' "$prog"
exit 1
fi
unset subdir
for d in "$cabaldir/lib/"*"-ghc-$version"
do
if [ ! -d "$d" ]
then
continue
elif [ "${subdir+x}" ]
then
prog=`basename "$0"`
printf >&2 '%s: %s\n' "$prog" "not sure which one to use:"
for x in "$cabaldir/lib/"*"-ghc-$version"
do
printf >&2 ' %s\n' "$x"
done
printf >&2 '%s: must specify ARCH-OS-ghc-VERSION argument\n' \
"$prog"
exit 1
else
subdir=`basename "$d"`
fi
done
if [ -z "${subdir+x}" ]
then
prog=`basename "$0"`
printf >&2 '%s: %s\n' "$prog" \
"can't find package directory for ghc-$version"
printf >&2 '%s: must specify ARCH-OS-ghc-VERSION argument\n' "$prog"
exit 1
fi
fi
# find directories that don't correspond to any registered package
dumpfile=${TMP:-/tmp}/cabal-gc.hc-pkg-dump.tmp
if [ "$CABAL_SANDBOX_CONFIG" ]
then cabal sandbox hc-pkg dump >"$dumpfile"
else ghc-pkg dump >"$dumpfile"
fi
for group in lib share share/doc
do
dir=$cabaldir/$group/$subdir
if [ ! -d "$dir" ]
then
prog=`basename "$0"`
printf >&2 '%s: directory does not exist: %s\n' "$prog" "$dir"
exit 1
fi
for pkgpath in "$dir/"*
do
if [ ! -d "$pkgpath" ] # guard against empty blobs and unknown files
then
continue
fi
pkg=`basename "$pkgpath"`
case $group in
lib) pattern="key: $pkg";;
*) pattern="id: $pkg";;
esac
if grep "$pattern" "$dumpfile" >/dev/null 2>&1
then :
elif [ "$remove" ]
then
rm -r -- "$pkgpath"
printf "removed: %s\n" "$pkgpath"
else
printf "can be removed: %s\n" "$pkgpath"
fi
done
done
rm -f "$dumpfile"