#!/bin/bash -x
#
# @file
# @brief Creates a Stage4 Image of the Current System (/) or the Specified Directory
#
# @see http://en.gentoo-wiki.com/wiki/Custom_Stage4
#

set -o errexit

st4_source="/"
st4_target="/stage4.tbz"

st4_imgdir=$(mktemp -d -u)
st4_except=$(mktemp)

st4_base=/opt/stage4/_st4_base
st4_boot=
st4_copy=/mnt/stage4/
st4_dont=
st4_file=/stage4.tgz
st4_home=

#
# Make a list of things to exclude
#
function make_exclude_list()
{
    # Don't creates a list of files that should not be included in the archive
    echo "Generating exclusion list..."
    
    if [ -n "$st4_dont" ]; then
        if [ -f "$st4_dont" ]; then
            cat "$st4_dont"
        else
            echo "$st4_dont"
        fi
    fi

    echo '.*history'
    echo '.cache'
    echo '.ccache'
    echo '.cpan'
    echo '.distcc'
    echo '.gconf'
    echo '.gnupg'
    echo '.lesshst'
    echo '.ncftp'
    echo '.revdep*'
    echo '.spamassassin'
    echo '.ssh'
    echo '.ssl'
    echo '.subversion'
    echo '.xchat2'
    echo '/dev/*'
    echo '/etc/ssh/ssh_host_*'
    # don't take changes to home, those have to be manual
    echo '/home/*'
    echo '/proc/*'
    # don't take changes to root, those have to be manual
    echo '/sys/*'
    echo '/tmp/*'
    echo '/usr/portage/*'
    echo '/var/cache/edb/*'
    echo '/var/cache/fontconfig/*'
    echo '/var/cache/genkernel/*'
    echo '/var/lock/*'
    echo '/var/run/*'
    echo '/var/tmp/*'

    # @todo allow optional additional exclude file to be appended?

    # Hardcoded Values
    echo '/dev/*'
    echo '/lost+found/*'
    echo '/tmp/*'
    echo '/usr/portage/*'
    echo '/usr/src/*'
    echo '/var/cache/edb/*'
    echo '/var/cache/fontconfig/*'
    echo '/var/cache/genkernel/*'
    echo '/var/lock/*'
    echo '/var/run/*'
    echo '/var/tmp/*'

    if [ -z "$st4_home" ]; then
        echo '/home/*'
    fi

    (
        echo "Checking /etc" 1>&2
        find $st4_source/etc -type f -name 'ssh_host*'

        # @todo should exclude shadow and passwd and group and require in overlay?

        echo "Checking /root" 1>&2
        (cd $st4_source/; find ./root -maxdepth 1 -type d -name '.*')
        (cd $st4_source/; find ./root -maxdepth 1 -type f -name '.*')

        # exclude /var/cache/ files?
        echo "Checking /var/cache/" 1>&2
        (cd $st4_source/; find ./var/cache -xdev -type f | sed 's/^\.\///')

        # exclude /var/log/ files?
        echo "Checking /var/lock" 1>&2
        (cd $st4_source/; find ./var/lock -xdev -type f | sed 's/^\.\///')

        echo "Checking /var/log" 1>&2
        (cd $st4_source/; find ./var/log -xdev -type f | sed 's/^\.\///')

        # exclude /var/run files
        echo "Checking /var/run" 1>&2
        (cd $st4_source/; find ./var/run -xdev -type f | sed 's/^\.\///')

    ) | sed 's/^\/\//\//'

}

#
# Does a double rsync to clone the existing system
#
function copy_source_image()
{
    echo "Creating Copy of $st4_source to $st4_imgdir"

    # First Pass
    rsync \
        --archive \
        --delete \
        --exclude-from=$st4_except \
        --one-file-system \
        --verbose \
        $st4_source/ \
        $st4_imgdir/

    # Second Pass
    rsync \
        --archive \
        --delete \
        --exclude-from=$st4_except \
        --one-file-system \
        --verbose \
        $st4_source/ \
        $st4_imgdir/

}

function pack_target_image()
{
    # Merging Stuff?
    # if [ -d $st4_base ]; then
    #     rsync --archive --one-file-system  --verbose $st4_base/ $st4_copy/
    # fi

    tar \
        --create \
        --bzip2 \
        --one-file-system \
        --verbose \
        --exclude-from $st4_except \
        --ignore-failed-read \
        --sparse \
        --totals \
        --wildcards \
        --directory $st4_imgdir/ \
        --file $st4_target \
        .

}


# Read Options
for opt in $@
do
    case "${opt}" in
    +base\=*)
        st4_base=$(echo "${opt}"|cut -d= -f2)
        echo "set st4_base = $st4_base" 1>&2
        ;;
    +boot\=*)
        st4_boot=$(echo "${opt}"|cut -d= -f2)
        echo "set st4_boot = $st4_boot" 1>&2
        ;;
    +copy\=*)
        st4_copy=$(echo "${opt}"|cut -d= -f2)
        echo "set st4_copy = $st4_copy" 1>&2
        ;;
    +dont\=*)
        st4_dont=$(echo "${opt}"|cut -d= -f2)
        echo "set st4_dont = $st4_dont" 1>&2
        ;;
    +file\=*)
        st4_file=$(echo "${opt}"|cut -d= -f2)
        echo "set st4_file = $st4_file" 1>&2
        ;;
    +home\=*)
        st4_home=$(echo "${opt}"|cut -d= -f2)
        echo "set st4_home = $st4_home" 1>&2
        ;;
    +root\=*)
        st4_root=$(echo "${opt}"|cut -d= -f2)
        echo "set st4_root = $st4_root" 1>&2
        ;;
    update)
        x=$(mktemp)
        curl -qs http://stage4.org/bin/stage4.sh > $x
        mv "$x" "$0"
        chmod 0700 "$0"
        echo "Update Success"
        exit
        ;;
    *)
        echo "Command '$cmd' not understood"
        ;;
    esac
done

make_exclude_list > $st4_except
copy_source_image
pack_target_image

# wipe_temp_stuff
# rm -fr $st4_except
# rm -fr $st4_imgdir

echo "Image in $st4_target created from $st4_source"
echo "Staging Image in $st4_imgdir"
echo "Exception List: $st4_except"

