#!/bin/sh # -*- coding: latin-1 -*- # Copyright © 2014, 2017, Trond Endrestøl # 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. # To work around a deficiency between portupgrade and the pkg package manager when dealing with new dependencies: # # 1. Gather a list of origins for the outdated installed ports, store in ${OUTDATED_PORTS}. # 2. Check to see if ports-mgmt/pkg is out of date. # 2a. Run portupgrade -fpv ports-mgmt/pkg. # 2b. Update list of outdated ports. # 2c. Check to see if ports-mgmt/pkg is still out of date. # 2d. Abort if ports-mgmt/pkg still needs to be updated. # 3. Run portupgrade -ncfprv on ${OUTDATED_PORTS}. # 4. Check to see if x11/xcb-proto is out of date. # 4a. Run portupgrade -fprv x11/xcb-proto. # 4b. Update list of outdated ports. # 4c. Check to see if x11/xcb-proto is still out of date. # 4d. Abort if x11/xcb-proto still needs to be updated. # 5. Set ${OLD_LIST} to a dummy value, e.g. "dummy". # 6. Set ${NEW_DEPENDENCIES} to the empty string. # 7. While ${NEW_DEPENDENCIES} does not equal ${OLD_LIST}: # 7a. Store ${NEW_DEPENDENCIES} in ${OLD_LIST}. # 7b. Set ${NEW_DEPENDENCIES} to the empty string. # 7c. For each of the outdated ports, gather an accumulative list of the origins of the new dependencies using make missing, store in ${NEW_DEPENDENCIES}. # 7d. If the length of ${NEW_DEPENDENCIES} is non-zero, run portupgrade -ncNfprv on ${NEW_DEPENDENCIES}, otherwise break out of the loop. # # (Hopefully, no further interactivity will be required of the user beyond this point.) # # 8. If the length of ${NEW_DEPENDENCIES} is non-zero, run portupgrade -Nfprv on ${NEW_DEPENDENCIES}. # 9. Check to see if graphics/poppler is out of date. # 9a. Run portupgrade -fpv on graphics/poppler. # 9b. Check to see if graphics/poppler is still out of date. # 9c. Abort if graphics/poppler still needs to be updated. # 9d. If print/tex-luatex or print/tex-xetex is installed. # 9d1. Find the name of the previous libpoppler.so.NN library. # 9d2. Link /usr/local/lib/compat/pkg/libpoppler.so.NN.* (hopefully one filename) to /usr/local/lib/compat/pkg/libpoppler.so.NN. # 9d3. Forcefully upgrade print/tex-luatex and/or print/tex-xetex. # 9e. Forcefully upgrade ports depending on graphics/poppler, excluding graphics/poppler, print/tex-luatex, and print/tex-xetex. # 9f. Update list of outdated ports. # 10. Check to see if devel/icu is out of date. # 10a. Run portupgrade -fpv on devel/icu. # 10b. Check to see if devel/icu is still out of date. # 10c. Abort if devel/icu still needs to be updated. # 10d. If print/tex-xetex is installed. # 10d1. Find the name of the previous libicu*.so.NN libraries. # 10d2. Link /usr/local/lib/compat/pkg/libicu*.so.NN.* (hopefully one filename) to /usr/local/lib/compat/pkg/libicu*.so.NN. # 10d3. Forcefully upgrade print/tex-xetex. # 10e. Forcefully upgrade ports depending on devel/icu, excluding devel/icu and print/tex-xetex. # 10f. Update list of outdated ports. # 11. Check to see if lang/rust or its dependencies are out of date. # 11a. Gather lists of ports lang/rust depends on, and on ports depending on lang/rust. # 11b. Run portupgrade -ncfprv on lang/rust and the lists gathered in 3a. # 11c. Run pkg delete -y lang/rust. # 11d. Update list of outdated ports. # 12. Run portupgrade -fprv on ${OUTDATED_PORTS}. # 13. Continue special handling of lang/rust and any ports depending on lang/rust. # 13a. Readd lang/rust. # 13b. Abort if unable to add lang/rust. # 13c. Readd ports depending on lang/rust. # # Note: It also helps to keep portupgrade's ports database up to date. # # Moving /usr/local/lib/compat/pkg/* to, say, /usr/local/lib-compat-pkg, # is recommended to avoid running out of disk space in the long run. # /usr/local/lib-compat-pkg should be emptied before moving said files. # # A bit of programmer's license has been applied below. #set -x export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin if [ -x /usr/local/bin/ccache ]; then export PATH=/usr/local/libexec/ccache:${PATH}; export CCACHE_PATH=/usr/bin:/usr/local/bin; fi PORTSDIR="/usr/ports" LOGDIR="/var/log/portupgrade" PKGUPG_RESULTS="${LOGDIR}/pkgupg-results.log" NEWDEP_CONFIG_RESULTS="${LOGDIR}/newdep-config-results.log" NEWDEP_RESULTS="${LOGDIR}/newdep-results.log" OUTDATED_PORTS_CONFIG_RESULTS="${LOGDIR}/outdated-ports-config-results.log" XCB_PROTO_RESULTS="${LOGDIR}/xcb-proto-results.log" POPPLER_RESULTS="${LOGDIR}/poppler-results.log" POPPLER_DEPS_RESULTS="${LOGDIR}/poppler-deps-results.log" LUATEX_RESULTS="${LOGDIR}/luatex-results.log" ICU_RESULTS="${LOGDIR}/icu-results.log" ICU_DEPS_RESULTS="${LOGDIR}/icu-deps-results.log" XETEX_RESULTS="${LOGDIR}/xetex-results.log" OUTDATED_PORTS_RESULTS="${LOGDIR}/outdated-ports-results.log" LANG_RUST_RESULTS="${LOGDIR}/lang-rust-results.log" PORTS_DEPENDING_ON_LANG_RUST_RESULTS="${LOGDIR}/ports-depending-on-lang-rust-results.log" EXTRA_PORTS="" if [ ! -d ${LOGDIR} ]; then mkdir -p ${LOGDIR}; if [ ! -d ${LOGDIR} ]; then echo "${0}: unable to create directory ${LOGDIR}" >/dev/stderr; exit 69; fi; fi cd ${PORTSDIR} || exit 69 echo "${0}: gathering list of outdated ports" # These lines don't work well with stuff like WITHOUT_NEW_XORG=yes, etc. # Also, the downloaded index might be slightly out of date for a short period when this script executes. #make fetchindex || exit 69 #OUTDATED_PORTS=`pkg version -ovIL= | awk '{print $1}'` # Instead go for the slower, but accurate way using the ports tree. OUTDATED_PORTS=`pkg version -ovPL= | awk '{print $1}'` if [ -z "${OUTDATED_PORTS}" -a "${#}" -eq 0 ]; then echo "${0}: no outdated ports found, try running svn up ${PORTSDIR}" >/dev/stderr; exit 69; fi # Special handling of the package manager ports-mgmt/pkg. # Too much breaks while it's out of date. for o in ${OUTDATED_PORTS}; do if [ "${o}" = "ports-mgmt/pkg" ]; then echo "${0}: upgrading ports-mgmt/pkg"; portupgrade -fpv -l ${PKGUPG_RESULTS} ports-mgmt/pkg; echo "${0}: checking to see if ports-mgmt/pkg is still outdated"; OUTDATED_PORTS=`pkg version -ovPL= | awk '{print $1}'`; for oo in ${OUTDATED_PORTS}; do if [ "${oo}" = "ports-mgmt/pkg" ]; then echo "${0}: unable to upgrade ports-mgmt/pkg, bailing out" >/dev/stderr; exit 69; fi; done; break; fi; done unset o unset oo if [ -z "${OUTDATED_PORTS}" -a "${#}" -eq 0 ]; then echo "${0}: no more outdated ports found, try running svn up ${PORTSDIR}" >/dev/stderr; exit 69; fi # Give the user a chance to (re)configure any of the outdated ports. portupgrade -ncfprv -l ${OUTDATED_PORTS_CONFIG_RESULTS} ${@} ${OUTDATED_PORTS} || exit; # Special handling of x11/xcb-proto. for o in ${OUTDATED_PORTS}; do if [ "${o}" = "x11/xcb-proto" ]; then echo "${0}: upgrading x11/xcb-proto and any ports depending on it"; portupgrade -fprv -l ${XCB_PROTO_RESULTS} x11/xcb-proto; echo "${0}: checking to see if x11/xcb-proto is still outdated"; OUTDATED_PORTS=`pkg version -ovPL= | awk '{print $1}'`; for oo in ${OUTDATED_PORTS}; do if [ "${oo}" = "x11/xcb-proto" ]; then echo "${0}: unable to upgrade x11/xcb-proto, bailing out" >/dev/stderr; exit 69; fi; done; break; fi; done unset o unset oo # Catch any missing new dependencies. # The list may grow or shrink as the user configures each new dependency. OLD_LIST="dummy" NEW_DEPENDENCIES="" while [ "${NEW_DEPENDENCIES}" != "${OLD_LIST}" ]; do OLD_LIST="${NEW_DEPENDENCIES}"; NEW_DEPENDENCIES=""; for p in ${OUTDATED_PORTS} ${@}; do echo "${0}: running make missing in ${p}"; # This approach is safer in cases of removed ports or ports with changed origins. cd ${PORTSDIR}/${p} && NEW_DEPENDENCIES="${NEW_DEPENDENCIES} `make missing`"; done; cd /tmp; NEW_DEPENDENCIES=`echo ${NEW_DEPENDENCIES} | sort | uniq`; if [ -n "${NEW_DEPENDENCIES}" ]; then # Give the user a chance to configure any of the new dependencies. portupgrade -ncNfpv -l ${NEWDEP_CONFIG_RESULTS} ${NEW_DEPENDENCIES} || exit; else break; fi; done # Install any new dependencies. if [ -n "${NEW_DEPENDENCIES}" ]; then portupgrade -Nfpv -l ${NEWDEP_RESULTS} ${NEW_DEPENDENCIES} || exit; unset NEW_DEPENDENCIES; fi # Special handling of graphics/poppler, print/tex-luatex, and print/tex-xetex. for o in ${OUTDATED_PORTS}; do if [ "${o}" = "graphics/poppler" ]; then # The real issue is that /usr/local/bin/{luatex,xetex} is still linked to # the old poppler library, and luatex from /usr/local/bin is run by fmtutil # during (re)build of print/tex-luatex. This would be a lot easier if the # rebuild always referred to luatex in the stage dir. # # Linking /usr/local/lib/compat/pkg/libpoppler.so.NN.0.0 to # /usr/local/lib/compat/pkg/libpoppler.so.NN lets the installed luatex and # xetex continue being executable. What a mess. if pkg info -e print/tex-luatex || pkg info -e print/tex-xetex; then echo "${0}: upgrading graphics/poppler"; portupgrade -fpv -l ${POPPLER_RESULTS} graphics/poppler; echo "${0}: checking to see if graphics/poppler is still outdated"; OUTDATED_PORTS=`pkg version -ovPL= | awk '{print $1}'`; for oo in ${OUTDATED_PORTS}; do if [ "${oo}" = "graphics/poppler" ]; then echo "${0}: unable to upgrade graphics/poppler, bailing out" >/dev/stderr; exit 69; fi; done; unset oo; OLD_POPPLER_LIB=`ldd /usr/local/bin/luatex | grep libpoppler | awk '{print $1}'`; # Assuming that /usr/local/lib/compat/pkg/${OLD_POPPLER_LIB}.* refers to a single filename. echo "${0}: linking /usr/local/lib/compat/pkg/${OLD_POPPLER_LIB}.* to /usr/local/lib/compat/pkg/${OLD_POPPLER_LIB}"; ln /usr/local/lib/compat/pkg/${OLD_POPPLER_LIB}.* /usr/local/lib/compat/pkg/${OLD_POPPLER_LIB}; unset OLD_POPPLER_LIB; if pkg info -e print/tex-luatex; then echo "${0}: upgrading print/tex-luatex early simply as a precaution"; portupgrade -fpv -l ${LUATEX_RESULTS} print/tex-luatex; fi; if pkg info -e print/tex-xetex; then echo "${0}: upgrading print/tex-xetex early simply as a precaution"; portupgrade -fpv -l ${XETEX_RESULTS} print/tex-xetex; fi; #echo "${0}: upgrading ports depending on graphics/poppler, excluding graphics/poppler, print/tex-luatex, and, print/tex-xetex"; #portupgrade -fprv -l ${POPPLER_DEPS_RESULTS} -x graphics/poppler -x print/tex-luatex -x print/tex-xetex graphics/poppler; # Propagate the remaining ports depending on graphics/poppler to the main action of this script. EXTRA_PORTS="${EXTRA_PORTS} `pkg query %ro graphics/poppler | grep -v print/tex-luatex | grep -v print/tex-xetex`" echo "${0}: updating list of outdated ports"; OUTDATED_PORTS=`pkg version -ovPL= | awk '{print $1}'`; fi; break; fi; done unset o # Special handling of devel/icu and print/tex-xetex. for o in ${OUTDATED_PORTS}; do if [ "${o}" = "devel/icu" ]; then # The real issue is that /usr/local/bin/xetex is still linked to the old # icu libraries, and xetex from /usr/local/bin is run by fmtutil during # (re)build of print/tex-xetex. This would be a lot easier if the rebuild # always referred to xetex in the stage dir. # # Linking /usr/local/lib/compat/pkg/libicu*.so.NN.* to # /usr/local/lib/compat/pkg/libicu*.so.NN lets the installed xetex # continue being executable. Another mess. if pkg info -e print/tex-xetex; then echo "${0}: upgrading devel/icu"; portupgrade -fpv -l ${ICU_RESULTS} devel/icu; echo "${0}: checking to see if devel/icu is still outdated"; OUTDATED_PORTS=`pkg version -ovPL= | awk '{print $1}'`; for oo in ${OUTDATED_PORTS}; do if [ "${oo}" = "devel/icu" ]; then echo "${0}: unable to upgrade devel/icu, bailing out" >/dev/stderr; exit 69; fi; done; OLD_ICU_LIBS=`ldd /usr/local/bin/xetex | grep libicu | awk '{print $1}'`; # Assuming that each occurrence of /usr/local/lib/compat/pkg/${OLD_ICU_LIBS}.* refers to a single filename. for oo in ${OLD_ICU_LIBS}; do echo "${0}: linking /usr/local/lib/compat/pkg/${oo}.* to /usr/local/lib/compat/pkg/${oo}"; ln /usr/local/lib/compat/pkg/${oo}.* /usr/local/lib/compat/pkg/${oo}; done; unset OLD_ICU_LIBS; unset oo; echo "${0}: upgrading print/tex-xetex early simply as a precaution"; portupgrade -fpv -l ${XETEX_RESULTS} print/tex-xetex; #echo "${0}: upgrading ports depending on devel/icu, excluding devel/icu and print/tex-xetex"; #portupgrade -fprv -l ${ICU_DEPS_RESULTS} -x devel/icu -x print/tex-xetex devel/icu; # Propagate the remaining ports depending on devel/icu to the main action of this script. EXTRA_PORTS="${EXTRA_PORTS} `pkg query %ro devel/icu | grep -v print/tex-xetex`" echo "${0}: updating list of outdated ports"; OUTDATED_PORTS=`pkg version -ovPL= | awk '{print $1}'`; fi; break; fi; done unset o # Special handling of lang/rust, its dependencies, and any ports depending on lang/rust. Part 1 of 2. if pkg info -e lang/rust; then echo "${0}: gathering list of ports that lang/rust depends on"; PORTS_RUST_DEPENDS_ON=`pkg query %do lang/rust`; for o in ${OUTDATED_PORTS}; do for oo in lang/rust ${PORTS_RUST_DEPENDS_ON}; do if [ "${oo}" = "${o}" ]; then RUST_NEEDS_UPDATE="yes"; echo "${0}: gathering list of ports depending on lang/rust"; PORTS_DEPENDING_ON_RUST=`pkg query %ro lang/rust`; # lang/rust cannot be upgraded while it's installed. # The same applies if any of its dependencies are outdated. # lang/rust and any ports depending on it will be restored later by this script. echo "${0}: removing lang/rust and any ports depending on it: ${PORTS_DEPENDING_ON_RUST}"; pkg delete -y lang/rust; echo "${0}: updating list of outdated ports"; OUTDATED_PORTS=`pkg version -ovPL= | awk '{print $1}'`; break 2; # Break out of the two nested for loops. fi; done; done; unset o; unset oo; fi # Upgrade the outdated ports. This is the main action of this script. # Everything else is to ensure this step goes as smooth as possible. portupgrade -fprv -l ${OUTDATED_PORTS_RESULTS} ${@} ${OUTDATED_PORTS} ${EXTRA_PORTS} || exit # Continue special handling of lang/rust, and any ports depending on lang/rust. Part 2 of 2. if [ -n "${RUST_NEEDS_UPDATE}" ]; then echo "${0}: I might need to add lang/rust and afterwards add: ${PORTS_DEPENDING_ON_RUST}"; if [ "`pkg query %o lang/rust`" != "lang/rust" ]; then echo "${0}: adding lang/rust"; portupgrade -Nfpv -l ${LANG_RUST_RESULTS} lang/rust || exit; else echo "${0}: lang/rust is already in place"; fi; if [ -n "${PORTS_DEPENDING_ON_RUST}" ]; then echo "${0}: adding removed ports depending on lang/rust: ${PORTS_DEPENDING_ON_RUST}"; for p in ${PORTS_DEPENDING_ON_RUST}; do if [ "`pkg query %o ${p}`" != "${p}" ]; then portupgrade -Nfpv -l ${PORTS_DEPENDING_ON_LANG_RUST_RESULTS} ${p} || exit; fi; done; fi; # if [ -n "${PORTS_DEPENDING_ON_RUST}" ]; then # echo "${0}: adding removed ports depending on lang/rust: ${PORTS_DEPENDING_ON_RUST}"; # portupgrade -Nfpv -l ${PORTS_DEPENDING_ON_LANG_RUST_RESULTS} ${PORTS_DEPENDING_ON_RUST} || exit; # fi; fi # EOF