6c25dec844
This is based on the decision The NetBSD Foundation made in 2008 to do so, which was already applied to src. This change has been applied to code which is likely not in other repositories. ok board@, reviewed by riastradh@
437 lines
13 KiB
Bash
Executable file
437 lines
13 KiB
Bash
Executable file
#!/bin/sh
|
|
#
|
|
# $NetBSD: binpkg-cache,v 1.22 2018/08/22 20:48:37 maya Exp $
|
|
#
|
|
# Script for generating a cache file with information about
|
|
# all binary packages contained in a directory.
|
|
#
|
|
# Copyright (c) 2005, 2006 The NetBSD Foundation, Inc.
|
|
# All rights reserved.
|
|
#
|
|
# This code is derived from software contributed to The NetBSD Foundation
|
|
# by Dan McMahill.
|
|
#
|
|
# 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
|
|
#
|
|
|
|
|
|
TMPDIR=${TMPDIR:-/tmp}
|
|
PACKAGES=${PACKAGES:-/usr/pkgsrc/packages/}
|
|
AWK=${AWK:-awk}
|
|
CMP=${CMP:-cmp}
|
|
FIND=${FIND:-find}
|
|
GREP=${GREP:-grep}
|
|
GZIP_CMD=${GZIP_CMD:-gzip}
|
|
BZIP2=${BZIP2:-bzip2}
|
|
PKG_INFO=${PKG_INFO:-pkg_info}
|
|
PKG_SUFX=${PKG_SUFX:-.tgz}
|
|
SED=${SED:-sed}
|
|
SORT=${SORT:-sort}
|
|
STAT=${STAT:-stat}
|
|
|
|
cachefile=.pkgcache
|
|
summaryfile=pkg_summary
|
|
cacheversion=20050428
|
|
|
|
prompt="----> "
|
|
tab=" "
|
|
|
|
tmpd=${TMPDIR}/pkg-cache.$$
|
|
mkdir -m 0700 ${tmpd}
|
|
if test $? -ne 0 ; then
|
|
echo "ERROR: Could not create temporary directory ${tmpd}"
|
|
echo "Either you do not have write permission to ${tmpd} or"
|
|
echo "${tmpd} already exists"
|
|
exit 1
|
|
fi
|
|
all_dirs=${tmpd}/all_dirs
|
|
|
|
prog=$0
|
|
|
|
usage(){
|
|
echo "$prog - Generates cache files for each directory containing binary"
|
|
echo " packages. This cache file can then be used by the README.html"
|
|
echo " generation code to avoid having to call pkg_info(1) over and over"
|
|
echo " on the same binary package. In addition, pkg_summary.gz files for"
|
|
echo " use by the pkgtools/pkg_chk pacakge may be generated."
|
|
echo " "
|
|
echo "Usage: $prog [-d|--debug] [-v|--verbose] [-s|--summary] [-p|--packages <dir>]"
|
|
echo " "
|
|
echo " $prog -h|--help"
|
|
echo " "
|
|
echo " $prog -V|--version"
|
|
echo " "
|
|
echo "The options supported by $prog are: "
|
|
echo " "
|
|
echo " -d|--debug Enables debugging output"
|
|
echo " "
|
|
echo " -F|--force Forces a rebuild of the cache files even if they are"
|
|
echo " otherwise up to date."
|
|
echo " "
|
|
echo " -h|--help Displays this help message"
|
|
echo " "
|
|
echo " -p|--packages <dir> Specifies the top level directory to be searched"
|
|
echo " for binary packages."
|
|
echo " "
|
|
echo " -s|--summary Enables the creation of pkg_summary.gz files in each"
|
|
echo " directory containing binary packages. The pkg_summary.gz"
|
|
echo " file is used by the pkgtools/pkg_chk package."
|
|
echo " "
|
|
echo " -v|--verbose Enables verbose output from the script."
|
|
echo " "
|
|
echo " -V|--version Displays the version of this script and exits."
|
|
echo " "
|
|
echo "Returns 0 on success, 1 on errors, 2 if the packages"
|
|
echo "directory does not exist."
|
|
echo " "
|
|
echo "Example: $prog -v --packages /usr/pkgsrc/packages"
|
|
echo " "
|
|
}
|
|
|
|
clean_and_exit0(){
|
|
rm -fr ${tmpd}
|
|
exit 0
|
|
}
|
|
|
|
clean_and_exit1(){
|
|
rm -fr ${tmpd}
|
|
exit 1
|
|
}
|
|
|
|
clean_and_exit2(){
|
|
rm -fr ${tmpd}
|
|
exit 2
|
|
}
|
|
|
|
all_cache_files=""
|
|
|
|
#############################################################################
|
|
#
|
|
# process_binpkg_dir()
|
|
#
|
|
# Process a directory by checking to see if a cache file exists. If the
|
|
# cache file exists, make sure it is up to date. If the file does not
|
|
# exist, create one.
|
|
#
|
|
# also keep track of this directory so it can be added to the master
|
|
# cache.
|
|
#
|
|
|
|
process_binpkg_dir(){
|
|
rdir=`${GREP} "^${d} " ${all_dirs} | ${AWK} '{print $2}'`
|
|
need_update=no
|
|
if test -f ${d}/${cachefile} ; then
|
|
stale_entries=`${FIND} ${d} -type f -name \*${PKG_SUFX} -newer ${d}/${cachefile} -print`
|
|
|
|
# FIX_ME
|
|
#
|
|
# We also should find cache entries for files which no longer exist
|
|
# and nuke them. Right now we simply declare the entire cache out
|
|
# of date. Once we implement incremental updates to the cache,
|
|
# we need to remove the entries but not mark the entire cache as
|
|
# bad.
|
|
$if_debug echo " Checking for cache entries with no corresponding pkg."
|
|
# get the list of what pkgs belong in the cache
|
|
rm -f ${tmpd}/pkg_list ${tmpd}/cache_pkg_list
|
|
${FIND} ${d}/ -name \*${PKG_SUFX} -print | \
|
|
${SED} -e "s;^${d}/*;${rdir}/;g" -e 's;//;/;g' | \
|
|
${SORT} > ${tmpd}/pkg_list
|
|
|
|
# and get the list of what is in the cache
|
|
${AWK} '/pkgcache_begin/ {gsub(/pkgcache_begin[ \t]*/, ""); print}' \
|
|
${d}/${cachefile} | ${SORT} > ${tmpd}/cache_pkg_list
|
|
|
|
if ${CMP} -s ${tmpd}/pkg_list ${tmpd}/cache_pkg_list ; then
|
|
$if_debug echo " No extra cache entries in ${d}/${cachefile}"
|
|
else
|
|
$if_debug echo "Package list:"
|
|
$if_debug cat ${tmpd}/pkg_list
|
|
$if_debug echo "Cache list:"
|
|
$if_debug cat ${tmpd}/cache_pkg_list
|
|
echo " Entries found in ${d}/${cachefile} but no packages found"
|
|
need_update=yes
|
|
fi
|
|
else
|
|
stale_entries=""
|
|
fi
|
|
|
|
if test "X${force}" = "Xyes" -o "X${need_update}" = "Xyes" ; then
|
|
need_update=yes
|
|
echo "${tab}Forcing rebuild of cache ${d}/${cachefile}."
|
|
elif test ! -f ${d}/${cachefile} ; then
|
|
need_update=yes
|
|
echo "${tab}Missing cache file. ${d}/${cachefile} will be generated."
|
|
elif test -n "${stale_entries}" ; then
|
|
need_update=yes
|
|
echo "${tab}Stale cache file. ${d}/${cachefile} will be regenerated."
|
|
else
|
|
${GREP} "pkgcache_version ${cacheversion}" ${d}/${cachefile} >/dev/null 2>&1
|
|
if test $? -ne 0 ; then
|
|
need_update=yes
|
|
echo "${tab}Invalid version cache file. ${d}/${cachefile} will be regenerated."
|
|
echo "Need version ${cacheversion} but the file has"
|
|
${GREP} "^pkgcache_version " ${d}/${cachefile}
|
|
else
|
|
$if_verbose echo "${tab}Cache file ${d}/${cachefile} is up to date."
|
|
fi
|
|
fi
|
|
|
|
if test "${build_summary}" = "yes" -a ! -f ${d}/${summaryfile}.gz ; then
|
|
echo "${tab}Summary file ${d}/${summaryfile}.gz is missing and will be created."
|
|
need_update=yes
|
|
fi
|
|
if test "${build_summary}" = "yes" -a ${d}/${summaryfile}.gz -ot ${d}/${cachefile} ; then
|
|
echo "${tab}Summary file ${d}/${summaryfile}.gz is out of date and will be regenerated."
|
|
need_update=yes
|
|
fi
|
|
|
|
# FIX_ME
|
|
# We should use stale_entries in a way where we only update the
|
|
# cache file entries corresponding to these if we're rebuilding
|
|
# due to stale entries. That should save a good bit of time.
|
|
#
|
|
if test "X${need_update}" = "Xyes" ; then
|
|
echo "pkgcache_version ${cacheversion}" > ${tmpd}/${cachefile}
|
|
rm -f ${tmpd}/${summaryfile}
|
|
touch ${tmpd}/${summaryfile}
|
|
for f in ${d}/*${PKG_SUFX} ; do
|
|
fn=`grep "^${d} " ${all_dirs} | ${AWK} '{print $2}'`"/"`basename ${f}`
|
|
$if_debug echo " Adding ${fn} (${f}) to the cache"
|
|
echo " " >> ${tmpd}/${cachefile}
|
|
# stat(1) needs to be added to the bootstrap kit
|
|
# first if we want to use it here
|
|
#eval $(${STAT} -s ${f} 2>/dev/null)
|
|
echo "pkgcache_begin ${fn}" >> ${tmpd}/${cachefile}
|
|
#echo "pkgcache_mtime=${st_mtime}" >> ${tmpd}/${cachefile}
|
|
|
|
$if_debug echo "${PKG_INFO} -q -B ${f}"
|
|
${PKG_INFO} -q -B ${f} >> ${tmpd}/${cachefile}
|
|
|
|
if test "${build_summary}" = "yes" ; then
|
|
$if_debug echo "${PKG_INFO} -X ${f}"
|
|
${PKG_INFO} -X ${f} >> ${tmpd}/${summaryfile}
|
|
fi
|
|
echo "pkgcache_end ${fn}" >> ${tmpd}/${cachefile}
|
|
done
|
|
if test -f ${d}/${cachefile} ; then
|
|
rm -f ${d}/${cachefile}
|
|
fi
|
|
mv -f ${tmpd}/${cachefile} ${d}/${cachefile}
|
|
if test $? -ne 0 ; then
|
|
echo "********** WARNING **********"
|
|
echo "move of ${tmpd}/${cachefile} to ${d}/${cachefile} failed!"
|
|
echo "Perhaps you do not have write permissions to ${d}?"
|
|
echo "This directory will be dropped from the master cache file."
|
|
echo "********** WARNING **********"
|
|
return
|
|
fi
|
|
|
|
if test "${build_summary}" = "yes" ; then
|
|
if test -f ${d}/${summaryfile}.gz ; then
|
|
rm -f ${d}/${summaryfile}.gz
|
|
fi
|
|
cat ${tmpd}/${summaryfile} | ${GZIP_CMD} > ${d}/${summaryfile}.gz
|
|
if test $? -ne 0 ; then
|
|
echo "********** WARNING **********"
|
|
echo "${GZIP_CMD} of ${tmpd}/${summaryfile} to ${d}/${summaryfile}.gz failed!"
|
|
echo "Perhaps you do not have write permissions to ${d}?"
|
|
echo "********** WARNING **********"
|
|
return
|
|
fi
|
|
# if it's there, update it, otherwise don't bother
|
|
if test -f ${d}/${summaryfile}.bz2 ; then
|
|
rm -f ${d}/${summaryfile}.bz2
|
|
cat ${tmpd}/${summaryfile} | ${BZIP2} > ${d}/${summaryfile}.bz2
|
|
if test $? -ne 0 ; then
|
|
echo "********** WARNING **********"
|
|
echo "${BZIP2} of ${tmpd}/${summaryfile} to ${d}/${summaryfile}.bz2 failed!"
|
|
echo "Perhaps you do not have write permissions to ${d}?"
|
|
echo "********** WARNING **********"
|
|
return
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
fi
|
|
|
|
# if we got here, then this directory should have a good cache file in
|
|
# it and we should be able to add it to the master cache file
|
|
all_cache_files="${all_cache_files} ${d}/${cachefile}"
|
|
|
|
}
|
|
|
|
process_cache_files(){
|
|
echo "${prompt}Checking master cache file ${PACKAGES}/${cachefile}"
|
|
echo "pkgcache_version ${cacheversion}" > ${tmpd}/${cachefile}
|
|
if test -n "${all_cache_files}" ; then
|
|
for c in ${all_cache_files} ; do
|
|
echo "pkgcache_cachefile ${c}" >> ${tmpd}/${cachefile}
|
|
done
|
|
fi
|
|
if test ! -f ${PACKAGES}/${cachefile} ; then
|
|
echo "${tab}Creating master cache file ${PACKAGES}/${cachefile}"
|
|
mv -f ${tmpd}/${cachefile} ${PACKAGES}/${cachefile}
|
|
if test $? -ne 0 ; then
|
|
echo "********** ERROR **********"
|
|
echo "move of ${tmpd}/${cachefile} to ${PACKAGES}/${cachefile} failed!"
|
|
echo "Perhaps you do not have write permissions to ${PACKAGES}?"
|
|
echo "********** ERROR **********"
|
|
clean_and_exit1
|
|
fi
|
|
elif ${CMP} -s ${tmpd}/${cachefile} ${PACKAGES}/${cachefile} ; then
|
|
echo "${tab}Master cache file ${PACKAGES}/${cachefile} is up to date"
|
|
else
|
|
echo "${tab}Updating master cache file ${PACKAGES}/${cachefile}"
|
|
mv -f ${tmpd}/${cachefile} ${PACKAGES}/${cachefile}
|
|
if test $? -ne 0 ; then
|
|
echo "********** ERROR **********"
|
|
echo "move of ${tmpd}/${cachefile} to ${PACKAGES}/${cachefile} failed!"
|
|
echo "Perhaps you do not have write permissions to ${PACKAGES}?"
|
|
echo "********** ERROR **********"
|
|
clean_and_exit1
|
|
fi
|
|
fi
|
|
}
|
|
|
|
######################################################################
|
|
#
|
|
# Handle command line options
|
|
#
|
|
######################################################################
|
|
|
|
if_debug=: # either ":" or ""
|
|
if_verbose=: # either ":" or ""
|
|
force=no
|
|
build_summary=no
|
|
|
|
while
|
|
test -n "$1"
|
|
do
|
|
case "$1" in
|
|
|
|
# Turn on debugging
|
|
-d|--debug)
|
|
if_debug=""
|
|
if_verbose=""
|
|
shift
|
|
;;
|
|
|
|
# Force a rebuilde of the cache
|
|
-F|--force)
|
|
force=yes
|
|
shift
|
|
;;
|
|
# Help
|
|
-h|--help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
|
|
# Use the specified packages directory
|
|
-p|--packages)
|
|
PACKAGES=$2
|
|
shift 2
|
|
;;
|
|
|
|
# Build the pkg_summary.gz files
|
|
-s|--summary)
|
|
build_summary=yes
|
|
shift
|
|
;;
|
|
|
|
# Version
|
|
-V|--version)
|
|
${AWK} '/^#[ \t]*\$NetBSD/ {gsub(/,v/,"",$3);printf("%s: Version %s, %s\n",$3,$4,$5); exit 0;}' $prog
|
|
exit 0
|
|
;;
|
|
|
|
# Turn on verbose output, but not as noisy as debug
|
|
-v|--verbose)
|
|
if_verbose=""
|
|
shift
|
|
;;
|
|
|
|
-*) echo "$prog: ERROR: $1 is not a valid option"
|
|
usage
|
|
clean_and_exit1
|
|
;;
|
|
|
|
*)
|
|
break
|
|
;;
|
|
|
|
esac
|
|
done
|
|
|
|
if test $# -ne 0 ; then
|
|
echo "$0: $* is invalid"
|
|
usage
|
|
clean_and_exit1
|
|
fi
|
|
|
|
if test ! -d ${PACKAGES} ; then
|
|
echo "Packages directory ${PACKAGES} seems to be missing"
|
|
clean_and_exit2
|
|
fi
|
|
|
|
# put a trailing / after ${PACKAGES} in case ${PACKAGES} is
|
|
# a link.
|
|
|
|
# pass 1, we find all directories under PACKAGES. Note that this
|
|
# may contain some directories more than once depending on what sort
|
|
# of soft links may be in place
|
|
rm -f ${all_dirs}.tmp
|
|
for d in `${FIND} ${PACKAGES}/ -type d -follow -print` ; do
|
|
cname=`(cd ${d} && pwd -P)`
|
|
rname=`echo ${d} | ${SED} "s;^${PACKAGES}/*;;g"`
|
|
echo "${cname} ${rname}" >> ${all_dirs}.tmp
|
|
done
|
|
${SORT} -u -k1,1 ${all_dirs}.tmp > ${all_dirs}
|
|
$if_debug echo "Full directory list:"
|
|
$if_debug cat ${all_dirs}.tmp
|
|
$if_debug echo "Unique directory list:"
|
|
$if_debug cat ${all_dirs}
|
|
|
|
for d in `${AWK} '{print $1}' ${all_dirs}` ; do
|
|
$if_debug echo "${prompt}Processing directory ${d}"
|
|
is_pkg_dir=no
|
|
for f in ${d}/*${PKG_SUFX} ; do
|
|
if test -f "${f}" -a ! -h "${f}" ; then
|
|
${PKG_INFO} ${f} >/dev/null 2>&1
|
|
if test $? -eq 0 ; then
|
|
is_pkg_dir=yes
|
|
break
|
|
fi
|
|
fi
|
|
done
|
|
if test "X${is_pkg_dir}" = "Xyes" ; then
|
|
$if_verbose echo "${prompt}Checking cache in ${d}"
|
|
process_binpkg_dir
|
|
else
|
|
$if_debug echo "${prompt}no binary packages in ${d}"
|
|
fi
|
|
|
|
done
|
|
|
|
process_cache_files
|
|
|
|
clean_and_exit0
|