+# cat_file TOPIC:PATH [FROM]
+# cat the file PATH from branch TOPIC when FROM is empty.
+# FROM can be -i or -w, than the file will be from the index or worktree,
+# respectively. The caller should than ensure that HEAD is TOPIC, to make sense.
+cat_file()
+{
+ path="$1"
+ case "${2-}" in
+ -w)
+ cat "$root_dir/${path#*:}"
+ ;;
+ -i)
+ # ':file' means cat from index
+ git cat-file blob ":${path#*:}"
+ ;;
+ '')
+ git cat-file blob "$path"
+ ;;
+ *)
+ die "Wrong argument to cat_file: '$2'"
+ ;;
+ esac
+}
+
+# get tree for the committed topic
+get_tree_()
+{
+ echo "$1"
+}
+
+# get tree for the base
+get_tree_b()
+{
+ echo "refs/top-bases/$1"
+}
+
+# get tree for the index
+get_tree_i()
+{
+ git write-tree
+}
+
+# get tree for the worktree
+get_tree_w()
+{
+ i_tree=$(git write-tree)
+ (
+ # the file for --index-output needs to sit next to the
+ # current index file
+ : ${GIT_INDEX_FILE:="$git_dir/index"}
+ TMP_INDEX="$(mktemp "${GIT_INDEX_FILE}-tg.XXXXXX")"
+ git read-tree -m $i_tree --index-output="$TMP_INDEX" &&
+ GIT_INDEX_FILE="$TMP_INDEX" &&
+ export GIT_INDEX_FILE &&
+ git diff --name-only -z HEAD |
+ git update-index -z --add --remove --stdin &&
+ git write-tree &&
+ rm -f "$TMP_INDEX"
+ )
+}
+
+# pretty_tree NAME [-b | -i | -w]
+# Output tree ID of a cleaned-up tree without tg's artifacts.
+# NAME will be ignored for -i and -w, but needs to be present
+pretty_tree()
+{
+ name=$1
+ source=${2#?}
+ git ls-tree --full-tree "$(get_tree_$source "$name")" |
+ awk -F ' ' '$2 !~ /^.top/' |
+ git mktree
+}
+