tg-annihilate.sh: autostash and support --stash and --no-stash
[topgit/pro.git] / tg-annihilate.sh
blob63b24b84d5405c134438a02485d36bc6280174f9
1 #!/bin/sh
2 # TopGit - A different patch queue manager
3 # (C) Petr Baudis <pasky@suse.cz> 2008
4 # (C) Per Cederqvist <ceder@lysator.liu.se> 2010
5 # (C) Kyle J. McKay <mackyle@gmail.com> 2017
6 # All rights reserved.
7 # GPLv2
9 force= # Whether to annihilate non-empty branch, or branch where only the base is left.
10 update=1 # Whether to run tg update on affected branches
11 stash= # tgstash refs before changes
13 if [ "$(git config --get --bool topgit.autostash 2>/dev/null)" != "false" ]; then
14 # topgit.autostash is true (or unset)
15 stash=1
18 ## Parse options
20 while [ -n "$1" ]; do
21 arg="$1"; shift
22 case "$arg" in
23 -f|--force)
24 force=1;;
25 --stash)
26 stash=1;;
27 --no-stash)
28 stash=;;
29 --no-update)
30 update=;;
31 --update)
32 update=1;;
34 echo "Usage: ${tgname:-tg} [...] annihilate [-f] [--no-update]" >&2
35 exit 1;;
36 esac
37 done
40 ## Sanity checks
42 v_verify_topgit_branch name HEAD
43 ! branch_annihilated "$name" || die "TopGit branch $name is already annihilated."
45 [ -z "$force" ] && { branch_empty "$name" || die "branch is non-empty: $name"; }
47 ## Annihilate
48 ensure_clean_tree
49 ensure_clean_topfiles
50 ensure_ident_available
51 alldeps="$(get_temp alldeps)"
52 tg --no-pager summary --deps >"$alldeps" || die "tg summary --deps failed"
54 # always auto stash even if it's just to the anonymous stash TG_STASH
56 stashbr="$(awk -v annb="$name" '
57 NF == 2 {
58 if ($1 == annb && $2 != "" && $2 != annb) print $2
59 if ($2 == annb && $1 != "" && $1 != annb) print $1
61 ' <"$alldeps" | sort -u)"
62 stashmsg="tgannihilate: autostash before annihilate branch $name"
63 if [ -n "$stash" ]; then
64 tg tag -q -q -m "$stashmsg" --stash $name $stashbr &&
65 stashhash="$(git rev-parse --quiet --verify refs/tgstash --)" &&
66 [ -n "$stashhash" ] &&
67 [ "$(git cat-file -t "$stashhash" -- 2>/dev/null)" = "tag" ] ||
68 die "requested --stash failed"
69 else
70 tg tag --anonymous $name $stashbr &&
71 stashhash="$(git rev-parse --quiet --verify TG_STASH --)" &&
72 [ -n "$stashhash" ] &&
73 [ "$(git cat-file -t "$stashhash" -- 2>/dev/null)" = "tag" ] ||
74 die "anonymous --stash failed"
77 mb="$(git merge-base "refs/$topbases/$name" "refs/heads/$name")"
78 git read-tree "$mb^{tree}"
79 # Need to pass --no-verify in order to inhibit TopGit's pre-commit hook to run,
80 # which would bark upon missing .top* files.
81 git commit --no-verify -m"TopGit branch $name annihilated."
83 # Propagate the dependencies through to dependents (if any), if they don't already have them
84 dependencies="$(awk -v annb="$name" 'NF == 2 && $2 != "" && $1 == annb { print $2 }' <"$alldeps")"
85 updatelist=
86 while read dependent && [ -n "$dependent" ]; do
87 # to avoid ambiguity with checkout -f we must use symbolic-ref + reset
88 git symbolic-ref HEAD "refs/heads/$dependent"
89 git reset -q --hard
90 needupdate=
91 while read dependency && [ -n "$dependency" ]; do
92 ! tg depend add --no-update "$dependency" >/dev/null 2>&1 || needupdate=1
93 done <<-EOT
94 $dependencies
95 EOT
96 [ -z "$needupdate" ] || updatelist="${updatelist:+$updatelist }$dependent"
97 done <<EOT
98 $(awk -v annb="$name" 'NF == 2 && $1 != "" && $2 == annb { print $1 }' <"$alldeps")
99 EOT
101 info "branch successfully annihilated: $name"
102 now="now"
103 if [ -n "$updatelist" ]; then
104 if [ -n "$update" ]; then
105 now="after the update completes"
106 else
107 info "skipping update because --no-update given"
108 info "be sure to update affected branches: $updatelist"
109 now="after updating"
112 info "If you have shared your work, you might want to run ${tgname:-tg} push $name $now."
113 if [ -n "$updatelist" ] && [ -n "$update" ]; then
114 info "now updating affected branches: $updatelist"
115 set -- $updatelist
116 . "$TG_INST_CMDDIR"/tg-update