aboutsummaryrefslogtreecommitdiff
path: root/ports-mgmt/wanted-ports
diff options
context:
space:
mode:
authorRene Ladan <rene@FreeBSD.org>2010-06-15 17:28:05 +0000
committerRene Ladan <rene@FreeBSD.org>2010-06-15 17:28:05 +0000
commite48a81f15b7b7d99cf725f7282071143db1c528b (patch)
tree7bc91de64808200c5cbaf1ee094dee0c2b766244 /ports-mgmt/wanted-ports
parent7722c237ddb97841be284d8e8bbf876f4832221b (diff)
downloadports-e48a81f15b7b7d99cf725f7282071143db1c528b.tar.gz
ports-e48a81f15b7b7d99cf725f7282071143db1c528b.zip
A special meta-port to do nothing but register dependencies on those
ports you specifically want to have installed. The normal dependency checking in programs like pkg_delete(1) will prevent easy deletion of ports that other ports depend on. Keeps egg off face. Protects feet from being shot. PR: ports/147808 Submitted by: Matthew Seaman <m.seaman at infracaninophile.co.uk> Approved by: tabthorpe (mentor)
Notes
Notes: svn path=/head/; revision=256557
Diffstat (limited to 'ports-mgmt/wanted-ports')
-rw-r--r--ports-mgmt/wanted-ports/Makefile47
-rw-r--r--ports-mgmt/wanted-ports/files/wanted-ports.1.in238
-rw-r--r--ports-mgmt/wanted-ports/files/wanted-ports.in370
-rw-r--r--ports-mgmt/wanted-ports/files/wanted-ports.pod129
-rw-r--r--ports-mgmt/wanted-ports/pkg-descr5
5 files changed, 789 insertions, 0 deletions
diff --git a/ports-mgmt/wanted-ports/Makefile b/ports-mgmt/wanted-ports/Makefile
new file mode 100644
index 000000000000..908da0d9d909
--- /dev/null
+++ b/ports-mgmt/wanted-ports/Makefile
@@ -0,0 +1,47 @@
+# New ports collection makefile for: wanted-ports
+# Date created: 7 June 2010
+# Whom: Matthew Seaman <m.seaman@infracaninophile.co.uk>
+#
+# $FreeBSD$
+#
+# port is self-contained in the files directory.
+
+PORTNAME= wanted-ports
+PORTVERSION= 0.1
+#PORTREVISION is set from ${CFGFILE}
+CATEGORIES= ports-mgmt
+MASTER_SITES= # none
+DISTFILES= # none
+
+MAINTAINER= m.seaman@infracaninphile.co.uk
+COMMENT= Just depend on a configurable, arbitrary set of other ports
+
+LICENSE= BSD
+
+NO_BUILD= yes
+SUB_FILES= ${PORTNAME} \
+ ${PORTNAME}.1
+SUB_LIST= PORTNAME=${PORTNAME} \
+ PKGNAME=${PKGNAME}
+PLIST_SUB= PORTNAME=${PORTNAME}
+PLIST_FILES= bin/${PORTNAME}
+
+MAN1= ${PORTNAME}.1
+
+.if defined(WANTEDPORTSCFG)
+CFGFILE= ${WANTEDPORTSCFG}
+.else
+CFGFILE?= /var/db/${PORTNAME}.conf
+.endif
+
+.if exists(${CFGFILE})
+.include "${CFGFILE}"
+.endif
+
+do-install:
+ ${INSTALL_SCRIPT} ${WRKDIR}/${PORTNAME} ${PREFIX}/bin/${PORTNAME}
+.if !defined(NOPORTDOCS)
+ ${INSTALL_MAN} ${WRKDIR}/${PORTNAME}.1 ${MANPREFIX}/man/man1/
+.endif
+
+.include <bsd.port.mk>
diff --git a/ports-mgmt/wanted-ports/files/wanted-ports.1.in b/ports-mgmt/wanted-ports/files/wanted-ports.1.in
new file mode 100644
index 000000000000..45050a268892
--- /dev/null
+++ b/ports-mgmt/wanted-ports/files/wanted-ports.1.in
@@ -0,0 +1,238 @@
+.\" Automatically generated by Pod::Man 2.22 (Pod::Simple 3.07)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings. \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote. \*(C+ will
+.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+. ds -- \(*W-
+. ds PI pi
+. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+. ds L" ""
+. ds R" ""
+. ds C` ""
+. ds C' ""
+'br\}
+.el\{\
+. ds -- \|\(em\|
+. ds PI \(*p
+. ds L" ``
+. ds R" ''
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD. Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.ie \nF \{\
+. de IX
+. tm Index:\\$1\t\\n%\t"\\$2"
+..
+. nr % 0
+. rr F
+.\}
+.el \{\
+. de IX
+..
+.\}
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear. Run. Save yourself. No user-serviceable parts.
+. \" fudge factors for nroff and troff
+.if n \{\
+. ds #H 0
+. ds #V .8m
+. ds #F .3m
+. ds #[ \f1
+. ds #] \fP
+.\}
+.if t \{\
+. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+. ds #V .6m
+. ds #F 0
+. ds #[ \&
+. ds #] \&
+.\}
+. \" simple accents for nroff and troff
+.if n \{\
+. ds ' \&
+. ds ` \&
+. ds ^ \&
+. ds , \&
+. ds ~ ~
+. ds /
+.\}
+.if t \{\
+. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+. \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+. \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+. \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+. ds : e
+. ds 8 ss
+. ds o a
+. ds d- d\h'-1'\(ga
+. ds D- D\h'-1'\(hy
+. ds th \o'bp'
+. ds Th \o'LP'
+. ds ae ae
+. ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "WANTED-PORTS 1"
+.TH WANTED-PORTS 1 "2010-06-12" "perl v5.10.1" "User Contributed Perl Documentation"
+.\" For nroff, turn off justification. Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+%%PORTNAME%% \-\- depend on the ports that you want installed
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+\&\fB%%PORTNAME%%\fR [\fB\-n\fR] [\fB\-f\fR \fIconfig\fR] [\fB\-a|\-d\fR \fIportname\fR]]
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+\&\fB%%PORTNAME%%\fR is a small port that simply has a user modifiable list
+of run-time dependencies. The idea is that by marking a port as
+wanted, it adds a double check helping to prevent accidental deletion
+of the ports you really want to have installed. \fIpkg_delete\fR\|(1) will
+refuse to delete a port when that port is a dependency required by
+some other installed port, unless you give the \fB\-f\fR option to force
+the action.
+.PP
+\&\fB%%PORTNAME%%\fR can also be used as a means to automate installing the
+required software load on a server.
+.SS "Using \fB%%PORTNAME%%\fP"
+.IX Subsection "Using %%PORTNAME%%"
+The first time you run the \fB%%PORTNAME%%\fR script, it will generate a
+skeleton configuration file. Run \fB%%PORTNAME%%\fR to modify the list
+of ports that you want to have marked. This will automatically
+increment the \f(CW\*(C`PORTREVISION\*(C'\fR of \fB%%PORTNAME%%\fR, marking the
+\&\fIports\-mgmt/%%PORTNAME%%\fR port to be updated, eg. the next time that
+\&\fIportmaster\fR\|(8) or \fIportupgrade\fR\|(1) is run.
+.PP
+Updating or reinstalling the port will cause the ports system to force
+all of the marked ports to be installed, using the standard dependency
+resolution mechanisms of the ports.
+.SH "OPTIONS"
+.IX Header "OPTIONS"
+.IP "\fB\-n\fR" 8
+.IX Item "-n"
+Dry-run. Causes \fB%%PORTNAME%%\fR not to update the configuration file,
+but instead to display what the final result would have been.
+.IP "\fB\-f\fR \fIconfig\fR" 8
+.IX Item "-f config"
+Read and modify an alternate configuration file. \fIconfig\fR should be
+the full path to the alternate file. \fINote:\fR when updating the
+\&\fIports\-management/%%PORTNAME%%\fR port, set \f(CW\*(C`CFGFILE\*(C'\fR or
+\&\f(CW\*(C`WANTEDPORTSCFG\*(C'\fR in the \fImake\fR\|(1) environment to achieve the same
+effect.
+.IP "\fB\-a\fR \fIportname\fR" 8
+.IX Item "-a portname"
+Add dependencies. Find all matching package names or port paths from
+the \fI\s-1INDEX\s0\fR file, and prompt the user whether to add any that are not
+already listed as dependencies in the configuration file.
+.IP "\fB\-d\fR \fIportname\fR" 8
+.IX Item "-d portname"
+Delete dependencies. Find all matching package names or port paths
+from the \fI\s-1INDEX\s0\fR file, and prompt the user whether to delete any that
+are currently listed as dependencies in the configuration file.
+.PP
+The add \fB\-a\fR and delete \fB\-d\fR options are processed in the order
+given on the command line, so a later option can override an earlier
+one. The \fIportname\fR argument will match any substring of the port or
+package name: care should be taken that you don't accidentally match
+unintended items. You can anchor searches to start or end of item
+using \f(CW\*(C`^\*(C'\fR or \f(CW\*(C`$\*(C'\fR.
+.SH "FILES"
+.IX Header "FILES"
+.IP "\fI/var/db/%%PORTNAME%%.conf\fR" 16
+.IX Item "/var/db/%%PORTNAME%%.conf"
+The default configuration file used by \fB%%PORTNAME%%\fR. This is a
+\&\fImakefile\fR snippet, that will be included by
+\&\fIports\-mgmt/%%PORTNAME%%/Makefile\fR. A skeleton version will be
+created by \fB%%PORTNAME%%\fR if it doesn't exist. The \fB%%PORTNAME%%\fR
+script exists to add or remove \f(CW\*(C`RUN_DEPENDS\*(C'\fR entries and update the
+\&\f(CW\*(C`PORTREVISION\*(C'\fR setting.
+.SH "ENVIRONMENT"
+.IX Header "ENVIRONMENT"
+The following environment variables affect the operation of
+\&\fB%%PORTNAME%%\fR. \f(CW\*(C`PORTSDIR\*(C'\fR, \f(CW\*(C`INDEXFILE\*(C'\fR and \f(CW\*(C`WANTEDPORTSCFG\*(C'\fR
+override the system default settings: normally they will not need to
+be set. \f(CW\*(C`USER\*(C'\fR and \f(CW\*(C`LOGNAME\*(C'\fR are standard settings, from
+\&\fIlogin\fR\|(1).
+.ie n .IP """PORTSDIR""" 16
+.el .IP "\f(CWPORTSDIR\fR" 16
+.IX Item "PORTSDIR"
+As in \fIports\fR\|(7), the location where the ports tree is installed.
+Default \fI/usr/ports\fR
+.ie n .IP """INDEXFILE""" 16
+.el .IP "\f(CWINDEXFILE\fR" 16
+.IX Item "INDEXFILE"
+As in \fIports\fR\|(7), overrides the automatic logic to determine the name
+of the index file. Default \fI\s-1INDEX\-\s0\fIN\fI\fR where \fIN\fR is the \s-1OS\s0 major
+version number.
+.ie n .IP """USER""" 16
+.el .IP "\f(CWUSER\fR" 16
+.IX Item "USER"
+.PD 0
+.ie n .IP """LOGNAME""" 16
+.el .IP "\f(CWLOGNAME\fR" 16
+.IX Item "LOGNAME"
+.PD
+The name of the user running the script. If neither are set, uses
+\&\f(CW\*(C`an unknown user\*(C'\fR.
+.ie n .IP """WANTEDPORTSCFG""" 16
+.el .IP "\f(CWWANTEDPORTSCFG\fR" 16
+.IX Item "WANTEDPORTSCFG"
+Override the default location of the configuration file. Using the
+\&\fB\-f config\fR command line option superceeds this setting. Default
+\&\fI/var/db/%%PORTNAME%%.conf\fR
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+\&\fIports\fR\|(7), \fIpkg_delete\fR\|(1), \fIpkg_cutleaves\fR\|(1), \fIportmaster\fR\|(8),
+\&\fIportupgrade\fR\|(1)
diff --git a/ports-mgmt/wanted-ports/files/wanted-ports.in b/ports-mgmt/wanted-ports/files/wanted-ports.in
new file mode 100644
index 000000000000..c29af3232389
--- /dev/null
+++ b/ports-mgmt/wanted-ports/files/wanted-ports.in
@@ -0,0 +1,370 @@
+#!/bin/sh
+#
+# $FreeBSD$
+
+# Copyright 2010 Matthew Seaman. 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 ``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.
+
+# Programatically edit the dependencies of %%PKGNAME%% to mark
+# depended on ports as wanted and help prevent accidental
+# removal. Wanted dependencies are read from a makefile snippet
+# containing PORTREVISION and RUN_DEPENDS variable settings:
+# PORTREVISION is incremented when any changes are made via this
+# script, which will cause this port to be reinstalled the next time
+# the ports are updated, hence forcing installation of the required
+# dependencies. Removing a depended-on port from the list does not
+# cause it to be removed automatically.
+
+umask 022
+IFS='
+'
+PATH=/bin:/sbin:/usr/bin:/usr/sbin:%%PREFIX%%/bin:%%PREFIX%%/sbin
+export IFS PATH
+
+
+# Dissect the PKGVERSION string, extracting the revision number.
+# Increment it or set it to 1 if unset and return the incremented
+# number.
+increment_revision () {
+ local revision
+
+ revision=$( echo $1 | sed -ne 's:^[^_]*_\([^,]*\).*$:\1:p' )
+ if [ ! -z $revision ]; then
+ revision=$(( $revision + 1 ))
+ else
+ revision=1
+ fi
+ echo $revision
+}
+
+# Update the $wanted_ports_conf file carefully.
+update_wanted_ports_conf() {
+ local conf_file revision run_deps tmp_conf
+
+ conf_file=$1
+ revision=$2
+ run_deps=$3
+
+
+ tmp_conf=$(mktemp "${conf_file%/*}/.${conf_file##*/}.XXXXXX")
+ if [ $? -ne 0 ]; then
+ echo "${ME}: FATAL -- Can't create temporary file in ${conf_file%/*}."
+ exit 1
+ fi
+
+ generate_conf $revision "$run_deps" > $tmp_conf
+
+ cp ${conf_file} ${conf_file}.old && \
+ cp $tmp_conf ${conf_file} && \
+ rm -f $tmp_conf
+}
+
+# Generate a new config file
+generate_conf() {
+ local revision run_deps firstline
+
+ revision=$1
+ run_deps=$2
+
+ cat <<EOF
+# -*- makefile -*-
+#
+# Last updated by ${USER} using ${ME} on ${DATE}
+#
+# Config file for %%PKGNAME%%. Maintain it using %%PORTNAME%%
+
+PORTREVISION= ${revision}
+
+EOF
+
+ printf 'RUN_DEPENDS=\t'
+
+ firstline=
+ for rd in $run_deps ; do
+ [ -z $firstline ] || printf ' \\\n\t\t'
+ echo -n $rd
+ firstline=no
+ done
+ echo
+ echo
+}
+
+# Given a pkgname or port directory, construct a RUN_DEPENDS entry for
+# it. Since we have no way of knowing what files are significant from
+# among whatever the port installs (and the port may not even be
+# installed yet) use the form
+# "pkgname>=n.nn:${PORTSDIR}/category/portname" where n.nn is the
+# currently available version of the port. Requires the INDEX to have
+# been installed. This can return any number of dependency lines,
+# including none.
+#
+# Note: Don't allow %%PORTNAME%% to add a dependency on itself...
+run_dep_from_index() {
+ local pkgpat
+
+ pkgpat=$1
+
+ # pkgpat should be a single word -- but it could be empty
+ for pp in $pkgpat ; do
+ # Has your head exploded yet?
+ awk -F '|' -v x=$pp \
+ '$1 ~ x || $2 ~ x { printf "%s:%s\n", $1, $2 }' \
+ < ${PORTSDIR}/${INDEXFILE} | grep -v %%PORTNAME%% | \
+ sed -e 's/-\([^-]*\):/>=\1:/' -e "s,${PORTSDIR},\${PORTSDIR},"
+ done
+}
+
+# Get the existing value of RUN_DEPENDS from the config file, and update it
+# against the current INDEX file.
+update_run_deps() {
+ local conf_file run_deps
+
+ conf_file=$1
+ run_deps=$( PORTSDIR=${PORTSDIR} make -f $conf_file -V RUN_DEPENDS )
+
+ for rd in $run_deps ; do
+ rd=$( echo $rd | sed -e "s,^.*${PORTSDIR},," -e 's, *$,$,' )
+ run_dep_from_index $rd
+ done | sort -u
+}
+
+# Return 0 or 1 according to user input "Y|y|yes" or "N|n|no"
+check_yesno() {
+ local answer junk rc
+
+ rc=
+ while [ -z $rc ]; do
+ read answer junk
+ case $answer in
+ [Yy]|[Yy][Ee][Ss])
+ rc=0
+ ;;
+ [Nn]|[Nn][Oo])
+ rc=1
+ ;;
+ *)
+ echo -n "${ME}: Errr... what?"
+ ;;
+ esac
+ done
+
+ return $rc
+}
+
+
+# Usage message
+usage() {
+ echo >&2 <<EOF
+${ME}: Usage
+ ${ME} [-n] [-f cfgfile] [-a portname|-d portname]...
+
+ Options:
+
+ -n dry-run: don't commit changes to $CONF_FILE
+ -f cfgfile alternative config file (default: $CONF_FILE)
+ -a portname add portname to the list of wanted files
+ -d portname remove portname from the list of wanted files
+
+ -a and -d options are processed in the order given on the command
+ line: later items may undo the effect of earlier ones.
+
+ portnames are matched against both the pkgname and the path within
+ the ports tree. One portname can result in adding or removing
+ dependencies on a number of different ports.
+
+ Trying to add %%PORTNAME%% as a dependency of itself is an error.
+
+ Without arguments, ${ME} will update the config file to reference
+ the current versions of any run-depends listed in the ports INDEX.
+
+EOF
+}
+
+add_dependency() {
+ local portname run_deps to_add
+
+ portname=$1
+ run_deps=$2
+
+ to_add=$( run_dep_from_index "$portname" )
+
+ # Check on exiting dependencies
+ {
+ for ta in $to_add ; do
+ if echo "$run_deps" | grep -q -F $ta ; then
+ echo "${ME}: Dependency \"$ta\" already registered" >&2
+ else
+ echo -n "${ME}: Register new dependency \"$ta\"? " >&2
+ if check_yesno >&2 ; then
+ echo $ta
+ fi
+ fi
+ done
+ echo "$run_deps"
+ } | sort -u
+}
+
+delete_dependency() {
+ local portname run_deps to_delete
+
+ portname=$1
+ run_deps=$2
+
+ to_delete=$( run_dep_from_index "$portname" )
+
+ for rd in $run_deps ; do
+ if echo "$to_delete" | grep -q -F $rd ; then
+ echo -n "${ME}: Delete dependency \"$rd\"? " >&2
+ if ! check_yesno >&2 ; then
+ echo $rd
+ fi
+ else
+ echo $rd
+ fi
+ done | sort -u
+}
+
+# Program name
+ME=${0##*/}
+
+# User running this scipt
+USER=${USER:-${LOGNAME:-"an unknown user"}}
+
+# Date now
+DATE=$( date )
+
+# Where the ports tree is installed
+PORTSDIR=${PORTSDIR:-/usr/ports}
+
+# We need the ports tree to be installed
+if ! [ -d ${PORTSDIR} -a -f ${PORTSDIR}/Makefile ] ; then
+ echo "${ME}: FATAL -- do you have the ports tree installed?" >&2
+ exit 1
+fi
+
+# The ports INDEX file
+INDEXFILE=${INDEXFILE:-$( make -f ${PORTSDIR}/Makefile -V INDEXFILE )}
+
+if ! [ -f ${PORTSDIR}/${INDEXFILE} ] ; then
+ echo "${ME}: FATAL -- can\'t access ${PORTSDIR}/${INDEXFILE}" >&2
+ exit 1
+fi
+
+# Makefile snippet containing PORTREVISION and RUN_DEPENDS data
+# Set WANTEDPORTSCFG in the environment to override, or use the -f
+# command line option
+CONF_FILE=${WANTEDPORTSCFG:-/var/db/%%PORTNAME%%.conf}
+
+# The currently installed version of %%PKGNAME%% -- accounting for any
+# dynamic updates to PORTREVISION
+INSTALLED_PKG=$( pkg_info -Ex %%PKGNAME%% )
+
+if [ -z $INSTALLED_PKG ] ; then
+ echo "${ME}: FATAL -- the package providing this script seems " \
+ "not to be installed" >&2
+ exit 1
+fi
+
+#
+# Handle Options -- Main Code Loop
+#
+
+dry_run=
+action=
+while getopts nf:a:d: opt ; do
+ case $opt in
+ n)
+ dry_run=yes
+ ;;
+ f)
+ CONF_FILE="$OPTARG"
+ ;;
+ a)
+ action="${action} A:${OPTARG}"
+ ;;
+ d)
+ action="${action} D:${OPTARG}"
+ ;;
+ *)
+ usage
+ exit 1
+ esac
+done
+
+#
+# Create the config file if it doesn't exist
+#
+
+if ! [ -f ${CONF_FILE} ] ; then
+ if [ -z $dry_run ] ; then
+ echo "${ME}: WARNING -- no config file found, " \
+ "creating initial ${CONF_FILE}" >&2
+ generate_conf 1 '' > ${CONF_FILE}
+ else
+ echo "${ME}: WARNING -- no config file found, " \
+ "dry run: this is what would have been generated" >&2
+ generate_conf 1 '' >&2
+ exit 0
+ fi
+fi
+
+#
+# Update and modify the list of run-depends
+#
+
+RUN_DEPS=$( update_run_deps ${CONF_FILE} )
+
+for a in $action ; do
+ case ${a%%:*} in
+ A)
+ # Add a port or ports
+ RUN_DEPS=$( add_dependency "${a#*:}" "$RUN_DEPS" ) >&1
+ ;;
+ D)
+ # Remove a port or ports
+ RUN_DEPS=$( delete_dependency "${a#*:}" "$RUN_DEPS" ) >&1
+ ;;
+ esac
+done
+
+#
+# Maybe write out the result to the config file, bumping the
+# PORTREVISION from the installed version of %%PORTNAME%%
+#
+
+revision=$( increment_revision $INSTALLED_PKG )
+
+if [ -z $dry_run ] ; then
+ # Do it
+ update_wanted_ports_conf $CONF_FILE $revision "$RUN_DEPS"
+else
+ echo "Dry run -- this is what would have been generated:"
+ generate_conf $revision "$RUN_DEPS"
+fi
+
+#
+# That's All Folks!
+#
diff --git a/ports-mgmt/wanted-ports/files/wanted-ports.pod b/ports-mgmt/wanted-ports/files/wanted-ports.pod
new file mode 100644
index 000000000000..36f1ec1d996c
--- /dev/null
+++ b/ports-mgmt/wanted-ports/files/wanted-ports.pod
@@ -0,0 +1,129 @@
+=head1 NAME
+
+%%PORTNAME%% -- depend on the ports that you want installed
+
+=head1 SYNOPSIS
+
+B<%%PORTNAME%%> [B<-n>] [B<-f> F<config>] [B<-a|-d> F<portname>]]
+
+=head1 DESCRIPTION
+
+B<%%PORTNAME%%> is a small port that simply has a user modifiable list
+of run-time dependencies. The idea is that by marking a port as
+wanted, it adds a double check helping to prevent accidental deletion
+of the ports you really want to have installed. L<pkg_delete(1)> will
+refuse to delete a port when that port is a dependency required by
+some other installed port, unless you give the B<-f> option to force
+the action.
+
+B<%%PORTNAME%%> can also be used as a means to automate installing the
+required software load on a server.
+
+=head2 Using B<%%PORTNAME%%>
+
+The first time you run the B<%%PORTNAME%%> script, it will generate a
+skeleton configuration file. Run B<%%PORTNAME%%> to modify the list
+of ports that you want to have marked. This will automatically
+increment the C<PORTREVISION> of B<%%PORTNAME%%>, marking the
+F<ports-mgmt/%%PORTNAME%%> port to be updated, eg. the next time that
+L<portmaster(8)> or L<portupgrade(1)> is run.
+
+Updating or reinstalling the port will cause the ports system to force
+all of the marked ports to be installed, using the standard dependency
+resolution mechanisms of the ports.
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<-n>
+
+Dry-run. Causes B<%%PORTNAME%%> not to update the configuration file,
+but instead to display what the final result would have been.
+
+=item B<-f> F<config>
+
+Read and modify an alternate configuration file. F<config> should be
+the full path to the alternate file. I<Note:> when updating the
+F<ports-management/%%PORTNAME%%> port, set C<CFGFILE> or
+C<WANTEDPORTSCFG> in the L<make(1)> environment to achieve the same
+effect.
+
+=item B<-a> F<portname>
+
+Add dependencies. Find all matching package names or port paths from
+the F<INDEX> file, and prompt the user whether to add any that are not
+already listed as dependencies in the configuration file.
+
+=item B<-d> F<portname>
+
+Delete dependencies. Find all matching package names or port paths
+from the F<INDEX> file, and prompt the user whether to delete any that
+are currently listed as dependencies in the configuration file.
+
+=back
+
+The add B<-a> and delete B<-d> options are processed in the order
+given on the command line, so a later option can override an earlier
+one. The F<portname> argument will match any substring of the port or
+package name: care should be taken that you don't accidentally match
+unintended items. You can anchor searches to start or end of item
+using C<^> or C<$>.
+
+=head1 FILES
+
+=over 16
+
+=item F</var/db/%%PORTNAME%%.conf>
+
+The default configuration file used by B<%%PORTNAME%%>. This is a
+F<makefile> snippet, that will be included by
+F<ports-mgmt/%%PORTNAME%%/Makefile>. A skeleton version will be
+created by B<%%PORTNAME%%> if it doesn't exist. The B<%%PORTNAME%%>
+script exists to add or remove C<RUN_DEPENDS> entries and update the
+C<PORTREVISION> setting.
+
+=back
+
+=head1 ENVIRONMENT
+
+The following environment variables affect the operation of
+B<%%PORTNAME%%>. C<PORTSDIR>, C<INDEXFILE> and C<WANTEDPORTSCFG>
+override the system default settings: normally they will not need to
+be set. C<USER> and C<LOGNAME> are standard settings, from
+L<login(1)>.
+
+=over 16
+
+=item C<PORTSDIR>
+
+As in L<ports(7)>, the location where the ports tree is installed.
+Default F</usr/ports>
+
+=item C<INDEXFILE>
+
+As in L<ports(7)>, overrides the automatic logic to determine the name
+of the index file. Default F<INDEX-I<N>> where I<N> is the OS major
+version number.
+
+=item C<USER>
+
+=item C<LOGNAME>
+
+The name of the user running the script. If neither are set, uses
+C<an unknown user>.
+
+=item C<WANTEDPORTSCFG>
+
+Override the default location of the configuration file. Using the
+B<-f config> command line option superceeds this setting. Default
+F</var/db/%%PORTNAME%%.conf>
+
+=back
+
+=head1 SEE ALSO
+
+L<ports(7)>, L<pkg_delete(1)>, L<pkg_cutleaves(1)>, L<portmaster(8)>,
+L<portupgrade(1)>
+
+=cut
diff --git a/ports-mgmt/wanted-ports/pkg-descr b/ports-mgmt/wanted-ports/pkg-descr
new file mode 100644
index 000000000000..32fa089f345b
--- /dev/null
+++ b/ports-mgmt/wanted-ports/pkg-descr
@@ -0,0 +1,5 @@
+A special meta-port to do nothing but register dependencies on those
+ports you specifically want to have installed. The normal dependency
+checking in programs like pkg_delete(1) will prevent easy deletion of
+ports that other ports depend on. Keeps egg off face. Protects feet
+from being shot.