Subject: RFC: new variable SUGGESTS
To: None <tech-pkg@netbsd.org>
From: Jan Schaumann <jschauma@netbsd.org>
List: tech-pkg
Date: 07/21/2002 14:41:33
--Dxnq1zWXvFF0Q93v
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hello everybody,

Below please find a proposal for the implementation of a new pkgsrc
variable 'SUGGESTS'.  Please comment on the usefulness, the
implementation, the flaws etc.


The problem:
------------
Several packages have what may be called "soft dependencies"; that is,
they include a DEPENDS line for a package that they do not strictly
depend upon.  Sometimes a package does not require another package, yet
it simply makes sense to install a second package alongside.  If a
package works well with a number of other packages, there is currently
no way for the package maintainer to allow the user to choose one (or
more).

Examples:
(1) sysutils/amanda DEPENDS on sysutils/amanda-plot, which can only
    be installed on systems which include X, yet amanda is fully functional
    without amanda-plot.
(2) wm/blackbox is a package for the Blackbox WindowManager, which does
    not implement keybindings.  Virtually every blackbox-user will
    install a keygrabber, most often wm/bbkeys;  yet, wm/blackbox must
    not DEPEND on bbkeys, as it is not a strict requirement, and other
    users may want to use it without a keygrabber
(3) consider a package for a piece of software that works well with a
    range of other packages.  One such an example is "grip" (which,
    currently, is not yet in pkgsrc).  Grip is a GTK-Audio-Player/
    CD-Ripper/MP3-Encoder.  It will work without any mp3-encoder or
    audio-ripper as pure CD-Player.  With any audio-ripper, it gains
    more functionality, with any mp3-encoder even more.  It may, for
    example, work with audio/lame, audio/bladeenc, audio/gogo or
    audio/flac;  yet, it must not DEPEND on all of those.  Nor can it
    DEPEND on one, as a user may have the other installed, etc.
(4) if it is known that there exists for example a benchmark-package for
    a given package, it may make sense to install this as well, yet the
    package must, for obvious reasons, not DEPEND on it.

The Solution:
-------------
The solution to these problems is the implementation of a new variable,
called "SUGGESTS".  (Debian GNU/Linux users may find this concept
familiar.)  This variable specifies a number of packages, that the user
may choose to install.  The user may specify whether to blindly install
all suggested packages, to be prompted for each individual suggested
package or to ignore all suggestions ("I know what I'm doing!").

The package maintainer may now suggest additional software that is known
to work well with her package, or that simply makes sense to be
installed alongside.

The Implementation:
-------------------
A packages Makefile may contain lines like this:
	SUGGESTS=	name:../../dir/dir
	SUGGESTS+=	name2:../../dir2/dir2

This is almost identical to DEPENDS, with the exception that 'name' may
not wild-cards (for example "foo>=5.8:../../bar/foo").  Since
suggestions are mere hints and may be ignored by the user, it does not
make sense to suggest a wildcarded or version-specific package.

pkgsrc/mk/bsd.pkg.mk has a new variable called "TAKE_SUGGESTS", which
may have the values "YES", "NO" and "ASK" and defaults to "NO".  This
variable may be set in /etc/mk.conf.

After a package has been installed and registered, 'make' now checks
the value of TAKE_SUGGESTS and performs the following actions, according
to the value:
	YES - make goes through the list of suggested packages and installs
	      the packages that are not already installed
	ASK - make loops through the list of suggested packages, prompting
	      the user for each package.  If the user wants to install a
	      suggested package, we check if it is already installed.  If
	      not, we install it.
	NO  - All suggested packages are ignored.  Note that this is the
	      default action when BATCH is defined, regardless of the value
	      of TAKE_SUGESSTS.


Note that suggested packages are not included in the list of
dependencies (nor should they!) and are therefore not removed upon
recursive package deletion.  Nor will pkgsrc complain if you deinstall a
suggested package purely on it having been suggested by another
package.  To remove suggested packages with their 'parents',
pkgsrc/mk/bsd.pkg.mk has a new variable called "DEINSTALLSUGGESTS",
which defaults to "NO".  This variable may be set in /etc/mk.conf.

If a user sets DEINSTALLSUGGESTS to any value other than "NO", suggested
packages are removed together with the package when issuing 'make
deinstall'.

Examples:
In the above examples, the problems are solved through the use of the
new variable SUGGESTS as follows:
(1) in sysutils/amanda, replace

DEPENDS+=   amanda-client-2.4.2p2:../../sysutils/amanda-client
DEPENDS+=   amanda-server-2.4.2p2:../../sysutils/amanda-server
DEPENDS+=  amanda-plot-2.4.2p2:../../sysutils/amanda-plot

with

DEPENDS+=   amanda-client-2.4.2p2:../../sysutils/amanda-client
DEPENDS+=   amanda-server-2.4.2p2:../../sysutils/amanda-server

SUGGESTS=  amanda-plot-2.4.2p2:../../sysutils/amanda-plot

(2) move wm/bbkeys to misc/bbkeys (it really doesn't belong into wm/,
and I assume it just sits there since it kinda belongs to blackbox) and
add the following line to wm/blackbox:

SUGGESTS=	bbkeys:../../misc/bbkeys

(3) A package for grip might contain the following lines:

# any one of the following will do
SUGGESTS=  lame:../../audio/lame
SUGGESTS+=  bladeenc:../../audio/bladeenc
SUGGESTS+=  gogo:../../audio/gogo
SUGGESTS+=  flac:../../audio/flac

(4) You get the idea.


Attached find a patch that implements this variable as described above
and adds the appropriate paragraph to Packages.txt.  This is my first
stab at implementing a "real" target in pkgsrc, so I'm sure there is
plenty of room for improvement.  I'll be happy about all critique.

Thanks,
-Jan

-- 
Life," said Marvin, "don't talk to me about life."

--Dxnq1zWXvFF0Q93v
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="suggests.diff"

Index: mk/bsd.pkg.mk
===================================================================
RCS file: /cvsroot/pkgsrc/mk/bsd.pkg.mk,v
retrieving revision 1.1009
diff -b -u -r1.1009 bsd.pkg.mk
--- mk/bsd.pkg.mk	2002/07/21 11:53:18	1.1009
+++ mk/bsd.pkg.mk	2002/07/21 18:37:31
@@ -65,6 +65,9 @@
 
 INTERACTIVE_STAGE?=	none
 
+TAKE_SUGGESTS?= NO
+DEINSTALLSUGGESTS?= NO
+
 .if defined(USE_JAVA)
 BUILD_DEFS+=		PKG_JVM JAVA_HOME
 .  if !defined(PKG_JVM)
@@ -1342,6 +1345,86 @@
 		${FALSE} ;;						\
 	esac
 
+################################################################
+# Suggestions                                                  #
+################################################################
+.if !target(check-suggests)
+check-suggests:
+.	if ${TAKE_SUGGESTS} == "YES" || ${TAKE_SUGGESTS} == "yes"
+		${_PKG_SILENT}${_PKG_DEBUG} \
+		for sugg in ${SUGGESTS}; do \
+			pkg=$${sugg%%:*}; \
+			dir=$${sugg#*:}; \
+			found=`${PKG_INFO} -e $$pkg || ${TRUE}`; \
+			if [ "X$$found" != "X" ]; then   \
+				${ECHO} "Suggested package $$pkg found: $$found"; \
+			else \
+				${ECHO_MSG} "=> Installing suggested package $$pkg ..."; \
+				cd $$dir; \
+				${MAKE} ${MAKEFLAGS} reinstall; \
+			fi; \
+		done; 
+.	elif ${TAKE_SUGGESTS} == "ASK"  && !defined(BATCH)
+		${_PKG_SILENT}${_PKG_DEBUG} \
+		for sugg in ${SUGGESTS}; do \
+			pkg=$${sugg%%:*}; \
+			dir=$${sugg#*:}; \
+			found=`${PKG_INFO} -e $$pkg || ${TRUE}`; \
+			if [ "X$$found" != "X" ]; then   \
+				${ECHO} "Suggested package $$pkg found: $$found"; \
+			else \
+				read -p "Install suggested package $$pkg? [y/n] " ANS; \
+				if [ "X$$ANS" = "Xy" ]; then \
+					${ECHO_MSG} "=> Installing suggested package $$pkg ..."; \
+					cd $$dir; \
+					${MAKE} ${MAKEFLAGS} reinstall; \
+				fi; \
+			fi; \
+		done;
+.	endif # TAKE_SUGGESTS == "YES"
+.endif # !target(check-suggests)
+
+# show suggestions
+.if !target(show-suggests-dirs)
+show-suggests-dirs:
+	${_PKG_SILENT}${_PKG_DEBUG}					\
+	dlist="";							\
+	thisdir=`pwd`;							\
+	for reldir in "" ${SUGGESTS:C/^[^:]*://:C/:.*$//} ;\
+	do								\
+		if [ "X$$reldir" = "X" ]; then continue; fi;		\
+		cd $$thisdir/$$reldir;					\
+		WD=`pwd`;						\
+		d=`dirname $$WD`;					\
+		absdir=`basename $$d`/`basename $$WD`;			\
+		dlist="$$dlist $$absdir";				\
+	done;								\
+	cd $$thisdir;							\
+	${ECHO} "$$dlist"
+.endif
+
+.if !target(show-installed-suggests)
+show-installed-suggests:
+.  if defined(SUGGESTS)
+	${_PKG_SILENT}${_PKG_DEBUG}					\
+	for i in ${SUGGESTS:C/:.*$//:Q:S/\ / /g} ; do			\
+		echo "$$i =>" `${PKG_INFO} -e $$i` ;			\
+	done
+.  endif
+.endif
+
+.if !target(clean-suggests)
+clean-suggests:
+.  if defined(SUGGESTS)
+	${_PKG_SILENT}${_PKG_DEBUG}					\
+	for i in `${MAKE} ${MAKEFLAGS} CLEAN_SUGGESTS_LIST_TOP=YES clean-suggests-list | ${SED} -e 's;\.\./[^ ]*; ;g' | ${TR} -s "[:space:]" "\n" | ${SORT} -u` ;\
+	do 								\
+		cd ${.CURDIR}/../../$$i &&				\
+		${MAKE} ${MAKEFLAGS} CLEANSUGGESTS=NO clean;		\
+	done
+.  endif
+.endif
+
 .if !target(do-fetch)
 do-fetch:
 .  if !empty(_ALLFILES)
@@ -2172,6 +2255,7 @@
 .if defined(PKG_DEVELOPER) && (${CHECK_SHLIBS} == "YES")
 	@${MAKE} ${MAKEFLAGS} check-shlibs
 .endif
+	@${MAKE} ${MAKEFLAGS} check-suggests
 
 
 
@@ -2717,6 +2801,17 @@
 	fi
 .    endfor
 .  endif # DEINSTALLDEPENDS
+.  if ${DEINSTALLSUGGESTS} != "NO"
+	@${SHCOMMENT} Also remove SUGGESTS:
+.    for pkg in ${SUGGESTS:C/:.*$//}
+	${_PKG_SILENT}${_PKG_DEBUG}					\
+	found="`${PKG_INFO} -e \"${pkg}\" || ${TRUE}`";			\
+	if [ "$$found" != "" ]; then					\
+		${ECHO} Running ${PKG_DELETE} $$found;			\
+		${PKG_DELETE} ${real-su-deinstall-flags} $$found || ${TRUE}; \
+	fi
+.    endfor
+.  endif # DEINSTALLSUGGESTS
 	@${RM} -f ${INSTALL_COOKIE} ${PACKAGE_COOKIE}
 .endif						# target(deinstall)
 
@@ -2943,7 +3038,6 @@
 .  endif
 .endif
 
-
 .if !target(clean-depends)
 clean-depends:
 .  if defined(BUILD_DEPENDS) || defined(DEPENDS)
@@ -2993,6 +3087,32 @@
 		${ECHO} " ${PKGPATH} $$CLEAN_DEPENDS_LIST_SEEN";	\
 	else								\
 		${ECHO} " $$CLEAN_DEPENDS_LIST_SEEN";			\
+	fi
+.  endif
+.endif
+
+.if !target(clean-suggests-list)
+clean-suggests-list:
+.  if defined(SUGGESTS)
+	@for dir in `${ECHO} ${SUGGESTS:C/^[^:]*://:C/:.*//} |		\
+			${TR} '\040' '\012' `; do			\
+		case "$$CLEAN_SUGGESTS_LIST_SEEN" in			\
+		*" "$$dir" "*)  ;; 					\
+		*) 							\
+			CLEAN_SUGGESTS_LIST_SEEN=" $$dir `cd ${.CURDIR} ; cd $$dir && ${MAKE} ${MAKEFLAGS} CLEAN_SUGGESTS_LIST_SEEN="$$CLEAN_SUGGESTS_LIST_SEEN" CLEAN_SUGGESTS_LIST_TOP=NO clean-suggests-list`";\
+			;;						\
+		esac							\
+	done ;								\
+	if [ "${CLEAN_SUGGESTS_LIST_TOP}" != "YES" ]; then		\
+		${ECHO} " ${PKGPATH} $$CLEAN_SUGGESTS_LIST_SEEN";	\
+	else								\
+		${ECHO} " $$CLEAN_SUGGESTS_LIST_SEEN";			\
+	fi
+.  else
+	@if [ "${CLEAN_SUGGESTS_LIST_TOP}" != "YES" ]; then		\
+		${ECHO} " ${PKGPATH} $$CLEAN_SUGGESTS_LIST_SEEN";	\
+	else								\
+		${ECHO} " $$CLEAN_SUGGESTS_LIST_SEEN";			\
 	fi
 .  endif
 .endif
Index: Packages.txt
===================================================================
RCS file: /cvsroot/pkgsrc/Packages.txt,v
retrieving revision 1.258
diff -b -u -r1.258 Packages.txt
--- Packages.txt	2002/07/04 13:42:11	1.258
+++ Packages.txt	2002/07/21 18:37:40
@@ -1396,6 +1396,10 @@
       done in pkgsrc/x11/kde, this is likely to remove whole KDE. Works by
       adding a "-R" to the pkg_delete command line.
 
+    - DEINSTALLSUGGESTS:
+      Additionally remove all packages suggested by the given package.
+      Works similarly to DEINSTALLDEPENDS.
+
  * update:
    This target causes the current package to be updated to the latest
    version.  The package and all depending packages first get de-installed,
@@ -1528,6 +1532,10 @@
    This target shows which installed packages match the current package's
    DEPENDS. Useful if out of date DEPENDS are causing build problems.
 
+ * show-installed-suggests:
+   This target shows which installed packages match the current package's
+   SUGGESTS.
+
  * check-shlibs:
    After a package is installed, check all it's binaries and (on ELF 
    platforms) shared libraries if they find the shared libs they need.
@@ -2059,8 +2067,38 @@
 and a different version string. "Xaw3d-1.5" e.g. will automatically conflict
 with the older version "Xaw3d-1.3".
 
+
+ 10.14 Suggesting other packages
+ ===============================
+
+Your package, even though it may not strictly DEPEND on another package, may
+suggest other packages that are useful with this package.  This allows the
+package maintainer to point the user to, for example, benchmark tests for the
+package in question or allow the user to select from a range of options that
+simply make sense to install alongside this package.
+
+The format is almost exactly as the format of DEPENDS, with the exception that
+you can not specify a version numbers or wildcards when suggesting a package,
+since suggestions are nothing more than pure hints, which the user may choose
+to ignore.
+
+For example, pkgsrc/wm/blackbox contains a WindowManager which does not
+include keybindings.  The vast majority of the users will want to install a
+keygrabber such as pkgsrc/wm/bbkeys, yet it is not a strict dependency for
+blackbox.  Thus, pkgsrc/wm/blackbox SUGGESTS the bbkeys package:
+
+    SUGGESTS=	bbkeys:../../wm/bbkeys
+
+The way suggestions are implemented allows the user to choose between ignoring
+suggestions alltogether, installing them or be prompted for each package to
+choose whether or not it should be installed.  This behaviour is regulated
+through the TAKE_SUGGESTS variable defined in /etc/mk.conf.  TAKE_SUGGESTS
+defaults to the value "NO", causing all suggestions to silently be ignored.
+Other possible values are "YES" and "ASK" with their logical consequences.
+(If BATCH is defined, suggestions are automatically ignored.)
+
 
- 10.14 Software which has a WWW Home Page
+ 10.15 Software which has a WWW Home Page
  ========================================
 
 The NetBSD packages system now supports a variable called HOMEPAGE.
@@ -2070,7 +2108,7 @@
 variable.
 
 
- 10.15 How to handle modified distfiles with the 'old' name
+ 10.16 How to handle modified distfiles with the 'old' name
  ==========================================================
 
 Sometimes authors of a software package make some modifications after the
@@ -2085,7 +2123,7 @@
 crept in.
 
 
- 10.16 What does "Don't know how to make /usr/share/tmac/tmac.andoc" mean?
+ 10.17 What does "Don't know how to make /usr/share/tmac/tmac.andoc" mean?
  =========================================================================
 
 When compiling the pkgsrc/pkgtools/pkg_install package, you get the error
@@ -2097,7 +2135,7 @@
 NOMAN=YES either in the environment or in /etc/mk.conf.
 
 
- 10.17 How to handle incrementing versions when fixing an existing package
+ 10.18 How to handle incrementing versions when fixing an existing package
  =========================================================================
 
 When making fixes to an existing package it can be useful to change
@@ -2118,7 +2156,7 @@
 DISTNAME=	foo-17.43
 
 
- 10.18 "Could not find bsd.own.mk" - what's wrong?
+ 10.19 "Could not find bsd.own.mk" - what's wrong?
  =================================================
 
 You didn't install the compiler set, comp.tgz, when you installed your
@@ -2130,7 +2168,7 @@
 the release you have installed (determine via "uname -r").
 
 
- 10.19 Restricted packages
+ 10.20 Restricted packages
  =========================
 
 Some licenses restrict how software may be re-distributed.  In order to
@@ -2167,7 +2205,7 @@
 unconditionally prevent users from generating binary packages!
 
 
- 10.20 Packages using (n)curses
+ 10.21 Packages using (n)curses
  ==============================
 
 Some packages need curses functionality that wasn't present in NetBSD's own
@@ -2182,7 +2220,7 @@
 define USE_NCURSES in the package's Makefile.
 
 
- 10.21 Automated security check
+ 10.22 Automated security check
  ==============================
 
 Please be aware that there can often be bugs in third-party software,
@@ -2238,7 +2276,7 @@
 /pub/NetBSD/packages/distfiles/vulnerabilities on ftp.netbsd.org. 
 
 
- 10.22 What's the proper way to create an account from a package?
+ 10.23 What's the proper way to create an account from a package?
  ================================================================
 
 There are two make variables used to control the creation of package-specific
@@ -2271,7 +2309,7 @@
 prior to package installation.
 
 
- 10.23 How to handle compiler bugs
+ 10.24 How to handle compiler bugs
  =================================
 
 Some source files trigger bugs in the compiler, based on combinations
@@ -2285,7 +2323,7 @@
 examples.
 
 
- 10.24 Packages providing info files
+ 10.25 Packages providing info files
  ===================================
 
 Some packages install info files or use the makeinfo or install-info
@@ -2333,7 +2371,7 @@
     mk/texinfo.mk).
 
 
- 10.25 Packages whose distfiles aren't available for plain downloading
+ 10.26 Packages whose distfiles aren't available for plain downloading
  =====================================================================
 
 If you need to download from a dynamic URL you can set DYNAMIC_MASTER_SITES
@@ -2351,7 +2389,7 @@
 www/ap-aolserver, www/openacs. Try to be consistent with them.
 
 
- 10.26 Using pkgsrc on non-NetBSD (Linux, Solaris, Darwin, MacOS X)
+ 10.27 Using pkgsrc on non-NetBSD (Linux, Solaris, Darwin, MacOS X)
  ==================================================================
 
 In order to use pkgsrc on a non-NetBSD operating system, you must first
@@ -2359,7 +2397,7 @@
 http://www.zoularis.org/ for information on boostrapping.
 
 
- 10.27 Configuration files handling and placement
+ 10.28 Configuration files handling and placement
  ================================================
 
 The global variable PKG_SYSCONFBASE (and some others) can be set by the

--Dxnq1zWXvFF0Q93v--