From: Uwe Kleine-König Date: Tue, 3 Mar 2009 09:30:10 +0000 (+0100) Subject: Merge branch 'upstream' of git.debian.org:/git/collab-maint/topgit X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=topgit.git;a=commitdiff_plain;h=2f7cb405238120a51ab113427d25488ef87ef14b;hp=a7f81c6f671c2c9803ae9e13108e7b3f37be9e9f Merge branch 'upstream' of git.debian.org:/git/collab-maint/topgit --- diff --git a/README b/README index 7c6a70f..d2f095d 100644 --- a/README +++ b/README @@ -284,8 +284,9 @@ tg patch tg patch will be able to automatically send the patches by mail or save them to files. (TODO) - TODO: tg patch -i to base at index instead of branch, - -w for working tree + Options: + -i base patch generation on index instead of branch + -w base patch generation on working tree instead of branch tg mail ~~~~~~~ diff --git a/contrib/tg-completion.bash b/contrib/tg-completion.bash index 9641d04..de8a7b5 100755 --- a/contrib/tg-completion.bash +++ b/contrib/tg-completion.bash @@ -359,6 +359,12 @@ _tg_patch () local cur="${COMP_WORDS[COMP_CWORD]}" case "$cur" in + -*) + __tgcomp " + -i + -w + " + ;; *) __tgcomp "$(__tg_topics)" esac diff --git a/tg-mail.sh b/tg-mail.sh index f5c0cf4..8d3b632 100644 --- a/tg-mail.sh +++ b/tg-mail.sh @@ -29,6 +29,10 @@ done base_rev="$(git rev-parse --short --verify "refs/top-bases/$name" 2>/dev/null)" || die "not a TopGit-controlled branch" +if ! git send-emmail --help >/dev/null 2>&1; then + die "git send-email command not available" +fi + if [ -n "$in_reply_to" ]; then send_email_args="$send_email_args --in-reply-to=$in_reply_to" fi diff --git a/tg-patch.sh b/tg-patch.sh index a704375..d701c54 100644 --- a/tg-patch.sh +++ b/tg-patch.sh @@ -5,14 +5,25 @@ name= +topic= +diff_opts= +diff_committed_only=yes # will be unset for index/worktree + ## Parse options while [ -n "$1" ]; do arg="$1"; shift case "$arg" in + -i) + topic='(i)' + diff_opts="$diff_opts --cached"; + diff_committed_only=;; + -w) + topic='(w)' + diff_committed_only=;; -*) - echo "Usage: tg [...] patch [NAME]" >&2 + echo "Usage: tg [...] patch [-i | -w] [NAME]" >&2 exit 1;; *) [ -z "$name" ] || die "name already specified ($name)" @@ -20,28 +31,39 @@ while [ -n "$1" ]; do esac done + +[ -n "$name" -a -z "$diff_committed_only" ] && + die "-i/-w are mutually exclusive with NAME" + [ -n "$name" ] || name="$(git symbolic-ref HEAD | sed 's#^refs/\(heads\|top-bases\)/##')" base_rev="$(git rev-parse --short --verify "refs/top-bases/$name" 2>/dev/null)" || die "not a TopGit-controlled branch" -git cat-file blob "$name:.topmsg" +# if not index/worktree, topic is current branch +[ -z "$topic" ] && topic="$name" + + + +setup_pager + +cat_file "$topic:.topmsg" echo -[ -n "$(git grep '^[-]--' "$name" -- ".topmsg")" ] || 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="$(mktemp -t tg-patch-changes.XXXXXX)" -git diff-tree --name-only "$base_rev" "$name" | +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 - cat "$git_is_stupid" | xargs git diff --patch-with-stat "$base_rev" "$name" -- + cat "$git_is_stupid" | xargs git diff --patch-with-stat $diff_opts "$base_rev" ${diff_committed_only:+"$name"} -- else echo "No changes." fi rm "$git_is_stupid" echo '-- ' -echo "tg: ($base_rev..) $name (depends on: $(git cat-file blob "$name:.topdeps" | paste -s -d' '))" +echo "tg: ($base_rev..) $name (depends on: $(cat_file "$topic:.topdeps" | paste -s -d' '))" branch_contains "$name" "$base_rev" || echo "tg: The patch is out-of-date wrt. the base! Run \`$tg update\`." diff --git a/tg.sh b/tg.sh index 5bb2d0c..f0496f1 100644 --- a/tg.sh +++ b/tg.sh @@ -3,6 +3,7 @@ # (c) Petr Baudis 2008 # GPLv2 +TG_VERSION=0.6 ## Auxiliary functions @@ -17,6 +18,27 @@ die() exit 1 } +# cat_file "topic:file" +# Like `git cat-file blob $1`, but topics '(i)' and '(w)' means index and worktree +cat_file() +{ + arg="$1" + case "$arg" in + '(w):'*) + arg=$(echo "$arg" | tail --bytes=+5) + cat "$arg" + return + ;; + '(i):'*) + # ':file' means cat from index + arg=$(echo "$arg" | tail --bytes=+5) + git cat-file blob ":$arg" + ;; + *) + git cat-file blob "$arg" + esac +} + # setup_hook NAME setup_hook() { @@ -243,7 +265,7 @@ do_help() sep="|" done - echo "TopGit v0.5 - A different patch queue manager" + 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 || : @@ -258,6 +280,44 @@ do_help() fi } +## Pager stuff + +# isatty FD +isatty() +{ + test -t $1 +} + +# setup_pager +# Spawn pager process and redirect the rest of our output to it +setup_pager() +{ + isatty 1 || return 0 + + # TG_PAGER = GIT_PAGER | PAGER | less + # NOTE: GIT_PAGER='' is significant + TG_PAGER=${GIT_PAGER-${PAGER-less}} + + [ -z "$TG_PAGER" -o "$TG_PAGER" = "cat" ] && return 0 + + + # now spawn pager + 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" + mkfifo -m 600 "$_pager_fifo" + + "$TG_PAGER" < "$_pager_fifo" & + exec > "$_pager_fifo" # dup2(pager_fifo.in, 1) + + # this is needed so e.g. `git diff` will still colorize it's output if + # requested in ~/.gitconfig with color.diff=auto + export GIT_PAGER_IN_USE=1 + + # atexit(close(1); wait pager) + trap "exec >&-; rm \"$_pager_fifo\"; rmdir \"$_pager_fifo_dir\"; wait" EXIT +} ## Startup