#!/bin/bash
#########################################################
# 							#
# This is BashStyle-NG					#
#							#
# Licensed under GNU GENERAL PUBLIC LICENSE v3    	#
#							#
# Copyright Christopher Bratusek			#
#							#
#########################################################

. gettext.sh
export TEXTDOMAIN="bashstyle-rc"

gitkit_ssh_add () {
	if check bt "$(bashstyle --ini-get git_ssh_remember)"; then
		check P "ssh-add" "remembering SSH password" || exit 1

		eval git_ssh_keyfile="$(bashstyle --ini-get git_ssh_keyfile)"

		local git_ssh_timeout="$(bashstyle --ini-get git_ssh_timeout)"
		local ssh_add_keys="$(ssh-add -l | gawk '{print $3}')"

		if [[ "${ssh_add_keys}" != *${git_ssh_keyfile}* ]]; then
			echo -e "$(eval_gettext "\n${egreen}[0] ssh-add ${git_ssh_keyfile}\n")"
			ssh-add -t "${git_ssh_timeout}" "${git_ssh_keyfile}"
		fi
	fi
}

github_clone () {
	check P "wget" "'gitkit cloneorg/cloneuser'" || exit 1
	check P "xe" "'gitkit cloneorg/cloneuser'" || exit 1

	wget -qO - https://api.github.com/"${1}"/"${2}"/repos?per_page=200 | \
		awk -F\" '/ssh_url/{print $4}' | xe git clone
}

github_list () {
	# https://www.commandlinefu.com/commands/view/24836/print-all-git-repos-from-a-user-only-curl-and-grep
	check P "curl" "'gitkit listorg/listuser'" || exit 1

	curl -s https://api.github.com/"${1}"/"${2}"/repos?per_page=1000 | \
		grep -oP '(?<="git_url": ").*(?="\,)'
}

case ${1} in

	action)
		if [[ -d .git ]]; then
			if [[ -f .git/dotest/rebasing ]]; then
				ACTION="rebase"
			elif [[ -f .git/dotest/applying ]]; then
				ACTION="apply"
			elif [[ -f .git/dotest-merge/interactive ]]; then
				ACTION="rebase -i"
			elif [[ -d .git/dotest-merge ]]; then
				ACTION="rebase -m"
			elif [[ -f .git/MERGE_HEAD ]]; then
				ACTION="merge"
			elif [[ -f .git/index.lock ]]; then
				ACTION="locked"
			elif [[ -f .git/BISECT_LOG ]]; then
				ACTION="bisect"
			else	ACTION="nothing"
			fi
			echo ${ACTION}
		else	echo --
		fi
	;;

	branch)
		if [[ -d .git ]]; then
			BRANCH=$(git symbolic-ref HEAD 2>/dev/null)
			echo "${BRANCH#refs/heads/}"
		else	echo --
		fi
	;;

	bz2)
		if [[ -d .git ]]; then
			git archive master | bzip2 -9 > "$(basename "${PWD}")".tar.bz2
		else	echo "$(eval_gettext "current directory is not the root of a git repository")"
		fi
	;;

	xz)
		if [[ -d .git ]]; then
			git archive master | xz -9 > "$(basename "${PWD}")".tar.xz
		else	echo "$(eval_gettext "current directory is not the root of a git repository")"
		fi
	;;

	zip)
		if [[ -d .git ]]; then
			git archive master --format=zip > "$(basename "${PWD}")".zip
		else	echo "$(eval_gettext "current directory is not the root of a git repository")"
		fi
	;;

	cloneuser)
		github_clone users "${2}"
	;;
	
	cloneorg)
		github_clone orgs "${2}"
	;;

	listuser)
		github_list users "${2}"
	;;

	listorg)
		github_list orgs "${2}"
	;;

	export)
		[[ -n "${2}" && -d .git ]] && git checkout-index --prefix="${2}"/ -a
	;;

	funmsg)
		check P "wget" "'gitkit funmsg'" || exit 1
		wget -qO - http://whatthecommit.com/index.txt
	;;

	openweb | web)
		if [ -d .git ]; then
			repo_url=$(git remote -v | gawk '/origin.*fetch/{print $2}')
			case "${repo_url}" in
				git@* )
					repo_url=$(echo "${repo_url}" | sed 's,:,/,;s,.*@,https://,')
					x-www-browser "${repo_url}" &
				;;

				http* )
					x-www-browser "${repo_url}" &
				;;

				* )
					echo "$(eval_gettext "couldn't parse web location")"
				;;
			esac
		else	echo "$(eval_gettext "current directory is not the root of a git repository")"
		fi
	;;

	revision)
		if [ -d .git ]; then
			REVISION=$(git rev-parse HEAD 2>/dev/null)
			REVISION=${REVISION/HEAD/}
			echo "${REVISION:0:6}"
		else	echo --
		fi
	;;

	revno)
		if [[ -d .git ]]; then
			git rev-list --reverse HEAD | \
				awk "/$(git log -n 1 --pretty="format:%h")/ {print NR}"
		else	echo --
		fi
	;;

	undelete)
		if [ -d .git ]; then
			git checkout "$(git ls-files --deleted)"
		else	echo "$(eval_gettext "current directory is not the root of a git repository")"
		fi
	;;

	push)
		gitkit_ssh_add

		echo -e "$(eval_gettext "\n${eblue}[1] push to upstream\n")"
		git push

		echo -e "$(eval_gettext "\n${ecyan}[2] push tags to upstream\n")"
		git push --tag

		if [ -f "${PWD}/.git_mirror" ]; then
			echo -e "$(eval_gettext "\n${emagenta}[3] push to mirror\n")"
			for repo in "$(cat ${PWD}/.git_mirror)"; do
				echo -e "$(eval_gettext "${eyellow} * mirror: ${repo}\n")"
				git push --mirror "${repo}"
			done
		fi
	;;

	taga)
		shift
		tag=${1}

		if [ -n "$(git tag -l "${tag}")" ]; then
			echo "$(eval_gettext "tag ${tag} already exists!")"
		else
			gitkit_ssh_add

			echo -e "$(eval_gettext "\n${eblue}[1] create local tag ${tag}\n")"
			git tag -a "${@}" || exit 1

			echo -e "$(eval_gettext "\n${ecyan}[2] push tag to remote\n")"
			git push --tag
		fi
	;;

	tagd)
		shift
		tag=${1}

		if [ -z "$(git tag -l "${1}")" ]; then
			echo "$(eval_gettext "tag ${tag} does not exist!")"
		else
			gitkit_ssh_add

			echo -e "$(eval_gettext "\n${eblue}[1] remove local tag ${tag}\n")"
			git tag -d "${1}" || exit 1

			echo -e "$(eval_gettext "\n${ecyan}[2] remove remote tag\n")"
			git push origin :refs/tags/"${1}"
		fi
	;;

	tagr)
		shift
		in_TAG="${1}"
		out_TAG="${2}"

		if [ -z "$(git tag -l "${in_TAG}")" ]; then
			echo "$(eval_gettext "tag ${in_TAG} does not exist!")"
			exit 1
		fi

		if [ -n "$(git tag -l "${out_TAG}")" ]; then
			echo "$(eval_gettext "tag ${out_TAG} already exists!")"
			exit 1
		fi

		TAG_msg="$(git tag -n1 "${in_TAG}" | gawk '{sub($1 FS,"")}1')"
		TAG_commit="$(git rev-list -n1 "${in_TAG}")"

		gitkit tagd "${in_TAG}"
		gitkit taga "${out_TAG}" -m "${TAG_msg}" "${TAG_commit}"
	;;

	tagc)
		shift
		TAG="${1}"
		COM="${2}"

		if [ -z "$(git tag -l "${TAG}")" ]; then
			echo "$(eval_gettext "tag ${TAG} does not exist!")"
			exit 1
		fi

		if [ ! "$(git rev-parse "${COM}")" ]; then
			echo "$(eval_gettext "commit ${COM} does not exist!")"
			exit 1
		fi

		TAG_msg="$(git tag -n1 "${in_TAG}" | gawk '{sub($1 FS,"")}1')"

		gitkit tagd "${TAG}"
		gitkit taga "${TAG}" -m "${TAG_msg}" "${COM}"
	;;

	*)
		bashstyle-help -a "Christopher Roy Bratusek" -e "nano@jpberlin.de" -h "https://www.nanolx.org/"\
			-l "GNU GPL v3" -n "gitkit" -s "$(eval_gettext "various companion functions for Git")"\
			-v "${BSNG_VERSION}" -y "${BSNG_YEAR}"\
			-o "$(eval_gettext "action:|print the current action in a Git repo")"\
			-o "$(eval_gettext "branch:|print the current branch in a Git repo")"\
			-o "$(eval_gettext "bz2:|create bz2 archive from a Git repo")"\
			-o "$(eval_gettext "xz:|create xz archive from a Git repo")"\
			-o "$(eval_gettext "zip:|create zip archive from a Git repo")"\
			-o "$(eval_gettext "cloneuser:username|clone all repos from a GitHub user (SSH)")"\
			-o "$(eval_gettext "cloneorg:organization|clone all repos from a GitHub organization (SSH)")"\
			-o "$(eval_gettext "listuser:username|list all repos from a GitHub user")"\
			-o "$(eval_gettext "listorg:organization|list all repos from a GitHub organization")"\
			-o "$(eval_gettext "export:directory|export Git repo for release tarball")"\
			-o "$(eval_gettext "funmsg:|create funny Git commit message")"\
			-o "$(eval_gettext "web:|open project page using x-www-browser")"\
			-o "$(eval_gettext "revision:|get 6 digit revision from a Git repo")"\
			-o "$(eval_gettext "revno:|get traditional revision number from a Git repo")"\
			-o "$(eval_gettext "undelete:|undelete files accidentally deleted locally")"\
			-o "$(eval_gettext "push:|push/push tag upstream + push to mirror in one go")"\
			-o "$(eval_gettext "taga:tag [-m msg commit]|create a tag and push remote")"\
			-o "$(eval_gettext "tagd:tag|remove tag locally and remote")"\
			-o "$(eval_gettext "tagr:tag newtag|rename a tag locally and remote")"\
			-o "$(eval_gettext "tagc:tag newcommit|make tag point to different commit")"
	;;
esac
