287 lines
8.6 KiB
Bash
287 lines
8.6 KiB
Bash
#!/bin/sh
|
|
# ports/Mk/Scripts/check-stagedir.sh - called from ports/Mk/bsd.stage.mk
|
|
# $FreeBSD$
|
|
#
|
|
# MAINTAINER: portmgr@FreeBSD.org
|
|
#
|
|
# This script serves 2 purposes:
|
|
# 1. Generate a plist
|
|
# 2. Test a plist for issues:
|
|
# a. Files in STAGEDIR that are missing from plist
|
|
# b. Files in plist missing from STAGEDIR
|
|
# c. Files in plist which are owned by dependencies/MTREEs
|
|
|
|
set -e
|
|
|
|
. ${SCRIPTSDIR}/functions.sh
|
|
|
|
# lists an mtree file's contents, prefixed to dir.
|
|
listmtree() { # mtreefile prefix
|
|
{
|
|
echo '#mtree'
|
|
sed 's/nochange$//;' $1
|
|
} | tar -tf- | sed "s,^,$2/,;s,^$2/\.$,$2,;s,^$,/,"
|
|
}
|
|
|
|
### PRODUCE MTREE FILE
|
|
parse_mtree() {
|
|
{
|
|
listmtree /etc/mtree/BSD.root.dist ""
|
|
listmtree /etc/mtree/BSD.usr.dist /usr
|
|
listmtree /etc/mtree/BSD.var.dist /var
|
|
|
|
# Use MTREE_FILE if specified and it doesn't already
|
|
# match LOCALBASE
|
|
if [ -n "${MTREE_FILE}" ]; then
|
|
if [ "${PREFIX}" != "${LOCALBASE}" -o "${MTREE_FILE}" \
|
|
!= "${PORTSDIR}/Templates/BSD.local.dist" ]; then
|
|
listmtree "${MTREE_FILE}" "${PREFIX}"
|
|
fi
|
|
fi
|
|
listmtree "${PORTSDIR}/Templates/BSD.local.dist" "${LOCALBASE}"
|
|
|
|
unset MTREE_FILE
|
|
|
|
# Add LOCALBASE
|
|
a=${LOCALBASE}
|
|
while :; do
|
|
echo ${a}
|
|
a=${a%/*}
|
|
[ -z "${a}" ] && break
|
|
done
|
|
|
|
# Add in PREFIX if this port wants it
|
|
if [ ${NO_PREFIX_RMDIR} -eq 0 ]; then
|
|
a=${PREFIX}
|
|
while :; do
|
|
echo ${a}
|
|
a=${a%/*}
|
|
[ -z "${a}" ] && break
|
|
done
|
|
fi
|
|
} >${WRKDIR}/.mtree
|
|
}
|
|
|
|
# Sort a directory list by the order of the dfs-sorted file (from find -d -s)
|
|
sort_dfs() {
|
|
while read -r dir; do
|
|
grep "^[0-9]* ${dir}$" ${WRKDIR}/.staged-dirs-dfs-sorted
|
|
done | sort -n | cut -d ' ' -f2-
|
|
}
|
|
|
|
# Prepare sed(1) regex for PLIST_SUB_SED/PORTEXAMPLES/OPTIONS/...
|
|
setup_plist_seds() {
|
|
### HANDLE PORTDOCS/PORTEXAMPLES
|
|
sed_portdocsexamples="/%%DOCSDIR%%/s!^!%%PORTDOCS%%!g; /%%EXAMPLESDIR%%/s!^!%%PORTEXAMPLES%%!g;"
|
|
if [ ${makeplist} -eq 0 ]; then
|
|
# echo "=====> Using OPTIONS: ${PORT_OPTIONS}" | /usr/bin/fmt -w 79 | \
|
|
# sed -e '2,$s/^/ /'
|
|
# Handle magical PORT* features
|
|
for option in DOCS EXAMPLES; do
|
|
want_option=0
|
|
case " ${PORT_OPTIONS} " in
|
|
*\ ${option}\ *) want_option=1 ;;
|
|
esac
|
|
[ ${want_option} -eq 0 ] && \
|
|
sed_portdocsexamples="${sed_portdocsexamples} /^%%PORT${option}%%/d;"
|
|
done
|
|
unset PORT_OPTIONS
|
|
fi
|
|
|
|
sed_plist_sub=$(mktemp -t sed_plist_sub)
|
|
# We only exit 0 or exit 1
|
|
trap "rm -f ${sed_plist_sub}" EXIT 1
|
|
echo "${PLIST_SUB_SED}" | /bin/sh ${SCRIPTSDIR}/plist_sub_sed_sort.sh ${sed_plist_sub}
|
|
unset PLIST_SUB_SED
|
|
# Used for generate_plist
|
|
sed_files_gen="${sed_portdocsexamples} /^share\/licenses/d; \
|
|
\#${LOCALBASE}/lib/debug#d;"
|
|
sed_dirs_gen="s,^,@dir ,; \
|
|
${sed_portdocsexamples} \
|
|
/^@dir share\/licenses/d;"
|
|
|
|
# These prevent ignoring DOCS/EXAMPLES dirs with sed_portdocsexamples
|
|
sed_files="/^share\/licenses/d; \
|
|
\#${LOCALBASE}/lib/debug#d;"
|
|
sed_dirs="s,^,@dir ,; \
|
|
/^@dir share\/licenses/d;"
|
|
|
|
}
|
|
|
|
# Generate plist from staged files
|
|
generate_plist() {
|
|
: >${WRKDIR}/.staged-plist
|
|
|
|
### HANDLE FILES
|
|
find ${STAGEDIR} -type f -o -type l | sort | \
|
|
sed -e "s,${STAGEDIR},," >${WRKDIR}/.staged-files
|
|
comm -13 ${WRKDIR}/.plist-files ${WRKDIR}/.staged-files | \
|
|
sed -e "s!^${PREFIX}/!!g;" -f "${sed_plist_sub}" -e "${sed_files_gen}" \
|
|
>>${WRKDIR}/.staged-plist || :
|
|
|
|
### HANDLE DIRS
|
|
cat ${WRKDIR}/.plist-dirs-unsorted ${WRKDIR}/.mtree \
|
|
| sort -u >${WRKDIR}/.traced-dirs
|
|
find ${STAGEDIR} -type d | sed -e "s,^${STAGEDIR},,;/^$/d" | sort \
|
|
>${WRKDIR}/.staged-dirrms-sorted
|
|
find -s -d ${STAGEDIR}${PREFIX} -type d -empty | sed -e "s,^${STAGEDIR},,;\,^${PREFIX}$,d;/^$/d" \
|
|
>${WRKDIR}/.staged-dirs-dfs
|
|
find -s -d ${STAGEDIR} -type d ! -path "${STAGEDIR}${PREFIX}/*" | sed -e "s,^${STAGEDIR},,;\,^${PREFIX}$,d;/^$/d" \
|
|
>>${WRKDIR}/.staged-dirs-dfs
|
|
sort ${WRKDIR}/.staged-dirs-dfs >${WRKDIR}/.staged-dirs-sorted
|
|
awk '{print FNR, $0}' ${WRKDIR}/.staged-dirs-dfs \
|
|
>${WRKDIR}/.staged-dirs-dfs-sorted
|
|
# Find all staged dirs and then sort them by depth-first (find -d -s)
|
|
comm -13 ${WRKDIR}/.traced-dirs ${WRKDIR}/.staged-dirs-sorted \
|
|
| sort_dfs | sed -e "s!^${PREFIX}/!!g;" -f "${sed_plist_sub}" -e "${sed_dirs_gen}" \
|
|
>>${WRKDIR}/.staged-plist || :
|
|
}
|
|
|
|
# Check for files in STAGEDIR missing from plist
|
|
check_orphans_from_plist() {
|
|
local ret=0
|
|
|
|
echo "===> Checking for items in STAGEDIR missing from pkg-plist"
|
|
# Handle whitelisting
|
|
while read -r path; do
|
|
case "${path}" in
|
|
*.bak) ;;
|
|
*.orig) ;;
|
|
*/.DS_Store) ;;
|
|
*/.cvsignore) ;;
|
|
*/.git/*|'@dir '*/.git) ;;
|
|
*/.gitattributes|*/.gitignore|*/.gitmodules) ;;
|
|
*/.svn/*|'@dir '*/.svn) ;;
|
|
*/.svnignore) ;;
|
|
*/CVS/*|'@dir '*/CVS) ;;
|
|
*/info/dir|info/dir|info/*/dir|share/info/*/dir) ;;
|
|
share/fonts/*/fonts.dir) ;;
|
|
share/fonts/*/fonts.scale) ;;
|
|
share/applications/mimeinfo.cache) ;;
|
|
share/mime/XMLnamespaces) ;;
|
|
share/mime/aliases) ;;
|
|
share/mime/generic-icons) ;;
|
|
share/mime/globs) ;;
|
|
share/mime/globs2) ;;
|
|
share/mime/icons) ;;
|
|
share/mime/magic) ;;
|
|
share/mime/mime.cache) ;;
|
|
share/mime/subclasses) ;;
|
|
share/mime/treemagic) ;;
|
|
share/mime/types) ;;
|
|
share/mime/version) ;;
|
|
'@dir etc/gconf/gconf.xml.defaults');;
|
|
*)
|
|
# An orphan was found, return non-zero status
|
|
ret=1
|
|
echo "Error: Orphaned: ${path}" >&2
|
|
;;
|
|
esac
|
|
done < ${WRKDIR}/.staged-plist
|
|
return ${ret}
|
|
}
|
|
|
|
# Check for items in plist not in STAGEDIR (pkg lstat(2) errors)
|
|
check_missing_plist_items() {
|
|
local ret=0
|
|
echo "===> Checking for items in pkg-plist which are not in STAGEDIR"
|
|
: >${WRKDIR}/.invalid-plist-missing
|
|
comm -23 ${WRKDIR}/.plist-files-no-comments ${WRKDIR}/.staged-files | \
|
|
sed -e "s!^${PREFIX}/!!g;" -f "${sed_plist_sub}" -e "${sed_files}" \
|
|
>>${WRKDIR}/.invalid-plist-missing || :
|
|
|
|
# Look for directories, then sort them by DFS. Must create the dirs
|
|
# so find -ds can be used to sort them.
|
|
rm -rf ${WRKDIR}/.missing-dirs > /dev/null 2>&1 || :
|
|
mkdir ${WRKDIR}/.missing-dirs
|
|
comm -23 ${WRKDIR}/.plist-dirs-sorted-no-comments \
|
|
${WRKDIR}/.staged-dirrms-sorted > ${WRKDIR}/.missing-plist-dirs
|
|
# Creates the dirs in WRKDIR/.missing-dirs and ensure spaces are
|
|
# quoted.
|
|
sed -e "s,^,${WRKDIR}/.missing-dirs," \
|
|
-e 's,^\(.*\)$,"\1",' \
|
|
${WRKDIR}/.missing-plist-dirs | xargs mkdir -p
|
|
find -d -s ${WRKDIR}/.missing-dirs | \
|
|
sed -e "s,^${WRKDIR}/.missing-dirs,," | \
|
|
while read -r dir; do \
|
|
grep -x "${dir}" ${WRKDIR}/.missing-plist-dirs || :; done | \
|
|
sed -e "s!^${PREFIX}/!!g;" -f "${sed_plist_sub}" -e "${sed_dirs}" \
|
|
>>${WRKDIR}/.invalid-plist-missing || :
|
|
rm -rf ${WRKDIR}/.missing-dirs
|
|
if [ -s "${WRKDIR}/.invalid-plist-missing" ]; then
|
|
ret=1
|
|
while read -r line; do
|
|
echo "Error: Missing: ${line}" >&2
|
|
done < ${WRKDIR}/.invalid-plist-missing
|
|
fi
|
|
return ${ret}
|
|
}
|
|
|
|
# obtain operating mode from command line
|
|
ret=0
|
|
makeplist=0
|
|
case "$1" in
|
|
checkplist) ;;
|
|
makeplist) makeplist=1 ;;
|
|
*) echo >&2 "Usage: $0 {checkplist|makeplist}" ; exit 1 ;;
|
|
esac
|
|
|
|
# validate environment
|
|
validate_env STAGEDIR PREFIX LOCALBASE WRKDIR WRKSRC MTREE_FILE \
|
|
TMPPLIST PLIST_SUB_SED SCRIPTSDIR PORT_OPTIONS NO_PREFIX_RMDIR
|
|
|
|
[ -n "${DEBUG_MK_SCRIPTS}" -o -n "${DEBUG_MK_SCRIPTS_CHECK_STAGEDIR}" ] && set -x
|
|
|
|
set -u
|
|
|
|
if [ $makeplist = 0 ] ; then
|
|
echo "===> Parsing plist"
|
|
parse_plist "${PREFIX}" 1 < ${TMPPLIST} \
|
|
3>${WRKDIR}/.plist-dirs-unsorted \
|
|
>${WRKDIR}/.plist-files-unsorted
|
|
unset TMPPLIST
|
|
# Create the -no-comments files and trim out @comment from the plists.
|
|
# This is used for various tests later.
|
|
sed -e '/^@comment/d' ${WRKDIR}/.plist-dirs-unsorted \
|
|
>${WRKDIR}/.plist-dirs-unsorted-no-comments
|
|
sed -i '' -e 's/^@comment //' ${WRKDIR}/.plist-dirs-unsorted
|
|
sed -e '/^@comment/d' ${WRKDIR}/.plist-files-unsorted | sort \
|
|
>${WRKDIR}/.plist-files-no-comments
|
|
sed -e 's/^@comment //' ${WRKDIR}/.plist-files-unsorted | sort \
|
|
>${WRKDIR}/.plist-files
|
|
else
|
|
# generate plist - pretend the plist had been empty
|
|
: >${WRKDIR}/.plist-dirs-unsorted
|
|
: >${WRKDIR}/.plist-files
|
|
echo '/you/have/to/check/what/makeplist/gives/you'
|
|
fi
|
|
|
|
parse_mtree
|
|
|
|
setup_plist_seds
|
|
generate_plist
|
|
|
|
# If just making plist, show results and exit successfully.
|
|
if [ ${makeplist} -eq 1 ]; then
|
|
cat ${WRKDIR}/.staged-plist
|
|
exit 0
|
|
fi
|
|
|
|
check_orphans_from_plist || ret=1
|
|
|
|
# Prepare plist-dirs for directory checks
|
|
sort -u ${WRKDIR}/.plist-dirs-unsorted-no-comments \
|
|
>${WRKDIR}/.plist-dirs-sorted-no-comments
|
|
|
|
check_missing_plist_items || ret=1
|
|
|
|
if [ ${ret} -ne 0 ]; then
|
|
echo "===> Error: Plist issues found." >&2
|
|
if [ "${PREFIX}" != "${LOCALBASE}" ]; then
|
|
echo "===> Warning: Test was done with PREFIX != LOCALBASE"
|
|
echo "===> Warning: The port may not be properly installing into PREFIX"
|
|
fi
|
|
fi
|
|
|
|
exit ${ret}
|