chiark / gitweb /
tg-files: list files changed by the topic branch
[topgit.git] / tg.sh
diff --git a/tg.sh b/tg.sh
index 8c174fbff4a2caadfabcaadc47d0a2afaf4d5814..f1b323b7cbe543994f373523ab2b84b814fd0adc 100644 (file)
--- a/tg.sh
+++ b/tg.sh
@@ -3,7 +3,7 @@
 # (c) Petr Baudis <pasky@suse.cz>  2008
 # GPLv2
 
-TG_VERSION=0.7
+TG_VERSION=0.8
 
 ## Auxiliary functions
 
@@ -14,7 +14,7 @@ info()
 
 die()
 {
-       info "fatal: $*"
+       info "fatal: $*" >&2
        exit 1
 }
 
@@ -25,20 +25,67 @@ cat_file()
        arg="$1"
        case "$arg" in
        '(w):'*)
-               arg=$(echo "$arg" | tail --bytes=+5)
-               cat "$arg"
-               return
+               cat "${arg#(w):}"
                ;;
        '(i):'*)
                # ':file' means cat from index
-               arg=$(echo "$arg" | tail --bytes=+5)
-               git cat-file blob ":$arg"
+               git cat-file blob "${arg#(i)}"
                ;;
        *)
                git cat-file blob "$arg"
+               ;;
        esac
 }
 
+# get tree for the committed topic
+get_tree_()
+{
+       echo "$1"
+}
+
+# get tree for the base
+get_tree_b()
+{
+       echo "refs/top-bases/$1"
+}
+
+# get tree for the index
+get_tree_i()
+{
+       git write-tree
+}
+
+# get tree for the worktree
+get_tree_w()
+{
+       i_tree=$(git write-tree)
+       (
+               # the file for --index-output needs to sit next to the
+               # current index file
+               : ${GIT_INDEX_FILE:="$git_dir/index"}
+               TMP_INDEX="$(mktemp "${GIT_INDEX_FILE}-tg.XXXXXX")"
+               git read-tree -m $i_tree --index-output="$TMP_INDEX" &&
+               GIT_INDEX_FILE="$TMP_INDEX" &&
+               export GIT_INDEX_FILE &&
+               git diff --name-only -z HEAD |
+                       git update-index -z --add --remove --stdin &&
+               git write-tree &&
+               rm -f "$TMP_INDEX"
+       )
+}
+
+# pretty_tree NAME [-b | -i | -w]
+# Output tree ID of a cleaned-up tree without tg's artifacts.
+# NAME will be ignored for -i and -w, but needs to be present
+pretty_tree()
+{
+       name=$1
+       source=${2#?}
+       git ls-tree --full-tree "$(get_tree_$source "$name")" |
+               awk -F '        ' '$2 !~ /^.top/' |
+               git mktree
+}
+
 # setup_hook NAME
 setup_hook()
 {
@@ -54,6 +101,8 @@ setup_hook()
        else
                hook_call="exec $hook_call"
        fi
+       # Don't call hook if tg is not installed
+       hook_call="if which \"$tg\" > /dev/null; then $hook_call; fi"
        # Insert call into the hook
        {
                echo "#!/bin/sh"
@@ -126,6 +175,13 @@ branch_annihilated()
        test "$(git rev-parse "$mb^{tree}")" = "$(git rev-parse "$_name^{tree}")";
 }
 
+# is_sha1 REF
+# Whether REF is a SHA1 (compared to a symbolic name).
+is_sha1()
+{
+       [ "$(git rev-parse "$1")" = "$1" ]
+}
+
 # recurse_deps CMD NAME [BRANCHPATH...]
 # Recursively eval CMD on all dependencies of NAME.
 # CMD can refer to $_name for queried branch name,
@@ -230,6 +286,27 @@ branch_empty()
        [ -z "$(git diff-tree "refs/top-bases/$1" "$1" -- | fgrep -v "  .top")" ]
 }
 
+# list_deps
+list_deps()
+{
+       git for-each-ref refs/top-bases |
+               while read rev type ref; do
+                       name="${ref#refs/top-bases/}"
+                       if branch_annihilated "$name"; then
+                               continue;
+                       fi
+
+                       git cat-file blob "$name:.topdeps" | while read dep; do
+                               dep_is_tgish=true
+                               ref_exists "refs/top-bases/$dep"  ||
+                                       dep_is_tgish=false
+                               if ! "$dep_is_tgish" || ! branch_annihilated $dep; then
+                                       echo "$name $dep"
+                               fi
+                       done
+               done
+}
+
 # switch_to_base NAME [SEED]
 switch_to_base()
 {
@@ -269,7 +346,8 @@ do_help()
                echo "TopGit v$TG_VERSION - A different patch queue manager"
                echo "Usage: tg [-r REMOTE] ($cmds|help) ..."
        elif [ -r "@cmddir@"/tg-$1 ] ; then
-               @cmddir@/tg-$1 -h || :
+               setup_pager
+               @cmddir@/tg-$1 -h 2>&1 || :
                echo
                if [ -r "@sharedir@/tg-$1.txt" ] ; then
                        cat "@sharedir@/tg-$1.txt"
@@ -303,7 +381,7 @@ setup_pager()
 
 
        # now spawn pager
-       export LESS=${LESS:-FRSX}       # as in pager.c:pager_preexec()
+       export LESS="${LESS:-FRSX}"     # as in pager.c:pager_preexec()
 
        _pager_fifo_dir="$(mktemp -t -d tg-pager-fifo.XXXXXX)"
        _pager_fifo="$_pager_fifo_dir/0"