Index: user/dougb/portmaster/portmaster =================================================================== --- user/dougb/portmaster/portmaster (revision 199067) +++ user/dougb/portmaster/portmaster (revision 199068) @@ -1,2732 +1,2739 @@ #!/bin/sh # Copyright (c) 2005-2009 Douglas Barton, All rights reserved # Please see detailed copyright below trap trap_exit INT # Initialize crucial values for the parent, and export them for the children if [ -z "$PM_PARENT_PID" ]; then PM_PARENT_PID=$$ : ${TMPDIR:=/tmp} UPGRADE_TOOL=portmaster # /usr/local is needed in the path for make PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin [ -e /usr/X11R6 -a ! -L /usr/X11R6 ] && PATH=$PATH:/usr/X11R6/bin if [ -n "$CCACHE_PATH" ]; then if [ -z "$NOCCACHE" ]; then PATH="/usr/local/libexec/ccache:$PATH" fi fi export PM_PARENT_PID TMPDIR UPGRADE_TOOL PATH set -o allexport # Read a global rc file first [ -r /etc/portmaster.rc ] && . /etc/portmaster.rc [ -r /usr/local/etc/portmaster.rc ] && . /usr/local/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 umask 022 #=============== Begin functions we always want to have =============== version () { local rcs cvs rcs='$Id: portmaster,v 2.54 2009/09/15 07:50:11 dougb Exp $' cvs='$FreeBSD$' rcs="${rcs#*,v }" ; rcs="${rcs%% *}" cvs="${cvs#*,v }" ; cvs="${cvs#*/portmaster }" ; cvs="${cvs%% *}" echo '' [ "${cvs#$}" != 'FreeBSD$' ] && { echo "===>>> FreeBSD version $cvs" ; return 0; } echo "===>>> Development version $rcs" } fail () { echo '' ; echo "===>>> $1" ; echo "===>>> Aborting update" [ "$$" -eq "$PM_PARENT_PID" ] && trap_exit fail safe_exit 1 } trap_exit () { TRAP=trap 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 "$PM_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-${PM_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 mypgid pid ppid pgid command ; IFS=' ' mypgid=`ps -o pgid -p $PM_PARENT_PID` ; mypgid=${mypgid##*PGID[^0-9]} ps -axo pid,ppid,pgid,command | sed '1d' | while read pid ppid pgid 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 ;; *) [ $pgid -eq $mypgid ] || continue case "$command" in *" $0 "*) [ $pid -ne $PM_PARENT_PID ] && pm_kill $pid ;; *'make -DBATCH checksum'*|*'/fetch '*|\[sh\]) pm_kill $pid ;; esac ;; esac done } safe_exit () { local files p f show_list if [ "$$" -eq "$PM_PARENT_PID" ]; then if [ -s "$DI_FILES" ]; then grep -q '%%%%%%%%%%%%' $DI_FILES || kill_bad_children fi [ -n "$FETCH_ONLY" -a -z "$FETCH_ONLY_DONE" ] && kill_bad_children if [ -z "$TRAP" ]; then if [ -n "$UPDATE_REQ_BYS" -o -n "$PM_FORCE" ]; then # Outdent [ -n "$UPDATE_REQ_BYS" -o -n "$PM_FORCE" ] && 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-${PM_PARENT_PID}-*; do pm_unlink $f ; done case "$DISPLAY_LIST" in *' '*) if [ -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 echo '' fi [ -n "$PAGER" ] && p=$PAGER || p='less -e' ( 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 if [ -n "$UPDATE_ALL" -a -n "$INSTALLED_LIST" ]; then show_list=all else case "$INSTALLED_LIST" in *\\n\\t*) show_list=all ;; *\\n) show_list=one ;; esac fi case "$show_list" in all) echo "===>>> The following actions were performed:" echo -e $INSTALLED_LIST ;; one) 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 elif [ -z "$NO_DEP_UPDATES" ]; then echo 'unset NO_DEP_UPDATES' >> $IPC_SAVE fi [ -z "$NO_BACKUP" -a -z "$BACKUP" ] && echo "NB_DELETE='$NB_DELETE'" >> $IPC_SAVE [ -n "$PM_MULTI_BUILT" ] && echo "PM_MULTI_BUILT='$PM_MULTI_BUILT'" >> $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 () { version echo '' echo 'Usage:' echo "Common flags: [--force-config] [-CGHKgntvw B|b f|i D|d]" echo " [--packages|--packages-only] [-P|-PP] [--packages-if-newer]" echo " [-m ]" echo " [-x ]" echo "${0##*/} [Common flags] " echo "${0##*/} [Common flags] " echo "${0##*/} [Common flags] " echo "${0##*/} [Common flags] Multiple full names/paths from $pdb|$pd" echo " and/or multiple globs from $pdb" echo '' echo "${0##*/} [Common flags] -p " echo "${0##*/} [Common flags] . [Use in $pd/foo/bar to build that port]" echo '' echo "${0##*/} --show-work [-Gv] [-m ] " echo '' echo "${0##*/} [Common flags] -o " echo "${0##*/} [Common flags] [-R] -r " echo '' echo "${0##*/} [Common flags] -a" echo '' echo "${0##*/} -[l|L]" echo '' echo "${0##*/} [-b D|d] -e " 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##*/} --check-depends" echo '' echo "${0##*/} --check-port-dbdir [-v]" echo '' echo "${0##*/} --list-origins" echo '' echo "${0##*/} -h|--help" echo "${0##*/} --version" echo '' echo "--force-config 'make config' for all ports" 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 "-K prevents 'make clean' from being run after building" 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 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 DEPRECATED" echo '[-R] -f always rebuild ports (overrides -i)' echo '-i interactive update -- ask whether to rebuild ports' echo '-D no cleaning of distfiles' echo '-d always clean distfiles' echo "-m " echo "-x " echo ' Can be specified more than once' echo '' echo '--show-work list what ports are and would be installed' echo '' echo '-o replace the installed port with a port from a different origin' echo '[-R] -r rebuild port, and all ports that depend on it' echo '-R used with -[rf] to skip ports updated on a previous run' echo '-a check all ports, update as necessary' echo '' echo 'NOTE: The package options imply -G' echo '-P|--packages use packages, but build port if not available' echo '-PP|--packages-only fail if no package is available' echo '--packages-if-newer use package if newer than installed even' echo ' if the package is not the latest according to the ports tree' echo '' echo '-l list installed ports by category' echo '-L list installed ports by category, and search for updates' echo '' 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 '--check-depends cross-check and update dependency information for all ports' echo '' echo "--check-port-dbdir check for stale entries in $port_dbdir" echo '' echo "--list-origins list directories from $pd for root and leaf 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' safe_exit ${1:-1} } pm_cd () { builtin cd $1 2>/dev/null || return 1; } pm_kill () { /bin/kill $* >/dev/null 2>/dev/null; } pm_make () { ( unset -v CUR_DEPS INSTALLED_LIST PM_DEPTH; unset -v MASTER_RB_LIST CONFIG_SEEN_LIST; /usr/bin/make $PM_MAKE_ARGS $*; ); } pm_make_b () { /usr/bin/make $PM_MAKE_ARGS BEFOREPORTMK=bpm $*; } pm_mktemp () { /usr/bin/mktemp -t f-${PM_PARENT_PID}-$1; } pm_unlink () { /bin/test -e $1 && /bin/unlink $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 () { ( unset -v CUR_DEPS INSTALLED_LIST PM_DEPTH; unset -v MASTER_RB_LIST CONFIG_SEEN_LIST; $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 "$PM_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 if [ -z "$port_dbdir" ]; then port_dbdir=`pm_make_b -f/usr/share/mk/bsd.port.mk -V PORT_DBDIR` [ -n "$port_dbdir" ] && export port_dbdir fi export pd pdb distdir fi pmuex () { fail "The -P/--packages and -PP/--packages-only options are mutually exclusive" } # XXX for var in "$@" ; do case "$var" in -P|--packages) [ "$PM_PACKAGES" = only ] && pmuex NO_RECURSIVE_CONFIG=Gopt; ARGS="-G $ARGS" PM_PACKAGES=first ; export PM_PACKAGES ;; -PP|--packages-only) [ "$PM_PACKAGES" = first ] && pmuex NO_RECURSIVE_CONFIG=Gopt; ARGS="-G $ARGS" PM_PACKAGES=only ; export PM_PACKAGES ;; --packages-if-newer) [ -z "$PM_PACKAGES" ] && { PM_PACKAGES=newer ; export PM_PACKAGES; NO_RECURSIVE_CONFIG=Gopt; ARGS="-G $ARGS"; } PM_PACKAGES_NEWER=pm_packages_newer export PM_PACKAGES_NEWER ;; -[A-Za-z0-9]*) newopts="$newopts $var" ;; --help) usage 0 ;; --version) version ; exit 0 ;; --clean-distfiles) CLEAN_DISTFILES=clean_distfiles ;; --clean-distfiles-all) CLEAN_DISTFILES=clean_distfiles_all ; ALL=cda ;; --check-depends) CHECK_DEPENDS=check_depends ;; --check-port-dbdir) CHECK_PORT_DBDIR=check_port_dbdir ;; --list-origins) LIST_ORIGINS=list_origins ;; --show-work) SHOW_WORK=show ; RECURSE_THOROUGH=thorough ;; --force-config) export FORCE_CONFIG=force_config ;; --*) echo "Illegal option $var" ; echo '' echo "===>>> Try ${0##*/} --help"; exit 1 ;; *) newopts="$newopts $var" ;; esac done set -- $newopts unset var newopts #=============== Begin functions relevant to --features and main =============== 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/} } origin_from_pdb () { local o o=`grep '@comment ORIGIN:' $pdb/$1/+CONTENTS 2>/dev/null` echo ${o#@comment ORIGIN:} } check_regular_file () { [ ! -L "$1" -a -f "$1" ] || fail "ERROR: $1 is not a regular file!" } check_dependency_files () { # Global: grep_deps local origin iport ro_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=a/a ;; *+*) ro_opd=`echo $ro_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)$" $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 "$PM_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 } 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 # To prevent words in a line being treated individually IFS=' ' [ "$1" = 'delete' ] && { delete=delete ; shift; } contents=$1 ; origin=$2 ; n_port=$3 ; old_origin=$4 iport=${contents#$pdb/} ; iport=${iport%/+CONTENTS} new_cont=`pm_mktemp contents-${iport}` if [ -z "$delete" ]; then o_seen=':'; else o_seen=":${origin}:"; fi for line in `cat $contents`; do if [ -n "$d_missing" ]; then unset d_missing d_origin=${line#*DEPORIGIN:} case "$o_seen" in *:${d_origin}:*) unset prev_line line ; continue ;; esac o_seen="${o_seen}${d_origin}:" if [ "$d_origin" = "$old_origin" ]; then d_iport=$n_port d_origin=$origin else d_iport=`iport_from_origin $d_origin` fi if [ -n "$d_iport" ]; then [ -n "$PM_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" echo '' if [ -n "$CHECK_DEPENDS" ]; then echo -n " ===>>> Delete this dependency data? [n] " read answer case "$answer" in [yY]) unset prev_line line ; continue ;; esac else echo " ===>>> Try ${0##*/} --check-depends" 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 case "$o_seen" in *:${d_origin}:*) continue ;; esac o_seen="${o_seen}${d_origin}:" 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=d_missing ;; @pkgdep*) d_iport="${line#@pkgdep }" [ -d "$pdb/$d_iport" ] || d_missing=dm2 ;; esac [ -n "$prev_line" ] && echo $prev_line >> $new_cont prev_line=$line done [ -n "$prev_line" ] && echo $prev_line >> $new_cont cmp -s $contents $new_cont && { pm_unlink $new_cont ; return; } check_regular_file $contents [ -n "$PM_VERBOSE" -o -n "$CHECK_DEPENDS" ] && echo " ===>>> Installing the new +CONTENTS file" pm_install_s $new_cont $contents pm_unlink $new_cont } find_moved_port () { # Global: moved_npd local sf iport IFS l reason sf=$1 # Search for iport=$2 # 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 "$PM_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 reason=${l##*|} [ "$3" != 'nonfatal' ] && fail "The $sf port has been deleted: $reason" 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 [ -z "$moved_npd" ]; then if [ -z "$reason" ]; then echo '' echo " ===>>> No $pd/$1 exists, and no information" echo " ===>>> about $1 can be found in $pd/MOVED" else # Only reached in LIST_PLUS echo " ===>>> The $sf port has been deleted: $reason" fi echo '' [ -n "$iport" ] || iport=`iport_from_origin $sf` if [ -e "$pdb/$iport/+IGNOREME" ]; then return 0 else return 1 fi fi return 0 } read_distinfos () { local pkg iport origin distinfo disc1 f disc2 echo '############' > $DI_FILES # Make the file > 0 bytes echo "===>>> Gathering distinfo list for installed ports" echo '' for pkg in ${pdb}/*; do [ -d $pkg ] || continue iport=${pkg#$pdb/} case "$iport" in bsdpan-*) continue ;; esac origin=`origin_from_pdb $iport` if [ ! -d "$pd/$origin" ]; then find_moved_port $origin $iport nonfatal >/dev/null [ -n "$moved_npd" ] || continue origin=$moved_npd fi pm_cd $pd/$origin || continue if [ -s distinfo ]; then distinfo=distinfo else distinfo=`pm_make -V MD5_FILE` 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 # Tell safe_exit that we are done [ -e "${DI_FILES}-e" ] && unlink ${DI_FILES}-e sed -i -e 1s/############/%%%%%%%%%%%%/ $DI_FILES [ -e "${DI_FILES}-e" ] && unlink ${DI_FILES}-e } globstrip () { local in in=${1%[*]} in=${in%\\} echo $in } ports_by_category () { local pkg [ -n "$PM_VERBOSE" ] && echo "===>>> Sorting ports by category" 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 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 } #=============== End functions relevant to --features and main =============== #=============== Begin code relevant only to --features =============== 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 echo "===>>> Checking for stale distfiles" for df in `find $distdir -type f | sort`; 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 done find -d $distdir -type d -empty -delete safe_exit fi if [ -n "$CHECK_DEPENDS" ]; then d_orig_ok=':' IFS=' ' for pkg in $pdb/*; do [ -d "$pkg" ] || continue iport=${pkg#$pdb/} case "$iport" in bsdpan-*) echo "===>>> BSDPAN ports do not record dependencies ($iport)" continue ;; esac echo "===>>> Checking $iport" [ -r "$pkg/+CONTENTS" ] || { echo " ===>>> Warning: No +CONTENTS file!"; continue; } origin=`origin_from_pdb ${pkg#$pdb/}` [ -n "$origin" ] || { echo " ===>>> Warning: No ORIGIN in +CONTENTS file"; continue; } if [ ! -d "$pd/$origin" ]; then echo " ===>>> $pd/$origin does not exist" echo " ===>>> This port should probably be updated" continue fi 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=do_update check_regular_file $pkg/+REQUIRED_BY else do_update=do_update2 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; } update_contents $pkg/+CONTENTS done exit 0 fi if [ -n "$CHECK_PORT_DBDIR" ]; then if [ "$2" = "-v" ]; then PM_VERBOSE=vopt; fi unique_list=':' echo "===>>> Building list of installed port names"; echo '' for pkg in $pdb/*; do unset unique_name iport=${pkg#$pdb/} origin=`origin_from_pdb $iport` if [ ! -d "$pd/$origin" ]; then find_moved_port $origin $iport nonfatal >/dev/null [ -n "$moved_npd" ] || continue origin=$moved_npd fi pm_cd $pd/$origin || { echo " ===>>> $pd/$origin does not exist for $pkg"; continue; } unique_name=`make -V UNIQUENAME` unique_list="${unique_list}${unique_name}:" done echo "===>>> Checking $port_dbdir" [ -n "$PM_VERBOSE" ] && { print='-print'; echo ''; echo "===>>> Deleting empty directories (if any)"; } pm_find_s $port_dbdir -type d -empty $print -delete [ -n "$PM_VERBOSE" ] && echo '' for dir in ${port_dbdir}/*; do dbdir=${dir#$port_dbdir/} [ -n "$PM_VERBOSE" ] && echo -n "===>>> Checking ${dbdir}: " case "$unique_list" in *:${dbdir}:*) [ -n "$PM_VERBOSE" ] && echo "Ok" ;; *) [ -n "$PM_VERBOSE" ] && echo '' echo '' echo " ===>>> $dbdir does not seem to be installed" echo -n " ===>>> Delete ${dir}? [n] " read answer case "$answer" in [yY]) pm_rm_s -rf $dir ;; esac ;; esac done exit 0 fi if [ -n "$LIST_ORIGINS" ]; then ports_by_category for iport in $roots $leaves; do origin=`origin_from_pdb $iport` echo $origin done exit 0 fi #=============== End code relevant only to --features =============== # Save switches for potential child processes while getopts 'BCDFGHKLRabde:fghilm:nop:r:stuvwx:' COMMAND_LINE_ARGUMENT ; do case "${COMMAND_LINE_ARGUMENT}" in B) NO_BACKUP=Bopt; ARGS="-B $ARGS" ;; C) DONT_PRE_CLEAN=Copt; ARGS="-C $ARGS" ;; D) DONT_SCRUB_DISTFILES=Dopt; ARGS="-D $ARGS" ;; F) FETCH_ONLY=Fopt; ARGS="-F $ARGS" ;; G) NO_RECURSIVE_CONFIG=Gopt; unset FORCE_CONFIG; ARGS="-G $ARGS" ;; H) HIDE_BUILD=Hopt; ARGS="-H $ARGS" ;; K) DONT_POST_CLEAN=Kopt; ARGS="-K $ARGS" ;; L) LIST_PLUS=Lopt ;; R) RESTART=Ropt ; ARGS="-R $ARGS" ;; a) UPDATE_ALL=aopt ;; b) BACKUP=bopt; ARGS="-b $ARGS" ;; d) ALWAYS_SCRUB_DISTFILES=dopt; ARGS="-d $ARGS" ;; e) EXPUNGE=$OPTARG ;; f) export PM_FORCE=fopt ;; g) MAKE_PACKAGE=gopt; ARGS="-g $ARGS" ;; h) usage 0 ;; i) INTERACTIVE_UPDATE=iopt; ARGS="-i $ARGS" ;; l) LIST=lopt ;; m) export PM_MAKE_ARGS=$OPTARG # For 'make checksum' ARGS="-m $PM_MAKE_ARGS $ARGS" ;; n) NO_ACTION=nopt; ARGS="-n $ARGS" ;; o) REPLACE_ORIGIN=oopt ;; p) portdir="${OPTARG#$pd/}" ; portdir=${portdir%/} ;; r) UPDATE_REQ_BYS=ropt ; portdir=`origin_from_pdb $OPTARG` ;; s) CLEAN_STALE=sopt ;; t) RECURSE_THOROUGH=topt; ARGS="-t $ARGS" ;; u) echo "===>>> The -u option has been deprecated" ; echo '' ;; v) PM_VERBOSE=vopt; ARGS="-v $ARGS" ;; w) SAVE_SHARED=wopt; ARGS="-w $ARGS" ;; x) case "$OPTARG" in -*) fail 'The -x option requires an argument' ;; esac PM_EXCL="${PM_EXCL}`globstrip ${OPTARG}` " ;; *) echo '' ; echo "===>>> Try ${0##*/} --help"; exit 1 ;; esac done shift $(( $OPTIND - 1 )) [ -n "$PM_EXCL" ] && export PM_EXCL # Error checking for getopts [ -n "$PM_FORCE" -a "$INTERACTIVE_UPDATE" ] && fail "The -f and -i options are mutually exclusive" [ -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" #=============== 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 () { # Global: num_updates local list_only nf iport origin port_ver udf do_update [ "$1" = 'list' ] && { list_only=list_only; nf=nonfatal; shift; } iport=$1 case "$iport" in bsdpan-*) [ -n "$PM_VERBOSE" ] && echo " ===>>> BSDPAN ports cannot be upgraded with portmaster" return 0 ;; esac origin=${2:-`origin_from_pdb $iport`} if [ -z "$origin" ]; then if [ -n "$PM_VERBOSE" ]; then echo "===>>> No ORIGIN in $pdb/$iport/+CONTENTS" echo '' fi return 0 fi 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/$origin" fi 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 "$PM_FORCE" ]; then check_restart_and_udf $udf $iport || do_update=do_update elif [ -n "$URB_YES" ]; then # Outdent case "$MASTER_RB_LIST" in *" $iport "*) if ! check_restart_and_udf $udf $iport; then do_update=do_update2 else URB_DONE_LIST="${URB_DONE_LIST}${upg_port}:" fi ;; esac # Outdent elif [ -n "$PM_MULTI_PORTS" ]; then case "$PM_MULTI_PORTS" in *:${iport}:*) do_update=do_update7 ;; *:${origin}:*) do_update=do_update8 ;; esac elif [ -n "$LIST_PLUS" ]; then check_state return 0 elif [ -n "$LIST" ]; then return 0 fi else case `pkg_version -t $iport $port_ver` in \<) do_update=do_update3 ;; =) ;; # Should not be reached \>) if [ -n "$PM_VERBOSE" ]; then echo " ===>>> Port version $port_ver does not" echo " ===>>> seem newer than installed $iport" fi if [ -n "$PM_FORCE" ]; then check_restart_and_udf $udf $iport || do_update=do_update4 elif [ -n "$URB_YES" ]; then # Outdent case "$MASTER_RB_LIST" in *" $iport "*) if ! check_restart_and_udf $udf $iport; then do_update=do_update5 else URB_DONE_LIST="${URB_DONE_LIST}${upg_port}:" fi ;; esac # Outdent fi ;; esac fi else find_moved_port $origin $iport $nf # If the port has moved, we have to update it, otherwise ignore [ -n "$moved_npd" ] && do_update=do_update6 fi [ -z "$do_update" ] && { CUR_DEPS="${CUR_DEPS}${iport}:${origin}:" ; return 0; } if [ -n "$list_only" ]; 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 return 0 fi # No need for check_exclude here because it is already # run in the places that call check_for_updates(). check_interactive $iport $port_ver || return 0 update_port $iport $port_ver || return 1 return 0 } init_packages () { # Global: packages pbu local pkgrep packages=`pm_make -f/usr/share/mk/bsd.port.mk -V PACKAGES` [ -n "$packages" ] || fail 'The value of PACKAGES cannot be empty' # 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 "===>>> The PACKAGES and PKGREPOSITORY variables conflict" fail "Set PACKAGES only - 'man portmaster' for more information" fi pbu=$packages/portmaster-backup if [ ! -d "$pbu" ]; then [ -n "$PM_SU_VERBOSE" ] && echo "===>>> Creating $pbu" pm_mkdir_s $pbu fi export packages pbu } 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 local pkg ; pkg=`echo $1.*` NB_DELETE="${NB_DELETE}${pkg} " fi else 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 fi } find_dl_distfiles () { # Global: dist_list dist_list_files local file # 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" [ -s "$dist_list" ] || { unset dist_list ; return 0; } [ -n "$DONT_SCRUB_DISTFILES" ] && return 0 # 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 else # The port might have moved, etc.; so take a stab at it, # but do not take a chance with a possibly wrong answer 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 } delete_dist_list () { [ -n "$dist_list" ] || return 0 local dir [ -n "$PM_SU_VERBOSE" ] && echo "===>>> Deleting $dist_list" pm_unlink_s $dist_list 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 () { # Global: distfiles distfiles_checked delete_all local ps pattern file answer ps=${port_subdir#$distdir} pattern=${1%[_-]*} for file in ${pattern}*; do # This generally means the pattern did not match case "$file" in *\*) [ "$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 [ -f "$file" ] || continue case "$distfiles" in *" ${file} "*) distfiles_checked="${distfiles_checked}${file}:" [ -n "$PM_VERBOSE" ] && echo "===>>> Keeping current distfile: $file" continue # Do not delete current version ;; *) if [ -e "$DI_FILES" ]; then grep -ql ${ps}$file $DI_FILES && continue fi if [ -n "$ALWAYS_SCRUB_DISTFILES" -o \ -n "$delete_all" ]; then echo "===>>> Deleting stale distfile: $file" pm_unlink $file continue fi echo -n "===>>> Delete $file? [n] " read answer case "$answer" in [yY]) pm_unlink $file ;; *) distfiles_checked="${distfiles_checked}${file}:" ;; esac ;; esac done } set_distfiles_and_subdir () { # Global: dist_list_files distfiles port_subdir distdir [ -z "$dist_list_files" ] && find_dl_distfiles $1 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 [ -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 "===>>> $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 for file in $dist_list_files; do [ -f "$file" ] || continue case "$distfiles" in *" ${file} "*) distfiles_checked="${distfiles_checked}${file}:" [ -n "$PM_VERBOSE" ] && echo "===>>> Keeping current distfile: $file" continue # Do not delete current version ;; esac if [ -n "$ALWAYS_SCRUB_DISTFILES" -o \ -n "$delete_all" ]; then echo "===>>> Deleting stale distfile: $file" pm_unlink $file continue fi echo -n "===>>> Delete $file? [n] " read answer case "$answer" in [yY]) pm_unlink $file ;; *) distfiles_checked="${distfiles_checked}${file}:" ;; esac done fi # 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 file in $distfiles $dist_list_files; do find_and_delete_distfiles $file done [ -n "$PM_VERBOSE" ] && { echo "===>>> Distfile cleaning complete" ; echo ''; } } delete_all_distfiles () { # 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 '' 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 "$ALWAYS_SCRUB_DISTFILES" ]; then echo "===>>> Deleting all distfiles for $origin" delete_all=delete_all else echo "===>>> Delete old and new distfiles for $origin" echo -n " without prompting? [n] " local answer ; read answer case "$answer" in [yY]) delete_all=delete_all2 ;; *) echo -n "===>>> Delete the current distfiles? [n] " read answer case "$answer" in [yY]) delete_current=delete_current ;; esac ;; esac fi 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 # Get back to somewhere safe so we do not # delete our CWD out from under ourselves pm_cd $distdir || fail "Cannot cd into $distdir" find -d $distdir -type d -empty -delete } #=============== 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 [ -n "$PM_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 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 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 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 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" echo '' num_ports=$(( $num_roots + $num_trunks + $num_branches + $num_leaves )) echo "===>>> $num_ports total installed ports" if [ "$num_updates" -gt 1 ]; then echo " ===>>> $num_updates have new versions available" elif [ "$num_updates" -eq 1 ]; then echo " ===>>> 1 has a new version available" elif [ -n "$LIST_PLUS" ]; then echo " ===>>> There are no new versions available" fi exit 0 fi if [ -n "$EXPUNGE" ]; then [ -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 [ -n "$BACKUP" ] && { init_packages ; backup_package $EXPUNGE; } [ -z "$DONT_SCRUB_DISTFILES" ] && delete_all_distfiles $origin 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 [ -z "$no_del_list" ] && export no_del_list=':' for file in `find $pdb -type f -name \+REQUIRED_BY -empty` ; do iport="${file%/+REQUIRED_BY}" ; iport=${iport#$pdb/} case "$no_del_list" in *:${iport}:*) continue ;; esac origin=`origin_from_pdb $iport` deplist=`grep -l DEPORIGIN:$origin$ $pdb/*/+CONTENTS` if [ -n "$deplist" ]; then 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 answer case "$answer" in [yY]) if [ -n "$BACKUP" ]; then [ -z "$packages" ] && init_packages backup_package $iport fi [ -z "$DONT_SCRUB_DISTFILES" ] && delete_all_distfiles $origin delete_dist_list echo "===>>> Running pkg_delete -f $iport" pm_pkg_delete_s -f $iport || fail 'pkg_delete failed' exec $0 -s $ARGS ;; *) echo -n " ===>>> Keep listing $iport as a dependency? [n] " read answer case "$answer" in [yY]) no_del_list="${no_del_list}${iport}:" ;; *) pm_unlink_s $file ;; esac ;; esac done exit 0 fi #=============== End code relevant only to getopts features =============== #=============== Begin functions for main =============== already_done () { [ -n "$PM_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 return 0 } check_interactive () { [ -n "$INTERACTIVE_UPDATE" ] || return 0 local update_to [ -n "$2" ] && update_to=" to $2" case "$INTERACTIVE_YES" in *:${1}:*) return 0 ;; esac case "$INTERACTIVE_NO" in *:${1}:*) return 1 ;; esac if [ -e "$pdb/$1/+IGNOREME" ]; then echo '' echo "===>>> +IGNOREME file is present for $1" fi echo '' ; echo -n "===>>> Update ${1}${update_to}? [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 "$PM_EXCL" ] || return 0 local pat for pat in $PM_EXCL; do case "$1" in *${pat}*) if [ -n "$PM_VERBOSE" ]; then echo "===>>> Skipping $1" echo " because it matches the pattern: *${pat}*" echo '' fi return 1 ;; esac done return 0 } check_fetch_only () { [ -n "$FETCH_ONLY" ] || return 0 local sleep nf fetches echo '' sleep=5 while `ls ${TMPDIR}/f-${PM_PARENT_PID}-fetchlog-* >/dev/null 2>&1`; do nf=`ps -ax | grep [f]etch | wc -l` nf=${nf##* } fetches=fetches ; [ "$nf" -eq 1 ] && fetches=fetch echo "===>>> Waiting for ${nf##* } distfile $fetches to finish" sleep $sleep if [ $sleep -eq 10 ]; then sleep=5 else sleep=$(( $sleep + 1 )) fi done echo "===>>> Distfile fetching is complete" FETCH_ONLY_DONE=fetch_only_done safe_exit } update_port () { local update_to [ -n "$2" ] && update_to=" to $2" echo "===>>> Launching child to update ${1#$pd/}${update_to}" [ -n "$PM_DEPTH" ] && echo " $PM_DEPTH >> ${1#$pd/}" [ -n "$doing_dep_check" -o \ \( -n "$UPDATE_ALL" -a -n "$CONFIG_ONLY" \) ] && unset NO_DEP_UPDATES if [ -z "$NO_ACTION" -o -n "$CONFIG_ONLY" ]; then ($0 $ARGS $1) || fail "Update for $1 failed" . $IPC_SAVE else [ -n "$PM_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 echo "===>>> Continuing 'make config' dependency check for $portdir" else echo "===>>> Returning to dependency check for $portdir" fi return 0 } dependency_check () { # Global: doing_dep_check local d_port_list # 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 local d_port origin iport conflicts glob confl_p udf # Do not export, for THIS parent process only [ -n "$CONFIG_ONLY" ] && doing_dep_check=doing_dep_check 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 "$PM_VERBOSE" ] && echo "===>>> Checking dependency: $origin" # Do this first to catch out of date dependencies if [ -n "$CONFIG_ONLY" ]; then case "$CONFIG_SEEN_LIST" in *:${origin}:*) continue ;; esac fi [ -z "$URB_YES" ] && case "$CUR_DEPS" in *:${origin}:*) continue ;; esac conflicts='' 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}` if [ -n "$iport" ]; then check_exclude $iport || continue else check_exclude $origin || continue fi udf="$pdb/$iport/PM_UPGRADE_DONE_FLAG" if [ -n "$PM_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 # No check_interactive here because we want to tell # the user whether or not there is a new version first check_for_updates $iport $origin || fail 'Update failed' else check_interactive $origin || continue update_port $origin fi done [ -n "$CONFIG_ONLY" ] && unset doing_dep_check if [ -n "$SHOW_WORK" ]; then safe_exit elif [ -n "$CONFIG_ONLY" ]; then echo "===>>> Recursive 'make config' check complete for $portdir" case "$PM_DEPTH" in *\>\>*) echo " $PM_DEPTH" ;; esac else echo "===>>> Dependency check complete for $portdir" case "$PM_DEPTH" in *\>\>*) echo " $PM_DEPTH" ;; esac fi } create_master_rb_list () { # Global: MASTER_RB_LIST local req_by 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" } multiport () { # Global PM_MULTI_PORTS=':' ; PM_MULTI_BUILT=':' export PM_MULTI_PORTS PM_MULTI_BUILT local port worklist_temp worklist portlist # Expand globs and check that the directories exist for port in $@; do port=${port#$pdb/} case "$port" in */*) port=${port#$pd/} if [ -d "$pd/${port}" ]; then worklist_temp="$worklist_temp $port" else fail "$pd/${port} does not exist" fi ;; *) if [ -d "$pdb/$port" ]; then worklist_temp="$worklist_temp $port" else # Keep synched with code in MAIN local glob_dirs dir port=`globstrip $port` glob_dirs=`find $pdb -maxdepth 1 -type d -name ${port}\*` case "$glob_dirs" in *\*|'') fail "$pdb/$port does not exist" ;; *) for dir in $glob_dirs; do worklist_temp="$worklist_temp ${dir#$pdb/}" done ;; esac fi ;; esac done for port in $worklist_temp; do check_exclude $port || continue check_interactive $port || continue worklist="$worklist $port" portlist="${portlist}\t${port}\n" PM_MULTI_PORTS="${PM_MULTI_PORTS}${port}:" done echo "===>>> Working on multiple ports:" echo -e $portlist if [ -n "$CONFIG_ONLY" ]; then for port in $worklist; do ($0 $ARGS $port) || fail "Update for $port failed" . $IPC_SAVE done check_fetch_only unset CONFIG_SEEN_LIST CONFIG_ONLY echo '' echo "===>>> Starting build for multiple ports <<<===" echo '' fi export PM_BUILDING=pmbuildingmultiport for port in $worklist; do case "$PM_MULTI_BUILT" in *:${port}:*) continue ;; esac 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 } #=============== End functions for main =============== # INIT Parent if [ "$$" -eq "$PM_PARENT_PID" -a -z "$SHOW_WORK" ]; then CUR_DEPS=':' ; DISPLAY_LIST='' ; INSTALLED_LIST='' PM_DEPTH='' ; IPC_SAVE=`pm_mktemp IPC_SAVE` export CUR_DEPS DISPLAY_LIST INSTALLED_LIST PM_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 [ -n "$UPDATE_REQ_BYS" ] && export URB_DONE_LIST=':' if [ -n "$UPDATE_REQ_BYS" -o -n "$PM_FORCE" ]; then if [ -z "$RESTART" ]; then # Outdent files=`find $pdb -type f -name PM_UPGRADE_DONE_FLAG` if [ -n "$files" ]; then echo "===>>> There are 'install complete' flags from a previous" echo -n " -[rf] run of ${0##*/}, delete them? [n] " read answer case "$answer" in [yY]) [ -n "$PM_SU_VERBOSE" ] && echo "===>>> Deleting 'install complete' flags" pm_find_s $pdb -type f -name PM_UPGRADE_DONE_FLAG -delete ;; *) echo -n "===>>> Enable the -R option? [n] " read answer case "$answer" in [yY]) RESTART=Ropt ; ARGS="-R $ARGS" ;; esac ;; esac fi # Outdent fi fi if [ -z "$NO_RECURSIVE_CONFIG" ]; then CONFIG_SEEN_LIST=':' ; CONFIG_ONLY=config_only NO_DEP_UPDATES=no_dep_updates export CONFIG_SEEN_LIST CONFIG_ONLY NO_DEP_UPDATES 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" \ -a -z "$PM_PACKAGES" ]; then export DI_FILES=`pm_mktemp DI-FILES` fi if [ $# -gt 1 -a -z "$REPLACE_ORIGIN" ]; then multiport $@ fi 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 all_config () { local iport origin for iport in $@; do [ -n "$PM_VERBOSE" ] && echo "===>>> $iport" case "$CUR_DEPS" in *:${iport}:*) continue ;; esac case "$iport" in bsdpan-*) [ -n "$PM_VERBOSE" ] && echo " ===>>> BSDPAN ports cannot be upgraded with portmaster" continue ;; esac origin=`origin_from_pdb $iport` case "$CONFIG_SEEN_LIST" in *:${origin}:*) continue ;; esac check_exclude $iport || continue PM_DEPTH= check_for_updates $iport $origin || fail 'Update failed' CONFIG_SEEN_LIST="${CONFIG_SEEN_LIST}${origin}:" done } if [ -z "$DONT_SCRUB_DISTFILES" -a -z "$FETCH_ONLY" ]; then (read_distinfos)& fi ports_by_category echo "===>>> Starting check of installed ports for available updates" if [ -n "$CONFIG_ONLY" ]; then [ -n "$FETCH_ONLY" ] && export ALL_FETCH=all_fetch echo "===>>> Checking ports for recursive 'make config'" [ -n "$PM_VERBOSE" ] && { echo '' ; echo "===>>> Root ports:"; } all_config $roots [ -n "$PM_VERBOSE" ] && { echo '' ; echo "===>>> Trunk ports:"; } all_config $trunks [ -n "$PM_VERBOSE" ] && { echo '' ; echo "===>>> Branch ports:"; } all_config $branches [ -n "$PM_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 CONFIG_SEEN_LIST CONFIG_ONLY echo '' echo "===>>> Starting build for ports that need updating <<<===" echo '' fi export PM_BUILDING=pmbuildingall 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 case "$iport" in bsdpan-*) continue ;; esac PM_DEPTH= if [ -n "$PM_FORCE" ]; then 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 continue fi if [ -z "$NO_RECURSIVE_CONFIG" ]; then check_interactive $iport || continue # We got here, so we know we have to build it update_port $iport else [ -n "$PM_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 no_valid_port () { echo "===>>> No valid installed port, or port directory given"; echo "===>>> Try ${0##*/} --help" ; echo '' ; safe_exit 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%/} ; argv=`globstrip $argv` case "$argv" in '') 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 if [ -z "$portdir" -a -z "$upg_port" ]; then # Keep synched with code in multiport() glob_dirs=`find $pdb -maxdepth 1 -type d -name ${argv}\*` case "$glob_dirs" in *\*|'') echo '' ; no_valid_port ;; # Match a newline in multiple responses from find *' '*) multiport $glob_dirs ;; $pdb/*) upg_port=${glob_dirs#$pdb/} ;; *) echo '' ; no_valid_port ;; esac fi 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 fi if [ -n "$upg_port" -a -z "$REPLACE_ORIGIN" ]; then portdir=`origin_from_pdb $upg_port` if [ ! -n "$portdir" ]; then case "$upg_port" in bsdpan-*) echo '' echo "===>>> BSDPAN ports cannot be upgraded with portmaster" echo " (${upg_port})"; echo ''; safe_exit ;; *) fail "No ORIGIN in $pdb/$upg_port/+CONTENTS" ;; esac fi 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 [ -d "$pd/$moved_npd" ] || no_valid_port if [ "$$" -eq "$PM_PARENT_PID" ]; then $0 $ARGS -o $moved_npd $upg_port safe_exit else exec $0 $ARGS -o $moved_npd $upg_port fi fi [ -z "$upg_port" -a -z "$REPLACE_ORIGIN" ] && upg_port=`iport_from_origin ${portdir}` if [ -e "$pdb/$upg_port/+IGNOREME" ]; then # Adding to CUR_DEPS means we will not get here in the build unless -G if [ -z "$PM_BUILDING" ]; then # Only need to prompt for this once if -ai case "$INTERACTIVE_YES" in *:${upg_port}:*) ;; # Let it build *) if [ -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" -o -n "$URB_YES" ]; then echo '' echo "===>>> $upg_port has an +IGNOREME file, ignoring" echo '' safe_exit fi fi # START # Should only be reached for multiport already built as a dependency case "$CONFIG_SEEN_LIST" in *:${portdir}:*) safe_exit ;; esac pm_cd $pd/$portdir || no_valid_port if [ -z "$PM_DEPTH" ]; then PM_DEPTH=${upg_port:-$portdir} else PM_DEPTH="$PM_DEPTH >> ${upg_port:-$portdir}" fi echo '' [ "$$" -eq "$PM_PARENT_PID" -a -n "$upg_port" ] && echo "===>>> Currently installed version: $upg_port" echo "===>>> Port directory: $pd/$portdir" 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 not start this in the background until we are sure we are going to build if [ "$$" -eq "$PM_PARENT_PID" -a -z "$SHOW_WORK" -a -z "$PM_PACKAGES" \ -a -z "$DONT_SCRUB_DISTFILES" -a -z "$FETCH_ONLY" ]; then echo ''; (read_distinfos)& fi # Do these things first time through, with or without 'make config' if [ -z "$PM_BUILDING" -a -z "$SHOW_WORK" -a -z "$NO_ACTION" ]; then dofetch () { echo "===>>> Launching 'make checksum' for $portdir in background" fetchlog=`pm_mktemp fetchlog-${portdir#*/}` (pm_make -DBATCH checksum >> $fetchlog 2>&1 && { rm -f ${TMPDIR}/f-${PM_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 pm_make -DBATCH checksum >> $fetchlog 2>&1; \ rm -f ${TMPDIR}/f-${PM_PARENT_PID}-*-${portdir#*/}.* )& } # Handle the problem of manual fetching # XXX Not for -P/-PP [ -z "$PM_PACKAGES" ] && master_sites=`pm_make_b -V MASTER_SITES` if [ -n "$master_sites" ]; then # 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 if ! ls ${TMPDIR}/f-${PM_PARENT_PID}-${file}-* >/dev/null 2>&1 then pm_mktemp ${file}-${portdir#*/} >/dev/null else DONT_FETCH=dont_fetch break fi done [ -z "$DONT_FETCH" -a -n "$distfiles" ] && dofetch fi unset master_sites if [ -z "$FETCH_ONLY" -a ! "$PM_PACKAGES" = 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" echo " require attention during the build" echo '' echo -n "===>>> Press the [Enter] or [Return] key to continue " read DISCARD echo '' fi fi if [ -n "$CONFIG_ONLY" ]; then config_type=config-conditional [ -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}:" 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 "$PM_PARENT_PID" ]; then # Save state for the parent process to read back in echo "CONFIG_SEEN_LIST='$CONFIG_SEEN_LIST'" > $IPC_SAVE safe_exit elif [ -n "$UPDATE_REQ_BYS" ]; then export URB_YES=urb_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 case "$URB_DONE_LIST" in *:${req_by}:*) already_done $req_by continue ;; esac [ -n "$PM_VERBOSE" ] && echo "===>>> $upg_port is required by $req_by" check_exclude $req_by || continue check_interactive $req_by || continue # Shortcut, since check_for will force it if [ -z "$RESTART" -a -z "$PM_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 check_fetch_only unset CONFIG_SEEN_LIST CONFIG_ONLY echo "===>>> Starting build for $portdir <<<===" echo '' fi [ -z "$PM_BUILDING" ] && export PM_BUILDING=pmbuildingmain cd $pd/$portdir if [ -z "$NO_DEP_UPDATES" ]; then if [ -z "$RECURSE_THOROUGH" ]; then if [ ! "$PM_PACKAGES" = only ]; then echo "===>>> Starting check for build dependencies" dependency_check build-depends-list fi else echo "===>>> Starting check for all dependencies" dependency_check all-depends-list fi cd $pd/$portdir elif [ -z "$NO_RECURSIVE_CONFIG" -a "$$" -eq "$PM_PARENT_PID" ]; then echo "===>>> The 'make config' check found no dependencies to update" echo '' fi if [ -n "$NO_ACTION" -a -z "$CONFIG_ONLY" ]; then [ -n "$PM_VERBOSE" ] && echo "===>>> Build canceled due to -n flag" safe_exit fi new_port=`pm_make -V PKGNAME` # XXX Build or package? if [ -n "$PM_PACKAGES" ]; then if [ -z "$PACKAGESITE" ]; then release=`uname -r` #release=7.0-RELEASE-p12 #release=8.0-RC1 #release=8.0-STABLE case "$release" in [678]\.[0-9]-STABLE) release=packages-${release%%\.*}-stable ;; [678]\.[0-9]-RELEASE*) release=packages-${release%-RELEASE*}-release ;; 9\.0-CURRENT) release=packages-8-current ;; # XXX *RC[0-9]*) release=${release%-RC[0-9]} release=packages-${release}-release ;; *BETA[0-9]*) release=${release%-BETA[0-9]} release=packages-${release}-release ;; esac sitepath="${PACKAGEROOT:-"http://ftp.freebsd.org"}/pub/FreeBSD/ports/`uname -p`/${release}/" unset release else sitepath="$PACKAGESITE" fi sitepath="${sitepath%/}/${portdir%/*}/" +#echo '' #echo "Debug> sitepath: $sitepath" +#echo '' [ -n "$PM_VERBOSE" ] && echo "===>>> Checking package repository" latest_link=`pm_make -V LATEST_LINK` latest_pv=`fetch -q -o - ${sitepath} 2>/dev/null | grep ">$latest_link"` unset latest_link if [ -z "$latest_pv" ]; then echo "===>>> Package and/or archive not found at:" echo "${sitepath}" echo '' echo " Check the pkg_add(1) man page for information" echo " on setting the PACKAGESITE environment variable" fail 'No package archive found' fi - latest_pv=${latest_pv#*tbz\">} + latest_pv=${latest_pv#*href=\"} latest_pv=${latest_pv%%\.tbz*} + case "$latest_pv" in + *%2[cC]*) latest_pv=`echo $latest_pv | sed s#%2[cC]#,#` ;; + esac +#echo '' #echo "Debug> new_port: $new_port latest_pv: $latest_pv" +#echo '' notnewer () { echo '' echo "===>>> The newest available package ($latest_pv)" echo " is not newer than the installed version ($upg_port)" } if [ "$latest_pv" = "$new_port" ]; then use_package=up_equal [ -n "$PM_VERBOSE" ] && echo "===>>> Available package ($latest_pv) matches the ports tree" elif [ -n "$PM_PACKAGES_NEWER" ]; then if [ -n "$upg_port" ]; then case `pkg_version -t $upg_port $latest_pv` in \<) use_package=up_newer [ -n "$PM_VERBOSE" ] && { echo "===>>> Available package ($latest_pv)"; echo " is newer than installed ($upg_port)"; } ;; =) if [ -n "$PM_FORCE" ]; then use_package=up_force else notnewer fi ;; *) notnewer ;; esac else use_package=up_no_installed [ -n "$PM_VERBOSE" ] && echo "===>>> There is a package available ($latest_pv)" fi else # Could happen if ports tree is out of date case `pkg_version -t $new_port $latest_pv` in \<) use_package=up_old_tree [ -n "$PM_VERBOSE" ] && { echo "===>>> Available package ($latest_pv)"; echo " is newer than ports tree ($new_port)"; } ;; =) ;; # Should not be reached *) echo '' echo "===>>> The newest available package ($latest_pv)" echo " is older than the version in ports ($new_port)" if [ "$PM_PACKAGES" = only ]; then if [ -n "$PM_FORCE" ]; then use_package=up_force2 echo "===>>> Installing anyway due to -f" else fail "Try --packages-if-newer, or do not use -PP/--packages-only" fi fi ;; esac fi if [ -n "$use_package" ]; then new_port=$latest_pv else if [ "$PM_PACKAGES" = only ]; then fail "There is no valid package to install" else echo '' echo "===>>> There is no valid package to install, building port instead" echo '' fi fi fi if [ -z "$use_package" ]; then [ -z "$DONT_PRE_CLEAN" ] && { pm_make clean NOCLEANDEPENDS=ncd || fail 'make clean failed'; echo ''; } sleep=3 fl_read=`echo ${TMPDIR}/f-${PM_PARENT_PID}-fetchlog-${portdir#*/}.*` while [ -f "$fl_read" ]; do echo "===>>> Waiting on fetch & checksum for $portdir <<<===" tail -10 $fl_read 2>/dev/null echo '' ; echo '' sleep $sleep if [ $sleep -eq 10 ]; then sleep=3 else sleep=$(( $sleep + 1 )) fi done unset sleep if [ -n "$HIDE_BUILD" ]; then port_log=`mktemp -t port_log-${PM_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" else # XXX fetch # Duplicated from pkg_init() packages=`pm_make -f/usr/share/mk/bsd.port.mk -V PACKAGES` [ -n "$packages" ] || fail 'The value of PACKAGES cannot be empty' ppd=$packages/portmaster-download if [ ! -d "$ppd" ]; then [ -n "$PM_SU_VERBOSE" ] && echo "===>>> Creating $ppd" pm_mkdir_s $ppd fi export ppd [ -n "$PM_VERBOSE" ] && echo "===>>> Starting package fetch" fetch_args=`pm_make -f/usr/share/mk/bsd.port.mk -V FETCH_ARGS` fetch $fetch_args -o $ppd ${sitepath}${latest_pv}.tbz 2>/dev/null || { pm_unlink ${ppd}/${latest_pv}.tbz; fetch $fetch_args -o $ppd ${sitepath}${latest_pv}.tbz || fail "Fetch for ${latest_pv}.tbz failed"; } fi # XXX Build or package? # Ignore if no old port exists if [ -n "$upg_port" ]; then UPGRADE_PORT=$upg_port UPGRADE_PORT_VER=`echo $UPGRADE_PORT | sed 's#.*-\(.*\)#\1#'` export UPGRADE_PORT UPGRADE_PORT_VER [ -z "$NO_BACKUP" ] && backup_package $upg_port if [ -n "$SAVE_SHARED" ]; then ldconfig_out=`pm_mktemp ldconfig` ldconfig -r | sed 's#.* ##' | grep -v ^$LOCALBASE_COMPAT > $ldconfig_out unset temp for file in `pkg_info -q -L $upg_port | sort - $ldconfig_out | \ uniq -d`; do temp="${temp}$file " done 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 find_dl_distfiles $portdir if [ -n "$REPLACE_ORIGIN" ]; then # 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 [ -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 -z "$NO_DEP_UPDATES" ]; then echo '' ; echo "===>>> Starting check for runtime dependencies" dependency_check run-depends-list cd $pd/$portdir fi install_failed () { 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 $1 ($portdir) failed" } echo '' if [ -z "$use_package" ]; then [ -n "$PM_SU_VERBOSE" ] && echo "===>>> Running make install" 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. eval pm_make_s -DNO_DEPENDS install $port_log_args || install_failed $new_port else # XXX Install the package echo "===>>> Installing package" pkg_add --no-deps --force ${ppd}/${latest_pv}.tbz || install_failed ${latest_pv}.tbz fi echo '' # Remove saved libs that match newly installed files 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 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 [ -z "$use_package" ] && distfiles=`pm_make -V ALLFILES | sed -e 's# *$##g'` if [ -n "$distfiles" ]; then distfiles=" ${distfiles} " # 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=`pm_make_b -V OPTIONSFILE` dist_list="${dist_list%options}distfiles" 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 "$PM_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" pm_make_s package >/dev/null || fail "Package creation of $new_port failed" echo " ===>>> Package saved to $packages/All" ; echo '' fi [ -z "$DONT_POST_CLEAN" -a -z "$use_package" ] && { pm_make clean NOCLEANDEPENDS=ncd2 ; echo ''; } check_dependency_files $portdir $new_port if [ -s "$grep_deps" ]; then echo "===>>> Updating package dependency entry for each dependent port" [ -n "$PM_VERBOSE" ] && echo '' while read d_port; do [ -n "$PM_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 # Do this one last so it can get deleted as a duplicate # if ro_opd is 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 [ -e "$pdb/$new_port/+REQUIRED_BY" ]; then sort $pdb/$new_port/+REQUIRED_BY | cmp -s $grep_deps - || do_update=do_update check_regular_file $pdb/$new_port/+REQUIRED_BY else do_update=do_update2 fi if [ -n "$do_update" ]; then [ -n "$PM_VERBOSE" ] && { echo ''; echo " ===>>> Updating $new_port/+REQUIRED_BY"; } pm_install_s $grep_deps $pdb/$new_port/+REQUIRED_BY fi 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 if [ "$$" -ne "$PM_PARENT_PID" -o -n "$UPDATE_REQ_BYS" ]; then echo "===>>> $ilist succeeded" ; echo '' fi [ -n "$PM_MULTI_BUILT" ] && PM_MULTI_BUILT="${PM_MULTI_BUILT}${new_port}:${portdir}:" INSTALLED_LIST="${INSTALLED_LIST}\t${ilist}\n" [ -e "$pdb/$new_port/+DISPLAY" ] && DISPLAY_LIST="${DISPLAY_LIST}$new_port " CUR_DEPS="${CUR_DEPS}${new_port}:${portdir}:" [ -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 "$PM_FORCE" ] && $PM_SU_CMD touch $pdb/$new_port/PM_UPGRADE_DONE_FLAG if [ -z "$DONT_SCRUB_DISTFILES" ]; then delete_stale_distfiles $portdir if [ -n "$ro_opd" ]; then delete_all_distfiles $ro_opd delete_dist_list fi fi if [ -n "$UPDATE_REQ_BYS" -a -s "$pdb/$new_port/+REQUIRED_BY" ]; then export URB_YES=urb_yes2 echo "===>>> Updating ports that depend on $new_port" echo '' create_master_rb_list for req_by in $MASTER_RB_LIST; do # Probably not needed, but JIC [ -d "$pdb/$req_by" ] || continue case "$URB_DONE_LIST" in *:${req_by}:*) already_done $req_by ; continue ;; esac # Check here since if "no" it will not prompt check_interactive $req_by || continue [ -n "$PM_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 "$PM_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 updating ports that depend on $new_port" echo '' fi safe_exit #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Copyright (c) 2005-2009 Douglas Barton # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE.