From: martin f. krafft Date: Tue, 2 Aug 2011 14:50:07 +0000 (+0200) Subject: import first prototype X-Git-Url: https://git.madduck.net/code/topgit-ng.git/commitdiff_plain import first prototype --- dc58ec49df849ec1aef6929cd40c759a6018e056 diff --cc tg-datastore index 0000000,0000000..e9ce139 new file mode 100755 --- /dev/null +++ b/tg-datastore @@@ -1,0 -1,0 +1,47 @@@ ++#!/bin/sh ++set -eu ++ ++. ${0%/*}/tg-datastore.inc ++ ++info() { printf "I: $@\n" >&2; } ++ ++case "$1" in ++ add) ++ # tg-datastore add var=val var2=val2 ... ++ # only add to HEAD ++ shift ++ info "returns non-zero if there is already a datastore on HEAD." ++ info "adding the following data to the datastore of HEAD:" ++ for pair in "$@"; do ++ info " ${pair%%=*}: ${pair#*=}\n" ++ printf "${pair%%=*}: ${pair#*=}\n" ++ done | tg_ds_add_data || die "E: HEAD already has a datastore" ++ ;; ++ remove) ++ # removes from HEAD ++ info "always returns zero, even if there was nothing to remove." ++ tg_ds_remove_data ++ ;; ++ list) ++ # $2 is the commit ++ info "returns non-zero if no datastore found at given commit." ++ info "prints contents of datastore otherwise." ++ tg_ds_list_data "${2:-HEAD}" ++ ;; ++ get) ++ # get parameter $2 from $3 (default HEAD) ++ info "prints the value of the parameter stored in the given commit." ++ info "prints nothing if the commit has a datastore but without the parameter." ++ info "returns non-zero if there is no datastore." ++ tg_ds_get_value "$2" ${3:-HEAD} ++ ;; ++ find) ++ # search for parameter $2 by backtracking from $3 (default HEAD) ++ info "prints the value of the parameter, or empty if parameter is not found." ++ info "returns non-zero if no datastore was found." ++ tg_ds_find_value "$2" ${3:-HEAD} ++ ;; ++ *) ++ echo "Usage: ${0##*/} [ add var=val... | remove | list | get var [commit] | find var [commit] ]" ++ ;; ++esac diff --cc tg-datastore-pcommits.inc index 0000000,0000000..f03ede5 new file mode 100644 --- /dev/null +++ b/tg-datastore-pcommits.inc @@@ -1,0 -1,0 +1,85 @@@ ++_get_empty_treeref() ++{ ++ git mktree $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' ++} diff --cc tg-datastore.inc index 0000000,0000000..d79f159 new file mode 100644 --- /dev/null +++ b/tg-datastore.inc @@@ -1,0 -1,0 +1,45 @@@ ++die() ++{ ++ printf "E: $@\n" >&2 ++ exit 1 ++} ++ ++tg_ds_resolve_commit() ++{ ++ git rev-parse --verify $1 2>/dev/null ++} ++ ++. ${0%/*}/tg-datastore-pcommits.inc ++ ++tg_ds_get_value() ++{ ++ local name; name="${1:-}" ++ local commit; commit="${2:-HEAD}" ++ ++ [ -z "$1" ] && die 'tg_ds_get_value: missing first argument (name)' ++ tg_ds_resolve_commit $commit >/dev/null || die "tg_ds_get_value: invalid commit: $commit" ++ ++ local data; data=$(tg_ds_list_data "$commit") || return 1 ++ printf "$data\n" | sed -rne "s,^${name}: *,,p" ++} ++ ++tg_ds_find_value() ++{ ++ local name; name="${1:-}" ++ local commit; commit="${2:-HEAD}" ++ ++ [ -z "$1" ] && die 'tg_ds_find_value: missing first argument (name)' ++ ref=$(tg_ds_resolve_commit $commit) || die "tg_ds_find_value: invalid commit: $commit" ++ ++ while :; do ++ if [ "$name" = commitref ]; then ++ tg_ds_list_data "$commit" >/dev/null && printf "$ref\n" && return 0 ++ else ++ tg_ds_get_value "$name" $commit && return 0 ++ fi ++ commit="${commit}^" ++ ref=$(tg_ds_resolve_commit "${commit}") || break ++ done ++ ++ return 1 ++}