#!/bin/sh -e

export LC_ALL=C LANG=C LANGUAGE=C

spt_dir=/usr/share/mspt
. $spt_dir/spt-sh-functions

show_help()
{
    [ -z "$*" ] || Info "$*"
    cat <<EOF
spt - make image of custom configured system using profile

Usage: $PROG [options] <path-to-workdir>

Valid options are:
  --mkiso                  make ISO image (compatible only with squashfs)
  --noiso                  do not make ISO image
  --noboot                 do not make boot actions (like initrd/syslinux/etc)
  --isoname=NAME           ISO image filename
  --image-type=TYPE        image archive/filesystem type:
     TYPE:
        squashfs           squashfs (default)
        ext2               ext2fs
        tbz2               tarball + bzip2 (always --noiso)
        tgz                tarball + gzip  (always --noiso)
  --skip-root              skip root creation
  --excludedocs            exclude docs during install
  --arch=ARCH              target architecture
  --apt-config=FILE        path to custom apt.conf file
  --apt-prefix=DIR         path to apt directory prefix (e.g. /usr)
  -p, --profile-dir=DIR    path to profile dir.
  -q, --quiet              try to be more quiet
  -v, --verbose            print a message from each action
  -V, --version            print program version and exit
  -h, --help               show this text and exit

Report bugs to http://bugs.altlinux.org/

EOF
    exit
}

TEMP=`getopt -n $PROG -o P:p:,v,q,V,h -l mkiso,noiso,noboot,init,isoname:,image-type:,skip-root,excludedocs,arch:,apt-config:,apt-prefix:,profile:,profile-dir:,verbose,help,quiet,version -- "$@"` || show_usage
eval set -- "$TEMP"

mkiso=1
mkboot=1
quiet=
isoname=
profile_dir=
ARCH=
apt_config=
apt_prefix=
skip_root=
excludedocs=
image_type='squashfs'
while :; do
    case "$1" in
	--mkiso) mkiso=1
	    ;;
	--noiso) 
		mkiso=
	    ;;
	--noboot) 
		mkboot=
		mkiso=
		;;
	--isoname) shift; isoname="${1##*/}"; mkiso=1
	    ;;
	--image-type) shift; 
	    case "$1" in
		    squashfs)
			    image_type="$1"
			    ;;
		    tbz2|tgz)
			    image_type="$1"
			    mkiso=
			    ;;
		    *)
			    Fatal "--image-type: $1: not known image type."
			    ;;
	    esac
	    ;;
	--skip-root) skip_root=1
	    ;;
	--excludedocs) excludedocs=--excludedocs
	    ;;
	--arch) shift; ARCH="$1"
	    [ -x "$ARCH" ] || ARCH=$(uname -m)
	    ;;
	--apt-config) shift
		apt_config="$(readlink -ev "$1")" && 
			[ -r "$apt_config" ] ||
			Fatal "$1: file not available."
	    ;;
	--apt-prefix) shift
		apt_prefix="$(readlink -ev "$1")" &&
			[ -d "$apt_prefix" -a -x "$apt_prefix" ] ||
			Fatal "$1: directory not available."
	    ;;
	-p|--profile-dir) shift; profile_dir="$1"
	    ;;
	-v|--verbose) verbose=-v
	    ;;
	-q|--quiet) quiet=-q
	    ;;
	-h|--help) show_help
	    ;;
	-V|--version) print_version "$PROG"
	    ;;
	--) shift; break
	    ;;
	*) Fatal "Unrecognized option: $1"
	    ;;
    esac
    shift
done

# Exactly one argument, please.
[ "$#" -ge 1 ] || show_help 'Insufficient arguments.'
[ "$#" -le 1 ] || show_usage 'Too many arguments.'

[ -d "$1" ] || mkdir "$1"
workdir="$(readlink -ev "$1")" && shift
chroot="$workdir/chroot"

profile_dir="${profile_dir:-$workdir/profile}"
[ -f "$profile_dir/config" ] || show_usage 'Profile in workdir not found. Please, init directories stucture first.'
. "$profile_dir/config"

outdir="$workdir/out"
tmpdir="$workdir/tmp"

if [ -z "$skip_root" ]; then
    rm -rf $outdir $tmpdir
    mkdir -p $outdir $tmpdir

    [ -n "$COMPONENTS" ] || Fatal "Please, add COMPONENTS to configuration file"
    COMPONENTS_ID=
    INSTALLDIRS=

    for comp in $COMPONENTS; do
	DIRS=
	IDENT="packages"
	VENDOR="ALTLinux"
	COPYONLY=
	CLASS=
	INSTALLDIR=
	INSTALL2HASH=
	NOIMAGE=
	PAUSE=
	SIZEDOWN=
	POSTLOCAL=
	EXTRAOPTS=

	. $profile_dir/$comp || Fatal "File \`$profile_dir/$comp' not found."
	copy_init_list=`grep -h '^[^#]' $profile_dir/$DIRS`

	Verbose "Making component $comp"

	if [ -n "$COPYONLY" ]; then
		gen_aptbox
		copy_filelist="$(print_uris setup filesystem rpm $copy_init_list)" ||
			Fatal 'Failed to generate package file list.'

		[ -n "$copy_filelist" ] ||
			Fatal 'Nothing to copy.'

		[ ! -d "$outdir/$INSTALLDIR/" ] || rm -rf -- "$outdir/$INSTALLDIR/"
		mkdir -p -- "$outdir/$INSTALLDIR/"

		install -p -m644 $verbose -- $copy_filelist "$outdir/$INSTALLDIR/" ||
			Fatal "Could not copy packages from $IDENT.packages to $INSTALLDIR."

		COMPONENTS_ID="$COMPONENTS_ID $IDENT"
		INSTALLDIRS="$INSTALLDIRS $INSTALLDIR"

		[ -z "$FILES" ] ||
			rsync $verbose -rtlpC "$profile_dir/$FILES" "$outdir" ||
			Fatal "Could not copy additional files for \`$comp' component."

		# create hashes for apt-get
		[ -z "$COMPONENTS_ID" ] || gen_repo $outdir
		continue
	fi #COPYONLY

	init_chroot_progs

	[ -z "$FILES" ] ||
		rsync $verbose -rtlpC "$profile_dir/$FILES" "$outdir" ||
		Fatal "Could not copy additional files for \`$comp' component."

	# Install packages
	hsh-install "$workdir" $verbose $quiet \
	    ${excludedocs:+$excludedocs} \
	    --save-fakeroot \
	    $copy_init_list
	
	chmod +r $chroot/.{host,in,out}

	[ -z "$CLASS" ] || postinstall "$CLASS" "$chroot"
	[ -z "$POSTLOCAL" ] || postinstall_local "$profile_dir" "$POSTLOCAL" "$chroot"

	if [ -n "$mkboot" ]; then

		[ ! -d $outdir/isolinux ] || rm -rf $outdir/isolinux

		# copy memtest
		cat << EOF > $tmpdir/mkmemtest
MEMTEST="\$(ls -1 /boot/memtest* 2>/dev/null|head -1)"
if [ ! -z "\$MEMTEST" ]; then
		mkdir -- /.isolinux
		cp -f /boot/\${MEMTEST##*/} /.isolinux/memtest
fi
EOF
		chroot_exec "$tmpdir/mkmemtest" &&
			Verbose 'Memtest stuff make complete.' ||
			Fatal 'Memtest stuff make failed.'

		# copy bootlogo
		if [ -f "$chroot/usr/share/gfxboot/$THEME/bootlogo" ]; then
			cat << EOF > $tmpdir/mkgfxboot
mkdir -- /.isolinux
cp -a /usr/share/gfxboot/$THEME/bootlogo /.isolinux/bootlogo
EOF
			chroot_exec "$tmpdir/mkgfxboot" && 
				Verbose 'Gfxboot stuff make complete.' ||
				Fatal 'Gfxboot stuff make failed.'
		fi

		if [ -d "$chroot/etc/bootsplash/themes/current/config" -a -x "$chroot/sbin/splash" ]; then
			cat << EOF > $tmpdir/mkbootsplash
mkdir -- /.isolinux
cd /etc/bootsplash/themes/current/config
for n in bootsplash-*.cfg; do
		[ "\$n" != "bootsplash-*.cfg" ] || break
		name="\${n##*/}"
		X="\$(echo \$name | sed -e 's/.*-\(.*\)x\(.*\)\.cfg/\1/' | xargs printf '%04d')"
		Y="\$(echo \$name | sed -e 's/.*-\(.*\)x\(.*\)\.cfg/\2/' | xargs printf '%04d')"
		filename="\$X\$Y.spl"
		tmpspl="\$(mktemp -d /spl.XXXXXXXXXX)"
		/sbin/splash -f -s \$n > \$tmpspl/bootsplash
		echo "file /bootsplash \$tmpspl/bootsplash 0777 0 0" |
		/usr/bin/gencpio - > /.isolinux/\$filename
		rm -rf \$tmpspl
done
EOF
			chroot_exec "$tmpdir/mkbootsplash" && 
				Verbose 'Bootsplash stuff make complete.' ||
				Fatal 'Bootsplash stuff make failed.'
		fi

		# copy boot stuff
		if [ -d $chroot/.isolinux ]; then
			mkdir -p $outdir/isolinux/
			cp -a $chroot/.isolinux/* $outdir/isolinux/
		fi
	fi

	# make archive for image
	Verbose "Creating archive image for \`$IDENT'."
	cp -a /bin/tar $chroot/.host/
	cat << EOF > $tmpdir/mktar
tar --numeric-owner --exclude /.archive.tar --exclude /.host --exclude /.isolinux --exclude /.splash --exclude /.in --exclude /.out --exclude /.fakedata --exclude /usr/lib*/*fakeroot* -cf /.archive.tar /
EOF
	chroot_exec "$tmpdir/mktar" &&
	    Verbose 'Chroot image arhivation complete.' ||
	    Fatal 'Chroot image arhivation failed.'

	[ -f $chroot/.archive.tar ] && cp -a $chroot/.archive.tar $tmpdir/

	[ -z "$NOIMAGE" ] || continue

	# create image
	Verbose "Creating image for \`$IDENT'."
	case "$image_type" in
	    squashfs)
		init_chroot_progs "squashfsprogs"
		cp -a $tmpdir/.archive.tar $chroot/tmp/
		cat << EOF > $tmpdir/mkfs
mkdir -p /tmp/.archive && cd /tmp/.archive
tar -xf /tmp/.archive.tar
mksquashfs /tmp/.archive /.altlinux.img $EXTRAOPTS
EOF
		chroot_exec "$tmpdir/mkfs"
		;;
	    tbz2)
		mkiso=
		cat "$tmpdir/.archive.tar" | bzip2 -f > "$outdir/$OUT.tar.bz2"
		;;
	    tgz)
		mkiso=
		cat "$tmpdir/.archive.tar" | gzip -f9 > "$outdir/$OUT.tar.gz"
		;;
	    *)
		Fatal 'Unsupported image type.'
		;;
	esac

	if [ -f $chroot/.altlinux.img ]; then
		# move image from chroot to outdir
		mv -f $chroot/.altlinux.img $outdir/$OUT
	fi
	postinstall image "$CLASS" $classdir/$CLASS/postimage.d

    done

fi

[ -n "$mkiso" -o -n "$mkboot" ] || exit 0
#
# make boot
#
# install init packages
init_chroot_progs "mar propagator syslinux $KERNEL"

[ -d $outdir/isolinux/alt0 ] && rm -rf $outdir/isolinux/alt0
mkdir -p $outdir/isolinux/alt0

# syslinux stuff
if [ -f $profile_dir/isolinux.cfg.in ]; then
	cp $profile_dir/isolinux.cfg.in $outdir/isolinux/isolinux.cfg
	cp $chroot/usr/lib/syslinux/isolinux.bin $outdir/isolinux/
fi
[ -f $profile_dir/syslinux.cfg.in ] && cp $profile_dir/syslinux.cfg.in $outdir/isolinux/syslinux.cfg

# copy profile & utils
for f in modules initfs; do
	cp -af $profile_dir/$f $chroot/.host/
done
cat << EOF > $tmpdir/mkboot
# kernel image
mkdir -p /.isolinux/alt0
cp -a /boot/vmlinuz-* /.isolinux/alt0/vmlinuz
kver=\$(rpm -q --qf '%{VERSION}-%{NAME}-%{RELEASE}' $KERNEL | sed -e 's,kernel\-image\-,,')

# generate marfile & co
mkdir -p /tmp/mkmar
/usr/bin/mkmar -r / \
    -p /.host/modules \
    -o /tmp/mkmar/modules \
    -k \$kver

# generate .VERSION
echo "${ORIGIN:+$ORIGIN }${VERSION:+$VERSION }${SUITE:+$SUITE }${CODENAME:+($CODENAME)}" > /tmp/.VERSION

# and create initramfs image
sed -e "s|@MODDIR@|/tmp/mkmar|g" \
    -e "s|@DOTVERSION@|/tmp/.VERSION|" \
    -e "s|@LIBDIR@|\$(getconf LIBDIR)|" \
    < /.host/initfs | gencpio - | gzip -c \
    > /full.cz
EOF

chroot_exec "$tmpdir/mkboot" && 
   Verbose 'Boot stuff make complete.' ||
   Fatal 'Boot stuff make failed.'

# copy boot stuff
cp -a $chroot/.isolinux/* $outdir/isolinux/
cp -a $chroot/full.cz $outdir/isolinux/alt0/

#
# make ISO image
#
mkdir -p $outdir/.disk
echo "${PUBLISHER:+$PUBLISHER }${VERSION:+$VERSION }${LABEL:+$LABEL }${CODENAME:+($CODENAME)}" > $outdir/.disk/info
CDFILENAME=${isoname:-$CDFILENAME}
CDFILENAME=${CDFILENAME:-livecd.iso}

mkisofs -b isolinux/isolinux.bin \
	-c isolinux/boot.cat \
	-copyright "LICENSE.html" \
	--volset "`cat $outdir/.disk/info`" \
	-V "$SUITE" \
	-publisher "$PUBLISHER" \
	-p `id -n -u` \
	-sysid "$ORIGIN" \
	-no-emul-boot \
	-boot-info-table \
	-boot-load-size 4 \
	-J -l -r \
	-o $workdir/$CDFILENAME $outdir
