# $Id$
# vim:et:ft=sh:sts=2:sw=2
#
# git-flow -- A collection of Git extensions to provide high-level
# repository operations for Vincent Driessen's branching model.
#
# A blog post presenting this model is found at:
#    http://blog.avirtualhome.com/development-workflow-using-git/
#
# Feel free to contribute to this project at:
#    http://github.com/petervanderdoes/gitflow
#
# Authors:
# Copyright 2012-2017 Peter van der Does. All rights reserved.
#
# Original Author:
# Copyright 2010 Vincent Driessen. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
#    list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
#    this list of conditions and the following disclaimer in the documentation
#    and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#

initialize() {
	require_git_repo
	require_gitflow_initialized
	git config --get gitflow.prefix.hotfix >/dev/null 2>&1 || die "Hotfix prefix not set. Please run 'git flow init'."
	gitflow_load_settings
	VERSION_PREFIX=$(git config --get gitflow.prefix.versiontag)
	PREFIX=$(git config --get gitflow.prefix.hotfix)
}

usage() {
	OPTIONS_SPEC="\
git flow hotfix [list]
git flow hotfix start
git flow hotfix finish
git flow hotfix publish
git flow hotfix delete

Manage your hotfix branches.

For more specific help type the command followed by --help
--
"
	flags_help
}

cmd_default() {
	cmd_list "$@"
}

cmd_list() {
	OPTIONS_SPEC="\
git flow hotfix [list] [-h] [-v]

Lists all local hotfix branches
--
h,help!           Show this help
v,verbose!        Verbose (more) output
"
	local hotfix_branches current_branch width branch len
	local base master_sha branch_sha

	# Define flags
	DEFINE_boolean 'verbose' false 'verbose (more) output' v

	# Parse arguments
	parse_args "$@"

	hotfix_branches=$(git_local_branches_prefixed "$PREFIX")
	if [ -z "$hotfix_branches" ]; then
		warn "No hotfix branches exist."
		warn ""
		warn "You can start a new hotfix branch:"
		warn ""
		warn "    git flow hotfix start <version> [<base>]"
		warn ""
		exit 0
	fi
	current_branch=$(git_current_branch)

	# Determine column width first
	width=0
	for branch in $hotfix_branches; do
		len=${#branch}
		width=$(max $width $len)
	done
	width=$(($width+3-${#PREFIX}))

	for branch in $hotfix_branches; do
		base=$(git merge-base "$branch" "$MASTER_BRANCH")
		master_sha=$(git rev-parse "$MASTER_BRANCH")
		branch_sha=$(git rev-parse "$branch")
		if [ "$branch" = "$current_branch" ]; then
			printf "* "
		else
			printf "  "
		fi
		if flag verbose; then
			printf "%-${width}s" "${branch#$PREFIX}"
			if [ "$branch_sha" = "$master_sha" ]; then
				printf "(no commits yet)"
			else
				local tagname=$(git name-rev --tags --no-undefined --name-only "$base")
				local nicename
				if [ "$tagname" != "" ]; then
					nicename=$tagname
				else
					nicename=$(git rev-parse --short "$base")
				fi
				printf "(based on $nicename)"
			fi
		else
			printf "%s" "${branch#$PREFIX}"
		fi
		echo
	done
}

cmd_help() {
	usage
	exit 0
}

# Parse arguments and set common variables
parse_args() {
	FLAGS "$@" || exit $?
	eval set -- "${FLAGS_ARGV}"

	# Read arguments into global variables
	if [ -z $1 ]; then
		VERSION=''
	else
		VERSION=$1
	fi
	BRANCH=$PREFIX$VERSION
}

require_no_existing_hotfix_branches() {
	local hotfix_branches first_branch

	hotfix_branches=$(git_local_branches_prefixed "$PREFIX")
	first_branch=$(echo ${hotfix_branches} | head -n1)

	first_branch=${first_branch#$PREFIX}
	[ -z "$hotfix_branches" ] || die "There is an existing hotfix branch '$first_branch'. Finish that one first."
}

cmd_start() {
	OPTIONS_SPEC="\
git flow hotfix start [-h] [-F] <version> [<base>]

Start new hotfix branch named <version>, optionally base it on <base> instead of the <master> branch
--
h,help!           Show this help
showcommands!     Show git commands while executing them
F,[no]fetch       Fetch from origin before performing local operation
"
	local base

	# Define flags
	DEFINE_boolean 'fetch' false "fetch from $ORIGIN before performing finish" F

	# Override defaults with values from config
	gitflow_override_flag_boolean   "hotfix.start.fetch"   "fetch"

	# Parse arguments
	parse_args "$@"
	eval set -- "${FLAGS_ARGV}"
	base=${2:-$MASTER_BRANCH}

	# No need to continue if not clean
	require_base_is_local_branch "$base"
	git_config_bool_exists "gitflow.allowdirty" || require_clean_working_tree

	# Update the local repo with remote changes, if asked
	if flag fetch; then
		git_fetch_branch "$ORIGIN" "$base"
	fi

	# Run filter on the version
	VERSION=$(run_filter_hook hotfix-start-version $VERSION)
	if [ $? -eq 127 ]; then
		die $VERSION
	fi

	# As VERSION might have changed reset BRANCH with new VERSION
	BRANCH=$PREFIX$VERSION

	gitflow_require_version_arg
	if ! $(git config --bool --get gitflow.multi-hotfix 2>&1); then
		require_no_existing_hotfix_branches
	fi

	# Sanity checks
	require_branch_absent "$BRANCH"
	require_tag_absent "$VERSION_PREFIX$VERSION"
	if git_remote_branch_exists "$ORIGIN/$base"; then
		require_branches_equal "$base" "$ORIGIN/$base"
	fi

	run_pre_hook "$VERSION_PREFIX$VERSION" "$ORIGIN" "$BRANCH" "$base"

	gitflow_config_set_base_branch $base $BRANCH

	# Create branch
	git_do checkout -b "$BRANCH" "$base"  || die "Could not create hotfix branch '$BRANCH'."

	run_post_hook "$VERSION_PREFIX$VERSION" "$ORIGIN" "$BRANCH" "$base"

	echo
	echo "Summary of actions:"
	echo "- A new branch '$BRANCH' was created, based on '$base'"
	echo "- You are now on branch '$(git_current_branch)'"
	echo
	echo "Follow-up actions:"
	echo "- Start committing your hot fixes"
	echo "- Bump the version number now!"
	echo "- When done, run:"
	echo
	echo "     git flow hotfix finish '$VERSION'"
	echo
}

cmd_publish() {
	OPTIONS_SPEC="\
git flow hotfix publish [-h] <version>

Start sharing hotfix <name> on $ORIGIN
--
h,help!           Show this help
showcommands!     Show git commands while executing them
"
	# Parse arguments
	parse_args "$@"

	# Use current branch if no version is given
	if [ "$VERSION" = "" ]; then
		gitflow_use_current_branch_version
	fi

	# Sanity checks
	require_clean_working_tree
	require_branch "$BRANCH"
	git_do fetch -q "$ORIGIN" || die "Could not fetch branch '$BRANCH' from remote '$ORIGIN'."
	require_branch_absent "$ORIGIN/$BRANCH"

	run_pre_hook "$VERSION_PREFIX$VERSION" "$ORIGIN" "$BRANCH"

	# Create remote branch with remote tracking
	git_do push -u "$ORIGIN" "$BRANCH:$BRANCH"
	git_do fetch -q "$ORIGIN" "$BRANCH" || die "Could not fetch branch '$BRANCH' from remote '$ORIGIN'."
	git_do checkout "$BRANCH" || die "Could not check out branch '$BRANCH'."

	run_post_hook "$VERSION_PREFIX$VERSION" "$ORIGIN" "$BRANCH"

	echo
	echo "Summary of actions:"
	echo "- The remote branch '$BRANCH' was created or updated"
	echo "- The local branch '$BRANCH' was configured to track the remote branch"
	echo "- You are now on branch '$(git_current_branch)'"
	echo
}

cmd_rebase() {
	OPTIONS_SPEC="\
git flow hotfix rebase [-h] [-i] [-p] [<name|nameprefix>]

Rebase <name> on <base_branch>
--
h,help!                Show this help
showcommands!          Show git commands while executing them
i,[no]interactive      Do an interactive rebase
p,[no]preserve-merges  Preserve merges
"
	local opts

	# Define flags
	DEFINE_boolean 'interactive' false 'do an interactive rebase' i
	DEFINE_boolean 'preserve-merges' false 'try to recreate merges' p

	# Override defaults with values from config
	gitflow_override_flag_boolean   "hotfix.rebase.interactive"       "interactive"
	gitflow_override_flag_boolean   "hotfix.rebase.preserve-merges"   "preserve_merges"

	# Parse arguments
	parse_args "$@"

	# Use current branch if no version is given
	if [ "$VERSION" = "" ]; then
		gitflow_use_current_branch_version
	fi

	BASE_BRANCH=$(gitflow_config_get_base_branch $BRANCH)
	BASE_BRANCH=${BASE_BRANCH:-$DEVELOP_BRANCH}

	warn "Will try to rebase '$NAME' which is based on '$BASE_BRANCH'..."
	if ! git_config_bool_exists "rebase.autostash"; then
		require_clean_working_tree
	fi
	require_branch "$BRANCH"

	git_local_branch_exists "$BASE_BRANCH" || die "The base '$BASE_BRANCH' doesn't exists locally or is not a branch. Can't rebase the hotfixe branch '$BRANCH'."

	git_do checkout -q "$BRANCH"  || die "Could not check out branch '$BRANCH'."
	if flag interactive; then
		opts="$opts -i"
	fi
	if flag preserve_merges; then
		opts="$opts -p"
	fi
	git_do rebase $opts "$BASE_BRANCH"
}

cmd_track() {
	OPTIONS_SPEC="\
git flow hotfix track [-h] <version>

Create a tracking hotfix branch from $ORIGIN
--
h,help!           Show this help
showcommands!     Show git commands while executing them
"
	# Parse arguments
	parse_args "$@"

	gitflow_require_version_arg

	# Sanity checks
	require_clean_working_tree
	require_branch_absent "$BRANCH"
	git_do fetch -q "$ORIGIN"
	require_branch "$ORIGIN/$BRANCH"

	# Create tracking branch
	git_do checkout -b "$BRANCH" "$ORIGIN/$BRANCH"

	echo
	echo "Summary of actions:"
	echo "- A new remote tracking branch '$BRANCH' was created"
	echo "- You are now on branch '$BRANCH'"
	echo
}

cmd_finish() {
	OPTIONS_SPEC="\
git flow hotfix finish [-h] [-F] [-s] [-u] [-m | -f ] [-p] [-k] [-n] [-b] [-S] <version>

Finish hotfix branch <version>
--
h,help!               Show this help
showcommands!         Show git commands while executing them
F,[no]fetch           Fetch from origin before performing finish
s,[no]sign            Sign the release tag cryptographically
u,[no]signingkey      Use the given GPG-key for the digital signature (implies -s)
m,[no]message         Use the given tag message
f,[no]messagefile=    Use the contents of the given file as tag message
p,[no]push            Push to origin after performing finish
k,[no]keep            Keep branch after performing finish
[no]keepremote        Keep the remote branch
[no]keeplocal         Keep the local branch
D,[no]force_delete    Force delete hotfix branch after finish
n,[no]notag           Don't tag this hotfix
b,[no]nobackmerge     Don't back-merge master, or tag if applicable, in develop
S,[no]squash          Squash hotfix during merge
T,tagname!            Use given tag name
"
	local opts commit keepmsg remotebranchdeleted localbranchdeleted

	# Define flags
	DEFINE_boolean 'fetch' false "fetch from $ORIGIN before performing finish" F
	DEFINE_boolean 'sign' false "sign the release tag cryptographically" s
	DEFINE_string  'signingkey' "" "use the given GPG-key for the digital signature (implies -s)" u
	DEFINE_string  'message' "" "use the given tag message" m
	DEFINE_string  'messagefile' "" "use the contents of the given file as tag message" f
	DEFINE_boolean 'push' false "push to $ORIGIN after performing finish" p
	DEFINE_boolean 'keep' false "keep branch after performing finish" k
	DEFINE_boolean 'keepremote' false "keep the remote branch"
	DEFINE_boolean 'keeplocal' false "keep the local branch"
	DEFINE_boolean 'force_delete' false "force delete hotfix branch after finish" D
	DEFINE_boolean 'notag' false "don't tag this hotfix" n
	DEFINE_boolean 'nobackmerge' false "don't back-merge $MASTER_BRANCH, or tag if applicable, in $DEVELOP_BRANCH " b
	DEFINE_boolean 'squash' false "squash release during merge" S
	DEFINE_boolean 'squash-info' false "add branch info during squash"
	DEFINE_string  'tagname' "" "use the given tag name" T

	# Override defaults with values from config
	gitflow_override_flag_boolean   "hotfix.finish.fetch"          "fetch"
	gitflow_override_flag_boolean   "hotfix.finish.sign"           "sign"
	gitflow_override_flag_boolean   "hotfix.finish.push"           "push"
	gitflow_override_flag_boolean   "hotfix.finish.keep"           "keep"
	gitflow_override_flag_boolean   "hotfix.finish.keepremote"     "keepremote"
	gitflow_override_flag_boolean   "hotfix.finish.keeplocal"      "keeplocal"
	gitflow_override_flag_boolean   "hotfix.finish.force-delete"   "force_delete"
	gitflow_override_flag_boolean   "hotfix.finish.notag"          "notag"
	gitflow_override_flag_boolean   "hotfix.finish.nobackmerge"    "nobackmerge"
	gitflow_override_flag_boolean   "hotfix.finish.squash"         "squash"
	gitflow_override_flag_boolean   "hotfix.finish.squash-info"    "squash_info"
	gitflow_override_flag_string    "hotfix.finish.signingkey"     "signingkey"
	gitflow_override_flag_string    "hotfix.finish.message"        "message"
	gitflow_override_flag_string    "hotfix.finish.messagefile"    "messagefile"

	# Parse arguments
	parse_args "$@"

	# Use current branch if no version is given
	if [ "$VERSION" = "" ]; then
		gitflow_use_current_branch_version
	fi

	# Use branch name if no tag name is given
	if [ "$FLAGS_tagname" != "" ]; then
		TAGNAME=$FLAGS_tagname
	else
		TAGNAME=$VERSION
	fi

	remotebranchdeleted=$FLAGS_FALSE
	localbranchdeleted=$FLAGS_FALSE

	# Handle flags that imply other flags
	if [ "$FLAGS_signingkey" != "" ]; then
		FLAGS_sign=$FLAGS_TRUE
	fi

	# Keeping both branches implies the --keep flag to be true.
	if flag keepremote && flag keeplocal; then
		FLAGS_keep=$FLAGS_TRUE
	fi

	# Sanity checks
	require_branch "$BRANCH"
	require_clean_working_tree

	BASE_BRANCH=$(gitflow_config_get_base_branch $BRANCH)
	BASE_BRANCH=${BASE_BRANCH:-$MASTER_BRANCH}
	git_local_branch_exists "$BASE_BRANCH" || die "The base '$BASE_BRANCH' doesn't exists locally or is not a branch. Can't finish the hotfix branch '$BRANCH'."

	# We always fetch the Branch from Origin
	# This is done to avoid possible commits on the remote that are not
	# merged into the local branch
	if git_remote_branch_exists "$ORIGIN/$BRANCH"; then
		git_fetch_branch "$ORIGIN" "$BRANCH"
	fi

	# Update local branches with remote branches
	if flag fetch; then
		git_fetch_branch "$ORIGIN" "$BASE_BRANCH"
		[ "$BASE_BRANCH" = "$MASTER_BRANCH" ] && git_fetch_branch "$ORIGIN" "$DEVELOP_BRANCH"
	fi

	# Check if the local branches have all the commits from the remote branches
	if git_remote_branch_exists "$ORIGIN/$BRANCH"; then
		require_branches_equal "$BRANCH" "$ORIGIN/$BRANCH"
	fi
	if git_remote_branch_exists "$ORIGIN/$BASE_BRANCH"; then
		require_branches_equal "$BASE_BRANCH" "$ORIGIN/$BASE_BRANCH"
	fi
	if [ "$BASE_BRANCH" = "$MASTER_BRANCH" ]; then
		if git_remote_branch_exists "$ORIGIN/$DEVELOP_BRANCH"; then
			require_branches_equal "$DEVELOP_BRANCH" "$ORIGIN/$DEVELOP_BRANCH"
		fi
	fi

	# If the branch is already merged there is no need to check the hotfix branch
	# This can happen when the merge in develop fails and we rerun the finish.
	if ! git_is_branch_merged_into "$BRANCH" "$BASE_BRANCH"; then
		# Check if the hotfix branch:
		# - has commits: No reason to finish a hotfix without commits
		# - Is ahead of the BASE: If it's not a good idea to merge
		# - Can be merged: If there's no common ancestor we can't merge the hotfix
		git_compare_refs "$BRANCH" "$BASE_BRANCH"
		case $? in
		0)
			die "You need some commits in the hotfix branch '$BRANCH'"
			;;
		1)
			die "The hotfix branch '$BRANCH' is not ahead of branch '$BASE_BRANCH'"
			;;
		4)
			die "The hotfix branch '$BRANCH' has no common ancestor with branch '$BASE_BRANCH'"
			;;
		*)
			;;
		esac
	fi

	if noflag notag; then
		# We ask for a tag, be sure it does not exists or
		# points to the latest hotfix commit
		if git_tag_exists "$VERSION_PREFIX$TAGNAME"; then
			git_compare_refs  "$BRANCH" "$VERSION_PREFIX$TAGNAME"^2 2>/dev/null
			[ $? -eq 0 ] || die "Tag already exists and does not point to hotfix branch '$BRANCH'"
		fi
	fi

	run_pre_hook "$VERSION_PREFIX$TAGNAME" "$ORIGIN" "$BRANCH"

	# Try to merge into BASE.
	# In case a previous attempt to finish this release branch has failed,
	# but the merge into BASE was successful, we skip it now
	if ! git_is_branch_merged_into "$BRANCH" "$BASE_BRANCH"; then
		git_do checkout "$BASE_BRANCH" || die "Could not check out branch '$BASE_BRANCH'."
		if noflag squash; then
			git_do merge --no-ff "$BRANCH" || die "There were merge conflicts." # TODO: What do we do now?
		else
			git_do merge --squash "$BRANCH" || die "There were merge conflicts." # TODO: What do we do now?
			flag squash_info && gitflow_create_squash_message "Merged hotfix branch '$BRANCH'" "$BASE_BRANCH" "$BRANCH" > "$DOT_GIT_DIR/SQUASH_MSG"
			git_do commit
		fi
	fi

	if noflag notag; then
		# Try to tag the release.
		# In case a previous attempt to finish this release branch has failed,
		# but the tag was set successful, we skip it now
		if ! git_tag_exists "$VERSION_PREFIX$TAGNAME"; then
			if [ "$FLAGS_message" != "" ] && [ "$FLAGS_messagefile" != "" ]; then
				die "Use either -m,--message or -f,--messagefile. Can not use both options at the same time"
			fi
			opts="-a"
			flag sign && opts="$opts -s"
			[ "$FLAGS_signingkey" != "" ] && opts="$opts -u '$FLAGS_signingkey'"
			if [ "$FLAGS_message" != "" ]; then
				# Run filter on the tag message
				FLAGS_message=$(run_filter_hook hotfix-finish-tag-message "${FLAGS_message}" "$VERSION_PREFIX$TAGNAME")
				opts="$opts -m '$FLAGS_message'"
			fi
			[ "$FLAGS_messagefile" != "" ] && opts="$opts -F '$FLAGS_messagefile'"
			eval git_do tag $opts "$VERSION_PREFIX$TAGNAME" || die "Tagging failed. Please run finish again to retry."
		fi
	fi

	if [ "$BASE_BRANCH" = "$MASTER_BRANCH" ]; then
		# By default we back-merge the $MASTER_BRANCH unless the user explicitly
		# stated not to do a back-merge, in that case we use the $BRANCH.
		if noflag nobackmerge; then
			MERGE_BRANCH="$BASE_BRANCH"
		else
			MERGE_BRANCH="$BRANCH"
		fi

		# Try to merge into develop.
		# In case a previous attempt to finish this release branch has failed,
		# but the merge into develop was successful, we skip it now
		if ! git_is_branch_merged_into "$MERGE_BRANCH" "$DEVELOP_BRANCH"; then
			git_do checkout "$DEVELOP_BRANCH" || die "Could not check out branch '$DEVELOP_BRANCH'."

			if noflag nobackmerge; then
				# Accounting for 'git describe', if a release is tagged
				# we use the tag commit instead of the branch.
				if noflag notag; then
					commit="$VERSION_PREFIX$TAGNAME"
				else
					commit="$BASE_BRANCH"
				fi
			else
				commit="$BRANCH"
			fi

			git_do merge --no-ff "$commit" || die "There were merge conflicts."
			# TODO: What do we do now?
		fi
	fi

	run_post_hook "$VERSION_PREFIX$TAGNAME" "$ORIGIN" "$BRANCH"

	# Delete branch
	if noflag keep; then

		# Always delete remote first
		if noflag keepremote;then
			if git_remote_branch_exists "$ORIGIN/$BRANCH"; then
				git_remote_branch_delete "$BRANCH" && remotebranchdeleted=$FLAGS_TRUE
			fi
		fi

		# Delete local after remote to avoid warnings
		if noflag keeplocal; then
			if [ "$BRANCH" = "$(git_current_branch)" ]; then
				git_do checkout "$DEVELOP_BRANCH" || die "Could not check out branch '$DEVELOP_BRANCH'."
			fi
			if flag force_delete; then
				git_do branch -D "$BRANCH" && localbranchdeleted=$FLAGS_TRUE
			else
				git_do branch -d "$BRANCH" && localbranchdeleted=$FLAGS_TRUE
			fi
		fi

		# no more branches: we can safely remove config section
		if ! git_remote_branch_exists "$ORIGIN/$BRANCH" -a ! git_local_branch_exists "$BRANCH"; then
			gitflow_config_remove_base_section "$BRANCH"
		fi

	fi

	if flag push; then
		if [ "$BASE_BRANCH" = "$MASTER_BRANCH" ]; then
			git_do push "$ORIGIN" "$DEVELOP_BRANCH" || die "Could not push branch '$DEVELOP_BRANCH' to remote '$ORIGIN'."
		fi
		git_do push "$ORIGIN" "$BASE_BRANCH" || die "Could not push branch '$BASE_BRANCH' to remote '$ORIGIN'."
		if noflag notag; then
			git_do push --tags "$ORIGIN" || die "Could not push tags to remote '$ORIGIN'."
		fi
	fi

	echo
	echo "Summary of actions:"
	if flag fetch; then
		echo "- Latest objects have been fetched from '$ORIGIN'"
	fi
	echo "- Hotfix branch '$BRANCH' has been merged into '$BASE_BRANCH'"
	if noflag notag; then
		echo "- The hotfix was tagged '$VERSION_PREFIX$TAGNAME'"
	fi
	if [ "$BASE_BRANCH" = "$MASTER_BRANCH" ]; then
		[ "$commit" = "$BASE_BRANCH" ] && echo "- Master branch '$BASE_BRANCH' has been back-merged into '$DEVELOP_BRANCH'"
		[ "$commit" = "$VERSION_PREFIX$TAGNAME" ] && echo "- Hotfix tag '$VERSION_PREFIX$TAGNAME' has been back-merged into '$DEVELOP_BRANCH'"
		[ "$commit" = "$BRANCH" ] && echo "- Hotfix branch '$BRANCH' has been merged into '$DEVELOP_BRANCH'"
	fi
	if noflag keep; then
		if [ $localbranchdeleted -eq $FLAGS_TRUE ]; then
			keepmsg="has been locally deleted"
		else
			keepmsg="is still locally available"
		fi
		if [ $remotebranchdeleted -eq $FLAGS_TRUE ]; then
			keepmsg=$keepmsg"; it has been remotely deleted from '$ORIGIN'"
		elif git_remote_branch_exists "$ORIGIN/$BRANCH"; then
			keepmsg=$keepmsg"; it is still remotely available on '$ORIGIN'"
		fi
	else
		keepmsg="is still locally available"
		if git_remote_branch_exists "$ORIGIN/$BRANCH"; then
			keepmsg=$keepmsg"; it is still remotely available on '$ORIGIN'"
		fi
	fi
	echo "- Hotfix branch '$BRANCH' "$keepmsg
	if flag push; then
		if [ "$BASE_BRANCH" = "$MASTER_BRANCH" ]; then
			echo "- '$DEVELOP_BRANCH', '$BASE_BRANCH' and tags have been pushed to '$ORIGIN'"
		else
			echo "- '$BASE_BRANCH' and tags have been pushed to '$ORIGIN'"
		fi
	fi
	echo "- You are now on branch '$(git_current_branch)'"
	echo

}

cmd_delete() {
	OPTIONS_SPEC="\
git flow hotfix delete [-h] [-f] [-r] <name>

Delete the given hotfix branch
--
h,help!               Show this help
showcommands!         Show git commands while executing them
f,[no]force           Force deletion
r,[no]remote          Delete remote branch
"
	local current_branch

	# Define flags
	DEFINE_boolean 'force' false "force deletion" f
	DEFINE_boolean 'remote' false "delete remote branch" r

	# Override defaults with values from config
	gitflow_override_flag_boolean   "hotfix.delete.force"    "force"
	gitflow_override_flag_boolean   "hotfix.finish.remote"   "remote"

	# Parse arguments
	parse_args "$@"

	gitflow_require_version_arg

	# Sanity checks
	require_branch "$BRANCH"

	run_pre_hook "$VERSION" "$ORIGIN" "$BRANCH"

	current_branch=$(git_current_branch)
	# We can't delete a branch we are on, switch to the master branch.
	if [ "$BRANCH" = "$current_branch" ]; then
		require_clean_working_tree
		git_do checkout "$MASTER_BRANCH" || die "Could not check out branch '$MASTER_BRANCH'."
	fi

	if ( git_is_branch_merged_into "$BRANCH" "$MASTER_BRANCH" && git_is_branch_merged_into "$BRANCH" "$DEVELOP_BRANCH" ); then
		git_do branch -d "$BRANCH" || die "Could not delete the $BRANCH."
		if flag remote; then
			git_remote_branch_delete "$BRANCH"
		fi
	else
		if flag force; then
			git_do branch -D "$BRANCH" || die "Could not delete the $BRANCH."
			if flag remote; then
				git_remote_branch_delete "$BRANCH"
			fi
		else
			die "Hotfix branch '$BRANCH' has been not been merged in branch '$MASTER_BRANCH' and/or branch '$DEVELOP_BRANCH'. Use -f to force the deletion."
		fi
	fi

	gitflow_config_remove_base_section "$BRANCH"
	run_post_hook "$VERSION" "$ORIGIN" "$BRANCH"

	echo
	echo "Summary of actions:"
	echo "- Hotfix branch '$BRANCH' has been deleted."
	flag remote && echo "- Hotfix branch '$BRANCH' in '$ORIGIN' has been deleted."
	echo "- You are now on branch '$(git_current_branch)'"
	echo
}

cmd_rename() {
	OPTIONS_SPEC="\
git flow hotfix rename <new_name> [<new_name>]

Rename a given hotfix branch
--
h,help!          Show this help
showcommands!    Show git commands while executing them
"
	gitflow_rename_branch "$@"
}
