builtin-notes: Add "prune" subcommand for removing notes for missing objects
"git notes prune" will remove all notes that annotate unreachable/non- existing objects. The patch includes tests verifying correct behaviour of the new subcommand. Suggested-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Johan Herland <johan@herland.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Johan Herland committed
Feb 13, 2010 at 22:28 UTC
d6576e1fe3ee4bd7bd2cf01d17499c94da24876f
3 files changed
+115
-11
Documentation/git-notes.txt
+3
-1
@@ -8,7 +8,7 @@ git-notes - Add/inspect commit notes
8
SYNOPSIS
9
--------
10
[verse]
11
-'git notes' (edit [-F <file> | -m <msg>] | show | remove) [commit]
11
+'git notes' (edit [-F <file> | -m <msg>] | show | remove | prune) [commit]
12
13
DESCRIPTION
14
-----------
@@ -37,6 +37,8 @@ remove::
37
This is equivalent to specifying an empty note message to
38
the `edit` subcommand.
39
40
+prune::
41
+ Remove all notes for non-existing/unreachable objects.
42
43
OPTIONS
44
-------
builtin-notes.c
+18
-10
@@ -21,6 +21,7 @@ static const char * const git_notes_usage[] = {
21
"git notes edit [-m <msg> | -F <file>] [<object>]",
22
"git notes show [<object>]",
23
"git notes remove [<object>]",
24
+ "git notes prune",
25
NULL
26
};
27
@@ -201,7 +202,7 @@ int cmd_notes(int argc, const char **argv, const char *prefix)
202
const char *object_ref;
203
char logmsg[100];
204
204
- int edit = 0, show = 0, remove = 0;
205
+ int edit = 0, show = 0, remove = 0, prune = 0;
206
const char *msgfile = NULL;
207
struct msg_arg msg = { 0, STRBUF_INIT };
208
struct option options[] = {
@@ -222,8 +223,10 @@ int cmd_notes(int argc, const char **argv, const char *prefix)
223
show = 1;
224
else if (argc && !strcmp(argv[0], "remove"))
225
remove = 1;
226
+ else if (argc && !strcmp(argv[0], "prune"))
227
+ prune = 1;
228
226
- if (edit + show + remove != 1)
229
+ if (edit + show + remove + prune != 1)
230
usage_with_options(git_notes_usage, options);
231
232
if ((msg.given || msgfile) && !edit) {
@@ -237,7 +240,7 @@ int cmd_notes(int argc, const char **argv, const char *prefix)
240
}
241
242
object_ref = argc == 2 ? argv[1] : "HEAD";
240
- if (argc > 2) {
243
+ if (argc > 2 || (prune && argc > 1)) {
244
error("too many parameters");
245
usage_with_options(git_notes_usage, options);
246
}
@@ -264,7 +267,7 @@ int cmd_notes(int argc, const char **argv, const char *prefix)
267
return execv_git_cmd(show_args);
268
}
269
267
- /* edit/remove command */
270
+ /* edit/remove/prune command */
271
272
if (remove)
273
strbuf_reset(&buf);
@@ -278,12 +281,17 @@ int cmd_notes(int argc, const char **argv, const char *prefix)
281
die_errno("could not open or read '%s'", msgfile);
282
}
283
281
- create_note(object, &buf, msg.given || msgfile || remove, note,
282
- new_note);
283
- if (is_null_sha1(new_note))
284
- remove_note(t, object);
285
- else
286
- add_note(t, object, new_note, combine_notes_overwrite);
284
+ if (prune) {
285
+ hashclr(new_note);
286
+ prune_notes(t);
287
+ } else {
288
+ create_note(object, &buf, msg.given || msgfile || remove, note,
289
+ new_note);
290
+ if (is_null_sha1(new_note))
291
+ remove_note(t, object);
292
+ else
293
+ add_note(t, object, new_note, combine_notes_overwrite);
294
+ }
295
snprintf(logmsg, sizeof(logmsg), "Note %s by 'git notes %s'",
296
is_null_sha1(new_note) ? "removed" : "added", argv[0]);
297
commit_notes(t, logmsg);
t/t3306-notes-prune.sh
new
+94
@@ -0,0 +1,94 @@
1
+#!/bin/sh
2
+
3
+test_description='Test git notes prune'
4
+
5
+. ./test-lib.sh
6
+
7
+test_expect_success 'setup: create a few commits with notes' '
8
+
9
+ : > file1 &&
10
+ git add file1 &&
11
+ test_tick &&
12
+ git commit -m 1st &&
13
+ git notes edit -m "Note #1" &&
14
+ : > file2 &&
15
+ git add file2 &&
16
+ test_tick &&
17
+ git commit -m 2nd &&
18
+ git notes edit -m "Note #2" &&
19
+ : > file3 &&
20
+ git add file3 &&
21
+ test_tick &&
22
+ git commit -m 3rd &&
23
+ git notes edit -m "Note #3"
24
+'
25
+
26
+cat > expect <<END_OF_LOG
27
+commit 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29
28
+Author: A U Thor <author@example.com>
29
+Date: Thu Apr 7 15:15:13 2005 -0700
30
+
31
+ 3rd
32
+
33
+Notes:
34
+ Note #3
35
+
36
+commit 08341ad9e94faa089d60fd3f523affb25c6da189
37
+Author: A U Thor <author@example.com>
38
+Date: Thu Apr 7 15:14:13 2005 -0700
39
+
40
+ 2nd
41
+
42
+Notes:
43
+ Note #2
44
+
45
+commit ab5f302035f2e7aaf04265f08b42034c23256e1f
46
+Author: A U Thor <author@example.com>
47
+Date: Thu Apr 7 15:13:13 2005 -0700
48
+
49
+ 1st
50
+
51
+Notes:
52
+ Note #1
53
+END_OF_LOG
54
+
55
+test_expect_success 'verify commits and notes' '
56
+
57
+ git log > actual &&
58
+ test_cmp expect actual
59
+'
60
+
61
+test_expect_success 'remove some commits' '
62
+
63
+ git reset --hard HEAD~2 &&
64
+ git reflog expire --expire=now HEAD &&
65
+ git gc --prune=now
66
+'
67
+
68
+test_expect_success 'verify that commits are gone' '
69
+
70
+ ! git cat-file -p 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29 &&
71
+ ! git cat-file -p 08341ad9e94faa089d60fd3f523affb25c6da189 &&
72
+ git cat-file -p ab5f302035f2e7aaf04265f08b42034c23256e1f
73
+'
74
+
75
+test_expect_success 'verify that notes are still present' '
76
+
77
+ git notes show 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29 &&
78
+ git notes show 08341ad9e94faa089d60fd3f523affb25c6da189 &&
79
+ git notes show ab5f302035f2e7aaf04265f08b42034c23256e1f
80
+'
81
+
82
+test_expect_success 'prune notes' '
83
+
84
+ git notes prune
85
+'
86
+
87
+test_expect_success 'verify that notes are gone' '
88
+
89
+ ! git notes show 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29 &&
90
+ ! git notes show 08341ad9e94faa089d60fd3f523affb25c6da189 &&
91
+ git notes show ab5f302035f2e7aaf04265f08b42034c23256e1f
92
+'
93
+
94
+test_done