#! /bin/bash

usage=$(cat << EOF

Usage: $0 [-h] [-a] [-r] [-k] [-w] [-b Commit/Tag/Branch]

    -a Apply all the changes to all repositories in the current tree.
    
    -b Update to a commit/tag/branch. This is useful if you work on a single
       branch/tag in all repositories. If the requested repository is not 
       found it falls back to the recent version. The -k and -i options are
       useful here.
       
    -h Prints this usage information
    
    -i Update to a commit/tag/branch with the -b flag in interactive mode.
       This asks if you want to fall back to the recent version if the
       requested commit/tag/branch is not found.
       This is only useful with the -b flag.
       
    -k This does not pull from the remote repository, just updates the
       repositories.
    
    -r Revert to the last version. This is not deleting the pull commit,
       just updating back to your last state.
    
    -w Do the pull over https instead of ssh
EOF
)

SAVED_STATE_FILE=~/.hg.saved

#set selected repository to current folder
SELECTED_REPOS=$(pwd)

source repo_update_helper.sh

#################################
#Parse arguments
#################################
while getopts "arb:hikw" flag
do
    case $flag in
        a)
            #update all repositories in the directory tree
            SELECTED_REPOS=$(find_repos)
            ;;
        r)
            #revert to commits after the last pull from the server
            REVERT="1"
            ;;
        b)
            #update to a tag/branch/commit
            VERSION=$OPTARG
            ;;
        k)
            NO_UPDATE="1"
            ;;
        i)
            INTERACTIVE_UPDATE="1"
            ;;
        w)
            REMOTE="http"
            ;;
        h)
            echo "$usage"
            exit 0
            ;;
        *)
            echo "$usage"
            exit 0
            ;;
    esac
done

if [ ! -e $SAVED_STATE_FILE ]
then
    touch $SAVED_STATE_FILE
fi
SAVED_STATE=$(cat $SAVED_STATE_FILE | sed "s/^$//g")
BASE_FOLDER=$(pwd)

#################################
# Revert changes and exit.
#################################
if [ -n "$REVERT" ]
then
    print_info "Reverting changes"
    for REPO in $SELECTED_REPOS
    do
        cd $REPO
        pwd
        
        REVERT_COMMIT=$(echo "$SAVED_STATE" | grep "$PWD " | grep -o -E "[a-z0-9]{12}")
        if [ -z "$REVERT_COMMIT" ]
        then
            echo "No saved commit."
            cd $BASE_FOLDER
            continue
        fi
        hg update $REVERT_COMMIT

        cd $BASE_FOLDER
    done
    exit 0
fi

#################################
# Save the current current state of the repository
#################################
print_info "Saving current commit."
for REPO in $SELECTED_REPOS
do
    cd $REPO
    pwd
    if [ 0 -ne $? ]
    then 
        echo "Cannot change to repository $REPO"
        exit 1
    fi
    
    STATE=$(hg summary)
    if [ 0 -ne $? ]
    then 
        echo "Not a repository: $REPO"
        exit 1
    fi
    CURRENT_COMMIT=$(echo "$STATE" | grep -o -E "[0-9]:[a-z0-9]{12}" | grep -o -E "[a-z0-9]{12}")
    
    #remove current repository from saved state
    SAVED_STATE=$(echo "$SAVED_STATE" | grep -v "$PWD ")
    SAVED_STATE=$(echo -e "$SAVED_STATE" && echo "$PWD $CURRENT_COMMIT")
    
    cd $BASE_FOLDER 
done
echo "$SAVED_STATE" > $SAVED_STATE_FILE

#################################
# Pull changes from remote server.
#################################
if [ -z "$NO_UPDATE" ]
then
    print_info "Pull changes from remote."
    for REPO in $SELECTED_REPOS
    do
        cd $REPO
        pwd
        hg pull $REMOTE
        if [ 0 -ne $? ]
        then
            echo "An issue occured while pulling changes from remote server."
            exit 1
        fi
        
        cd $BASE_FOLDER
    done
fi

#################################
# Update repository to most recent version
#################################
print_info "Updating repositories."
for REPO in $SELECTED_REPOS
do
    cd $REPO
    pwd
    
    if [ -n "$VERSION" ]
    then
        hg update $VERSION
        if [ 0 -ne $? ]
        then
            #update not possible. falling back to recent version or interactive mode
            if [ -n "$INTERACTIVE_UPDATE" ]
            then
                while true
                do
                    read -p "Fallback to recent version? [y/n]: " answer
                    if [ "$answer" = "y" ]
                    then
                        hg update
                        break
                    fi
                    if [ "$answer" = "n" ]
                    then
                        echo "Not updated."
                        break
                    fi
                done
            else
                hg update
            fi
        fi
    else
        hg update
    fi
    if [ 0 -ne $? ]
    then
        echo "Error updating the repository."
        exit 1
    fi
    
    cd $BASE_FOLDER
done
