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

Maintainer script informative call graph



Hi,

        Inspired by Marga's excellent document claryfying the maintainer
 scripts at http://women.debian.org/wiki/English/MaintainerScripts, and
 also enthused about Emacs org-mode's ability to create a simple plain
 ascii input file and leveragte things like graphviz and ditaa, I have
 some up with a slightly different take on clarification of the
 maintainer script call sequence.

        Please have a look-see at:
 http://people.debian.org/~srivasta/MaintainerScripts.html

        I'm attaching the source below. I think I am going to continue
 to enhance it, but I ran out of steam tonight. I am proposing adding
 this to the policy package, once it gets polished a bit more, and
 checked for correctness.

        manoj

#+STARTUP: hidestars showall
#+TITLE:     Maintainer scripts
#+AUTHOR:    Manoj Srivastava
#+EMAIL:     srivasta@debian.org
#+DATE:      <2009-10-16 Fri>
#+LANGUAGE:  en
#+OPTIONS:   H:0 num:nil toc:nil \n:nil @:t ::t |:t ^:t -:t f:t *:t TeX:t LaTeX:t skip:nil d:nil tags:not-in-toc
#+INFOJS_OPT: view:info toc:1 path:org-info.js tdepth:2 ftoc:t
#+LINK_UP:   http://www.golden-gryphon.com/blog/manoj/
#+LINK_HOME: http://www.golden-gryphon.com/

* Introduction

This document is meant to clarify the interaction between maintainer
scripts and the state changes for a package when a user interacts with
the packaging system. This was inspired by Margarita Manterola's
[[http://women.debian.org/wiki/English/MaintainerScripts][excellent treatise]] on the subject, but has a slightly different slant:
this document is more concerned about user actions, and the resulting
state transitions of a package's state on a Debian installation,
rather than a maintainer script centric treatment of the process.

* Common Use Cases

To start with, we consider the most common use cases related to a
user's interaction with the packaging system:

- *Install*: Starting with a package which is not installed on the
  system, the user asks the packaging system to install a package. If
  all goes well, the end result is that the package is installed on
  the system.
- *Remove*: Starting with a package that is currently installed on the
  system, the user asks the packaging system to remove it. If all goes
  well, only configuration files shall  remain on the system at the
  end.
- *Purge*: Starting with the state when only configuration files
  remain on the system, the user asks the package system to remove
  even the configuration files. If all goes well, the package will be
  fully un-installed.
- Starting with a package installed on the system, the user asks the
  system to fully uninstall the package. This is not an independent
  use case, it is just the /Remove/ followed by a /Purge/, and we do
  not consider it separately below.
- *Reinstall*: Starting with just the configuration files remaining on
  the system, the user asks the packaging system to install the
  package again (potentially newer version of the package).
- *Upgrade*: Starting with a version of the package installed on the
  system, the user asks the packaging system to install a newer
  version of the package. (A variation is the case where the old and
  the new version of the package are the same, but it follows the same
  process).

This is not as complex a scenario as one might be afraid of; there are
only three states a package may be in when the user initiates the
action (/Not Installed/, /Configuration files only/, and
/Installed/). These states are also successful terminal state, and
there are only three failure terminal states (/Half Installed/,
/Failed config/, and /Unpacked/).

In the treatment below, we do not discuss details of failure modes, we
just detail what happens when a maintainer script encounters an
error. Also, we do not go into early sanity checks, for example,
complications like the absence of a dependency when trying to
(re)install a package, or the presence of a conflicting package. We
also do not deal with the cases where the package we are trying to
remove has other installed packages that depend on it; in all these
cases the result is to abort the operation early, and let the user
handle further action.

** Install a previously unknown package

This is the case where a package is not currently installed on the
system, and the user asks the packaging system to install version
/V1/.

*** State diagram

#+begin_ditaa InstallState.png -r -o -s 0.8
+--------------------------------------------------------+
|       +------+                                         |
|       |      |                                         |
|       |      v                                         |
|   /---*------*----+             /------------------+   |
|   | Not Installed |             |   Half Installed |   |
|   |   cGRE        *------------>*      cRED        |   |
|   |               |             +------------------/   |
|   +---*------*----/                                    |
|       |      |                                         |
|       |      +--------------------------+              |
|       |                                 |              |
|       v                                 v              |
|   /---*-----------+             /-------*----------+   |
|   |   Installed   |             |    Failed Config |   |
|   |    cGRE       |             |    cRED          |   |
|   +---------------/             +------------------/   |
|                      cCCC                              |
+--------------------------------------------------------+
#+end_ditaa

*** Activity diagram

The green ellipses are the start states a package may be in, the Blue
labels represent user actions. The maintainer scripts are represented
by decision boxes, since usually how the process flows depends on
whether the maintainer scripts succeeds or fails. Terminal states are
/octagons/. The colors /green/ and /red/ denote success and failure,
respectively.

#+begin_dot InstallActivity.png -Tpng
digraph MaintainerScripts {
  bgcolor=gray3;
  center="true";
  charset="iso-8859-1";
  compound=true;
  concentrate=true;
  pack=true;
  outputorder="nodesfirst";

  /* Starting states */
  "Not-Installed"     [shape=ellipse,fontsize=12,fontname="Times-Bold",style=filled,fillcolor="#99FF99" ];
  /* Maybe Stating or Terminal states */
  "Installed-V1"      [shape=ellipse,fontsize=12,fontname="Times-Bold",style=filled,fillcolor="#99FF99" ];


  /* install V1*/
  "V1->\npreinst install"      [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V1->\npostrm abort-install" [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V1->\npostinst configure"   [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];

  /* Failure terminal states */
  "Half-Installed-V1" [shape=octagon,fontsize=12,fontname="Times-Bold",style=filled,fillcolor="#FFCCFF" ];
  "Failed-Config-V1"  [shape=octagon,fontsize=12,fontname="Times-Bold",style=filled,fillcolor="#FFCCFF" ];


  subgraph installation
  {
    "Not-Installed"              -> "V1->\npreinst install"      [fontsize=12,fontname="Times-Bold",label="Install",color="cyan",fontcolor=lightskyblue];
    "V1->\npreinst install"      -> "V1->\npostrm abort-install" [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V1->\npreinst install"      -> "V1->\npostinst configure"   [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V1->\npostrm abort-install" -> "Half-Installed-V1"          [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V1->\npostrm abort-install" -> "Not-Installed"              [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V1->\npostinst configure"   -> "Installed-V1"               [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V1->\npostinst configure"   -> "Failed-Config-V1"           [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
  }

 labelloc="t";
 label="\n";
 fontsize="32";
}

#+end_dot

** Remove and Purge an installed package

This is the reverse operation from above: starting with an installed
package, remove the package, and then purge the configuration files.

*** State diagram

#+begin_ditaa RemoveState.png -r -o -s 0.8
+--------------------------------------------------------+
|                                   /------------------+ |
|                                   |                  | |
|         +------------------------>* Installed        | |
|         |                         |    cRED          | |
|         |                         +------------------/ |
|     /---*-----------+             /------------------+ |
|     |  Installed    |             |   Half Installed | |
|     |   cGRE        |------------>*      cRED        | |
|     +---*------*----/             +------------------/ |
|         |      |                  /------------------+ |
|         |      |                  |                  | |
|         |      +----------------->* Failed Config    | |
|         v                         |     cRED         | |
|     /---*-----------+             +------------------/ |
|     | Config Files  |             /------------------+ |
| +-->*    cGRE       |             |                  | |
| |   |               *------------>*  Not Installed   | |
| +---*               |             |     cGRE         | |
|     +---------------/             +------------------/ |
|                         cCCC                           |
+--------------------------------------------------------+
#+end_ditaa

*** Activity Diagram

#+begin_dot RemoveActivity.png -Tpng
digraph MaintainerScripts {
  bgcolor=gray3;
  center="true";
  charset="iso-8859-1";
  compound=true;
  concentrate=true;
  pack=true;
  outputorder="nodesfirst";

  /* Starting states */
  "Installed-V1"      [shape=ellipse,fontsize=12,fontname="Times-Bold",style=filled,fillcolor="#99FF99" ];

  /* Removal and Purge */
  "V1->\nprerm remove"          [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V1->\npostinst abort-remove" [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V1->\npostrm remove"         [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V1->\npostrm purge"          [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];

  /* Maybe  Terminal states */
  "Not-Installed"     [shape=ellipse,fontsize=12,fontname="Times-Bold",style=filled,fillcolor="#99FF99" ];
  "Config-Files-V1"   [shape=ellipse,fontsize=12,fontname="Times-Bold",style=filled,fillcolor="#99FF00" ];


  /* Failure terminal states */
  "Half-Installed-V1" [shape=octagon,fontsize=12,fontname="Times-Bold",style=filled,fillcolor="#FFCCFF" ];
  "Failed-Config-V1"  [shape=octagon,fontsize=12,fontname="Times-Bold",style=filled,fillcolor="#FFCCFF" ];


  subgraph removal
  {
    "Installed-V1"                -> "V1->\nprerm remove"          [fontsize=12,fontname="Times-Bold",label="Remove",color="cyan",fontcolor=lightskyblue];
    "V1->\nprerm remove"          -> "V1->\npostinst abort-remove" [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V1->\nprerm remove"          -> "V1->\npostrm remove"         [fontsize=9,fontname="Times-Roman",label="OK (del files)",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V1->\npostinst abort-remove" -> "Failed-Config-V1"            [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V1->\npostinst abort-remove" -> "Installed-V1"                [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V1->\npostrm remove"         -> "Half-Installed-V1"           [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V1->\npostrm remove"         -> "Config-Files-V1"             [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
    "Config-Files-V1"             -> "V1->\npostrm purge"          [fontsize=12,fontname="Times-Bold",label="Purge",color="cyan",fontcolor=lightskyblue];
    "V1->\npostrm purge"          -> "Config-Files-V1"             [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V1->\npostrm purge"          -> "Not-Installed"               [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
  }

 labelloc="t";
 label="\n";
 fontsize="32";
}

#+end_dot


** Reinstall a package

This is the case where configuration files from a previous
installation still exist on the system, and the user asks the
packaging system to install a (potentially different) version of the
package.
*** State Diagram

#+begin_ditaa ReinstallState.png -r -o -s 0.8
+--------------------------------------------------------+
|       +------+                                         |
|       |      |                                         |
|       |      v                                         |
|   /---*------*----+             /------------------+   |
|   | Config Files  |             |   Half Installed |   |
|   |   cGRE        *------------>*      cRED        |   |
|   |               |             +------------------/   |
|   +---*------*----/                                    |
|       |      |                                         |
|       |      +--------------------------+              |
|       |                                 |              |
|       v                                 v              |
|   /---*-----------+             /-------*----------+   |
|   |   Installed   |             |    Failed Config |   |
|   |    cGRE       |             |    cRED          |   |
|   +---------------/             +------------------/   |
|                        cCCC                            |
+--------------------------------------------------------+
#+end_ditaa

*** Activity Diagram
#+begin_dot ReinstallActivity.png -Tpng
digraph MaintainerScripts {
  bgcolor=gray3;
  center="true";
  charset="iso-8859-1";
  compound=true;
  concentrate=true;
  pack=true;
  outputorder="nodesfirst";

  /* Starting states */
  "Config-Files-V1"   [shape=ellipse,fontsize=12,fontname="Times-Bold",style=filled,fillcolor="#99FF00" ];

  /* reinstall V2 (config files from V1 present) */
  "V2->\npreinst install V1"      [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V2->\npostrm abort-install V1" [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V2->\npostinst configure V1"   [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];

  /* Successful terminal states */
  "Installed-V2"      [shape=octagon,fontsize=12,fontname="Times-Bold",style=filled,fillcolor="#99FF99" ];
  /* Failure terminal states */
  "Half-Installed-V2" [shape=octagon,fontsize=12,fontname="Times-Bold",style=filled,fillcolor="#FFCCFF" ];
  "Failed-Config-V2"  [shape=octagon,fontsize=12,fontname="Times-Bold",style=filled,fillcolor="#FFCCFF" ];



  subgraph reinstall
  {
    "Config-Files-V1"               -> "V2->\npreinst install V1"       [fontsize=12,fontname="Times-Bold",label="Install V2",color="cyan",fontcolor=lightskyblue];
    "V2->\npreinst install V1"      -> "V2->\npostrm abort-install V1"  [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V2->\npreinst install V1"      -> "V2->\npostinst configure V1"    [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V2->\npostrm abort-install V1" -> "Half-Installed-V2"              [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V2->\npostrm abort-install V1" -> "Config-Files-V1"                [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V2->\npostinst configure V1"   -> "Failed-Config-V2"               [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V2->\npostinst configure V1"   -> "Installed-V2"                   [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
  }


 labelloc="t";
 label="\n";
 fontsize="32";
}

#+end_dot


** Upgrade a package to a new version

This is, perhaps unsurprisingly, the most complex operation of the
ones we have so far considered.
*** State Diagram

#+begin_ditaa UpgradeState.png -r -o -s 0.8
+--------------------------------------------------------+
|                                /-------------------+   |
|      +--+                      | Unpacked V1       |   |
|      |  |  +------------------>*  cRED             |   |
|      |  v  |                   +-------------------/   |
|  /---*--*--*-----+             /-------------------+   |
|  | Installed V1  |             | Half Installed V1 |   |
|  |   cGRE        *------------>*      cRED         |   |
|  |               |             +-------------------/   |
|  +---*------*-*--/             /-------------------+   |
|      |      | |                | Failed Config V1  |   |
|      |      | +--------------->*   cRED            |   |
|      |      |                  +-------------------/   |
|      v      +------------+                             |
|  /---*-----------+       |     /------------------+    |
|  |  Installed V2 |       |     | Failed Config V2 |    |
|  |    cGRE       |       +---->*     cRED         |    |
|  +---------------/             +------------------/    |
|                      cCCC                              |
+--------------------------------------------------------+
#+end_ditaa

*** Activity Diagram

#+begin_dot UpgradeActivity.png -Tpng
digraph MaintainerScripts {
  bgcolor=gray3;
  center="true";
  charset="iso-8859-1";
  compound=true;
  concentrate=true;
  pack=true;
  outputorder="nodesfirst";

  /* Starting states */
  "Installed-V1"      [shape=ellipse,fontsize=12,fontname="Times-Bold",style=filled,fillcolor="#99FF99" ];

  /* Upgrade from V1 to V2 */
  "V1->\nprerm upgrade V2"               [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V2->\nprerm failed-upgrade V1"        [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V1->\npostinst abort-upgrade V2->\na" [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V2->\npreinst upgrade V1"             [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V2->\npostrm abort-upgrade V1->\na"   [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V1->\npostinst abort-upgrade V2->\nb" [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V1->\npostrm upgrade V2"              [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V2->\npostrm failed-upgrade V2"       [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V1->\npreinst abort-upgrade V2"       [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V2->\npostrm abort-upgrade V1->\nb"   [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V2->\npostinst configure V1"          [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];

  "Installed-V2"      [shape=octagon,fontsize=12,fontname="Times-Bold",style=filled,fillcolor="#99FF99" ];
  /* Failure terminal states */
  "Half-Installed-V1" [shape=octagon,fontsize=12,fontname="Times-Bold",style=filled,fillcolor="#FFCCFF" ];
  "Failed-Config-V1"  [shape=octagon,fontsize=12,fontname="Times-Bold",style=filled,fillcolor="#FFCCFF" ];
  "Failed-Config-V2"  [shape=octagon,fontsize=12,fontname="Times-Bold",style=filled,fillcolor="#FFCCFF" ];
  "Unpacked-V1"       [shape=octagon,fontsize=12,fontname="Times-Bold",style=filled,fillcolor="#FFCCFF" ];


  subgraph upgrading
  {
    "Installed-V1"                         -> "V1->\nprerm upgrade V2"               [fontsize=12,fontname="Times-Bold",label="Install V2",color="cyan",fontcolor=lightskyblue];
    "V1->\nprerm upgrade V2"               -> "V2->\nprerm failed-upgrade V1"        [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V1->\nprerm upgrade V2"               -> "V2->\npreinst upgrade V1"             [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V2->\nprerm failed-upgrade V1"        -> "V1->\npostinst abort-upgrade V2->\na" [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V2->\nprerm failed-upgrade V1"        -> "V2->\npreinst upgrade V1"             [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V1->\npostinst abort-upgrade V2->\na" -> "Failed-Config-V1"                     [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V1->\npostinst abort-upgrade V2->\na" -> "Installed-V1"                         [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V2->\npreinst upgrade V1"             -> "V2->\npostrm abort-upgrade V1->\na"   [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V2->\npreinst upgrade V1"             -> "V1->\npostrm upgrade V2"              [fontsize=9,fontname="Times-Roman",label="OK (unpack)",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V2->\npostrm abort-upgrade V1->\na"   -> "Half-Installed-V1"                    [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V2->\npostrm abort-upgrade V1->\na"   -> "V1->\npostinst abort-upgrade V2->\nb" [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V1->\npostinst abort-upgrade V2->\nb" -> "Unpacked-V1"                          [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V1->\npostinst abort-upgrade V2->\nb" -> "Installed-V1"                         [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V1->\npostrm upgrade V2"              -> "V2->\npostrm failed-upgrade V2"       [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V1->\npostrm upgrade V2"              -> "V2->\npostinst configure V1"          [fontsize=9,fontname="Times-Roman",label="OK (del old)",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V2->\npostrm failed-upgrade V2"       -> "V1->\npreinst abort-upgrade V2"       [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V2->\npostrm failed-upgrade V2"       -> "V2->\npostinst configure V1"          [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V1->\npreinst abort-upgrade V2"       -> "Half-Installed-V1"                    [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V1->\npreinst abort-upgrade V2"       -> "V2->\npostrm abort-upgrade V1->\nb"   [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V2->\npostrm abort-upgrade V1->\nb"   -> "Half-Installed-V1"                    [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V2->\npostrm abort-upgrade V1->\nb"   -> "V1->\npostinst abort-upgrade V2->\nb" [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V2->\npostinst configure V1"          -> "Failed-Config-V2"                     [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V2->\npostinst configure V1"          -> "Installed-V2"                         [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
 }

 labelloc="t";
 label="\n";
 fontsize="32";
}

#+end_dot

* Conclusion

In conclusion, here is the full activity diagram encompassing the
above use cases. While this is certainly complex, it is still fairly
easy to see how the use cases flow from the initial states (the green
ellipses), through the decision points (the blue diamonds of the
maintainer script execution), to the octagonal terminal states.

#+begin_dot Activity.png -Tpng
digraph MaintainerScripts {
  bgcolor=gray3;
  center="true";
  charset="iso-8859-1";
  compound=true;
  concentrate=true;
  pack=true;
  outputorder="nodesfirst";

  /* Starting states */
  "Not-Installed"     [shape=ellipse,fontsize=12,fontname="Times-Bold",style=filled,fillcolor="#99FF99" ];
  /* Maybe Stating or Terminal states */
  "Config-Files-V1"   [shape=ellipse,fontsize=12,fontname="Times-Bold",style=filled,fillcolor="#99FF00" ];
  "Installed-V1"      [shape=ellipse,fontsize=12,fontname="Times-Bold",style=filled,fillcolor="#99FF99" ];


  /* install V1*/
  "V1->\npreinst install"      [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V1->\npostrm abort-install" [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V1->\npostinst configure"   [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];

  /* Removal and Purge */
  "V1->\nprerm remove"          [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V1->\npostinst abort-remove" [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V1->\npostrm remove"         [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V1->\npostrm purge"          [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];

  /* reinstall V2 (config files from V1 present) */
  "V2->\npreinst install V1"      [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V2->\npostrm abort-install V1" [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V2->\npostinst configure V1"   [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];

  /* Upgrade from V1 to V2 */
  "V1->\nprerm upgrade V2"               [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V2->\nprerm failed-upgrade V1"        [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V1->\npostinst abort-upgrade V2->\na" [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V2->\npreinst upgrade V1"             [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V2->\npostrm abort-upgrade V1->\na"   [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V1->\npostinst abort-upgrade V2->\nb" [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V1->\npostrm upgrade V2"              [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V2->\npostrm failed-upgrade V2"       [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V1->\npreinst abort-upgrade V2"       [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];
  "V2->\npostrm abort-upgrade V1->\nb"   [shape=diamond,style=filled,fillcolor="#CCFFFF",fontsize=9,fontname="Times-Roman"];

  /* Successful terminal states */
  "Installed-V2"      [shape=octagon,fontsize=12,fontname="Times-Bold",style=filled,fillcolor="#99FF99" ];
  /* Failure terminal states */
  "Half-Installed-V1" [shape=octagon,fontsize=12,fontname="Times-Bold",style=filled,fillcolor="#FFCCFF" ];
  "Half-Installed-V2" [shape=octagon,fontsize=12,fontname="Times-Bold",style=filled,fillcolor="#FFCCFF" ];
  "Failed-Config-V1"  [shape=octagon,fontsize=12,fontname="Times-Bold",style=filled,fillcolor="#FFCCFF" ];
  "Failed-Config-V2"  [shape=octagon,fontsize=12,fontname="Times-Bold",style=filled,fillcolor="#FFCCFF" ];
  "Unpacked-V1"       [shape=octagon,fontsize=12,fontname="Times-Bold",style=filled,fillcolor="#FFCCFF" ];


  subgraph installation
  {
    "Not-Installed"              -> "V1->\npreinst install"      [fontsize=12,fontname="Times-Bold",label="Install",color="cyan",fontcolor=lightskyblue];
    "V1->\npreinst install"      -> "V1->\npostrm abort-install" [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V1->\npreinst install"      -> "V1->\npostinst configure"   [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V1->\npostrm abort-install" -> "Half-Installed-V1"          [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V1->\npostrm abort-install" -> "Not-Installed"              [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V1->\npostinst configure"   -> "Installed-V1"               [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V1->\npostinst configure"   -> "Failed-Config-V1"           [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
  }

  subgraph removal
  {
    "Installed-V1"                -> "V1->\nprerm remove"          [fontsize=12,fontname="Times-Bold",label="Remove",color="cyan",fontcolor=lightskyblue];
    "V1->\nprerm remove"          -> "V1->\npostinst abort-remove" [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V1->\nprerm remove"          -> "V1->\npostrm remove"         [fontsize=9,fontname="Times-Roman",label="OK (del files)",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V1->\npostinst abort-remove" -> "Failed-Config-V1"            [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V1->\npostinst abort-remove" -> "Installed-V1"                [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V1->\npostrm remove"         -> "Half-Installed-V1"           [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V1->\npostrm remove"         -> "Config-Files-V1"             [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
    "Config-Files-V1"             -> "V1->\npostrm purge"          [fontsize=12,fontname="Times-Bold",label="Purge",color="cyan",fontcolor=lightskyblue];
    "V1->\npostrm purge"          -> "Config-Files-V1"             [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V1->\npostrm purge"          -> "Not-Installed"               [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
  }

  subgraph reinstall
  {
    "Config-Files-V1"               -> "V2->\npreinst install V1"       [fontsize=12,fontname="Times-Bold",label="Install V2",color="cyan",fontcolor=lightskyblue];
    "V2->\npreinst install V1"      -> "V2->\npostrm abort-install V1"  [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V2->\npreinst install V1"      -> "V2->\npostinst configure V1"    [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V2->\npostrm abort-install V1" -> "Half-Installed-V2"              [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V2->\npostrm abort-install V1" -> "Config-Files-V1"                [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V2->\npostinst configure V1"   -> "Failed-Config-V2"               [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V2->\npostinst configure V1"   -> "Installed-V2"                   [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
  }

  subgraph upgrading
  {
    "Installed-V1"                         -> "V1->\nprerm upgrade V2"               [fontsize=12,fontname="Times-Bold",label="Install V2",color="cyan",fontcolor=lightskyblue];
    "V1->\nprerm upgrade V2"               -> "V2->\nprerm failed-upgrade V1"        [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V1->\nprerm upgrade V2"               -> "V2->\npreinst upgrade V1"             [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V2->\nprerm failed-upgrade V1"        -> "V1->\npostinst abort-upgrade V2->\na" [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V2->\nprerm failed-upgrade V1"        -> "V2->\npreinst upgrade V1"             [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V1->\npostinst abort-upgrade V2->\na" -> "Failed-Config-V1"                     [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V1->\npostinst abort-upgrade V2->\na" -> "Installed-V1"                         [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V2->\npreinst upgrade V1"             -> "V2->\npostrm abort-upgrade V1->\na"   [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V2->\npreinst upgrade V1"             -> "V1->\npostrm upgrade V2"              [fontsize=9,fontname="Times-Roman",label="OK (unpack)",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V2->\npostrm abort-upgrade V1->\na"   -> "Half-Installed-V1"                    [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V2->\npostrm abort-upgrade V1->\na"   -> "V1->\npostinst abort-upgrade V2->\nb" [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V1->\npostinst abort-upgrade V2->\nb" -> "Unpacked-V1"                          [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V1->\npostinst abort-upgrade V2->\nb" -> "Installed-V1"                         [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V1->\npostrm upgrade V2"              -> "V2->\npostrm failed-upgrade V2"       [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V1->\npostrm upgrade V2"              -> "V2->\npostinst configure V1"          [fontsize=9,fontname="Times-Roman",label="OK (del old)",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V2->\npostrm failed-upgrade V2"       -> "V1->\npreinst abort-upgrade V2"       [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V2->\npostrm failed-upgrade V2"       -> "V2->\npostinst configure V1"          [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V1->\npreinst abort-upgrade V2"       -> "Half-Installed-V1"                    [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V1->\npreinst abort-upgrade V2"       -> "V2->\npostrm abort-upgrade V1->\nb"   [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
    "V2->\npostrm abort-upgrade V1->\nb"   -> "Half-Installed-V1"                    [fontsize=9,fontname="Times-Roman",label="Failed",color="firebrick",fontcolor="#FF6633",decorate="true"];
    "V2->\npostrm abort-upgrade V1->\nb"   -> "V1->\npostinst abort-upgrade V2->\nb" [fontsize=9,fontname="Times-Roman",label="OK",color="chartreuse",fontcolor="#009900",decorate="true"];
 }

 labelloc="t";
 label="\n";
 fontsize="32";
}

#+end_dot



# Local variables:
# mode: org
# fill-column: 72
# End:
-- 
"One man's mate is another man's passion." Jeff Daiell's description of
adultery
Manoj Srivastava <srivasta@debian.org> <http://www.debian.org/~srivasta/>  
1024D/BF24424C print 4966 F272 D093 B493 410B  924B 21BA DABB BF24 424C

Reply to: