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 <johan@herland.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:

committed by
Junio C Hamano

parent
b0032d1e06
commit
00fbe63627
39
notes.c
39
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);
|
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,
|
int combine_notes_concatenate(unsigned char *cur_sha1,
|
||||||
const unsigned char *new_sha1)
|
const unsigned char *new_sha1)
|
||||||
{
|
{
|
||||||
@ -922,6 +945,22 @@ int write_notes_tree(struct notes_tree *t, unsigned char *result)
|
|||||||
return ret;
|
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)
|
void free_notes(struct notes_tree *t)
|
||||||
{
|
{
|
||||||
if (!t)
|
if (!t)
|
||||||
|
12
notes.h
12
notes.h
@ -161,6 +161,18 @@ int for_each_note(struct notes_tree *t, int flags, each_note_fn fn,
|
|||||||
*/
|
*/
|
||||||
int write_notes_tree(struct notes_tree *t, unsigned char *result);
|
int write_notes_tree(struct notes_tree *t, unsigned char *result);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove all notes annotating non-existing objects from the given notes tree
|
||||||
|
*
|
||||||
|
* All notes in the given notes_tree that are associated with objects that no
|
||||||
|
* longer exist in the database, are removed from the notes tree.
|
||||||
|
*
|
||||||
|
* IMPORTANT: The changes made by prune_notes() to the given notes_tree
|
||||||
|
* structure are not persistent until a subsequent call to write_notes_tree()
|
||||||
|
* returns zero.
|
||||||
|
*/
|
||||||
|
void prune_notes(struct notes_tree *t);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Free (and de-initialize) the given notes_tree structure
|
* Free (and de-initialize) the given notes_tree structure
|
||||||
*
|
*
|
||||||
|
Reference in New Issue
Block a user