--- /dev/null
+_get_empty_treeref()
+{
+ git mktree </dev/null
+}
+
+_make_pcommit()
+{
+ local timestamp; timestamp=$(date +'%s %z')
+ git hash-object -t commit -w --stdin <<-_commit_data
+ tree $(_get_empty_treeref)
+ author TopGit <> $timestamp
+ committer "$author"
+ x-topgit-data-node yes
+
+ TopGit data node
+
+ This commit is used internally by TopGit. Please just ignore it.
+
+ TopGit data follow:
+ $(cat)
+ _commit_data
+}
+
+_append_parentref_to_HEAD()
+{
+ local parent; parent="$1"
+ local ref; ref=$(git cat-file commit HEAD |
+ sed -e "/^parent/aparent ${parent}" |
+ git hash-object -t commit -w --stdin)
+ git update-ref HEAD $ref
+}
+
+_remove_parentref_from_HEAD()
+{
+ local parent; parent="$1"
+ local ref; ref=$(git cat-file commit HEAD |
+ grep -v "^parent ${parent}" |
+ git hash-object -t commit -w --stdin)
+ git update-ref HEAD $ref
+}
+
+# returns 0 if $1 is a valid TopGit pcommit
+_is_pcommit()
+{
+ local pcommit; pcommit="$1"
+ git cat-file commit $pcommit | grep -q '^x-topgit-data-node yes$'
+}
+
+# returns the ref of the pcommit attached to $1
+# returns 1 when none is found
+_find_pcommit()
+{
+ local commit; commit="$1"
+ local parentnr; parentnr=1
+
+ while :; do
+ ref=$(tg_ds_resolve_commit "${commit}^${parentnr}") || break
+ _is_pcommit "$ref" && printf "$ref\n" && return 0
+ parentnr=$(($parentnr + 1))
+ done
+ return 1
+}
+
+# expects data on stdin and adds to HEAD
+tg_ds_add_data()
+{
+ local author; author=$(git cat-file commit HEAD | sed -rne 's,^author ,,p')
+ _append_parentref_to_HEAD $(_make_pcommit "$author")
+}
+
+# removes data from HEAD
+tg_ds_remove_data()
+{
+ local pcommit; pcommit=$(_find_pcommit HEAD) || return # no error
+ _remove_parentref_from_HEAD $pcommit
+}
+
+# lists data on a given commit
+tg_ds_list_data()
+{
+ local commit; commit="${1:-HEAD}"
+ ref=$(tg_ds_resolve_commit $commit) || die "tg_ds_list_data: invalid commit: $commit"
+ local pcommit; pcommit=$(_find_pcommit $commit) || return 1
+ git cat-file commit $pcommit | sed -e '0,/^TopGit data follow:$/d'
+}