@matheusbsbs / matheus-bagliano / commits / e2656c82fd
Fork 0

notes.h/c: Allow combine_notes functions to remove notes

Allow combine_notes functions to request that a note be removed, by setting the resulting note SHA1 to null_sha1 (0000000...). For consistency, also teach note_tree_insert() to skip insertion of an empty note (a note with entry->val_sha1 equal to null_sha1) when there is no note to combine it with. In general, an empty note (null_sha1) is treated identically to no note at all, but when adding an empty note where there already exists a non-empty note, we allow the combine_notes function to potentially record a new/changed note. Document this behaviour, and clearly specify how combine_notes functions are expected to handle null_sha1 in input. Before this patch, storing null_sha1s in the notes tree were silently allowed, causing an invalid notes tree (referring to blobs with null_sha1) to be produced by write_notes_tree(). Signed-off-by: Johan Herland <johan@herland.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Johan Herland committed Nov 9, 2010 at 22:49 UTC e2656c82fd836a3d410230c98f6a725368f15642
2 files changed +26 -2
notes.c
+11 -1
@@ -248,7 +248,10 @@ static void note_tree_insert(struct notes_tree *t, struct int_node *tree,
248 switch (GET_PTR_TYPE(*p)) {
249 case PTR_TYPE_NULL:
250 assert(!*p);
251 - *p = SET_PTR_TYPE(entry, type);
251 + if (is_null_sha1(entry->val_sha1))
252 + free(entry);
253 + else
254 + *p = SET_PTR_TYPE(entry, type);
255 return;
256 case PTR_TYPE_NOTE:
257 switch (type) {
@@ -264,6 +267,9 @@ static void note_tree_insert(struct notes_tree *t, struct int_node *tree,
267 sha1_to_hex(l->val_sha1),
268 sha1_to_hex(entry->val_sha1),
269 sha1_to_hex(l->key_sha1));
270 +
271 + if (is_null_sha1(l->val_sha1))
272 + note_tree_remove(t, tree, n, entry);
273 free(entry);
274 return;
275 }
@@ -295,6 +301,10 @@ static void note_tree_insert(struct notes_tree *t, struct int_node *tree,
301 /* non-matching leaf_node */
302 assert(GET_PTR_TYPE(*p) == PTR_TYPE_NOTE ||
303 GET_PTR_TYPE(*p) == PTR_TYPE_SUBTREE);
304 + if (is_null_sha1(entry->val_sha1)) { /* skip insertion of empty note */
305 + free(entry);
306 + return;
307 + }
308 new_node = (struct int_node *) xcalloc(sizeof(struct int_node), 1);
309 note_tree_insert(t, new_node, n + 1, l, GET_PTR_TYPE(*p),
310 combine_notes);
notes.h
+15 -1
@@ -12,7 +12,10 @@
12 * resulting SHA1 into the first SHA1 argument (cur_sha1). A non-zero return
13 * value indicates failure.
14 *
15 - * The two given SHA1s must both be non-NULL and different from each other.
15 + * The two given SHA1s shall both be non-NULL and different from each other.
16 + * Either of them (but not both) may be == null_sha1, which indicates an
17 + * empty/non-existent note. If the resulting SHA1 (cur_sha1) is == null_sha1,
18 + * the note will be removed from the notes tree.
19 *
20 * The default combine_notes function (you get this when passing NULL) is
21 * combine_notes_concatenate(), which appends the contents of the new note to
@@ -90,6 +93,17 @@ void init_notes(struct notes_tree *t, const char *notes_ref,
93 /*
94 * Add the given note object to the given notes_tree structure
95 *
96 + * If there already exists a note for the given object_sha1, the given
97 + * combine_notes function is invoked to break the tie. If not given (i.e.
98 + * combine_notes == NULL), the default combine_notes function for the given
99 + * notes_tree is used.
100 + *
101 + * Passing note_sha1 == null_sha1 indicates the addition of an
102 + * empty/non-existent note. This is a (potentially expensive) no-op unless
103 + * there already exists a note for the given object_sha1, AND combining that
104 + * note with the empty note (using the given combine_notes function) results
105 + * in a new/changed note.
106 + *
107 * IMPORTANT: The changes made by add_note() to the given notes_tree structure
108 * are not persistent until a subsequent call to write_notes_tree() returns
109 * zero.