git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCHv11 19/20] Notes API: gc_notes(): Prune notes that belong to non-existing objects

From
Johan Herland <johan@herland.net>
Date
Jan 17, 2010, 21:04 UTC
Message-ID
<1263762277-31419-20-git-send-email-johan@herland.net>
In-Reply-To
<1263762277-31419-1-git-send-email-johan@herland.net>

When an object is garbage collected by Git, any notes that annotate that object is not automatically garbage-collected, since all notes are 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 GC.

gc_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 gc_notes() is not persistent unless a subsequent call to write_notes_tree() is made.

Signed-off-by: Johan Herland <johan@herland.net>
---
 notes.c |   39 +++++++++++++++++++++++++++++++++++++++
 notes.h |   12 ++++++++++++
 2 files changed, 51 insertions(+), 0 deletions(-)
diff --git a/notes.c b/notes.c
index 4f260a5..880a306 100644
--- a/notes.c
+++ b/notes.c
@@ -747,6 +747,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 gc_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 => GC 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)
 {
@@ -920,6 +943,22 @@ int write_notes_tree(struct notes_tree *t, unsigned char *result)
 	return ret;
 }
 
+void gc_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, gc_notes_helper, &l);
+
+	while (l) {
+		remove_note(t, l->sha1);
+		l = l->next;
+	}
+}
+
 void free_notes(struct notes_tree *t)
 {
 	if (!t)
diff --git a/notes.h b/notes.h
index f25643e..71d3fab 100644
--- a/notes.h
+++ b/notes.h
@@ -158,6 +158,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);
 
 /*
+ * 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 gc_notes() to the given notes_tree structure
+ * are not persistent until a subsequent call to write_notes_tree() returns
+ * zero.
+ */
+void gc_notes(struct notes_tree *t);
+
+/*
  * Free (and de-initialize) the given notes_tree structure
  *
  * IMPORTANT: Changes made to the given notes_tree since the last, successful
-- 
1.6.6.rc1.321.g0496e
Previous: Johan HerlandNext: Johan Herland
Message 22 of 26 in “[PATCHv11 00/20] git notes”
  1. Johan HerlandJan 17, 2010
  2. 01/20 Minor non-functional fixes to notes.cJohan Herland, Jan 17, 2010
  3. 02/20 Notes API: get_commit_notes() -> format_note() + remove the commit restrictionJohan Herland, Jan 17, 2010
  4. 03/20 Add tests for checking correct handling of $GIT_NOTES_REF and core.notesRefJohan Herland, Jan 17, 2010
  5. 04/20 Notes API: init_notes(): Initialize the notes tree from the given notes refJohan Herland, Jan 17, 2010
  6. 05/20 Notes API: add_note(): Add note objects to the internal notes tree structureJohan Herland, Jan 17, 2010
  7. 06/20 Notes API: remove_note(): Remove note objects from the notes tree structureJohan Herland, Jan 17, 2010
  8. 07/20 Notes API: get_note(): Return the note annotating the given objectJohan Herland, Jan 17, 2010
  9. 08/20 Notes API: for_each_note(): Traverse the entire notes tree with a callbackJohan Herland, Jan 17, 2010
  10. 09/20 Notes API: write_notes_tree(): Store the notes tree in the databaseJohan Herland, Jan 17, 2010
  11. 10/20 Notes API: Allow multiple concurrent notes trees with new struct notes_treeJohan Herland, Jan 17, 2010
  12. 11/20 Refactor notes concatenation into a flexible interface for combining notesJohan Herland, Jan 17, 2010
  13. 12/20 Builtin-ify git-notesJohan Herland, Jan 17, 2010
  14. Stephen BoydJan 21, 2010
  15. Johan HerlandJan 26, 2010
  16. 13/20 t3301: Verify successful annotation of non-commitsJohan Herland, Jan 17, 2010
  17. 14/20 t3305: Verify that adding many notes with git-notes triggers increased fanoutJohan Herland, Jan 17, 2010
  18. 15/20 Teach notes code to properly preserve non-notes in the notes treeJohan Herland, Jan 17, 2010
  19. 16/20 Teach builtin-notes to remove empty notesJohan Herland, Jan 17, 2010
  20. 17/20 builtin-notes: Teach -d option for deleting existing notesJohan Herland, Jan 17, 2010
  21. 18/20 t3305: Verify that removing notes triggers automatic fanout consolidationJohan Herland, Jan 17, 2010
  22. 19/20 Notes API: gc_notes(): Prune notes that belong to non-existing objectsJohan Herland, Jan 17, 2010
  23. 20/20 builtin-gc: Teach the new --notes option to garbage-collect notesJohan Herland, Jan 17, 2010
  24. Stephen BoydJan 21, 2010
  25. Junio C HamanoJan 21, 2010
  26. Johan HerlandJan 27, 2010

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.