notes remove: --stdin reads from the standard input

Teach the command to read object names to remove from the standard input, in addition to the object names given from the command line. Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed May 18, 2011 at 16:44 UTC 46538012d943156ead4024fb510a1ce5d4ff443a
3 files changed +56 -5
Documentation/git-notes.txt
+6 -1
@@ -17,7 +17,7 @@ SYNOPSIS
17 'git notes' merge [-v | -q] [-s <strategy> ] <notes_ref>
18 'git notes' merge --commit [-v | -q]
19 'git notes' merge --abort [-v | -q]
20 -'git notes' remove [--ignore-missing] [<object>...]
20 +'git notes' remove [--ignore-missing] [--stdin] [<object>...]
21 'git notes' prune [-n | -v]
22 'git notes' get-ref
23
@@ -159,6 +159,11 @@ OPTIONS
159 Do not consider it an error to request removing notes from an
160 object that does not have notes attached to it.
161
162 +--stdin::
163 + Also read the object names to remove notes from from the standard
164 + input (there is no reason you cannot combine this with object
165 + names from the command line).
166 +
167 -n::
168 --dry-run::
169 Do not remove anything; just report the object names whose notes
builtin/notes.c
+15 -4
@@ -953,7 +953,7 @@ static int merge(int argc, const char **argv, const char *prefix)
953 return result < 0; /* return non-zero on conflicts */
954 }
955
956 -#define MISSING_OK 1
956 +#define IGNORE_MISSING 1
957
958 static int remove_one_note(struct notes_tree *t, const char *name, unsigned flag)
959 {
@@ -966,16 +966,19 @@ static int remove_one_note(struct notes_tree *t, const char *name, unsigned flag
966 fprintf(stderr, _("Object %s has no note\n"), name);
967 else
968 fprintf(stderr, _("Removing note for object %s\n"), name);
969 - return (flag & MISSING_OK) ? 0 : status;
969 + return (flag & IGNORE_MISSING) ? 0 : status;
970 }
971
972 static int remove_cmd(int argc, const char **argv, const char *prefix)
973 {
974 unsigned flag = 0;
975 + int from_stdin = 0;
976 struct option options[] = {
977 OPT_BIT(0, "ignore-missing", &flag,
978 "attempt to remove non-existent note is not an error",
978 - MISSING_OK),
979 + IGNORE_MISSING),
980 + OPT_BOOLEAN(0, "stdin", &from_stdin,
981 + "read object names from the standard input"),
982 OPT_END()
983 };
984 struct notes_tree *t;
@@ -986,7 +989,7 @@ static int remove_cmd(int argc, const char **argv, const char *prefix)
989
990 t = init_notes_check("remove");
991
989 - if (!argc) {
992 + if (!argc && !from_stdin) {
993 retval = remove_one_note(t, "HEAD", flag);
994 } else {
995 while (*argv) {
@@ -994,6 +997,14 @@ static int remove_cmd(int argc, const char **argv, const char *prefix)
997 argv++;
998 }
999 }
1000 + if (from_stdin) {
1001 + struct strbuf sb = STRBUF_INIT;
1002 + while (strbuf_getwholeline(&sb, stdin, '\n') != EOF) {
1003 + strbuf_rtrim(&sb);
1004 + retval |= remove_one_note(t, sb.buf, flag);
1005 + }
1006 + strbuf_release(&sb);
1007 + }
1008 if (!retval)
1009 commit_notes(t, "Notes removed by 'git notes remove'");
1010 free_notes(t);
t/t3301-notes.sh
+35
@@ -475,6 +475,41 @@ test_expect_success 'removing with --ignore-missing but bogus ref' '
475 test "$before" = "$after"
476 '
477
478 +test_expect_success 'remove reads from --stdin' '
479 + before=$(git rev-parse --verify refs/notes/commits) &&
480 + test_when_finished "git update-ref refs/notes/commits $before" &&
481 +
482 + # We have only two -- add another and make sure it stays
483 + git notes add -m "extra" &&
484 + git notes list HEAD >after-removal-expect &&
485 + git rev-parse HEAD^^ HEAD^^^ >input &&
486 + git notes remove --stdin <input &&
487 + git notes list | sed -e "s/ .*//" >actual &&
488 + test_cmp after-removal-expect actual
489 +'
490 +
491 +test_expect_success 'remove --stdin is also atomic' '
492 + before=$(git rev-parse --verify refs/notes/commits) &&
493 + test_when_finished "git update-ref refs/notes/commits $before" &&
494 + git rev-parse HEAD^^ HEAD^^^ HEAD^ >input &&
495 + test_must_fail git notes remove --stdin <input &&
496 + after=$(git rev-parse --verify refs/notes/commits) &&
497 + test "$before" = "$after"
498 +'
499 +
500 +test_expect_success 'removing with --stdin --ignore-missing' '
501 + before=$(git rev-parse --verify refs/notes/commits) &&
502 + test_when_finished "git update-ref refs/notes/commits $before" &&
503 +
504 + # We have only two -- add another and make sure it stays
505 + git notes add -m "extra" &&
506 + git notes list HEAD >after-removal-expect &&
507 + git rev-parse HEAD^^ HEAD^^^ HEAD^ >input &&
508 + git notes remove --ignore-missing --stdin <input &&
509 + git notes list | sed -e "s/ .*//" >actual &&
510 + test_cmp after-removal-expect actual
511 +'
512 +
513 test_expect_success 'list notes with "git notes list"' '
514 git notes list > output &&
515 test_cmp expect output