From cd30539214bb09881b84c796a50d30e409dee3fa Mon Sep 17 00:00:00 2001 From: Johan Herland Date: Sat, 13 Feb 2010 22:28:18 +0100 Subject: Notes API: Allow multiple concurrent notes trees with new struct notes_tree The new struct notes_tree encapsulates access to a specific notes tree. It is provided to allow callers to make use of several different notes trees simultaneously. A struct notes_tree * parameter is added to every function in the notes API. In all cases, NULL can be passed, in which case the fallback "default" notes tree (default_notes_tree) is used. Signed-off-by: Johan Herland Signed-off-by: Junio C Hamano --- notes.c | 90 ++++++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 56 insertions(+), 34 deletions(-) (limited to 'notes.c') diff --git a/notes.c b/notes.c index b576f7e624..08a369af82 100644 --- a/notes.c +++ b/notes.c @@ -50,9 +50,7 @@ struct leaf_node { #define SUBTREE_SHA1_PREFIXCMP(key_sha1, subtree_sha1) \ (memcmp(key_sha1, subtree_sha1, subtree_sha1[19])) -static struct int_node root_node; - -static int initialized; +struct notes_tree default_notes_tree; static void load_subtree(struct leaf_node *subtree, struct int_node *node, unsigned int n); @@ -287,8 +285,8 @@ static int note_tree_consolidate(struct int_node *tree, * - Replace the matching leaf_node with a NULL entry (and free the leaf_node). * - Consolidate int_nodes repeatedly, while walking up the tree towards root. */ -static void note_tree_remove(struct int_node *tree, unsigned char n, - struct leaf_node *entry) +static void note_tree_remove(struct notes_tree *t, struct int_node *tree, + unsigned char n, struct leaf_node *entry) { struct leaf_node *l; struct int_node *parent_stack[20]; @@ -310,7 +308,7 @@ static void note_tree_remove(struct int_node *tree, unsigned char n, if (!n) return; /* cannot consolidate top level */ /* first, build stack of ancestors between root and current node */ - parent_stack[0] = &root_node; + parent_stack[0] = t->root; for (i = 0; i < n; i++) { j = GET_NIBBLE(i, entry->key_sha1); parent_stack[i + 1] = CLR_PTR_TYPE(parent_stack[i]->a[j]); @@ -661,14 +659,15 @@ static int write_each_note(const unsigned char *object_sha1, return write_each_note_helper(d->root, note_path, mode, note_sha1); } -void init_notes(const char *notes_ref, int flags) +void init_notes(struct notes_tree *t, const char *notes_ref, int flags) { unsigned char sha1[20], object_sha1[20]; unsigned mode; struct leaf_node root_tree; - assert(!initialized); - initialized = 1; + if (!t) + t = &default_notes_tree; + assert(!t->initialized); if (!notes_ref) notes_ref = getenv(GIT_NOTES_REF_ENVIRONMENT); @@ -677,6 +676,10 @@ void init_notes(const char *notes_ref, int flags) if (!notes_ref) notes_ref = GIT_NOTES_DEFAULT_REF; + t->root = (struct int_node *) xcalloc(sizeof(struct int_node), 1); + t->ref = notes_ref ? xstrdup(notes_ref) : NULL; + t->initialized = 1; + if (flags & NOTES_INIT_EMPTY || !notes_ref || read_ref(notes_ref, object_sha1)) return; @@ -686,52 +689,65 @@ void init_notes(const char *notes_ref, int flags) hashclr(root_tree.key_sha1); hashcpy(root_tree.val_sha1, sha1); - load_subtree(&root_tree, &root_node, 0); + load_subtree(&root_tree, t->root, 0); } -void add_note(const unsigned char *object_sha1, const unsigned char *note_sha1) +void add_note(struct notes_tree *t, const unsigned char *object_sha1, + const unsigned char *note_sha1) { struct leaf_node *l; - assert(initialized); + if (!t) + t = &default_notes_tree; + assert(t->initialized); l = (struct leaf_node *) xmalloc(sizeof(struct leaf_node)); hashcpy(l->key_sha1, object_sha1); hashcpy(l->val_sha1, note_sha1); - note_tree_insert(&root_node, 0, l, PTR_TYPE_NOTE); + note_tree_insert(t->root, 0, l, PTR_TYPE_NOTE); } -void remove_note(const unsigned char *object_sha1) +void remove_note(struct notes_tree *t, const unsigned char *object_sha1) { struct leaf_node l; - assert(initialized); + if (!t) + t = &default_notes_tree; + assert(t->initialized); hashcpy(l.key_sha1, object_sha1); hashclr(l.val_sha1); - return note_tree_remove(&root_node, 0, &l); + return note_tree_remove(t, t->root, 0, &l); } -const unsigned char *get_note(const unsigned char *object_sha1) +const unsigned char *get_note(struct notes_tree *t, + const unsigned char *object_sha1) { struct leaf_node *found; - assert(initialized); - found = note_tree_find(&root_node, 0, object_sha1); + if (!t) + t = &default_notes_tree; + assert(t->initialized); + found = note_tree_find(t->root, 0, object_sha1); return found ? found->val_sha1 : NULL; } -int for_each_note(int flags, each_note_fn fn, void *cb_data) +int for_each_note(struct notes_tree *t, int flags, each_note_fn fn, + void *cb_data) { - assert(initialized); - return for_each_note_helper(&root_node, 0, 0, flags, fn, cb_data); + if (!t) + t = &default_notes_tree; + assert(t->initialized); + return for_each_note_helper(t->root, 0, 0, flags, fn, cb_data); } -int write_notes_tree(unsigned char *result) +int write_notes_tree(struct notes_tree *t, unsigned char *result) { struct tree_write_stack root; struct write_each_note_data cb_data; int ret; - assert(initialized); + if (!t) + t = &default_notes_tree; + assert(t->initialized); /* Prepare for traversal of current notes tree */ root.next = NULL; /* last forward entry in list is grounded */ @@ -740,7 +756,7 @@ int write_notes_tree(unsigned char *result) cb_data.root = &root; /* Write tree objects representing current notes tree */ - ret = for_each_note(FOR_EACH_NOTE_DONT_UNPACK_SUBTREES | + ret = for_each_note(t, FOR_EACH_NOTE_DONT_UNPACK_SUBTREES | FOR_EACH_NOTE_YIELD_SUBTREES, write_each_note, &cb_data) || tree_write_stack_finish_subtree(&root) || @@ -749,15 +765,19 @@ int write_notes_tree(unsigned char *result) return ret; } -void free_notes(void) +void free_notes(struct notes_tree *t) { - note_tree_free(&root_node); - memset(&root_node, 0, sizeof(struct int_node)); - initialized = 0; + if (!t) + t = &default_notes_tree; + if (t->root) + note_tree_free(t->root); + free(t->root); + free(t->ref); + memset(t, 0, sizeof(struct notes_tree)); } -void format_note(const unsigned char *object_sha1, struct strbuf *sb, - const char *output_encoding, int flags) +void format_note(struct notes_tree *t, const unsigned char *object_sha1, + struct strbuf *sb, const char *output_encoding, int flags) { static const char utf8[] = "utf-8"; const unsigned char *sha1; @@ -765,10 +785,12 @@ void format_note(const unsigned char *object_sha1, struct strbuf *sb, unsigned long linelen, msglen; enum object_type type; - if (!initialized) - init_notes(NULL, 0); + if (!t) + t = &default_notes_tree; + if (!t->initialized) + init_notes(t, NULL, 0); - sha1 = get_note(object_sha1); + sha1 = get_note(t, object_sha1); if (!sha1) return; -- cgit v1.2.3