summaryrefslogtreecommitdiff
path: root/contrib/paccache.sh.in
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/paccache.sh.in')
-rw-r--r--contrib/paccache.sh.in366
1 files changed, 0 insertions, 366 deletions
diff --git a/contrib/paccache.sh.in b/contrib/paccache.sh.in
deleted file mode 100644
index 02fae527..00000000
--- a/contrib/paccache.sh.in
+++ /dev/null
@@ -1,366 +0,0 @@
-#!/bin/bash
-#
-# pacache - flexible pacman cache cleaning
-#
-# Copyright (C) 2011 Dave Reisner <dreisner@archlinux.org>
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-
-shopt -s extglob
-
-declare -r myname='paccache'
-declare -r myver='@PACKAGE_VERSION@'
-
-declare -a cachedirs=() candidates=() cmdopts=() whitelist=() blacklist=()
-declare -i delete=0 dryrun=0 filecount=0 move=0 needsroot=0 totalsaved=0 verbose=0
-declare delim=$'\n' keep=3 movedir= scanarch=
-
-QUIET=0
-USE_COLOR='y'
-
-m4_include(../scripts/library/output_format.sh)
-m4_include(../scripts/library/parseopts.sh)
-
-die() {
- error "$@"
- exit 1
-}
-
-get_cachedir_from_config() {
- local key value
-
- while IFS=$'= \t' read -r key value _; do
- if [[ $key = CacheDir ]]; then
- echo "$value"
- return 0
- fi
- done <"$1"
-
- return 1
-}
-
-# reads a list of files on stdin and prints out deletion candidates
-pkgfilter() {
- # there's whitelist and blacklist parameters passed to this
- # script after the block of awk.
-
- awk -v keep="$1" -v scanarch="$2" '
- function basename(str) {
- sub(".*/", "", str);
- return str;
- }
-
- function parse_filename(filename, parts, count, i, pkgname, arch) {
-
- count = split(basename(filename), parts, "-")
-
- i = 1
- pkgname = parts[i++]
- while (i <= count - 3) {
- pkgname = pkgname "-" parts[i++]
- }
-
- arch = substr(parts[count], 1, index(parts[count], ".") - 1)
-
- # filter on whitelist or blacklist
- if (wlen && !whitelist[pkgname]) return
- if (blen && blacklist[pkgname]) return
-
- if ("" == packages[pkgname,arch]) {
- packages[pkgname,arch] = filename
- } else {
- packages[pkgname,arch] = packages[pkgname,arch] SUBSEP filename
- }
- }
-
- BEGIN {
- # create whitelist
- wlen = ARGV[1]; delete ARGV[1]
- for (i = 2; i < 2 + wlen; i++) {
- whitelist[ARGV[i]] = 1
- delete ARGV[i]
- }
-
- # create blacklist
- blen = ARGV[i]; delete ARGV[i]
- while (i++ < ARGC) {
- blacklist[ARGV[i]] = 1
- delete ARGV[i]
- }
-
- # read package filenames
- while (getline < "/dev/stdin") {
- parse_filename($0)
- }
-
- for (pkglist in packages) {
- # idx[1,2] = idx[pkgname,arch]
- split(pkglist, idx, SUBSEP)
-
- # enforce architecture match if specified
- if (!scanarch || scanarch == idx[2]) {
- count = split(packages[idx[1], idx[2]], pkgs, SUBSEP)
- for(i = 1; i <= count - keep; i++) {
- print pkgs[i]
- }
- }
- }
- }' "${@:3}"
-}
-
-m4_include(../scripts/library/size_to_human.sh)
-
-runcmd() {
- if (( needsroot && EUID != 0 )); then
- msg "Privilege escalation required"
- if sudo -v &>/dev/null && sudo -l &>/dev/null; then
- sudo "$@"
- else
- die 'Unable to escalate privileges using sudo'
- fi
- else
- "$@"
- fi
-}
-
-summarize() {
- (( QUIET )) && return
-
- local -i filecount=$1; shift
- local seenarch= seen= arch= name=
- local -r pkg_re='(.+)-[^-]+-[0-9]+-([^.]+)\.pkg.*'
-
- if (( delete )); then
- printf -v output 'finished: %d packages removed' "$filecount"
- elif (( move )); then
- printf -v output "finished: %d packages moved to '%s'" "$filecount" "$movedir"
- elif (( dryrun )); then
- if (( verbose )); then
- msg "Candidate packages:"
- while read -r pkg; do
- if (( verbose >= 3 )); then
- [[ $pkg =~ $pkg_re ]] && name=${BASH_REMATCH[1]} arch=${BASH_REMATCH[2]}
- if [[ -z $seen || $seenarch != "$arch" || $seen != "$name" ]]; then
- seen=$name seenarch=$arch
- printf '%s (%s):\n' "${name##*/}" "$arch"
- fi
- printf ' %s\n' "${pkg##*/}"
- elif (( verbose >= 2 )); then
- printf "%s$delim" "$pkg"
- else
- printf "%s$delim" "${pkg##*/}"
- fi
- done < <(printf '%s\n' "$@" | pacsort --files)
- fi
- printf -v output 'finished dry run: %d candidates' "$filecount"
- fi
-
- echo
- msg "$output (disk space saved: %s)" "$(size_to_human "$totalsaved")"
-}
-
-usage() {
- cat <<EOF
-${myname} (pacman) v${myver}
-
-A flexible pacman cache cleaning utility.
-
-Usage: ${myname} <operation> [options] [targets...]
-
- Operations:
- -d, --dryrun perform a dry run, only finding candidate packages.
- -m, --move <dir> move candidate packages to "dir".
- -r, --remove remove candidate packages.
-
- Options:
- -a, --arch <arch> scan for "arch" (default: all architectures).
- -c, --cachedir <dir> scan "dir" for packages. can be used more than once.
- (default: read from @sysconfdir@/pacman.conf).
- -f, --force apply force to mv(1) and rm(1) operations.
- -h, --help display this help message and exit.
- -i, --ignore <pkgs> ignore "pkgs", comma-separated. Alternatively, specify
- "-" to read package names from stdin, newline-
- delimited.
- -k, --keep <num> keep "num" of each package in the cache (default: 3).
- --nocolor remove color from output.
- -q, --quiet minimize output
- -u, --uninstalled target uninstalled packages.
- -v, --verbose increase verbosity. specify up to 3 times.
- -z, --null use null delimiters for candidate names (only with -v
- and -vv).
-
-EOF
-}
-
-version() {
- printf "%s %s\n" "$myname" "$myver"
- echo 'Copyright (C) 2011 Dave Reisner <dreisner@archlinux.org>'
-}
-
-OPT_SHORT=':a:c:dfhi:k:m:qrsuVvz'
-OPT_LONG=('arch:' 'cachedir:' 'dryrun' 'force' 'help' 'ignore:' 'keep:' 'move'
- 'nocolor' 'quiet' 'remove' 'uninstalled' 'version' 'verbose' 'null')
-
-if ! parseopts "$OPT_SHORT" "${OPT_LONG[@]}" -- "$@"; then
- exit 1
-fi
-set -- "${OPTRET[@]}"
-unset OPT_SHORT OPT_LONG OPTRET
-
-while :; do
- case $1 in
- -a|--arch)
- scanarch=$2
- shift ;;
- -c|--cachedir)
- cachedirs+=("$2")
- shift ;;
- -d|--dryrun)
- dryrun=1 ;;
- -f|--force)
- cmdopts=(-f) ;;
- -h|--help)
- usage
- exit 0 ;;
- -i|--ignore)
- if [[ $2 = '-' ]]; then
- [[ ! -t 0 ]] && IFS=$'\n' read -r -d '' -a ign
- else
- IFS=',' read -r -a ign <<< "$2"
- fi
- blacklist+=("${ign[@]}")
- unset i ign
- shift ;;
- -k|--keep)
- keep=$2
- if [[ -z $keep || -n ${keep//[0-9]/} ]]; then
- die 'argument to option -k must be a non-negative integer'
- else
- keep=$(( 10#$keep ))
- fi
- shift ;;
- -m|--move)
- move=1 movedir=$2
- shift ;;
- --nocolor)
- USE_COLOR='n' ;;
- -q|--quiet)
- QUIET=1 ;;
- -r|--remove)
- delete=1 ;;
- -u|--uninstalled)
- IFS=$'\n' read -r -d '' -a ign < <(pacman -Qq)
- # pacman -Qq may exit with an error, thus making ign an empty array
- (( ${#ign[@]} )) || die 'failed to retrieve the list of installed packages'
- blacklist+=("${ign[@]}")
- unset ign ;;
- -V|--version)
- version
- exit 0 ;;
- -v|--verbose)
- (( ++verbose )) ;;
- -z|--null)
- delim='\0' ;;
- --)
- shift
- break 2 ;;
- esac
- shift
-done
-
-m4_include(../scripts/library/term_colors.sh)
-
-# setting default cachedir
-if [[ -z $cachedirs ]]; then
- if cachedir=$(get_cachedir_from_config "@sysconfdir@/pacman.conf"); then
- cachedirs=("$cachedir")
- else
- cachedirs=("${cachedirs[@]:-@localstatedir@/cache/pacman/pkg}")
- fi
-fi
-
-# remaining args are a whitelist
-whitelist=("$@")
-
-# sanity checks
-case $(( dryrun+delete+move )) in
- 0) die "no operation specified (use -h for help)" ;;
- [^1]) die "only one operation may be used at a time" ;;
-esac
-
-[[ $movedir && ! -d $movedir ]] &&
- die "destination directory '%s' does not exist or is not a directory" "$movedir"
-
-if (( move || delete )); then
- # make it an absolute path since we're about to chdir
- [[ $movedir && ${movedir:0:1} != '/' ]] && movedir=$PWD/$movedir
- [[ $movedir && ! -w $movedir ]] && needsroot=1
-fi
-
-for cachedir in "${cachedirs[@]}"; do
- [[ -d $cachedir ]] ||
- die "cachedir '%s' does not exist or is not a directory" "$cachedir"
-
- if (( move || delete )); then
- [[ ! -w $cachedir ]] && needsroot=1
- fi
-
- # unlikely that this will fail, but better make sure
- pushd "$cachedir" &>/dev/null || die "failed to chdir to '%s'" "$cachedir"
-
- # note that these results are returned in an arbitrary order from awk, but
- # they'll be resorted (in summarize) iff we have a verbosity level set.
- IFS=$'\n' read -r -d '' -a cand < \
- <(printf '%s\n' "$PWD"/*.pkg.tar?(.+([^.])) | pacsort --files |
- pkgfilter "$keep" "$scanarch" \
- "${#whitelist[*]}" "${whitelist[@]}" \
- "${#blacklist[*]}" "${blacklist[@]}")
-
- candidates+=("${cand[@]}")
- unset cand
-
- popd &>/dev/null
-done
-
-if (( ! ${#candidates[*]} )); then
- msg 'no candidate packages found for pruning'
- exit 0
-fi
-
-# grab this prior to signature scavenging
-pkgcount=${#candidates[*]}
-
-# copy the list, merging in any found sigs
-for cand in "${candidates[@]}"; do
- candtemp+=("$cand")
- [[ -f $cand.sig ]] && candtemp+=("$cand.sig")
-done
-candidates=("${candtemp[@]}")
-unset candtemp
-
-# do this before we destroy anything
-totalsaved=$(@SIZECMD@ "${candidates[@]}" | awk '{ sum += $1 } END { print sum }')
-
-# crush. kill. destroy.
-(( verbose )) && cmdopts+=(-v)
-if (( delete )); then
- printf '%s\0' "${candidates[@]}" | runcmd xargs -0 rm "${cmdopts[@]}"
-elif (( move )); then
- printf '%s\0' "${candidates[@]}" | runcmd xargs -0 mv "${cmdopts[@]}" -t "$movedir"
-fi
-
-summarize "$pkgcount" "${candidates[@]}"
-
-# vim: set noet: