diff options
author | dougb <dougb@FreeBSD.org> | 2008-01-24 10:36:58 +0800 |
---|---|---|
committer | dougb <dougb@FreeBSD.org> | 2008-01-24 10:36:58 +0800 |
commit | 5b8436e59f094f7d9e2d972460e12b85c85e2e3a (patch) | |
tree | 39153ff29ecf68b8db999e45ced748fbedb010f1 /ports-mgmt/portmaster | |
parent | a2a36937a6530ca3295cb109d5e19bdca6444389 (diff) | |
download | freebsd-ports-gnome-5b8436e59f094f7d9e2d972460e12b85c85e2e3a.tar.gz freebsd-ports-gnome-5b8436e59f094f7d9e2d972460e12b85c85e2e3a.tar.zst freebsd-ports-gnome-5b8436e59f094f7d9e2d972460e12b85c85e2e3a.zip |
The code for this 2.0 version has been totally reorganized, and
in several cases totally rewritten. I am also glad to say that
all of the advertised features now work as advertised. :)
The most exciting new feature is the completely new dependency
updater. I finally took the time to write the line-oriented version
of update_contents() that I wanted to write in the first place, so
no more sed, and no more warnings sent to $PAGER. This version relies
entirely on exact matches to DEPORIGIN to do its work, so it's 100%
reliable.
So what else is new? A lot of micro-optimizations have been done to
eliminate duplicated work, avoid using external commands when not
necessary, etc. There are also some not-so-micro optimizations, which
means that this version is noticably faster.
Totally new features:
1. --check-depends, which as described above calls the new functions
to parse existing +CONTENTS files for dependency data, uses that data
to update +REQUIRED_BY, and updates the +CONTENTS files. These same
routines are also used for updating ports.
2. A "fetch only" feature (-F) that will go get distfiles for new
versions of installed ports by default, and can also be used to get
the files for all of your installed ports, or certain branches by
using the -aft options.
3. An option to hide the build and install process by saving it to a
log (-H). These logs are deleted on successful install, and saved if
the update process aborts.
4. We now keep track of all the ports that get updated or installed in
a given invocation, and print the list at the very end of the process.
5. There is now a little "map" to show you where you are in the
process of the form "parent >> child >> grandchild >> etc."
6. Support for running as an unprivileged user (via sudo) has been
added. See the man page for details on how to configure this.
Improved features:
1. When showing the pkg-message/+DISPLAY files at the end of the
process, all files are grouped together and spit out to $PAGER (or
just cat if -u). If there is an error, there is a pause first
(unless -u).
2. There is now much more sanity checking on user input so that we can
bail out early if there is a problem.
3. The error messages have been completely re-done to be more
informative, and many of them include helpful suggestions on how to
fix the problems.
4. In the expunge (-e) feature, if there is dependency data for the
port you want to delete we now offer you the chance to delete that
instead of just aborting. (Use at your own risk!)
5. The "save old shared libs" feature (-w) is now a lot more
efficient, only runs ldconfig when it has to, and uses
/etc/rc.d/ldconfig.
6. The /var/db/pkg/*/+IGNOREME file now has more functions associated
with it. See the man page for details.
7. When using the -L feature, there is a warning printed if the port
has been set to FORBIDDEN, DEPRECATED, BROKEN, or IGNORE.
8. If you have a real /usr/X11R6 directory (not a symlink) this is
added to the PATH. Otherwise it's assumed that LOCALBASE == X11BASE.
9. Backup packages of existing ports are now saved to
/usr/ports/packages/portmaster-backup, and left there if -b is used.
This way you can create backup packages of a port without disturbing
existing packages with the same version.
There are numerous other things that are not user-visible which have
been cleaned, polished, made more efficient, etc.
Diffstat (limited to 'ports-mgmt/portmaster')
-rw-r--r-- | ports-mgmt/portmaster/files/portmaster.sh.in | 3076 |
1 files changed, 1701 insertions, 1375 deletions
diff --git a/ports-mgmt/portmaster/files/portmaster.sh.in b/ports-mgmt/portmaster/files/portmaster.sh.in index a6c4518d03b3..2aeb6bddb1fb 100644 --- a/ports-mgmt/portmaster/files/portmaster.sh.in +++ b/ports-mgmt/portmaster/files/portmaster.sh.in @@ -1,37 +1,213 @@ #!/bin/sh -# Local version: 1.193 -# $FreeBSD$ - -# Copyright (c) 2005-2007 Douglas Barton, All rights reserved +# Copyright (c) 2005-2008 Douglas Barton, All rights reserved # Please see detailed copyright below trap trap_exit INT -# Keep track of the parent process +# Initialize crucial values for the parent, and export them for the children if [ -z "$PARENT_PID" ]; then PARENT_PID=$$ : ${TMPDIR:=/tmp} UPGRADE_TOOL=portmaster - export PARENT_PID TMPDIR UPGRADE_TOOL -fi -# %%LOCALBASE%% and %%X11BASE%% are needed in path for make -PATH=/bin:/usr/bin:/sbin:/usr/sbin:%%LOCALBASE%%/bin:%%LOCALBASE%%/sbin:%%X11BASE%%/bin -if [ -n "$CCACHE_PATH" ]; then - if [ -z "$NOCCACHE" ]; then - PATH="%%LOCALBASE%%/libexec/ccache:$PATH" + # %%LOCALBASE%% is needed in the path for make + PATH=/bin:/usr/bin:/sbin:/usr/sbin:%%LOCALBASE%%/bin:%%LOCALBASE%%/sbin + [ -e /usr/X11R6 -a ! -L /usr/X11R6 ] && PATH=$PATH:/usr/X11R6/bin + if [ -n "$CCACHE_PATH" ]; then + if [ -z "$NOCCACHE" ]; then + PATH="%%LOCALBASE%%/libexec/ccache:$PATH" + fi fi + export PARENT_PID TMPDIR UPGRADE_TOOL PATH + + set -o allexport + # Read a global rc file first + [ -r /etc/portmaster.rc ] && . /etc/portmaster.rc + + # Read a local one next, and allow the command line to override + [ -r "$HOME/.portmasterrc" ] && . $HOME/.portmasterrc + set +o allexport + + # If we are already root, unset this to avoid potential conflict + euid=`ps -o uid $$` ; euid=${euid##* } + [ "$euid" -eq 0 ] && unset PM_SU_CMD fi -export PATH umask 022 +#=============== Begin functions we always want to have =============== + +version () { + local rcs cvs + + rcs='$Id: portmaster,v 2.23 2008/01/24 02:01:46 doug Exp $' + cvs='$FreeBSD$' + + rcs="${rcs#*,v }" ; rcs="${rcs%% *}" + cvs="${cvs#*,v }" ; cvs="${cvs%% *}" + + echo '' + [ "$cvs" != '$FreeBSD$' ] && + { echo "===>>> FreeBSD version $cvs" ; return 0; } + echo "===>>> Development version $rcs" +} + +fail () { + echo '' ; echo "===>>> $1" ; echo "===>>> Aborting update" + [ "$$" -eq "$PARENT_PID" ] && trap_exit fail + safe_exit 1 +} + +trap_exit () { + TRAP=yes + + echo '' # Helps if the previous message was 'echo -n' + if [ -n "$portdir" -a -z "$1" ]; then + echo "===>>> Build/Install for $portdir exiting due to signal" + elif [ -z "$1" ]; then + echo "===>>> Exiting due to signal" + fi + + if [ "$$" -eq "$PARENT_PID" ]; then + local n=0 + while ps -axo pid,ppid,command | grep -v egrep | egrep -q "(make -DBATCH checksum|/fetch |\[sh\])"; do + # Protect from infinite loop if there is another fetch + [ $n -gt 9 ] && break + n=$(( $n + 1 )) + kill_bad_children + done + if [ -n "$HIDE_BUILD" ]; then + local logs file + logs=`echo ${TMPDIR}/port_log-${PARENT_PID}-*` + case "$logs" in *\*) unset logs ;; esac + if [ -n "$logs" ]; then + echo '' + echo "===>>> Build/Install logs available:" + for file in $logs; do + echo " $file" + done + fi + [ -n "$logs" ] && echo '' + fi + fi + safe_exit 1 +} + +kill_bad_children () { + local pid ppid command ; IFS=' ' + + ps -axo pid,ppid,command | sed '1d' | while read pid ppid command; do + [ "$pid" -gt 25 ] || continue + case "$ppid" in + 1) case "$command" in + *" $0 "*) pm_kill $pid ;; + *'make -DBATCH checksum'*|*'/fetch '*|\[sh\]) + pm_kill -9 $pid ;; + esac + ;; + $PARENT_PID) + case "$command" in + *'make -DBATCH checksum'*|*'/fetch '*|\[sh\]) + pm_kill -9 $pid ;; + esac + ;; + *) case "$command" in + *" $0 "*) [ $pid -ne $PARENT_PID ] && pm_kill $pid ;; + esac + ;; + esac + done +} + +safe_exit () { + local files p f + + if [ "$$" -eq "$PARENT_PID" ]; then + [ -n "$DI_FILES" -o -n "$FETCH_ONLY" ] && kill_bad_children + + if [ -z "$TRAP" ]; then + if [ -n "$UPDATE_REQ_BYS" -o -n "$FORCE" ]; then + # Outdent + files=`find $pdb -type f -name PM_UPGRADE_DONE_FLAG` + if [ -n "$files" ]; then + [ -n "$PM_SU_VERBOSE" ] && + echo "===>>> Deleting 'install complete' flags" + pm_find_s $pdb -type f -name PM_UPGRADE_DONE_FLAG -delete + fi + # Outdent + fi + if [ -z "$BACKUP" -a -z "$NO_BACKUP" -a \ + -n "$NB_DELETE" ]; then + [ -n "$PM_SU_VERBOSE" ] && + echo "===>>> Deleting safety packages for successful installs" + pm_cd $pbu || fail "Cannot cd to $pbu" + pm_rm_s $NB_DELETE + fi + fi + + [ -n "$pbu" ] && pbu=`find $pbu -type d -empty 2>/dev/null` + if [ -d "$pbu" ]; then + [ -n "$PM_SU_VERBOSE" ] && + echo "===>>> Removing empty backup package directory" + pm_rmdir_s $pbu + fi + + for f in ${TMPDIR}/f-${PARENT_PID}-*; do pm_unlink $f ; done + + case "$DISPLAY_LIST" in + *' '*) if [ -z "$UNATTENDED" -a -n "$TRAP" ]; then + echo "===>>> There are messages from installed ports to display," + echo " but first take a moment to review the error messages" + echo -n " above. Then press Enter when ready to proceed. " + read DISCARD + fi + + p='less -e' + if [ -n "$UNATTENDED" ]; then p=cat; + elif [ -n "$PAGER" ]; then p=$PAGER; fi + ( for f in $DISPLAY_LIST; do + echo "===>>> pkg-message for $f" + cat $pdb/$f/+DISPLAY + echo '' + done + echo "===>>> Done displaying pkg-message files" ) | $p + ;; + esac + + case "$INSTALLED_LIST" in + *:*:) IFS=':' + echo "===>>> The following actions were performed:" + for f in $INSTALLED_LIST; do echo " $f" ; done ;; + *:) echo "===>>> ${ilist%:} complete" ; echo '' ;; + esac + else + [ -n "$grep_deps" ] && pm_unlink $grep_deps + + # Save state for the parent process to read back in + echo "CUR_DEPS='$CUR_DEPS'" >> $IPC_SAVE + if [ -z "$CONFIG_ONLY" ]; then + echo "DISPLAY_LIST='$DISPLAY_LIST'" >> $IPC_SAVE + echo "INSTALLED_LIST='$INSTALLED_LIST'" >> $IPC_SAVE + fi + [ -z "$NO_BACKUP" -a -z "$BACKUP" ] && + echo "NB_DELETE='$NB_DELETE'" >> $IPC_SAVE + if [ -n "$INTERACTIVE_UPDATE" ]; then + echo "INTERACTIVE_YES='$INTERACTIVE_YES'" >> $IPC_SAVE + echo "INTERACTIVE_NO='$INTERACTIVE_NO'" >> $IPC_SAVE + fi + [ -n "$URB_YES" ] && + echo "URB_DONE_LIST='$URB_DONE_LIST'" >> $IPC_SAVE + fi + + exit ${1:-0} +} + usage () { - echo "portmaster version `grep "[$]FreeBSD:" $0 | cut -d ' ' -f 4`" + version echo '' echo 'Usage:' - echo "Common flags: [--force-config] [-CGgntvw B|b uf|i D|d]" + echo "Common flags: [--force-config] [-CGHgntvw B|b uf|i D|d]" echo " [-m <arguments for make>]" echo " [-x <glob pattern to exclude from building>]" echo "${0##*/} [Common flags] <full name of port directory in $pdb>" @@ -42,40 +218,46 @@ usage () { echo "${0##*/} [Common flags] -p <port directory in $pd>" echo "${0##*/} [Common flags] . [Use in $pd/foo/bar to build that port]" echo '' - echo "${0##*/} --show-work [-Gv] [-m <args for make>] <port, as above>" + echo "${0##*/} --show-work [-Gv] [-m <args>] <single port, as above>" echo '' echo "${0##*/} [Common flags] -o <new port dir in $pd> <installed port>" echo "${0##*/} [Common flags] [-R] -r <name/glob of port directory in $pdb>" echo '' - echo "${0##*/} -a [Common flags]" + echo "${0##*/} [Common flags] -a" echo '' echo "${0##*/} -[l|L]" echo '' echo "${0##*/} [-b D|d] -e <full name of port directory in $pdb>" echo "${0##*/} [-b D|d] -s" echo '' + echo "${0##*/} [--force-config] [-aftv] -F" + echo '' echo "${0##*/} --clean-distfiles" echo "${0##*/} --clean-distfiles-all" echo '' - echo "${0##*/} -h" + echo "${0##*/} --check-depends" + echo '' + echo "${0##*/} -h|--help" + echo "${0##*/} --version" echo '' echo "--force-config 'make config' for all ports (must be first option)" - echo "-C prevents 'make clean' being run in port directory" - echo "-G prevents recursive 'make config' (unsets --force-config)" + echo "-C prevents 'make clean' from being run before building" + echo "-G prevents recursive 'make config' (overrides --force-config)" + echo "-H hide details of the port build and install in a log file" echo '-B prevents creation of the backup package for the installed port' echo '-b create and keep a backup package of an installed port' echo '-g create a package of the new port' - echo '-n do not actually make or install any ports' + echo '-n run through configure, but do not make or install any ports' echo '-t recurse dependencies thoroughly, using all-depends-list' echo '-v verbose output' echo '-w save old shared libraries before deinstall' echo "-u unattended mode -- accept defaults for all but 'make config'" echo '[-R] -f always rebuild ports (overrides -i)' - echo '-i interactive update mode' - echo '-D prevents cleaning of distfiles' + echo '-i interactive update -- ask whether to rebuild ports' + echo '-D no cleaning of distfiles' echo '-d always clean distfiles' echo "-m <arguments for the 'make' command line>" - echo "-x <avoid building ports as dependencies that match this pattern>" + echo "-x <avoid building or updating ports that match this pattern>" echo '' echo '--show-work list what ports are and would be installed' echo '' @@ -90,749 +272,800 @@ usage () { echo '-e expunge a port via pkg_delete, and remove its distfiles' echo '-s clean out stale ports that used to be depended on' echo '' + echo '[--force-config] [-aftv] -F fetch distfiles only (mutually exclusive of -G)' + echo '' echo '--clean-distfiles offer to delete stale distfiles' echo '--clean-distfiles-all delete stale distfiles without prompting' echo '' - echo '-h display this help message' + echo '--check-depends cross-check and update dependency information for all ports' + echo '' + echo '-h|--help display this help message' + echo '--version display the version number' echo '' echo 'Please see the portmaster(8) man page for more information' - exit ${1:-1} + safe_exit ${1:-1} } -fail () { - echo '' - echo "===>>> $1" - echo "===>>> Aborting update" +pm_cd () { builtin cd $1 2>/dev/null || return 1; } +pm_kill () { /bin/kill $* >/dev/null 2>/dev/null; } +pm_make () { /usr/bin/make $PM_MAKE_ARGS $*; } +pm_make_b () { /usr/bin/make $PM_MAKE_ARGS BEFOREPORTMK=yes $*; } +pm_mktemp () { /usr/bin/mktemp -t f-${PARENT_PID}-$1; } +pm_unlink () { /bin/test -e $1 && /bin/unlink $1; } - if [ "$$" -eq "$PARENT_PID" ]; then - trap_exit fail - else - safe_exit 1 +# Superuser versions for commands that need root privileges +# +# The following are used once, so they have $PM_SU_CMD in line: +# truncate, pkg_create, cp, /etc/rc.d/ldconfig, touch + +pm_find_s () { $PM_SU_CMD /usr/bin/find $*; } +pm_install_s () { $PM_SU_CMD /usr/bin/install -o root \ + -g wheel -m 644 $1 $2; } +pm_make_s () { $PM_SU_CMD /usr/bin/make $PM_MAKE_ARGS $*; } +pm_mkdir_s () { $PM_SU_CMD /bin/mkdir -p $1; } +pm_pkg_delete_s () { $PM_SU_CMD /usr/sbin/pkg_delete $*; } +pm_rm_s () { $PM_SU_CMD /bin/rm $*; } +pm_rmdir_s () { $PM_SU_CMD /bin/rmdir $*; } +pm_unlink_s () { /bin/test -e $1 && $PM_SU_CMD /bin/unlink $1; } + +#=============== End functions we always want to have =============== + +# Do this here so it can use the fancy functions above, and default values +# can be overridden in the rc files +if [ "$$" -eq "$PARENT_PID" ]; then + if [ -z "$pd" ]; then + pd=`pm_make_b -f/usr/share/mk/bsd.port.mk -V PORTSDIR` + [ -n "$pd" ] || fail 'The value of PORTSDIR cannot be empty' + fi + if [ -z "$pdb" ]; then + pdb=`pm_make -f/usr/share/mk/bsd.port.mk -V PKG_DBDIR` + [ -n "$pdb" ] || fail 'The value of PKG_DBDIR cannot be empty' + fi + if [ -z "$distdir" ]; then + distdir=`pm_make_b -f/usr/share/mk/bsd.port.mk -VDISTDIR` + [ -n "$distdir" ] || fail 'The value of DISTDIR cannot be empty' + # In case it is a symlink + distdir="${distdir}/" fi -} -pmkill () { - /bin/kill $1 >/dev/null 2>/dev/null - return $? -} + export pd pdb distdir +fi -kill_bad_children () { - # Make parent_N global in case PIDs are random, - # and we have to come back in here after them. - local rc pid ppid command +case "$1" in +--help) usage 0 ;; +--version) version ; exit 0 ;; +--clean-distfiles) CLEAN_DISTFILES=yes ;; +--clean-distfiles-all) CLEAN_DISTFILES=yes ; ALL=yes ;; +--check-depends) CHECK_DEPENDS=yes ;; +--show-work) SHOW_WORK=yes ; RECURSE_THOROUGH=yes ; shift ;; +--force-config) export FORCE_CONFIG=yes ; shift ;; +--*) echo "Illegal option $1" ; echo '' + echo "===>>> Try ${0##*/} --help"; exit 1 ;; +esac - rc=0 - ps -axo pid,ppid,command | while read pid ppid command; do - case "$ppid" in - 1) case "$command" in - *" $0 "*) rc=1 ; parent_2=$pid ; pmkill $pid ;; - *dialog*) pmkill $pid ;; - esac - ;; - $PARENT_PID) - case "$command" in - # Don't kill this pipeline's subshell, but do chase it - *" $0 "*) rc=1 ; parent_2=$pid ;; - *dialog*) pmkill $pid ;; - esac - ;; - $parent_2) - case "$command" in - *" $0 "*) rc=1 ; parent_3=$pid ; pmkill $pid ;; - 'make checksum') rc=1 ; parent_3=$pid ; pmkill $pid ;; - *dialog*) pmkill $pid ;; - esac - ;; - $parent_3|1) - case "$command" in - \[sh\]|*'/sh '*) rc=1 ; parent_4=$pid ; pmkill $pid ;; - *dialog*) pmkill $pid ;; - esac - ;; - $parent_4|1) - case "$command" in - \[sh\]|*'/sh '*) rc=1 ; parent_5=$pid ; pmkill $pid ;; - *dialog*) pmkill $pid ;; - esac - ;; - $parent_5|1) - case "$command" in - *'/fetch '*) rc=1 ; pmkill $pid ;; - *dialog*) pmkill $pid ;; - esac - ;; - esac - done +#=============== Begin functions relevant to --features and main =============== - return $rc +iport_from_origin () { + local dir + dir=`grep -l "@comment ORIGIN:${1}$" $pdb/*/+CONTENTS` + + # It should not happen that more than one port meets this + # requirement, but it can if the pkg data is corrupted. + dir="${dir%%/+CONTENTS*}" + echo ${dir#$pdb/} } -trap_exit () { - local pid +origin_from_pdb () { + local o + o=`grep '@comment ORIGIN:' $pdb/$1/+CONTENTS 2>/dev/null` + echo ${o#@comment ORIGIN:} +} - TRAP=yes +check_regular_file () { + [ ! -L "$1" -a -f "$1" ] || fail "ERROR: $1 is not a regular file!" +} - if [ -n "$portdir" -a -z "$1" ]; then - echo '' - echo "===>>> Upgrade for $portdir exiting due to signal" - elif [ -z "$1" ]; then - echo "===>>> Exiting due to signal" +check_dependency_files () { + # Global: grep_deps + local origin iport ro_opd moved_opd + + origin=$1 ; iport=$2 + + # egrep hates + in file names + case "$origin" in *+*) + origin=`echo $origin | sed 's#\+#\\\\+#g'` ;; esac + case "$ro_opd" in *+*) + ro_opd=`echo $ro_opd | sed 's#\+#\\\\+#g'` ;; esac + case "$moved_opd" in *+*) + moved_opd=`echo $moved_opd | sed 's#\+#\\\\+#g'` ;; esac + + # Always rely on the grep'ed dependencies instead of +REQUIRED_BY + grep_deps=`pm_mktemp grep-deps-${iport}` + egrep -l "DEPORIGIN:($origin|$ro_opd|$moved_opd)$" $pdb/*/+CONTENTS | + cut -f 5 -d '/' | sort -u > $grep_deps + + if [ ! -s "$grep_deps" ]; then + if [ -s "$pdb/$iport/+REQUIRED_BY" ]; then + # No actual dependencies exist, so this file is stale + # Zero it out so that -s mode can find it +# Outdent +if [ -n "$VERBOSE" -o -n "$CHECK_DEPENDS" ]; then + echo " ===>>> No installed ports depend on $iport" + echo " ===>>> Emptying +REQUIRED_BY file. Try ${0##*/} -s" +fi +# Outdent + check_regular_file $pdb/$iport/+REQUIRED_BY + $PM_SU_CMD truncate -s0 $pdb/$iport/+REQUIRED_BY + fi fi + return 0 +} - if [ "$$" -eq "$PARENT_PID" ]; then - for file in ${TMPDIR}/fetchlog-${PARENT_PID}-*; do - pid=`awk '/^MCS_CHILD_PID / {print $2}' $file 2>/dev/null` - test -n "$pid" || continue - echo "===>>> Child process $pid:" - if ! pmkill $pid ; then - if ps -p $pid >/dev/null; then - echo "Did not die!" - fi - fi - rm -f $file - done +update_contents () { + local IFS delete contents origin n_port old_origin iport new_cont + local o_seen line d_missing d_origin d_iport prev_line answer - while ! kill_bad_children ; do - # cheap way to keep it looping - done - fi +# To prevent words in a line being treated individually +IFS=' +' + [ "$1" = 'delete' ] && { delete=yes ; shift; } - safe_exit 1 -} + contents=$1 ; origin=$2 ; n_port=$3 ; old_origin=$4 + iport=${contents#$pdb/} ; iport=${iport%/+CONTENTS} + new_cont=`pm_mktemp contents-${iport}` -safe_exit () { - echo '' - test -n "$grep_deps" && rm -f $grep_deps - test -n "$req_deps" && rm -f $req_deps + if [ -z "$delete" ]; then o_seen=':'; else o_seen=":${origin}:"; fi - if [ "$$" -eq "$PARENT_PID" ]; then - test -n "$NO_DEP_UPDATES" && rm -f $NO_DEP_UPDATES - test -n "$IPC_SAVE" && rm -f $IPC_SAVE - test -n "$DI_FILES" && rm -f $DI_FILES && kill_bad_children - if [ -n "$MASTER_RB_LIST" ]; then - case "$MASTER_RB_LIST" in - */+REQUIRED_BY) ;; - *) rm -f $MASTER_RB_LIST ;; - esac - fi + for line in `cat $contents`; do + if [ -n "$d_missing" ]; then + unset d_missing + d_origin=${line#*DEPORIGIN:} - if [ -z "$TRAP" -a \ - -e "${TMPDIR}/f-${PARENT_PID}-package-flag" -a \ - -n "$pkgrep" ]; then -find ${pkgrep}/ -type f -newer ${TMPDIR}/f-${PARENT_PID}-package-flag -delete - fi + case "$o_seen" in *:${d_origin}:*) + unset prev_line line ; continue ;; esac + o_seen="${o_seen}${d_origin}:" - for file in ${TMPDIR}/f-${PARENT_PID}-*; do - test -f $file && unlink $file - done + if [ "$d_origin" = "$old_origin" ]; then + d_iport=$n_port + d_origin=$origin + else + d_iport=`iport_from_origin $d_origin` + fi - if [ -n "$RESTART" -o -n "$FORCE" ]; then - if [ -z "$TRAP" ]; then - find $pdb -type f -name PM_UPGRADE_DONE_FLAG -delete + if [ -n "$d_iport" ]; then + [ -n "$VERBOSE" -o -n "$CHECK_DEPENDS" ] && + echo " ===>>> Updating @pkgdep for $d_origin" + else + echo " ===>>> $d_origin is listed as a dependency" + echo " ===>>> but there is no installed version" + if [ -n "$CHECK_DEPENDS" ]; then + echo '' + echo -n " ===>>> Delete this dependency data? [n] " + read answer + case "$answer" in + [yY]) unset prev_line line ; continue ;; + esac + fi fi + + # Could be fixed or not, but if we get here write it + # so we can warn the user again later if we need to. + echo "@pkgdep $d_iport" >> $new_cont + echo "@comment DEPORIGIN:$d_origin" >> $new_cont + unset prev_line + continue fi + case "$line" in + "@comment DEPORIGIN:$origin"|"@comment DEPORIGIN:$old_origin") + d_origin=${line#*DEPORIGIN:} + unset prev_line line - if [ -n "$DISPLAY_LIST" ]; then - for f in $DISPLAY_LIST; do - echo "===>>> pkg-message for ${f%/+DISPLAY}" - cat $pdb/$f - echo '' - done + case "$o_seen" in *:${d_origin}:*) continue ;; esac + o_seen="${o_seen}${d_origin}:" - echo "===>>> Done displaying pkg-message files" - fi - else - # Save state for the parent process to read back in - echo "CURRENT_DEPS_O='$CURRENT_DEPS_O'" >> $IPC_SAVE - echo "CURRENT_DEPS_I='$CURRENT_DEPS_I'" >> $IPC_SAVE - echo "IGNOREME_YES='$IGNOREME_YES'" >> $IPC_SAVE - echo "DISPLAY_LIST='$DISPLAY_LIST'" >> $IPC_SAVE + echo "@pkgdep $n_port" >> $new_cont + echo "@comment DEPORIGIN:$origin" >> $new_cont + ;; + '@comment DEPORIGIN:'*) + d_origin=${line#*DEPORIGIN:} + case "$o_seen" in *:${d_origin}:*) + unset prev_line line ; continue ;; esac + o_seen="${o_seen}${d_origin}:" + ;; + '@pkgdep '|@pkgdep) d_missing=yes ;; + @pkgdep*) d_iport="${line#@pkgdep }" + [ -d "$pdb/$d_iport" ] || d_missing=yes ;; + esac + [ -n "$prev_line" ] && echo $prev_line >> $new_cont + prev_line=$line + done + [ -n "$prev_line" ] && echo $prev_line >> $new_cont - if [ -n "$INTERACTIVE_UPDATE" ]; then - echo "INTERACTIVE_YES='$INTERACTIVE_YES'" >> $IPC_SAVE - echo "INTERACTIVE_NO='$INTERACTIVE_NO'" >> $IPC_SAVE - fi - if [ -n "$URB_YES" ]; then - echo "URB_DONE_LIST='$URB_DONE_LIST'" >> $IPC_SAVE - fi - if [ -n "$FORCE" ]; then - echo "FORCE_DONE_LIST='$FORCE_DONE_LIST'" >> $IPC_SAVE - fi - fi + cmp -s $contents $new_cont && { pm_unlink $new_cont ; return; } - exit ${1:-0} + check_regular_file $contents + [ -n "$VERBOSE" -o -n "$CHECK_DEPENDS" ] && + echo " ===>>> Installing the new +CONTENTS file" + pm_install_s $new_cont $contents + pm_unlink $new_cont } -update_contents () { - local tempfile +find_moved_port () { + # Global: moved_opd moved_npd + local sf iport IFS l - tempfile=`mktemp -t tempfile-${new_port}` + sf=$1 # Search for + iport=$2 + # Old port directory, do not update if we recurse + [ -z "$moved_opd" ] && moved_opd=$1 - sed "s/@pkgdep $1/@pkgdep $2/" $dep_port_contents > $tempfile && - mv $tempfile $pdb/$dep_port/+CONTENTS - chmod 644 $pdb/$dep_port/+CONTENTS + # To avoid having each word of the reason treated separately + IFS=' +' + for l in `grep "^$sf|" $pd/MOVED`; do + case "$l" in + ${sf}\|\|*) [ -n "$iport" ] || iport=`iport_from_origin $sf` + if [ -e "$pdb/$iport/+IGNOREME" ]; then + if [ -n "$VERBOSE" ]; then + echo '' + echo " ===>>> The $sf port has been deleted" + echo " ===>>> Reason: ${l##*|}" + echo " ===>>> Skipping it due to +IGNOREME file" + echo '' + fi + return 0 + else + fail "The $sf port has been deleted: ${l##*|}" + fi + ;; + ${sf}\|*) moved_npd=${l#*\|} # New port directory + moved_npd=${moved_npd%%\|*} + echo '' + echo " ===>>> The $sf port moved to $moved_npd" + echo " ===>>> Reason: ${l##*|}" + echo '' + find_moved_port $moved_npd + ;; + esac + done - if [ -n "$oldportdir" ]; then - sed "s%N:${oldportdir}\$%N:${newportdir}%" $dep_port_contents > $tempfile && - mv $tempfile $pdb/$dep_port/+CONTENTS - chmod 644 $pdb/$dep_port/+CONTENTS + if [ -z "$moved_npd" ]; then + echo '' + echo " ===>>> No $pd/$1 exists, and no information" + echo " ===>>> about $1 can be found in $pd/MOVED" + echo '' + [ -n "$iport" ] || iport=`iport_from_origin $sf` + if [ -e "$pdb/$iport/+IGNOREME" ]; then + return 0 + else + return 1 + fi fi + return 0 } -dep_warn () { - local num_ports1 +read_distinfos () { + local pkg iport origin distinfo disc1 f disc2 - echo '' - echo "===>>> Warning! Potential unrecorded dependencies on $new_port" - echo "===>>> From existing +CONTENTS files:" - grep -B1 DEPORIGIN:$upg_origin$ $pdb/*/+CONTENTS | - sort -u | sed -e "s#$pdb/##" -e 1d | less -F - num_ports1=`grep DEPORIGIN:$upg_origin$ $pdb/*/+CONTENTS | - sort -u | wc -l | awk '{print $1}'` - echo "===>>> $num_ports1 ports" - echo '' -} + echo "===>>> Gathering distinfo list for installed ports" + for pkg in ${pdb}/*; do + [ -d $pkg ] || continue + iport=${pkg#$pdb/} + origin=`origin_from_pdb $iport` -update_reqfile () { - local num_ports2 sdiff_deps + if [ ! -d "$pd/$origin" ]; then + find_moved_port $origin $iport >/dev/null + [ -n "$moved_npd" ] || continue + origin=$moved_npd + fi - dep_warn - num_ports2=`wc -l $req_deps | awk '{print $1}'` - echo "===>>> From $pdb/$upg_port/+REQUIRED_BY:" - less -F $req_deps - echo "===>>> $num_ports2 ports" - echo '' - echo "===>>> Use dependencies from existing +CONTENTS files [c]" - echo "===>>> Use dependencies from existing +REQUIRED_BY file [r]" - echo "===>>> Use sdiff to edit both files into a new file [s]" - echo '' - if [ -z "$UNATTENDED" ]; then - echo -n "===>>> Update dependency list? [r] " - read DEPUPDATE - - case "$DEPUPDATE" in - [cC]) mv $grep_deps $req_deps ; unset grep_deps ;; - [sS]) sdiff_deps=`mktemp -t sdiff-deps-${short_port}` - sdiff -o $sdiff_deps --text --suppress-common-lines \ - --width=`tput columns` $req_deps $grep_deps - mv $sdiff_deps $req_deps - ;; - esac - else - echo "===>>> Default (use +REQUIRED_BY file) in unattended mode" - fi -} + pm_cd $pd/$origin || continue -update_port () { - local upd upd_origin + if [ -s distinfo ]; then + distinfo=distinfo + else + distinfo=`pm_make -V MD5_FILE` + fi - if [ -n "$NO_DEP_UPDATES" ]; then - rm -f $NO_DEP_UPDATES - unset NO_DEP_UPDATES - fi + if [ -s "$distinfo" ]; then + grep '^MD5' $distinfo | while read disc1 f disc2; do + f=${f#(} ; f=${f%)} + echo $f >> $DI_FILES + done + fi + done +} - case "$1" in - -p) upd=$2 - test -n "$URB_YES" && upd_origin=${2#$pd/} - ;; - *) upd=$1 - test -n "$URB_YES" && upd_origin=`origin_from_pdb $pdb/$1` - ;; - esac +#=============== End functions relevant to --features and main =============== +#=============== Begin code relevant only to --features =============== - echo "===>>> Launching child to update ${upd#$pd/}" - echo '' - if [ -z "$NO_ACTION" ]; then - ($0 $ARGS $@) || fail "Update for $upd failed" - . $IPC_SAVE +if [ -n "$CLEAN_DISTFILES" ]; then + # Set the file name here since we are usually called in a subshell + DI_FILES=`pm_mktemp DI-FILES` + read_distinfos - # Only do this if we are in the +REQUIRED_BY code to - # avoid nasty (potential) circular dependencies - if [ -n "$URB_YES" ]; then - URB_DONE_LIST="${URB_DONE_LIST}${upd_origin}:" + echo "===>>> Checking for stale distfiles" + for df in `find $distdir -type f`; do + f=${df#$distdir} + if ! grep -ql $f $DI_FILES; then + if [ -n "$ALL" ]; then + echo "===>>> Deleting $f" + pm_unlink $df + else + echo -n "===>>> Delete stale file: ${f}? [y] " + read answer + case "$answer" in + [nN]*) continue ;; + *) pm_unlink $df ;; + esac + fi fi - else - test -n "$VERBOSE" && - echo "===>>> Build canceled due to -n flag" - fi + done - if [ -n "$UPDATE_ALL" ]; then - echo "===>>> Returning to update check of installed ports" - elif [ -n "$UPDATE_REQ_BYS" ]; then - return 0 - elif [ -n "$CONFIG_ONLY" ]; then - echo "===>>> Continuing 'make config' dependency check for $portdir" - else - echo "===>>> Returning to dependency check for $portdir" - fi + find -d $distdir -type d -empty -delete + safe_exit +fi - return 0 -} +if [ -n "$CHECK_DEPENDS" ]; then + d_orig_ok=':' +IFS=' +' + for pkg in $pdb/*; do + [ -d "$pkg" ] || continue -check_interactive () { - local UPD_OR_NOT + iport=${pkg#$pdb/} + echo "===>>> Checking $iport" - if [ -n "$INTERACTIVE_UPDATE" ]; then - case "$INTERACTIVE_YES" in - *:${1}:*) return 0 ;; - esac + [ -r "$pkg/+CONTENTS" ] || { + echo " ===>>> Warning: No +CONTENTS file!"; + continue; } - case "$INTERACTIVE_NO" in - *:${1}:*) return 1 ;; - esac + origin=`origin_from_pdb ${pkg#$pdb/}` + [ -n "$origin" ] || { + echo " ===>>> Warning: No ORIGIN in +CONTENTS file"; + continue; } - echo -n "===>>> Update ${1}? [y] " - read UPD_OR_NOT - case "$UPD_OR_NOT" in - [nN]*) INTERACTIVE_NO="${INTERACTIVE_NO}${1}:" - return 1 - ;; - *) INTERACTIVE_YES="${INTERACTIVE_YES}${1}:" ;; - esac - fi + if [ ! -d "$pd/$origin" ]; then + echo " ===>>> $pd/$origin does not exist" + echo " ===>>> This port should probably be updated" + continue + fi - return 0 -} + check_dependency_files $origin $iport + if [ -s "$grep_deps" ]; then + if [ -e "$pkg/+REQUIRED_BY" ]; then + sort $pkg/+REQUIRED_BY | cmp -s $grep_deps - || + do_update=yes + check_regular_file $pkg/+REQUIRED_BY + else + do_update=yes + fi + if [ -n "$do_update" ]; then + unset do_update + echo " ===>>> Updating +REQUIRED_BY" + pm_install_s $grep_deps $pkg/+REQUIRED_BY + fi + fi + [ -n "$grep_deps" ] && { + pm_unlink $grep_deps && unset grep_deps; } -iport_from_origin () { - local dir + update_contents $pkg/+CONTENTS + done + exit 0 +fi - dir=`grep -l "@comment ORIGIN:${1}$" $pdb/*/+CONTENTS` +#=============== End code relevant only to --features =============== - # It should not happen that more than one port meets this - # requirement, but it can if the pkg data is corrupted. - dir="${dir%%/+CONTENTS*}" - dir="${dir#$pdb/}" +# Save switches for potential child processes +while getopts 'BCDFGHLRabde:fghilm:nop:r:stuvwx:' COMMAND_LINE_ARGUMENT ; do + case "${COMMAND_LINE_ARGUMENT}" in + B) NO_BACKUP=yes; ARGS="-B $ARGS" ;; + C) DONT_PRE_CLEAN=yes; ARGS="-C $ARGS" ;; + D) DONT_SCRUB_DISTFILES=yes; ARGS="-D $ARGS" ;; + F) FETCH_ONLY=yes; ARGS="-F $ARGS" ;; + G) NO_RECURSIVE_CONFIG=yes; unset FORCE_CONFIG ; ARGS="-G $ARGS" ;; + H) HIDE_BUILD=yes; ARGS="-H $ARGS" ;; + L) LIST_PLUS=yes ;; + R) RESTART=yes ; ARGS="-R $ARGS" ;; + a) UPDATE_ALL=yes ;; + b) BACKUP=yes; ARGS="-b $ARGS" ;; + d) ALWAYS_SCRUB_DISTFILES=yes; ARGS="-d $ARGS" ;; + e) EXPUNGE=$OPTARG ;; + f) export FORCE=yes ;; + g) MAKE_PACKAGE=yes; ARGS="-g $ARGS" ;; + h) usage 0 ;; + i) INTERACTIVE_UPDATE=yes; ARGS="-i $ARGS" ;; + l) LIST=yes ;; + m) export PM_MAKE_ARGS=$OPTARG # For 'make checksum' + ARGS="-m $PM_MAKE_ARGS $ARGS" + ;; + n) NO_ACTION=yes; ARGS="-n $ARGS" ;; + o) REPLACE_ORIGIN=yes ;; + p) portdir="${OPTARG#$pd/}" ; portdir=${portdir%/} ;; + r) UPDATE_REQ_BYS=yes ; portdir=`origin_from_pdb $OPTARG` ;; + s) CLEAN_STALE=yes ;; + t) RECURSE_THOROUGH=yes; ARGS="-t $ARGS" ;; + u) UNATTENDED=yes; ARGS="-u $ARGS" ;; + v) VERBOSE=yes; ARGS="-v $ARGS" ;; + w) SAVE_SHARED=yes; ARGS="-w $ARGS" ;; + x) EXCL=$OPTARG ;; + *) echo '' ; echo "===>>> Try ${0##*/} --help"; exit 1 ;; + esac +done +shift $(( $OPTIND - 1 )) - echo $dir -} +# Error checking for getopts +[ -n "$FORCE" ] && unset INTERACTIVE_UPDATE +if [ -n "$UNATTENDED" ]; then + unset INTERACTIVE_UPDATE + if [ -z "$DONT_SCRUB_DISTFILES" -a -z "$ALWAYS_SCRUB_DISTFILES" ]; then + ALWAYS_SCRUB_DISTFILES=yes + ARGS="-d $ARGS" + fi +fi +[ -n "$BACKUP" -a -n "$NO_BACKUP" ] && + fail "The -b and -B options are mutually exclusive" +[ -n "$ALWAYS_SCRUB_DISTFILES" -a -n "$DONT_SCRUB_DISTFILES" ] && + fail "The -d and -D options are mutually exclusive" +[ -n "$FETCH_ONLY" -a -n "$NO_RECURSIVE_CONFIG" ] && + fail "The -F and -G options are mutually exclusive" +if [ -n "$EXCL" ]; then + case "$EXCL" in + -*) fail 'The -x option requires an argument' ;; + *) ARGS="-x $EXCL $ARGS" ;; + esac +fi -origin_from_pdb () { - grep '@comment ORIGIN' ${1}/+CONTENTS 2>/dev/null | cut -f2 -d':' +#=============== Begin functions for getopts features and main =============== + +check_state () { + # Global: state + local state_set + + if egrep -ql '^(FORBIDDEN|DEPRECATED|BROKEN|IGNORE)' Makefile; then + for state in FORBIDDEN DEPRECATED BROKEN IGNORE; do + state_set=`pm_make -V $state` + if [ -n "$state_set" ]; then + echo " ===>>> This port is marked $state" + printf " ===>>> $state_set\n" + echo '' + return 1 + fi + done + fi + return 0 } check_for_updates () { - local upd_port port_ver do_update + # Global: num_updates + local list iport origin port_ver udf do_update - upd_port=`origin_from_pdb $pdb/$1` - if [ -z "$upd_port" ]; then + [ "$1" = 'list' ] && { list=yes ; shift; } + + iport=$1 ; origin=${2:-`origin_from_pdb $iport`} + if [ -z "$origin" ]; then if [ -n "$VERBOSE" ]; then - echo "===>>> No ORIGIN in $pdb/$1/+CONTENTS" + echo "===>>> No ORIGIN in $pdb/$iport/+CONTENTS" echo '' fi return 0 fi - if [ -d "$pd/$upd_port" ]; then - if ! cd $pd/$upd_port 2>/dev/null; then - if [ -e "$pdb/$1/+IGNOREME" ]; then - echo "===>>> Warning: Unable to cd to $pd/$upd_port" - echo "===>>> Continuing due to $pdb/$1/+IGNOREME" + if [ -d "$pd/$origin" ]; then + if ! pm_cd $pd/$origin; then + if [ -e "$pdb/$iport/+IGNOREME" ]; then + echo " ===>>> Warning: Unable to cd to $pd/$origin" + echo " ===>>> Continuing due to $pdb/$iport/+IGNOREME" return 0 else - fail "Cannot cd to port directory: $pd/$upd_port" + fail "Cannot cd to port directory: $pd/$origin" fi fi - port_ver=`make $PM_MAKE_ARGS -V PKGNAME` - - [ -z "$port_ver" ] && fail "Is $pd/$upd_port/Makefile missing?" - - if [ "$1" = "$port_ver" ]; then - if [ -z "$LIST" -a -z "$LIST_PLUS" ]; then - # Keep list both ways to increase performance - CURRENT_DEPS_O="${CURRENT_DEPS_O}${upd_port}:" - CURRENT_DEPS_I="${CURRENT_DEPS_I}${1}:" - fi + port_ver=`pm_make -V PKGNAME` + [ -z "$port_ver" ] && fail "Is $pd/$origin/Makefile missing?" + udf="$pdb/$iport/PM_UPGRADE_DONE_FLAG" + if [ "$iport" = "$port_ver" ]; then if [ -n "$FORCE" ]; then - if [ ! -e "$pdb/$1/PM_UPGRADE_DONE_FLAG" ]; then + check_restart_and_udf $udf $iport || do_update=yes - fi - elif [ -n "$URB_YES" -a -n "$RESTART" ]; then - if [ ! -e "$pdb/$1/PM_UPGRADE_DONE_FLAG" ]; then - if grep -q $1 $MASTER_RB_LIST; then - do_update=yes - fi - else - return 0 - fi + elif [ -n "$URB_YES" ]; then + # Outdent + case "$MASTER_RB_LIST" in *" $iport "*) + if ! check_restart_and_udf $udf $iport; then + do_update=yes else + URB_DONE_LIST="${URB_DONE_LIST}${upg_port}:" + fi ;; + esac + # Outdent + elif [ -n "$LIST_PLUS" ]; then + check_state + return 0 + elif [ -n "$LIST" ]; then return 0 fi else - case `pkg_version -t $1 $port_ver` in + case `pkg_version -t $iport $port_ver` in \<) do_update=yes ;; =) ;; # Should not be reached - *) if [ -n "$VERBOSE" ]; then - echo '' + \>) if [ -n "$VERBOSE" ]; then echo " ===>>> Port version $port_ver does not" - echo " ===>>> seem newer than installed $1" - echo '' - fi - ;; + echo " ===>>> seem newer than installed $iport" + fi + if [ -n "$FORCE" ]; then + check_restart_and_udf $udf $iport || + do_update=yes + elif [ -n "$URB_YES" ]; then + # Outdent + case "$MASTER_RB_LIST" in *" $iport "*) + if ! check_restart_and_udf $udf $iport; then + do_update=yes + else + URB_DONE_LIST="${URB_DONE_LIST}${upg_port}:" + fi ;; + esac + # Outdent + fi ;; esac fi else - # This will fail if it doesn't exist anymore - # It will return 1 if we know nothing about the port - find_moved_port $upd_port || return 0 + find_moved_port $origin $iport - # If the port has moved, we have to update it - do_update=yes + # If the port has moved, we have to update it, otherwise ignore + [ -n "$moved_npd" ] && do_update=yes fi - if [ -n "$do_update" ]; then - case "$2" in - list) if [ -z "$newportdir" ]; then - echo " ===>>> New version available: $port_ver" - if [ -e "$pdb/$1/+IGNOREME" ]; then - echo " ===>>> +IGNOREME file is present for $1" - fi - num_updates=$(( $num_updates + 1 )) - else - unset newportdir - fi - return 0 - ;; - esac + [ -z "$do_update" ] && { + CUR_DEPS="${CUR_DEPS}${iport}:${origin}:" ; return 0; } - if ! check_interactive $1 ; then - return 0 + if [ -n "$list" ]; then + if [ -z "$moved_npd" ]; then + echo " ===>>> New version available: $port_ver" + [ -e "$pdb/$iport/+IGNOREME" ] && + echo " ===>>> +IGNOREME file is present for $1" + check_state + num_updates=$(( $num_updates + 1 )) + else + unset moved_npd fi - - update_port $1 || return 1 + return 0 fi + check_interactive $iport || return 0 + update_port $iport || return 1 return 0 } -find_moved_port () { - # newportdir and oldportdir are used globally - local sf IFS l +init_packages () { + # Global: packages pbu + local pkgrep - sf=$1 + packages=`pm_make -f/usr/share/mk/bsd.port.mk -V PACKAGES` + [ -n "$packages" ] || fail 'The value of PACKAGES cannot be empty' - # To avoid having each word of the reason treated separately - IFS=' -' - for l in `grep "^$sf" $pd/MOVED`; do - case "$l" in - ${sf}\|\|*) fail "The $sf port has been deleted: ${l##*|}" - ;; - ${sf}\|*) newportdir=${l#*\|} - newportdir=${newportdir%%\|*} - echo '' - echo "===>>> The $sf port moved to $newportdir" - echo "===>>> Reason: ${l##*|}" - echo '' - find_moved_port $newportdir - ;; - esac - done - - if [ -z "$newportdir" ]; then + # Compatibility shim for users who had previously defined this + pkgrep=`pm_make -f/usr/share/mk/bsd.port.mk -V PKGREPOSITORY` + if [ ! "$packages" = "${pkgrep%/All}" ]; then echo '' - echo "===>>> No $pd/$1 exists, and no information" - echo "===>>> about $1 can be found in $pd/MOVED" - echo '' - return 1 + echo "===>>> The PACKAGES and PKGREPOSITORY variables conflict" + fail "Set PACKAGES only - 'man portmaster' for more information" fi - oldportdir=$1 + pbu=$packages/portmaster-backup - return 0 + if [ ! -d "$pbu" ]; then + [ -n "$PM_SU_VERBOSE" ] && + echo "===>>> Creating $pbu" + pm_mkdir_s $pbu + fi + export packages pbu } -ports_by_category () { - local pkg - - for pkg in $pdb/*; do - if [ -s "$pkg/+REQUIRED_BY" ]; then - if grep -q '^@pkgdep ' $pkg/+CONTENTS 2>/dev/null; then - branches="$branches $pkg" - else - trunks="$trunks $pkg" - fi +backup_package () { + echo "===>>> Creating a backup package for old version $1" + pm_cd $pbu || fail "Cannot cd into $pbu to create a package" + if $PM_SU_CMD pkg_create -b $1; then + if [ -n "$BACKUP" ]; then + echo " ===>>> Package saved to $pbu" + echo '' else - if grep -q '^@pkgdep ' $pkg/+CONTENTS 2>/dev/null; then - leaves="$leaves $pkg" - else - test -s $pkg/+CONTENTS && roots="$roots $pkg" - fi + local pkg ; pkg=`echo $1.*` + NB_DELETE="${NB_DELETE}${pkg} " fi - done -} - -dependency_check () { - local dep_port_list dep_port ign_p cur_p upd_args p op old_p conflicts glob conflict_port - - # Print a message here because sometimes list generation takes - # a long time to return. - echo "===>>> Gathering dependency list for $portdir from ports" - dep_port_list=`make $PM_MAKE_ARGS $1 | sort -u` - - if [ -z "$dep_port_list" ]; then - echo "===>>> No dependencies for $portdir" - [ -n "$SHOW_WORK" ] && safe_exit - return 0 else - if [ -n "$CONFIG_ONLY" ]; then - echo "===>>> Starting recursive 'make config' check" + if [ -z "$UNATTENDED" ]; then + echo '' + echo "===>>> Backup package creation failed for ${1}!" + echo '' + echo "===>>> Ignore this error [i]" + echo "===>>> Abort [a]" + echo '' + echo -n "===>>> How would you like to proceed? [i] " + local answer ; read answer + case "$answer" in + a) fail "Backup package creation failed for $1" ;; + esac else - echo "===>>> Starting dependency check" + fail "Backup package creation failed for $1" fi fi +} - for dep_port in $dep_port_list; do - case "$dep_port" in - *${EXCL}*) test -n "$VERBOSE" && -echo "===>>> Skipping ${dep_port#$pd/} because it matches the pattern: *${EXCL}*" - continue - ;; - esac - - if [ -n "$SHOW_WORK" ]; then - orig=${dep_port#$pd/} - dir=`iport_from_origin $orig` - case "$dir" in - '') echo "===>>> NOT INSTALLED $orig" ;; - *) echo "===>>> Installed $orig" ;; - esac - - continue - fi - - test -n "$VERBOSE" && - echo "===>>> Checking dependency: $dep_port" - - # Do this first to catch out of date dependencies - if [ -n "$CONFIG_ONLY" ]; then - case "$CONFIG_SEEN_LIST" in - *:${dep_port#$pd/}:*) continue ;; - esac - CONFIG_SEEN_LIST="${CONFIG_SEEN_LIST}${dep_port#$pd/}:" - fi +find_dl_distfiles () { + # Global: dist_list dist_list_files + local file - case "$CURRENT_DEPS_O" in - *:${dep_port#$pd/}:*) continue ;; - esac + # We need to define these for use in the deletion/update process. + if pm_cd $pd/$1; then + dist_list=`pm_make_b -V OPTIONSFILE` + dist_list="${dist_list%options}distfiles" - case "$FORCE_DONE_LIST" in - *:${dep_port#$pd/}:*) continue ;; - esac + [ -s "$dist_list" ] || { unset dist_list ; return 0; } + [ -n "$DONT_SCRUB_DISTFILES" ] && return 0 - cd $dep_port && - conflicts=`make BEFOREPORTMK=yes $PM_MAKE_ARGS -V CONFLICTS` - for glob in $conflicts; do - conflict_port=`pkg_info -I $glob 2>/dev/null | - cut -f1 -d' '` - if [ -n "$conflict_port" ]; then - echo '' - echo "===>>> The dependency for ${dep_port#$pd/}" - echo " seems to be handled by $conflict_port" - echo '' - dep_port="$pd/`origin_from_pdb $pdb/$conflict_port`" - fi + # The grep is needed to allow for comments, etc. + for file in `grep ^DISTFILE $dist_list`; do + file=${file#DISTFILE:} ; file=${file%%:*} + dist_list_files="${dist_list_files}${file#*/} " done - - ign_p='' - cur_p=`iport_from_origin ${dep_port#$pd/}` - if [ -n "$cur_p" ]; then - upd_args=$cur_p - ign_p=$cur_p - else - upd_args="-p $dep_port" # Sensible default - - # Check to see if the dependency has moved because - # if so, we need to update the old port to fix it - p=${dep_port#$pd/} - op=`sed -ne "s#\([^|]*\)|$p|.*#\1#p" $pd/MOVED` - - # In case there is more than one match, use the latest - op=${op##* } - - if [ -n "$op" ]; then - old_p=`iport_from_origin ${op}` - if [ -n "$old_p" ]; then - upd_args=$old_p - ign_p=$old_p - fi - fi - fi - - if [ -e "$pdb/$ign_p/+IGNOREME" ]; then - if [ -n "$VERBOSE" ]; then - echo '' - echo "===>>> Skipping $ign_p due to +IGNOREME file" - echo '' - fi - continue - fi - - if [ -n "$FORCE" ]; then - if [ ! -e "$pdb/$cur_p/PM_UPGRADE_DONE_FLAG" ]; then - echo "===>>> Forcing update for $dep_port" - update_port $upd_args - continue - fi - fi - - if [ -z "$cur_p" -a -n "$old_p" ]; then - cur_p=$old_p - fi - - if [ -n "$URB_YES" -a -n "$cur_p" ]; then - case "$URB_DONE_LIST" in - *:${dep_port#$pd/}:*) continue ;; - esac - - if grep -q $cur_p $MASTER_RB_LIST; then - if ! check_interactive $cur_p ; then - continue - fi - - if [ -z "$RESTART" -a -z "$FORCE" ]; then - update_port $cur_p || return 1 - else - check_for_updates $cur_p || return 1 - fi - continue - fi - fi - - if [ -n "$cur_p" ]; then - check_for_updates $cur_p - else - if ! check_interactive $dep_port ; then - continue - fi - - update_port -p $dep_port - fi - done - if [ -n "$CONFIG_ONLY" ]; then - echo "===>>> Recursive 'make config' check complete for $portdir" else - echo "===>>> Dependency check complete for $portdir" - echo '' + local port_dbdir + # The port might have moved, etc.; so take a stab at it, + # but do not take a chance with a possibly wrong answer + port_dbdir=`pm_make_b -f/usr/share/mk/bsd.port.mk -V PORT_DBDIR` + dist_list="$port_dbdir/${1##*/}/distfiles" + + [ -s "$dist_list" ] || { unset dist_list ; return 0; } + [ -n "$DONT_SCRUB_DISTFILES" ] && return 0 + + # Do not strip the subdir, we will use it in delete_all + for file in `grep ^DISTFILE $dist_list`; do + file=${file#DISTFILE:} ; file=${file%%:*} + dist_list_files="${dist_list_files}${file} " + done fi - - [ -n "$SHOW_WORK" ] && safe_exit } -unset_recursive_config () { - unset CONFIG_SEEN_LIST CONFIG_ONLY -} +delete_dist_list () { + [ -n "$dist_list" ] || return 0 + + local dir -req_by_error () { - local DISCARD + [ -n "$PM_SU_VERBOSE" ] && echo "===>>> Deleting $dist_list" + pm_unlink_s $dist_list - echo "===>>> WARNING! $pdb/$1/+REQUIRED_BY " - echo "===>>> shows that $2 requires $1, but " - echo "===>>> $2 does not seem to be installed" - echo -n "===>>> Press Enter to proceed " - read DISCARD + dir=`find ${dist_list%/distfiles} -type d -empty 2>/dev/null` + if [ -d "$dir" ]; then + [ -n "$PM_SU_VERBOSE" ] && + echo "===>>> Deleting the $dir directory" + pm_rmdir_s $dir + fi } find_and_delete_distfiles () { - # old_distpattern is used for subsequent invocations of the function - # distfiles_checked is used globally - local distpattern file DELORNOT + # Global: distfiles distfiles_checked delete_all + local ps pattern file answer + + ps=${port_subdir#$distdir} - distpattern=${1%[_-]*} - [ "$distpattern" = "$old_distpattern" ] && return 0 - for file in ${distpattern}*; do + pattern=${1%[_-]*} + for file in ${pattern}*; do # This generally means the pattern did not match case "$file" in - *\*) old_distpattern=$distpattern - find_and_delete_distfiles ${distpattern} - continue + *\*) [ "$pattern" = "${pattern%[_-]*}" ] && return 0 + # This will happen for files like foo-bar_baz-1.23 + find_and_delete_distfiles $pattern ;; esac - case "$distfiles_checked" in - *${file}*) continue ;; - esac + case "$distfiles_checked" in *:${file}:*) continue ;; esac + [ -f "$file" ] || continue case "$distfiles" in - *${file}*) - distfiles_checked="$file $distfiles_checked" - if [ -n "$VERBOSE" -a -z "$do_delete" ]; then - echo "===>>> Keeping current distfile: $file" - fi + *" ${file} "*) + distfiles_checked="${distfiles_checked}${file}:" + [ -n "$VERBOSE" ] && + echo "===>>> Keeping current distfile: $file" continue # Do not delete current version ;; - *) [ ! -d "$file" ] || continue - if [ -e "$DI_FILES" ]; then - grep -q \(${file}\) $DI_FILES && continue + *) if [ -e "$DI_FILES" ]; then + grep -ql ${ps}$file $DI_FILES && continue fi - if [ -n "$ALWAYS_SCRUB_DISTFILES" ]; then + if [ -n "$ALWAYS_SCRUB_DISTFILES" -o \ + -n "$delete_all" ]; then echo "===>>> Deleting stale distfile: $file" - rm -f $file + pm_unlink $file continue fi echo -n "===>>> Delete $file? [n] " - read DELORNOT - case "$DELORNOT" in - [yY]) rm -f $file ;; + read answer + case "$answer" in + [yY]) pm_unlink $file ;; + *) distfiles_checked="${distfiles_checked}${file}:" ;; esac ;; esac done } -delete_stale_distfiles () { - # distfiles is used globally - # distfiles_checked is used globally - # inherit distdir from the environment, but only modify our copy - local distdir dist_subdir file DELORNOT distfile +set_distfiles_and_subdir () { + # Global: dist_list_files distfiles port_subdir distdir - dist_subdir=`make BEFOREPORTMK=yes $PM_MAKE_ARGS -V DIST_SUBDIR` - test -n "$dist_subdir" && distdir="${distdir}/${dist_subdir}/" + [ -z "$dist_list_files" ] && find_dl_distfiles $1 - # Also used in find_and_delete_distfiles() to make sure - # we do not delete the current set of distfiles - distfiles=`make $PM_MAKE_ARGS -V ALLFILES` + if [ -d "$pd/$1" ]; then + pm_cd $pd/$1 || fail "cd to $pd/$1 failed" + else + return 1 + fi + + if [ -z "$distfiles" ]; then + distfiles=`pm_make -V ALLFILES | sed -e 's# *$##g'` + [ -n "$distfile" ] && distfiles=" ${distfiles} " + fi + # Ports may have no distfiles + [ -z "$dist_list_files" -a -z "$distfiles" ] && return 2 - if [ -d "$distdir" ]; then - cd $distdir || fail "cd to $distdir failed!" + if [ -z "$port_subdir" ]; then + port_subdir=`pm_make -V DIST_SUBDIR` + if [ -n "$port_subdir" ]; then + port_subdir="${distdir}${port_subdir}/" + else + port_subdir=$distdir + fi + fi + if [ -d "$port_subdir" ]; then + pm_cd $port_subdir || fail "cd to $port_subdir failed!" else - echo '' ; echo '' - echo "===>>> $distdir does not exist, therefore we" - echo " will assume that all relevant distfiles are gone." echo '' - return 0 + echo "===>>> $port_subdir does not exist, therefore we" + echo ' will assume that all relevant distfiles are gone.' + echo '' + echo " Try ${0##*/} --clean-distfiles[-all] for a full cleanup" + echo '' + return 3 fi + return 0 +} + +delete_stale_distfiles () { + # Global: distfiles port_subdir distfiles_checked delete_all + local file answer + + set_distfiles_and_subdir $1 || return 0 + distfiles_checked=':' # If these two match, it means that the distfiles in the +CONTENTS # file are the current set, so do not delete them. - if [ ! "$dist_list_files" = "${distfiles% }" ]; then + if [ ! " $dist_list_files" = "$distfiles" ]; then for file in $dist_list_files; do - [ -f $file ] || continue + [ -f "$file" ] || continue case "$distfiles" in - *${file}*) - distfiles_checked="$file $distfiles_checked" - if [ -n "$VERBOSE" ]; then - echo "===>>> Keeping current distfile: $file" - fi - continue # Do not delete current version + *" ${file} "*) + distfiles_checked="${distfiles_checked}${file}:" + [ -n "$VERBOSE" ] && + echo "===>>> Keeping current distfile: $file" + continue # Do not delete current version ;; esac - if [ -n "$ALWAYS_SCRUB_DISTFILES" ]; then + if [ -n "$ALWAYS_SCRUB_DISTFILES" -o \ + -n "$delete_all" ]; then echo "===>>> Deleting stale distfile: $file" - rm -f $file + pm_unlink $file continue fi echo -n "===>>> Delete $file? [n] " - read DELORNOT - case "$DELORNOT" in - [yY]) rm -f $file ;; + read answer + case "$answer" in + [yY]) pm_unlink $file ;; + *) distfiles_checked="${distfiles_checked}${file}:" ;; esac done fi @@ -840,241 +1073,134 @@ delete_stale_distfiles () { # Eventually we will hide this behind an "aggressive distfile purge" # flag, but until the DISTFILE stuff is well populated in PORT_DBDIR, # keep doing it both ways. - for distfile in $distfiles; do - find_and_delete_distfiles $distfile + for file in $distfiles $dist_list_files; do + find_and_delete_distfiles $file done + + [ -n "$VERBOSE" ] && { + echo "===>>> Distfile cleaning complete" ; echo ''; } } delete_all_distfiles () { - # do_delete is used globally - local DELORNOT - - if ! cd $pd/$1 2>/dev/null; then + # Global: delete_all distdir + local origin rc delete_current + + # In case we are called more than once + unset delete_all dist_list dist_list_files + origin=$1 + + set_distfiles_and_subdir $origin ; rc=$? + case "$rc" in + 1) echo '' + echo "===>>> No $pd/$origin exists to find the distfile list" + echo " Try ${0##*/} --clean-distfiles[-all] for a full cleanup" echo '' - echo "===>>> No $pd/$1 to cd to in order to delete" - echo " old distfiles, remove by hand if desired" - else - if [ -n "$ALWAYS_SCRUB_DISTFILES" ]; then - echo "===>>> Deleting all distfiles for $1" - do_delete=1 - else - echo -n "===>>> Delete all distfiles for ${1}? [n] " - read DELORNOT - case "$DELORNOT" in - [yY]) do_delete=1 ;; - *) delete_stale_distfiles ;; + if [ -n "$dist_list_files" ]; then + echo "===>>> However, the list of files in $dist_list" + echo -n " should be current. Delete the files on this list? [n] " + local answer f ; read answer + case "$answer" in + [yY]) for f in $dist_list_files; do + if [ -f "${distdir}${f}" ]; then + echo " Deleting ${distdir}${f}" + pm_unlink ${distdir}${f} + fi + done ;; esac fi + return 0 ;; + 2) echo "===>>> This port has no distfiles" ; return 0 ;; + 3) return 0 ;; # port_subdir does not exist + esac - if [ -n "$do_delete" ]; then - delete_stale_distfiles - rm -f $distfiles - find $distdir -type d -empty -delete - fi - fi -} - -init_pkgrep () { - pkgrep=`make $PM_MAKE_ARGS -f/usr/share/mk/bsd.port.mk -VPKGREPOSITORY` - [ -n "$pkgrep" ] || fail 'The value of PKGREPOSITORY cannot be empty' - export pkgrep - mkdir -p $pkgrep -} - -backup_package () { - echo "===>>> Creating a backup package for old version $1" - cd $pkgrep || fail "Cannot cd into the $pkgrep directory for backup" - if pkg_create -b $1; then - echo " ===>>> Package can be found in $pkgrep" + if [ -n "$ALWAYS_SCRUB_DISTFILES" ]; then + echo "===>>> Deleting all distfiles for $origin" + delete_all=yes else - local PROCEED - - if [ -z "$UNATTENDED" ]; then - echo '' - echo "===>>> Backup package creation failed for ${1}!" - echo '' - echo "===>>> Ignore this error [i]" - echo "===>>> Abort update [a]" - echo '' - echo -n "===>>> How would you like to proceed? [i] " - read PROCEED - case "$PROCEED" in - a) fail "Backup package creation failed for $1" ;; - esac - else - fail "Backup package creation failed for $1" - fi + echo "===>>> Delete old and new distfiles for $origin" + echo -n " without prompting? [n] " + local answer ; read answer + case "$answer" in + [yY]) delete_all=yes ;; + *) echo -n "===>>> Delete the current distfiles? [n] " + read answer + case "$answer" in + [yY]) delete_current=yes ;; + esac ;; + esac fi -} - -# Read a global rc file first -if [ -r /etc/portmaster.rc ]; then - . /etc/portmaster.rc -fi - -# Read a local one next, and allow the command line to override -if [ -r "$HOME/.portmasterrc" ]; then - . $HOME/.portmasterrc -fi - -# Set default values here so that they can be overriden above -if [ -z "$pd" ]; then - pd=`make BEFOREPORTMK=yes -f/usr/share/mk/bsd.port.mk -V PORTSDIR` - [ -n "$pd" ] || fail 'The value of PORTSDIR cannot be empty' - export pd -fi -if [ -z "$pdb" ]; then - pdb=`make -f/usr/share/mk/bsd.port.mk -V PKG_DBDIR` - [ -n "$pdb" ] || fail 'The value of PKG_DBDIR cannot be empty' - export pdb -fi -if [ -z "$distdir" ]; then - distdir=`make BEFOREPORTMK=yes -f/usr/share/mk/bsd.port.mk -V DISTDIR` - [ -n "$distdir" ] || fail 'The value of DISTDIR cannot be empty' - # In case it is a symlink - distdir="${distdir}/" - export distdir -fi - -case "$1" in ---clean-distfiles) CLEAN_DISTFILES=yes ;; ---clean-distfiles-all) CLEAN_DISTFILES=yes ; ALL=yes ;; ---show-work) SHOW_WORK=yes ; RECURSE_THOROUGH=yes ; shift ;; ---force-config) FORCE_CONFIG=yes ; export FORCE_CONFIG ; shift ;; -esac -read_distinfos () { - local ugp pkg origin distinfo disc1 file disc2 - - echo "===>>> Gathering distinfo list for installed ports" - [ -n "$upg_port" ] && upg="${pdb}/$upg_port" - - for pkg in $upg ${pdb}/*; do - [ -d $pkg ] || continue - origin=`origin_from_pdb $pkg` + if [ -n "$delete_all" -o -n "$delete_current" ]; then + # Doing this now means less work in delete_stale() + [ -n "$distfiles" ] && eval rm -f $distfiles + fi + delete_stale_distfiles $origin - if [ ! -d "$pd/$origin" ]; then - find_moved_port $origin >/dev/null || continue - origin=$newportdir - fi + # Get back to somewhere safe so we do not + # delete our CWD out from under ourselves + pm_cd $distdir || fail "Cannot cd into $distdir" - cd $pd/$origin 2>/dev/null || continue - distinfo=`make $PM_MAKE_ARGS -V MD5_FILE` - if [ -s "$distinfo" ]; then - grep '^MD5' $distinfo | while read disc1 file disc2; do - echo $file >> $DI_FILES - done - fi - done + find -d $distdir -type d -empty -delete } -if [ -n "$CLEAN_DISTFILES" ]; then - # Set the file name here because this function is - # usually called in a subshell. - DI_FILES=`mktemp -t DI-FILES-$PARENT_PID` - export DI_FILES - read_distinfos +ports_by_category () { + local pkg + [ -n "$VERBOSE" ] && echo "===>>> Sorting ports by category" - echo "===>>> Checking for stale distfiles" - for df in `find $distdir -type f`; do - f=${df#$distdir} - if ! grep -q \(${f}\) $DI_FILES; then - if [ -n "$ALL" ]; then - echo "===>>> Deleting $f" - rm $df + for pkg in $pdb/*; do + if [ -s "$pkg/+REQUIRED_BY" ]; then + if grep -ql '^@pkgdep ' $pkg/+CONTENTS 2>/dev/null; then + branches="$branches ${pkg#$pdb/}" else - echo -n "===>>> Delete stale file: ${f}? [y] " - read DEL_OR_NOT - case "$DEL_OR_NOT" in - [nN]*) continue ;; - *) rm $df ;; - esac + trunks="$trunks ${pkg#$pdb/}" + fi + else + if grep -ql '^@pkgdep ' $pkg/+CONTENTS 2>/dev/null; then + leaves="$leaves ${pkg#$pdb/}" + else + [ -d "$pkg" ] || continue + roots="$roots ${pkg#$pdb/}" fi fi done +} - safe_exit -fi - -# Save switches for potential child processes -while getopts 'BCDGLRabde:fghilm:nop:r:stuvwx:' COMMAND_LINE_ARGUMENT ; do - case "${COMMAND_LINE_ARGUMENT}" in - B) NO_BACKUP=yes; ARGS="-B $ARGS" ;; - C) DONT_PRE_CLEAN=yes; ARGS="-C $ARGS" ;; - D) DONT_SCRUB_DISTFILES=yes; ARGS="-D $ARGS" ;; - G) NO_RECURSIVE_CONFIG=yes; unset FORCE_CONFIG ; ARGS="-G $ARGS" ;; - L) LIST_PLUS=yes ;; - R) RESTART=yes ; ARGS="-R $ARGS" ;; - a) UPDATE_ALL=yes ;; - b) BACKUP=yes; ARGS="-b $ARGS" ;; - d) ALWAYS_SCRUB_DISTFILES=yes; ARGS="-d $ARGS" ;; - e) EXPUNGE=$OPTARG ;; - f) FORCE=yes - FORCE_DONE_LIST=':' - export FORCE FORCE_DONE_LIST - ;; - g) MAKE_PACKAGE=yes; ARGS="-g $ARGS" ;; - h) usage 0 ;; - i) INTERACTIVE_UPDATE=yes; ARGS="-i $ARGS" ;; - l) LIST=yes ;; - m) PM_MAKE_ARGS=$OPTARG - export PM_MAKE_ARGS # For 'make checksum' - ARGS="-m $PM_MAKE_ARGS $ARGS" - ;; - n) NO_ACTION=yes; ARGS="-n $ARGS" ;; - o) REPLACE_ORIGIN=yes ;; - p) portdir="${OPTARG#$pd/}" ; portdir=${portdir%/} ;; - r) UPDATE_REQ_BYS=yes; upg_port=$OPTARG ;; - s) CLEAN_STALE=yes ;; - t) RECURSE_THOROUGH=yes; ARGS="-t $ARGS" ;; - u) UNATTENDED=yes; ARGS="-u $ARGS" ;; - v) VERBOSE=yes; ARGS="-v $ARGS" ;; - w) SAVE_SHARED=yes; ARGS="-w $ARGS" ;; - x) EXCL=$OPTARG ; ARGS="-x $EXCL $ARGS" ;; - *) usage ;; - esac -done -shift $(( $OPTIND - 1 )) - -: ${EXCL:=Ishouldthinkofsomethingclevertosayhere} +#=============== End functions for getopts features and main =============== +#=============== Begin code relevant only to getopts features =============== if [ -n "$LIST" -o -n "$LIST_PLUS" ]; then ports_by_category - - num_roots=0 - num_trunks=0 - num_branches=0 - num_leaves=0 - num_updates=0 + [ -n "$VERBOSE" ] && echo '' + num_roots=0; num_trunks=0; num_branches=0; num_leaves=0; num_updates=0 echo "===>>> Root ports (No dependencies, not depended on)" - for port in $roots; do - echo "===>>> ${port##*/}" - [ -n "$LIST_PLUS" ] && check_for_updates ${port##*/} list + for iport in $roots; do + echo "===>>> $iport" + [ -n "$LIST_PLUS" ] && check_for_updates list $iport num_roots=$(( $num_roots + 1 )) done echo "===>>> $num_roots root ports" echo '' echo "===>>> Trunk ports (No dependencies, are depended on)" - for port in $trunks; do - echo "===>>> ${port##*/}" - [ -n "$LIST_PLUS" ] && check_for_updates ${port##*/} list + for iport in $trunks; do + echo "===>>> $iport" + [ -n "$LIST_PLUS" ] && check_for_updates list $iport num_trunks=$(( $num_trunks + 1 )) done echo "===>>> $num_trunks trunk ports" echo '' echo "===>>> Branch ports (Have dependencies, are depended on)" - for port in $branches; do - echo "===>>> ${port##*/}" - [ -n "$LIST_PLUS" ] && check_for_updates ${port##*/} list + for iport in $branches; do + echo "===>>> $iport" + [ -n "$LIST_PLUS" ] && check_for_updates list $iport num_branches=$(( $num_branches + 1 )) done echo "===>>> $num_branches branch ports" echo '' echo "===>>> Leaf ports (Have dependencies, not depended on)" - for port in $leaves; do - echo "===>>> ${port##*/}" - [ -n "$LIST_PLUS" ] && check_for_updates ${port##*/} list + for iport in $leaves; do + echo "===>>> $iport" + [ -n "$LIST_PLUS" ] && check_for_updates list $iport num_leaves=$(( $num_leaves + 1 )) done echo "===>>> $num_leaves leaf ports" @@ -1093,459 +1219,665 @@ if [ -n "$LIST" -o -n "$LIST_PLUS" ]; then exit 0 fi -find_dl_distfiles () { - # dist_list and dist_list_files are used globally - - # We need to define this for use in the deletion/update process. - # Do it relative to OPTIONSFILE so we can be sure that they end - # up in the same place without having to derive it ourselves. - cd $pd/$1 - dist_list=`make BEFOREPORTMK=yes $PM_MAKE_ARGS -V OPTIONSFILE` - dist_list="${dist_list%options}distfiles" - - [ -n "$DONT_SCRUB_DISTFILES" ] && return 0 - [ -s "$dist_list" ] || return 0 - - # The grep is needed to allow for comments, etc. - local file - for file in `grep ^DISTFILE $dist_list | cut -f2 -d:`; do - dist_list_files="${dist_list_files} ${file#*/}" - done - - dist_list_files=${dist_list_files# } -} - -delete_dist_list () { - test -e "$dist_list" && unlink $dist_list - rmdir ${dist_list%/distfiles} 2>/dev/null -} - if [ -n "$EXPUNGE" ]; then - if [ -d "$pdb/$EXPUNGE" ]; then - origin=`origin_from_pdb $pdb/$EXPUNGE` - deplist=`grep -l DEPORIGIN:$origin$ $pdb/*/+CONTENTS` - if [ -n "$deplist" ]; then - echo "===>>> Warning: ports with dependencies on ${EXPUNGE}:" - for dep in $deplist; do echo ${dep%/+CON*}; done - exit 1 - fi - - if [ -n "$BACKUP" ]; then - init_pkgrep - backup_package $EXPUNGE - fi + [ -d "$pdb/$EXPUNGE" ] || fail "No such directory/port: $pdb/$EXPUNGE" + + origin=`origin_from_pdb $EXPUNGE` + deplist=`grep -l DEPORIGIN:$origin$ $pdb/*/+CONTENTS` + if [ -n "$deplist" ]; then + echo "===>>> Warning: Ports with dependencies on ${EXPUNGE}:" + for dep in $deplist; do + dep=${dep%/+CON*} ; echo " ${dep##*/}" + done + echo '' + echo -n "===>>> Delete this dependency data? [n] " + read answer + case "$answer" in + [yY]) for f in $deplist; do + update_contents delete $f $origin + done ;; + *) exit 1 ;; + esac + fi - find_dl_distfiles $origin + [ -n "$BACKUP" ] && { init_packages ; backup_package $EXPUNGE; } + [ -z "$DONT_SCRUB_DISTFILES" ] && delete_all_distfiles $origin - echo "===>>> Running pkg_delete -f $EXPUNGE" - pkg_delete -f $EXPUNGE - delete_dist_list - if [ -z "$DONT_SCRUB_DISTFILES" ]; then - delete_all_distfiles $origin - fi - exec $0 -s $ARGS - else - fail "No such directory/port: $pdb/$EXPUNGE" - fi + delete_dist_list + echo "===>>> Running pkg_delete -f $EXPUNGE" + pm_pkg_delete_s -f $EXPUNGE || fail 'pkg_delete failed' + echo '' ; echo "===>>> Running ${0##*/} -s $ARGS" + exec $0 -s $ARGS exit 0 # Should not be reached fi if [ -n "$CLEAN_STALE" ]; then - if [ -z "$do_not_delete" ]; then - do_not_delete=':' - export do_not_delete - fi + [ -z "$no_del_list" ] && export no_del_list=':' - for file in `find $pdb/ -name \+REQUIRED_BY -empty` ; do - dir="${file%/+REQUIRED_BY}" - iport=${dir#$pdb/} + for file in `find $pdb -type f -name \+REQUIRED_BY -empty` ; do + iport="${file%/+REQUIRED_BY}" ; iport=${iport#$pdb/} - case "$do_not_delete" in - *:${iport}:*) continue ;; - esac + case "$no_del_list" in *:${iport}:*) continue ;; esac - echo '' - - origin=`origin_from_pdb $dir` + origin=`origin_from_pdb $iport` deplist=`grep -l DEPORIGIN:$origin$ $pdb/*/+CONTENTS` if [ -n "$deplist" ]; then - echo "===>>> Warning: unrecorded dependencies on ${iport}:" - for dep in $deplist; do echo ${dep%/+CON*}; done + echo '' + echo "===>>> Warning: Unrecorded dependencies on ${iport}:" + for dep in $deplist; do + dep=${dep%/+CON*} ; echo " ${dep##*/}" + done + echo '' + echo "===>>> Try ${0##*/} --check-depends" + echo '' continue fi pkg_info $iport echo -n "===>>> ${iport} is no longer depended on, delete? [n] " - read YESNO - case "$YESNO" in + read answer + case "$answer" in [yY]) if [ -n "$BACKUP" ]; then - [ -z "$pkgrep" ] && init_pkgrep + [ -z "$packages" ] && init_packages backup_package $iport fi - find_dl_distfiles $origin + [ -z "$DONT_SCRUB_DISTFILES" ] && + delete_all_distfiles $origin - echo "===>>> Running pkg_delete -f $iport" - pkg_delete -f ${iport} delete_dist_list - if [ -z "$DONT_SCRUB_DISTFILES" ]; then - delete_all_distfiles $origin - fi + echo "===>>> Running pkg_delete -f $iport" + pm_pkg_delete_s -f $iport || fail 'pkg_delete failed' + exec $0 -s $ARGS ;; *) echo -n " ===>>> Remove empty +REQUIRED_BY file? [n] " - read DELORNOT - case "$DELORNOT" in - [yY]) rm -f $file ;; - *) do_not_delete="${do_not_delete}${iport}:" ;; + read answer + case "$answer" in + [yY]) pm_unlink_s $file ;; + *) no_del_list="${no_del_list}${iport}:" ;; esac ;; esac done - exit 0 fi -test -n "$FORCE" && unset INTERACTIVE_UPDATE -if [ -n "$UNATTENDED" ]; then - unset INTERACTIVE_UPDATE +#=============== End code relevant only to getopts features =============== +#=============== Begin functions for main =============== - if [ -z "$DONT_SCRUB_DISTFILES" -a -z "$ALWAYS_SCRUB_DISTFILES" ]; then - ALWAYS_SCRUB_DISTFILES=yes - ARGS="-d $ARGS" +already_done () { + [ -n "$VERBOSE" ] || return 0 + echo "===>>> The update for $1 is already done" +} + +check_restart_and_udf () { + # RESTART will usually be empty, and we don't want + # to go out to the disk if we don't have to. + if [ -z "$RESTART" ]; then + return 1 + elif [ ! -e "$1" ]; then + return 1 + else + already_done $2 ; echo '' fi -fi + return 0 +} -if [ "$$" -eq "$PARENT_PID" ]; then - CURRENT_DEPS_O=':' - CURRENT_DEPS_I=':' - IGNOREME_YES=':' - DISPLAY_LIST='' - IPC_SAVE=`mktemp -t ipc_save-$PARENT_PID` - export CURRENT_DEPS_O CURRENT_DEPS_I IGNOREME_YES DISPLAY_LIST IPC_SAVE +check_interactive () { + [ -n "$INTERACTIVE_UPDATE" ] || return 0 - PORTS_PREFIX=`make BEFOREPORTMK=yes $PM_MAKE_ARGS -f/usr/share/mk/bsd.port.mk -VPREFIX` - [ -n "$PORTS_PREFIX" ] || fail 'The value of PREFIX cannot be empty' - export PORTS_PREFIX + case "$INTERACTIVE_YES" in *:${1}:*) return 0 ;; esac + case "$INTERACTIVE_NO" in *:${1}:*) return 1 ;; esac - if [ -n "$INTERACTIVE_UPDATE" ]; then - INTERACTIVE_YES=':' - INTERACTIVE_NO=':' - export INTERACTIVE_YES INTERACTIVE_NO + if [ -e "$pdb/$1/+IGNOREME" ]; then + echo '' + echo "===>>> +IGNOREME file is present for $1" fi - if [ -n "$UPDATE_REQ_BYS" ]; then - URB_DONE_LIST=':' - export URB_DONE_LIST + echo '' ; echo -n "===>>> Update ${1}? [y] " + local answer ; read answer + case "$answer" in + [nN]*) INTERACTIVE_NO="${INTERACTIVE_NO}${1}:" ; return 1 ;; + *) INTERACTIVE_YES="${INTERACTIVE_YES}${1}:" ;; + esac + return 0 +} + +check_exclude () { + [ -n "$EXCL" ] || return 0 + + case "$1" in + *${EXCL}*) + if [ -n "$VERBOSE" ]; then + echo "===>>> Skipping $1" + echo " because it matches the pattern: *${EXCL}*" fi + return 1 ;; + esac + return 0 +} - if [ -n "$UPDATE_REQ_BYS" -o -n "$FORCE" ]; then - if [ -z "$RESTART" ]; then - find $pdb -type f -name PM_UPGRADE_DONE_FLAG -delete +check_fetch_only () { + [ -n "$FETCH_ONLY" ] || return 0 + + local sleep + + echo '' + sleep=5 + while `ls ${TMPDIR}/f-${PARENT_PID}-fetchlog-* >/dev/null 2>&1`; do + echo "===>>> Waiting for all distfile fetches to finish" + sleep $sleep + + if [ $sleep -eq 10 ]; then + sleep=5 + else + sleep=$(( $sleep + 1 )) fi + done + echo "===>>> Distfile fetching is complete" + safe_exit +} + +update_port () { + echo "===>>> Launching child to update ${1#$pd/}" + + [ -n "$DEPTH" ] && echo " $DEPTH >> ${1#$pd/}" + + if [ -z "$NO_ACTION" -o -n "$CONFIG_ONLY" ]; then + ($0 $ARGS $@) || fail "Update for $1 failed" + . $IPC_SAVE + else + [ -n "$VERBOSE" ] && + echo "===>>> Build canceled due to -n flag" + fi + + if [ -n "$UPDATE_ALL" ]; then + echo "===>>> Returning to update check of installed ports" + echo '' + elif [ -n "$UPDATE_REQ_BYS" ]; then + return 0 + elif [ -n "$CONFIG_ONLY" ]; then + [ -e "$NO_DEP_UPDATES" ] || unset NO_DEP_UPDATES + echo "===>>> Continuing 'make config' dependency check for $portdir" + else + echo "===>>> Returning to dependency check for $portdir" fi + return 0 +} - if [ -z "$CONFIG_ONLY" -a -z "$NO_RECURSIVE_CONFIG" ]; then - NO_DEP_UPDATES=`mktemp -t no_dep_updates-$PARENT_PID` +dependency_check () { + local d_port_list - CONFIG_SEEN_LIST=':' - CONFIG_ONLY=yes - export CONFIG_SEEN_LIST CONFIG_ONLY + # Print a message here because sometimes list generation takes + # a long time to return. + echo "===>>> Gathering dependency list for $portdir from ports" + d_port_list=`pm_make $1 | sort -u` + + if [ -z "$d_port_list" ]; then + echo "===>>> No dependencies for $portdir" + [ -n "$SHOW_WORK" ] && safe_exit + return 0 + else + if [ -n "$SHOW_WORK" ]; then + echo '' + elif [ -n "$CONFIG_ONLY" ]; then + echo "===>>> Starting recursive 'make config' check" + else + echo "===>>> Starting dependency check" + fi fi - if [ -z "$NO_BACKUP" ]; then - init_pkgrep - if [ -z "$BACKUP" ]; then - touch ${TMPDIR}/f-${PARENT_PID}-package-flag + local d_port origin iport conflicts glob confl_p udf + + for d_port in $d_port_list; do + origin="${d_port#$pd/}" + if [ -n "$SHOW_WORK" ]; then + iport=`iport_from_origin $origin` + case "$iport" in + '') echo "===>>> NOT INSTALLED $origin" ;; + *) echo "===>>> Installed $origin" ;; + esac + continue + fi + + [ -n "$VERBOSE" ] && echo "===>>> Checking dependency: $d_port" + + check_exclude $origin || continue + + # Do this first to catch out of date dependencies + if [ -n "$CONFIG_ONLY" ]; then + case "$CONFIG_SEEN_LIST" in *:${origin}:*) continue ;; esac + CONFIG_SEEN_LIST="${CONFIG_SEEN_LIST}${origin}:" + fi + + [ -z "$URB_YES" ] && + case "$CUR_DEPS" in *:${origin}:*) continue ;; esac + + if pm_cd $d_port; then + grep -ql ^CONFLICTS Makefile && + conflicts=`pm_make_b -V CONFLICTS` + else + fail "Cannot cd to $d_port" fi + for glob in $conflicts; do + confl_p=`pkg_info -I $glob 2>/dev/null` + if [ -n "$confl_p" ]; then + confl_p=${confl_p%% *} + echo '' + echo "===>>> The dependency for ${origin}" + echo " seems to be handled by $confl_p" + echo '' + d_port="$pd/`origin_from_pdb $confl_p`" + fi + done + + # In case d_port changed above + origin="${d_port#$pd/}" ; iport=`iport_from_origin ${origin}` + + udf="$pdb/$iport/PM_UPGRADE_DONE_FLAG" + if [ -n "$FORCE" -a -n "$iport" ]; then + if ! check_restart_and_udf $udf $iport; then + echo "===>>> Forcing update for $pd/$origin" + update_port $iport + else + CUR_DEPS="${CUR_DEPS}${iport}:${origin}:" + fi + continue + elif [ -n "$URB_YES" -a -n "$iport" ]; then + case "$URB_DONE_LIST" in + *:${iport}:*) already_done ; continue ;; esac + + case "$MASTER_RB_LIST" in *" $iport "*) + check_interactive $iport || continue + if ! check_restart_and_udf $udf $iport; then + update_port $iport + else + CUR_DEPS="${CUR_DEPS}${iport}:${origin}:" + URB_DONE_LIST="${URB_DONE_LIST}${upg_port}:" + fi + continue ;; + esac + fi + + if [ -n "$iport" ]; then + check_for_updates $iport $origin || fail 'Update failed' + else + update_port $d_port + fi + done + + if [ -n "$SHOW_WORK" ]; then + safe_exit + elif [ -n "$CONFIG_ONLY" ]; then + echo "===>>> Recursive 'make config' check complete for $portdir" + case "$DEPTH" in *\>\>*) echo " $DEPTH" ;; esac + else + echo "===>>> Dependency check complete for $portdir" + case "$DEPTH" in *\>\>*) echo " $DEPTH" ;; esac fi + echo '' +} + +create_master_rb_list () { + # Global: MASTER_RB_LIST + local req_by - if [ -z "$SHOW_WORK" -a -z "$DONT_SCRUB_DISTFILES" ]; then - # Set the file name here so it's visible to the children - DI_FILES=`mktemp -t DI-FILES-$PARENT_PID` - export DI_FILES + for req_by in `grep -l DEPORIGIN:$portdir$ $pdb/*/+CONTENTS | \ + cut -f 5 -d '/'`; do + MASTER_RB_LIST="${MASTER_RB_LIST}${req_by} " + done + + [ -n "$MASTER_RB_LIST" ] && export MASTER_RB_LIST=" $MASTER_RB_LIST" +} + +#=============== End functions for main =============== + +# INIT Parent + +if [ "$$" -eq "$PARENT_PID" -a -z "$SHOW_WORK" ]; then + CUR_DEPS=':' ; DISPLAY_LIST='' ; INSTALLED_LIST='' + DEPTH='' ; IPC_SAVE=`pm_mktemp IPC_SAVE` + export CUR_DEPS DISPLAY_LIST INSTALLED_LIST DEPTH IPC_SAVE + + PORTS_LOCALBASE=`pm_make_b -f/usr/share/mk/bsd.port.mk -V LOCALBASE` + [ -n "$PORTS_LOCALBASE" ] || + fail 'The value of LOCALBASE cannot be empty' + LOCALBASE_COMPAT="$PORTS_LOCALBASE/lib/compat" + export LOCALBASE_COMPAT + + if [ -n "$INTERACTIVE_UPDATE" ]; then + INTERACTIVE_YES=':' ; INTERACTIVE_NO=':' + export INTERACTIVE_YES INTERACTIVE_NO fi - if [ $# -gt 1 -a -z "$REPLACE_ORIGIN" ]; then - # This has to be done here because the children - # will never be PARENT_PID for the test below. - if [ -z "$SHOW_WORK" -a -z "$DONT_SCRUB_DISTFILES" ]; then - (read_distinfos)& + [ -n "$UPDATE_REQ_BYS" ] && export URB_DONE_LIST=':' + if [ -n "$UPDATE_REQ_BYS" -o -n "$FORCE" ]; then + if [ -z "$RESTART" ]; then + # Outdent + files=`find $pdb -type f -name PM_UPGRADE_DONE_FLAG` + if [ -n "$files" ]; then + [ -n "$PM_SU_VERBOSE" ] && + echo "===>>> Deleting 'install complete' flags" + pm_find_s $pdb -type f -name PM_UPGRADE_DONE_FLAG -delete + fi + # Outdent fi + fi - if [ -z "$NO_RECURSIVE_CONFIG" ]; then + if [ -z "$NO_RECURSIVE_CONFIG" ]; then + CONFIG_SEEN_LIST=':' ; CONFIG_ONLY=yes + export CONFIG_SEEN_LIST CONFIG_ONLY + fi + + [ -n "$NO_BACKUP" -a -z "$MAKE_PACKAGE" ] || init_packages + [ -z "$NO_BACKUP" -a -z "$BACKUP" ] && export NB_DELETE + + # Set the file name here so it's visible to the children + if [ -z "$DONT_SCRUB_DISTFILES" -a -z "$FETCH_ONLY" ]; then + export DI_FILES=`pm_mktemp DI-FILES` + (read_distinfos)& + fi + + if [ $# -gt 1 -a -z "$REPLACE_ORIGIN" ]; then + # Quick check of the command line arguments + for port in $@; do + case "$port" in + */*) [ -d "$pd/${port#$pd/}" ] || + fail "$pd/${port#$pd/} does not exist" + ;; + *) [ -d "$pdb/$port" ] || + fail "$pdb/$port does not exist" + ;; + esac + done + if [ -n "$CONFIG_ONLY" ]; then for port in $@; do ($0 $ARGS $port) || fail "Update for $port failed" . $IPC_SAVE done - unset_recursive_config + check_fetch_only + unset CONFIG_SEEN_LIST CONFIG_ONLY echo '' - echo "===>>> Starting build for ports: <<<===" - echo "===>>> $@ <<<===" + echo "===>>> Starting build for multiple ports <<<===" echo '' fi for port in $@; do + case "$port" in + */*) ;; # Ok to proceed + *) # If an installed version does not + # exist at this point it probably + # got updated as a dependency + [ -d "$pdb/$port" ] || continue + ;; + esac ($0 $ARGS $port) || fail "Update for $port failed" . $IPC_SAVE done safe_exit fi -else + # Does not make sense to do this for multi-ports + [ -n "$CONFIG_ONLY" ] && + export NO_DEP_UPDATES=`pm_mktemp NO_DEP_UPDATES` +elif [ -z "$SHOW_WORK" ]; then # Zero out this file so that we can save our data to it safely > $IPC_SAVE fi +# This has to come after the initialization, it uses all the same stuff if [ -n "$UPDATE_ALL" ]; then - if [ -z "$DONT_SCRUB_DISTFILES" ]; then - (read_distinfos)& - fi +all_config () { + local iport origin - echo "===>>> Starting check of installed ports for available updates" - ports_by_category + for iport in $@; do + [ -n "$VERBOSE" ] && echo "===>>> $iport" - if [ -n "$CONFIG_ONLY" ]; then - echo "===>>> Checking ports for recursive 'make config'" - for pkg in $roots $trunks $branches $leaves; do - test -n "$VERBOSE" && - echo "===>>> Checking installed port: ${pkg#$pdb/}" + case "$CUR_DEPS" in *:${iport}:*) continue ;; esac - case "$pkg" in - *${EXCL}*) test -n "$VERBOSE" && -echo "===>>> Skipping ${pkg#$pdb/} because it matches the pattern: *${EXCL}*" - continue - ;; - esac + origin=`origin_from_pdb $iport` + case "$CONFIG_SEEN_LIST" in *:${origin}:*) continue ;; esac - case "$CURRENT_DEPS_I" in - *:${pkg#$pdb/}:*) continue ;; - esac + check_exclude $iport || continue - orig=`origin_from_pdb $pkg` - case "$CONFIG_SEEN_LIST" in - *:${orig}:*) continue ;; - esac - CONFIG_SEEN_LIST="${CONFIG_SEEN_LIST}${orig}:" - check_for_updates ${pkg#$pdb/} || fail 'Update failed' - done + CONFIG_SEEN_LIST="${CONFIG_SEEN_LIST}${origin}:" - if [ -e "$NO_DEP_UPDATES" ]; then - echo "===>>> The 'make config' check revealed no ports to update" + DEPTH= + check_for_updates $iport $origin || fail 'Update failed' + [ -e "$NO_DEP_UPDATES" ] || unset NO_DEP_UPDATES + done +} + ports_by_category + echo "===>>> Starting check of installed ports for available updates" + + if [ -n "$CONFIG_ONLY" ]; then + [ -n "$FETCH_ONLY" ] && export ALL_FETCH=yes + + echo "===>>> Checking ports for recursive 'make config'" + [ -n "$VERBOSE" ] && { echo '' ; echo "===>>> Root ports:"; } + all_config $roots + [ -n "$VERBOSE" ] && { echo '' ; echo "===>>> Trunk ports:"; } + all_config $trunks + [ -n "$VERBOSE" ] && { echo '' ; echo "===>>> Branch ports:"; } + all_config $branches + [ -n "$VERBOSE" ] && { echo '' ; echo "===>>> Leaf ports:"; } + all_config $leaves + + check_fetch_only + if [ -n "$NO_DEP_UPDATES" ]; then + echo "===>>> The 'make config' check found no ports to update" safe_exit fi - unset_recursive_config + unset CONFIG_SEEN_LIST CONFIG_ONLY echo '' echo "===>>> Starting build for ports that need updating <<<===" echo '' fi - BUILDING=yes - export BUILDING + export BUILDING=yes - for pkg in $roots $trunks $branches $leaves; do - case "$pkg" in - *${EXCL}*) test -n "$VERBOSE" && -echo "===>>> Skipping ${pkg#$pdb/} because it matches the pattern: *${EXCL}*" - continue - ;; - esac + for iport in $roots $trunks $branches $leaves; do + # Probably got updated as a dependency for something else + [ -d "$pdb/$iport" ] || continue + case "$CUR_DEPS" in *:${iport}:*) continue ;; esac + check_exclude $iport || continue + check_interactive $iport || continue - if [ ! -d "$pkg" ]; then - # This port probably got updated as a dependency - # for something else - continue - fi + DEPTH= if [ -n "$FORCE" ]; then - p=`origin_from_pdb $pkg` - case "$FORCE_DONE_LIST" in - *:${p}:*) test -n "$VERBOSE" && - echo "===>>> Update for $p already done" - continue - ;; - esac - - if [ -e "${pkg}/PM_UPGRADE_DONE_FLAG" ]; then - test -n "$VERBOSE" && - echo "===>>> Update for $p already done" - continue + udf="$pdb/$iport/PM_UPGRADE_DONE_FLAG" + if ! check_restart_and_udf $udf $iport; then + echo "===>>> Forcing update for $iport" + update_port $iport + else + CUR_DEPS="${CUR_DEPS}${iport}:" fi - - echo "===>>> Forcing update for ${pkg#$pdb/}" - update_port ${pkg#$pdb/} continue - else - test -n "$VERBOSE" && - echo "===>>> Checking installed port: ${pkg#$pdb/}" fi - case "$CURRENT_DEPS_I" in - *:${pkg#$pdb/}:*) continue ;; - esac - check_for_updates ${pkg#$pdb/} || fail 'Update failed' + if [ -z "$NO_RECURSIVE_CONFIG" ]; then + # We got here, so we know we have to build it + update_port $iport + else + [ -n "$VERBOSE" ] && + echo "===>>> Checking installed port: $iport" + check_for_updates $iport || fail 'Update failed' + fi done + echo "===>>> Update check of installed ports complete" safe_exit fi -if [ -n "$REPLACE_ORIGIN" ]; then - portdir="${1#$pd/}" - portdir="${portdir%/}" - newportdir=$portdir - - if [ -d "$pdb/$2" ]; then - # Handle the portmaster'ish way to specify the port - upg_port=$2 - else - # Handle existing portupgrade syntax - upg_port=`grep -l " ORIGIN:${2#$pd/}$" $pdb/*/+CONTENTS` - [ -n "$upg_port" ] || - upg_port=`grep -l " ORIGIN:${2#$pd/}" $pdb/*/+CONTENTS` - [ -n "$upg_port" ] || - fail "Cannot find an installed port with ORIGIN $2" - upg_port="${upg_port%/+CONTENTS}" - upg_port="${upg_port#$pdb/}" - fi - - oldportdir=`origin_from_pdb $pdb/$upg_port` -fi +no_valid_port () { + echo "===>>> No valid installed port, or port directory given"; + echo "===>>> Try ${0##*/} --help" ; echo '' ; safe_exit 1 +} -# Exercised in the common case of not using -p option -case "$portdir" in -'') argv=${1%/} +# Figure out what we are going to be working on +if [ -z "$REPLACE_ORIGIN" ]; then + [ -n "$portdir" ] && { argv=$portdir ; unset portdir; } + argv=${argv:-$1} ; argv=${argv%/} case "$argv" in - '') test -z "$UPDATE_REQ_BYS" && usage ;; - ${pd}/*) portdir="${argv#$pd/}" ;; - /*) upg_port="${argv##*/}" ;; - \.) portdir="${PWD##*/ports/}" ;; - *) if [ -d "${pd}/${argv}" ]; then - portdir=$argv - else - upg_port=$argv - fi - ;; + '') echo '' ; no_valid_port ;; + $pd/*) portdir=${argv#$pd/} ;; + $pdb/*) upg_port=${argv#$pdb/} ;; + /*) echo '' ; no_valid_port ;; + */*) portdir=$argv ;; + \.) portdir=${PWD##*/ports/} ;; # Not always $pd, could be symlink + *) [ -d "$pdb/$argv" ] && upg_port=$argv ;; esac -esac - -case "$upg_port" in -'') test -n "$portdir" || usage - old_port_dir=`iport_from_origin ${portdir}` - if [ -n "$old_port_dir" ]; then - upg_port="${old_port_dir}" - fi - ;; -*) if [ ! -d "$pdb/$upg_port" ]; then - glob_dirs=`find $pdb -type d -name ${upg_port}\*` + if [ -z "$portdir" -a -z "$upg_port" ]; then + glob_dirs=`find $pdb -maxdepth 1 -type d -name ${argv}\*` case "$glob_dirs" in - *\*) fail "$upg_port did not match an installed port" ;; + *\*|'') echo '' ; no_valid_port ;; *) for dir in $glob_dirs; do echo -n "===>>> Update ${dir#$pdb/}? [n] " - read GLOB_DIR - case "$GLOB_DIR" in - [yY]) upg_port=${dir#$pdb/} - selected=yes - break - ;; + read answer + case "$answer" in + [yY]) upg_port=${dir#$pdb/} ; break ;; esac done - test -n "$selected" || usage ;; esac fi - echo "===>>> Port to upgrade: $upg_port" - if [ -z "$portdir" ]; then - portdir=`origin_from_pdb $pdb/$upg_port` - [ -n "$portdir" ] || - fail "No ORIGIN in $pdb/$upg_port/+CONTENTS" +else + portdir="${1#$pd/}" ; portdir="${portdir%/}" + [ -d "$pd/$portdir" ] || { echo '' + echo "===>>> The first argument must be a directory in $pd" + echo '' ; no_valid_port; } + upg_port=${2#$pdb/} ; upg_port="${upg_port%/}" + if [ -d "$pdb/$upg_port" ]; then + ro_opd=`origin_from_pdb $upg_port` # Old port directory + else + ro_opd=${upg_port#$pd/} # Portupgrade syntax + upg_port=`iport_from_origin $ro_opd` + if [ -z "$upg_port" -o ! -d "$pdb/$upg_port" ]; then + if grep -ql "DEPORIGIN:$ro_opd$" $pdb/*/+CONTENTS; then + unset upg_port + PM_MAKE_ARGS="-DFORCE_PKG_REGISTER $PM_MAKE_ARGS" + else + echo '' + echo "===>>> The second argument can be a port in $pdb," + echo " or a port directory from $pd" + echo '' ; no_valid_port + fi + fi fi - ;; -esac +fi + +if [ -n "$upg_port" ]; then + portdir=`origin_from_pdb $upg_port` + [ -n "$portdir" ] || fail "No ORIGIN in $pdb/$upg_port/+CONTENTS" +elif [ -z "$portdir" ]; then + no_valid_port +fi + +if [ ! -d "$pd/$portdir" ]; then + find_moved_port $portdir $upg_port || no_valid_port + [ -n "$moved_npd" ] || no_valid_port + portdir=$moved_npd + [ -d "$pd/$portdir" ] || no_valid_port +fi +[ -z "$upg_port" -a -z "$REPLACE_ORIGIN" ] && + upg_port=`iport_from_origin ${portdir}` if [ -e "$pdb/$upg_port/+IGNOREME" ]; then - echo '' - if [ -z "$UNATTENDED" ]; then - if [ -z "$BUILDING" ]; then - echo "===>>> $upg_port has an +IGNOREME file" - echo -n "===>>> Update anyway? [n] " - read UPD_OR_NOT - case "$UPD_OR_NOT" in - [yY]*) IGNOREME_YES="${IGNOREME_YES}${upg_port}:" ;; - *) safe_exit ;; - esac - else - case "$IGNOREME_YES" in - *:${upg_port}:*) ;; - *) safe_exit ;; - esac - fi - else + # Adding to CUR_DEPS means we will not get here in the build unless -G + if [ -z "$BUILDING" ]; then + # Only need to prompt for this once if -ai + case "$INTERACTIVE_YES" in + *:${upg_port}:*) ;; # Let it build + *) if [ -z "$UNATTENDED" -a -z "$FETCH_ONLY" ]; then + echo '' + echo "===>>> $upg_port has an +IGNOREME file" + echo '' + echo -n "===>>> Update anyway? [n] " + read answer + case "$answer" in + [yY]) ;; # Let it build + *) CUR_DEPS="${CUR_DEPS}${upg_port}:${portdir}:" + safe_exit ;; + esac + else + echo '' + echo "===>>> $upg_port has an +IGNOREME file, ignoring" + echo '' + CUR_DEPS="${CUR_DEPS}${upg_port}:${portdir}:" + safe_exit + fi + ;; + esac + elif [ -n "$NO_RECURSIVE_CONFIG" ]; then + echo '' echo "===>>> $upg_port has an +IGNOREME file, ignoring" + echo '' safe_exit fi fi -if [ -d "$pd/$portdir" ]; then - echo "===>>> Port directory: $pd/$portdir" +# START + +pm_cd $pd/$portdir || no_valid_port + +if [ -z "$DEPTH" ]; then + DEPTH=${upg_port:-$portdir} else - find_moved_port $portdir || usage - portdir=$newportdir + DEPTH="$DEPTH >> ${upg_port:-$portdir}" fi -cd $pd/$portdir || usage - -for state in FORBIDDEN BROKEN IGNORE; do - state_set=`make -V $state` - if [ -n "$state_set" ]; then - echo "===>>> This port is marked $state:" - printf "===>>> $state_set" - echo "===>>> If you are sure you can build it, remove the" - echo " $state line in the Makefile and try again." - safe_exit 1 - fi -done +echo '' +[ "$$" -eq "$PARENT_PID" -a -n "$upg_port" ] && + echo "===>>> Currently installed version: $upg_port" +echo "===>>> Port directory: $pd/$portdir" -# Since this task is non-trivial, when only one port is supplied on the -# command line do not start this process until we are sure that we are -# going to (at least try to) build the port. -if [ "$$" -eq "$PARENT_PID" -a -z "$SHOW_WORK" \ - -a -z "$DONT_SCRUB_DISTFILES" ]; then - (read_distinfos)& -fi +check_state || { + echo " ===>>> If you are sure you can build it, remove the"; + echo " $state line in the Makefile and try again."; + safe_exit 1; } # Do these things first time through, with or without 'make config' if [ -z "$BUILDING" -a -z "$SHOW_WORK" ]; then dofetch () { echo "===>>> Launching 'make checksum' for $portdir in background" - fetchlog=`mktemp -t fetchlog-${PARENT_PID}-${portdir##*/}` - (make -DBATCH $PM_MAKE_ARGS checksum >> $fetchlog 2>&1 && - { rm -f $fetchlog; \ - rm -f ${TMPDIR}/f-${PARENT_PID}-*-${portdir##*/}.*; exit 0;} - allfiles=`make $PM_MAKE_ARGS -V ALLFILES` - make $PM_MAKE_ARGS delete-distfiles RESTRICTED_FILES="${allfiles}" \ + fetchlog=`pm_mktemp fetchlog-${portdir#*/}` + (pm_make -DBATCH checksum >> $fetchlog 2>&1 && { + rm -f ${TMPDIR}/f-${PARENT_PID}-*-${portdir#*/}.*; exit 0; } + allfiles=`pm_make -V ALLFILES` + pm_make delete-distfiles RESTRICTED_FILES="${allfiles}" \ >> $fetchlog 2>&1 && echo "===>>> RE-STARTING FETCH <<<===" >> $fetchlog - make $PM_MAKE_ARGS checksum >> $fetchlog 2>&1; \ - rm -f ${TMPDIR}/f-${PARENT_PID}-*-${portdir##*/}.*; \ - rm -f $fetchlog)& - echo "MCS_CHILD_PID $!" >> $fetchlog + pm_make -DBATCH checksum >> $fetchlog 2>&1; \ + rm -f ${TMPDIR}/f-${PARENT_PID}-*-${portdir#*/}.* )& } - - distfiles=`make $PM_MAKE_ARGS -V ALLFILES` + # PATCHFILES may get added post-config, but we want to + # do as much of this as we can, as early as we can, and + # patch files are usually small anyway. + distfiles=`pm_make -V ALLFILES | sed -e 's# *$##g'` + [ -n "$distfiles" ] && distfiles=" ${distfiles} " + + # Make sure that different ports using the same distfiles + # do not clobber each other's fetchs for file in $distfiles; do - flag_file=f-${PARENT_PID}-${file} - if ! ls ${TMPDIR}/${flag_file}-* >/dev/null 2>&1; then - mktemp -t ${flag_file}-${portdir##*/} >/dev/null + if ! ls ${TMPDIR}/f-${PARENT_PID}-${file}-* >/dev/null 2>&1 + then + pm_mktemp ${file}-${portdir#*/} >/dev/null else DONT_FETCH=yes break fi done - test -z "$DONT_FETCH" && dofetch + [ -z "$DONT_FETCH" -a -n "$distfiles" ] && dofetch - TESTINT=`make -V IS_INTERACTIVE` + if [ -z "$FETCH_ONLY" ]; then + TESTINT=`grep -l ^IS_INTERACTIVE Makefile` + else + [ -n "$ALL_FETCH" ] && safe_exit + fi if [ -n "$TESTINT" ]; then echo '' echo "===>>> Warning: $portdir is interactive, and will likely" @@ -1555,91 +1887,75 @@ dofetch () { read DISCARD echo '' fi - - if [ -n "$UPDATE_REQ_BYS" ]; then - MASTER_RB_LIST=`mktemp -t master_rb_list-${PARENT_PID}` - export MASTER_RB_LIST - if [ -s "$pdb/$upg_port/+REQUIRED_BY" ]; then - old_rb=$pdb/$upg_port/+REQUIRED_BY - fi - upg_origin=`origin_from_pdb $pdb/$upg_port` - grep -l DEPORIGIN:$upg_origin$ $pdb/*/+CONTENTS | - cut -f 5 -d '/' | sort -u - $old_rb > $MASTER_RB_LIST - fi fi if [ -n "$CONFIG_ONLY" ]; then config_type=config-conditional - test -n "$FORCE_CONFIG" && config_type=config - make $PM_MAKE_ARGS $config_type + [ -n "$FORCE_CONFIG" ] && config_type=config + [ -n "$PM_SU_VERBOSE" ] && echo "===>>> Running 'make $config_type'" + pm_make_s $config_type CONFIG_SEEN_LIST="${CONFIG_SEEN_LIST}${portdir}:" - if [ -z "$RECURSE_THOROUGH" ]; then - dependency_check 'build-depends-list run-depends-list' - else - dependency_check all-depends-list - fi + dep_check_type='build-depends-list run-depends-list' + [ -n "$RECURSE_THOROUGH" ] && dep_check_type=all-depends-list + dependency_check "$dep_check_type" + + [ -n "$UPDATE_REQ_BYS" -o -n "$URB_YES" ] && + URB_DONE_LIST="${URB_DONE_LIST}${upg_port}:" if [ ! "$$" -eq "$PARENT_PID" ]; then # Save state for the parent process to read back in echo "CONFIG_SEEN_LIST='$CONFIG_SEEN_LIST'" > $IPC_SAVE + [ -n "$NO_DEP_UPDATES" ] && pm_unlink $NO_DEP_UPDATES safe_exit - else - if [ -n "$UPDATE_REQ_BYS" ]; then - URB_YES=yes ; export URB_YES - echo '' - echo "===>>> Checking ports that depend on $upg_port" - for req_by in `cat $MASTER_RB_LIST`; do - case "$req_by" in - *${EXCL}*) test -n "$VERBOSE" && - echo "===>>> Skipping $req_by because it matches the pattern: *${EXCL}*" - continue - ;; - esac + elif [ -n "$UPDATE_REQ_BYS" ]; then + export URB_YES=yes + echo "===>>> Checking ports that depend on $upg_port" + echo '' + create_master_rb_list + [ -n "$MASTER_RB_LIST" ] || { + echo "===>>> No ports depend on $upg_port" ; echo ''; } + for req_by in $MASTER_RB_LIST; do + # Probably not needed, but JIC + [ -d "$pdb/$req_by" ] || continue - rb_origin=`origin_from_pdb $pdb/$req_by` - case "$URB_DONE_LIST" in - *:${rb_origin}:*) continue ;; - esac + case "$URB_DONE_LIST" in + *:${req_by}:*) already_done $req_by + continue ;; esac - test -n "$VERBOSE" && - echo "===>>> $upg_port is required by $req_by" - if [ ! -d "$pdb/$req_by" ]; then - # A failure here is probably just a - # stale dependency, but warn the user. - req_by_error $upg_port $req_by - continue - fi - if ! check_interactive ${req_by} ; then - continue - fi + [ -n "$VERBOSE" ] && + echo "===>>> $upg_port is required by $req_by" - if [ -z "$RESTART" -a -z "$FORCE" ]; then - update_port $req_by - else - check_for_updates $req_by - fi - done - rm -f $MASTER_RB_LIST - echo "===>>> Done checking ports that depend on $upg_port" - unset URB_YES - URB_DONE_LIST=':' - fi + check_exclude $req_by || continue + check_interactive $req_by || continue - unset_recursive_config + # Shortcut, since check_for will force it + if [ -z "$RESTART" -a -z "$FORCE" ]; then + update_port $req_by + else + check_for_updates $req_by || + fail 'Update failed' + fi + echo "===>>> Returning to check of ports depending on $upg_port" + done + + echo "===>>> Done checking ports that depend on $upg_port" + echo '' + unset URB_YES MASTER_RB_LIST ; URB_DONE_LIST=':' fi - echo '' + + check_fetch_only + unset CONFIG_SEEN_LIST CONFIG_ONLY echo "===>>> Starting build for $portdir <<<===" echo '' fi -BUILDING=yes -export BUILDING +export BUILDING=yes cd $pd/$portdir -if [ ! -e "$NO_DEP_UPDATES" ]; then +if [ -z "$NO_DEP_UPDATES" ]; then if [ -z "$RECURSE_THOROUGH" ]; then echo "===>>> Starting check for build dependencies" dependency_check build-depends-list @@ -1647,308 +1963,318 @@ if [ ! -e "$NO_DEP_UPDATES" ]; then echo "===>>> Starting check for all dependencies" dependency_check all-depends-list fi -else - if [ -z "$NO_RECURSIVE_CONFIG" ]; then - echo "===>>> The 'make config' check revealed no dependencies to update" - echo '' - fi + cd $pd/$portdir +elif [ -z "$NO_RECURSIVE_CONFIG" -a "$$" -eq "$PARENT_PID" ]; then + echo "===>>> The 'make config' check found no dependencies to update" + echo '' fi -if [ -n "$NO_ACTION" ]; then - test -n "$VERBOSE" && - echo "===>>> Build canceled due to -n flag" +if [ -n "$NO_ACTION" -a -z "$CONFIG_ONLY" ]; then + [ -n "$VERBOSE" ] && echo "===>>> Build canceled due to -n flag" safe_exit fi -# In case we went elsewhere in the dependency check -cd $pd/$portdir - -case "$DONT_PRE_CLEAN" in -'') make $PM_MAKE_ARGS clean NOCLEANDEPENDS=yes || fail 'make clean failed' ;; -esac +[ -z "$DONT_PRE_CLEAN" ] && { + pm_make clean NOCLEANDEPENDS=yes || fail 'make clean failed'; echo ''; } -fl_read=`echo ${TMPDIR}/fetchlog-${PARENT_PID}-${portdir##*/}.*` +sleep=3 +fl_read=`echo ${TMPDIR}/f-${PARENT_PID}-fetchlog-${portdir#*/}.*` while [ -f "$fl_read" ]; do - echo '' - echo "===>>> Waiting on fetch & checksum for $portdir <<<===" - tail -10 $fl_read 2>/dev/null | egrep -v '^$|MCS_CHILD_PID' - echo '' echo "===>>> Waiting on fetch & checksum for $portdir <<<===" - sleep 5 -done - -make $PM_MAKE_ARGS || fail "make failed for $portdir" - -new_port=`make $PM_MAKE_ARGS -V PKGNAME` -prefix=`make $PM_MAKE_ARGS -V PKGNAMEPREFIX` -portname=`make $PM_MAKE_ARGS -V PORTNAME` -suffix=`make $PM_MAKE_ARGS -V PKGNAMESUFFIX` -short_port="${prefix}${portname}${suffix}" - -# Check for dependencies here in case +REQUIRED_BY is not up to date or missing -grep_deps=`mktemp -t grep-deps-${short_port}` - -upg_origin=$portdir -if [ -n "$upg_port" ]; then - upg_origin=`origin_from_pdb $pdb/$upg_port` -fi -grep -l DEPORIGIN:$upg_origin$ $pdb/*/+CONTENTS | cut -f 5 -d '/' | - sort -u > $grep_deps - -if [ -s "$pdb/$upg_port/+REQUIRED_BY" ]; then - req_deps=`mktemp -t req-deps-${short_port}` - sort -u $pdb/$upg_port/+REQUIRED_BY > $req_deps -fi + tail -10 $fl_read 2>/dev/null + echo '' ; echo '' + sleep $sleep -if [ ! -s "$grep_deps" -a ! -s "$req_deps" ]; then - if [ -n "$upg_port" ]; then - echo "===>>> $upg_port is not depended on by any other ports" - fi -elif [ -s "$grep_deps" -a -s "$req_deps" ]; then - if ! cmp -s $grep_deps $req_deps; then - update_reqfile - fi -elif [ -s "$grep_deps" -a ! -s "$req_deps" ]; then - dep_warn - echo -n "===>>> Install these as the new +REQUIRED_BY file? [n] " - if [ -z "$UNATTENDED" ]; then - read INSTALLDEPS - - case "$INSTALLDEPS" in - [yY]) req_deps=`mktemp -t req-deps-${short_port}` - mv $grep_deps $req_deps ; unset grep_deps - ;; - esac + if [ $sleep -eq 10 ]; then + sleep=3 else - echo "===>>> Default (no) in unattended mode" + sleep=$(( $sleep + 1 )) fi -else - # It should not happen that req_deps exist but grep_deps does not - echo '' - echo "===>>> $pdb/$upg_port/+REQUIRED_BY indicates" - echo " a dependency on this port, but no other ports have" - echo " it recorded. If that file does not contain any valid" - echo " dependency data, try removing it and then start again." - fail "Stale dependency data in $pdb/$upg_port/+REQUIRED_BY" +done +unset sleep + +if [ -n "$HIDE_BUILD" ]; then + port_log=`mktemp -t port_log-${PARENT_PID}-${portdir#*/}` + port_log_args=">> $port_log 2>&1" + echo "===>>> Logging build to $port_log" fi +eval pm_make $port_log_args || fail "make failed for $portdir" + # Ignore if no old port exists if [ -n "$upg_port" ]; then - find_dl_distfiles $portdir - UPGRADE_PORT=$upg_port UPGRADE_PORT_VER=`echo $UPGRADE_PORT | sed 's#.*-\(.*\)#\1#'` export UPGRADE_PORT UPGRADE_PORT_VER - if [ -z "$NO_BACKUP" ]; then - backup_package $upg_port - fi + [ -z "$NO_BACKUP" ] && backup_package $upg_port if [ -n "$SAVE_SHARED" ]; then - ldconfig_out=`mktemp -t f-${PARENT_PID}-ldconfig` + ldconfig_out=`pm_mktemp ldconfig` ldconfig -r | sed 's#.* ##' | - grep -v ^${PORTS_PREFIX}/lib/compat > $ldconfig_out - - mkdir -p ${PORTS_PREFIX}/lib/compat/pkg + grep -v ^$LOCALBASE_COMPAT > $ldconfig_out + unset temp for file in `pkg_info -q -L $upg_port | sort - $ldconfig_out | \ uniq -d`; do - cp -p $file ${PORTS_PREFIX}/lib/compat/pkg/ + temp="${temp}$file " done - ldconfig -m ${PORTS_PREFIX}/lib/compat/pkg + if [ -n "$temp" ]; then + if [ ! -d "$LOCALBASE_COMPAT/pkg" ]; then + [ -n "$PM_SU_VERBOSE" ] && + echo "===>>> Creating $LOCALBASE_COMPAT/pkg for -w" + pm_mkdir_s $LOCALBASE_COMPAT/pkg + fi + + [ -n "$PM_SU_VERBOSE" ] && + echo "===>>> Copying old shared libraries for -w" + $PM_SU_CMD cp -p $temp $LOCALBASE_COMPAT/pkg/ + fi + + pm_unlink $ldconfig_out ; unset ldconfig_out temp file fi - pkg_delete -f $upg_port || fail 'pkg_delete failed' - delete_dist_list + find_dl_distfiles $portdir if [ -n "$REPLACE_ORIGIN" ]; then - installed_newport=`iport_from_origin ${newportdir}` - if [ -n "$installed_newport" ]; then - pkg_delete -f $installed_newport - delete_dist_list + # upg_port will be the port we are replacing + # Delete any existing versions of the new port + iport=`iport_from_origin $portdir` + if [ -n "$iport" ]; then + [ -n "$PM_SU_VERBOSE" ] && + echo "===>>> Running pkg_delete for $iport" + pm_pkg_delete_s -f $iport fi fi -fi -# In case we went elsewhere to create a backup package -cd $pd/$portdir + [ -n "$PM_SU_VERBOSE" ] && + echo "===>>> Running pkg_delete for $upg_port" + pm_pkg_delete_s -f $upg_port + cd $pd/$portdir +fi -if [ -z "$RECURSE_THOROUGH" -a ! -e "$NO_DEP_UPDATES" ]; then - echo '' - echo "===>>> Starting check for runtime dependencies" +if [ -z "$RECURSE_THOROUGH" -a -z "$NO_DEP_UPDATES" ]; then + echo '' ; echo "===>>> Starting check for runtime dependencies" dependency_check run-depends-list + cd $pd/$portdir fi -# In case we went elsewhere in the dependency check -cd $pd/$portdir +new_port=`pm_make -V PKGNAME` + +if [ -n "$PM_SU_UNSET_PORT_LOG_ARGS" ]; then + unset port_log_args +else + [ -n "$HIDE_BUILD" ] && echo "===>>> Logging install to $port_log" +fi # Defining NO_DEPENDS ensures that we will control the installation of the # depends, not bsd.port.mk. -make -DNO_DEPENDS $PM_MAKE_ARGS install || { - if [ -z "$NO_BACKUP" -a -n "$upg_port" ]; then - echo '' - echo "===>>> A backup package for $portdir should be located in $pkgrep" - fi - fail "Installation of new port failed";} +[ -n "$PM_SU_VERBOSE" ] && echo "===>>> Running make install" + +eval pm_make_s -DNO_DEPENDS install $port_log_args || { + if [ -z "$NO_BACKUP" -a -n "$upg_port" ]; then + echo '' + echo "===>>> A backup package for $upg_port should" + echo " be located in $pbu" + fi + fail "Installation of $new_port ($portdir) failed"; } # Remove saved libs that match newly installed files -pkg_info -q -L $new_port | while read file; do - if [ -e "${PORTS_PREFIX}/lib/compat/pkg/${file##*/}" ]; then - unlink ${PORTS_PREFIX}/lib/compat/pkg/${file##*/} + +temp=`find $LOCALBASE_COMPAT/pkg -type d -empty 2>/dev/null` +if [ -z "$temp" -a -d "$LOCALBASE_COMPAT/pkg" ]; then + unset files + for file in `pkg_info -q -L $new_port`; do + [ -f "$LOCALBASE_COMPAT/pkg/${file##*/}" ] && { + files="${files}$LOCALBASE_COMPAT/pkg/${file##*/} "; } + done + + if [ -n "$files" ]; then + [ -n "$PM_SU_VERBOSE" ] && + echo "===>>> Removing old shared libraries, and running ldconfig" + pm_rm_s $files + $PM_SU_CMD /etc/rc.d/ldconfig start > /dev/null fi -done -test -d "${PORTS_PREFIX}/lib/compat/pkg" && - ldconfig -m ${PORTS_PREFIX}/lib/compat/pkg + unset temp file files +fi + +[ -z "$temp" ] && temp=`find $LOCALBASE_COMPAT/pkg -type d -empty 2>/dev/null` +if [ -d "$temp" ]; then + [ -n "$PM_SU_VERBOSE" ] && + echo "===>>> Deleting the empty $LOCALBASE_COMPAT/pkg" + pm_rmdir_s $temp +fi +unset temp + +# This will serve for *delete*distfiles() as well +distfiles=`pm_make -V ALLFILES | sed -e 's# *$##g'` +if [ -n "$distfiles" ]; then + distfiles=" ${distfiles} " -allfiles=`make $PM_MAKE_ARGS -V ALLFILES` -if [ ! "$allfiles" = ' ' ]; then # Implement storage of distfile information in the way that # it will (hopefully, soon?) be implemented in bsd.port.mk # See http://www.freebsd.org/cgi/query-pr.cgi?pr=106483 - dist_list=`make BEFOREPORTMK=yes $PM_MAKE_ARGS -V OPTIONSFILE` + dist_list=`pm_make_b -V OPTIONSFILE` dist_list="${dist_list%options}distfiles" - mkdir -p ${dist_list%/distfiles} - ds=`make BEFOREPORTMK=yes $PM_MAKE_ARGS -V DIST_SUBDIR` - test -n "$ds" && ds="${ds}/" - distinfo=`make $PM_MAKE_ARGS -V MD5_FILE` - echo '# Added by portmaster' > $dist_list - for file in $allfiles; do - size=`grep "^SIZE (${ds}${file})" $distinfo | cut -f4 -d' '` - sha256=`grep "^SHA256 (${ds}${file})" $distinfo | cut -f4 -d' '` - md5=`grep "^MD5 (${ds}${file})" $distinfo | cut -f4 -d' '` - echo "DISTFILE:${ds}${file}:SIZE=${size}:SHA256=${sha256}:MD5=${md5}" >> $dist_list + if [ ! -d "${dist_list%/distfiles}" ]; then + [ -n "$PM_SU_VERBOSE" ] && + echo "===>>> Creating ${dist_list%/distfiles}" + pm_mkdir_s ${dist_list%/distfiles} + fi + + ds=`pm_make -V DIST_SUBDIR` + [ -n "$ds" ] && ds="${ds}/" + port_subdir="${distdir}${ds}" # Also for *delete*distfiles() + + if [ -s distinfo ]; then + distinfo=distinfo + else + distinfo=`pm_make -V MD5_FILE` + fi + + dist_list_temp=`pm_mktemp dist_list` + echo '# Added by portmaster' > $dist_list_temp + for file in $distfiles; do + size=`grep "^SIZE (${ds}${file})" $distinfo` + sha256=`grep "^SHA256 (${ds}${file})" $distinfo` + md5=`grep "^MD5 (${ds}${file})" $distinfo` + echo "DISTFILE:${ds}${file}:SIZE=${size##* }:SHA256=${sha256##* }:MD5=${md5##* }" >> $dist_list_temp + # Make sure any new distfiles get added to the list + [ -z "$DONT_SCRUB_DISTFILES" -a ! "$$" -eq "$PARENT_PID" ] && + echo "${ds}$file" >> $DI_FILES done + + [ -n "$PM_SU_VERBOSE" ] && + echo "===>>> Installing $dist_list" + pm_install_s $dist_list_temp $dist_list + pm_unlink $dist_list_temp ; unset ds dist_list_temp fi if [ -n "$MAKE_PACKAGE" ]; then echo "===>>> Creating a package for new version $new_port" - make $PM_MAKE_ARGS package || fail 'Package creation of new port failed' - echo " ===>>> Package can be found in $pkgrep" + pm_make_s package >/dev/null || + fail "Package creation of $new_port failed" + echo " ===>>> Package saved to $packages/All" ; echo '' fi -make $PM_MAKE_ARGS clean NOCLEANDEPENDS=yes - -# By now, if this file exists, it should be authoritative -if [ -s "$req_deps" ]; then - -update_dep_entries () { - local upg_port - - test -n "$1" && upg_port=$1 +pm_make clean NOCLEANDEPENDS=yes ; echo '' +check_dependency_files $portdir $new_port +if [ -s "$grep_deps" ]; then echo "===>>> Updating package dependency entry for each dependent port" - while read dep_port; do - dep_port_contents="$pdb/$dep_port/+CONTENTS" - [ -e "$pdb/$dep_port/+CONTENTS" ] || continue - if grep -q "@pkgdep $upg_port" $dep_port_contents; then - update_contents $upg_port $new_port - else - echo -n "===>>> In ${dep_port}" - echo " no entry for $upg_port, trying $short_port" - update_contents "$short_port.*" $new_port + [ -n "$VERBOSE" ] && echo '' + while read d_port; do + [ -n "$VERBOSE" ] && echo "===>>> $d_port" + dp_cont=$pdb/$d_port/+CONTENTS + [ -e "$dp_cont" ] || continue + + if [ -n "$ro_opd" ]; then + grep -ql "DEPORIGIN:$ro_opd$" $dp_cont && + update_contents $dp_cont $portdir $new_port $ro_opd fi - done < $req_deps -} - update_dep_entries - mv $req_deps $pdb/$new_port/+REQUIRED_BY - unset req_deps - chmod 644 $pdb/$new_port/+REQUIRED_BY + if [ -n "$moved_opd" ]; then + grep -ql "DEPORIGIN:$moved_opd$" $dp_cont && + update_contents $dp_cont $portdir $new_port $moved_opd + fi + # Do this one last so it can get deleted as a duplicate + # if either of the other two were present. + if grep -ql "DEPORIGIN:$portdir$" $dp_cont; then + update_contents $dp_cont $portdir $new_port + fi + done < $grep_deps + unset d_port dp_cont do_update - if [ -n "$REPLACE_ORIGIN" ]; then - req_deps=`mktemp -t req-deps-${short_port}` + if [ -e "$pdb/$new_port/+REQUIRED_BY" ]; then + sort $pdb/$new_port/+REQUIRED_BY | cmp -s $grep_deps - || + do_update=yes + check_regular_file $pdb/$new_port/+REQUIRED_BY + else + do_update=yes + fi + if [ -n "$do_update" ]; then + [ -n "$VERBOSE" ] && { echo ''; + echo " ===>>> Updating $new_port/+REQUIRED_BY"; } + pm_install_s $grep_deps $pdb/$new_port/+REQUIRED_BY + fi - grep -l DEPORIGIN:$newportdir$ $pdb/*/+CONTENTS | - cut -f 5 -d '/' | sort -u > $req_deps - update_dep_entries $new_port - cat $req_deps >> $pdb/$new_port/+REQUIRED_BY + pm_unlink $grep_deps && unset grep_deps do_update + echo '' +fi + +if [ -n "$upg_port" ]; then + if [ ! "$upg_port" = "$new_port" ]; then + ilist="Upgrade of $upg_port to $new_port" + else + ilist="Re-installation of $upg_port" fi +else + ilist="Installation of $portdir ($new_port)" fi -echo '' -test -z "$upg_port" && upg_port=$portdir -echo "===>>> Upgrade for $upg_port to $new_port succeeded" -echo '' +if [ "$$" -ne "$PARENT_PID" -o -n "$UPDATE_REQ_BYS" ]; then + echo "===>>> $ilist succeeded" ; echo '' +fi -test -n "$FORCE" && FORCE_DONE_LIST="${FORCE_DONE_LIST}${portdir}:" -test -e "$pdb/$new_port/+DISPLAY" && - DISPLAY_LIST="${DISPLAY_LIST}$new_port/+DISPLAY " +INSTALLED_LIST="${INSTALLED_LIST}$ilist:" +[ -e "$pdb/$new_port/+DISPLAY" ] && DISPLAY_LIST="${DISPLAY_LIST}$new_port " +CUR_DEPS="${CUR_DEPS}${new_port}:${portdir}:" -if [ -n "$URB_YES" -o -n "$UPDATE_REQ_BYS" -o -n "$FORCE" ]; then - touch $pdb/$new_port/PM_UPGRADE_DONE_FLAG -fi +[ -n "$HIDE_BUILD" -a -n "$port_log" ] && pm_unlink $port_log + +[ -n "$URB_YES" -o -n "$UPDATE_REQ_BYS" ] && + URB_DONE_LIST="${URB_DONE_LIST}${new_port}:" +[ -n "$URB_YES" -o -n "$UPDATE_REQ_BYS" -o -n "$FORCE" ] && + $PM_SU_CMD touch $pdb/$new_port/PM_UPGRADE_DONE_FLAG if [ -z "$DONT_SCRUB_DISTFILES" ]; then - # Make sure any new distfiles get added to the list - cd $pd/$portdir 2>/dev/null || - fail "Cannot cd to $pd/$portdir for distfile update" - distinfo=`make $PM_MAKE_ARGS -V MD5_FILE` - if [ -s "$distinfo" ]; then - grep '^MD5' $distinfo | while read disc1 file disc2; do - echo $file >> $DI_FILES - done + delete_stale_distfiles $portdir + if [ -n "$ro_opd" ]; then + delete_all_distfiles $ro_opd + delete_dist_list fi - - if [ -z "$oldportdir" ]; then - delete_stale_distfiles - else - delete_all_distfiles ${oldportdir} - cd $pd/$newportdir && delete_stale_distfiles + if [ -n "$moved_opd" ]; then + delete_all_distfiles $moved_opd + delete_dist_list fi fi if [ -n "$UPDATE_REQ_BYS" -a -s "$pdb/$new_port/+REQUIRED_BY" ]; then - URB_YES=yes ; export URB_YES - MASTER_RB_LIST=$pdb/$new_port/+REQUIRED_BY + export URB_YES=yes echo "===>>> Updating ports that depend on $new_port" - for req_by in `cat $pdb/$new_port/+REQUIRED_BY`; do - if [ ! -d "$pdb/$req_by" ]; then - # Since the dependency list was probably updated as - # a result of updating the parent port, a missing - # directory here is likely the result of the port - # being updated as a dependency for something else. - continue - fi - - case "$req_by" in - *${EXCL}*) test -n "$VERBOSE" && - echo "===>>> Skipping $req_by because it matches the pattern: *${EXCL}*" - continue - ;; - esac + echo '' + create_master_rb_list + for req_by in $MASTER_RB_LIST; do + # Probably not needed, but JIC + [ -d "$pdb/$req_by" ] || continue - p=`origin_from_pdb $pdb/$req_by` case "$URB_DONE_LIST" in - *:${p}:*) continue ;; - esac - - case "$FORCE_DONE_LIST" in - *:${p}:*) test -n "$VERBOSE" && - echo "===>>> Update for $p already done" - continue - ;; + *:${req_by}:*) already_done $req_by ; continue ;; esac - if ! check_interactive ${req_by} ; then - continue - fi + # Check here since if "no" it will not prompt + check_interactive $req_by || continue - test -n "$VERBOSE" && - echo "===>>> $new_port is required by $req_by" + [ -n "$VERBOSE" ] && + echo "===>>> $new_port is required by $req_by" + check_exclude $req_by || continue + # Shortcut, since check_for will force it if [ -z "$RESTART" -a -z "$FORCE" ]; then update_port $req_by else - check_for_updates $req_by + check_for_updates $req_by || fail 'Update failed' fi + echo "===>>> Returning to check of ports depending on $upg_port" done echo "===>>> Done updating ports that depend on $new_port" + echo '' fi safe_exit #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copyright (c) 2005-2007 Douglas Barton +# Copyright (c) 2005-2008 Douglas Barton # All rights reserved. # # Redistribution and use in source and binary forms, with or without |