#!/bin/bash
# Desc: Initializes a git repository

#==BEGIN Define script parameters==
#===BEGIN Declare local script functions===
yell() { echo "$0: $*" >&2; }      #o Yell, Die, Try Three-Fingered Claw technique
die() { yell "$*"; exit 111; }     #o Ref/Attrib: https://stackoverflow.com/a/25515370
try() { "$@" || die "cannot $*"; } #o
checkURL() {
    # Desc: Checks if string is a valid URL.
    # Warning: Does not correctly handle multi-byte characters.
    # Version: 0.0.2
    # Input: arg1: string
    # Output: return code 0: string is a valid URL
    #         return code 1: string is NOT a valid URL
    # Depends: Bash 5.0.3
    # Ref/Attrib: https://stackoverflow.com/a/3184819
    regex='(https?|ftp|file|ssh|git)://[-A-Za-z0-9\+&@#/%?=~_|!:,.;]*[-A-Za-z0-9\+&@#/%=~_|]'
    arg1="$1";
    if [[ $arg1 =~ $regex ]]; then
	return 0;
    else
	return 1;
    fi;
} # Check if arg1 is valid URL
initGitRepo() {
    # Desc: Creates, adds remotes to, and pulls to git repository
    # Note: Does nothing if repoDir is already initialized git repo.
    # Usage: createGitRepo arg1 arg2 arg3 arg4
    # Input: arg1: repoURL
    #        arg2: repoDir
    #        arg3: remoteName
    #        arg4: branchName
    # Version: 0.0.7
    # Depends: checkURL() 0.0.2, yell(), Bash 5.0.3
    # Ref/Attrib: [1]: Test for space-less alphanuemric string. https://unix.stackexchange.com/a/416120
    #             [2]: Test for argument count. https://stackoverflow.com/q/18568706
    #             [3]: Test if dir is (in) git repository. https://stackoverflow.com/a/39518382
    # Note: Pulls use '--ff-only' option which requires an upstream branch be set.
    #   This can be done by using:
    #     $ git branch --set-upstream-to origin/master master
    # 
    #==BEGIN Validate input arguments==
    arg1="$1";
    arg2="$2";
    arg3="$3";
    arg4="$4";
    # Validate repoURL
    if checkURL "$arg1"; then repoURL="$arg1";
    else yell "ERROR:Not a valid URL:$arg1"; return 1; fi;

    # Passthrough repoDir (it may not exist yet)
    repoDir="$arg2";
    
    # Validate remoteName
    if [[ "$arg3" =~ ^[[:alnum:]]+$ ]]; then remoteName="$arg3";
    else yell "ERROR:Not a valid remote name:$arg3"; return 1; fi;  # See [1].

    # Validate branchName
    if [[ "$arg4" =~ ^[[:alnum:]]+$ ]]; then branchName="$arg4";
    else yell "ERROR:Not a valid remote branch name:$arg4"; return 1; fi;  # See [1].

    # Check argument count
    if [[ $# -gt 4 ]]; then yell "ERROR:Too many arguments."; return 1; fi;  # See [2].
    #==END Validate input arguments==
    #==BEGIN create and populate git repository==
    if [[ ! -d "$repoDir" ]]; then mkdir "$repoDir"; fi;
    pushd "$repoDir" || return 1;
    if ! git -C "$(pwd)" rev-parse 1>/dev/null 2>&1; then
	yell "STATUS:Initializing as git repo:$repoDir";
	git init;  # Init repo if not already a git repo. See [3]
    else
	yell "STATUS:Already a git repository:$repoDir";
	git status; git remote -v;
    fi;
    yell "STATUS:Adding $repoURL as remote $remoteName";
    git remote add "$remoteName" "$repoURL";
    yell "STATUS:Pulling branch $branchName from remote $remoteName";
    git pull --ff-only "$remoteName" "$branchName";
    unset repoURL repoDir remoteName branchName;
    popd || exit 1;
    #==END create and populate git repository==
    yell "================================";
} # Init Git Repository
#===END Declare local script functions===
#==END Define script parameters==

#==BEGIN sample code
tmpDir=/tmp/"$(date +%Y%m%dT%H%M%S%z)";
mkdir -p "$tmpDir";
pushd "$tmpDir" || exit 1;

repoURL="https://zdv2.bktei.com/gitweb/baltakatei-exdev.git";
repoDir="BK-2020-03..bkexdev";
remoteName="zdv2";
branchName="master";
initGitRepo "$repoURL" "$repoDir" "$remoteName" "$branchName";
unset repoURL repoDir remoteName branchName;

yell "STATUS:Done.";
#==END sample code

# Author: Steven Baltaktei Sandoval
# License: GPLv3+