Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 28 Nov 2000 17:34:52 +0100
From:      Stijn Hoop <stijn@win.tue.nl>
To:        Garrett Wollman <wollman@khavrinen.lcs.mit.edu>
Cc:        ports@freebsd.org
Subject:   Re: Upgrade hack idea
Message-ID:  <20001128173452.A94211@pcwin002.win.tue.nl>
In-Reply-To: <200011272051.PAA96852@khavrinen.lcs.mit.edu>; from wollman@khavrinen.lcs.mit.edu on Mon, Nov 27, 2000 at 03:51:56PM -0500
References:  <200011272051.PAA96852@khavrinen.lcs.mit.edu>

next in thread | previous in thread | raw e-mail | index | archive | help

--oyUTqETQ0mS9luUI
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi,

On Mon, Nov 27, 2000 at 03:51:56PM -0500, Garrett Wollman wrote:
> I just did an upgrade from libpng.so.3 to libpng.so.4 on one of my
> machines.  I did not want to recompile the client applications, and I
> did want to keep some record of the installation of this library and
> its dependencies so I remember to delete it when I do recompile those
> clients.
>
> I went through the following steps, which seem to be fairly
> automatable, and would make a nice script hack (on the level of
> `save_shared_libraries png-1.0.5 png-compat-1.0.5').

[snip procedure]

I took your idea and automated it. Attached is my updateport script
that takes these exact steps. Before running it, you need to create
${PREFIX}/lib/compat (for the port, this usually means /usr/X11R6 and
/usr/local) and add it to /etc/rc.conf in the ${ldconfig_path} variable.

The one thing this script doesn't do: it doesn't handle updating dependencies
at the same time. So if port #1 depends on an update of port #2, and you
run portupdate port #1, you'll *install* the new version of port #2, not
update it. You'd have to run updateport port #2 first.

I suppose this idea really needs to be in bsd.port.mk, but the script is older
than your idea, I just updated it and thought that this could be handy for
others. It could also be updated to use Maxim's new information in /var/db/pkg
as to the origin of a package, but I don't have the right bsd.port.mk now
so I couldn't test that. For now it guesses the old version of a port from
the information in /var/db/pkg.

Note that I only tested it with your shared library idea *ONCE* on
print/gnomeprint, upgraded from under gnumeric. This worked like a charm
but YMMV of course. Warning, alpha quality code, here be dragons, etc.

Regards,

--Stijn

--oyUTqETQ0mS9luUI
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=updateport

#!/bin/sh

# ----------------------------------------------------------------------------
# "THE BEER-WARE LICENSE" (Revision 42):
# <stijn@win.tue.nl> wrote this file.  As long as you retain this notice you
# can do whatever you want with this stuff. If we meet some day, and you think
# this stuff is worth it, you can buy me a beer in return.   Stijn Hoop
# ----------------------------------------------------------------------------

# Global settings
PORTSDIR=/usr/ports
PKGDBDIR=/var/db/pkg
COMPATLIBDIR=lib/compat

# Check arguments
if [ -z "$1" ]; then
	echo "Usage: $0 <port-to-upgrade>"
	echo
	echo "For example:"
	echo "	$0 misc/screen"
	exit 1
fi

if [ ! -d "${PORTSDIR}/$1" ]; then
	echo "===>  Error: ${PORTSDIR}/$1 not found. Stop."
	exit 1
fi

# Figure out the upgrade path
echo "===>  Determining installed port version for $1"
cd $PORTSDIR/$1 || exit 1
PORTNAME=`make -V PKGNAMEPREFIX``make -V PORTNAME``make -V PKGNAMESUFFIX`
OLDVERSION=`ls -d ${PKGDBDIR}/${PORTNAME}-[0-9]* 2>/dev/null | \
		sed "s/^.*-\(.*\)$/\1/"`
if [ -z $OLDVERSION ]; then
	echo "===> No old version of $PORTNAME installed."
	exit 1
fi
OLDNAME=${PORTNAME}-${OLDVERSION}
NEWVERSION=`make -V PORTVERSION``make -V _SUF1``make -V _SUF2`
NEWNAME=`make -V PKGNAME`
if [ $NEWNAME = $OLDNAME ]; then
	echo "===>  ${PORTNAME} is up to date (at version $OLDVERSION)."
	exit 2
fi

# For shared library compatability
PREFIX=`make -V PREFIX`
COMPATNAME=${PORTNAME}-compat-${OLDVERSION}

# Figure out if the port installs shared libraries
if [ ! -z `make -V INSTALLS_SHLIB` ]; then
	SHLIB_SAVE=

	# Determine upgraded libraries
	NEWLIBS=`grep '\.so\.' pkg-plist | sort`
	for i in $NEWLIBS; do
		NEWLIBNAME=`echo $i | sed "s/\.[0-9][0-9]*$//"`
		NEWLIBVERSION=`echo $i | sed "s/^.*\.\([0-9][0-9]*\)$/\1/"`
		OLDLIBNAME=`grep "$NEWLIBNAME\." \
			${PKGDBDIR}/${OLDNAME}/+CONTENTS`
		OLDLIBVERSION=`echo ${OLDLIBNAME} | \
			sed "s/^.*\.\([0-9][0-9]*\)$/\1/"`
		if [ ! -z $OLDLIBVERSION ]; then
			if [ $OLDLIBVERSION != $NEWLIBVERSION ]; then
				# An incompatible shared library version
				SHLIB_SAVE="${SHLIB_SAVE} ${OLDLIBNAME}"
			fi
		fi
	done

	# Now determine libraries that aren't in the new port anymore, and
	# save them too
	OLDLIBS=`grep '\.so\.' ${PKGDBDIR}/${OLDNAME}/+CONTENTS | sort`
	for i in $OLDLIBS; do
		OLDLIBNAME=`echo $i | sed "s/\.[0-9][0-9]*$//"`
		if ! grep $OLDLIBNAME pkg-plist >/dev/null; then
			SHLIB_SAVE="${SHLIB_SAVE} $i"
		fi
	done
else
	SHLIB_SAVE=
fi

# Ask for confirmation for now, this script is still not well tested.
echo "===>  Upgrading ${OLDNAME} to ${NEWNAME}"
if [ ! -z "$SHLIB_SAVE" ]; then
	echo "       WARNING: this will upgrade shared libraries, which other"
	echo "       programs may depend on! Doing this automatically is not"
	echo "       always guaranteed to yield usable results."
fi
read -p "===>   Are you sure you want to do this? [y/n] " ANS
if [ "x$ANS" != "xyes" -a "x$ANS" != "xy" ]; then
	echo "===>   Upgrade cancelled."
	exit 1;
fi

# Save the old package metadata for later use
cp -rp ${PKGDBDIR}/${OLDNAME} ${PKGDBDIR}/${COMPATNAME}
if [ ! -z "$SHLIB_SAVE" ]; then
	# Build a new +CONTENTS for the compat package, containing
	# just the shared libraries.
	CONTENTS=`mktemp -t updateport`
	if [ $? -ne 0 ]; then
		echo "$0: Can't create temporary file."
		exit 1
	fi

	echo "@name ${COMPATNAME}" >> $CONTENTS
	echo "@cwd ${PREFIX}" >> $CONTENTS
	for i in $SHLIB_SAVE; do
		cp -p ${PREFIX}/$i ${PREFIX}/${COMPATLIBDIR}
		echo $i | sed "s#lib/#${COMPATLIBDIR}/#" >> $CONTENTS
		echo "@comment MD5:"`md5 -q ${PREFIX}/$i` >> $CONTENTS
	done
	echo "@unexec ldconfig -R" >> $CONTENTS
	mv -f $CONTENTS ${PKGDBDIR}/${COMPATNAME}/+CONTENTS
	chmod a+r ${PKGDBDIR}/${COMPATNAME}/+CONTENTS
	ldconfig -m ${PREFIX}/${COMPATLIBDIR}
fi

# Upgrade the port (building it if necessary)
make || exit 1
pkg_delete -f ${OLDNAME} || exit 1
make install || exit 1

# Update dependencies
echo "===>  Updating dependencies from ${OLDNAME} to ${NEWNAME}"
if [ -e ${PKGDBDIR}/${COMPATNAME}/+REQUIRED_BY ]; then
	if [ -z "$SHLIB_SAVE" ]; then
		# Let's just hope we are binary compatible...
		REPLACE=${NEWNAME}
	else
		# Change the dependencies to use compat package
		REPLACE=${COMPATNAME}
	fi
	for i in `cat ${PKGDBDIR}/${COMPATNAME}/+REQUIRED_BY`; do
		if [ -e ${PKGDBDIR}/$i/+CONTENTS ]; then
			perl -pi -e "s/${OLDNAME}/${REPLACE}/g" \
				${PKGDBDIR}/$i/+CONTENTS
		fi
	done
	if [ -z "$SHLIB_SAVE" ]; then
		cp ${PKGDBDIR}/${COMPATNAME}/+REQUIRED_BY \
			${PKGDBDIR}/${REPLACE}/+REQUIRED_BY
	fi
fi

# Remove the compat 'package' if we're not installing a new shared library
if [ -z "$SHLIB_SAVE" ]; then
	rm -rf ${PKGDBDIR}/${COMPATNAME}
else
	echo "===>  The old shared libraries (if any) were saved in a"
	echo "      compatability 'package' named ${COMPATNAME} for"
	echo "      your convenience."
fi

--oyUTqETQ0mS9luUI--


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-ports" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20001128173452.A94211>