From 6a7fd0e49cb8dbd025771feb95c2dcafb408c1b8 Mon Sep 17 00:00:00 2001
From: Charles Plessy <plessy@debian.org>
Date: Sat, 2 Mar 2013 22:48:04 +0900
Subject: [PATCH] Document dpkg triggers.

Closes: #582109.
---
 policy.sgml | 275 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 268 insertions(+), 7 deletions(-)

diff --git a/policy.sgml b/policy.sgml
index a41bc1f..c6e1a9e 100644
--- a/policy.sgml
+++ b/policy.sgml
@@ -900,9 +900,12 @@ zope.
 	the package.  Other control information files include
 	the <qref id="sharedlibs-symbols"><file>symbols</file> file</qref>
 	or <qref id="sharedlibs-shlibdeps"><file>shlibs</file> file</qref>
-	used to store shared library dependency information and
+	used to store shared library dependency information,
 	the <file>conffiles</file> file that lists the package's
-	configuration files (described in <ref id="config-files">).
+	configuration files (described in <ref id="config-files">), and the
+	file <file>triggers</file> that lists the
+	<qref id="dpkg-triggers">triggers</qref> that the package is interested
+	in.
       </p>
 
       <p>
@@ -3958,6 +3961,51 @@ Checksums-Sha256:
 	</p>
 
 	<p>
+	  Dpkg defines the folowing states for the packages.
+	  <taglist>
+	    <tag>Not-Installed</tag>
+	    <item>
+	      The package is not installed on the system.
+	    </item>
+
+	    <tag>Config-Files</tag>
+	    <item>
+	      Only the configuration files of the package exist on the system.
+	    </item>
+
+	    <tag>Half-Installed</tag>
+	    <item>
+	      The installation of the package has been started, but not
+	      completed for some reason.
+	    </item>
+
+	    <tag>Unpacked</tag>
+	    <item>
+	      The package is unpacked, but not configured.
+	    </item>
+
+	    <tag>Half-Configured</tag>
+	    <item>
+	      The package is unpacked and configuration has been started, but
+	      not yet completed for some reason.
+	    </item>
+
+	    <tag>Triggers-Awaited</tag>
+	    <item>
+	      The package awaits trigger processing by another package.
+	    </item>
+
+	    <tag>Triggers-Pending</tag>
+	    <item>
+	      The package has been triggered.
+	    </item>
+
+	    <tag>Installed</tag>
+	    <item>
+	      The package is unpacked and configured.
+	    </item>
+	  </taglist>
+	<p>
 	  Broadly speaking the <prgn>preinst</prgn> is called before
 	  (a particular version of) a package is unpacked, and the
 	  <prgn>postinst</prgn> afterwards; the <prgn>prerm</prgn>
@@ -4141,6 +4189,26 @@ Checksums-Sha256:
 	      from the package dependencies are not available is often the
 	      best approach.
 	    </item>
+
+	    <tag><var>postinst</var> <tt>triggered</tt>
+	      "<var>trigger-name</var> <var>trigger-name</var> ..."</tag>
+	    <item>
+	      Process one or more <qref id="dpkg-triggers">triggers</qref> that
+	      this package is <em>interested</em> in.  In case of failure the
+	      package's state becomes <tt>config-failed</tt>, so that the trigger
+	      processing will not be attempted again until explicitly
+	      requested<footnote>
+		When an interested package has more than one trigger and wants
+		to process them differently, the list of triggers can be can be
+		examined in a shell script like this:
+		<example>
+case " $2 " in
+*" trigger-name-a "*)  process-trigger-a ;;
+esac</example>
+		Generally each trigger name should be tested for separately, as
+		the postinst will often be called for several triggers at once.
+	      </footnote>.
+	    </item>
 	  </taglist>
 	</p>
 
@@ -4694,6 +4762,198 @@ fi
 
 	</p>
       </sect>
+
+      <sect id="dpkg-triggers">
+	<heading>Dpkg triggers</heading>
+
+	<p>
+	  A <prgn>dpkg</prgn> trigger is a facility that allows events caused
+	  by the installation, upgrade or removal of one package, and of
+	  <em>interest</em> to another package, to be recorded and
+	  aggregated, and processed later by the interested package.  This
+	  feature simplifies various registration and system-update tasks and
+	  reduces duplication of processing.
+	<p>
+
+	<p>
+	  Each trigger is named, and at any time zero or more packages may be
+	  <em>interested</em> in it.  Packages declare their interest by
+	  including a <file>triggers</file> file in their control archive.
+          This file contains one directive per line. Leading and trailing
+	  whitespace, everything after the first hash character (<tt>#</tt>)
+	  on any line, and empty lines are ignored.  The following directives
+	  are supported.
+	  <taglist>
+	    <tag><tt>interest</tt> <var>trigger-name</var></tag>
+	    <tag><tt>interest-noawait</tt> <var>trigger-name</var></tag>
+	    <item>
+	      Specifies that the package is interested in the named trigger.
+	      The <em>noawait</em> variant does not put the triggering packages
+	      in "Triggers-Awaited" state, and does not add the
+	      interested package to the <tt>Triggers-Awaited</tt> list of the
+	      triggering package.
+	    </item>
+
+	    <tag><tt>activate</tt> <var>trigger-name</var></tag>
+	    <tag><tt>activate-noawait</tt> <var>trigger-name</var></tag>
+	    <item>
+	      Specifies that changes to this package's state will activate the
+	      named trigger.  The <em>noawait</em> variant does not put the
+	      triggering packages in "Triggers-Awaited" state, and does
+	      not add the interested package to the <tt>Triggers-Awaited</tt>
+	      list of the triggering package.
+	    </item>
+	  </taglist>
+	</p>
+
+	<p>
+	  There currently two kinds of triggers.
+	<taglist>
+	  <tag>Explicit triggers</tag>
+	  <item>
+	    These can be activated by any program by running
+	    <prgn>dpkg-trigger</prgn> (at any time, but ideally from a
+	    maintainer script.
+	  </item>
+
+	  <tag>File triggers</tag>
+	  <item>
+	    These are activated automatically by <prgn>dpkg</prgn> when a
+	    matching file or directory is created, upgraded or deleted as
+	    part of a package's unpacking or removal.  They may also be
+	    explicitly activated by running <prgn>dpkg-trigger</prgn>.
+	    Trigger activation due to a particular file should not generally
+	    modify that file again.  If there are directory symlinks which
+	    result in packages referring to files by different names, then to
+	    be sure of activation all of the paths which might be included in
+	    packages should be listed.  The path specified by the interested
+	    package is matched against the path included in the triggering
+	    package, not against the true name of the file as installed.
+	    Only textually identical filenames (or filenames where the
+	    interest is a directory prefix of the installed file) are
+	    guaranteed to match.
+	  </item>
+	</taglist>
+	</p>
+
+	<p>
+	  Trigger names are composed of US-ASCII characters excluding
+	  control characters and space (i.e., characters in the range 33-126,
+	  inclusive).  The names of file triggers is an absolute path to
+	  a file or a directory.  The names of Explicit triggers have the same
+	  syntax as package names, but should not by identical to a package
+	  name<footnote>
+	    When choosing an explicit trigger name it is usually good to
+	    include a relevant package name or some other useful identifier
+	    to help make the trigger name unique.  On the other hand,
+	    explicit triggers should generally not be renamed just because
+	    the interested or triggering packages' names change.
+	  </footnote>.
+	</p>
+
+	<p>
+	  When a configured package activates a trigger, its state becomes
+	  "Triggers-Awaited" instead of "Installed".  For this
+	  package, <prgn>dpkg</prgn> keeps a list, <tt>Triggers-Awaited</tt>
+	  of interested packages whose trigger processing is awaited.  Every
+	  package in this list either has a nonempty list of pending triggers,
+	  or is in <tt>config-failed</tt> or worse.  When a package in the
+	  state "Triggers-Pending" becomes "Installed",
+	  "Config-Files" or "Not-Installed", its entry is
+	  removed from the <tt>Triggers-Awaited</tt> lists of other packages.
+	</p>
+
+	<p>
+	  When a trigger is activated, the state of every interested package
+	  becomes "Triggers-Pending".  For each package,
+	  <prgn>dpkg</prgn> keeps a list, <tt>Triggers-Pending</tt>, of
+	  triggers whose processing is pending.  Repeated activation of the
+	  same trigger has no additional effect.  In general a trigger will
+	  not be processed immediately when it is activated; processing is
+	  deferred until it is convenient.
+	</p>
+
+	<p>
+	  Packages in the state "Triggers-Pending" that activate a
+	  trigger become "Triggers-Awaited".  If a package has nonempty
+	  <tt>Triggers-Awaited</tt> and <tt>Triggers-Pending</tt> lists, then
+	  its state is "Triggers-Awaited".  Nevertheless efforts will
+	  still be made to process its triggers so as to empty the
+	  <tt>Triggers-Pending</tt> list.  When a package in the state
+	  "Triggers-Awaited" no longer awaits any packages, it becomes 
+	  "Installed" or "Triggers-Pending".  
+	</p>
+
+	<p>
+	  Packages should be written so that they do not break just because
+	  their pending triggers have not yet been run.  It is allowed for the
+	  functionality relating to the unprocessed trigger to fail (ie, the
+	  package which is awaiting the trigger processing may be broken), but
+	  the remainder of the interested package must work normally.
+	</p>
+
+	<p>
+	  Packages in "Config-Files" or "Not-Installed" do not
+	  await triggers.
+	</p>
+
+	<p>
+	  Triggers are processed by running the intersted packages'
+	  <tt>postinst</tt> script with the <tt>triggered</tt> parameter (see
+	  <ref id="mscriptsinstact">).  This will be attempted for each
+	  relevant package at the end of each <prgn>dpkg</prgn> run; so,
+	  normally, in the same dpkg run as the event which made the package go
+	  to <prgn>triggers-pending</prgn>.
+	</p>
+
+	<p>
+	  Packages in <tt>config-failed</tt> or worse are never considered to
+	  have lists of pending triggers.  A package whose postinst is being
+	  run can however acquire pending triggers during that run (ie, a
+	  package can trigger itself).
+	</p>
+
+	<p>
+	  This means that if a triggering package <var>T</var> awaits trigger
+	  processing by an interested package <var>I</var>, and <var>I</var>
+	  goes to <tt>config-failed</tt> or worse (eg, during unpack for
+	  upgrade), then when <var>I</var> is reconfigured (goes to
+	  "Installed") or removed, <var>T</var> will no longer await
+	  processing by <var>I</var>, so that <var>T</var> may automatically go
+	  from "Triggers-Awaited" to "Installed".
+	</p>
+
+	<p>
+	  Or to put it another way, triggered actions are considered irrelevant
+	  if the interested package <var>I</var> is not configured.  When
+	  <var>I</var>'s postinst is called with <tt>configure</tt>, it must do
+	  whatever actions are necessary to deal with any trigger activations
+	  which might have occurred while it was not configured, just as if the
+	  package was being configured for the first time.
+	</p>
+
+	<p>
+	  A package is only guaranteed to become notified of a trigger
+	  activation if it is continuously interested in the trigger, and never
+	  in <tt>config-failed</tt> or worse, during the period from when the
+	  trigger is activated until dpkg runs the package postinst (either due
+	  to <tt>--configure --pending</tt>, or at the end of the relevant run,
+	  as described above).  Subsequent to activation and before
+	  notification, the interested package will not be considered in state
+	  "Installed", so long as the package remains interested, and
+	  the triggering package will not be considered "Installed".
+	</p>
+
+	<p>
+	  If the package is not in state "Installed",
+	  "Triggers-Pending" or "Triggers-Awaited" then pending
+	  triggers are not accumulated.  However, if such a package (between
+	  "Half-Installed" and <tt>config-failed</tt> inclusive)	
+	  declares some trigger interests then the triggering packages will
+	  await their configuration (which implies completion of any necessary
+	  trigger processing) or removal.
+	</p>
+      </sect>
     </chapt>
 
 
@@ -4716,8 +4976,8 @@ fi
           dependencies on other packages, the package names listed may
           also include lists of alternative package names, separated
           by vertical bar (pipe) symbols <tt>|</tt>.  In such a case,
-          if any one of the alternative packages is installed, that
-          part of the dependency is considered to be satisfied.
+          if any one of the alternative packages is installed or has pending
+	  triggers, that part of the dependency is considered to be satisfied.
 	</p>
 
 	<p>
@@ -4978,7 +5238,8 @@ Build-Depends: foo [linux-any], bar [any-i386], baz [!linux-any]
 		<prgn>postinst</prgn> or <prgn>prerm</prgn> scripts
 		require the depended-on package to be unpacked or
 		configured in order to run.  In the case of <tt>postinst
-		configure</tt>, the depended-on packages will be unpacked
+		configure</tt> and <tt>postinst triggers</tt>,
+	        the depended-on packages will be unpacked
 		and configured first.  (If both packages are involved in a
 		dependency loop, this might not work as expected; see the
 		explanation a few paragraphs back.)  In the case
@@ -8097,8 +8358,8 @@ Reloading <var>description</var> configuration...done.
 	<p>
 	  The <package>mime-support</package> package provides the
 	  <prgn>update-mime</prgn> program, which integrates these
-	  registrations in the <file>/etc/mailcap</file> file, using dpkg
-	  triggers<footnote>
+	  registrations in the <file>/etc/mailcap</file> file, using
+	  <qref id="dpkg-triggers">dpkg triggers</qref><footnote>
 	    Creating, modifying or removing a file in
 	    <file>/usr/lib/mime/packages/</file> using maintainer scripts will
 	    not activate the trigger.  In that case, it can be done by calling
-- 
1.8.2.rc0

