[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[PATCH] add dpkg-conffile, based upon http://wiki.debian.org/DpkgConffileHandling



As discussed on debian-devel, different versions of these conffile handling
shell functions on the wiki are being copied into maintainer scripts
repeatedly, and adding a program to dpkg that handles things is a more
maintainable approach.

Note that in two places, parameters are required by dpkg-conffile that are
not currently used. I did this to future-proof calls to the program.
Perhaps in the future it will want to know the new conffile name in
`prep_mv`, or the package name in `mv`.

There is no copyright statement on the code in the wiki. (Which is being
copied into many packages .. without a copyright statment!) I looked at
the edit histories of both
http://wiki.debian.org/DpkgConffileHandling and
http://www.dpkg.org/dpkg/ConffileHandling, and it was originally written
by Scott, and was then modified by Guillem. This patch assumes that both
of them are willing to license it under GPL2+.

Signed-off-by: Joey Hess <joeyh@debian.org>
---
 debian/changelog         |    3 +
 debian/copyright         |    3 +-
 debian/dpkg.install      |    3 +
 man/Makefile.am          |    1 +
 man/dpkg-conffile.8      |  132 ++++++++++++++++++++++++++++++++++++++++++++++
 scripts/Makefile.am      |    2 +
 scripts/dpkg-conffile.sh |   94 ++++++++++++++++++++++++++++++++
 7 files changed, 237 insertions(+), 1 deletions(-)
 create mode 100644 man/dpkg-conffile.8
 create mode 100755 scripts/dpkg-conffile.sh

diff --git a/debian/changelog b/debian/changelog
index 1eb6246..86c51e1 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -22,6 +22,9 @@ dpkg (1.14.17) UNRELEASED; urgency=low
   * German (Helge Kreutzmann).
   * Swedish (Peter Karlsson).
 
+  [ Joey Hess ]
+  * Add dpkg-conffile, based upon http://wiki.debian.org/DpkgConffileHandling
+
  -- Guillem Jover <guillem@debian.org>  Mon, 21 Jan 2008 10:11:55 +0200
 
 dpkg (1.14.16.5) unstable; urgency=low
diff --git a/debian/copyright b/debian/copyright
index 8ea1e6d..ac15365 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -1,11 +1,12 @@
 This is Debian's package maintenance system.
 
+Copyright © 2007 Guillem Jover <guillem@debian.org>
 Copyright © 2006-2007 Frank Lichtenheld <djpig@debian.org>
 Copyright © 2004-2005 Scott James Remnant <scott@netsplit.com>
 Copyright © 2004-2005 Canonical Ltd.
 Copyright © 1999-2002 Wichert Akkerman <wakkerma@debian.org>
 Copyright © 1999-2001 Marcus Brinkmann <brinkmd@debian.org>
-Copyright © 2001 Joey Hess <joeyh@debian.org>
+Copyright © 2001,2008 Joey Hess <joeyh@debian.org>
 Copyright © 1994-1999 Ian Jackson <ian@chiark.greenend.org.uk>
 Copyright © 1999 Richard Kettlewell <rjk@sfere.greenend.org.uk>
 Copyright © 1999 Ben Collins <bcollins@debian.org>
diff --git a/debian/dpkg.install b/debian/dpkg.install
index 2f54618..bd33273 100644
--- a/debian/dpkg.install
+++ b/debian/dpkg.install
@@ -7,6 +7,7 @@ usr/bin/dpkg
 usr/bin/dpkg-deb
 usr/bin/dpkg-query
 usr/bin/dpkg-split
+usr/bin/dpkg-conffile
 usr/lib/dpkg/mksplit
 usr/sbin
 usr/share/dpkg
@@ -21,6 +22,8 @@ usr/share/man/*/*/dpkg-query.1
 usr/share/man/*/dpkg-query.1
 usr/share/man/*/*/dpkg-split.1
 usr/share/man/*/dpkg-split.1
+usr/share/man/*/*/dpkg-conffile.8
+usr/share/man/*/dpkg-conffile.8
 usr/share/man/*/*/dpkg-statoverride.8
 usr/share/man/*/dpkg-statoverride.8
 usr/share/man/*/*/dpkg.cfg.5
diff --git a/man/Makefile.am b/man/Makefile.am
index 42b17af..c975329 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -78,6 +78,7 @@ dist_man_MANS = \
 	dpkg-architecture.1 \
 	dpkg-buildpackage.1 \
 	dpkg-checkbuilddeps.1 \
+	dpkg-conffile.8 \
 	dpkg-deb.1 \
 	dpkg-distaddfile.1 \
 	dpkg-divert.8 \
diff --git a/man/dpkg-conffile.8 b/man/dpkg-conffile.8
new file mode 100644
index 0000000..6bd8bf6
--- /dev/null
+++ b/man/dpkg-conffile.8
@@ -0,0 +1,132 @@
+.\" This is an -*- nroff -*- source file.
+.\" dpkg-conffile and this manpage are Copyright 2008 by Joey Hess.
+.\"
+.\" This is free software; see the GNU General Public Licence version 2
+.\" or later for copying conditions.  There is NO warranty.
+.TH dpkg\-conffile 8 "2008-1-25" "Debian Project" "dpkg utilities"
+.SH NAME
+dpkg\-conffile \- graceful deletion or moving of conffiles
+.
+.SH SYNOPSIS
+.B dpkg\-conffile
+.I rm <package> <conffile>
+.P
+.B dpkg\-conffile
+.I prep_mv <package> <oldconffile> <newconffile>
+.P
+.B dpkg\-conffile
+.I mv <package> <oldconffile> <newconffile>
+.
+.SH DESCRIPTION
+When upgrading a package, dpkg will not automatically remove a conffile (a
+configuration filefor which dpkg should preserve user changes) if it is not
+present in the newer version. There are two principal reasons for this; the
+first is that the conffile could've been dropped by accident and the next
+version could restore it, users wouldn't want their changes thrown away.
+The second is to allow packages to transition files from a dpkg-maintained
+conffile to a file maintained by the package's maintainer scripts, usually
+with a tool like debconf or ucf.
+.P
+This means that if a package is intended to rename or remove a conffile,
+it must explicitly do do.
+.B dpkg\-conffile
+helps with graceful deletion and moving of conffiles.
+.
+.SH "REMOVING A CONFFILE"
+If a conffile is completely removed, it should be removed from disk,
+unless the user has modified it. If there are local modifications, they
+should be preserved. This can be accomplished by making the package's
+preinst script call
+.B dpkg\-conffile rm <conffile>
+.P
+Generally the preinst should check to only do so on install or upgrade,
+and only when upgrading from a version of the package that contained the
+conffile.
+.P
+Internally,
+.B dpkg\-conffile rm
+will first check to make sure the conffile actually exists on the disk, if the
+user has removed it already there's no point carrying on as everything's fine.
+It then checks to see whether the user has modified it from the package's
+version or not. It obtains the current md5sum, and compares that to
+one taken from the dpkg database. This is why
+.B dpkg\-conffile rm
+must be called from the preinst, as the old md5sum information is still
+available in the dpkg database at that point.
+.P
+If the user has not modified the conffile, it is simply removes from the disk.
+If they have, it is moved to a filename that can be easily identified by the
+user and ignored bytools such as run-parts.
+.
+.SH "MOVING A CONFFILE"
+If a conffile is moved from one location to another, you need to make sure you
+move across any changes the user has made. This may seem a simple change to the
+preinst script at first, however that will result in the user being prompted by
+dpkg to approve the conffile edits they have made. If you change the conffile
+format, that may be desirable, however often you can do that kind of checking
+yourself.
+.P
+.B dpkg\-conffile
+allows moving a conffile without triggering the dpkg question. To move
+a conffile, there are two steps. The preinst of the package, on install or
+upgrade from the version that contained the conffile in the old location,
+should call
+.B dpkg\-conffile prep_mv <package> <oldconffile> <newconffile>
+.P
+Much like removal, this first checks to make sure the old conffile
+exists on the disk and whether the user has changed it or not. If the user
+has not changed it, the old conffile is simply removed from disk. If the
+user has changed the conffile, it is left in place; its rename will be
+handled by the postinst script.
+.P
+The postinst of the package should call
+.B dpkg\-conffile mv <package> <oldconffile> <newconffile>
+.P
+This checks to see if the old conffile still exists on disk. If so,
+it must contain changes that should be preserved. The new conffile (as
+unpacked by dpkg) is moved to a .dpkg-new file, and the old conffile is
+moved into its place.
+.
+.SH EXAMPLES
+Removing a conffile, in a preinst script:
+
+  case "$1" in
+  install|upgrade)
+      if dpkg --compare-versions "$2" le "$LASTVERSION"; then
+          dpkg-conffile rm mypackage /etc/pkg/conf
+      fi
+  esac
+
+Preparing to rename a conffile, in a preinst script:
+
+  case "$1" in
+  install|upgrade)
+      if dpkg --compare-versions "$2" le "$LASTVERSION"; then
+          dpkg-conffile prep_mv mypackage /etc/pkg.conf /etc/pkg/conf
+      fi
+  esac
+
+Renaming the conffile, in a postinst script:
+
+  case "$1" in
+  configure)
+      if dpkg --compare-versions "$2" le "$LASTVERSION"; then
+          dpkg-conffile mv mypackage /etc/pkg_conf /etc/pkg/conf
+      fi
+  esac
+.P
+In the above examples, replace $LASTVERSION with the last version
+of the package to contain the old conffile.
+.
+.SH BUGS
+Arguably the need for this program at all is a bug in dpkg. If dpkg is
+ever changed to somehow handle conffile deletion and renaming on its own,
+this program could turn into a deprecated no-op.
+.SH SEE ALSO
+.BR dpkg (1),
+.
+.SH AUTHOR
+Copyright 2008 Joey Hess
+.sp
+This is free software; see the GNU General Public Licence version 2 or
+later for copying conditions. There is NO WARRANTY.
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index e27f294..8c24971 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -7,6 +7,7 @@ bin_SCRIPTS = \
 	dpkg-architecture \
 	dpkg-buildpackage \
 	dpkg-checkbuilddeps \
+	dpkg-conffile \
 	dpkg-distaddfile \
 	dpkg-genchanges \
 	dpkg-gencontrol \
@@ -34,6 +35,7 @@ EXTRA_DIST = \
 	dpkg-architecture.pl \
 	dpkg-buildpackage.pl \
 	dpkg-checkbuilddeps.pl \
+	dpkg-conffile.sh \
 	dpkg-distaddfile.pl \
 	dpkg-genchanges.pl \
 	dpkg-gencontrol.pl \
diff --git a/scripts/dpkg-conffile.sh b/scripts/dpkg-conffile.sh
new file mode 100755
index 0000000..9a1ce2d
--- /dev/null
+++ b/scripts/dpkg-conffile.sh
@@ -0,0 +1,94 @@
+#!/bin/sh
+# Copyright (C) 2005 Scott James Remnant (original implementation on www.dpkg.org)
+# Copyright (C) 2007 Guillem Jover (modifications on wiki.debian.org)
+# Copyright (C) 2008 Joey Hess <joeyh@debian.org> (this script)
+# 
+# This is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2, or (at your option) any
+# later version.
+# 
+# This is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the file
+# /usr/share/common-licenses/GPL for more details."
+
+set -e
+
+# Remove a no-longer used conffile
+rm_conffile() {
+	PKGNAME="$1"
+	CONFFILE="$2"
+	if [ -e "$CONFFILE" ]; then
+		md5sum="`md5sum \"$CONFFILE\" | sed -e \"s/ .*//\"`"
+		old_md5sum="`dpkg-query -W -f='${Conffiles}' $PKGNAME | sed -n -e \"\\\\' $CONFFILE'{s/ obsolete$//;s/.* //p}\"`"
+		if [ "$md5sum" != "$old_md5sum" ]; then
+			echo "Obsolete conffile $CONFFILE has been modified by you."
+			echo "Saving as $CONFFILE.dpkg-bak ..."
+			mv -f "$CONFFILE" "$CONFFILE".dpkg-bak
+		else
+			echo "Removing obsolete conffile $CONFFILE ..."
+			rm -f "$CONFFILE"
+		fi
+	fi
+}
+
+# Prepare to move a conffile without triggering a dpkg question
+prep_mv_conffile() {
+	PKGNAME="$1"
+	OLDCONFFILE="$2"
+	NEWCONFFILE="$3" # currently not used
+	if [ -e "$OLDCONFFILE" ]; then
+		md5sum="`md5sum \"$OLDCONFFILE\" | sed -e \"s/ .*//\"`"
+		old_md5sum="`dpkg-query -W -f='${Conffiles}' $PKGNAME | sed -n -e \"\\\\' $OLDCONFFILE'{s/ obsolete$//;s/.* //p}\"`"
+		if [ "$md5sum" = "$old_md5sum" ]; then
+			rm -f "$OLDCONFFILE"
+		fi
+	fi
+}
+
+# Move a conffile without triggering a dpkg question
+mv_conffile() {
+	PKGNAME="$1" # currently not used
+	OLDCONFFILE="$2"
+	NEWCONFFILE="$3"
+	if [ -e "$OLDCONFFILE" ]; then
+		echo "Preserving user changes to $NEWCONFFILE ..."
+		mv -f "$NEWCONFFILE" "$NEWCONFFILE".dpkg-new
+		mv -f "$OLDCONFFILE" "$NEWCONFFILE"
+	fi
+}
+
+usage() {
+	cat <<EOF >&2
+Usage:
+	dpkg-conffile rm <package> <conffile>
+	dpkg-conffile prep_mv <package> <oldconffile> <newconffile>
+	dpkg-conffile mv package <package> <oldconffile> <newconffile>
+EOF
+	exit 1
+}
+
+case "$1" in
+rm)
+	if [ -z "$2" ] || [ -z "$3" ]; then
+		usage
+	fi
+	rm_conffile "$2" "$3"
+;;
+prep_mv)
+	if [ -z "$2" ] || [ -z "$3" ] || [ -z "$4" ]; then
+		usage
+	fi
+	prep_mv_conffile "$2" "$3" "$4"
+;;
+mv)
+	if [ -z "$2" ] || [ -z "$3" ] || [ -z "$4" ]; then
+		usage
+	fi
+	mv_conffile "$2" "$3" "$4"
+;;
+*)
+	usage
+;;
+esac
-- 
1.5.3.8


-- 
see shy jo

Attachment: signature.asc
Description: Digital signature


Reply to: