Subject: package dependency checking is not friendly or safe with CVS/sup/etc.
To: NetBSD Packages Technical Discussion List <tech-pkg@NetBSD.ORG>
From: Greg A. Woods <woods@most.weird.com>
List: tech-pkg
Date: 12/12/1999 15:54:24
WindowMaker's pkgsrc Makefile has the following line in it:

	DEPENDS+=		libproplist-0.9.*:../../devel/libproplist

This causes the build to do this:

	===>  windowmaker-0.61.1 depends on package: libproplist-0.9.*
	===>  Verifying install for ../../devel/libproplist
	===>  Returning to build of windowmaker-0.61.1

Unfortunately it doesn't check the right things:

	15:09 [1110] $ /usr/sbin/pkg_info -I libproplist
	libproplist-0.8.3   GNUstep/OPENSTEP property lists compatibility library

Oops -- there's an older and incompatible version already there!

This all happens because of an overy simplistic (or presumptious) bit of
logic in the "misc-depends:" target of bsd.pkg.mk.  If the exact package
is not found with pkg_info then it is assumed that one can just dive
over to the dependent package's pkgsrc module and building it.

However this didn't work in the above case because I've got a left-over
"work" directory in the libproplist module that was from the previous
version of the package.

This happens regularly for me because I "sup" (and "cvs import ... yyy"
and "cvs update -j xxx -j yyy", etc.) but do not do a "make clean"
first.

I think the logic in "misc-depends:" could relatively easily be made
smart enough (now, with the more modern and smarter pkgtools) so that it
would know enough to fail (or optionally "pkg_delete && make clean &&
make install") if *any* non-matching version of a dependent package was
indeed installed.

The problem could of course be avoided by recommending (and of course
documenting!) that I (and anyone else doing similar tracking of pkgsrc)
should just run "make clean" at the top before I do my "sup" (or "cvs
update").  In my environment that's slightly more complex because I use
"OBJMACHINE" and would thus need to do something like "make superclean"
where that target removed every "work*" directory.....  However that
presumes that would be overly wasteful and costly too because I have
sometimes got work directories where I'm still doing new packages or
upgrades, etc.

I'd like to propose the following change as a minimum fix, but of course
I'm not opposed to making it smart enough to *optionally* go and do a
"pkg_delete && make clean && make install":

(line numbers will be off...)
***************
*** 2117,2130 ****
  	if [ X"$$found" != X"" ]; then					\
  		${ECHO_MSG} "===>  ${PKGNAME} depends on installed package: $$package - `${ECHO} $$found | ${SED} -e 's|${PKG_DBDIR}/||g' | tr '\012' '\040'` found"; \
  	else								\
! 		${ECHO_MSG} "===>  ${PKGNAME} depends on package: $$package"; \
! 		target=${DEPENDS_TARGET};				\
! 		${ECHO_MSG} "===>  Verifying $$target for $$dir"; 	\
! 		if [ ! -d $$dir ]; then					\
! 			${ECHO_MSG} ">> No directory for $$dir.  Skipping.."; \
  		else							\
! 			(cd $$dir && ${MAKE} ${.MAKEFLAGS} $$target) &&	\
! 			${ECHO_MSG} "===>  Returning to build of ${PKGNAME}"; \
  		fi;							\
  	fi
  .endfor
--- 2123,2143 ----
  	if [ X"$$found" != X"" ]; then					\
  		${ECHO_MSG} "===>  ${PKGNAME} depends on installed package: $$package - `${ECHO} $$found | ${SED} -e 's|${PKG_DBDIR}/||g' | tr '\012' '\040'` found"; \
  	else								\
! 		oldpackage="`${ECHO} \"$$package\" | ${SED} -e 's:-[^-]*$$::'`"; \
! 		found="`${PKG_INFO} -e \"$$oldpackage\" || ${TRUE}`";	\
! 		if [ ${DEPENDS_TARGET} = "install" -a X"$$found" != X"" ]; then				\
! 			${ECHO_MSG} "===>  dependent package version did not match: $$package - `${ECHO} $$found | ${SED} -e 's|${PKG_DBDIR}/||g' | tr '\012' '\040'` found"; \
! 			false;						\
  		else							\
! 			${ECHO_MSG} "===>  ${PKGNAME} depends on package: $$package"; \
! 			target=${DEPENDS_TARGET};			\
! 			${ECHO_MSG} "===>  Verifying $$target for $$dir"; 	\
! 			if [ ! -d $$dir ]; then				\
! 				${ECHO_MSG} ">> No directory for $$dir.  Skipping.."; \
! 			else						\
! 				(cd $$dir && ${MAKE} ${.MAKEFLAGS} $$target) &&	\
! 				${ECHO_MSG} "===>  Returning to build of ${PKGNAME}"; \
! 			fi;							\
  		fi;							\
  	fi
  .endfor


Now it does the following:

	15:49 [1142] $ make 
	===>  Validating dependencies for windowmaker-0.61.1
	>> Checksum OK for WindowMaker-0.61.1.tar.bz2.
	===>  Extracting for windowmaker-0.61.1
	===>  windowmaker-0.61.1 depends on file: /usr/pkg/bin/pkglibtool-a.out-1.2p2 - found
	===>  dependent package version did not match: libproplist-0.9.* - libproplist-0.8.3  found
	*** Error code 1
	
	Stop.

It would be better to barf during the "Validating dependencies" phase,
but I didn't try figuring out why the ${ECHO_MSG} wasn't echoing
anything at that point....

-- 
							Greg A. Woods

+1 416 218-0098      VE3TCP      <gwoods@acm.org>      <robohack!woods>
Planix, Inc. <woods@planix.com>; Secrets of the Weird <woods@weird.com>