tg export
~~~~~~~~~
- Create a new branch containing tidied-up history
- of the current topic branch and its dependencies,
- suitable for pull by upstream - each topic branch
- corresponds to a single commit in the cleaned up history
- (corresponding basically exactly to `tg patch` output
- for the topic branch).
+ Export a tidied-up history of the current topic branch
+ and its dependencies, suitable for feeding upstream.
+ Each topic branch corresponds to a single commit or patch
+ in the cleaned up history (corresponding basically exactly
+ to `tg patch` output for the topic branch).
+ The command has two posible outputs now - either a Git branch
+ with the collapsed 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
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 the quilt mode,
+
+ master$ tg export --quilt for-linus
+
+ would create this directory for-linus:
+
+ for-linus/t/foo/blue.diff
+ for-linus/t/foo/red.diff
+ for-linus/t/bar/good.diff
+ for-linus/t/baz.diff
+ for-linus/series:
+ t/foo/blue.diff -p1
+ t/bar/good.diff -p1
+ t/foo/red.diff -p1
+ t/baz.diff -p1
+
The command works on the current topic branch
- and requires one mandatory argument: the name of the branch
+ and can be called either without a parameter
+ (in that case, '--collapse' is assumed)
+ and with one mandatory argument: the name of the branch
where the exported result shall be stored.
The branch will be silently overwritten if it exists already!
Use git reflog to recover in case of mistake.
- Usage: tg export BRANCH
+ Alternatively, call it with the '--quilt' parameter
+ and an argument specifying the directory
+ where the quilt series should be saved.
+
+ Usage: tg export ([--collapse] BRANCH | --quilt DIR)
TODO: Make stripping of non-essential headers configurable
TODO: Make stripping of [PATCH] and other prefixes configurable
- TODO: --quilt and --mbox options for other modes of operation
+ TODO: --mbox option for other mode of operation
tg update
~~~~~~~~~
name=
output=
+driver=collapse
## Parse options
while [ -n "$1" ]; do
arg="$1"; shift
case "$arg" in
+ --quilt)
+ driver=quilt;;
+ --collapse)
+ driver=collapse;;
-*)
- echo "Usage: tg export NEWBRANCH" >&2
+ echo "Usage: tg export ([--collapse] NEWBRANCH | --quilt DIRECTORY)" >&2
exit 1;;
*)
- [ -z "$output" ] || die "new branch already specified ($output)"
+ [ -z "$output" ] || die "output already specified ($output)"
output="$arg";;
esac
done
base_rev="$(git rev-parse --short --verify "refs/top-bases/$name" 2>/dev/null)" ||
die "not on a TopGit-controlled branch"
-[ -n "$output" ] ||
- die "no target branch specified"
-
-! git rev-parse --verify "$output" >/dev/null 2>&1 ||
- die "target branch '$output' already exists; first run: git branch -D $output"
-
playground="$(mktemp -d)"
trap 'rm -rf "$playground"' EXIT
+
+## Collapse driver
+
# Trusty Cogito code:
load_author()
{
echo "$name" >>"$playground/^ticker"
}
-# collapse_one
+# collapse
# This will collapse a single branch, using information about
# previously collapsed branches stored in $playground.
-collapse_one()
+collapse()
{
- branch_needs_update >/dev/null
- [ "$_ret" -eq 0 ] ||
- die "cancelling $_ret export of $_dep (-> $_name): branch not up-to-date"
-
if [ -s "$playground/$_dep" ]; then
# We've already seen this dep
commit="$(cat "$playground/$_dep")"
echo "$commit $_dep" >>"$playground/$_name^parents"
}
-# Collapse all the branches - this way, collapse_one will be
-# called in topological order.
-recurse_deps collapse_one "$name"
-(_ret=0; _dep="$name"; _name=""; _dep_is_tgish=1; collapse_one)
-git update-ref "refs/heads/$output" "$(cat "$playground/$name")"
+## Quilt driver
+
+quilt()
+{
+ if [ -z "$_dep_is_tgish" ]; then
+ # This dep is not for rewrite
+ return
+ fi
+
+ filename="$output/$_dep.diff"
+ if [ -e "$filename" ]; then
+ # We've already seen this dep
+ return
+ fi
+
+ mkdir -p "$(dirname "$filename")"
+ tg patch "$_dep" >"$filename"
+ echo "$_dep.diff -p1" >>"$output/series"
+ echo "Exported $_dep"
+}
+
+
+## Machinery
+
+if [ "$driver" = "collapse" ]; then
+ [ -n "$output" ] ||
+ die "no target branch specified"
+ ! git rev-parse --verify "$output" >/dev/null 2>&1 ||
+ die "target branch '$output' already exists; first run: git branch -D $output"
+
+elif [ "$driver" = "quilt" ]; then
+ [ -n "$output" ] ||
+ die "no target directory specified"
+ [ ! -e "$output" ] ||
+ die "target directory already exists: $output"
+
+ mkdir -p "$output"
+fi
+
+
+driver()
+{
+ branch_needs_update >/dev/null
+ [ "$_ret" -eq 0 ] ||
+ die "cancelling export of $_dep (-> $_name): branch not up-to-date"
+
+ $driver
+}
+
+# Call driver on all the branches - this will happen
+# in topological order.
+recurse_deps driver "$name"
+(_ret=0; _dep="$name"; _name=""; _dep_is_tgish=1; driver)
+
+
+if [ "$driver" = "collapse" ]; then
+ git update-ref "refs/heads/$output" "$(cat "$playground/$name")"
+
+ depcount="$(cat "$playground/^ticker" | wc -l)"
+ echo "Exported topic branch $name (total $depcount topics) to branch $output"
-depcount="$(cat "$playground/^ticker" | wc -l)"
-echo "Exported topic branch $name (total $depcount topics) to branch $output"
+elif [ "$driver" = "quilt" ]; then
+ depcount="$(cat "$output/series" | wc -l)"
+ echo "Exported topic branch $name (total $depcount topics) to directory $output"
+fi