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