#! /bin/sh
set -e

. /usr/share/debconf/confmodule

db_capb backup

ARCH="$(udpkg --print-architecture)"
BASECACHE=/target/var/cache/apt/archives
DESKTOPCACHE=/target/var/cache/archive-copier/desktop
SHIPCACHE=/target/var/cache/archive-copier/ship
WORK=/var/spool/archive-copier

log () {
    logger -t archive-copier "$@"
}

error () {
    log "error: $@"
}

if [ ! -f /cdrom/.disk/base_installable ]; then
    log "not installing from base-installable CD-ROM"
    exit 0
fi

if ! db_get mirror/suite; then
    log "required mirror/suite not set"
    exit 0
fi
SUITE="$RET"

db_capb backup

db_input medium archive-copier/copy || [ $? -eq 30 ]
if ! db_go; then
    exit 10 # back up to menu
fi

db_get archive-copier/copy
if [ "$RET" = false ]; then
    log "user requested no copy"
    exit 0
fi

# Get list of files; must do this first in order to know how long the
# progress bar should be.

if [ -f /cdrom/.disk/base_components ]; then
    COMPONENTS="$(grep -v '^#' /cdrom/.disk/base_components)"
else
    COMPONENTS=main
fi
rm -rf "$WORK"
mkdir -p "$WORK"
for component in $COMPONENTS; do
    zcat "/cdrom/dists/$SUITE/$component/binary-$ARCH/Packages.gz" \
	>>"$WORK/packages"
done

BASE="$(debootstrap --print-debs "$SUITE")"
db_get archive-copier/desktop-task
DESKTOP="$RET"
db_get archive-copier/ship-task
SHIP="$RET"
# TODO: for Debian, using $SUITE for debootstrap wouldn't work (unstable vs.
# sid).
/usr/lib/archive-copier/package-cache-names "$WORK/packages" \
    "$DESKTOP" "$SHIP" $BASE >"$WORK/list"

progress=

die () {
    template="$1"
    shift

    error "$@"
    db_input critical "$template" || [ $? -eq 30 ]
    db_go || true
    [ "$progress" ] && db_progress STOP
    rm -rf "$WORK"
    exit 1
}

# Current policy is:
#   never copy Base
#   copy Desktop and Ship except in custom mode

copybase=no
if db_get ubuntu/install-type && [ "$RET" = custom ]; then
    copydesktop=no
    copyship=no
else
    copydesktop=yes
    copyship=yes
fi

if [ "$copybase" = yes ]; then
    mkdir -p "$BASECACHE" || \
	die archive-copier/copy-failed "'mkdir -p \"$BASECACHE\"' failed with code $?"
fi
if [ "$copydesktop" = yes ]; then
    mkdir -p "$DESKTOPCACHE" || \
	die archive-copier/copy-failed "'mkdir -p \"$DESKTOPCACHE\"' failed with code $?"
fi
if [ "$copyship" = yes ]; then
    mkdir -p "$SHIPCACHE" || \
	die archive-copier/copy-failed "'mkdir -p \"$SHIPCACHE\"' failed with code $?"
fi

# Filter in only the packages we want to copy before bringing up the
# progress bar.

while read filename version status; do
    base="${filename##*/}"

    package="${base%%_*}"
    trailer="${base##*_}"

    case $status in
	base)
	    [ "$copybase" = yes ] || continue
	    cachedir="$BASECACHE"
	    ;;
	desktop)
	    [ "$copydesktop" = yes ] || continue
	    cachedir="$DESKTOPCACHE"
	    ;;
	ship)
	    [ "$copyship" = yes ] || continue
	    cachedir="$SHIPCACHE"
	    ;;
	*)
	    continue
	    ;;
    esac
    cachebase="${package}_${version}_${trailer}"

    echo "/cdrom/$filename $cachedir/$cachebase $package"
done <"$WORK/list" | sort >"$WORK/to-copy"

NUM_FILES="$(wc -l "$WORK/to-copy" | sed 's/^ *//' | cut -d' ' -f1)"
POOLCOUNT="$(set -- /cdrom/pool/*/*; echo $#)"
db_progress START 0 "$(($NUM_FILES + $POOLCOUNT))" archive-copier/progress
progress=1

# Get all the pool directories into the dentry cache, to cut down on seek
# times.
for pooldir in /cdrom/pool/*/*; do
    db_progress STEP 1
    if [ -d "$pooldir" ]; then
	db_subst archive-copier/progress/directory DIR "${pooldir#/cdrom/}"
	db_progress INFO archive-copier/progress/directory
	find "$pooldir/" >/dev/null 2>&1
    fi
done

# Copy everything. Be paranoid about failures.
# Using fd 9 is a bit ugly; debconf gets in the way of random other fds.

while read cdromfile cachefile package <&9; do
    db_progress STEP 1
    db_subst archive-copier/progress/package PACKAGE "$package"
    db_progress INFO archive-copier/progress/package
    cp -a "$cdromfile" "$cachefile" || \
	die archive-copier/copy-failed \
	    "'cp -a \"$cdromfile\" \"$cachefile\"' failed with code $?"
done 9<"$WORK/to-copy"

# Figure out whether all necessary language support is on the CD, and, if
# not, ask the user whether it's OK to download it. Putting this in
# archive-copier is admittedly a bit odd, but it's a handy CD-only package
# that knows about the contents of the CD ...

# First, figure out what language support packages will be required. Keep
# this in sync with base-config/lib/menu/pkgsel.
if db_get base-config/language-packs && [ "$RET" ]; then
	languages="$(echo "$RET" | sed 's/,//g')"
elif db_get localechooser/supported-locales && [ "$RET" ]; then
	languages="$(echo "$RET" | sed -e 's/,//g' -e 's/_[^ ]*//g')"
elif db_get debian-installer/locale && [ "$RET" ]; then
	languages="${RET%%_*}"
else
	languages=
fi
log "languages: $languages"

# If any language support packages are due to be installed, check whether
# they're on the CD. If they aren't, ask.
if [ "$languages" ]; then
	got_langsupport=1
	for l in $languages; do
		if ! cut -d' ' -f3 "$WORK/to-copy" | \
		     grep -q "^language-support-$l\$"; then
			got_langsupport=
			break
		fi
	done

	if [ "$got_langsupport" ]; then
		log "language-support packages available"
	else
		log "language-support packages not available"
		db_input high base-config/install-language-support || true
		if ! db_go; then
			rm -rf "$WORK"
			db_progress STOP
			exit 10
		fi
	fi
fi

rm -rf "$WORK"

db_progress STOP

exit 0
