#!/bin/bash
# author Jens Getreu 
# version 1.1.0
set -e
declare SCRIPT_NAME="$(basename $0)"
function usage {
    echo "Usage: $SCRIPT_NAME -l <absolute path to source file/dir>  "
    echo "                     <absolute path to destination dir>"
    echo
    echo "       $SCRIPT_NAME -l  links source file/dir"
    echo "       into destination directory using the shortest possible"
    echo "       relative path."
    echo "       It works like "ln -s" but with relative paths." 
    exit 1
}


# author of this fuction: juancn
#  http://stackoverflow.com/questions/2564634/
function find_relpath () {
    #echo "find_relpath $# parameters"; echo "$@"
    declare base=$1
    declare target=$2
    declare -a base_part=()
    declare -a target_part=()

    #Split path elements & canonicalize
    OFS="$IFS"; IFS='/'
    bpl=0;
    for bp in $base; do
        case "$bp" in
            ".");;
            "..") let "bpl=$bpl-1" ;;
            *) base_part[${bpl}]="$bp" ; let "bpl=$bpl+1";;
        esac
    done
    tpl=0;
    for tp in $target; do
        case "$tp" in
            ".");;
            "..") let "tpl=$tpl-1" ;;
            *) target_part[${tpl}]="$tp" ; let "tpl=$tpl+1";;
        esac
    done
    IFS="$OFS"
    
    #Count common prefix
    common=0
    for (( i=0 ; i<$bpl ; i++ )); do
        if [ "${base_part[$i]}" = "${target_part[$common]}" ] ; then
            let "common=$common+1"
        else
            break   
        fi
    done
    
    #Compute number of directories up
    let "updir=$bpl-$common" || updir=0 #if the expression is zero, 'let' fails
    
    #trivial case (after canonical decomposition)
    if [ $updir -eq 0 ]; then
         #echo ./
         result="./"
    fi
    
    #Print updirs
    for (( i=0 ; i<$updir ; i++ )); do
        #echo -n ../
        result="${result}../"
    done
    
    #Print remaining path
    for (( i=$common ; i<$tpl ; i++ )); do
        if [ $i -ne $common ]; then
            #echo -n "/"
            result="${result}/"
        fi
        if [ "" != "${target_part[$i]}" ] ; then
            #echo -n "${target_part[$i]}"
            result="${result}${target_part[$i]}"
        fi
    done
    #One last newline
}


# Start
 if [ $# -ne 3 ]||[ "$1" != "-s" ]; then usage;exit 1; fi

 #echo "main $# parameters"; echo "$@"
 # compute shortest path
 find_relpath "$3" "$2"  #quotes for not splitting whitespaces 

 # link it into $3
 echo "executing:  cd <$3>; ln -s <$result> <.>"
 pushd . >/dev/null
 cd "$3"
 ln -s "$result" .
 exit_code=$?
 popd >/dev/null
 exit $exit_code
