#!/bin/sh # http://www.phys.ethz.ch/~franklin/Projects/dphys2/makepackage # - generate directory structure and content and operate for making packages # copyright ETH Zuerich Physics Deparement, use under either BSD or GPL license # author Neil Franklin, last modification 2003.06.13 # this script is intended to be run as an normal user # use as makepackage [options] # ------ configuration to run site package # first CONF_* various site or subnet dependant user config variables # then DEBUG_* various debugging settings # last SYS_* various system internal values # some of these are overridable by command line options # --- CONF_* various site or subnet dependant user config variables # this is prepended to packagename if only a hostname is given (no - in name) # do not insert an specific hostname into this, this is prefixed to the hostn CONF_HOST_TO_PKG_PREFIX=dphys-host- # this is the contents for /usr/share/doc/*/copyright file # not that we expect anyone else to ever use these packages :-) CONF_PKG_COPY="copyright ETH Zuerich Physics Deparement, use under either BSD or GPL license" # this is the contents for /usr/share/doc/*/changelog file CONF_PKG_CHLOG_VERS="current:" CONF_PKG_CHLOG_TEXT="\tcurrent version, changes constantly, versioning done only on debianising" # this is for the /usr/share/doc/*/changelog.Debian and /DEBIAN/control # and the Packages list entry for apt-get and dpkg CONF_PKG_MAINTAINER="dphys2 makepackage script " # this is the site package to put into the "Depends:" of this packages control # it itsself then refers to all packages that we want to have loaded #CONF_SITE_PKG=dphys-site #CONF_SITE_PKG=dphys-site-franklin-experimental CONF_SITE_PKG=dphys-site-dsbg-experimental # what we put into the package as description # this comment is really outdated, reflected original purpose of this stuff # today edit this by the user, to what this package is for CONF_DESC_SH="Pull in packages via Depends: and config files" # we offer 3 lines, blank at front gets added CONF_DESC_1="This package exists soley to produce Depends: dependencies." CONF_DESC_2="This is to get apt-get to load all packages we want." CONF_DESC_3="It also loads various config files that we want to have." # --- DEBUG_*, various debugging settings # set this to output debug state info and wait after each step DEBUG_PRINT_STEP=no # --- SYS_*, various system internal values # set our default architecture, no binary stuff in host or site packages SYS_ARCH=all # set out default debianisation level SYS_PKG_LEVEL=1 ### ------ actual implementation from here on # no user settings any more # --- parse command line while [ x`echo $1 | cut -c 1` = x- ] ; do # options from command line and cut off the "-" OPTS=`echo $1 | cut -c 2-` shift 1 while [ x${OPTS} != x ] ; do # first option to process OPT=`echo ${OPTS} | cut -c 1` OPTS=`echo ${OPTS} | cut -c 2-` # creating packages case ${OPT} in g) # generate: generate work directories DO_GEN=yes ;; b) # blank: user wants to set no site package name, delete the default CONF_SITE_PKG='' ;; s) # site: user wants to set custom site package name, overwrite default CONF_SITE_PKG=$1 shift 1 ;; a) # architecture: user wants to set custom architecture type, not "all" SYS_ARCH=$1 shift 1 ;; c) # clone: take/clone content from this existing package DO_CLONE=$1 shift 1 ;; d) # depend: user wants to add an further dependency, extend Depends: line if [ "x${DO_DEPEND}" != x ] ; then DO_DEPEND="${DO_DEPEND}, $1" else DO_DEPEND=$1 fi shift 1 ;; o) # option: user wants to add an option line to control file DO_OPTION=$1 shift 1 ;; r) # remove: remove existing/old .deb files, before making new one DO_REMOVE=yes ;; p) # package: take work directory, and package it DO_PACK=yes ;; l) # level: user wants to set custom debianisation level, not "1" SYS_PKG_LEVEL=$1 shift 1 ;; t) # tidy: delete work directory, leaves only .deb DO_TIDY=yes ;; x) # (e)xpand: expand package back to an work directory # this is not -e expand, because it craches echo in option test DO_EXPAND=yes ;; i) # info: show progress DO_INFO=yes ;; v) # verbose: show progress DEBUG_PRINT_STEP=yes ;; h) # help: give out help how this script can be used cat << EOF Usage is: $0 [options] packagename options: [for creating] -g generate: generate work directories and their content -b blank: no setting of any Depends: used mainly for making site packages, which have no Depends: on an other site package. Usually together with -g as then user modification of DEBIAN/control file is needed, using -d -s sitepackage site: use Depends: on this site package, instead of the default site package: ${CONF_SITE_PKG} -a arch architecture: set architecture to this, default: ${SYS_ARCH} [for cloning] -c oldpackage clone/copy: clone contents from , instead of new * all installable files copied unchanged * postinst and prerm copied unchanged * changelog new, with remark that it was cloned * control copied and package name in it changed if no - in the oldpackage name, expand like packagename if directory of old package prefer that, else unpack .deb [for modifying] -d dependancy depend: extend the Depends: line with this dependancy if there is no Depends: line in control, it will be added this option can be used multiple times, get all added -o optionline option: add this option line to the control file before Maintainer: line (places after Depends:, newer below) or extend existing line of this type, if one is there use this for Predepends:, Conflicts:, Provides:, Recommends: [for packing] -r remove: delete all existing/old .deb files -p pack: pack up the work directories, making .deb file this also generates the actual package version (date) -l level level: set debianisation level, default: ${SYS_PKG_LEVEL} as we we use 8 digit date for version numbers this can be used if multiple versions in one day -t tidy: tidy up, delete work directories [for expanding] -x (e)xpand: take an .deb and make work directories from it this can undo the effect of -t, so long -p was done before -t gotcha: give only package name, not full .deb file name [other stuff] -i info: show information about an .deb package this will not work if there is only an work directory -v verbose: show progress -h help: output this text packagename: something like dphys-site dphys-group- dphys-host- if no - in the name, it is regarded as hostname and expanded to an packagename by prepending ${CONF_HOST_TO_PKG_PREFIX} EOF exit 0 ;; *) # not one of our recognized options echo $0: unknown option at: ${OPT} >&2 echo # call self with -h to display help $0 -h exit 1 ;; esac done done if [ $# != 1 ] ; then # user did not give an parameter (package name), or gave multiple echo $0: missing package name to work on, or multiple given >&2 echo # call self with -h to display help $0 -h exit 1 fi PKG_NAME=$1 if [ x${DEBUG_PRINT_STEP} = xyes ] ; then echo '###' options are: DO_GEN: ${DO_GEN}, DO_CLONE: ${DO_CLONE}, \ DO_EXPAND: ${DO_EXPAND}, DO_DEPEND: ${DO_DEPEND}, \ DO_OPTION: ${DO_OPTION}, DO_PACK: ${DO_PACK}, \ DO_TIDY: ${DO_TIDY}, DO_INFO: ${DO_INFO}, PKG_NAME: ${PKG_NAME} fi # --- extend hostnames to packagenames # no "-" in the given packagename -> is a hostname # ###bug avoidance: the - in the echo part is needed # else cut (at least GNU textutils 2.0) just gives the first field, # instead of an empty line! if [ x`echo ${PKG_NAME}- | cut -f 2 -d "-" ` = x ] ; then # extend an hostname to an packagename PKG_NAME=${CONF_HOST_TO_PKG_PREFIX}${PKG_NAME} fi if [ x${DO_CLONE} != x ] ; then # no "-" in the given clone packagename -> is a clone hostname if [ x`echo ${DO_CLONE}- | cut -f 2 -d "-" ` = x ] ; then # extend an clone hostname to an clone packagename DO_CLONE=${CONF_HOST_TO_PKG_PREFIX}${DO_CLONE} fi fi if [ x${DEBUG_PRINT_STEP} = xyes ] ; then echo '###' expanded names are: PKG_NAME: ${PKG_NAME}, DO_CLONE: ${DO_CLONE} fi # --- make the minimal set of working directories # not inside the "if" because used in multiple places/functions later PKGDIR=${PKG_NAME} DOCDIR=${PKGDIR}/usr/share/doc/${PKG_NAME} DEBDIR=${PKGDIR}/DEBIAN if [ x${DO_GEN} = xyes -o x${DO_CLONE} != x ] ; then mkdir -p ${PKGDIR} mkdir -p ${DOCDIR} mkdir -p ${DEBDIR} if [ x${DEBUG_PRINT_STEP} = xyes ] ; then echo '###' mkdir done ls -ald ${PKGDIR} ${DOCDIR} ${DEBDIR} fi fi # --- if we are cloning, copy all the stuff from existing package if [ x${DO_CLONE} != x ] ; then if [ -d ${DO_CLONE}/DEBIAN ] ; then # do we find an work directory (must be same or newer than a package) CLONE_FULLNAME=${DO_CLONE} # copy clone packages data files into new package tar cf - -C ${CLONE_FULLNAME} --exclude DEBIAN . | tar xpf - -C ${PKGDIR} # copy clone packages control files into new package cp -p ${CLONE_FULLNAME}/DEBIAN/* ${DEBDIR} else # only got an .deb archive, no possibly newer directory, use .deb # find newest version of this package to clone CLONE_FULLNAME=`ls -1d ${DO_CLONE}* | tail -1` # unpack clone packages data files into new package dpkg-deb --extract ${CLONE_FULLNAME} ${PKGDIR} # unpack clone packages control files into new package (cd ${PKGDIR}; dpkg-deb --control ../${CLONE_FULLNAME}) fi # move over documentation to the new directory and lose old directory mv ${PKGDIR}/usr/share/doc/${DO_CLONE}/* ${DOCDIR} rmdir ${PKGDIR}/usr/share/doc/${DO_CLONE} if [ x${DEBUG_PRINT_STEP} = xyes ] ; then echo '###' clone package name is: CLONE_FULLNAME: ${CLONE_FULLNAME} fi fi # --- satisfy the Debian copyright fetishists for this package # cloning takes over the existing copyright, leave unchanged if [ x${DO_GEN} = xyes ] ; then # we just put in our standard copyright echo ${CONF_PKG_COPY} > ${DOCDIR}/copyright if [ x${DEBUG_PRINT_STEP} = xyes ] ; then echo '###' copyright generated ls -al ${DOCDIR}/copyright fi fi # --- make the changelog for this package if [ x${DO_GEN} = xyes -o x${DO_CLONE} != x ] ; then # we mention only one package version, then this package is done # is not strictly true, but simpler so, and sufficient for our purpose # if someone wants more, edit it in the file echo ${CONF_PKG_CHLOG_VERS} > ${DOCDIR}/changelog echo -e ${CONF_PKG_CHLOG_TEXT} >> ${DOCDIR}/changelog if [ x${DO_CLONE} != x ] ; then # can not be an CONF_ up top, because of ${DO_CLONE} not defined then PKG_CHLOG_CLON="\tinitially cloned from ${DO_CLONE}" echo -e ${PKG_CHLOG_CLON} >> ${DOCDIR}/changelog fi echo >> ${DOCDIR}/changelog echo "since:" >> ${DOCDIR}/changelog echo -e "\tnothing" >> ${DOCDIR}/changelog # compress the changelog file, with the newest edits in it # get rid of any existing old compressed version rm -f ${DOCDIR}/changelog.gz # and pack the current one, the --best way that lintian wants to see gzip --best ${DOCDIR}/changelog if [ x${DEBUG_PRINT_STEP} = xyes ] ; then echo '###' changelog generated ls -al ${DOCDIR}/changelog.gz fi fi # --- make the postinst/prerm stuff # this is just the standard linking stuff that everyone needs to repeat # they really should have put this functionality into the actual installer # clone leave this unchanged, as we want the old stuff incl user changes in it if [ x${DO_GEN} = xyes ] ; then cat < ${DEBDIR}/postinst #!/bin/sh set -e # Automatically added by dh_installdocs (actually by makepackage) if [ \$1 = configure ]; then if [ -d /usr/doc -a ! -e /usr/doc/${PKG_NAME} -a -d /usr/share/doc/${PKG_NAME} ]; then ln -sf ../share/doc/${PKG_NAME} /usr/doc/${PKG_NAME} fi fi # End automatically added section EOF cat < ${DEBDIR}/prerm #!/bin/sh set -e # Automatically added by dh_installdocs (actually by makepackage) if [ \$1 = upgrade -o \$1 = remove ]; then if [ -L /usr/doc/${PKG_NAME} ]; then rm -f /usr/doc/${PKG_NAME} fi fi # End automatically added section EOF chmod 755 ${DEBDIR}/postinst ${DEBDIR}/prerm if [ x${DEBUG_PRINT_STEP} = xyes ] ; then echo '###' postinst and prerm scripts made ls -al ${DEBDIR}/postinst ${DEBDIR}/prerm fi fi # --- make the control file for the Packages list if [ x${DO_GEN} = xyes ] ; then # this control file may need user editing/extending later on # such as adding Depends:, or other such control lines # that is the reason for splitting into generate/pack/tidy functions echo "Package: ${PKG_NAME}" > ${DEBDIR}/control echo "Version: +++ set later when packaging +++" \ >> ${DEBDIR}/control echo "Section: misc" >> ${DEBDIR}/control echo "Priority: optional" >> ${DEBDIR}/control echo "Architecture: ${SYS_ARCH}" >> ${DEBDIR}/control if [ x${CONF_SITE_PKG} != x ] ; then echo "Depends: ${CONF_SITE_PKG}" >> ${DEBDIR}/control fi echo "Maintainer: ${CONF_PKG_MAINTAINER}" \ >> ${DEBDIR}/control echo "Description:" ${CONF_DESC_SH} >> ${DEBDIR}/control # empty string, as there is an space put in after it, by echo echo "" ${CONF_DESC_1} >> ${DEBDIR}/control echo "" ${CONF_DESC_2} >> ${DEBDIR}/control echo "" ${CONF_DESC_3} >> ${DEBDIR}/control if [ x${DEBUG_PRINT_STEP} = xyes ] ; then echo '###' control file generated ls -al ${DEBDIR}/control fi fi # --- modify control file from existing package if [ x${DO_CLONE} != x ] ; then # fix up the control file withr this packages name sed -e "/^Package:/s/.*/Package: ${PKG_NAME}/" ${DEBDIR}/control > \ ${DEBDIR}/.control mv ${DEBDIR}/.control ${DEBDIR}/control if [ x${DEBUG_PRINT_STEP} = xyes ] ; then echo '###' control file modified ls -al ${DEBDIR}/control fi fi # --- expand existing package back to an work directory if [ x${DO_EXPAND} != x ] ; then # do this before all modifying options, so that they can be applied in one go # allows -x -d something -p -t to add an Depends: to an package # find newest version of this package to clone PKG_FULLNAME=`ls -1d ${PKG_NAME}* | tail -1` # expand packages data files into new package dpkg-deb --extract ${PKG_FULLNAME} ${PKGDIR} # expand packages control files into new package (cd ${PKGDIR}; dpkg-deb --control ../${PKG_FULLNAME}) if [ x${DEBUG_PRINT_STEP} = xyes ] ; then echo '###' extracted package name is: PKG_FULLNAME: ${PKG_FULLNAME} fi fi # --- add an dependency if [ "x${DO_DEPEND}" != x ] ; then if [ `grep -c '^Depends: ' ${DEBDIR}/control` != 0 ] ; then # extend Depends: line with one or multiple dependencies # sed substitute line end = extend line sed -e "/^Depends: /s/$/, ${DO_DEPEND}/" ${DEBDIR}/control > \ ${DEBDIR}/.control mv ${DEBDIR}/.control ${DEBDIR}/control if [ x${DEBUG_PRINT_STEP} = xyes ] ; then echo '###' control Depends: line extended grep '^Depends: ' ${DEBDIR}/control fi else # add Depends: line to control file, with one or multiple dependencies sed -e "/^Maintainer: /i\\ Depends: ${DO_DEPEND}" ${DEBDIR}/control > ${DEBDIR}/.control mv ${DEBDIR}/.control ${DEBDIR}/control if [ x${DEBUG_PRINT_STEP} = xyes ] ; then echo '###' control Depends: line added grep '^Depends: ' ${DEBDIR}/control fi fi fi # --- add an option line if [ "x${DO_OPTION}" != x ] ; then OPTION=`echo ${DO_OPTION} | cut -f 1 -d " "` VALUE=`echo ${DO_OPTION} | cut -f 2- -d " " ` if [ `grep -c "^${OPTION} " ${DEBDIR}/control` != 0 ] ; then # extend option line with an element sed -e "/^${OPTION} /s/$/, ${VALUE}/" ${DEBDIR}/control > \ ${DEBDIR}/.control mv ${DEBDIR}/.control ${DEBDIR}/control if [ x${DEBUG_PRINT_STEP} = xyes ] ; then echo '###' control option line extended grep "^${OPTION} " ${DEBDIR}/control fi else # add option line to control file with an element sed -e "/^Maintainer: /i\\ ${DO_OPTION}" ${DEBDIR}/control > ${DEBDIR}/.control mv ${DEBDIR}/.control ${DEBDIR}/control if [ x${DEBUG_PRINT_STEP} = xyes ] ; then echo '###' control option line added grep "^${OPTION} " ${DEBDIR}/control fi fi fi # --- remove all .deb archives of an package # do this before -p in case someone is using -rp to clean and then pack newly if [ x${DO_REMOVE} != x ] ; then # find all versions of this package PKG_FULLNAME=`ls -1d ${PKG_NAME}* | tail -1` # and remove them rm ${PKG_FULLNAME} if [ x${DEBUG_PRINT_STEP} = xyes ] ; then echo '###' removed package name is: PKG_FULLNAME: ${PKG_FULLNAME} fi fi # --- compute package version if [ x${DO_PACK} = xyes ] ; then # we base our versions on the current date DATE_NUM=`date +%Y%m%d.%H%M%S` DATE_ISO=`date +%Y-%m-%d` PKG_VERSION=${DATE_NUM} PKG_DEBVERS=${PKG_VERSION}-${SYS_PKG_LEVEL} PKG_FILENAME=${PKG_NAME}_${PKG_DEBVERS}_${SYS_ARCH}.deb if [ x${DEBUG_PRINT_STEP} = xyes ] ; then echo '###' package file is: ${PKG_FILENAME} fi fi # --- fix up control file for this package and level if [ x${DO_PACK} = xyes ] ; then # fix up the control file for this packages version being packaged sed -e "/^Version:/s/.*/Version: ${PKG_DEBVERS}/" ${DEBDIR}/control > \ ${DEBDIR}/.control mv ${DEBDIR}/.control ${DEBDIR}/control fi # --- make the changelog.Debian for this package and level if [ x${DO_PACK} = xyes ] ; then # when packaging, debianise this version with date from now # this is usually only one level, as starting from 1 per version # can be changed with -l, patch for making multiple releases in one day echo "${PKG_NAME} (${PKG_DEBVERS}) stable; urgency=high" \ > ${DOCDIR}/changelog.Debian echo >> ${DOCDIR}/changelog.Debian echo " * auto-generated release from versionless (=current) upstream" \ >> ${DOCDIR}/changelog.Debian echo >> ${DOCDIR}/changelog.Debian echo " -- ${CONF_PKG_MAINTAINER} ${DATE_ISO}" \ >> ${DOCDIR}/changelog.Debian # get rid of any possible existing old compressed version rm -f ${DOCDIR}/changelog.Debian.gz # and pack the current one, the --best way that lintian wants to see gzip --best ${DOCDIR}/changelog.Debian if [ x${DEBUG_PRINT_STEP} = xyes ] ; then echo '###' Debian changelog generated ls -al ${DOCDIR}/changelog.Debian.gz fi fi # --- make the .deb package file and check it for errors if [ x${DO_PACK} = xyes ] ; then # save and eliminate CVS stuff SAVE_TAR=.tmp-makepackage-$$-save.tar if [ -f ${SAVE_TAR} ] ; then rm ${SAVE_TAR} fi if [ -d ${PKGDIR}/CVS ] ; then tar cf ${SAVE_TAR} ${PKGDIR} find ${PKGDIR} -name CVS -exec rm -rf {} \; 2> /dev/null fi # then do the actual .deb stuff fakeroot dpkg-deb --build ${PKGDIR} . # restore CVS stuff if [ -f ${SAVE_TAR} ] ; then tar xpf ${SAVE_TAR} rm ${SAVE_TAR} fi # and run a test over it, to get more error messages lintian ${PKG_FILENAME} if [ x${DEBUG_PRINT_STEP} = xyes ] ; then echo '###' .deb package generated ls -al ${PKG_FILENAME} fi fi # --- delete temporary work directory if [ x${DO_TIDY} = xyes ] ; then rm -rf ${PKGDIR} if [ x${DEBUG_PRINT_STEP} = xyes ] ; then echo '###' work directory deleted for ${PKGDIR} fi fi # --- information on package if [ x${DO_INFO} = xyes ] ; then # find newest version of this package to inform on PKG_FULLNAME=`ls -1d ${PKG_NAME}* | tail -1` # print out packages info dpkg-deb --info ${PKG_FULLNAME} if [ x${DEBUG_PRINT_STEP} = xyes ] ; then echo '###' information given for ${PKGDIR} fi fi # that's all folks!