#!/bin/sh -e

# Moves a loopinstallation (e.g. Wubi) to a dedicated partition.

# Copyright (C) 2008 Agostino Russo <agostino.russo@gmail.com>

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option) any
# later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

dev=$1
swapdev=$2
target=/tmp/wubitarget
swap=/tmp/wubiswap    
usage="
The function should be invokes as follows:
\n
\n\tsudo sh $0 target_partition [swap_partition]
\n
\nFor instance, in order to move to /dev/sda3 use:
\n
\n\tsudo sh $0 /dev/sda3
\n
\nand if you want to have swap on sda5 use:
\n
\n\tsudo sh $0 /dev/sda3 /dev/sda5
\n
"

usage(){
    echo $usage
    exit 1
}

sanity_checks(){
    echo "Sanity checks..."
    if [ -z "$dev" ] || [ ! -b "$dev" ]; then
        echo "First argument (target_partition=$dev) must be a valid partition."
        usage    
    fi
    if [ -n "$swapdev" ] && [ ! -b "$swapdev" ]; then
        echo "Swapdevice=$swapdev is not a block device."            
        usage
    fi
    if [ "$(whoami)" != root ]; then
        echo "Admin rights are required to run this program."
        exit 1
    fi
    mkdir -p $target    
    umount $target 2> /dev/null || true
    if mount -t auto "$dev" $target 2> /dev/null; then
        if [ $(ls -1 $target | wc -l) -gt 1 ] || \
        [ "$(ls -1 $target)" != "lost+found" ]; then    
            echo "Volume $dev is in use. Aborting"
            umount $target || true        
            exit 1
        fi
        umount $target
    fi
}

create_root(){
    mkfs.ext3 $dev
    mount $dev $target
    size=$(df | awk '$5=="/" || $5=="/home" || $5=="/usr" {sum += $3} END {print sum}')
    free_space=$(df $target|tail -n 1|awk '{print $4}')
    if [ $free_space -lt $size ]; then
        echo "Not enough free space ($free_space MB < $size MB), aborting."
        exit 1
    fi
}

migrate_files(){
    echo "Migrating files..."
    rsync -av --exclude=/host --exclude=/mnt/* --exclude=/home/*/.gvfs --exclude=/media/*/* --exclude=/tmp/* --exclude=/proc/* --exclude=/sys/* / $target
}

edit_fstab(){
    echo "Editing fstab..."
    sed -i 's:/.*[\.]disk .*::' $target/etc/fstab
    sed -i 's:/.*/disks/boot .*::' $target/etc/fstab
    echo "UUID=$(vol_id --uuid $dev)    /    ext3    errors=remount-ro    0    1" >> $target/etc/fstab
    if [ -b "$swapdev" ]; then
        echo "UUID=$(vol_id --uuid $swapdev)    none    swap    sw    0    0" >> $target/etc/fstab
    fi
}

target_cmd(){
    mount -o bind /proc $target/proc
    mount -o bind /dev $target/dev
    mount -o bind /sys $target/sys
    chroot $target $*
    umount $target/proc
    umount $target/dev
    umount $target/sys     
}

edit_grub(){
    echo "Editing grub..."    
    sed -i "s:# groot=.*::" $target/boot/grub/menu.lst
    sed -i "s:kopt=.* ro:kopt=root=UUID=$(vol_id --uuid $dev) ro:" $target/boot/grub/menu.lst
    cp /usr/lib/grub/*/*stage* $target/boot/grub/    
    target_cmd update-grub
    disk=${dev%%[0-9]*}
    partn=${dev#$disk}
    disk=${disk##*/}
    gdisk=$(grep -w $disk /boot/grub/device.map|cut -d ')' -f 1)
    gdisk=${gdisk#\(}
    gpartn=$(expr $partn - 1)
    [ -z "$gdisk" ] && gdisk=hd0
    [ -z "$gpartn" ] && gpartn=0    
    echo "
    root ($gdisk,$gpartn)
    setup ($gdisk)
    setup (hd0)
    quit" | grub --batch --device-map=/boot/grub/device.map
}

remove_lupin_support(){
    echo "Removing lupin_support..."    
    target_cmd apt-get -y remove lupin-support
}

create_swap(){
    echo "Creating swap..."
    if [ -b "$swapdev" ]; then
        mkdir -p $swap        
        if mount -t auto "$swapdev" $swap 2> /dev/null; then
            echo "Volume $swapdev is in use. Skipping swap"
            umount $swap || true
        else
            mkswap $swapdev         
        fi
    fi
}

sanity_checks
create_root
create_swap
migrate_files
edit_fstab
remove_lupin_support
edit_grub
umount $dev
echo "\nOperation completed successfully, if all is good feel free to remove the installation from windows."


