1# $Id$
2# vim:et:ft=sh:sts=2:sw=2
3#
4# git-flow -- A collection of Git extensions to provide high-level
5# repository operations for Vincent Driessen's branching model.
6#
7# A blog post presenting this model is found at:
8#    http://blog.avirtualhome.com/development-workflow-using-git/
9#
10# Feel free to contribute to this project at:
11#    http://github.com/petervanderdoes/gitflow
12#
13# Authors:
14# Copyright 2012-2019 Peter van der Does. All rights reserved.
15#
16# Original Author:
17# Copyright 2010 Vincent Driessen. All rights reserved.
18#
19# Redistribution and use in source and binary forms, with or without
20# modification, are permitted provided that the following conditions are met:
21#
22# 1. Redistributions of source code must retain the above copyright notice, this
23#    list of conditions and the following disclaimer.
24# 2. Redistributions in binary form must reproduce the above copyright notice,
25#    this list of conditions and the following disclaimer in the documentation
26#    and/or other materials provided with the distribution.
27#
28# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
29# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
30# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
31# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
32# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
33# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
34# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
35# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38#
39
40initialize() {
41	require_git_repo
42	require_gitflow_initialized
43	git config --get gitflow.prefix.hotfix >/dev/null 2>&1 || die "Hotfix prefix not set. Please run 'git flow init'."
44	gitflow_load_settings
45	VERSION_PREFIX=$(git config --get gitflow.prefix.versiontag)
46	PREFIX=$(git config --get gitflow.prefix.hotfix)
47}
48
49usage() {
50	OPTIONS_SPEC="\
51git flow hotfix [list]
52git flow hotfix start
53git flow hotfix finish
54git flow hotfix publish
55git flow hotfix delete
56
57Manage your hotfix branches.
58
59For more specific help type the command followed by --help
60--
61"
62	flags_help
63}
64
65cmd_default() {
66	cmd_list "$@"
67}
68
69cmd_list() {
70	OPTIONS_SPEC="\
71git flow hotfix [list] [-h] [-v]
72
73Lists all local hotfix branches
74--
75h,help!           Show this help
76v,verbose!        Verbose (more) output
77"
78	local hotfix_branches current_branch width branch len
79	local base master_sha branch_sha
80
81	# Define flags
82	DEFINE_boolean 'verbose' false 'verbose (more) output' v
83
84	# Parse arguments
85	parse_args "$@"
86
87	hotfix_branches=$(git_local_branches_prefixed "$PREFIX")
88	if [ -z "$hotfix_branches" ]; then
89		warn "No hotfix branches exist."
90		warn ""
91		warn "You can start a new hotfix branch:"
92		warn ""
93		warn "    git flow hotfix start <version> [<base>]"
94		warn ""
95		exit 0
96	fi
97	current_branch=$(git_current_branch)
98
99	# Determine column width first
100	width=0
101	for branch in $hotfix_branches; do
102		len=${#branch}
103		width=$(max $width $len)
104	done
105	width=$(($width+3-${#PREFIX}))
106
107	for branch in $hotfix_branches; do
108		base=$(git merge-base "$branch" "$MASTER_BRANCH")
109		master_sha=$(git rev-parse "$MASTER_BRANCH")
110		branch_sha=$(git rev-parse "$branch")
111		if [ "$branch" = "$current_branch" ]; then
112			printf "* "
113		else
114			printf "  "
115		fi
116		if flag verbose; then
117			printf "%-${width}s" "${branch#$PREFIX}"
118			if [ "$branch_sha" = "$master_sha" ]; then
119				printf "(no commits yet)"
120			else
121				local tagname=$(git name-rev --tags --no-undefined --name-only "$base")
122				local nicename
123				if [ "$tagname" != "" ]; then
124					nicename=$tagname
125				else
126					nicename=$(git rev-parse --short "$base")
127				fi
128				printf "(based on $nicename)"
129			fi
130		else
131			printf "%s" "${branch#$PREFIX}"
132		fi
133		echo
134	done
135}
136
137cmd_help() {
138	usage
139	exit 0
140}
141
142# Parse arguments and set common variables
143parse_args() {
144	FLAGS "$@" || exit $?
145	eval set -- "${FLAGS_ARGV}"
146
147	# Read arguments into global variables
148	if [ -z $1 ]; then
149		VERSION=''
150	else
151		VERSION=$1
152	fi
153	BRANCH=$PREFIX$VERSION
154}
155
156require_no_existing_hotfix_branches() {
157	local hotfix_branches first_branch
158
159	hotfix_branches=$(git_local_branches_prefixed "$PREFIX")
160	first_branch=$(echo ${hotfix_branches} | head -n1)
161
162	first_branch=${first_branch#$PREFIX}
163	[ -z "$hotfix_branches" ] || die "There is an existing hotfix branch '$first_branch'. Finish that one first."
164}
165
166cmd_start() {
167	OPTIONS_SPEC="\
168git flow hotfix start [-h] [-F] <version> [<base>]
169
170Start new hotfix branch named <version>, optionally base it on <base> instead of the <master> branch
171--
172h,help!           Show this help
173showcommands!     Show git commands while executing them
174F,[no]fetch       Fetch from origin before performing local operation
175"
176	local base
177
178	# Define flags
179	DEFINE_boolean 'fetch' false "fetch from $ORIGIN before performing finish" F
180
181	# Override defaults with values from config
182	gitflow_override_flag_boolean   "hotfix.start.fetch"   "fetch"
183
184	# Parse arguments
185	parse_args "$@"
186	eval set -- "${FLAGS_ARGV}"
187	base=${2:-$MASTER_BRANCH}
188
189	# No need to continue if not clean
190	require_base_is_local_branch "$base"
191	git_config_bool_exists "gitflow.allowdirty" || require_clean_working_tree
192
193	# Update the local repo with remote changes, if asked
194	if flag fetch; then
195		git_fetch_branch "$ORIGIN" "$base"
196	fi
197
198	# Run filter on the version
199	VERSION=$(run_filter_hook hotfix-start-version $VERSION)
200	if [ $? -eq 127 ]; then
201		die $VERSION
202	fi
203
204	# As VERSION might have changed reset BRANCH with new VERSION
205	BRANCH=$PREFIX$VERSION
206
207	gitflow_require_version_arg
208	if ! $(git config --bool --get gitflow.multi-hotfix 2>&1); then
209		require_no_existing_hotfix_branches
210	fi
211
212	# Sanity checks
213	require_branch_absent "$BRANCH"
214	require_tag_absent "$VERSION_PREFIX$VERSION"
215	if git_remote_branch_exists "$ORIGIN/$base"; then
216		require_branches_equal "$base" "$ORIGIN/$base"
217	fi
218
219	run_pre_hook "$VERSION_PREFIX$VERSION" "$ORIGIN" "$BRANCH" "$base"
220
221	gitflow_config_set_base_branch $base $BRANCH
222
223	# Create branch
224	git_do checkout -b "$BRANCH" "$base"  || die "Could not create hotfix branch '$BRANCH'."
225
226	run_post_hook "$VERSION_PREFIX$VERSION" "$ORIGIN" "$BRANCH" "$base"
227
228	echo
229	echo "Summary of actions:"
230	echo "- A new branch '$BRANCH' was created, based on '$base'"
231	echo "- You are now on branch '$(git_current_branch)'"
232	echo
233	echo "Follow-up actions:"
234	echo "- Start committing your hot fixes"
235	echo "- Bump the version number now!"
236	echo "- When done, run:"
237	echo
238	echo "     git flow hotfix finish '$VERSION'"
239	echo
240}
241
242cmd_publish() {
243	OPTIONS_SPEC="\
244git flow hotfix publish [-h] <version>
245
246Start sharing hotfix <name> on $ORIGIN
247--
248h,help!           Show this help
249showcommands!     Show git commands while executing them
250"
251	# Parse arguments
252	parse_args "$@"
253
254	# Use current branch if no version is given
255	if [ "$VERSION" = "" ]; then
256		gitflow_use_current_branch_version
257	fi
258
259	# Sanity checks
260	require_clean_working_tree
261	require_branch "$BRANCH"
262	git_do fetch -q "$ORIGIN" || die "Could not fetch branch '$BRANCH' from remote '$ORIGIN'."
263	require_branch_absent "$ORIGIN/$BRANCH"
264
265	run_pre_hook "$VERSION_PREFIX$VERSION" "$ORIGIN" "$BRANCH"
266
267	# Create remote branch with remote tracking
268	git_do push -u "$ORIGIN" "$BRANCH:$BRANCH"
269	git_do fetch -q "$ORIGIN" "$BRANCH" || die "Could not fetch branch '$BRANCH' from remote '$ORIGIN'."
270	git_do checkout "$BRANCH" || die "Could not check out branch '$BRANCH'."
271
272	run_post_hook "$VERSION_PREFIX$VERSION" "$ORIGIN" "$BRANCH"
273
274	echo
275	echo "Summary of actions:"
276	echo "- The remote branch '$BRANCH' was created or updated"
277	echo "- The local branch '$BRANCH' was configured to track the remote branch"
278	echo "- You are now on branch '$(git_current_branch)'"
279	echo
280}
281
282cmd_rebase() {
283	OPTIONS_SPEC="\
284git flow hotfix rebase [-h] [-i] [-p] [<name|nameprefix>]
285
286Rebase <name> on <base_branch>
287--
288h,help!                Show this help
289showcommands!          Show git commands while executing them
290i,[no]interactive      Do an interactive rebase
291p,[no]preserve-merges  Preserve merges
292"
293	local opts
294
295	# Define flags
296	DEFINE_boolean 'interactive' false 'do an interactive rebase' i
297	DEFINE_boolean 'preserve-merges' false 'try to recreate merges' p
298
299	# Override defaults with values from config
300	gitflow_override_flag_boolean   "hotfix.rebase.interactive"       "interactive"
301	gitflow_override_flag_boolean   "hotfix.rebase.preserve-merges"   "preserve_merges"
302
303	# Parse arguments
304	parse_args "$@"
305
306	# Use current branch if no version is given
307	if [ "$VERSION" = "" ]; then
308		gitflow_use_current_branch_version
309	fi
310
311	BASE_BRANCH=$(gitflow_config_get_base_branch $BRANCH)
312	BASE_BRANCH=${BASE_BRANCH:-$DEVELOP_BRANCH}
313
314	warn "Will try to rebase '$NAME' which is based on '$BASE_BRANCH'..."
315	if ! git_config_bool_exists "rebase.autostash"; then
316		require_clean_working_tree
317	fi
318	require_branch "$BRANCH"
319
320	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'."
321
322	git_do checkout -q "$BRANCH"  || die "Could not check out branch '$BRANCH'."
323	if flag interactive; then
324		opts="$opts -i"
325	fi
326	if flag preserve_merges; then
327		opts="$opts -p"
328	fi
329	git_do rebase $opts "$BASE_BRANCH"
330}
331
332cmd_track() {
333	OPTIONS_SPEC="\
334git flow hotfix track [-h] <version>
335
336Create a tracking hotfix branch from $ORIGIN
337--
338h,help!           Show this help
339showcommands!     Show git commands while executing them
340"
341	# Parse arguments
342	parse_args "$@"
343
344	gitflow_require_version_arg
345
346	# Sanity checks
347	require_clean_working_tree
348	require_branch_absent "$BRANCH"
349	git_do fetch -q "$ORIGIN"
350	require_branch "$ORIGIN/$BRANCH"
351
352	# Create tracking branch
353	git_do checkout -b "$BRANCH" "$ORIGIN/$BRANCH"
354
355	echo
356	echo "Summary of actions:"
357	echo "- A new remote tracking branch '$BRANCH' was created"
358	echo "- You are now on branch '$BRANCH'"
359	echo
360}
361
362cmd_finish() {
363	OPTIONS_SPEC="\
364git flow hotfix finish [-h] [-F] [-s] [-u] [-m | -f ] [-p] [-k] [-n] [-b] [-S] <version>
365
366Finish hotfix branch <version>
367--
368h,help!               Show this help
369showcommands!         Show git commands while executing them
370F,[no]fetch           Fetch from origin before performing finish
371s,[no]sign            Sign the release tag cryptographically
372u,[no]signingkey      Use the given GPG-key for the digital signature (implies -s)
373m,[no]message         Use the given tag message
374f,[no]messagefile=    Use the contents of the given file as tag message
375p,[no]push            Push to origin after performing finish
376k,[no]keep            Keep branch after performing finish
377[no]keepremote        Keep the remote branch
378[no]keeplocal         Keep the local branch
379D,[no]force_delete    Force delete hotfix branch after finish
380n,[no]notag           Don't tag this hotfix
381b,[no]nobackmerge     Don't back-merge master, or tag if applicable, in develop
382S,[no]squash          Squash hotfix during merge
383T,tagname!            Use given tag name
384"
385	local opts commit keepmsg remotebranchdeleted localbranchdeleted
386
387	# Define flags
388	DEFINE_boolean 'fetch' false "fetch from $ORIGIN before performing finish" F
389	DEFINE_boolean 'sign' false "sign the release tag cryptographically" s
390	DEFINE_string  'signingkey' "" "use the given GPG-key for the digital signature (implies -s)" u
391	DEFINE_string  'message' "" "use the given tag message" m
392	DEFINE_string  'messagefile' "" "use the contents of the given file as tag message" f
393	DEFINE_boolean 'push' false "push to $ORIGIN after performing finish" p
394	DEFINE_boolean 'keep' false "keep branch after performing finish" k
395	DEFINE_boolean 'keepremote' false "keep the remote branch"
396	DEFINE_boolean 'keeplocal' false "keep the local branch"
397	DEFINE_boolean 'force_delete' false "force delete hotfix branch after finish" D
398	DEFINE_boolean 'notag' false "don't tag this hotfix" n
399	DEFINE_boolean 'nobackmerge' false "don't back-merge $MASTER_BRANCH, or tag if applicable, in $DEVELOP_BRANCH " b
400	DEFINE_boolean 'squash' false "squash release during merge" S
401	DEFINE_boolean 'squash-info' false "add branch info during squash"
402	DEFINE_string  'tagname' "" "use the given tag name" T
403
404	# Override defaults with values from config
405	gitflow_override_flag_boolean   "hotfix.finish.fetch"          "fetch"
406	gitflow_override_flag_boolean   "hotfix.finish.sign"           "sign"
407	gitflow_override_flag_boolean   "hotfix.finish.push"           "push"
408	gitflow_override_flag_boolean   "hotfix.finish.keep"           "keep"
409	gitflow_override_flag_boolean   "hotfix.finish.keepremote"     "keepremote"
410	gitflow_override_flag_boolean   "hotfix.finish.keeplocal"      "keeplocal"
411	gitflow_override_flag_boolean   "hotfix.finish.force-delete"   "force_delete"
412	gitflow_override_flag_boolean   "hotfix.finish.notag"          "notag"
413	gitflow_override_flag_boolean   "hotfix.finish.nobackmerge"    "nobackmerge"
414	gitflow_override_flag_boolean   "hotfix.finish.squash"         "squash"
415	gitflow_override_flag_boolean   "hotfix.finish.squash-info"    "squash_info"
416	gitflow_override_flag_string    "hotfix.finish.signingkey"     "signingkey"
417	gitflow_override_flag_string    "hotfix.finish.message"        "message"
418	gitflow_override_flag_string    "hotfix.finish.messagefile"    "messagefile"
419
420	# Parse arguments
421	parse_args "$@"
422
423	# Use current branch if no version is given
424	if [ "$VERSION" = "" ]; then
425		gitflow_use_current_branch_version
426	fi
427
428	# Use branch name if no tag name is given
429	if [ "$FLAGS_tagname" != "" ]; then
430		TAGNAME=$FLAGS_tagname
431	else
432		TAGNAME=$VERSION
433	fi
434
435	remotebranchdeleted=$FLAGS_FALSE
436	localbranchdeleted=$FLAGS_FALSE
437
438	# Handle flags that imply other flags
439	if [ "$FLAGS_signingkey" != "" ]; then
440		FLAGS_sign=$FLAGS_TRUE
441	fi
442
443	# Keeping both branches implies the --keep flag to be true.
444	if flag keepremote && flag keeplocal; then
445		FLAGS_keep=$FLAGS_TRUE
446	fi
447
448	# Sanity checks
449	require_branch "$BRANCH"
450	require_clean_working_tree
451
452	BASE_BRANCH=$(gitflow_config_get_base_branch $BRANCH)
453	BASE_BRANCH=${BASE_BRANCH:-$MASTER_BRANCH}
454	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'."
455
456	# We always fetch the Branch from Origin
457	# This is done to avoid possible commits on the remote that are not
458	# merged into the local branch
459	if git_remote_branch_exists "$ORIGIN/$BRANCH"; then
460		git_fetch_branch "$ORIGIN" "$BRANCH"
461	fi
462
463	# Update local branches with remote branches
464	if flag fetch; then
465		git_fetch_branch "$ORIGIN" "$BASE_BRANCH"
466		[ "$BASE_BRANCH" = "$MASTER_BRANCH" ] && git_fetch_branch "$ORIGIN" "$DEVELOP_BRANCH"
467	fi
468
469	# Check if the local branches have all the commits from the remote branches
470	if git_remote_branch_exists "$ORIGIN/$BRANCH"; then
471		require_branches_equal "$BRANCH" "$ORIGIN/$BRANCH"
472	fi
473	if git_remote_branch_exists "$ORIGIN/$BASE_BRANCH"; then
474		require_branches_equal "$BASE_BRANCH" "$ORIGIN/$BASE_BRANCH"
475	fi
476	if [ "$BASE_BRANCH" = "$MASTER_BRANCH" ]; then
477		if git_remote_branch_exists "$ORIGIN/$DEVELOP_BRANCH"; then
478			require_branches_equal "$DEVELOP_BRANCH" "$ORIGIN/$DEVELOP_BRANCH"
479		fi
480	fi
481
482	# If the branch is already merged there is no need to check the hotfix branch
483	# This can happen when the merge in develop fails and we rerun the finish.
484	if ! git_is_branch_merged_into "$BRANCH" "$BASE_BRANCH"; then
485		# Check if the hotfix branch:
486		# - has commits: No reason to finish a hotfix without commits
487		# - Is ahead of the BASE: If it's not a good idea to merge
488		# - Can be merged: If there's no common ancestor we can't merge the hotfix
489		git_compare_refs "$BRANCH" "$BASE_BRANCH"
490		case $? in
491		0)
492			die "You need some commits in the hotfix branch '$BRANCH'"
493			;;
494		1)
495			die "The hotfix branch '$BRANCH' is not ahead of branch '$BASE_BRANCH'"
496			;;
497		4)
498			die "The hotfix branch '$BRANCH' has no common ancestor with branch '$BASE_BRANCH'"
499			;;
500		*)
501			;;
502		esac
503	fi
504
505	if noflag notag; then
506		# We ask for a tag, be sure it does not exists or
507		# points to the latest hotfix commit
508		if git_tag_exists "$VERSION_PREFIX$TAGNAME"; then
509			git_compare_refs  "$BRANCH" "$VERSION_PREFIX$TAGNAME"^2 2>/dev/null
510			[ $? -eq 0 ] || die "Tag already exists and does not point to hotfix branch '$BRANCH'"
511		fi
512	fi
513
514	run_pre_hook "$VERSION_PREFIX$TAGNAME" "$ORIGIN" "$BRANCH"
515
516	# Try to merge into BASE.
517	# In case a previous attempt to finish this release branch has failed,
518	# but the merge into BASE was successful, we skip it now
519	if ! git_is_branch_merged_into "$BRANCH" "$BASE_BRANCH"; then
520		git_do checkout "$BASE_BRANCH" || die "Could not check out branch '$BASE_BRANCH'."
521		if noflag squash; then
522			git_do merge --no-ff "$BRANCH" || die "There were merge conflicts." # TODO: What do we do now?
523		else
524			git_do merge --squash "$BRANCH" || die "There were merge conflicts." # TODO: What do we do now?
525			flag squash_info && gitflow_create_squash_message "Merged hotfix branch '$BRANCH'" "$BASE_BRANCH" "$BRANCH" > "$DOT_GIT_DIR/SQUASH_MSG"
526			git_do commit
527		fi
528	fi
529
530	if noflag notag; then
531		# Try to tag the release.
532		# In case a previous attempt to finish this release branch has failed,
533		# but the tag was set successful, we skip it now
534		if ! git_tag_exists "$VERSION_PREFIX$TAGNAME"; then
535			if [ "$FLAGS_message" != "" ] && [ "$FLAGS_messagefile" != "" ]; then
536				die "Use either -m,--message or -f,--messagefile. Can not use both options at the same time"
537			fi
538			opts="-a"
539			flag sign && opts="$opts -s"
540			[ "$FLAGS_signingkey" != "" ] && opts="$opts -u '$FLAGS_signingkey'"
541			if [ "$FLAGS_message" != "" ]; then
542				# Run filter on the tag message
543				FLAGS_message=$(run_filter_hook hotfix-finish-tag-message "${FLAGS_message}" "$VERSION_PREFIX$TAGNAME")
544				opts="$opts -m '$FLAGS_message'"
545			fi
546			[ "$FLAGS_messagefile" != "" ] && opts="$opts -F '$FLAGS_messagefile'"
547			eval git_do tag $opts "$VERSION_PREFIX$TAGNAME" || die "Tagging failed. Please run finish again to retry."
548		fi
549	fi
550
551	if [ "$BASE_BRANCH" = "$MASTER_BRANCH" ]; then
552		# By default we back-merge the $MASTER_BRANCH unless the user explicitly
553		# stated not to do a back-merge, in that case we use the $BRANCH.
554		if noflag nobackmerge; then
555			MERGE_BRANCH="$BASE_BRANCH"
556		else
557			MERGE_BRANCH="$BRANCH"
558		fi
559
560		# Try to merge into develop.
561		# In case a previous attempt to finish this release branch has failed,
562		# but the merge into develop was successful, we skip it now
563		if ! git_is_branch_merged_into "$MERGE_BRANCH" "$DEVELOP_BRANCH"; then
564			git_do checkout "$DEVELOP_BRANCH" || die "Could not check out branch '$DEVELOP_BRANCH'."
565
566			if noflag nobackmerge; then
567				# Accounting for 'git describe', if a release is tagged
568				# we use the tag commit instead of the branch.
569				if noflag notag; then
570					commit="$VERSION_PREFIX$TAGNAME"
571				else
572					commit="$BASE_BRANCH"
573				fi
574			else
575				commit="$BRANCH"
576			fi
577
578			git_do merge --no-ff "$commit" || die "There were merge conflicts."
579			# TODO: What do we do now?
580		fi
581	fi
582
583	run_post_hook "$VERSION_PREFIX$TAGNAME" "$ORIGIN" "$BRANCH"
584
585	if flag push; then
586		if [ "$BASE_BRANCH" = "$MASTER_BRANCH" ]; then
587			git_do push "$ORIGIN" "$DEVELOP_BRANCH" || die "Could not push branch '$DEVELOP_BRANCH' to remote '$ORIGIN'."
588		fi
589		git_do push "$ORIGIN" "$BASE_BRANCH" || die "Could not push branch '$BASE_BRANCH' to remote '$ORIGIN'."
590		if noflag notag; then
591			git_do push --tags "$ORIGIN" || die "Could not push tags to remote '$ORIGIN'."
592		fi
593	fi
594
595	# Delete branch
596	if noflag keep; then
597
598		# Always delete remote first
599		if noflag keepremote;then
600			if git_remote_branch_exists "$ORIGIN/$BRANCH"; then
601				git_remote_branch_delete "$BRANCH" && remotebranchdeleted=$FLAGS_TRUE
602			fi
603		fi
604
605		# Delete local after remote to avoid warnings
606		if noflag keeplocal; then
607			if [ "$BRANCH" = "$(git_current_branch)" ]; then
608				git_do checkout "$DEVELOP_BRANCH" || die "Could not check out branch '$DEVELOP_BRANCH'."
609			fi
610			if flag force_delete; then
611				git_do branch -D "$BRANCH" && localbranchdeleted=$FLAGS_TRUE
612			else
613				git_do branch -d "$BRANCH" && localbranchdeleted=$FLAGS_TRUE
614			fi
615		fi
616
617		# no more branches: we can safely remove config section
618		if ! git_remote_branch_exists "$ORIGIN/$BRANCH" -a ! git_local_branch_exists "$BRANCH"; then
619			gitflow_config_remove_base_section "$BRANCH"
620		fi
621
622	fi
623
624	echo
625	echo "Summary of actions:"
626	if flag fetch; then
627		echo "- Latest objects have been fetched from '$ORIGIN'"
628	fi
629	echo "- Hotfix branch '$BRANCH' has been merged into '$BASE_BRANCH'"
630	if noflag notag; then
631		echo "- The hotfix was tagged '$VERSION_PREFIX$TAGNAME'"
632	fi
633	if [ "$BASE_BRANCH" = "$MASTER_BRANCH" ]; then
634		[ "$commit" = "$BASE_BRANCH" ] && echo "- Master branch '$BASE_BRANCH' has been back-merged into '$DEVELOP_BRANCH'"
635		[ "$commit" = "$VERSION_PREFIX$TAGNAME" ] && echo "- Hotfix tag '$VERSION_PREFIX$TAGNAME' has been back-merged into '$DEVELOP_BRANCH'"
636		[ "$commit" = "$BRANCH" ] && echo "- Hotfix branch '$BRANCH' has been merged into '$DEVELOP_BRANCH'"
637	fi
638	if noflag keep; then
639		if [ $localbranchdeleted -eq $FLAGS_TRUE ]; then
640			keepmsg="has been locally deleted"
641		else
642			keepmsg="is still locally available"
643		fi
644		if [ $remotebranchdeleted -eq $FLAGS_TRUE ]; then
645			keepmsg=$keepmsg"; it has been remotely deleted from '$ORIGIN'"
646		elif git_remote_branch_exists "$ORIGIN/$BRANCH"; then
647			keepmsg=$keepmsg"; it is still remotely available on '$ORIGIN'"
648		fi
649	else
650		keepmsg="is still locally available"
651		if git_remote_branch_exists "$ORIGIN/$BRANCH"; then
652			keepmsg=$keepmsg"; it is still remotely available on '$ORIGIN'"
653		fi
654	fi
655	echo "- Hotfix branch '$BRANCH' "$keepmsg
656	if flag push; then
657		if [ "$BASE_BRANCH" = "$MASTER_BRANCH" ]; then
658			echo "- '$DEVELOP_BRANCH', '$BASE_BRANCH' and tags have been pushed to '$ORIGIN'"
659		else
660			echo "- '$BASE_BRANCH' and tags have been pushed to '$ORIGIN'"
661		fi
662	fi
663	echo "- You are now on branch '$(git_current_branch)'"
664	echo
665
666}
667
668cmd_delete() {
669	OPTIONS_SPEC="\
670git flow hotfix delete [-h] [-f] [-r] <name>
671
672Delete the given hotfix branch
673--
674h,help!               Show this help
675showcommands!         Show git commands while executing them
676f,[no]force           Force deletion
677r,[no]remote          Delete remote branch
678"
679	local current_branch
680
681	# Define flags
682	DEFINE_boolean 'force' false "force deletion" f
683	DEFINE_boolean 'remote' false "delete remote branch" r
684
685	# Override defaults with values from config
686	gitflow_override_flag_boolean   "hotfix.delete.force"    "force"
687	gitflow_override_flag_boolean   "hotfix.finish.remote"   "remote"
688
689	# Parse arguments
690	parse_args "$@"
691
692	gitflow_require_version_arg
693
694	# Sanity checks
695	require_branch "$BRANCH"
696
697	run_pre_hook "$VERSION" "$ORIGIN" "$BRANCH"
698
699	current_branch=$(git_current_branch)
700	# We can't delete a branch we are on, switch to the master branch.
701	if [ "$BRANCH" = "$current_branch" ]; then
702		require_clean_working_tree
703		git_do checkout "$MASTER_BRANCH" || die "Could not check out branch '$MASTER_BRANCH'."
704	fi
705
706	if ( git_is_branch_merged_into "$BRANCH" "$MASTER_BRANCH" && git_is_branch_merged_into "$BRANCH" "$DEVELOP_BRANCH" ); then
707		git_do branch -d "$BRANCH" || die "Could not delete the $BRANCH."
708		if flag remote; then
709			git_remote_branch_delete "$BRANCH"
710		fi
711	else
712		if flag force; then
713			git_do branch -D "$BRANCH" || die "Could not delete the $BRANCH."
714			if flag remote; then
715				git_remote_branch_delete "$BRANCH"
716			fi
717		else
718			die "Hotfix branch '$BRANCH' has been not been merged in branch '$MASTER_BRANCH' and/or branch '$DEVELOP_BRANCH'. Use -f to force the deletion."
719		fi
720	fi
721
722	gitflow_config_remove_base_section "$BRANCH"
723	run_post_hook "$VERSION" "$ORIGIN" "$BRANCH"
724
725	echo
726	echo "Summary of actions:"
727	echo "- Hotfix branch '$BRANCH' has been deleted."
728	flag remote && echo "- Hotfix branch '$BRANCH' in '$ORIGIN' has been deleted."
729	echo "- You are now on branch '$(git_current_branch)'"
730	echo
731}
732
733cmd_rename() {
734	OPTIONS_SPEC="\
735git flow hotfix rename <new_name> [<new_name>]
736
737Rename a given hotfix branch
738--
739h,help!          Show this help
740showcommands!    Show git commands while executing them
741"
742	gitflow_rename_branch "$@"
743}
744