Difficulty: ★★☆ (medium)
Keywords: version control system, revhistory, Bazaar, Git, Mercurial, Subversion

Problem

You want to include revision information into your DocBook document from your version control systems, like Bazaar, Subversion, Mercurial, Git, and others.

Solution

Usually, the solution for each version control system is to output its log into its specific XML output and transform it with XSLT into a revhistory element.

Bazaar

Bazaar does not come with a predefined XML output. If you need this functionality, you have to install the xmloutput plugin first. This brings the --xml option to the log subcommand. Proceed as follows:

Procedure 3.2. Installing the Bazaar Plugin xmloutput
  1. Download the tar archive from http://wiki.bazaar.canonical.com/XMLOutput.

  2. Unpack the archive.

  3. Change to the extension directory (usually something like bzr-xmloutput-VERSION) and run:

    python setup build_ext
  4. Copy the result directory build/lib/bzrlib/plugins/xmloutput/ to your plugin directory. For Linux it is something like $HOME/.bazaar/plugins/, for Windows copy it to $APPDATA/bazaar/VERSION/plugins

  5. Check if the plugin is correctly detected:

    bzr plugins

    You should see the following line:

    xmloutput VERSION
        This plugin adds an option (--xml) to log and provides an xml version of
        some built-in commands.

After you have successully installed the plugin, create the log output in XML with the following command:

bzr log --xml REPO > bzr-log.xml

To convert the previous log file into DocBook's revhistory, use the following stylesheet:

Example 3.19. Stylesheet to Convert Bazaar's Log File
TBD

Git

Git does not have any options to turn the log into XML. However, with the --pretty option you can collect the information and wrap it into any XML elements you wish. The following command uses this option and sed to insert the <logs> start tag in the first line and </logs> end tag in the last line:

git log --date=iso --pretty=format:"<logentry revision='%h'>%n <author email='%ae'>%an</author>%n <date>%ad</date>%n <msg xml:space='preserve'>%s</msg>%n</logentry>" \
  | sed -e '1i<logs>' -e '$a</logs>' > git-log.xml

As the element names can be freely chosen, we use the same names as in Example 3.20, “Mercurial Log File in XML”. This allows us to use the stylesheet from Example 3.21, “Stylesheet hg2revhistory.xsl to Convert Mercurial XML Log Files into DocBook's revhistory.

Mercurial

Mercurial has the --style option to output its log into XML:

hg log --style xml > hg-log.xml

The XML file of the Mercurial log looks like this:

Example 3.20. Mercurial Log File in XML
<log>
  <logentry revision="69"
    node="dfadd024594c4083362fe6919264362803dcd285">
    <tag>tip</tag>
    <author email="tux@example.de">Tux Penguin</author>
    <date>2011-05-22T01:56:21+02:00</date>
    <msg xml:space="preserve">Corrected xml:id attribute</msg>
    <paths>
      <path action="M">xml/structure/topic.extract-element.xml</path>
    </paths>
  </logentry>
  <logentry revision="68"
    node="833287df8943d0bab5ec65ec8aafe5bc42002289">
    <author email="wilber@example.de">Wilber Gimp</author>
    <date>2011-05-22T01:56:03+02:00</date>
    <msg xml:space="preserve">Changed chapter title</msg>
    <paths>
      <path action="M">xml/structure/topic.revision-list.xml</path>
    </paths>
  </logentry>
  <!-- Many more entries ... -->
</log

The following stylesheet converts the log file from Example 3.20, “Mercurial Log File in XML” into DocBook's revhistory:

Example 3.21. Stylesheet hg2revhistory.xsl to Convert Mercurial XML Log Files into DocBook's revhistory
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet
[
  <!ENTITY dbns "http://docbook.org/ns/docbook">
]>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  
  <xsl:output method="xml" indent="yes"/>
  
  <xsl:param name="include.paths" select="1"/>
  <xsl:param name="include.copies" select="1"/>
  
  <xsl:template match="log">
    <revhistory xmlns="&dbns;">
      <xsl:apply-templates/>
    </revhistory>
  </xsl:template>
  
  <xsl:template match="logentry">
    <revhistory xmlns="&dbns;">
      <xsl:apply-templates select="@revision|*"/>
    </revhistory>
  </xsl:template>
  
  <xsl:template match="logentry/@revision">
    <revnumber xmlns="&dbns;">
      <xsl:apply-templates/>
    </revnumber>
  </xsl:template>
  
  <xsl:template match="tag">
    <revremark xmlns="&dbns;">
      <xsl:apply-templates/>
    </revremark>
  </xsl:template>
  
  <xsl:template match="date">
    <date xmlns="&dbns;">
      <xsl:apply-templates/>
    </date>
  </xsl:template>
  
  <xsl:template match="author">
    <xsl:variable name="firstname" select="substring-before(., ' ')"/>
    <xsl:variable name="surname" select="substring-after(., ' ')"/>
    <author xmlns="&dbns;">
      <personname>
        <firstname><xsl:value-of select="$firstname"/></firstname>
        <!--<othername></othername>-->
        <surname><xsl:value-of select="$surname"/></surname>
      </personname>
      <email><xsl:value-of select="@email"/></email>
    </author>
  </xsl:template>
  
  <xsl:template match="msg">
    <revdescription xmlns="&dbns;">
      <para>
        <xsl:apply-templates/>
      </para>
    </revdescription>
  </xsl:template>
  
  <xsl:template match="paths">
    <xsl:if test="$include.paths != 0">
      <itemizedlist xmlns="&dbns;">
        <title>Paths</title>
        <xsl:apply-templates/>
      </itemizedlist>
    </xsl:if>
  </xsl:template>
  
  <xsl:template match="path">
    <listitem xmlns="&dbns;">
      <para>
        <xsl:apply-templates select="@action|text()"/>
      </para>
    </listitem>    
  </xsl:template>
  
  <xsl:template match="path/@action">
    <xsl:text>[</xsl:text>
    <xsl:value-of select="."/>
    <xsl:text>] </xsl:text>
  </xsl:template>
  <xsl:template match="path/text()">
    <filename xmlns="&dbns;">
      <xsl:value-of select="."/>
    </filename>
  </xsl:template>

  <xsl:template match="copyies">
    <xsl:if test="$include.paths != 0">
      <listitem xmlns="&dbns;">
        <title>Copies</title>
        <para>
          <xsl:apply-templates select="@*|text()"/>
        </para>
      </listitem>
    </xsl:if>
  </xsl:template>
  <xsl:template match="copy">
    <listitem xmlns="&dbns;">
      <para>
        <xsl:apply-templates select="@*|text()"/>
      </para>
    </listitem>    
  </xsl:template>
  
  <xsl:template match="copy/@source">
    <filename xmlns="&dbns;">
      <xsl:value-of select="."/>
    </filename>
  </xsl:template>
  <xsl:template match="copy/text()">
    <xsl:text> -> </xsl:text>
    <filename xmlns="&dbns;">
      <xsl:value-of select="."/>
    </filename>
  </xsl:template>
  
</xsl:stylesheet>

Subversion

Subversion is similar to Mercurial: It has an --xml option to turn the log output into XML:

svn log --xml > svn-log.xml

With the -v option (verbose) you get additional path information. As the output is very similar to Mercurial, you can apply the stylesheet shown in Example 3.21, “Stylesheet hg2revhistory.xsl to Convert Mercurial XML Log Files into DocBook's revhistory also for Subversion's log file.

As an alternative, the DocBook Subversion repository (see https://docbook.svn.sourceforge.net/svnroot/docbook/trunk) contains the XSLT stylesheet releasetools/svnlog2docbook.xsl with additional features.

Discussion

TBD


Project@GitHubIssue#8