2 # TopGit contains command
3 # (C) 2017 Kyle J. McKay <mackyle@gmail.com>
8 Usage: ${tgname:-tg} [...] contains [-v] [-r] [--ann] [--no-strict] [--] <committish>"
12 if [ "${1:-0}" != 0 ]; then
13 printf '%s\n' "$USAGE" >&2
15 printf '%s\n' "$USAGE"
25 while [ $# -gt 0 ]; do case "$1" in
32 --ann|
--annihilated|
--annihilated-ok|
--annihilated-okay)
36 echo "Did you mean --verbose (-v) instead of --heads?" >&2
40 verbose
=$
(( ${verbose:-0} + 1 ))
42 -vv|
-vvv|
-vvvv|
-vvvvv)
43 verbose
=$
(( ${verbose:-0} + ${#1} - 1 ))
56 echo "Unknown option: $1" >&2
64 [ "$1" != "@" ] ||
set -- HEAD
67 findrev
="$(git rev-parse --verify "$1"^0 --)" ||
exit 1
69 # true if $1 is contained by (or the same as) $2
72 [ "$(git rev-list --count --max-count=1 "$1" --not "$2" --)" = "0" ]
75 # $1 => return correct $topbases value in here on success
77 # $3 => remote branch name
78 # succeeds if both refs/remotes/$2/$3 and refs/remotes/$2/${$1#heads/}/$3 exist
79 v_is_remote_tgbranch
()
81 git rev-parse
--quiet --verify "refs/remotes/$2/$3^0" -- >/dev
/null ||
return 1
82 if git rev-parse
--quiet --verify "refs/remotes/$2/${topbases#heads/}/$3^0" -- >/dev
/null
; then
83 [ -z "$1" ] ||
eval "$1="'"$topbases"'
86 git rev-parse
--quiet --verify "refs/remotes/$2/${oldbases#heads/}/$3^0" -- >/dev
/null ||
return 1
87 if [ -z "$annok" ]; then
88 rmb
="$(git merge-base "refs
/remotes
/$2/${oldbases#heads/}/$3^
0" "refs
/remotes
/$2/$3^
0" 2>/dev/null)" ||
:
89 if [ -n "$rmb" ]; then
90 rmbtree
="$(git rev-parse --quiet --verify "$rmb^
{tree
}" --)" ||
:
93 rbrtree
="$(git rev-parse --quiet --verify "refs
/remotes
/$2/$3^
{tree
}" --)" ||
:
94 [ -z "$rmbtree" ] ||
[ -z "$rbrtree" ] ||
[ "$rmbtree" != "$rbrtree" ] ||
return 1
97 [ -z "$1" ] ||
eval "$1="'"$oldbases"'
102 if [ -n "$_dep_is_tgish" ] && [ -z "$_dep_missing$_dep_annihilated" ]; then
103 printf '%s\n' "$_dep ${_depchain##* }"
112 depslist
="$(get_temp depslist)"
113 $tg summary
--topgit-heads |
114 while read -r onetghead
; do
115 printf '%s %s\n' "$onetghead" "$onetghead"
116 recurse_deps process_dep
"$onetghead"
117 done | LC_ALL
=C
sort -u >"$depslist"
122 localb
="$(get_temp localb)"
126 [ -z "$remotes" ] || remoteb
="$(get_temp remoteb)"
127 while IFS
= read -r branch
&& [ -n "$branch" ]; do
128 branch
="${branch#??}"
129 if v_verify_topgit_branch
"" "$branch" -f; then
130 [ -n "$annok" ] ||
! branch_annihilated
"$branch" ||
continue
131 if contained_by
"$findrev" "refs/$topbases/$branch"; then
132 [ -z "$strict" ] ||
continue
133 depth
="$(git rev-list --count --ancestry-path "refs
/$topbases/$branch" --not "$findrev")"
134 depth
=$
(( ${depth:-0} + 1 ))
138 localcnt
=$
(( ${localcnt:-0} + 1 ))
139 [ ${#branch} -le $localwide ] || localwide
=${#branch}
140 printf '%s %s\n' "$depth" "$branch" >>"$localb"
143 [ -n "$remotes" ] && [ -z "$localcnt" ] && [ "${branch#remotes/}" != "$branch" ] ||
continue
144 rbranch
="${branch#remotes/}"
145 rremote
="${rbranch%%/*}"
146 rbranch
="${rbranch#*/}"
147 [ "remotes/$rremote/$rbranch" = "$branch" ] ||
continue
148 v_is_remote_tgbranch rtopbases
"$rremote" "$rbranch" ||
continue
149 if contained_by
"$findrev" "refs/remotes/$rremote/${rtopbases#heads/}/$rbranch"; then
150 [ -z "$strict" ] ||
continue
151 depth
="$(git rev-list --count --ancestry-path "refs
/remotes
/$rremote/${rtopbases#heads/}/$rbranch" --not "$findrev")"
152 depth
=$
(( ${depth:-0} + 1 ))
156 remotecnt
=$
(( ${remotecnt:-0} + 1 ))
157 [ ${#branch} -le $remotewide ] || remotewide
=${#branch}
158 [ -n "$remoteb" ] || remoteb
="$(get_temp remoteb)"
159 printf '%s %s\n' "$depth" "remotes/$rremote/$rbranch" >>"$remoteb"
162 $(git branch ${remotes:+-a} --contains "$findrev")
164 [ -n "$localcnt$remotecnt" ] ||
exit 1
165 [ -z "$localcnt" ] ||
[ ${verbose:-0} -le 0 ] || make_deps_list
166 if [ -n "$localcnt" ]; then
174 LC_ALL
=C
sort -k1,1n
"$process" |
175 while read -r depth ref
; do
176 [ -n "$mindepth" ] || mindepth
="$depth"
177 [ $depth -le $mindepth ] ||
continue
179 done | LC_ALL
=C
sort -u |
180 while read -r oneresult
; do
183 [ -z "$annok" ] ||
[ -z "$depslist" ] ||
! branch_annihilated
"$oneresult" || isann
=1
184 [ -z "$depslist" ] ||
[ -n "$isann" ] ||
185 headinfo
="$(printf '%s\n' "$oneresult" | join -o 2.2 - "$depslist" |
186 LC_ALL=C sort -u | paste -d , -s - | sed -e 's/,/, /g')"
187 [ -z "$annok" ] ||
[ -z "$depslist" ] ||
[ -z "$isann" ] || headinfo
=":annihilated:"
188 if [ -z "$headinfo" ]; then
189 printf '%s\n' "$oneresult"
191 printf '%-*s [%s]\n' $minwide "$oneresult" "$headinfo"