#! /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" /target file:///cdrom/)"
BASEOPTS=
for b in $BASE; do
    BASEOPTS="${BASEOPTS:+$BASEOPTS }-b $b"
done

# These aren't really in Desktop, but are installed by base-config so
# archive-copier needs to consider them as such.
DESKTOPOPTS='-d laptop-detect -d xresprobe -d discover1 -d discover1-data -d libdiscover1 -d dash'

# 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 db_get base-config/language-pack-patterns; then
    lppatterns="$RET"
else
    lppatterns='language-pack-$LL language-pack-gnome-$LL'
fi

SHIPOPTS=
for l in $languages; do
    for pattern in $lppatterns; do
	pack="$(echo "$pattern" | sed "s/\\\$LL/$l/g")"
	SHIPOPTS="${SHIPOPTS:+$SHIPOPTS }-S $pack"
    done
    SHIPOPTS="${SHIPOPTS:+$SHIPOPTS }-S language-support-$l"
done

db_get archive-copier/desktop-task
if [ "$RET" ]; then
    DESKTOP="$RET"
    DESKTOPOPTS="$DESKTOPOPTS -D $DESKTOP"
fi
db_get archive-copier/ship-task
if [ "$RET" ]; then
    SHIP="$RET"
    SHIPOPTS="$SHIPOPTS -S $SHIP"
fi

# TODO: for Debian, using $SUITE for debootstrap wouldn't work (unstable vs.
# sid).
/usr/lib/archive-copier/package-cache-names -P "$WORK/packages" \
    $BASEOPTS $DESKTOPOPTS $SHIPOPTS \
    >"$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 if there is anything to copy for them

copybase=no
if [ "$DESKTOPOPTS" ]; then
    copydesktop=yes
else
    copydesktop=no
fi
if [ "$SHIPOPTS" ]; then
    copyship=yes
else
    copyship=no
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)"

if [ "$NUM_FILES" -ge 100 ]; then
    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 (but don't bother if there aren't many packages to copy, as
    # it probably won't be worth it).
    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
else
    db_progress START 0 "$NUM_FILES" archive-copier/progress
    progress=1
fi

# 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 ...

# 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
