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
~~~~~~~
in the cleaned up history (corresponding basically exactly
to `tg patch` output for the topic branch).
- The command has two possible outputs now - either a Git branch
- with the collapsed history, or a quilt series in new directory.
+ The command has three possible outputs now - either a Git branch with
+ the collapsed history, a Git branch with a linearized history, or a
+ quilt series in new directory.
In case of producing collapsed history in new branch,
- You can use this collapsed structure either for providing
+ you can use this collapsed structure either for providing
a pull source for upstream, or further linearization e.g.
for creation of a quilt series using git log:
`- t/bar/good <,-------------------'/
`- t/baz ---------------------'
+ In case of using the linearize mode:
+
+ master$ tg export --linearize for-linus
+
+ you get a linear history respecting the dependencies of your patches in
+ a new branch for-linus. The result should be more or less the same as
+ using quilt mode and reimporting it into a Git branch. (More or less
+ because the topologic order can usually be extended in more than one
+ way into a complete ordering and the two methods may choose different
+ one's.) The result might be more appropriate for merging upstream as
+ it contains fewer merges.
+
+ Note that you might get conflicts during linearization because the
+ patches are reordered to get a linear history.
+
In case of the quilt mode,
master$ tg export --quilt for-linus
names get a number as prefix to allow getting the order without
consulting the series file, which eases sending out the patches.
- Usage: tg export ([--collapse] BRANCH | --quilt DIR)
+ Usage: tg export ([(--collapse | --linearize)] BRANCH | --quilt DIR)
TODO: Make stripping of non-essential headers configurable
TODO: Make stripping of [PATCH] and other prefixes configurable
TODO: --mbox option for other mode of operation
TODO: -a option to export all branches
- TODO: For quilt exporting, use a temporary branch and remove it when
- done - this would allow producing conflict-less series
+ TODO: For quilt exporting, export the linearized history created in a
+ temporary branch---this would allow producing conflict-less
+ series
tg import
~~~~~~~~~
# (c) Petr Baudis <pasky@suse.cz> 2008
# GPLv2
+ TG_VERSION=0.6
## Auxiliary functions
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()
{
# Whether B1 is a superset of B2.
branch_contains()
{
- [ -z "$(git rev-list ^"$1" "$2" --)" ]
+ [ -z "$(git rev-list --max-count=1 ^"$1" "$2" --)" ]
}
# ref_exists REF
[ -n "$base_remote" ] && ref_exists "remotes/$base_remote/$1"
}
+branch_annihilated()
+{
+ _name="$1";
+
+ # use the merge base in case the base is ahead.
+ mb="$(git merge-base "refs/top-bases/$_name" "$_name")";
+
+ test "$(git rev-parse "$mb^{tree}")" = "$(git rev-parse "$_name^{tree}")";
+}
+
# recurse_deps CMD NAME [BRANCHPATH...]
# Recursively eval CMD on all dependencies of NAME.
# CMD can refer to $_name for queried branch name,
if has_remote "top-bases/$_name"; then
echo "refs/remotes/$base_remote/top-bases/$_name" >>"$_depsfile"
fi
- git cat-file blob "$_name:.topdeps" >>"$_depsfile"
+
+ # if the branch was annihilated, there exists no .topdeps file
+ if ! branch_annihilated "$_name"; then
+ #TODO: handle nonexisting .topdeps?
+ git cat-file blob "$_name:.topdeps" >>"$_depsfile";
+ fi;
_ret=0
while read _dep; do
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 || :
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