From: Uwe Kleine-König Date: Sun, 26 Dec 2010 12:20:26 +0000 (+0100) Subject: Merge commit 'index-wt~2' of git://repo.or.cz/topgit/bertw X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=topgit.git;a=commitdiff_plain;h=refs%2Ftop-bases%2Ffixes%2Fexport--b-deps;hp=9b25e8482c536324a6ecdefdf8abc1c0b1dca83e Merge commit 'index-wt~2' of git://repo.or.cz/topgit/bertw --- diff --git a/.gitignore b/.gitignore index 2a4d165..6cfab6e 100644 --- a/.gitignore +++ b/.gitignore @@ -30,10 +30,14 @@ /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 48db36a..ed8d358 100644 --- 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 -------------- diff --git a/contrib/tg-completion.bash b/contrib/tg-completion.bash index 48e47c7..e34b66f 100755 --- a/contrib/tg-completion.bash +++ b/contrib/tg-completion.bash @@ -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 ;; diff --git a/tg-export.sh b/tg-export.sh index 1d0533e..486ec94 100644 --- a/tg-export.sh +++ b/tg-export.sh @@ -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; diff --git a/tg-files.sh b/tg-files.sh index b88940a..507efcb 100644 --- a/tg-files.sh +++ b/tg-files.sh @@ -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 + diff --git a/tg-mail.sh b/tg-mail.sh index dd4a95a..17ce02c 100644 --- a/tg-mail.sh +++ b/tg-mail.sh @@ -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 index 0000000..93dd5b5 --- /dev/null +++ b/tg-next.sh @@ -0,0 +1,45 @@ +#!/bin/sh +# TopGit - A different patch queue manager +# (c) Petr Baudis 2008 +# (c) Bert Wesarg 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 diff --git a/tg-patch.sh b/tg-patch.sh index 85346ec..9def6e5 100644 --- a/tg-patch.sh +++ b/tg-patch.sh @@ -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 index 0000000..1f1e0c1 --- /dev/null +++ b/tg-prev.sh @@ -0,0 +1,38 @@ +#!/bin/sh +# TopGit - A different patch queue manager +# (c) Petr Baudis 2008 +# (c) Bert Wesarg 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 diff --git a/tg-summary.sh b/tg-summary.sh index 612bd27..1c99e22 100644 --- a/tg-summary.sh +++ b/tg-summary.sh @@ -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 c778986..9082d88 100644 --- 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