Why do we need Monodoc integration?

We need Monodoc integration because:

  1. we are using a grep and sed hack, which is not really good to look at, and sometimes wrong;
  2. we are losing all the information on each upgrade of monodoc-manual, because we write into /usr/lib/monodoc/monodoc.xml, which is owned by the monodoc-manual package.

Possible solutions

Global Registry (involves upstream cooperation)

This approach has many advantages. First of all, we don't lose all our informations on monodoc-manual upgrades. The registry could be kept in /usr/lib/monodoc/manuals.d/, and should be parsed by monodoc-related software We could take a look at dh_installcligac to see how it manages the GAC registry.

We'd also need to patch monodoc itself. Monodoc is, in fact, looking for /usr/lib/monodoc/monodoc.xml. We should make it happy with this new /usr/'lib'/monodoc/manuals.d/, and with all the files it would contain.

The code which looks for monodoc.xml is at ./engine/provider.cs:743 (citation starting at line 740):

                //
                // Load the layout
                //
                string layout = Path.Combine (basedir, "monodoc.xml");
                doc.Load (layout);
                XmlNodeList nodes = doc.SelectNodes ("/node/node");
                root.name_to_node ["root"] = root;
                root.Populate (root, nodes);
                Node third_party = root.LookupEntryPoint ("various");
                if (third_party == null) {
                        Console.Error.WriteLine ("No 'various' doc node! Check monodoc.xml!");
                        third_party = root;
                }

We obviously should make Monodoc capable of looking not only in monodoc.xml, but also in /usr/'lib'/monodoc/manuals.d/. That shouldn't be that much difficult, though :)

Patching Monodoc

What would be the right way of patching the above code? The idea is simple: the nodes variable is a System.Xml.XmlIteratorNodeList instance. Why can't we append something to it (and, eventually, sort it)?

The idea is: put many small XML files into /usr/'lib'/monodoc/manuals.d/, parse them, and append the resulting nodes to the bigger nodes XmlIteratorNodeList.

Local Registry (Debian-only)

This approach has many advantages. First of all, we don't lose all our informations on monodoc-manual upgrades. The registry could be kept in /usr/share/monodoc/manuals.d/, and should be parsed by monodoc-related software We could take a look at dh_installcligac to see how it manages the GAC registry.

We would not patch monodoc though, instead we write a monodoc.xml generator tool that takes the manual info from /usr/share/monodoc/manuals.d/and writes (creates or updates) the monodoc.xml file in-place.The generator maybe need to take care of ordering so the list of libraries are ordered alphabetically, if monodoc does it already then the generator doesn't need to take care of that.

dh_installmonodoc would read debian/*.installmonodoc files and copies the tree/zip/sources files in the right place and does the postinst (or maybe dpkg triggers) handling. For that it needs some information to do it's job. Like the build-path where the doc files are (*.tree/zip/sources) and parent-node which is by default Various (as 99% of the packages will (or maybe must, not sure of monodoc enforces this already, but upstream doesn't want other libs to be listed in "their" parent-nodes) use that one anyhow).

Format of *.installmonodoc

Abstract Format:

PATH BASENAME LABEL [PARENT]

PATH, BASENAME and LABEL are required, PARENT is optional.

PATH points to the build-directory where the manual files can be found, it will be copied from that location into the package directory.

BASENAME is the name of the file set (*.{tree,zip,sources})

LABEL describes the label that will be visible in the tree of the monodoc-browser.

PARENT is the parent-node of the tree, if it's not specified, Various will be used. A special value is "root:" (beware of the colon!).

Example:

# PATH BASENAME LABEL [PARENT]
debian/tmp/usr/lib/monodoc/sources/ MySql.Data MySql.Data

You can use a special format, used especially for (monodoc.xml's) upstream-provided XML nodes. Some of these do not have corresponding *.{tree,zip,sources} files, so you have to specify the destination filename manually. A clear example is the "Various" node:

# FILENAME  BASENAME   LABEL         PARENT
various     none       "Various"     root:

This is also useful to specify new parent nodes.

Involved scripts

The involved scripts/files to help maintainers would be:

  1. /usr/bin/dh_installmonodoc
  2. /usr/sbin/update-monodoc
  3. /usr/share/debhelper/autoscripts/postinst-monodoc
  4. /usr/share/debhelper/autoscripts/postrm-monodoc

Node removal policy

The best thing to do is: if there is no related file in /usr/share/monodoc/manuals.d/, remove the node. But, problems will arise during the "transition phase": how should we behave?

update-monodoc will simply create the monodoc.xml file always from scratch, then postrm will call update-monodoc and that will make sure the node is removed.

XML-diff check in debian/rules of mondoc

As we create the monodoc.xml file always from scratch we need to ensure that we don't break changes that upstream does in the file. For that reason we have to make a xml-diff check in the build stage of monodoc that compares the upstream provided XML with the generated XML and exit with an error if it doesn't matches.

What we need

  1. Someone doing it.
  2. Someone doing it.
  3. Someone doing it.
  4. Time. Plenty of it. Or some boring Saturday evening like this one.