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,2016,2017,2018
30 echo "Usage: ${tgname:-tg} [...] summary [-t | --list | --heads[-only] | --sort | --deps[-only] | --rdeps | --graphviz] [-i | -w] [--tgish-only] [--with[out]-(deps|related)] [--exclude branch]... [--all | branch...]" >&2
38 [ -z "$head_from" ] || die
"-i and -w are mutually exclusive"
43 verbose
=$
(( $verbose + 1 ));;
45 terse
=1 verbose
=$
(( $verbose + 1 ));;
47 verbose
=$
(( $verbose + 2 ));;
49 terse
=1 verbose
=$
(( $verbose + 2 ));;
50 --heads|
--topgit-heads)
64 --without-deps|
--no-with-deps|
--without-related|
--no-with-related)
90 [ -n "${1#--exclude=}" ] || die
"--exclude= requires a branch name"
91 exclude
="$exclude ${1#--exclude=}";;
94 [ -n "$1" ] && [ "$1" != "--all" ] || die
"--exclude requires a branch name"
95 exclude
="$exclude $1";;
103 [ $# -eq 0 ] || defwithdeps
=1
104 [ -z "$exclude" ] || exclude
="$exclude "
106 [ $# -ne 0 ] ||
[ z
"$head" != z
"" ] || doingall
=1
107 if [ "$1" = "--all" ]; then
108 [ -z "$withdeps" ] || die
"mutually exclusive options given"
109 [ $# -eq 1 ] || usage
115 [ "$heads$rdeps" != "11" ] ||
head=
116 [ $# -ne 0 ] ||
[ -z "$head" ] ||
set -- "$head"
117 [ -z "$defwithdeps" ] ||
[ $# -ne 1 ] ||
{ [ z
"$1" != z
"HEAD" ] && [ z
"$1" != z
"@" ]; } || defwithdeps
=2
119 [ "$terse$heads$headsonly$graphviz$sort$deps$depsonly" = "" ] ||
120 [ "$terse$heads$headsonly$graphviz$sort$deps$depsonly$rdeps" = "1" ] ||
121 { [ "$terse$heads$headsonly$graphviz$sort$deps$depsonly$rdeps" = "11" ] && [ "$heads$rdeps" = "11" ]; } ||
122 die
"mutually exclusive options given"
123 [ -z "$withdeps" ] ||
[ -z "$rdeps$depsonly$heads$headsonly" ] ||
124 die
"mutually exclusive options given"
127 [ "$b" != "--all" ] || usage
128 branches
="$branches $(verify_topgit_branch "$b")"
133 if [ -n "$branches" ]; then
135 printf '%s\n' $branches |
sort -u
137 printf '%s\n' $branches
140 non_annihilated_branches
144 show_heads_independent
()
146 topics
="$(get_temp topics)"
147 get_branch_list |
sed -e 's,^\(.*\)$,refs/heads/\1 \1,' |
148 git cat-file
--batch-check='%(objectname) %(rest)' |
149 sort -u -b -k1,1 >"$topics"
150 git merge-base
--independent $
(cut
-d ' ' -f 1 <"$topics") |
151 sort -u -b -k1,1 |
join - "$topics" |
sort -u -b -k2,2 |
152 while read rev name
; do
153 case "$exclude" in *" $name "*) continue; esac
154 printf '%s\n' "$name"
160 if [ -n "$branches" ]; then
161 navigate_deps
-s=-1 -1 -- "$branches" |
sort
165 while read -r name
; do
166 case "$exclude" in *" $name "*) continue; esac
167 printf '%s\n' "$name"
173 if [ -n "$headsindep" ]; then
174 show_heads_independent
"$@"
176 show_heads_topgit
"$@"
180 if [ -n "$heads" ] && [ -z "$rdeps" ]; then
185 # if $1 is non-empty, show the dep only (including self), not the edge (no self)
188 if [ -n "$branches" ]; then
190 [ -z "$1" ] || edgenum
=1
192 recurse_deps_exclude
="$exclude"
193 recurse_deps_internal
-n ${tgish:+-t} -m ${1:+-s} -e=$edgenum -- $branches |
sort -u
196 [ -z "$1" ] || cutcmd
='| cut -d " " -f 2 | sort -u'
198 [ -z "$tg_read_only" ] ||
[ -z "$tg_ref_cache" ] ||
! [ -s "$tg_ref_cache" ] ||
199 refslist
="-r=\"$tg_ref_cache\""
201 v_get_tdopt tdopt
"$head_from"
202 eval run_awk_topgit_deps
"$refslist" "$tdopt" "${tgish:+-t}" \
203 "${1:+-s}" '-n -x="$exclude" "refs/$topbases"' "$cutcmd"
207 if [ -n "$deps$depsonly$sort" ]; then
208 eval show_deps
$depsonly "${sort:+|tsort}"
212 if [ -n "$rdeps" ]; then
215 recurse_deps_exclude
="$exclude"
218 if [ -n "$heads" ]; then
223 } |
while read -r b
; do
224 case "$exclude" in *" $b "*) continue; esac
225 ref_exists
"refs/heads/$b" ||
continue
226 [ -z "$showbreak" ] ||
echo
228 recurse_deps_internal
${tgish:+-t} -n -s ${rdepsonce:+-o=-1} "$b" |
229 awk -v elided
="$rdepsonce" '{
230 if ($1 == "1" || NF < 5) next
233 if ($6 != "") haschild[$6] = 1
234 sub(/^[^ ]+ +[^ ]+ +[^ ]+ +[^ ]+ +[^ ]+/, "")
237 if (elided && xvisits > 0 && haschild[dep]) xtra="^"
244 if [ -n "$headsonly" ]; then
246 branches
="$(show_heads)"
249 [ -n "$withdeps" ] || withdeps
="$defwithdeps"
250 if [ -z "$doingall$terse$graphviz$sort$withdeps$branches" ]; then
251 branches
="$(tg info --heads 2>/dev/null | paste -d " " -s -)" ||
:
252 [ -z "$branches" ] || withdeps
=1
254 [ "$withdeps" != "0" ] || withdeps
=
255 if [ -n "$withdeps" ]; then
256 [ "$withdeps" != "2" ] || branches
="$(show_heads_topgit | paste -d " " -s -)"
259 origbranches
="$branches"
260 branches
="$(show_deps 1 | paste -d " " -s -)"
264 if [ -n "$terse" ]; then
266 [ -z "$tg_read_only" ] ||
[ -z "$tg_ref_cache" ] ||
! [ -s "$tg_ref_cache" ] ||
267 refslist
="-r=\"$tg_ref_cache\""
268 cmd
="run_awk_topgit_msg --list"
269 [ $verbose -lt 2 ] || cmd
="run_awk_topgit_msg -c -nokind"
270 [ $verbose -gt 0 ] || cmd
="run_awk_topgit_branches -n"
271 eval "$cmd" "$refslist" '-i="$branches" -x="$exclude" "refs/$topbases"'
275 curname
="$(strip_ref "$
(git symbolic-ref
-q HEAD
)")" ||
:
277 if [ -n "$graphviz" ]; then
279 '# GraphViz output; pipe to:
280 # | dot -Tpng -o <output>
288 label="TopGit Layout\n\n\n"
293 show_deps |
while read -r name dep
; do
294 printf '"%s" -> "%s";\n' "$name" "$dep"
295 if [ "$name" = "$curname" ] ||
[ "$dep" = "$curname" ]; then
296 printf '"%s" [%s];\n' "$curname" "style=filled,fillcolor=yellow"
307 [ -z "$tg_read_only" ] ||
[ -z "$tg_ref_cache" ] ||
! [ -s "$tg_ref_cache" ] ||
308 refslist
="-r=\"$tg_ref_cache\""
309 msgsfile
="$(get_temp msgslist)"
310 eval run_awk_topgit_msg
-nokind "$refslist" '"refs/$topbases"' >"$msgsfile"
311 needs_update_check_clear
312 needs_update_check_no_same
=1
313 [ -z "$branches" ] ||
[ -n "$withdeps" ] ||
return 0
314 [ -n "$withdeps" ] || origbranches
="$(navigate_deps -s=-1 | paste -d ' ' -s -)"
315 for onehead
in $origbranches; do
316 case "$exclude" in *" $onehead "*) continue; esac
317 needs_update_check
$onehead
319 aheadlist
=" $needs_update_ahead "
327 [ "$name" != "$curname" ] || current
='>'
329 [ "$name" = "$curname" ] ||
332 ! branch_empty
"$name" $from || nonempty
='0'
334 [ -z "$base_remote" ] || remote
='l'
335 ! has_remote
"$name" || remote
='r'
337 [ "$remote" != 'r' ] ||
! ref_exists
"refs/remotes/$base_remote/${topbases#heads/}/$name" ||
{
338 branch_contains
"refs/$topbases/$name" "refs/remotes/$base_remote/${topbases#heads/}/$name" &&
339 branch_contains
"refs/heads/$name" "refs/remotes/$base_remote/$name"
341 [ "$remote" != 'r' ] ||
[ "$rem_update" = 'R' ] ||
{
342 branch_contains
"refs/remotes/$base_remote/$name" "refs/heads/$name" 2>/dev
/null
344 needs_update_check
"$name"
346 ! vcontains needs_update_behind
"$name" || deps_update
='D'
348 ! vcontains needs_update_partial
"$name" || deps_missing
='!'
350 branch_contains
"refs/heads/$name" "refs/$topbases/$name" || base_update
='B'
352 case "$aheadlist" in *" $name "*) ahead
='*'; esac
354 printf '%-8s %s\n' "$current$nonempty$remote$rem_update$deps_update$deps_missing$base_update$ahead" \
360 if (msgsfile != "") {
361 while ((e = (getline msg <msgsfile)) > 0) {
362 gsub(/[ \t]+/, " ", msg)
364 if (split(msg, scratch, " ") < 2 ||
365 scratch[1] == "" || scratch[2] == "") continue
366 msg = substr(msg, length(scratch[1]) + 2)
367 msgs[scratch[1]] = msg
373 name = substr($0, 10)
374 if (name != "" && name in msgs)
375 printf "%-39s\t%s\n", $0, msgs[name]
382 cmd
='get_branch_list | while read name; do process_branch; done'
383 [ -z "$msgsfile" ] || cmd
="$cmd"' | awk -v msgsfile="$msgsfile" "$awkpgm"'