#!/bin/sh
set -e

VERSION='@VERSION@'

unset TMP TEMP TMPDIR || true

# might not be exported if we're running from init=/bin/sh or similar
export PATH

###########################################################################

if [ -z "$DEBOOTSTRAP_DIR" ]; then
	if [ -x /debootstrap/debootstrap ]; then
		DEBOOTSTRAP_DIR=/debootstrap
	else
		DEBOOTSTRAP_DIR=/usr/share/debootstrap
	fi
fi

. "$DEBOOTSTRAP_DIR/functions"
exec 4>&1

LANG=C
EXTRA_SUITES=""
USE_COMPONENTS=main
KEYRING=""
DISABLE_KEYRING=""
FORCE_KEYRING=""
VARIANT=""
MERGED_USR=""
ARCH=""
HOST_ARCH=""
HOST_OS=""
KEEP_DEBOOTSTRAP_DIR=""
USE_DEBIANINSTALLER_INTERACTION=""
SECOND_STAGE_ONLY=""
CHROOTDIR=""
MAKE_TARBALL=""
EXTRACTOR_OVERRIDE=""
UNPACK_TARBALL=""
ADDITIONAL=""
EXCLUDE=""
VERBOSE=""
CERTIFICATE=""
CHECKCERTIF=""
PRIVATEKEY=""
CACHE_DIR=""

DEF_MIRROR="http://deb.debian.org/debian"
DEF_HTTPS_MIRROR="https://deb.debian.org/debian"

# set $CONTAINER
detect_container

export LANG USE_COMPONENTS
umask 022

###########################################################################

## phases:
##   finddebs dldebs printdebs save_variables first_stage second_stage

RESOLVE_DEPS=true

WHAT_TO_DO="finddebs dldebs save_variables first_stage second_stage"
am_doing_phase () {
	# usage:   if am_doing_phase finddebs; then ...; fi
	local x;
	for x in "$@"; do
		if echo " $WHAT_TO_DO " | grep -q " $x "; then return 0; fi
	done
	return 1
}

###########################################################################

usage_err()
{
	info USAGE1 "usage: [OPTION]... <suite> <target> [<mirror> [<script>]]"
	info USAGE2 "Try \`${0##*/} --help' for more information."
	error "$@"
}

usage()
{
	echo "Usage: ${0##*/} [OPTION]... <suite> <target> [<mirror> [<script>]]"
	echo "Bootstrap a Debian base system into a target directory."
	echo
	cat <<EOF
      --help                 display this help and exit
      --version              display version information and exit
      --verbose              don't turn off the output of wget

      --download-only        download packages, but don't perform installation
      --print-debs           print the packages to be installed, and exit

      --arch=A               set the architecture to install (use if no dpkg)
                               [ --arch=powerpc ]

      --include=A,B,C        adds specified names to the list of base packages
      --exclude=A,B,C        removes specified packages from the list
      --extra-suites=A,B,C   also use packages from the listed suites of the
                             archive
      --components=A,B,C     use packages from the listed components of the
                             archive
      --variant=X            use variant X of the bootstrap scripts
                             (currently supported variants: buildd, fakechroot,
                              minbase)
      --no-merged-usr        do not make /{bin,sbin,lib}/ symlinks to /usr/
      --keyring=K            check Release files against keyring K
      --no-check-gpg         avoid checking Release file signatures
      --force-check-gpg      force checking Release file signatures
                             (also disables automatic fallback to HTTPS in case
                             of a missing keyring), aborting otherwise
      --no-resolve-deps      don't try to resolve dependencies automatically
      --log-extra-deps       record extra dependency info in debootstrap.log
      --cache-dir=DIR        Use specified directory as package cache directory

      --unpack-tarball=T     acquire .debs from a tarball instead of http
      --make-tarball=T       download .debs and create a gzipped tarball
      --second-stage-target=DIR
                             Run second stage in a subdirectory instead of root
                               (can be used to create a foreign chroot)
                               (requires --second-stage)
      --extractor=TYPE       override automatic .deb extractor selection
                               (supported: $EXTRACTORS_SUPPORTED)
      --debian-installer     used for internal purposes by debian-installer
      --private-key=file     read the private key from file
      --certificate=file     use the client certificate stored in file (PEM)
      --no-check-certificate do not check certificate against certificate authorities
EOF
}

###########################################################################

if [ -z "$PKGDETAILS" ]; then
	error 1 NO_PKGDETAILS "No pkgdetails available; either install perl, or build pkgdetails.c from the base-installer source package"
fi

###########################################################################

if [ $# != 0 ] ; then
    while true ; do
	case "$1" in
	    --help)
		usage
		exit 0
		;;
	    --version)
		echo "debootstrap $VERSION"
		exit 0
		;;
	    --debian-installer)
		if ! (echo -n "" >&3) 2>/dev/null; then
			error 1 ARG_DIBYHAND "If running debootstrap by hand, don't use --debian-installer"
		fi
		USE_DEBIANINSTALLER_INTERACTION=yes
		shift
		;;
	    --foreign)
		check_conflicting_option "$1"
		if [ -n "$LOOSEN_CONFLICTING_RESTRICTION" ]; then
			WHAT_TO_DO="first_stage"
		else
			WHAT_TO_DO="finddebs dldebs save_variables first_stage"
			fi
		shift
		;;
	    --second-stage)
		check_conflicting_option "$1"
		WHAT_TO_DO="second_stage"
		SECOND_STAGE_ONLY=true
		shift
		;;
	    --second-stage-target|--second-stage-target=?*)
		if [ "$SECOND_STAGE_ONLY" != "true" ] ; then
			error 1 STAGE2ONLY "option %s only applies in the second stage" "$1"
		fi
		if [ "$1" = "--second-stage-target" ] && [ -n "$2" ] ; then
			CHROOTDIR="$2"
			shift 2
		elif [ "$1" != "${1#--second-stage-target=}" ]; then
			CHROOTDIR="${1#--second-stage-target=}"
			shift
		else
			error 1 NEEDARG "option requires an argument: %s" "$1"
		fi
		;;
	    --print-debs)
		check_conflicting_option "$1"
		WHAT_TO_DO="finddebs printdebs kill_target"
		shift
		;;
	    --download-only)
		check_conflicting_option "$1"
		WHAT_TO_DO="finddebs dldebs"
		shift
		;;
	    --make-tarball|--make-tarball=?*)
		check_conflicting_option "$1"
		WHAT_TO_DO="finddebs dldebs save_variables maketarball kill_target"
		if [ "$1" = "--make-tarball" ] && [ -n "$2" ] ; then
			MAKE_TARBALL="$2"
			shift 2
		elif [ "$1" != "${1#--make-tarball=}" ]; then
			MAKE_TARBALL="${1#--make-tarball=}"
			shift
		else
			error 1 NEEDARG "option requires an argument %s" "$1"
		fi
		;;
	    --resolve-deps)
		# redundant, but avoids breaking compatibility
		RESOLVE_DEPS=true
		shift
		;;
	    --no-resolve-deps)
		RESOLVE_DEPS=false
		shift
		;;
	    --log-extra-deps)
		LOG_EXTRA_DEPS=true
		shift
		;;
	    --keep-debootstrap-dir)
		KEEP_DEBOOTSTRAP_DIR=true
		shift
		;;
	    --arch|--arch=?*)
		if [ "$1" = "--arch" ] && [ -n "$2" ] ; then
			ARCH="$2"
			shift 2
                elif [ "$1" != "${1#--arch=}" ]; then
			ARCH="${1#--arch=}"
			shift
		else
			error 1 NEEDARG "option requires an argument %s" "$1"
		fi
		;;
	    --extractor|--extractor=?*)
		if [ "$1" = "--extractor" ] && [ -n "$2" ] ; then
			EXTRACTOR_OVERRIDE="$2"
			shift 2
		elif [ "$1" != "${1#--extractor=}" ]; then
			EXTRACTOR_OVERRIDE="${1#--extractor=}"
			shift
		else
			error 1 NEEDARG "option requires an argument %s" "$1"
		fi
		if valid_extractor "$EXTRACTOR_OVERRIDE"; then
			if ! in_path "$EXTRACTOR_OVERRIDE"; then
				error 1 MISSINGEXTRACTOR "The selected extractor cannot be found: %s" "$EXTRACTOR_OVERRIDE"
			fi
		else
			error 1 BADEXTRACTOR "%s: unknown extractor" "$EXTRACTOR_OVERRIDE"
		fi
		;;
	    --unpack-tarball|--unpack-tarball=?*)
		if [ "$1" = "--unpack-tarball" ] && [ -n "$2" ] ; then
			check_conflicting_option "$1"
			if [ -n "$LOOSEN_CONFLICTING_RESTRICTION" ]; then
				WHAT_TO_DO="first_stage"
			else
				WHAT_TO_DO="first_stage second_stage"
			fi
			UNPACK_TARBALL="$2"
			shift 2
		elif [ "$1" != "${1#--unpack-tarball=}" ]; then
			check_conflicting_option "$1"
			if [ -n "$LOOSEN_CONFLICTING_RESTRICTION" ]; then
				WHAT_TO_DO="first_stage"
			else
				WHAT_TO_DO="first_stage second_stage"
			fi
			UNPACK_TARBALL="${1#--unpack-tarball=}"
			shift
		else
			error 1 NEEDARG "option requires an argument %s" "$1"
		fi
		if [ ! -f "$UNPACK_TARBALL" ] ; then
			error 1 NOTARBALL "%s: No such file or directory" "$UNPACK_TARBALL"
		fi
		;;
	    --include|--include=?*)
		if [ "$1" = "--include" ] && [ -n "$2" ]; then
			ADDITIONAL="$2"
			shift 2
                elif [ "$1" != "${1#--include=}" ]; then
			ADDITIONAL="${1#--include=}"
			shift 1
		else
			error 1 NEEDARG "option requires an argument %s" "$1"
		fi
		ADDITIONAL="$(echo "$ADDITIONAL" | tr , " ")"
		;;
	    --exclude|--exclude=?*)
		if [ "$1" = "--exclude" ] && [ -n "$2" ]; then
			EXCLUDE="$2"
			shift 2
                elif [ "$1" != "${1#--exclude=}" ]; then
			EXCLUDE="${1#--exclude=}"
			shift 1
		else
			error 1 NEEDARG "option requires an argument %s" "$1"
		fi
		EXCLUDE="$(echo "$EXCLUDE" | tr , " ")"
		;;
	    --verbose)
		VERBOSE=true
		export VERBOSE
		shift 1
		;;
	    --extra-suites|--extra-suites=?*)
		if [ "$1" = "--extra-suites" ] && [ -n "$2" ]; then
			EXTRA_SUITES="$2"
			shift 2
                elif [ "$1" != "${1#--extra-suites=}" ]; then
			EXTRA_SUITES="${1#--extra-suites=}"
			shift 1
		else
			error 1 NEEDARG "option requires an argument %s" "$1"
		fi
		EXTRA_SUITES="$(echo "$EXTRA_SUITES" | tr , " ")"
		;;
	    --components|--components=?*)
		if [ "$1" = "--components" ] && [ -n "$2" ]; then
			USE_COMPONENTS="$2"
			shift 2
                elif [ "$1" != "${1#--components=}" ]; then
			USE_COMPONENTS="${1#--components=}"
			shift 1
		else
			error 1 NEEDARG "option requires an argument %s" "$1"
		fi
		USE_COMPONENTS="$(echo "$USE_COMPONENTS" | tr , "|")"
		;;
	    --variant|--variant=?*)
		if [ "$1" = "--variant" ] && [ -n "$2" ]; then
			VARIANT="$2"
			shift 2
                elif [ "$1" != "${1#--variant=}" ]; then
			VARIANT="${1#--variant=}"
			shift 1
		else
			error 1 NEEDARG "option requires an argument %s" "$1"
		fi
		;;
	    --cache-dir|--cache-dir=?*)
		# Okay, let's check user's option
		if [ "$1" = "--cache-dir" ] && [ -n "$2" ] ; then
			CACHE_DIR="$2"
			shift 2
		elif [ "$1" != "${1#--cache-dir=}" ]; then
			CACHE_DIR="${1#--cache-dir=}"
			shift
		else
			error 1 NEEDARG "option requires an argument %s" "$1"
		fi
		if [ ! -z "${CACHE_DIR##/*}" ]; then
			error 1 NOTABSOLUTEPATH "cache directory should be specified with an absolute path"
		fi
		if [ ! -d "$CACHE_DIR" ] ; then
			error 1 NOCACHEDIR "%s: No such directory" "$CACHE_DIR"
		fi
		;;
            --merged-usr)
		MERGED_USR=yes
		shift
		;;
	    --no-merged-usr)
		MERGED_USR=no
		shift
		;;
	    --keyring|--keyring=?*)
		if ! gpgv --version >/dev/null 2>&1; then
			error 1 NEEDGPGV "gpgv not installed, but required for Release verification"
		fi
		if [ "$1" = "--keyring" ] && [ -n "$2" ]; then
			KEYRING="$2"
			shift 2
                elif [ "$1" != "${1#--keyring=}" ]; then
			KEYRING="${1#--keyring=}"
			shift 1
		else
			error 1 NEEDARG "option requires an argument %s" "$1"
		fi
		if [ ! -e "$KEYRING" ]; then
			error 1 KEYRING "specified keyring file ($KEYRING) not found"
		fi
		;;
	    --no-check-gpg)
			shift 1
			DISABLE_KEYRING=1
		;;
	    --force-check-gpg)
			shift 1
			FORCE_KEYRING=1
		;;
	    --certificate|--certificate=?*)
		if [ "$1" = "--certificate" ] && [ -n "$2" ]; then
			CERTIFICATE="--certificate=$2"
			shift 2
		elif [ "$1" != "${1#--certificate=}" ]; then
			CERTIFICATE="--certificate=${1#--certificate=}" 
			shift 1
		else
		       error 1 NEEDARG "option requires an argument %s" "$1" 
		fi
		;;
	    --private-key|--private-key=?*)
		if [ "$1" = "--private-key" ] && [ -n "$2" ]; then
			PRIVATEKEY="--private-key=$2"
			shift 2
		elif [ "$1" != "${1#--private-key=}" ]; then
			PRIVATEKEY="--private-key=${1#--private-key=}" 
			shift 1
		else
		       error 1 NEEDARG "option requires an argument %s" "$1" 
		fi
		;;
	    --no-check-certificate)
		CHECKCERTIF="--no-check-certificate"
		shift
		;;
	    -*)
		error 1 BADARG "unrecognized or invalid option %s" "$1"
		;;
	    *)
		break
		;;
	esac
    done
fi

###########################################################################
# do auto proxy discovery
AUTOPROXY=""
if ! doing_variant fakechroot && command -v apt-config >/dev/null; then
    eval "$(apt-config shell AUTOPROXY Acquire::http::ProxyAutoDetect)"
    if [ -z "$http_proxy" ] && [ -x "$AUTOPROXY" ]; then
        http_proxy="$($AUTOPROXY)"
        if [ -n "$http_proxy" ]; then
            info AUTOPROXY "Using auto-detected proxy: $http_proxy"
            export http_proxy
        fi
    fi
fi

###########################################################################
if [ -n "$DISABLE_KEYRING" ] && [ -n "$FORCE_KEYRING" ]; then
	error 1 BADARG "Both --no-check-gpg and --force-check-gpg specified, please pick one (at most)"
fi

###########################################################################

if [ "$SECOND_STAGE_ONLY" = "true" ]; then
	SUITE=$(cat "$DEBOOTSTRAP_DIR/suite")
	if [ -e "$DEBOOTSTRAP_DIR/extra-suites" ]; then
		EXTRA_SUITES=$(cat "$DEBOOTSTRAP_DIR/extra-suites")
	fi
	ARCH=$(cat "$DEBOOTSTRAP_DIR/arch")
	USER_MIRROR=$(cat "$DEBOOTSTRAP_DIR/mirror")
	if [ -e "$DEBOOTSTRAP_DIR/variant" ]; then
		VARIANT=$(cat "$DEBOOTSTRAP_DIR/variant")
		SUPPORTED_VARIANTS="$VARIANT"
	fi
	if [ -z "$CHROOTDIR" ]; then
		TARGET=/
	else
		TARGET=$CHROOTDIR
	fi
	SCRIPT="$DEBOOTSTRAP_DIR/suite-script"
else
	if ! in_path wget; then
		error 1 NEEDWGET "You must install wget to download packages."
	fi
	if [ -z "$1" ] || [ -z "$2" ]; then
		usage_err 1 NEEDSUITETARGET "You must specify a suite and a target."
	fi
	SUITE="$1"
	TARGET="$2"
	USER_MIRROR="$3"
	TARGET="${TARGET%/}"
	if [ "${TARGET#/}" = "${TARGET}" ]; then
		if [ "${TARGET%/*}" = "$TARGET" ] ; then
			TARGET="$(pwd)/$TARGET"
		else
			TARGET="$(cd "${TARGET%/*}"; echo "$(pwd)/${TARGET##*/}")"
		fi
	fi

	SCRIPT="$DEBOOTSTRAP_DIR/scripts/$1"
	if [ -n "$VARIANT" ] && [ -e "${SCRIPT}.${VARIANT}" ]; then
		SCRIPT="${SCRIPT}.${VARIANT}"
		SUPPORTED_VARIANTS="$VARIANT"
	fi
	if [ "$4" != "" ]; then
		if [ -e "$DEBOOTSTRAP_DIR/scripts/$4" ]; then
			SCRIPT="$DEBOOTSTRAP_DIR/scripts/$4"
		else
			SCRIPT="$4"
		fi
	fi
fi

###########################################################################

if am_doing_phase kill_target; then
	# Require empty target when we are going to remove it afterwards
	if [ -d "$TARGET" ] && [ -n "$(ls -A "$TARGET")" ] && \
	   [ "$KEEP_DEBOOTSTRAP_DIR" != "true" ]; then
		error 1 BADTARGET "Target directory '$TARGET' is not empty and it would be wiped"
	fi
fi

###########################################################################

if in_path dpkg && \
     dpkg --print-architecture >/dev/null 2>&1; then
	HOST_ARCH=$(/usr/bin/dpkg --print-architecture)
elif in_path udpkg && \
     udpkg --print-architecture >/dev/null 2>&1; then
	HOST_ARCH=$(/usr/bin/udpkg --print-architecture)
elif [ -e "$DEBOOTSTRAP_DIR/arch" ]; then
	HOST_ARCH=$(cat "$DEBOOTSTRAP_DIR/arch")
fi
HOST_OS="$HOST_ARCH"
# basic host OS guessing for non-Debian systems
if [ -z "$HOST_OS" ]; then
	case $(uname) in
		Linux)
			HOST_OS=linux
		;;
		GNU/kFreeBSD)
			HOST_OS=kfreebsd
		;;
		GNU)
			HOST_OS=hurd
		;;
		FreeBSD*)
			HOST_OS=freebsd
		;;
	esac
fi

if [ -z "$ARCH" ]; then
	ARCH="$HOST_ARCH"
fi

if [ -z "$ARCH" ] || [ -z "$HOST_OS" ]; then
        error 1 WHATARCH "Couldn't work out current architecture"

fi

if [ "$HOST_OS" = "kfreebsd" ] || [ "$HOST_OS" = "freebsd" ]; then
	for module in linprocfs fdescfs tmpfs linsysfs; do
		kldstat -m "$module" > /dev/null 2>&1 || warning SANITYCHECK "Probably required module %s is not loaded" "$module"
	done
fi

if [ "$TARGET" = "/" ]; then
	CHROOT_CMD=""
else
	CHROOT_CMD="chroot \"$TARGET\""
fi

# fakeroot cannot check /proc/1/environ
if [ "$HOST_OS" = Linux ] && ! doing_variant fakechroot && [ "$CONTAINER" = "lxc-libvirt" ]; then
       CHROOT_CMD="unshare --net $CHROOT_CMD"
fi

if [ -z "$SHA_SIZE" ]; then
	SHA_SIZE=256
fi
if ! in_path "sha${SHA_SIZE}sum" && ! in_path "sha${SHA_SIZE}"; then
	warning SHA_SIZE "Cannot find binary for checking sha%s checksums, falling back to sha1" "${SHA_SIZE}"
	SHA_SIZE=1
fi
DEBOOTSTRAP_CHECKSUM_FIELD="SHA$SHA_SIZE"

export ARCH SUITE EXTRA_SUITES TARGET CHROOT_CMD SHA_SIZE DEBOOTSTRAP_CHECKSUM_FIELD

if am_doing_phase first_stage second_stage; then
	if in_path id && [ "$(id -u)" -ne 0 ]; then
		error 1 NEEDROOT "debootstrap can only run as root"
	fi
	# Ensure that we can create working devices and executables on the target.
	if ! check_sane_mount "$TARGET"; then
		error 1 NOEXEC "Cannot install into target '$TARGET' mounted with noexec or nodev"
	fi
fi

if [ ! -e "$SCRIPT" ]; then
	error 1 NOSCRIPT "No such script: %s" "$SCRIPT"
fi

###########################################################################

if [ "$TARGET" != "" ]; then
	mkdir -p "$TARGET/debootstrap"
fi

###########################################################################

# Use of fd's by functions/scripts:
#
#    stdin/stdout/stderr: used normally
#    fd 4: I:/W:/etc information
#    fd 5,6: spare for functions
#    fd 7,8: spare for scripts

if [ "$USE_DEBIANINSTALLER_INTERACTION" = yes ]; then
	#    stdout=stderr: full log of debootstrap run
	#    fd 3: I:/W:/etc information
	exec 4>&3
elif am_doing_phase printdebs; then
	#    stderr: I:/W:/etc information
	#    stdout: debs needed
	exec 4>&2
else
	#    stderr: used in exceptional circumstances only
	#    stdout: I:/W:/etc information
	#    $TARGET/debootstrap/debootstrap.log: full log of debootstrap run
	exec 4>&1
	exec >>"$TARGET/debootstrap/debootstrap.log"
	exec 2>&1
fi

###########################################################################

if [ -x /usr/bin/arch-test ] && am_doing_phase second_stage; then
	if doing_variant fakechroot; then
		ret=0; arch-test "$ARCH" || ret=$?
	# Avoid failure with old arch-test package
	elif arch-test --version > /dev/null 2>&1; then
		ret=0; arch-test -c "$TARGET" "$ARCH" || ret=$?
	else
		ret=3
	fi

	case $ret in
	0)      info ARCHEXEC "Target architecture can be executed" ;;
	1)      error 1 ARCHNOTEXEC "Unable to execute target architecture" ;;
	*)      info ARCHEXECUNKNOWN "Can't verify that target arch works" ;;
	esac
fi

###########################################################################



if [ "$UNPACK_TARBALL" ]; then
	if [ "${UNPACK_TARBALL#/}" = "$UNPACK_TARBALL" ]; then
		error 1 TARPATH "Tarball must be given an absolute path"
	fi
	if [ "${UNPACK_TARBALL%.tar}" != "$UNPACK_TARBALL" ]; then
		(cd "$TARGET" && tar -xf "$UNPACK_TARBALL")
	elif [ "${UNPACK_TARBALL%.tar.[g|x]z}" != "$UNPACK_TARBALL" ]; then
		(cd "$TARGET" && tar -xf "$UNPACK_TARBALL")
	elif [ "${UNPACK_TARBALL%.tgz}" != "$UNPACK_TARBALL" ]; then
		(cd "$TARGET" && zcat "$UNPACK_TARBALL" | tar -xf -)
	else
		error 1 NOTTAR "Unknown tarball: must be .tar.[gz,xz], .tar or .tgz"
	fi
fi

###########################################################################

. "$SCRIPT"

MIRRORS="$DEF_MIRROR"
if [ "$USER_MIRROR" != "" ]; then
	MIRRORS="${USER_MIRROR%/}"
fi

export MIRRORS

ok=false
for v in $SUPPORTED_VARIANTS; do
	if doing_variant "$v"; then ok=true; fi
done
if ! "$ok"; then
	error 1 UNSUPPVARIANT "unsupported variant"
fi

###########################################################################

if am_doing_phase finddebs; then
	if [ "$FINDDEBS_NEEDS_INDICES" = "true" ] || \
	   [ "$RESOLVE_DEPS" = "true" ]; then
		download_indices
		GOT_INDICES=true
	fi

	work_out_debs

	base=$(without "$base $ADDITIONAL" "$EXCLUDE")
	required=$(without "$required" "$EXCLUDE")

	if [ "$RESOLVE_DEPS" = true ]; then
		requiredX=$(echo "$required" | tr ' ' '\n' | sort | uniq)
		baseX=$(echo "$base" | tr ' ' '\n' | sort | uniq)

		info RESOLVEREQ "Resolving dependencies of required packages..."
		required=$(resolve_deps "$requiredX")
		info RESOLVEBASE "Resolving dependencies of base packages..."
		base=$(resolve_deps "$baseX")
		base=$(without "$base" "$required")

		if [ "$LOG_EXTRA_DEPS" = true ]; then
			baseN=$(without "$baseX" "$requiredX")
			baseU=$(without "$baseX" "$baseN")

			if [ "$baseU" != "" ]; then
		  		info REDUNDANTBASE "Found packages in base already in required: %s" "$baseU"
			fi

			requiredX=$(without "$required" "$requiredX")
			baseX=$(without "$base" "$baseX")
			if [ "$requiredX" != "" ]; then
				info NEWREQUIRED "Found additional required dependencies: %s" "$requiredX"
			fi
			if [ "$baseX" != "" ]; then
				info NEWBASE "Found additional base dependencies: %s" "$baseX"
			fi
		fi
	fi

	all_debs="$required $base"
fi

if am_doing_phase printdebs; then
	echo "$all_debs"
fi

if am_doing_phase dldebs; then
	if [ "$GOT_INDICES" != "true" ]; then
		download_indices
	fi
	download "$all_debs"
fi

if am_doing_phase save_variables; then
	cp "$0"				 "$TARGET/debootstrap/debootstrap"
	cp "$DEBOOTSTRAP_DIR/functions"	 "$TARGET/debootstrap/functions"
	cp "$SCRIPT"			 "$TARGET/debootstrap/suite-script"
	# pick up common setting scripts
	cp "$DEBOOTSTRAP_DIR"/scripts/*-common	"$TARGET/debootstrap/"
	echo "$ARCH"			>"$TARGET/debootstrap/arch"
	echo "$SUITE"			>"$TARGET/debootstrap/suite"
	[ "" = "$EXTRA_SUITES" ] ||
	echo "$EXTRA_SUITES"		>"$TARGET/debootstrap/extra-suites"
	[ "" = "$VARIANT" ] ||
	echo "$VARIANT"			>"$TARGET/debootstrap/variant"
	echo "$required"		>"$TARGET/debootstrap/required"
	echo "$base"			>"$TARGET/debootstrap/base"

	chmod 755 "$TARGET/debootstrap/debootstrap"
fi

if am_doing_phase maketarball; then
	(cd "$TARGET";
	 tar czf - var/lib/apt var/cache/apt debootstrap) >"$MAKE_TARBALL"
fi

if am_doing_phase first_stage; then
	choose_extractor

	if [ -n "$UNPACK_TARBALL" ]; then
		required=$(cat "$TARGET/debootstrap/required")
		base=$(cat "$TARGET/debootstrap/base")
		all_debs="$required $base"
	fi

	# first stage sets up the chroot -- no calls should be made to
	# "chroot $TARGET" here; but they should be possible by the time it's
	# finished
	first_stage_install

	if ! am_doing_phase second_stage; then
		cp "$0"				 "$TARGET/debootstrap/debootstrap"
		cp "$DEBOOTSTRAP_DIR/functions"	 "$TARGET/debootstrap/functions"
		cp "$SCRIPT"			 "$TARGET/debootstrap/suite-script"
		# pick up common setting scripts
		cp "$DEBOOTSTRAP_DIR"/scripts/*-common	"$TARGET/debootstrap/"
		echo "$ARCH"			>"$TARGET/debootstrap/arch"
		echo "$SUITE"			>"$TARGET/debootstrap/suite"
		[ "" = "$EXTRA_SUITES" ] ||
		echo "$EXTRA_SUITES"		>"$TARGET/debootstrap/extra-suites"
		echo "$USER_MIRROR"		>"$TARGET/debootstrap/mirror"
		[ "" = "$VARIANT" ] ||
		echo "$VARIANT"			>"$TARGET/debootstrap/variant"
		echo "$required"		>"$TARGET/debootstrap/required"
		echo "$base"			>"$TARGET/debootstrap/base"

		chmod 755 "$TARGET/debootstrap/debootstrap"
	fi

	# create sources.list
	if [ "${MIRRORS#http*://}" != "$MIRRORS" ]; then
		setup_apt_sources "${MIRRORS%% *}"
	else
		setup_apt_sources "$DEF_MIRROR"
	fi
fi

if am_doing_phase second_stage; then
	if [ "$SECOND_STAGE_ONLY" = true ]; then
		required=$(cat "$DEBOOTSTRAP_DIR/required")
		base=$(cat "$DEBOOTSTRAP_DIR/base")
		all_debs="$required $base"
	fi

	# second stage uses the chroot to clean itself up -- has to be able to
	# work from entirely within the chroot (in case we've booted into it,
	# possibly over NFS eg)
	second_stage_install

	if [ -e "$TARGET/debootstrap/debootstrap.log" ]; then
		if [ "$KEEP_DEBOOTSTRAP_DIR" = true ]; then
			cp "$TARGET/debootstrap/debootstrap.log" "$TARGET/var/log/bootstrap.log"
		else
			# debootstrap.log is still open as stdout/stderr and needs
			# to remain so, but after unlinking it some NFS servers
			# implement this by a temporary file in the same directory,
			# which makes it impossible to rmdir that directory.
			# Moving it instead works around the problem.
			mv "$TARGET/debootstrap/debootstrap.log" "$TARGET/var/log/bootstrap.log"
		fi
	fi
	sync

	if [ "$KEEP_DEBOOTSTRAP_DIR" = true ]; then
		if [ -x "$TARGET/debootstrap/debootstrap" ]; then
			chmod 644 "$TARGET/debootstrap/debootstrap"
		fi
	else
		rm -rf "$TARGET/debootstrap"
	fi
fi

if am_doing_phase kill_target; then
	if [ "$KEEP_DEBOOTSTRAP_DIR" != true ]; then
                info KILLTARGET "Deleting target directory"
		rm -rf --one-file-system "$TARGET"
	fi
fi
