#!/bin/sh
################################################
#
# This script generates an "apt-get"-able package.
# The package is empty and has a dependency for
# everything that's on the machine.
#
# Only include packages that are both installed
# and available from the apt sources. Do not
# include anything from Priority: required
#
################################################

set -e

BOX=`hostname --fqdn | tr '[:upper:]' '[:lower:]'`
ARCH=`dpkg-architecture -qDEB_BUILD_ARCH`
VER=`date +%Y%m%d`
HUMANDATE=`date +%m/%d/%Y`
PKGNAME=`echo jablicate-${BOX} | sed 's/\\./-/g'`
PKGDIR=${PKGNAME}-${VER}
LETTER=`echo ${PKGNAME} | cut -b-1`
DISTRO=debian-custom
DEB=${PKGNAME}_${VER}_all.deb
POOLDIR=pool/contrib/${LETTER}/${PKGNAME}
SRCDIR=dists/${DISTRO}/contrib/source
DISTDIR=dists/${DISTRO}/contrib/binary-${ARCH}

#######################################
#                                     #
# Basic program flow                  #
#                                     #
#######################################

# Handle command line arguments
parse_command_line() {
    while test $# -gt 0; do
	case "$1" in
             -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
             *) optarg= ;;
        esac

        case $1 in 
        --root)         ROOT=$2 
                        shift
                        ;;
        *)              echo "Usage: jablicator [--root <path>]"
                        exit 1 ;;
        esac
        shift
    done
}

# Guess at maintainer email
set_bang_maintainer() {
    FIRST_PART=${USER}
    SECOND_PART=`hostname --domain`
    if [ "$SECOND_PART" = "" ]
    then
        SECOND_PART=`hostname`
    fi
    MAINTAINER="Collection Maintainer <${FIRST_PART}@${SECOND_PART}>"   
}

# Make sure system is not completely broken
sanity_check() {
    if [ "`hostname --fqdn`" = "" ]
    then
        echo "Error: hostname command is failing."
        exit
    fi
}

clean () 
{
    rm -rf ${PKGDIR}
    rm -f ${PKGNAME}_${VER}_${ARCH}.build
}

#######################################
#                                     #
# Figure out the dependencies         #
#                                     #
#######################################

# Record apt-get sources
sources ()
{
    cat $ROOT/etc/apt/sources.list | sed 's/\#.*$//g' | grep deb
}

# Packages that are installed
install_list ()
{
    # It has been suggested that dpkg --getselections may be better than 
    # grepping through files with grep-dctrl. I haven't yet investigated 
    # this in detail, but I think grep-dctrl is at the right abstraction
    # level.
    grep-dctrl -v --field Priority required  --exact-match \
        $ROOT/var/lib/dpkg/status |\
        grep-dctrl    --field Status "install ok installed" --exact-match |\
        grep-dctrl -v --field Package xfonts \
        --no-field-names --show-field $1
}

# Packages available from apt sources
available_list () 
{
    # Very annoying workaround for Debian bug #234657; I want to say -r .
    grep-dctrl --no-field-names --show-field Package . \
        $ROOT/var/lib/apt/lists/*Packages | sort -u
}

# Packages installed + packages available
monster_list () 
{
    install_list "Package"
    available_list
}

# Golden list of packages
list () 
{
    monster_list | sort | uniq --repeated | grep -v ${PKGNAME} | sed 's/$/,/g'
}

#######################################
#                                     #
# Creating the Debian package         #
#                                     #
#######################################

control () 
{
    PACKAGES=`list`
    echo Source: ${PKGNAME}
    echo Section: admin
    echo Priority: optional
    echo "Maintainer: ${MAINTAINER}"
    echo "Build-Depends: debhelper (>> 3.0.0)"
    echo Standards-Version: 3.8.0
    echo
    echo Package: ${PKGNAME}
    echo Architecture: all
    echo Depends: ${PACKAGES}
    echo Description: Replicate software collection on ${BOX}
    echo " Replicate the software collection from ${BOX}"
    echo " A software collection is simply the group of packages"
    echo " installed on a particular machine."
    echo " ."
    echo " This package contains dependencies that may be "
    echo " fulfilled from the following sources. Check to see if "
    echo " they are present in your /etc/apt/sources.list."
    echo " ."
    sources | sed 's/^/ /g'
}

changelog ()
{
    DATE=`date -R`
    echo "${PKGNAME} (${VER}) unstable; urgency=low"
    echo
    echo "  * This package was generated by a computer progam which"
    echo "    does not keep track of historical data."
    echo 
    echo " -- ${MAINTAINER}  ${DATE}"
}

copyright ()
{
    echo This package contains a list of the debian software that 
    echo was on ${BOX} on ${DATE}.  
    echo
    echo You are welcome to call an army of lawyers and philosphers 
    echo to decide on the exact copyright status and/or ownership
    echo of this package. If I had to guess, this package is just 
    echo a collection of facts and therefore public domain.
    echo
    echo This package in no way affects the copyright status of 
    echo its dependencies.

}

rules () 
{
    echo "#!/usr/bin/make -f"
    echo ""
    echo "configure: configure-stamp"
    echo "configure-stamp:"
    echo "	dh_testdir"
    echo "	touch configure-stamp"
    echo ""
    echo "build: configure-stamp build-stamp"
    echo "build-stamp:"
    echo "	dh_testdir"
    echo "	touch build-stamp"
    echo ""
    echo "clean:"
    echo "	dh_testdir"
    echo "	dh_testroot"
    echo "	rm -f build-stamp configure-stamp"
    echo "	dh_clean"
    echo ""
    echo "install: build"
    echo "	dh_testdir"
    echo "	dh_testroot"
    echo "	dh_clean -k"
    echo "	dh_installdirs"
    echo ""
    echo "binary-arch:"
    echo ""
    echo "binary-indep: build install"
    echo "	dh_testdir -i"
    echo "	dh_testroot -i"
    echo "	dh_installdocs -i"
    echo "	dh_installchangelogs -i"
    echo "	dh_link -i"
    echo "	dh_compress -i"
    echo "	dh_fixperms -i"
    echo "	dh_installdeb -i"
    echo "	dh_shlibdeps -i"
    echo "	dh_gencontrol -i"
    echo "	dh_md5sums -i"
    echo "	dh_builddeb -i"
    echo ""
    echo "binary: binary-indep"
    echo ".PHONY: build clean binary-indep binary install configure"
    echo ""
}

build_package()
{
    mkdir -p ${PKGDIR}/debian
    control > ${PKGDIR}/debian/control
    control
    changelog > ${PKGDIR}/debian/changelog
    copyright > ${PKGDIR}/debian/copyright
    rules > ${PKGDIR}/debian/rules
    echo 4 > ${PKGDIR}/debian/compat
    chmod +x ${PKGDIR}/debian/rules

    cd ${PKGDIR}
    debuild -us -uc
    if [ "$?" != 0 ]
    then
	echo "Aborting due to error."
	exit
    fi
    cd -
}

#######################################
#                                     #
# Apt-get publication functions       #
#                                     #
#######################################

serve ()
{
    mkdir -p ${DISTDIR}
    mkdir -p ${SRCDIR}
    mkdir -p ${POOLDIR}
    mv ${DEB} ${POOLDIR}
    mv ${PKGNAME}_${VER}.dsc ${POOLDIR}
    mv ${PKGNAME}_${VER}.tar.gz ${POOLDIR}
    mv ${PKGNAME}_${VER}_${ARCH}.changes ${POOLDIR}
    dpkg-scanpackages pool /dev/null | gzip -9c > ${DISTDIR}/Packages.gz
    dpkg-scansources  pool /dev/null | gzip -9c > ${SRCDIR}/Sources.gz 
}

instructions () 
{
    echo
    echo " ===============  SUCCESS ==================="
    echo
    echo "First, read the man page for security implications. If you wish to share" 
    echo "your software collection, copy the newly created dists and pool directories "
    echo "to a web accessable location. Others may then replicate your software"
    echo "collection by adding the following line to their /etc/apt/sources.list:"
    echo
    echo "  deb http://<WEB LOCATION> ${DISTRO} contrib"
    echo
    echo "For example, if you are running a webserver on this machine you could "
    echo "copy the directories to /var/www/dists and /var/www/pool. Then people could "
    echo "access it via the following line in /etc/apt/sources.list:"
    echo
    echo "  deb http://${BOX} ${DISTRO} contrib"
    echo
    echo "Your followers can then use their favorite apt front end, for example:"
    echo
    echo "  apt-get update && apt-get install ${PKGNAME}"
    echo
}


#######################################
#                                     #
#         ACTION                      #
#                                     #
#######################################

set_bang_maintainer
parse_command_line $@
sanity_check
build_package
serve
clean
instructions
