builtin-notes: Add "remove" subcommand for removing existing notes

Using "git notes remove" is equivalent to specifying an empty note message.

The patch includes tests verifying correct behaviour of the new subcommand.

Signed-off-by: Johan Herland <johan@herland.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
maint
Johan Herland 2010-02-13 22:28:25 +01:00 committed by Junio C Hamano
parent a0b4dfa9b3
commit 92b3385fca
3 changed files with 72 additions and 33 deletions

View File

@ -8,14 +8,14 @@ git-notes - Add/inspect commit notes
SYNOPSIS SYNOPSIS
-------- --------
[verse] [verse]
'git notes' (edit [-F <file> | -m <msg>] | show) [commit] 'git notes' (edit [-F <file> | -m <msg>] | show | remove) [commit]


DESCRIPTION DESCRIPTION
----------- -----------
This command allows you to add notes to commit messages, without This command allows you to add/remove notes to/from commit messages,
changing the commit. To discern these notes from the message stored without changing the commit. To discern these notes from the message
in the commit object, the notes are indented like the message, after stored in the commit object, the notes are indented like the message,
an unindented line saying "Notes:". after an unindented line saying "Notes:".


To disable commit notes, you have to set the config variable To disable commit notes, you have to set the config variable
core.notesRef to the empty string. Alternatively, you can set it core.notesRef to the empty string. Alternatively, you can set it
@ -32,6 +32,11 @@ edit::
show:: show::
Show the notes for a given commit (defaults to HEAD). Show the notes for a given commit (defaults to HEAD).


remove::
Remove the notes for a given commit (defaults to HEAD).
This is equivalent to specifying an empty note message to
the `edit` subcommand.



OPTIONS OPTIONS
------- -------

View File

@ -20,6 +20,7 @@
static const char * const git_notes_usage[] = { static const char * const git_notes_usage[] = {
"git notes edit [-m <msg> | -F <file>] [<object>]", "git notes edit [-m <msg> | -F <file>] [<object>]",
"git notes show [<object>]", "git notes show [<object>]",
"git notes remove [<object>]",
NULL NULL
}; };


@ -197,9 +198,10 @@ int cmd_notes(int argc, const char **argv, const char *prefix)
struct notes_tree *t; struct notes_tree *t;
unsigned char object[20], new_note[20]; unsigned char object[20], new_note[20];
const unsigned char *note; const unsigned char *note;
const char *object_ref, *logmsg; const char *object_ref;
char logmsg[100];


int edit = 0, show = 0; int edit = 0, show = 0, remove = 0;
const char *msgfile = NULL; const char *msgfile = NULL;
struct msg_arg msg = { 0, STRBUF_INIT }; struct msg_arg msg = { 0, STRBUF_INIT };
struct option options[] = { struct option options[] = {
@ -218,10 +220,22 @@ int cmd_notes(int argc, const char **argv, const char *prefix)
edit = 1; edit = 1;
else if (argc && !strcmp(argv[0], "show")) else if (argc && !strcmp(argv[0], "show"))
show = 1; show = 1;
else if (argc && !strcmp(argv[0], "remove"))
remove = 1;


if (edit + show != 1) if (edit + show + remove != 1)
usage_with_options(git_notes_usage, options); usage_with_options(git_notes_usage, options);


if ((msg.given || msgfile) && !edit) {
error("cannot use -m/-F options with %s subcommand.", argv[0]);
usage_with_options(git_notes_usage, options);
}

if (msg.given && msgfile) {
error("mixing -m and -F options is not allowed.");
usage_with_options(git_notes_usage, options);
}

object_ref = argc == 2 ? argv[1] : "HEAD"; object_ref = argc == 2 ? argv[1] : "HEAD";
if (argc > 2) { if (argc > 2) {
error("too many parameters"); error("too many parameters");
@ -236,7 +250,7 @@ int cmd_notes(int argc, const char **argv, const char *prefix)


if (prefixcmp(t->ref, "refs/notes/")) if (prefixcmp(t->ref, "refs/notes/"))
die("Refusing to %s notes in %s (outside of refs/notes/)", die("Refusing to %s notes in %s (outside of refs/notes/)",
edit ? "edit" : "show", t->ref); argv[0], t->ref);


note = get_note(t, object); note = get_note(t, object);


@ -250,35 +264,28 @@ int cmd_notes(int argc, const char **argv, const char *prefix)
return execv_git_cmd(show_args); return execv_git_cmd(show_args);
} }


/* edit command */ /* edit/remove command */


if (msg.given || msgfile) { if (remove)
if (msg.given && msgfile) { strbuf_reset(&buf);
error("mixing -m and -F options is not allowed."); else if (msg.given)
usage_with_options(git_notes_usage, options);
}
if (msg.given)
strbuf_addbuf(&buf, &(msg.buf)); strbuf_addbuf(&buf, &(msg.buf));
else { else if (msgfile) {
if (!strcmp(msgfile, "-")) { if (!strcmp(msgfile, "-")) {
if (strbuf_read(&buf, 0, 1024) < 0) if (strbuf_read(&buf, 0, 1024) < 0)
die_errno("cannot read '%s'", msgfile); die_errno("cannot read '%s'", msgfile);
} else { } else if (strbuf_read_file(&buf, msgfile, 1024) < 0)
if (strbuf_read_file(&buf, msgfile, 1024) < 0) die_errno("could not open or read '%s'", msgfile);
die_errno("could not open or read '%s'",
msgfile);
}
}
} }


create_note(object, &buf, msg.given || msgfile, note, new_note); create_note(object, &buf, msg.given || msgfile || remove, note,
if (is_null_sha1(new_note)) { new_note);
if (is_null_sha1(new_note))
remove_note(t, object); remove_note(t, object);
logmsg = "Note removed by 'git notes edit'"; else
} else {
add_note(t, object, new_note, combine_notes_overwrite); add_note(t, object, new_note, combine_notes_overwrite);
logmsg = "Note added by 'git notes edit'"; snprintf(logmsg, sizeof(logmsg), "Note %s by 'git notes %s'",
} is_null_sha1(new_note) ? "removed" : "added", argv[0]);
commit_notes(t, logmsg); commit_notes(t, logmsg);


free_notes(t); free_notes(t);

View File

@ -265,6 +265,33 @@ test_expect_success 'verify non-creation of note with -m ""' '
! git notes show ! git notes show
' '


test_expect_success 'remove note with "git notes remove" (setup)' '
git notes remove HEAD^
'

cat > expect-rm-remove << EOF
commit bd1753200303d0a0344be813e504253b3d98e74d
Author: A U Thor <author@example.com>
Date: Thu Apr 7 15:17:13 2005 -0700

5th

commit 15023535574ded8b1a89052b32673f84cf9582b8
Author: A U Thor <author@example.com>
Date: Thu Apr 7 15:16:13 2005 -0700

4th
EOF

printf "\n" >> expect-rm-remove
cat expect-multiline >> expect-rm-remove

test_expect_success 'verify note removal with "git notes remove"' '
git log -4 > output &&
test_cmp expect-rm-remove output &&
! git notes show HEAD^
'

test_expect_success 'create other note on a different notes ref (setup)' ' test_expect_success 'create other note on a different notes ref (setup)' '
: > a6 && : > a6 &&
git add a6 && git add a6 &&