#!/bin/sh
#
# @(#) create_rel_br
#
# Usage:
#   ./create_rel_br.sh -v 1.00_38 -b master -x
# Description
#   create and push release branch and tag.
# Return
#   0: Success
#   not 0: Fail

progname=${0##*/}
progdir=${0%/*}
export LANG=C

set -o pipefail

# オプションからパラメータを生成する
Verbose=0
Base_branch="master"
while getopts v:b:x OPT; do
    case "${OPT}" in
    v) Version="${OPTARG}" ;;
    b) Base_branch="${OPTARG}" ;;
    x) Verbose=1 ;;
    *) usage ;;
    esac
done
shift $((OPTIND - 1))

# 使用方法
usage() {
    cat <<EOF
$progname [-v ver] [-b base_branch] [-x verbose]
    -v ver バージョン指定。
        ?.??_? 形式。
    -b 派生元Branch (指定が無ければmaster)
    -x debug用表示追加
    releaseブランチの作成とversion.dat, specファイルのversion/dateを更新する。
EOF
    exit 2
}

# sony_fpgaか否か？
Sony_fpga=0
git remote -v | grep "sony_fpga.git" &>/dev/null
if (($? == 0)); then
    Sony_fpga=1
fi

# sony_fpga_driver_pyか否か？
Sony_fpga_driver_py=0
git remote -v | grep "sony_fpga_driver_py.git" &>/dev/null
if (($? == 0)); then
    Sony_fpga_driver_py=1
fi

cmd() {
    local cmd="$@"
    if ((${Verbose} == 1)); then
        echo ${cmd}
    fi
    eval "${cmd} 2>&1"
    return $?
}

# パラメータ決定
get_options() {
    if ((${Verbose} == 1)); then
        echo -e "\n<パラメータ一覧表示>"
    fi
    if [[ ! "${Version}" =~ ^[0-9]*.[0-9]*_[0-9a-zA-Z]*$ ]]; then
        echo " - Error: Input valid version ?.??_?"
        exit 1
    fi

    Tag=V$(echo "${Version}" | sed 's/\.//g')
    Rel_branch="release/${Tag}"

    Ver_file=$(find -maxdepth 3 -name version.dat -type f)

    Spec_file=$(find -maxdepth 1 -name \*.spec -type f)
    if ((${Sony_fpga_driver_py}==0)); then
        if ((${#Spec_file[@]} != 1)); then
            echo " - Error: Not found *.spec"
            exit 1
        fi
        if [[ ! -f "${Spec_file}" ]]; then
            echo " - Error: Not found *.spec"
            exit 1
        fi
    fi

    Timestamp=$(env LC_ALL=C TZ=Asia/Tokyo date '+%a %b %d %Y_%Y-%m-%d %H:%M')
    Message="Release ${Version} "$(echo -n "${Timestamp}" | cut -f 2 -d "_")

    if ((${Verbose} == 1)); then
        echo -e "\n<parameters>"
        echo " - version: ${Version}"
        echo " - tag: ${Tag}"
        echo " - rel_branch: ${Rel_branch}"
        for file in ${Ver_file[@]}; do
            echo " - ver_file: ${file}"
        done
        echo " - base_branch: ${Base_branch}"
        echo " - spec_file: ${Spec_file}"
        echo " - timestamp: ${Timestamp}"
        echo " - message: ${Message}"
    fi
}

# Release Branch作成元に戻る
return_base_br() {
    if ((${Verbose} == 1)); then
        echo -e "\n<Release Branch作成元に戻る>"
    fi

    cmd "git pull"

    cmd "git branch -a | grep remotes/origin/${Base_branch}" &>/dev/null
    if (($? != 0)); then
        echo " - Error: Not found remotes/origin/${Base_branch}"
        exit 1
    fi

    cmd "git checkout ${Base_branch}"
    if (($? != 0)); then
        echo " - Error: git checkout ${Base_branch}"
        exit 1
    fi
    if [[ "${Base_branch}" != $(git rev-parse --abbrev-ref HEAD) ]]; then
        echo " - Error: base branch ${Base_branch}"
        exit 1
    fi

    if ((${Verbose} == 1)); then
        echo -e "\n<サブモジュールを最新に更新する(コミット変更までは実施しない)>"
    fi
    cmd "git submodule update"
    if (($? != 0)); then
        echo " - Error: git submodule update"
        exit 1
    fi

    if ((${Verbose} == 1)); then
        echo -e "\n<更新ファイルの変更を元に戻す>"
    fi

    if ((${Sony_fpga_driver_py}==0)); then
        cmd "git checkout HEAD ${Spec_file}"
        if (($? != 0)); then
            echo " - Error: git checkout HEAD ${Spec_file}"
            exit 1
        fi
        for file in ${Ver_file[@]}; do
            cmd "git checkout HEAD ${file}"
            if (($? != 0)); then
                echo " - Error: git checkout HEAD ${file}"
                exit 1
            fi
        done
    fi
}

# Version/Branch/Tagの二重定義を許可しない
verify_double_define() {
    local old_version
    local old_branch
    local old_tag

    if ((${Sony_fpga_driver_py}==0)); then
        old_version=$(grep -E "^Version:" ${Spec_file} | sed -e "s/^Version: *\(.*\)$/\1/")
        if [[ "${Version}" == "${old_version}" ]]; then
            echo " - Error: [Version] ${Version} has been already used."
            exit 1
        fi
    fi

    old_branch=$(git branch -a | grep ${Rel_branch})
    for old in ${old_branch[@]}; do
        if [[ "${old}" ]]; then
            echo " - Error: [Branch] ${Rel_branch} has been already used. Please delete ${Rel_branch}."
            echo "   -> git branch -D ${Rel_branch}"
            echo "   -> git push --delete origin ${Rel_branch}"
            exit 1
        fi
    done

    old_tag=$(git tag | grep -E "${Tag}$")
    for old in ${old_tag[@]}; do
        if [[ "${old}" ]]; then
            echo " - Error: Tag [${Tag}] has been already used. Please delete ${Tag}."
            echo " - [Caution] 過去のリリースで使用したTagを削除してはいけません。"
            echo "   -> git tag -d ${Tag}"
            echo "   -> git push --delete origin ${Tag}"
            exit 1
        fi
    done
}

# Release Branchを新規作成する
checkout_release_br() {
    if ((${Verbose} == 1)); then
        echo -e "\n<Release Branchを新規作成する>"
    fi

    cmd "git checkout -b ${Rel_branch} ${Base_branch}"
    if (($? != 0)); then
        echo " - Error: git checkout -b ${Rel_branch}"
        exit 1
    fi
}

# specファイル、version.datファイル等を更新する
modify_file() {
    local change_log
    local module

    if ((${Sony_fpga}==1)); then
        if ((${Verbose} == 1)); then
            echo -e "\n<sony_fpga.hファイルを更新する>"
        fi

        # modify spec file
        change_log="\n* $(echo ${Timestamp} | cut -f 1 -d '_') ULM Project <ulm-soft@vsp.cpg.sony.co.jp> - ${Version}\n- Release Version: ${Version}\n"
        sed -i -e "s/^\(Version: *\).*$/\1${Version}/g" "${Spec_file}"
        sed -i -e "s/^\(%changelog\)$/\1$change_log/g" "${Spec_file}"

        # modify sony_fpga.h
        sed -i -e "s/^\(#define SONY_FPGA_DRIVER_VERSION *\).*$/\1\"${Version}\"/g" "sony_fpga.h"

    elif ((${Sony_fpga_driver_py}==1)); then
        if ((${Verbose} == 1)); then
            echo -e "\n<setup.pyファイルを更新する>"
        fi

        # modify setup.py
        sed -i -e "s/^\(    version=*\).*$/\1\'${Version}\',  \# Required/g" "setup.py"

    else
        if ((${Verbose} == 1)); then
            echo -e "\n<specファイルとversion.datファイルを更新する>"
        fi

        # modify spec file
        change_log="\n* $(echo ${Timestamp} | cut -f 1 -d '_') ULM Project <ulm-soft@vsp.cpg.sony.co.jp> - ${Version}\n- Release Version: ${Version}\n"
        sed -i -e "s/^\(Version: *\).*$/\1${Version}/g" "${Spec_file}"
        sed -i -e "s/^\(%changelog\)$/\1$change_log/g" "${Spec_file}"

        # modify version.dat file
        for file in ${Ver_file[@]}; do
            module=$(cat "${file}" | cut -f 1 -d " ")
            echo -n "${module} ${Version} " >"${file}"
            echo -n "${Timestamp}" | cut -f 2 -d "_" >>"${file}"
        done
    fi
}

# specファイルとversion.datファイルをgit addする
git_add() {
    if ((${Sony_fpga}==1)); then
        if ((${Verbose} == 1)); then
            echo -e "\n<sony_fpga.hファイルをgit addする>"
        fi
        cmd "git add ${Spec_file}"
        if (($? != 0)); then
            echo " - Error: git add ${Spec_file}"
            exit 1
        fi
        cmd "git add sony_fpga.h"
        if (($? != 0)); then
            echo " - Error: git add sony_fpga.h"
            exit 1
        fi

    elif ((${Sony_fpga_driver_py}==1)); then
        if ((${Verbose} == 1)); then
            echo -e "\n<setup.pyファイルをgit addする>"
        fi
        cmd "git add setup.py"
        if (($? != 0)); then
            echo " - Error: git add setup.py"
            exit 1
        fi

    else
        if ((${Verbose} == 1)); then
            echo -e "\n<specファイルとversion.datファイルをgit addする>"
        fi
        cmd "git add ${Spec_file}"
        if (($? != 0)); then
            echo " - Error: git add ${Spec_file}"
            exit 1
        fi
        for file in ${Ver_file[@]}; do
            cmd "git add ${file}"
            if (($? != 0)); then
                echo " - Error: git add ${file}"
                exit 1
            fi
        done
    fi
}

# git commitする
git_commit() {
    if ((${Verbose} == 1)); then
        echo -e "\n<git commitする>"
    fi
    cmd "git commit -m \"${Message}\""
    if (($? != 0)); then
        echo " - Error: git commit -m ${Message}"
        exit 1
    fi
}

# tag打ちをする
git_add_tag() {
    if ((${Verbose} == 1)); then
        echo -e "\n<tag打ちをする>"
    fi
    cmd "git tag -a ${Tag} -m \"${Message}\""
    if (($? != 0)); then
        echo " - Error: git tag -a ${Tag} -m ${Message}"
        exit 1
    fi
}

# git pushする
git_push() {
    if ((${Verbose} == 1)); then
        echo -e "\n<git pushする>"
    fi
    cmd "git push origin ${Rel_branch} ${Tag}"
    if (($? != 0)); then
        echo " - Error: git push origin ${Rel_branch} ${Tag}"
        exit 1
    fi
}

# メインシーケンス
get_options
return_base_br
verify_double_define
checkout_release_br
modify_file
git_add
git_commit
git_add_tag
git_push

echo
echo "Success!!"
exit 0
