[Pkg-crosswire-devel] Automated Sword module packaging: it works

Jonathan Marsden jmarsden at fastmail.fm
Mon Jan 26 11:28:25 GMT 2009


Today I have been able to script the process of converting Sword modules
into Debian packages.  While the script is, shall we say, not
necessarily bulletproof (!), it *is* packaging a pile of Sword modules
for me as I type this.

The resulting modules are likely to benefit from manual checking and
probably some manual edits to control files etc. before release, of
course, and Matthew has privately suggested some interesting ideas about
automatically generating lucene indexes to go with them... but I think
the basic principle of automated module to package conversion can now be
considered to be proven.

Below are module2deb which does the conversion/packaging, and
package-modules.sh, a script that grabs the Crosswire archive of Sword
modules and then packages all of them which are labelled as being
"Public Domain".  I hope word-wrap won't destroy them beyond all
recognition.

module2deb expects that whoever runs it has a normal packaging
environment set up, complete with $DEBFULLNAME and $DEBEMAIL, and by
default it does do package signing, so for bulk use you have to set up
gpg-agent or seahorse or whatever so that you don't have to type your
GPG passphrase twice for each package build!  It generates module names
including a component based on ModDrv, so the names try to distinguish
between text and commentary and so forth.  How useful that feature is,
is definitely up for discussion...!

[I see that module2deb seems to have at least one bug; it is not
handling lines in the module *.conf files that contain parentheses
sanely at the moment... probably a quoting issue somewhere.]

The build has now finished, and I have 130 sword-*.deb (and *.dsc, etc)
files!  I'm not about to upload them to my PPA, though.

The lintian warnings are almost all about the changelogs not closing an
ITP bug (impossible to 100% automate that!), and then a few (which I'll
try to check up on) about the description and synopsis fields in the
control file (which module2deb tries to generate from the Description
and About fields in the module .conf file).

NOTE: Please do *not* run package-modules.sh if you do not intend to
work on this stuff, as it will download around 270MB of modules from
Crosswire the first time you run it.  The Crosswire archive does not
seem to have an obvious way to download just the metadata (just the
*.conf files), so one can then download only the Public Domain
modules... so the script downloads all of them, but then only builds the
PD ones.  If there is a better way to do this, please let me know.

Of course, no-one who does objects to them needs to to use these
scripts, or the resulting packages they generate.  No-one is being
forced to do anything, here -- I'm simply providing tools.  The
resulting packages could be submitted to Debian and/or Ubuntu, or could
be put into a PPA or a local "private" repository; none of that is being
dictated by the existence of the tools in any way.

I'm not sure quite where the scripts would belong in the team git
repository, but I'll happily commit them there.  Do we need a new
"modules" chunk of git space for things like this?

Jonathan

#--------------------------------------------------------------------

#!/bin/bash
# module2deb - converts a Sword module .zip file into a Debian source
package
#              Expects to be able to create the package, the orig.tar.gz
and
#              a package dir in the current directory.
#
# Author: Jonathan Marsden <jmarsden at fastmail.fm>
# Copyright: Copyright (C) 2009 Jonathan Marsden
# Licence: GPLv2 or later
# Version: 0.1

distribution="unstable" # Set this to intrepid, jaunty etc. for Ubuntu
debuild_options=""	# Can set to "-us -uc" to avoid GPG signing

[ -z "$1" ] && echo -e "$0: Usage is: $0 zipfile ...\n" && exit 1

function line2var () {
  # function line2var takes one parameter which is the entire line.
  # Most lines in the .conf files are of the form varname=value
  # The first line of each file can be a tag of the form [tag].
  # In this exceptional case, we set conffiletag to the [tag] string.
  varname=${1%%=*}
  value=${1#*=}
  if [ "${varname:0:1}" = "[" ]; then
    value="$varname"
    varname=conffiletag
  fi
  varname=${varname/./_}	# Periods not allowed in bash varnames
  eval ${varname}=\""$value"\"
  #echo "l2v DEBUG $varname is ${!varname}"
}

# Main loop (once through loop for each zipfile)
while [ -n "$1" ]
do
  zipfile="$1"

  # Can we read the file?
  if [ ! -r "$zipfile" -o ! -s "$zipfile" ]; then
    echo "$0: ERROR: $zipfile is not a readable zipfile"
    exit 2
  fi

  # Unzip zipfile into a temporary location
  tempzip="/tmp/$$/$zipfile"
  mkdir -p $tempzip
  if [ ! -d "$tempzip" ];then
    echo "%0: ERROR: $tempzip dir not created"
    exit 3
  fi
  unzip -nqq "$zipfile" -d "$tempzip"

  # Grab data from mods.d/*.conf file into shell variables
  # We need $Version for the version number, and so forth
  unset Version DistributionLicense conffiletag Description About
  Version=${Version:-1.0}	# a few modules have no Version line in their
.conf
  while read -r x ; do line2var "$x" ; done <${tempzip}/mods.d/*.conf
  # Convert ModDrv into a moduletype, removing any leading z
  moduletype=`echo $ModDrv |tr [A-Z] [a-z]`
  [ "${moduletype:0:1}" = "z" ] && moduletype=${moduletype:1}

  # Make sure this module is sufficiently free
  free=no
  case "$DistributionLicense" in
    "Public Domain") free=yes ;;
    "General public license for distribution for any purpose") free=yes ;;
  esac

  if [ "$free" != "yes" ]; then
    echo "$0: ERROR: $zipfile has non-free DistributionLicence of
$DistributionLicense"
    exit 4
  fi

  # Convert file.zip to file-$Version_orig.tar.gz
  stem=`basename $1 .zip`
  stem=`basename $stem .ZIP` # just in case we have any .ZIP files
  stem=`echo $stem |tr [A-Z] [a-z]`
  tarname="sword-${moduletype}-${stem}-$Version"
  origtarname="sword-${moduletype}-${stem}_$Version"
  tardir="$tempzip/$tarname"
  mkdir -p "$tardir"
  unzip -nqq "$zipfile" -d "$tardir"
  tar -z -c -C "$tempzip" -f "$origtarname.orig.tar.gz" "$tarname"

  # Unpack tarball
  [ -d "$tarname" ] && echo "$0: ERROR: directory $tarname already
exists" && exit 5
  tar zxf "$origtarname.orig.tar.gz"

  # Create source package tree debian/ files
  cd $tarname
  mkdir debian
  datestamp=`date -R`

  cat >debian/changelog <<EOF
sword-${moduletype}-$stem ($Version-1) $distribution; urgency=low

  * Initial Release.

 -- $DEBFULLNAME <$DEBEMAIL>  $datestamp
EOF
  echo 5 >debian/compat

  # Word-wrap $About ready for use in control file
  echo "$About" >$tempzip/about
  sed -i 's/\\par/\n\n/g' $tempzip/about	# Deal with \par meaning
paragraph break
  fmt -s $tempzip/about >$tempzip/about2
  sed -i 's/^ *$/./' $tempzip/about2	# Make sure para breaks are exactly "."
  sed -i 's/^/ /' $tempzip/about2	# Indent everything one space

  cat >debian/control <<EOF
Source: sword-${moduletype}-$stem
Section: text
Priority: optional
Maintainer: $DEBFULLNAME <$DEBEMAIL>
Homepage: http://www.crosswire.org/sword/modules/
Build-Depends: debhelper (>= 5)
Standards-Version: 3.8.0

Package: sword-${moduletype}-$stem
Architecture: all
Suggests: libsword7
Provides: sword-text
Enhances: sword-frontend
Description: $Description
EOF
  cat $tempzip/about2 >>debian/control

  cat >debian/copyright <<EOF
This package was debianized by $DEBFULLNAME <$DEBEMAIL> on
$datestamp .

It was downloaded from

  http://crosswire.org/ftpmirror/pub/sword/packages/rawzip/

Based on the information in the upstream .conf file, the
"Distribution Licence" for this module is:

$DistributionLicense

EOF
  #include $About (formatted) if relevant
  grep -sqi copyright $tempzip/about2 &&
    cat $tempzip/about2 >>debian/copyright
  #include info on decompression
  cat >>debian/copyright <<EOF

The text as distributed is in a compressed format.  You can use the mod2imp,
mod2osis or mod2vpl commands from the libsword-tools package in order to
extract the text into an uncompressed form.
EOF

  cat >debian/rules <<EOF
#!/usr/bin/make -f
# -*- makefile -*-
# This file was originally written by Joey Hess and Craig Small.
# As a special exception, when this file is copied by dh-make into a
# dh-make output file, you may use that output file without restriction.
# This special exception was added by Craig Small in version 0.37 of
dh-make.

configure: configure-stamp
configure-stamp:
	dh_testdir
	touch configure-stamp

build: build-stamp
build-stamp: configure-stamp
	dh_testdir
	touch build-stamp

clean:
	dh_testdir
	dh_testroot
	rm -f build-stamp configure-stamp
	dh_clean

install: build
	dh_testdir
	dh_testroot
	dh_clean -k
	dh_installdirs
	install -d m* debian/sword-$moduletype-$stem/usr/share/sword

# Build architecture-independent files here.
binary-indep: build install
	dh_testdir
	dh_testroot
	dh_installchangelogs
	dh_installdocs
	dh_compress
	dh_fixperms
	dh_installdeb
	dh_shlibdeps
	dh_gencontrol
	dh_md5sums
	dh_builddeb

# Build architecture-dependent files here.
binary-arch: build install
# We have nothing to do by default.

binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install configure

EOF
  chmod 0700 debian/rules

  # Clean up
  [ -n "$tempzip" -a -d "$tempzip" ] && rm -r "$tempzip"

  # Package it!
  echo "$0: Packaging $1 in `pwd`"
  debuild $debuild_options
  debuild -S -sa $debuild_options

  # Even more clean up (comment out when debugging this script)
  cd ..
  [ -n "$tarname" -a -d "$tarname" ] && rm -r ./"$tarname"

  # Get ready to go back and process the next zipfile
  shift
done

#--------------------------------------------------------------------

#!/bin/bash
# package-modules.sh - downloads and packages packages a pile of Sword
modules

ziparchivedir=~/packages/sword/modules/zipfiles		# Module archive dir
builddir=~/packages/sword/modules			# Package build area
m2d=$builddir/module2deb				# Path to module2deb script

# Create/update zip archive of Sword modules from Crosswire
mkdir -p $ziparchivedir
cd $ziparchivedir
wget -m --no-parent -nH -nd
http://crosswire.org/ftpmirror/pub/sword/packages/rawzip/
rm index.html* robots.txt	# Get rid of junk that is not .zip modules

# First convert KJV to a package (because it is freely redistributable
but not labelled PD)
mkdir -p $builddir
cd $builddir
$m2d $ziparchivedir/KJV.zip

# Then build all the rest of the modules that are labelled as being
public domain
cd $builddir
for i in $ziparchivedir/*zip
do
  unzip -p $i 'mods.d/*.conf' |grep -sqx 'DistributionLicense=Public
Domain' && $m2d $i
done

#--------------------------------------------------------------------




More information about the Pkg-crosswire-devel mailing list