#!/bin/sh # # Copyright (c) 2013 Bryan Drewery # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. usage() { cat </dev/null } BADFILES_LIST=$(mktemp -t poudriere_pkgclean) FOUND_ORIGINS=$(mktemp -t poudriere_pkgclean) for file in ${PACKAGES}/All/*; do case ${file} in *.${PKG_EXT}) pkgname="${file##*/}" pkgname="${pkgname%.*}" if ! pkg_get_origin origin "${file}"; then msg_verbose "Found corrupt package: ${file}" echo "${file}" >> ${BADFILES_LIST} elif ! pkgbase_is_needed "${pkgname}"; then msg_verbose "Found unwanted package: ${file}" echo "${file}" >> ${BADFILES_LIST} else echo "${file} ${origin}" >> ${FOUND_ORIGINS} fi ;; *) msg_verbose "Found incorrect format file: ${file}" echo "${file}" >> ${BADFILES_LIST} ;; esac done pkg_compare() { [ $# -eq 2 ] || eargs pkg_compare oldversion newversion local oldversion="$1" local newversion="$2" ensure_pkg_installed || err 1 \ "ports-mgmt/pkg is missing. First build it with bulk, then rerun pkgclean" injail ${PKG_VERSION} -t "${oldversion}" "${newversion}" } # Check for duplicated origins (older packages) and keep only newer ones # This also groups by pkgbase to respect DEPENDS_ARGS / PKGNAME uniqueness sort ${FOUND_ORIGINS} | awk ' { pkg = $1 origin = $2 # Determine pkgbase to group by n = split(pkg, a, "/") pkgbase = a[n] sub(/-[^-]*$/, "", pkgbase) origins[pkgbase] = origin if (!origin_count[pkgbase]) origin_count[pkgbase] = 0 if (packages[pkgbase]) packages[pkgbase] = packages[pkgbase] " " pkg else packages[pkgbase] = pkg origin_count[pkgbase] += 1 } END { for (pkgbase in origin_count) if (origin_count[pkgbase] > 1) print origins[pkgbase],packages[pkgbase] } ' | while mapfile_read_loop_redir origin packages; do lastpkg= lastver=0 for pkg in $packages; do pkgversion="${pkg##*-}" pkgversion="${pkgversion%.*}" if [ -z "${lastpkg}" ]; then lastpkg="${pkg}" lastver="${pkgversion}" continue fi pkg_compare="$(pkg_compare "${pkgversion}" "${lastver}")" case ${pkg_compare} in '>') msg_verbose "Found old package: ${lastpkg}" echo "${lastpkg}" >> ${BADFILES_LIST} lastpkg="${pkg}" lastver="${pkgversion}" ;; '<') msg_verbose "Found old package: ${pkg}" echo "${pkg}" >> ${BADFILES_LIST} ;; '=') # This should be impossible now due to the # earlier pkgbase_is_needed() comparison # (by PKGBASE) and that this check is grouped # by PKGBASE. Any renamed package is trimmed # out by the failed pkgbase_is_needed() check. err 1 "Found duplicated packages ${pkg} vs ${lastpkg} with origin ${origin}" ;; esac done msg_verbose "Keeping latest package: ${lastpkg##*/}" done ret=0 do_confirm_delete "${BADFILES_LIST}" "stale packages" \ "${answer}" "${DRY_RUN}" || ret=$? if [ ${ret} -eq 2 ]; then exit 0 fi # After deleting stale files, need to remake repo. if [ $ret -eq 1 ]; then [ "${NO_RESTRICTED}" != "no" ] && clean_restricted delete_stale_symlinks_and_empty_dirs delete_stale_pkg_cache if [ ${BUILD_REPO} -eq 1 ]; then if [ ${DO_ALL} -eq 1 ]; then msg "Removing pkg repository files" rm -f "${PACKAGES}/meta.txz" \ "${PACKAGES}/digests.txz" \ "${PACKAGES}/packagesite.txz" else build_repo fi fi if [ ${DO_ALL} -eq 1 ]; then msg "Cleaned all packages but ${PACKAGES} may need to be removed manually." fi fi run_hook pkgclean done ${ret} ${BUILD_REPO}