[Webapps-common-discuss] webapps-common/doc Webapps-Pear-Policy-Manual-DRAFT.html, NONE, 1.1 pear.xsl, NONE, 1.1

madcoder-guest at haydn.debian.org madcoder-guest at haydn.debian.org
Mon Jul 18 14:30:47 UTC 2005


Update of /cvsroot/webapps-common/webapps-common/doc
In directory haydn:/tmp/cvs-serv7163

Added Files:
	Webapps-Pear-Policy-Manual-DRAFT.html pear.xsl 
Log Message:
import my PEAR doc to webapps repo

--- NEW FILE: Webapps-Pear-Policy-Manual-DRAFT.html ---
{* $Id: Webapps-Pear-Policy-Manual-DRAFT.html,v 1.1 2005/07/18 14:30:44 madcoder-guest Exp $ *}
{cvsdate date="\$Date: 2005/07/18 14:30:44 $"}

<h1>1. Policy for PEAR modules</h1>

<h2>1.1 Package name</h2>

<p>the PEAR package name should :</p>
<ul>
  <li>be prefixed with 'php-',</li>
  <li>be lowercased</li>
  <li>have all underscores be replaced by dashes</li>
</ul>

<h2>1.2 What the package has to achieve</h2>

<p>
PEAR has its own packaging system, and debian packages have to register
themselves with PEAR.
</p>

<p>
You may use <tt>pear install -r package.xml</tt> in <tt>postinst</tt> and
<tt>pear uninstall -r PEAR_MODULE_NAME</tt> in <tt>prerm</tt> to achieve that
</p>

<h2>1.3 Other Packaging Notes</h2>

<ul>
  <li>you should write a debian/watch file looking like :
  <div class="src">
    version=2<br />
    http://pear.php.net/package/&lt;package&gt;/download&nbsp;/get/&lt;package&gt;-([\d.]+)\.tgz
  </div>
  </li>
  <li>Lookup copyright in the package.xml, and write a debian/copyright with it,
  add the authors to the copyright file too, don't forget to name the website
  http://pear.php.net/package/&lt;package&gt;</li>
  <li>Add to /usr/share/doc/&lt;packagename&gt; a README where you refer to the
  website for documentation, bugs (optional, one could use Debian's BTS too),
  etc</li>
  <li>Documentation on the website is generated by phpDocumenter from the source
  package, you should run it, and put the documentation in
  /usr/share/doc/.../html).  If it's much, you might split the documentation out
  of it, but that'd usually not be necessary.</li>
</ul>

<h2>1.4 Other Advices</h2>

<p>
Respond to bugs, use rss2email to subscribe to the RSS feed for that
package to know about new releases.
</p>

<h1>2. A packaging suggestion</h1>

<p>We wanted to fulfill a few wishes :</p>

<ul>
  <li>having a quite general and easy to reproduce way to package PEAR modules</li>
  <li>do as less modifications to the PEARs tgz as possible</li>
  <li>having a human readable diff (so no tarball in the tarball !)</li>
  <li>to not break pear's own packaging system</li>
</ul>

<h2>2.1 Create the debian/ dir</h2>

<p>First, get the official pear module you want to package using the
<tt>pear</tt> command from the <tt>php4-pear</tt> package</p>
<div class="src">
  ~$ <strong>pear download MDB</strong><br />
  File MDB-1.3.0.tgz downloaded (218957 bytes)
</div>

<p>
And then prepare our deb-source tree : rename the tgz into a
package_version.orig.tar.gz, and unpack it.
</p>
<div class="src">
  ~$ <strong>mv MDB-1.3.0.tgz php-mdb_1.3.0.orig.tar.gz</strong><br />
  ~$ <strong>mkdir php-mdb</strong><br />
  ~$ <strong>cd php-mdb</strong><br />
  ~/php-mdb$ <strong>tar xzf ../php-mdb_1.3.0.orig.tar.gz</strong><br />
  ~/php-mdb$ <strong>mkdir debian</strong><br />
  ~/php-mdb$ <strong>echo 4 &gt; debian/compat</strong><br />
  ~/php-mdb$ <strong>ls</strong><br />
  MDB-1.3.0  debian  package.xml
</div>

<p>I know that to decompress the orig.tar.gz into a subdir seems to be awkward,
but in fact, it has a file (<tt>package.xml</tt>) that is at the toplevel of the
archive, and dpkg knows how to deal with it alone ! big good boy ;)</p>

<h2>2.2 Create the debian/rules script</h2>

<p>how it works ? In three steps :</p>
<ol>
  <li>It creates some scripts and files from templates (<tt>postinst</tt>,
  <tt>prerm</tt>, <tt>watch</tt>)</li>
  <li>It creates the PEAR tgz again (see in <tt>build:</tt> target)</li>
  <li>And then use <tt>pear</tt> to install it in the <tt>debian/foo/</tt>
  subtree</li>
</ol>

<p>The very good points here are :</p>
<ul>
  <li>We have nothing to do if the PEAR package structure we are packaging
  changes, we let <tt>pear</tt> deal with it alone</li>
  <li>We never have to deal with the <tt>package.xml</tt> ourself</li>
  <li>The method still work for PECL packages, since <tt>pear</tt> knows about
  building such extensions.<br />
  Some remarks for PECL :
  <ul>
    <li>we have to <tt>mkdir debian/<em>foo</em>/usr/lib/php4/20020429/</tt>
    ourself since <tt>pear</tt> doesn't seem to take care of it</li>
    <li>pear need <tt>phpize</tt> for that, so you have to add <tt>php4-dev</tt>
    to the build-depends as well</li>
  </ul>
  </li>
</ul>

<p>The bad point is that <tt>pear</tt> does at the same time :
<tt>configure</tt>, <tt>make</tt> and <tt>make install</tt>.  So it's hard to
split them (build: and binary: targets of the <tt>debian/rules</tt>)</p>

<p>You only need to copy the following <tt>debian/rules</tt> :</p>
<p style="font-size:smaller">you have to get <a href="pear.xsl">the pear.xsl</a> used to generate the upstream's changelog</p>
<div class="src">
{literal}
<pre>#!/usr/bin/make -f

pear_pkg := $(shell xpath -q -e '/package/name/text()' package.xml)
package = $(shell echo php-$(pear_pkg) | tr '[:upper:]_' '[:lower:]-')

clean:
        rm -f \
                debian/package.tgz \
                debian/$(package).postinst \
                debian/$(package).prerm \
                debian/watch \
                debian/Changelog
        dh_testdir
        dh_testroot
        dh_clean

build:
        cat debian/postinst.tpl | perl -e 'while(&lt;&gt;) { exit if /@xml@/; print;}' \
                        &gt;  debian/$(package).postinst
        cat package.xml &gt;&gt; debian/$(package).postinst
        cat debian/postinst.tpl | perl -e 'while(&lt;&gt;) { print if $$b; $$b=1 if /@xml@/;}' \
                        &gt;&gt; debian/$(package).postinst

        cat debian/prerm.tpl | sed -e 's/@pear_pkg@/$(pear_pkg)/g' \
                        &gt; debian/$(package).prerm

        cat debian/watch.tpl | sed -e 's/@pear_pkg@/$(pear_pkg)/g' \
                        &gt; debian/watch

        xsltproc --nonet --novalid debian/pear.xsl package.xml &gt; debian/Changelog

        tar czf debian/package.tgz `ls | grep -v debian`

binary: binary-arch binary-indep
        # Nothing to do here

binary-arch:
        # Nothing to do here

binary-indep:
        dh_testdir
        dh_installdirs

        # Custom package commands
        pear install -n -R debian/$(package)/ debian/package.tgz
        rm -rf \
                debian/$(package)/usr/share/php/.filemap \
                debian/$(package)/usr/share/php/.lock \
                debian/$(package)/usr/share/php/.registry

        # Resume debhelper scripts
        dh_testroot
        dh_installchangelogs  debian/Changelog
        dh_installdocs
        dh_installdeb
        dh_fixperms
        dh_compress
        dh_gencontrol
        dh_md5sums
        dh_builddeb

.PHONY: binary binary-arch binary-indep build clean</pre>
{/literal}
</div>

<h2>2.3 create the postinst template</h2>

<p>
We need to keep the <tt>package.xml</tt> safe, since it allows us to register
the package in PEAR.
</p>

<p>You'll have to create a <tt>debian/postinst.tpl</tt> which should have a line
beeing exactly '@xml@', that will be replaced by the package.xml content.  It
should looks like :</p>

<div class="src">
<pre>#! /bin/sh

set -e

case "$1" in

    configure)
        curdir=`pwd`
        tmp=`mktemp -t -d`
        cd $tmp
        (cat &lt;&lt;-EOF
<strong>@xml@</strong>
EOF
        ) &gt; package.xml
        pear install -r package.xml &amp;&gt;/dev/null
        cd $curdir
        rm -rf $tmp
    ;;

    abort-upgrade|abort-remove|abort-deconfigure)
    ;;

    *)
        echo "postinst called with unknown argument \`$1'" &gt;&amp;2
        exit 1
    ;;

esac

#DEBHELPER#

exit 0</pre>
</div>

<h2>2.4 Create the prerm template</h2>

<p>We have to know the PEAR's module name here, in order to be unregistered from
PEAR at remove, upgrade or deconfigure time.  You have to create a prerm.tpl
containing the @pear_pkg@ token, that will be replaced by the PEAR's module name
:</p>

<div class="src">
<pre>#!/bin/sh

set -e

case "$1" in
    remove|upgrade|deconfigure)
        pear uninstall -r <strong>@pear_pkg@</strong> 1&gt;/dev/null 2&gt;/dev/null
    ;;

    *)
    ;;
esac

#DEBHELPER#

exit 0</pre>
</div>

<h2> 2.5 Create the watch template</h2>

<p>It works like the postrm template does.  it replaces the @pear_pkg@ token
with the PEAR's module name.  So here is a watch.tpl example: </p>
<div class="src">
<pre>version=2
http://pear.php.net/package/<strong>@pear_pkg@</strong>/download /get/@pear_pkg at -([\d.]+)\.tgz</pre>
</div>


<h2> 2.6 further notes</h2>

<p>don't forget to create <tt>debian/changelog</tt>, <tt>debian/copyright</tt>
(see policy above) and <tt>debian/control</tt> file, and you'll be done</p>

<p>be carefull, your Build-Depends(-Indep) in <tt>debian/control</tt> has to
mention <span style="color:red">php4-pear, libxml-xpath-perl and
  xsltproc</span></p>

<p><strong>TODO:</strong></p>
<ul>
  <li>some automatic scripts (like dh_make does)</li>
  <li>write some helper scripts that can help to create
  <tt>debian/copyright</tt> and <tt>debian/control</tt> from the package.xml
  files</li>
</ul>
{* vim:set et sw=2 sts=2 sws=2: *}

--- NEW FILE: pear.xsl ---
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:util="urn:xslt:functions:util" xmlns:func="http://exslt.org/functions" xmlns:str="http://exslt.org/strings" extension-element-prefixes="func str">
<xsl:output method="text"/>

  <func:function name="util:maximize">
    <xsl:param name="string"/>
    <xsl:param name="line-length"/>

    <func:result>
      <xsl:variable name="tmp" select="string-length(substring-before($string,' '))"/>
      <xsl:choose>
	<xsl:when test="($tmp &gt; $line-length) or (not(contains($string, ' ')))">0</xsl:when>
        <xsl:when test="(substring($string,$line-length,1) = ' ')">
	  <xsl:value-of select="$line-length"/>
	</xsl:when>
	<xsl:otherwise>
	  <xsl:value-of select="util:maximize(substring-after($string, ' '), $line-length - $tmp - 1) + 1 + $tmp"/>
	</xsl:otherwise>
      </xsl:choose>
    </func:result>
  </func:function>

  <func:function name="util:format">
    <xsl:param name="string"/>
    <xsl:param name="indent" select="2"/>
    <xsl:param name="line-length" select="76"/>

    <func:result>
      <xsl:choose>
        <xsl:when test="contains($string,'&#xA;') or contains($string,'&#xD;')">
          <xsl:for-each select="str:tokenize($string,'&#xA;&#xD;')">
	    <xsl:value-of select="util:format(., $indent, $line-length)"/>
          </xsl:for-each>	    
	</xsl:when>
	<xsl:when test="string-length($string) &gt; $line-length">
	  <xsl:variable name="tmp" select="util:maximize($string, $line-length)"/>
	  <xsl:value-of select="str:padding($indent,' ')"/>
	  <xsl:value-of select="substring($string, 1, $tmp)"/>
	  <xsl:text>&#xA;</xsl:text>
	  <xsl:value-of select="util:format(substring($string, $tmp + 1))"/>
	</xsl:when>
	<xsl:otherwise>
	  <xsl:value-of select="str:padding($indent,' ')"/>
	  <xsl:value-of select="$string"/>
	  <xsl:text>&#xA;</xsl:text>
	</xsl:otherwise>
      </xsl:choose>
    </func:result>
  </func:function>

  <func:function name="util:norm">
    <xsl:param name="num"/>
    <xsl:param name="length" select="4"/>

    <xsl:choose>
      <xsl:when test="$length &gt; string-length($num)">
        <func:result select="concat('0',util:norm($num, $length - 1))"/>
      </xsl:when>
      <xsl:otherwise>
        <func:result select="$num"/>
      </xsl:otherwise>
    </xsl:choose>
  </func:function>

  <func:function name="util:extractnum">
    <xsl:param name="string"/>

    <xsl:choose>
      <xsl:when test="$string = ''">
        <func:result select="0"/>
      </xsl:when>
      <xsl:when test="$string &lt;= '9' and $string &gt;= '0'">
        <func:result select="$string"/>
      </xsl:when>
      <xsl:otherwise>
        <func:result select="util:extractnum(substring($string,1,string-length($string)-1))"/>
      </xsl:otherwise>
    </xsl:choose>
  </func:function>

  <func:function name="util:ver2num">
    <xsl:param name="version"/>

    <xsl:choose>
      <xsl:when test="contains($version,'.')">
        <func:result select="concat(util:norm(substring-before($version,'.')), util:ver2num(substring-after($version,'.')))"/>
      </xsl:when>
      <xsl:when test="$version = number($version)">
        <func:result select="concat(util:norm($version), util:norm(0))"/>
      </xsl:when>
      <xsl:otherwise>
	<xsl:variable name="tmp" select="util:extractnum($version)"/>
        <func:result select="concat(util:norm($tmp),' ', substring($version, string-length($tmp) + 1))"/>
      </xsl:otherwise>
    </xsl:choose>
  </func:function>

  <xsl:template match="package">
    <xsl:apply-templates select="changelog/release">
      <xsl:sort order="descending" select="util:ver2num(normalize-space(version))" data-type="text"/>
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="release">
    <xsl:text>Version </xsl:text>
    <xsl:value-of select="version"/>
    <xsl:text> - </xsl:text>
    <xsl:value-of select="date"/>
    <xsl:if test="state">
      <xsl:text> (</xsl:text>
      <xsl:value-of select="state"/>
      <xsl:text>)</xsl:text>
    </xsl:if>
    <xsl:text>&#xA;----------------------------------------&#xA;Notes:&#xA;</xsl:text>
    <xsl:value-of select="util:format(notes)"/>
    <xsl:text>&#xA;</xsl:text>
  </xsl:template>

</xsl:stylesheet>




More information about the Webapps-common-discuss mailing list