On Tue, Oct 05, 2010 at 12:28:17AM +0200, Bert Wesarg wrote: > This adds general functions to get the list of all offending branches for Is offending the right word here? I don't understand that. > a given one. Either which depends on the given branch (fan-in) or all > dependencies (fan-out). > > Two simple users are provided which just lists the names or generates dot > input. This should then be used for tg summary --graphviz, too, doesn't it? > > Signed-off-by: Bert Wesarg <bert.wesarg@xxxxxxxxxxxxxx> > > --- > tg.sh | 170 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 files changed, 170 insertions(+), 0 deletions(-) > > diff --git a/tg.sh b/tg.sh > index 3718702..926b31b 100644 tg.sh > --- a/tg.sh > +++ b/tg.sh > @@ -351,6 +351,176 @@ setup_pager() > trap "exec >&-; rm \"$_pager_fifo\"; rmdir \"$_pager_fifo_dir\"; wait" EXIT > } > > +# traverse_fan_out(for_each_name, for_each_dep, name, head_deps) This uses an unusual format. please make it # traverse_fan_out FOR_EACH_NAME FOR_EACH_DEP NAME HEAD_DEPS > +# > +# traverse the dependencies of @name in bfs order and call @for_each_name > +# on each dep (i.e. node) and @for_each_dep on all dependencies (i.e. edge) > +# with source and dest as arguments. > +# > +# @name' needs to be a TopGit controlled branch > +# > +# @head_deps specifies where to take the .topdeps from for the HEAD branch > +# empty - from the committed tree > +# '(i)' - from the index > +# '(w)' - from the working dir > +# > +traverse_fan_out() > +{ > + local for_each_name=$1 > + local for_each_dep=$2 > + local name=$3 > + local head_deps=$4 || : > + local deps_src > + local head="$(git symbolic-ref HEAD | sed 's#^refs/\(heads\|top-bases\)/##')" || : I don't remember the exact problems, but some shells get using local and assignment in a single command wrong. Can you please fix that up? (I fixed that up for one of your commits.) > + > + branchq="$(mktemp -t tg-fan-out.XXXXXX)" > + allbranches="$(mktemp -t -d tg-fan-out-all.XXXXXX)" > + trap "rm -rf \"$branchq\" \"$allbranches\"" 0 > + > + # fill queue with root name > + echo "$name" > "$branchq" > + > + while [ -s "$branchq" ]; do > + # dequeue > + { > + read name > + cat > "$branchq.headless" > + } < "$branchq" > + mv -f "$branchq.headless" "$branchq" > + > + # eval name > + eval "$for_each_name \"$name\"" > + > + # don't travers non-tgish branches > + ref_exists "refs/top-bases/$name" || > + continue > + > + deps_src=$name > + # select .topdeps source for HEAD branch > + [ "x$name" = "x$head" -a -n "$head_deps" ] && > + deps_src=$head_deps > + > + old_IFS="$IFS" > + IFS="" > + cat_file "$deps_src:.topdeps" | > + while read dep; do > + > + # eval dep > + eval "$for_each_dep \"$name\" \"$dep\"" > + > + [ -d "$allbranches/$dep" ] || { > + mkdir -p "$allbranches/$dep" > + echo "$dep" >> "$branchq" > + } > + done > + IFS="$old_IFS" > + > + done > +} > + > +_graph_dep_edge() > +{ > + printf "\t\"%s\" -> \"%s\";\n" "$1" "$2" > +} > + > +# prints the fan-out as a dot graph with edges > +graph_fan_out() > +{ > + printf "digraph G {\n" > + > + traverse_fan_out : _graph_dep_edge "$1" $2 > + > + printf "}\n" > +} > + > +# prints the fan-out as name per line > +list_fan_out() > +{ > + traverse_fan_out echo : "$1" $2 > +} > + > +# traverse_fan_in(for_each_name, for_each_dep, name, head_deps) > +# > +# traverse all branches which depends on @name in bfs order and call > +# @for_each_name on each (i.e. node) and @for_each_dep on all dependencies > +# (i.e. edge) with source and dest as arguments. > +# > +# @name' needs not to be a TopGit controlled branch > +# > +# @head_deps specifies where to take the .topdeps from for the HEAD branch > +# empty - from the committed tree > +# '(i)' - from the index > +# '(w)' - from the working dir > +# > +traverse_fan_in() > +{ > + local for_each_name=$1 > + local for_each_dep=$2 > + local name=$3 > + local head_deps=$4 || : > + local deps_src > + local head="$(git symbolic-ref HEAD | sed 's#^refs/\(heads\|top-bases\)/##')" || : > + > + branchq="$(mktemp -t tg-fan-in.XXXXXX)" > + allbranches="$(mktemp -t -d tg-fan-in-all.XXXXXX)" > + trap "rm -rf \"$branchq\" \"$allbranches\"" 0 > + > + echo "$name" > "$branchq" > + > + while [ -s "$branchq" ]; do > + # dequeue > + { > + read name > + cat > "$branchq.headless" > + } < "$branchq" > + mv -f "$branchq.headless" "$branchq" > + > + [ ! -d "$allbranches/$name" ] || > + continue; > + mkdir -p "$allbranches/$name" > + > + # eval branch > + eval "$for_each_name \"$name\"" > + > + old_IFS="$IFS" > + IFS="" > + git for-each-ref --format='%(refname)' refs/top-bases | > + while read ref; do > + parent="${ref#refs/top-bases/}" > + > + deps_src=$parent > + # select branch/index/worktree for HEAD branch > + [ "x$parent" = "x$head" -a -n "$head_deps" ] && > + deps_src=$head_deps > + cat_file "$deps_src:.topdeps" | fgrep -qx "$name" || > + continue > + > + # eval dep > + eval "$for_each_dep \"$parent\" \"$name\"" > + > + echo "$parent" >> "$branchq" > + done > + IFS="$old_IFS" > + > + done > +} > + > +# prints the fan-in as a dot graph with edges > +graph_fan_in() > +{ > + printf "digraph G {\n" > + > + traverse_fan_in : _graph_dep_edge "$1" $2 > + > + printf "}\n" > +} > + > +# prints the fan-in as name per line > +list_fan_in() > +{ > + traverse_fan_in echo : "$1" $2 > +} > + > ## Startup > > [ -d "@cmddir@" ] || > -- > tg: (ff59ac7..) bw/fan-in-out (depends on: master) > -- Pengutronix e.K. | Uwe Kleine-König | Industrial Linux Solutions | http://www.pengutronix.de/ | -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html