tg-create.sh: switch from warn to err
[topgit/pro.git] / tg-summary.sh
blob6a35ebcd5013da3ba115053cd1afa6d3b38650ed
1 #!/bin/sh
2 # TopGit - A different patch queue manager
3 # Copyright (C) Petr Baudis <pasky@suse.cz> 2008
4 # Copyright (C) Kyle J. McKay <mackyle@gmail.com> 2015
5 # All rights reserved.
6 # GPLv2
8 terse=
9 graphviz=
10 sort=
11 deps=
12 depsonly=
13 rdeps=
14 head_from=
15 branches=
16 head=
17 exclude=
19 ## Parse options
21 usage()
23 echo "Usage: ${tgname:-tg} [...] summary [-t | --list | --sort | --deps | --deps-only | --rdeps | --graphviz] [-i | -w] [--exclude branch]... [--all | branch...]" >&2
24 exit 1
27 while [ -n "$1" ]; do
28 arg="$1"
29 case "$arg" in
30 -i|-w)
31 [ -z "$head_from" ] || die "-i and -w are mutually exclusive"
32 head_from="$arg";;
33 -t|--list|-l)
34 terse=1;;
35 --graphviz)
36 graphviz=1;;
37 --sort)
38 sort=1;;
39 --deps)
40 deps=1;;
41 --deps-only)
42 head=HEAD
43 depsonly=1;;
44 --rdeps)
45 head=HEAD
46 rdeps=1;;
47 --all)
48 break;;
49 --exclude=*)
50 [ -n "${1#--exclude=}" ] || die "--exclude= requires a branch name"
51 exclude="$exclude ${1#--exclude=}";;
52 --exclude)
53 shift
54 [ -n "$1" -a "$1" != "--all" ] || die "--exclude requires a branch name"
55 exclude="$exclude $1";;
56 -*)
57 usage;;
59 break;;
60 esac
61 shift
62 done
63 [ -z "$exclude" ] || exclude="$exclude "
64 if [ "$1" = "--all" ]; then
65 [ $# -eq 1 ] || usage
66 shift
67 head=
69 [ $# -ne 0 -o -z "$head" ] || set -- "$head"
71 [ "$terse$graphviz$sort$deps$depsonly" = "" ] ||
72 [ "$terse$graphviz$sort$deps$depsonly$rdeps" = "1" ] ||
73 die "mutually exclusive options given"
75 for b; do
76 [ "$b" != "--all" ] || usage
77 branches="$branches $(verify_topgit_branch "$b")"
78 done
80 get_branch_list()
82 if [ -n "$branches" ]; then
83 printf '%s\n' $branches
84 else
85 non_annihilated_branches
89 show_dep() {
90 case "$exclude" in *" $_dep "*) return; esac
91 case " $seen_deps " in *" $_dep "*) return 0; esac
92 seen_deps="${seen_deps:+$seen_deps }$_dep"
93 printf '%s\n' "$_dep"
96 show_deps()
98 no_remotes=1
99 recurse_deps_exclude=
100 get_branch_list | while read _b; do
101 case "$exclude" in *" $_b "*) continue; esac
102 case " $recurse_deps_exclude " in *" $_b "*) continue; esac
103 seen_deps=
104 _dep="$_b"; _dep_is_tgish=1; show_dep
105 recurse_deps show_dep "$_b"
106 recurse_deps_exclude="$recurse_deps_exclude $seen_deps"
107 done
110 if [ -n "$depsonly" ]; then
111 show_deps | LC_ALL=C sort -u -b -k1,1
112 exit 0
115 show_rdeps()
117 case "$exclude" in *" $_dep "*) return; esac
118 printf '%s %s\n' "$_depchain" "$_dep"
121 if [ -n "$rdeps" ]; then
122 no_remotes=1
123 showbreak=
124 get_branch_list |
125 while read b; do
126 case "$exclude" in *" $b "*) continue; esac
127 [ -z "$showbreak" ] || echo
128 showbreak=1
129 ref_exists "refs/heads/$b" || continue
131 echo "$b"
132 recurse_preorder=1
133 recurse_deps show_rdeps "$b"
134 } | sed -e 's/[^ ][^ ]*[ ]/ /g'
135 done
136 exit 0
139 curname="$(strip_ref "$(git symbolic-ref HEAD 2>/dev/null)")"
141 if [ -n "$graphviz" ]; then
142 cat <<EOT
143 # GraphViz output; pipe to:
144 # | dot -Tpng -o <output>
145 # or
146 # | dot -Txlib
148 digraph G {
150 graph [
151 rankdir = "TB"
152 label="TopGit Layout\n\n\n"
153 fontsize = 14
154 labelloc=top
155 pad = "0.5,0.5"
161 if [ -n "$sort" ]; then
162 tsort_input="$(get_temp tg-summary-sort)"
163 exec 4>$tsort_input
164 exec 5<$tsort_input
167 ## List branches
169 process_branch()
171 missing_deps=
173 current=' '
174 [ "$name" != "$curname" ] || current='>'
175 from=$head_from
176 [ "$name" = "$curname" ] ||
177 from=
178 nonempty=' '
179 ! branch_empty "$name" $from || nonempty='0'
180 remote=' '
181 [ -z "$base_remote" ] || remote='l'
182 ! has_remote "$name" || remote='r'
183 rem_update=' '
184 [ "$remote" != 'r' ] || ! ref_exists "refs/remotes/$base_remote/top-bases/$name" || {
185 branch_contains "refs/top-bases/$name" "refs/remotes/$base_remote/top-bases/$name" &&
186 branch_contains "refs/heads/$name" "refs/remotes/$base_remote/$name"
187 } || rem_update='R'
188 [ "$remote" != 'r' -o "$rem_update" = 'R' ] || {
189 branch_contains "refs/remotes/$base_remote/$name" "refs/heads/$name" 2>/dev/null
190 } || rem_update='L'
191 deps_update=' '
192 needs_update "$name" >/dev/null || deps_update='D'
193 deps_missing=' '
194 [ -z "$missing_deps" ] || deps_missing='!'
195 base_update=' '
196 branch_contains "refs/heads/$name" "refs/top-bases/$name" || base_update='B'
198 if [ "$(ref_exists_rev "refs/heads/$name")" != "$(ref_exists_rev "refs/top-bases/$name")" ]; then
199 subject="$(cat_file "refs/heads/$name:.topmsg" $from | sed -n 's/^Subject: //p')"
200 else
201 # No commits yet
202 subject="(No commits)"
205 printf '%s\t%-31s\t%s\n' "$current$nonempty$remote$rem_update$deps_update$deps_missing$base_update" \
206 "$name" "$subject"
209 if [ -n "$deps" ]; then
210 if [ -n "$branches" ]; then
211 get_branch_list |
212 while read b; do
213 case "$exclude" in *" $b "*) continue; esac
214 list_deps $head_from $b |
215 while read name dep; do
216 case "$exclude" in *" $dep "*) continue; esac
217 echo "$name $dep"
218 done
219 done
220 else
221 list_deps $head_from |
222 while read name dep; do
223 case "$exclude" in *" $dep "*) continue; esac
224 echo "$name $dep"
225 done
227 exit 0
230 get_branch_list |
231 while read name; do
232 case "$exclude" in *" $name "*) continue; esac
233 if [ -n "$terse" ]; then
234 echo "$name"
235 elif [ -n "$graphviz$sort" ]; then
236 from=$head_from
237 [ "$name" = "$curname" ] ||
238 from=
239 cat_file "refs/heads/$name:.topdeps" $from | while read dep; do
240 dep_is_tgish=true
241 ref_exists "refs/top-bases/$dep" ||
242 dep_is_tgish=false
243 if ! "$dep_is_tgish" || ! branch_annihilated $dep; then
244 if [ -n "$graphviz" ]; then
245 echo "\"$name\" -> \"$dep\";"
246 if [ "$name" = "$curname" ] || [ "$dep" = "$curname" ]; then
247 echo "\"$curname\" [style=filled,fillcolor=yellow];"
249 else
250 echo "$name $dep" >&4
253 done
254 else
255 process_branch
257 done
259 if [ -n "$graphviz" ]; then
260 echo '}'
263 if [ -n "$sort" ]; then
264 tsort <&5
268 # vim:noet