#!/bin/bash

set -e

# DEFAULT VALUES
#Live Build Astra directory
LBA="/usr/share/live-build-astra"
HOOKS_DIR="${LBA}/hooks"
INCLUDES_CHROOT_DIR="${LBA}/includes.chroot"
INCLUDES_BINARY_DIR="${LBA}/includes.binary"
COMPONENTS="main contrib non-free"
TASKS="Base Fly Internet Multimedia Office"
ARCHITECTURE="amd64"
BUILD_DIR="build"
GENERATE_ISO="false"
GENERATE_TAR="false"
GENERATE_IMG="false"
PARTITION_SCRIPT_NAME="${LBA}/partition.script"

USAGE=$(cat <<EOF
Live CD builder
Usage: live-build-astra [OPTIONS]

OPTIONS
     -h|--help display this help and exit
     -o|--output <filename> set output ISO filename
     -D|--distribution <distribution> create liveCD of given distribution
     -T|--tasks  Set tasksel tasks to complete in liveCD
     -P|--packages-list <filename> file with list of packages to be installed in system
     -p|--additional-packages <list> list of additional packages to install
     -e|--exclude-packages <list> list of packages to be excluded from any package lists. But they still could be installed as dependency resolutions.
     -b|--build-directory <dirname> build in given directory
     -c|--clean-before clean build directory before build
     -C|--clean-after clean build directory after build
     -k|--hooks <dirname> do not use default hooks, but use hook in given directory
     -l|--includes-binary <dirname> do not use default set of files included in iso, but given
     -m|--includes-chroot <dirname> do not use default set of files included in filesystem, but given
     -t|--tarball <filename> build root FS tarball named <filename>
     -i|--image <filename> generate SD card image
     -q|--partition-script <filename> Image partitioning description
     -s|--source-iso <filename> ISO image to use as a source of packages and other stuff
     -r|--repositories <URL> Repositories URL semicolon (;) separated
     -a|--arch <ARCHITECTURE> Target CPU architecture

Example: live-build-astra -o smolensk.iso -i smolensk.img -t smolensk.tar.xz -D smolensk -s "smolensk-current.iso;devel-smolensk-current.iso"
EOF
)

usage () {
    echo "${USAGE}"
}

current_distribution () {
    # If something goes wrong return default value.
    result="${DISTRIBUTION}"
    if [ -e /etc/os-release ]; then
        grep -qE 'VARIANT=.+' /etc/os-release && \
            result=$(grep 'VARIANT=' /etc/os-release | sed 's/VARIANT=//')
    fi
    echo ${DISTRIBUTION}
}

mount_source_iso () {
    local iso=$1
    local mount_point=$2

    if [ -e $mount_point ]; then
        #Check if mount_point is directory and is empty.
        if [ -d $mount_point ] && ! [ "$(ls -A $mount_point)" ]; then
            mount -o loop $iso $mount_point 2>&1 >/dev/null
        else
            echo "--source-iso mount point ${mount_point} is not empty directory." >&2
            exit 6
        fi
    else
        #If there is no mount_point -- create it.
        mkdir -p $mount_point
        mount -o loop $iso $mount_point 2>&1 >/dev/null
    fi
}

umount_source_iso () {
    local mount_point=$1
    umount $mount_point
}

main_repository() {
    local repos=${1}
    echo $repos | sed 's/;.*//'
}

check_qemu () {
    local arch
    if [ ${ARCHITECTURE} = "armhf" ]; then
        arch="arm"
    else
        arch=${ARCHITECTURE}
    fi

    if ! which qemu-${arch}-static ; then
        echo "You need qemu-${arch}-static in your system to make ${arch} images." 1>&2
        echo "Try installing apt-get qemu-user-static" 1>&2
        exit 1
    fi
}

apt_cache_show_filename() {
    local pkgname=$1
    echo ${COMPONENTS} | tr ' ' '\n' | while read component; do
        grep -m 1 -A 20 "^Package: ${pkgname}$" Packages.${component} | grep -m 1 "^Filename: " | sed 's/Filename: //'
    done
}

get_tasksel-data_package() {
    local filepath=$(apt_cache_show_filename "tasksel-data")
    if echo "$REPOSITORY" | grep -q '^file:' ; then
        cp ${REPO_PATH}/${filepath} ./tasksel-data.deb
    else
        wget -nv ${REPOSITORY}/${filepath} -O ./tasksel-data.deb
    fi
}

unpack_tasksel-data_package() {
    mkdir -p ./tasksel-data
    dpkg -x tasksel-data.deb ./tasksel-data/
}

get_task_package_lists() {
    local taskname
    local is_package_name="false"

    sed '/^\s*$/d' ./tasksel-data/usr/share/tasksel/debian-tasks.desc | while IFS= read line; do
        if echo "$line" | grep -q ": "; then
            is_package_name="false"
            if echo "$line" | grep -q "Task: "; then
                taskname=$(echo $line | sed 's/Task: //')
            fi
            if echo "$line" | grep -q "Packages: "; then
                is_package_name="true"
            fi
        elif [ "${is_package_name}" = "true" ]; then
            echo  "$line" | sed 's/^  //' >> ./tasksel-data/${taskname}
        fi
    done
}

get_cut_dirs_num()
{
    repo_path=${1}
    echo $(($(echo ${repo_path} | sed 's/\// /g' | wc -w) - 2))
}

generate_info_file()
{
    distrib_name=`grep 'VARIANT_ID' ${BUILD_DIR}/chroot/etc/os-release | sed 's/^VARIANT_ID=//'`
    distrib_version=`grep 'VERSION_ID' ${BUILD_DIR}/chroot/etc/os-release | sed 's/^VERSION_ID=//'`
    echo "Building date: $(LC_ALL=C date)" > ${BUILD_DIR}/binary/${distrib_name}-${distrib_version}.info
}

fix_booloader_configs()
{
    local distrib=${1}
    sed "s/DISTRIBUTION/${distrib}/g" -i ${BUILD_DIR}/binary/boot/grub/grub.cfg
    sed "s/DISTRIBUTION/${distrib}/g" -i ${BUILD_DIR}/binary/isolinux/menu.cfg
}

get_sd_card_size()
{
    local source_dir=${1}
    local result="1048576" # Start from 1 Gb
    local free_space="110000" # About 100 Mb
    while [[ $(($(du -s ${source_dir} | sed 's/\t.*//') + free_space)) -gt "${result}" ]];
    do
        result=$((result * 2))
    done
    echo $result
}

# In 512b sectors
get_image_size () {
    local partition_script=`mktemp`
    sed 's/#.*//' $PARTITION_SCRIPT_NAME | sed 's/\s+/ /g' | sed '/^\s*$/d' > ${partition_script}

    prev_part_end="1" # One sector for partition table
    extended_count="false"
    while read line; do
        local first_word=`echo ${line} | cut -d " " -f 1`
        local second_word=`echo ${line} | cut -d " " -f 2`
        local third_word=`echo ${line} | cut -d " " -f 3`

        if [ "$first_word" = "offset" ]; then
            part_size=$((second_word * 2))
            part_end=$((prev_part_end + part_size))
        else
            if [ "$second_word" = "ROOTFS" ]; then
                part_size=$(($(get_ROOTFS_size) * 2048))
            else
                part_size=$((second_word * 2048))
            fi
            part_end=$((prev_part_end + part_size))
            if [ "$first_word" = "logical" ]; then
                # Additional sector for extened partition table
                part_end=$((part_end + 1))
                extended_count="true"
            fi
        fi
        prev_part_end=$part_end
    done < <(tail -n +2 $partition_script)
    echo $prev_part_end
}

# ext4 partition size in megabytes
get_ROOTFS_size ()
{
    size=$(($(du -s ${BUILD_DIR}/chroot | sed 's/\s.*//') / 890))
    echo $size
}

create_image()
{
    local size_in_mb=$(($(get_image_size)/2048))
    if [ $((size_in_mb * 2048)) -ne $(get_image_size) ]; then
        size_in_mb=$((size_in_mb + 1))
    fi
    dd if=/dev/zero of=${IMG_NAME} bs=1M count=${size_in_mb}
}

partition_image()
{
    local partition_script=`mktemp`
    sed 's/#.*//' $PARTITION_SCRIPT_NAME | sed 's/\s+/ /g' | sed '/^\s*$/d' > ${partition_script}

    parted ${IMG_NAME} --script mklabel msdos
    local extended_created="false"
    prev_part_end="1"
    while read line; do
        local first_word=`echo ${line} | cut -d " " -f 1`
        local second_word=`echo ${line} | cut -d " " -f 2`
        local third_word=`echo ${line} | cut -d " " -f 3`
        local fourth_word=`echo ${line} | cut -d " " -f 4`

        if [ "$first_word" = "offset" ]; then
            part_size=$((second_word * 2))
            part_end=$((prev_part_end + part_size))
        else
            if [ "$first_word" = "logical" ] && [ "$extended_created" = "false" ]; then
                parted ${IMG_NAME} --script "mkpart extended $((prev_part_end + 1))s -1s"
                prev_part_end=$((prev_part_end + 1))
                extended_created="true"
            fi
            if [ "$first_word" = "logical" ]; then
                # Additional sector for extened partition table
                prev_part_end=$((prev_part_end + 1))
            fi
            if [ "$second_word" = "ROOTFS" ]; then
                part_size=$(($(get_ROOTFS_size) * 2048))
            else
                part_size=$((second_word * 2048))
            fi
            part_end=$((prev_part_end + part_size))
            if [ "$third_word" = "ROOTFS" ]; then
                script="mkpart ${first_word} ${fourth_word}"
            else
                script="mkpart ${first_word} ${third_word}"
            fi
            parted ${IMG_NAME} --script ${script} $((prev_part_end + 1))s ${part_end}s
        fi
        prev_part_end=$part_end
    done < <(tail -n +2 $partition_script)
    rm ${partition_script}
}

mkfs_image() {
    local partition_script=`mktemp`
    sed 's/#.*//' $PARTITION_SCRIPT_NAME | sed 's/\s+/ /g' | sed '/^\s*$/d' > ${partition_script}

    local primary_counter="1"
    local logical_counter="5"
    local loop_device=`kpartx -av ${IMG_NAME} | head -n 1 | cut -d " " -f 8 | sed 's/dev/dev\/mapper/'`
    while read line; do
        local first_word=`echo ${line} | cut -d " " -f 1`
        local second_word=`echo ${line} | cut -d " " -f 2`
        local third_word=`echo ${line} | cut -d " " -f 3`
        local fourth_word=`echo ${line} | cut -d " " -f 4`

        if [ "$first_word" = "primary" ]; then
            local loop_partition="${loop_device}p${primary_counter}"
            primary_counter=$((primary_counter + 1))
        elif [ "$first_word" = "logical" ]; then
            local loop_partition="${loop_device}p${logical_counter}"
            logical_counter=$((logical_counter + 1))
        fi

        if [ "$third_word" = "ROOTFS" ]; then
            third_word=${fourth_word}
        fi
        local mkfs_command=""
        if [ "$third_word" = "ext2" ]; then
            mkfs_command="mkfs.ext2"
        elif [ "$third_word" = "ext3" ]; then
            mkfs_command="mkfs.ext3"
        elif [ "$third_word" = "ext4" ]; then
            mkfs_command="mkfs.ext4"
        elif [ "$third_word" = "fat12" ]; then
            mkfs_command="mkdosfs -F 12"
        elif [ "$third_word" = "fat16" ]; then
            mkfs_command="mkdosfs -F 16"
        elif [ "$third_word" = "fat32" ]; then
            mkfs_command="mkdosfs -F 32"
        fi
        eval "${mkfs_command} ${loop_partition}"
    done < <(tail -n +2 $partition_script)
    rm ${partition_script}
    kpartx -d ${IMG_NAME}
}

copy_data_to_image()
{
    local partition_script=`mktemp`
    sed 's/#.*//' $PARTITION_SCRIPT_NAME | sed 's/\s+/ /g' | sed '/^\s*$/d' > ${partition_script}
    local mountpoint=`mktemp -d`
    local primary_counter="1"
    local logical_counter="5"
    local loop_device=`kpartx -av ${IMG_NAME} | head -n 1 | cut -d " " -f 8 | sed 's/dev/dev\/mapper/'`
    while read line; do
        local first_word=`echo ${line} | cut -d " " -f 1`
        local second_word=`echo ${line} | cut -d " " -f 2`
        local third_word=`echo ${line} | cut -d " " -f 3`
        local fourth_word=`echo ${line} | cut -d " " -f 4`

        if [ "$first_word" = "primary" ]; then
            local loop_partition="${loop_device}p${primary_counter}"
            primary_counter=$((primary_counter + 1))
        elif [ "$first_word" = "logical" ]; then
            local loop_partition="${loop_device}p${logical_counter}"
            logical_counter=$((logical_counter + 1))
        fi

        echo "$line" | grep -q "ROOTFS" && mount ${loop_partition} ${mountpoint} && tar -xaf ${TAR_NAME} -C ${mountpoint}/ && umount ${mountpoint}

    done < <(tail -n +2 $partition_script)

    rm ${partition_script}
    rmdir ${mountpoint}
    kpartx -d ${IMG_NAME}
}

create_vmlinuz_links()
{
    local vmlinuz_path=`basename $(ls ${BUILD_DIR}/chroot/boot/vmlinuz-* | head -n 1)`
    local initrd_path=`basename $(ls ${BUILD_DIR}/chroot/boot/initrd.img-* | head -n 1)`
    ln -s ${vmlinuz_path} ${BUILD_DIR}/chroot/boot/vmlinuz
    ln -s ${initrd_path} ${BUILD_DIR}/chroot/boot/initrd.img
}

place_chroot_scripts()
{
    local arch
    if [ ${ARCHITECTURE} = "armhf" ]; then
        arch="arm"
    else
        arch=${ARCHITECTURE}
    fi

    cp ${LBA}/goto_chroot.sh ${BUILD_DIR}/
    cp `which qemu-${arch}-static` ${BUILD_DIR}/chroot/usr/bin
}
# SCRIPT STARTS HERE. No function declarations below.

DISTRIBUTION=$(current_distribution)
PROGRAM="live-build-astra"
LONG_OPTIONS="help,output:,distribution:,tasks:,packages-list:,additional-packages:,exclude-packages:,build-directory:,clean-before,clean-after,hooks:,includes-binary:,includes-chroot:,tarball:,image:,partition-script:,source-iso:,repositories:,arch:"
LONG_OPTIONS="$(echo ${LONG_OPTIONS} | tr -d ' ')"
ARGUMENTS="$(getopt --longoptions ${LONG_OPTIONS} --name="${PROGRAM}" --options ho:D:T:P:p:e:b:cCk:l:m:t:i:q:s:r:a: --shell sh -- "${@}")"

if [ "${?}" != "0" ]; then
    echo "You must pass some arguments. --help at least." >&2
    exit 1
fi

eval set -- "${ARGUMENTS}"

while true; do
    case "${1}" in
        -h|--help)
            usage
            exit 0
            ;;
        -o|--output)
            GENERATE_ISO="true"
            OUTPUT_FILE="${2}"
            shift 2
            ;;
        -D|--distribution)
            DISTRIBUTION="${2}"
            shift 2
            ;;
        -T|--tasks)
            TASKS="${2}"
            shift 2
            ;;
        -P|--packages-list)
            PACKAGES_LIST="${2}"
            shift 2
            ;;
        -p|--additional-packages)
            ADDITIONAL_PACKAGES="${2}"
            shift 2
            ;;
        -e|--exclude-packages)
            EXCLUDE_PACKAGES="${2}"
            shift 2
            ;;
        -b|--build-directory)
            BUILD_DIR="${2}"
            shift 2
            ;;
        -c|--clean-before)
            CLEAN_BEFORE="true"
            shift
            ;;
        -C|--clean-after)
            CLEAN_AFTER="false"
            shift
            ;;
        -k|--hooks)
            HOOKS_DIR="${2}"
            shift 2
            ;;
        -l|--includes-binary)
            INCLUDES_BINARY_DIR="${2}"
            shift 2
            ;;
        -m|--includes-chroot)
            INCLUDES_CHROOT_DIR="${2}"
            shift 2
            ;;
        -t|--tarball)
            GENERATE_TAR="true"
            TAR_NAME="${2}"
            shift 2
            ;;
        -i|--image)
            GENERATE_IMG="true"
            IMG_NAME="${2}"
            shift 2
            ;;
        -q|--partition-script)
            PARTITION_SCRIPT_NAME="${2}"
            shift 2
            ;;
        -s|--source-iso)
            SOURCE_ISO="${2}"
            if [ -z $REPO_PRIORITY ]; then
                REPO_PRIORITY="iso"
            fi
            shift 2
            ;;
        -r|--repositories)
            export REPOSITORIES="${2}"
            if [ -z $REPO_PRIORITY ]; then
                REPO_PRIORITY="url"
            fi
            shift 2
            ;;
        -a|--arch)
            ARCHITECTURE="${2}"
            shift 2
            ;;
        --)
            shift
            break
            ;;
        *)
            echo "internal error %s" "${0}"
            exit 1
            ;;
    esac
done

# Perform some checks
# Check if live-build-astra is ran from root.
if ! [ "$(id -u)" = "0" ]; then
    echo 'live-build-astra had to be ran from root or with sudo' >&2
    exit 1
fi


if [ "${ARCHITECTURE}" != "amd64" ] && [ "${GENERATE_ISO}" = "true" ]; then
    echo "Could not generate ISO images for ${ARCHITECTURE}."
    GENERATE_ISO="false"
fi

if ! [ -d ${HOOKS_DIR} ]; then
    echo "No such directory ${HOOKS_DIR}." >&2 && exit 4
fi
if ! [ -d ${INCLUDES_BINARY_DIR} ]; then
    echo "No such directory ${INCLUDES_BINARY_DIR}." >&2 && exit 5
fi
if ! [ -d ${INCLUDES_CHROOT_DIR} ]; then
    echo "No such directory ${INCLUDES_CHROOT_DIR}." >&2 && exit 6
fi

if [ "${CLEAN_BEFORE}" = "true" ]; then
    if [ $(readlink -f ${BUILD_DIR}) != "/" ]; then
        rm -rf ${BUILD_DIR}
    fi
fi

# Check if build directory exists and is empty. Create it if doesn't exist.
if [ -e ${BUILD_DIR} ]; then
    if ! [ -d ${BUILD_DIR} ]; then
        echo "${BUILD_DIR} exists and is not a directory. Aborting" >&2
        exit 2
    else
        [ "$(ls -A ${BUILD_DIR})" ] && echo "${BUILD_DIR} is not empty. Aborting" >&2 && exit 3
    fi
else
    mkdir -p ${BUILD_DIR}
fi
if [ $(readlink -f ${BUILD_DIR}) != "/" ]; then
    rm -rf ${BUILD_DIR}/* ${BUILD_DIR}/.build ${BUILD_DIR}/.lock
fi
if [ -n "$SOURCE_ISO" ]; then
    repo_count=0
    mkdir -p ${BUILD_DIR}/repos
    while read LINE; do
        mkdir -p ${BUILD_DIR}/repos/${repo_count} || true
        mount_source_iso $(readlink -f ${LINE}) ${BUILD_DIR}/repos/${repo_count}
        if [ -n "${ISO_REPOSITORIES}" ]; then
            ISO_REPOSITORIES="${ISO_REPOSITORIES};file://$(readlink -f ${BUILD_DIR})/repos/${repo_count}"
        else
            ISO_REPOSITORIES="file://$(readlink -f ${BUILD_DIR})/repos/${repo_count}"
        fi
        repo_count=$(($repo_count+1))
     done <<< "$(echo ${SOURCE_ISO} | tr ';' '\n')"

    if [ $REPO_PRIORITY = "iso" ]; then
        export REPOSITORIES="${ISO_REPOSITORIES};${REPOSITORIES}"
    else
        export REPOSITORIES="${REPOSITORIES};${ISO_REPOSITORIES}"
    fi
fi

export REPOSITORY=$(main_repository $REPOSITORIES)

#TODO: check this. What if broken:/repository is not the first in line
if echo "$REPOSITORIES" | grep -q '^http:' || echo "$REPOSITORIES" | grep -q '^ftp:' || echo "$REPOSITORIES" | grep -q '^file:' ; then
    echo "Using ${REPOSITORIES} as package source."
else
    echo "Sorry, but live-build-astra works only with HTTP, FTP and file: repositories."
    exit 1
fi

LB_OPTIONS="--verbose --apt-source-archives false --security false --updates false --apt-secure false --distribution ${DISTRIBUTION} --mirror-bootstrap ${REPOSITORY} --parent-mirror-binary ${REPOSITORY} --firmware-chroot false --zsync false --mode debian"

if [ "${GENERATE_ISO}"="true" ]; then
    LB_OPTIONS="${LB_OPTIONS} --bootloader grub2 --memtest none --iso-volume none --iso-application none --iso-preparer none --iso-publisher none"
fi

if [ "${ARCHITECTURE}" = "amd64" ]; then
    LB_OPTIONS="${LB_OPTIONS} --linux-packages linux-image --linux-flavours generic"
elif [ "${ARCHITECTURE}" = "armhf" ]; then
    check_qemu
    LB_OPTIONS="${LB_OPTIONS} --architectures armhf --bootstrap-qemu-arch armhf --bootstrap-qemu-static /usr/bin/qemu-arm-static --linux-packages none --initramfs none --initsystem none --binary-images tar --chroot-filesystem none"
    echo "UnMounting binfmt_misc ..."
    umount /proc/sys/fs/binfmt_misc
    echo "Mounting binfmt_misc ..."
    mount -t binfmt_misc none /proc/sys/fs/binfmt_misc
    echo "Register handler for ARM ELF ..."
    echo "-1" > /proc/sys/fs/binfmt_misc/arm || true
    echo ":arm:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-arm-static:" > /proc/sys/fs/binfmt_misc/register
elif [ "${ARCHITECTURE}" = "mips" ]; then
    check_qemu
    LB_OPTIONS="${LB_OPTIONS} --architectures mips --bootstrap-qemu-arch mips --bootstrap-qemu-static /usr/bin/qemu-mips-static --linux-packages none --initramfs none --initsystem none --binary-images tar --chroot-filesystem none"
    echo "UnMounting binfmt_misc ..."
    umount /proc/sys/fs/binfmt_misc
    echo "Mounting binfmt_misc ..."
    mount -t binfmt_misc none /proc/sys/fs/binfmt_misc
    echo "Register handler for MIPS ELF ..."
    echo "-1" > /proc/sys/fs/binfmt_misc/mips || true
    echo ":mips:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/bin/qemu-mips-static:" > /proc/sys/fs/binfmt_misc/register
elif [ "${ARCHITECTURE}" = "mipsel" ]; then
    check_qemu
    LB_OPTIONS="${LB_OPTIONS} --architectures mipsel --bootstrap-qemu-arch mipsel --bootstrap-qemu-static /usr/bin/qemu-mipsel-static --linux-packages none --initramfs none --initsystem none --binary-images tar --chroot-filesystem none"
    echo "UnMounting binfmt_misc ..."
    umount /proc/sys/fs/binfmt_misc
    echo "Mounting binfmt_misc ..."
    mount -t binfmt_misc none /proc/sys/fs/binfmt_misc
    echo "Register handler for MIPSel ELF ..."
    echo "-1" > /proc/sys/fs/binfmt_misc/mipsel || true
    echo ":mipsel:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-mipsel-static:" > /proc/sys/fs/binfmt_misc/register
fi

pushd ${BUILD_DIR} && \
    lb config ${LB_OPTIONS} --apt-options "--yes --force-yes" --debootstrap-options "--variant=minbase" --archive-areas "main contrib non-free" --parent-archive-areas "main contrib non-free"
if [ "${ARCHITECTURE}" = "amd64" ]; then
    cp -r ${INCLUDES_CHROOT_DIR}/* config/includes.chroot/
    cp -r ${INCLUDES_BINARY_DIR}/* config/includes.binary/
fi
if [ -n "$SOURCE_ISO" ]; then
    mkdir -p config/includes.binary/boot/grub/
    cp repos/0/boot/grub/efi.img config/includes.binary/boot/grub/
    mkdir -p config/includes.binary/efi/boot
    cp repos/0/efi/boot/* config/includes.binary/efi/boot/
    cp -r repos/0/install.amd config/includes.binary/install/
    cp -r repos/0/install-doc config/includes.binary/
    cp -r repos/0/netinst config/includes.binary/
    cp repos/0/astra.ico config/includes.binary/
    cp repos/0/Autorun.inf config/includes.binary/
    cp repos/0/*.info config/includes.binary/
fi
cp -r ${HOOKS_DIR}/* config/hooks/ && \


## Get Packages.<>
if echo "$REPOSITORY" | grep -q '^file:' ; then
    REPO_PATH=$(echo ${REPOSITORY} | sed 's/file://')
    echo ${COMPONENTS} | tr ' ' '\n' | while read component; do
        cp ${REPO_PATH}/dists/${DISTRIBUTION}/${component}/binary-${ARCHITECTURE}/Packages Packages.${component}
    done
else
    echo ${COMPONENTS} | tr ' ' '\n' | while read component; do
        wget -nv -O Packages.${component} ${REPOSITORY}/dists/${DISTRIBUTION}/${component}/binary-${ARCHITECTURE}/Packages 2>/dev/null
    done
fi

if [ "${ARCHITECTURE}" = "amd64" ] && [ "${GENERATE_ISO}"="true" ]; then
    if echo "$REPOSITORY" | grep -q '^file:' ; then
        REPO_PATH=$(echo ${REPOSITORY} | sed 's/file://')
        ## Add "dists"
        cp -r $REPO_PATH/dists config/includes.binary/ || true
        # find $REPO_PATH/dists -type d | sed "s,${REPO_PATH}\/,," | while read LINE ; do
        #     mkdir -p config/includes.binary/${LINE}
        # done
        ## Add "pool"
        find $REPO_PATH/pool -type d | sed "s,${REPO_PATH}\/,," | while read LINE ; do
            mkdir -p config/includes.binary/${LINE}
        done
        ## Add udebs to pool
        find $REPO_PATH/pool -type f -name *.udeb | while read LINE ; do
            cp ${LINE} config/includes.binary/`echo $LINE | sed "s,${REPO_PATH}\/,,"`
        done
        ## Add debs from "minimal.packages" to pool
        while read pkgname; do
            pkgpath=$(apt_cache_show_filename ${pkgname})
            if [ "${pkgpath}" != "" ]; then
                cp ${REPO_PATH}/${pkgpath} config/includes.binary/${pkgpath}
            else
                echo "${pkgname}" >> minimal.failed.packages
            fi
        done < ${LBA}/minimal.packages
    else
        ## Add "dists"
        wget -r -nH -nv --cut-dirs=$(get_cut_dirs_num ${REPOSITORY}) -l 4 -P config/includes.binary ${REPOSITORY}/dists

        ## Add udebs to pool
        wget -r -nH -nv --cut-dirs=$(get_cut_dirs_num ${REPOSITORY}) -l 4 -A udeb -P config/includes.binary ${REPOSITORY}/pool
        ## Add debs from "minimal.packages" to pool
        while read pkgname; do
            pkgpath=$(apt_cache_show_filename ${pkgname})
            if [ "${pkgpath}" != "" ]; then
                wget -nv ${REPOSITORY}/${pkgpath} -O config/includes.binary/${pkgpath}
            else
                echo "${pkgname}" >> minimal.failed.packages
            fi
        done < ${LBA}/minimal.packages
    fi
fi

# Get list of packages in tasksel tasks
get_tasksel-data_package
unpack_tasksel-data_package
get_task_package_lists
rm -rf ./tasksel-data/usr

if [ -n "${TASKS}" ]; then
    if [ "${TASKS}" = "all" ]; then
        for file in ./tasksel-data/* ;do
            cat ${file} >> config/package-lists/tasksel.list.chroot
        done
    else
        echo ${TASKS} | sed 's/,/ /g' | sed 's/\s\+/\n/g' | while read task; do
            if [ -f ./tasksel-data/${task} ]; then
                cat ./tasksel-data/${task} >> config/package-lists/tasksel.list.chroot
            else
                echo "No such task ${task} in tasksel." >&2
                exit 1
            fi
        done
    fi
fi

echo "${ADDITIONAL_PACKAGES}" >> config/package-lists/additional.list.chroot

if [ -n "${EXCLUDE_PACKAGES}" ]; then
    echo "${EXCLUDE_PACKAGES}" | sed 's/,/ /g' | sed 's/\s\+/\n/g' | while read package; do
        for file in config/package-lists/*.list.chroot ; do
            sed "/^${package}$/d" -i ${file}
        done
    done
fi

if [ "${ARCHITECTURE}" = "armhf" ]; then
    echo "linux-image-3.2.0-4-vexpress" >> config/package-lists/kernel.list.chroot
fi

# Remove empty directories
find ./config/includes.binary/ -depth -type d -empty -exec rmdir {} \;

lb build
popd

create_vmlinuz_links

if [ "${GENERATE_ISO}" = "true" ]; then
    # live-build doesn't copy hidden .disk directory by itself
    # so we have to copy it manualy
    cp -r ${INCLUDES_BINARY_DIR}/.disk/* ${BUILD_DIR}/binary/.disk
    cp ${BUILD_DIR}/chroot/boot/vmlinuz ${BUILD_DIR}/binary/live/vmlinuz
    cp ${BUILD_DIR}/chroot/boot/initrd.img ${BUILD_DIR}/binary/live/initrd
    cp /usr/share/doc/live-build-astra/LiveCD_Readme.txt ${BUILD_DIR}/binary/Readme.txt
    generate_info_file
    fix_booloader_configs ${DISTRIBUTION^}

    xorriso -as mkisofs -V "${DISTRIBUTION^} Live" -isohybrid-mbr /usr/lib/syslinux/isohdpfx.bin -b isolinux/isolinux.bin -no-emul-boot -boot-load-size 4 -boot-info-table -eltorito-alt-boot -e boot/grub/efi.img -no-emul-boot -isohybrid-gpt-basdat -append_partition 2 0xef ${BUILD_DIR}/binary/boot/grub/efi.img -o ${BUILD_DIR}/output.iso ${BUILD_DIR}/binary
    if [ -f ${BUILD_DIR}/output.iso ];then
        mkdir -p $(dirname ${OUTPUT_FILE})
        mv ${BUILD_DIR}/output.iso ${OUTPUT_FILE}
    fi
fi

if [ "${GENERATE_TAR}" = "true" ]; then
    echo "Generating tar."
    tar -caf ${BUILD_DIR}/$(basename ${TAR_NAME}) --exclude binary --exclude binary.hybrid.iso --exclude binary.sh -C ${BUILD_DIR}/chroot ./
    if [ -f ${BUILD_DIR}/$(basename ${TAR_NAME}) ];then
        mkdir -p $(dirname ${TAR_NAME})
        mv ${BUILD_DIR}/$(basename ${TAR_NAME}) ${TAR_NAME}
    fi
fi

if [ "${GENERATE_IMG}" = "true" ]; then
    if [ "${GENERATE_TAR}" = "false" ]; then
        tar_dir=`mktemp -d`
        TAR_NAME=${tar_dir}/chroot.tar
        tar -caf ${TAR_NAME} --exclude binary --exclude binary.hybrid.iso --exclude binary.sh -C ${BUILD_DIR}/chroot ./
    fi
    echo "Generating image."
    create_image
    partition_image
    mkfs_image
    copy_data_to_image
    if [ "${GENERATE_TAR}" = "false" ]; then
        rm -rf $tar_dir
    fi
    if [ "${ARCHITECTURE}" = "armhf" ]; then
        place_chroot_scripts
    fi
    if [ -f ${BUILD_DIR}/output.img ];then
        mkdir -p $(dirname ${IMG_NAME})
        mv ${BUILD_DIR}/output.img ${IMG_NAME}
    fi
fi

if [ -n "$SOURCE_ISO" ]; then
    repo_count=0
    echo ${SOURCE_ISO} | tr ';' '\n' | while read LINE; do
        umount_source_iso $(readlink -f ${BUILD_DIR})/repos/${repo_count}
        repo_count=$(($repo_count+1))
    done
fi

if [ "${CLEAN_AFTER}" = "true" ]; then
    echo "Cleaning build directory."
    if [ $(readlink -f ${BUILD_DIR}) != "/" ]; then
        rm -rf ${BUILD_DIR}
    fi
fi

if [ -f ${BUILD_DIR}/chroot/apt.failed.packages ]; then
    echo "Some packages not installed."
    echo "See list in ${BUILD_DIR}/chroot/apt.failed.packages"
fi
