chiark / gitweb /
Merge commit 'index-wt~2' of git://repo.or.cz/topgit/bertw upstream features/vim-modelines fixes/ensure-worktree fixes/export--b-deps fixes/independent-help fixes/more-help fixes/tg--r-require-arg
authorUwe Kleine-König <u.kleine-koenig@pengutronix.de>
Sun, 26 Dec 2010 12:20:26 +0000 (13:20 +0100)
committerUwe Kleine-König <u.kleine-koenig@pengutronix.de>
Sun, 26 Dec 2010 12:20:37 +0000 (13:20 +0100)
.gitignore
README
contrib/tg-completion.bash
tg-export.sh
tg-files.sh
tg-mail.sh
tg-next.sh [new file with mode: 0644]
tg-patch.sh
tg-prev.sh [new file with mode: 0644]
tg-summary.sh
tg.sh

index 2a4d16597b3883e5cf9dd2ecefe99c321f830242..6cfab6e9446d1213cb633e4542ce7c20f3b0c456 100644 (file)
 /tg-info.txt
 /tg-mail
 /tg-mail.txt
+/tg-next
+/tg-next.txt
 /tg-log
 /tg-log.txt
 /tg-patch
 /tg-patch.txt
+/tg-prev
+/tg-prev.txt
 /tg-push
 /tg-push.txt
 /tg-remote
diff --git a/README b/README
index 48db36a08f5566f709e68560ad0667be9290becd..ed8d358c9c85132931c2781498e3205f5d61ce2d 100644 (file)
--- a/README
+++ b/README
@@ -323,6 +323,10 @@ tg mail
 
        to let `git send-email` ask for confirmation before sending any mail.
 
+       Options:
+         -i            base patch generation on index instead of branch
+         -w            base patch generation on working tree instead of branch
+
        TODO: 'tg mail patchfile' to mail an already exported patch
        TODO: mailing patch series
        TODO: specifying additional options and addresses on command
@@ -370,6 +374,10 @@ tg summary
        branches in a machine-readable format.  Feed this to "tsort"
        to get the output from --sort.
 
+       Options:
+         -i            Use TopGit meta data from the index instead of branch
+         -w            Use TopGit meta data from the working tree instead of branch
+
        TODO: Speed up by an order of magnitude
        TODO: Text graph view
 
@@ -531,8 +539,24 @@ tg log
        Note: if you have merged changes from a different repository, this
        command might not list all interesting commits.
 
-TODO: tg rename
+tg prev
+~~~~~~~
+       Outputs the direct dependencies for the current or named patch.
 
+       Options:
+         -i            show dependencies based on index instead of branch
+         -w            show dependencies based on working tree instead of branch
+
+tg next
+~~~~~~~
+       Outputs all patches which directly depend on the current or
+       named patch.
+
+       Options:
+         -i            show dependencies based on index instead of branch
+         -w            show dependencies based on working tree instead of branch
+
+TODO: tg rename
 
 IMPLEMENTATION
 --------------
index 48e47c7047c3c7308cd10b5a0327a63e94cd6fb1..e34b66f56fb22f50ad6bc1e05524f1a4fe4b4d28 100755 (executable)
@@ -359,6 +359,14 @@ _tg_mail ()
        local cur="${COMP_WORDS[COMP_CWORD]}"
 
        case "$cur" in
+       -*)
+               __tgcomp "
+                       -i
+                       -w
+                       -s
+                       -r
+               "
+               ;;
        *)
                __tgcomp "$(__tg_topics)"
        esac
@@ -426,7 +434,11 @@ _tg_summary ()
        *)
                __tgcomp "
                        --graphviz
+                       --sort
+                       --deps
                        -t
+                       -i
+                       -w
                "
        esac
 }
@@ -441,6 +453,38 @@ _tg_update ()
        esac
 }
 
+_tg_next ()
+{
+       local cur="${COMP_WORDS[COMP_CWORD]}"
+
+       case "$cur" in
+       -*)
+               __tgcomp "
+                       -i
+                       -w
+               "
+               ;;
+       *)
+               __tgcomp "$(__tg_heads)"
+       esac
+}
+
+_tg_prev ()
+{
+       local cur="${COMP_WORDS[COMP_CWORD]}"
+
+       case "$cur" in
+       -*)
+               __tgcomp "
+                       -i
+                       -w
+               "
+               ;;
+       *)
+               __tgcomp "$(__tg_topics)"
+       esac
+}
+
 ### }}}
 ### {{{ tg completion
 
@@ -488,7 +532,9 @@ _tg ()
        info)        _tg_info ;;
        log)         _tg_log ;;
        mail)        _tg_mail ;;
+       next)        _tg_next ;;
        patch)       _tg_patch ;;
+       prev)        _tg_prev ;;
        push)        _tg_push ;;
        remote)      _tg_remote ;;
        summary)     _tg_summary ;;
index 1d0533e4dac05993775ad0aa4ef004eb5a01c252..486ec94ba00f97e831848648ecb6c37272d5e823 100644 (file)
@@ -102,7 +102,7 @@ collapsed_commit()
                        echo "TopGit-driven merge of branches:"
                        echo
                        cut -f 2 "$playground/$name^parents"
-               } | git commit-tree "$(pretty_tree "refs/top-bases/$name")" \
+               } | git commit-tree "$(pretty_tree "$name" -b)" \
                        $(for p in $parent; do echo -p $p; done))"
        fi
 
@@ -217,7 +217,7 @@ linearize()
        else
                retmerge=0;
 
-               git merge-recursive "$(pretty_tree "refs/top-bases/$_dep")" -- HEAD "$(pretty_tree "refs/heads/$_dep")" || retmerge="$?";
+               git merge-recursive "$(pretty_tree "$_dep" -b)" -- HEAD "$(pretty_tree "refs/heads/$_dep")" || retmerge="$?";
 
                if test "x$retmerge" != "x0"; then
                        git rerere;
index b88940a0ba8f2a294514f7a8f4b31444e41f2a21..507efcb331aa026f48d76f0c5cd89db31cc38e04 100644 (file)
@@ -4,7 +4,7 @@
 # GPLv2
 
 name=
-topic=
+head_from=
 
 
 ## Parse options
@@ -12,12 +12,9 @@ topic=
 while [ -n "$1" ]; do
        arg="$1"; shift
        case "$arg" in
-       -i)
-               [ -z "$topic" ] || die "-i and -w are mutually exclusive"
-               topic=-i;;
-       -w)
-               [ -z "$topic" ] || die "-i and -w are mutually exclusive"
-               topic=-w;;
+       -i|-w)
+               [ -z "$head_from" ] || die "-i and -w are mutually exclusive"
+               head_from="$arg";;
        -*)
                echo "Usage: tg [...] files [-i | -w] [NAME]" >&2
                exit 1;;
@@ -28,16 +25,22 @@ while [ -n "$1" ]; do
 done
 
 
-[ -n "$name" -a -n "$topic" ] &&
-       die "-i/-w are mutually exclusive with NAME"
+head="$(git symbolic-ref HEAD)"
+head="${head#refs/heads/}"
 
-[ -n "$name" ] || name="$(git symbolic-ref HEAD | sed 's#^refs/\(heads\|top-bases\)/##')"
+[ -n "$name" ] ||
+       name="$head"
 base_rev="$(git rev-parse --short --verify "refs/top-bases/$name" 2>/dev/null)" ||
        die "not a TopGit-controlled branch"
 
+if [ -n "$head_from" ] && [ "$name" != "$head" ]; then
+       die "$head_from makes only sense for the current branch"
+fi
+
 b_tree=$(pretty_tree "$name" -b)
-t_tree=$(pretty_tree "$name" $topic)
+t_tree=$(pretty_tree "$name" $head_from)
 
 git diff-tree --name-only -r $b_tree $t_tree
 
 # vim:noet
+
index dd4a95a74ad9e47ed39dbff05f5f5d53993981e7..17ce02c9f4a904724d802a825e42a22c2aa61a62 100644 (file)
@@ -3,6 +3,7 @@
 # GPLv2
 
 name=
+head_from=
 send_email_args=
 in_reply_to=
 
@@ -12,12 +13,15 @@ in_reply_to=
 while [ -n "$1" ]; do
        arg="$1"; shift
        case "$arg" in
+       -i|-w)
+               [ -z "$head_from" ] || die "-i and -w are mutually exclusive"
+               head_from="$arg";;
        -s)
                send_email_args="$1"; shift;;
        -r)
                in_reply_to="$1"; shift;;
        -*)
-               echo "Usage: tg [...] mail [-s SEND_EMAIL_ARGS] [-r REFERENCE_MSGID] [NAME]" >&2
+               echo "Usage: tg [...] mail [-s SEND_EMAIL_ARGS] [-r REFERENCE_MSGID] [-i | -w] [NAME]" >&2
                exit 1;;
        *)
                [ -z "$name" ] || die "name already specified ($name)"
@@ -25,7 +29,8 @@ while [ -n "$1" ]; do
        esac
 done
 
-[ -n "$name" ] || name="$(git symbolic-ref HEAD | sed 's#^refs/heads/##')"
+head="$(git symbolic-ref HEAD | sed 's#^refs/heads/##')"
+[ -n "$name" ] || name="$head"
 base_rev="$(git rev-parse --short --verify "refs/top-bases/$name" 2>/dev/null)" ||
        die "not a TopGit-controlled branch"
 
@@ -36,7 +41,8 @@ fi
 
 patchfile="$(get_temp tg-mail)"
 
-$tg patch "$name" >"$patchfile"
+# let tg patch sort out whether $head_from makes sense for $name
+$tg patch "$name" $head_from >"$patchfile"
 
 header="$(sed -e '/^$/,$d' -e "s,','\\\\'',g" "$patchfile")"
 
diff --git a/tg-next.sh b/tg-next.sh
new file mode 100644 (file)
index 0000000..93dd5b5
--- /dev/null
@@ -0,0 +1,45 @@
+#!/bin/sh
+# TopGit - A different patch queue manager
+# (c) Petr Baudis <pasky@suse.cz>  2008
+# (c) Bert Wesarg <Bert.Wesarg@googlemail.com>  2009
+# GPLv2
+
+name=
+head_from=
+
+
+## Parse options
+
+while [ -n "$1" ]; do
+       arg="$1"; shift
+       case "$arg" in
+       -i|-w)
+               [ -z "$head_from" ] || die "-i and -w are mutually exclusive"
+               head_from="$arg";;
+       -*)
+               echo "Usage: tg next [-i | -w] [NAME]" >&2
+               exit 1;;
+       *)
+               [ -z "$name" ] || die "name already specified ($name)"
+               name="$arg";;
+       esac
+done
+
+head="$(git rev-parse --abbrev-ref=loose HEAD)"
+[ -n "$name" ] ||
+       name="$head"
+
+git for-each-ref --format='%(refname)' refs/top-bases |
+       while read ref; do
+               parent="${ref#refs/top-bases/}"
+
+               from=$head_from
+               # select .topdeps source for HEAD branch
+               [ "x$parent" = "x$head" ] ||
+                       from=
+
+               cat_file "$parent:.topdeps" $from | fgrep -qx "$name" ||
+                       continue
+
+               echo "$parent"
+       done
index 85346ec045952eb72d9ed408ebc469dc78469f58..9def6e5e934056c3498cd8158bdc7a6cc9ffe251 100644 (file)
@@ -6,8 +6,6 @@
 name=
 
 head_from=
-diff_opts=
-diff_committed_only=yes        # will be unset for index/worktree
 
 
 ## Parse options
@@ -15,15 +13,9 @@ diff_committed_only=yes      # will be unset for index/worktree
 while [ -n "$1" ]; do
        arg="$1"; shift
        case "$arg" in
-       -i)
+       -i|-w)
                [ -z "$head_from" ] || die "-i and -w are mutually exclusive"
-               head_from=-i
-               diff_opts="$diff_opts --cached";
-               diff_committed_only=;;
-       -w)
-               [ -z "$head_from" ] || die "-i and -w are mutually exclusive"
-               head_from=-w
-               diff_committed_only=;;
+               head_from="$arg";;
        -*)
                echo "Usage: tg [...] patch [-i | -w] [NAME]" >&2
                exit 1;;
@@ -49,20 +41,36 @@ fi
 
 setup_pager
 
-cat_file "$name:.topmsg" $head_from
-echo
-[ -n "$(git grep $diff_opts '^[-]--' ${diff_committed_only:+"$name"} -- ".topmsg")" ] || echo '---'
-
-# Evil obnoxious hack to work around the lack of git diff --exclude
-git_is_stupid="$(get_temp tg-patch-changes)"
-git diff --name-only $diff_opts "$base_rev" ${diff_committed_only:+"$name"} -- |
-       fgrep -vx ".topdeps" |
-       fgrep -vx ".topmsg" >"$git_is_stupid" || : # fgrep likes to fail randomly?
-if [ -s "$git_is_stupid" ]; then
-       cd "$root_dir"
-       cat "$git_is_stupid" | xargs git diff -a --patch-with-stat $diff_opts "$base_rev" ${diff_committed_only:+"$name"} --
-else
+
+# put out the commit message
+# and put an empty line out, if the last one in the message was not an empty line
+# and put out "---" if the commit message does not have one yet
+cat_file "$name:.topmsg" $head_from |
+       awk '
+/^---/ {
+    has_3dash=1;
+}
+       {
+    need_empty = 1;
+    if ($0 == "")
+        need_empty = 0;
+    print;
+}
+END    {
+    if (need_empty)
+        print "";
+    if (!has_3dash)
+        print "---";
+}
+'
+
+b_tree=$(pretty_tree "$name" -b)
+t_tree=$(pretty_tree "$name" $head_from)
+
+if [ $b_tree = $t_tree ]; then
        echo "No changes."
+else
+       git diff-tree -p --stat $b_tree $t_tree
 fi
 
 echo '-- '
diff --git a/tg-prev.sh b/tg-prev.sh
new file mode 100644 (file)
index 0000000..1f1e0c1
--- /dev/null
@@ -0,0 +1,38 @@
+#!/bin/sh
+# TopGit - A different patch queue manager
+# (c) Petr Baudis <pasky@suse.cz>  2008
+# (c) Bert Wesarg <Bert.Wesarg@googlemail.com>  2009
+# GPLv2
+
+name=
+head_from=
+
+
+## Parse options
+
+while [ -n "$1" ]; do
+       arg="$1"; shift
+       case "$arg" in
+       -i|-w)
+               [ -z "$head_from" ] || die "-i and -w are mutually exclusive"
+               head_from="$arg";;
+       -*)
+               echo "Usage: tg next [-i | -w] [NAME]" >&2
+               exit 1;;
+       *)
+               [ -z "$name" ] || die "name already specified ($name)"
+               name="$arg";;
+       esac
+done
+
+head="$(git rev-parse --abbrev-ref=loose HEAD)"
+[ -n "$name" ] ||
+       name="$head"
+base_rev="$(git rev-parse --short --verify "refs/top-bases/$name" 2>/dev/null)" ||
+       die "not a TopGit-controlled branch"
+
+# select .topdeps source for HEAD branch
+[ "x$name" = "x$head" ] ||
+       head_from=
+
+cat_file "$name:.topdeps" $head_from
index 612bd27443779266de3385dfce6b2812be81f85a..1c99e2225c61a2a4c9a07ec6bd64ee82558ddda7 100644 (file)
@@ -7,13 +7,16 @@ terse=
 graphviz=
 sort=
 deps=
-
+head_from=
 
 ## Parse options
 
 while [ -n "$1" ]; do
        arg="$1"; shift
        case "$arg" in
+       -i|-w)
+               [ -z "$head_from" ] || die "-i and -w are mutually exclusive"
+               head_from="$arg";;
        -t)
                terse=1;;
        --graphviz)
@@ -23,7 +26,7 @@ while [ -n "$1" ]; do
        --deps)
                deps=1;;
        *)
-               echo "Usage: tg [...] summary [-t | --sort | --deps | --graphviz]" >&2
+               echo "Usage: tg [...] summary [-t | --sort | --deps | --graphviz] [-i | -w]" >&2
                exit 1;;
        esac
 done
@@ -68,8 +71,11 @@ process_branch()
 
        current=' '
        [ "$name" != "$curname" ] || current='>'
+       from=$head_from
+       [ "$name" = "$curname" ] ||
+               from=
        nonempty=' '
-       ! branch_empty "$name" || nonempty='0'
+       ! branch_empty "$name" $from || nonempty='0'
        remote=' '
        [ -z "$base_remote" ] || remote='l'
        ! has_remote "$name" || remote='r'
@@ -88,7 +94,7 @@ process_branch()
        branch_contains "$name" "refs/top-bases/$name" || base_update='B'
 
        if [ "$(git rev-parse "$name")" != "$rev" ]; then
-               subject="$(git cat-file blob "$name:.topmsg" | sed -n 's/^Subject: //p')"
+               subject="$(cat_file "$name:.topmsg" $from | sed -n 's/^Subject: //p')"
        else
                # No commits yet
                subject="(No commits)"
@@ -99,7 +105,7 @@ process_branch()
 }
 
 if [ -n "$deps" ]; then
-       list_deps
+       list_deps $head_from
        exit 0
 fi
 
@@ -113,7 +119,10 @@ git for-each-ref refs/top-bases |
                if [ -n "$terse" ]; then
                        echo "$name"
                elif [ -n "$graphviz$sort" ]; then
-                       git cat-file blob "$name:.topdeps" | while read dep; do
+                       from=$head_from
+                       [ "$name" = "$curname" ] ||
+                               from=
+                       cat_file "$name:.topdeps" $from | while read dep; do
                                dep_is_tgish=true
                                ref_exists "refs/top-bases/$dep"  ||
                                        dep_is_tgish=false
diff --git a/tg.sh b/tg.sh
index c77898678cdd275783746b0567a6de7edb905192..9082d88910569af146dde388332bedd0b555ffc1 100644 (file)
--- a/tg.sh
+++ b/tg.sh
@@ -284,15 +284,23 @@ needs_update()
        recurse_deps branch_needs_update "$@"
 }
 
-# branch_empty NAME
+# branch_empty NAME [-i | -w]
 branch_empty()
 {
-       [ -z "$(git diff-tree "refs/top-bases/$1" "$1" -- | fgrep -v "  .top")" ]
+       [ "$(pretty_tree "$1" -b)" = "$(pretty_tree "$1" ${2-})" ]
 }
 
-# list_deps
+# list_deps [-i | -w]
+# -i/-w apply only to HEAD
 list_deps()
 {
+       local head
+       local head_from
+       local from
+       head_from=${1-}
+       head="$(git symbolic-ref -q HEAD)" ||
+               head="..detached.."
+
        git for-each-ref refs/top-bases |
                while read rev type ref; do
                        name="${ref#refs/top-bases/}"
@@ -300,7 +308,10 @@ list_deps()
                                continue;
                        fi
 
-                       git cat-file blob "$name:.topdeps" | while read dep; do
+                       from=$head_from
+                       [ "refs/heads/$name" = "$head" ] ||
+                               from=
+                       cat_file "$name:.topdeps" $from | while read dep; do
                                dep_is_tgish=true
                                ref_exists "refs/top-bases/$dep"  ||
                                        dep_is_tgish=false