From 00fbe63627b72c807e558643f0634e435137122f Mon Sep 17 00:00:00 2001 From: Johan Herland Date: Sat, 13 Feb 2010 22:28:27 +0100 Subject: Notes API: prune_notes(): Prune notes that belong to non-existing objects When an object is made unreachable by Git, any notes that annotate that object are not automagically made unreachable, since all notes are always trivially reachable from a notes ref. In order to remove notes for non-existing objects, we therefore need to add functionality for traversing the notes tree and explicitly removing references to notes that annotate non-reachable objects. Thus the notes objects themselves also become unreachable, and are removed by a later garbage collect. prune_notes() performs this traversal (by using for_each_note() internally), and removes the notes in question from the notes tree. Note that the effect of prune_notes() is not persistent unless a subsequent call to write_notes_tree() is made. Signed-off-by: Johan Herland Signed-off-by: Junio C Hamano --- notes.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'notes.c') diff --git a/notes.c b/notes.c index d432517587..3ba3e6de17 100644 --- a/notes.c +++ b/notes.c @@ -749,6 +749,29 @@ static int write_each_note(const unsigned char *object_sha1, write_each_note_helper(d->root, note_path, mode, note_sha1); } +struct note_delete_list { + struct note_delete_list *next; + const unsigned char *sha1; +}; + +static int prune_notes_helper(const unsigned char *object_sha1, + const unsigned char *note_sha1, char *note_path, + void *cb_data) +{ + struct note_delete_list **l = (struct note_delete_list **) cb_data; + struct note_delete_list *n; + + if (has_sha1_file(object_sha1)) + return 0; /* nothing to do for this note */ + + /* failed to find object => prune this note */ + n = (struct note_delete_list *) xmalloc(sizeof(*n)); + n->next = *l; + n->sha1 = object_sha1; + *l = n; + return 0; +} + int combine_notes_concatenate(unsigned char *cur_sha1, const unsigned char *new_sha1) { @@ -922,6 +945,22 @@ int write_notes_tree(struct notes_tree *t, unsigned char *result) return ret; } +void prune_notes(struct notes_tree *t) +{ + struct note_delete_list *l = NULL; + + if (!t) + t = &default_notes_tree; + assert(t->initialized); + + for_each_note(t, 0, prune_notes_helper, &l); + + while (l) { + remove_note(t, l->sha1); + l = l->next; + } +} + void free_notes(struct notes_tree *t) { if (!t) -- cgit v1.2.1