OSDN Git Service

notes remove: --stdin reads from the standard input
authorJunio C Hamano <gitster@pobox.com>
Wed, 18 May 2011 23:44:30 +0000 (16:44 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 19 May 2011 17:54:16 +0000 (10:54 -0700)
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>
Documentation/git-notes.txt
builtin/notes.c
t/t3301-notes.sh

index 8bbffdf..6a187f2 100644 (file)
@@ -17,7 +17,7 @@ SYNOPSIS
 'git notes' merge [-v | -q] [-s <strategy> ] <notes_ref>
 'git notes' merge --commit [-v | -q]
 'git notes' merge --abort [-v | -q]
-'git notes' remove [--ignore-missing] [<object>...]
+'git notes' remove [--ignore-missing] [--stdin] [<object>...]
 'git notes' prune [-n | -v]
 'git notes' get-ref
 
@@ -159,6 +159,11 @@ OPTIONS
        Do not consider it an error to request removing notes from an
        object that does not have notes attached to it.
 
+--stdin::
+       Also read the object names to remove notes from from the standard
+       input (there is no reason you cannot combine this with object
+       names from the command line).
+
 -n::
 --dry-run::
        Do not remove anything; just report the object names whose notes
index 541f776..f8e437d 100644 (file)
@@ -953,7 +953,7 @@ static int merge(int argc, const char **argv, const char *prefix)
        return result < 0; /* return non-zero on conflicts */
 }
 
-#define MISSING_OK 1
+#define IGNORE_MISSING 1
 
 static int remove_one_note(struct notes_tree *t, const char *name, unsigned flag)
 {
@@ -966,16 +966,19 @@ static int remove_one_note(struct notes_tree *t, const char *name, unsigned flag
                fprintf(stderr, _("Object %s has no note\n"), name);
        else
                fprintf(stderr, _("Removing note for object %s\n"), name);
-       return (flag & MISSING_OK) ? 0 : status;
+       return (flag & IGNORE_MISSING) ? 0 : status;
 }
 
 static int remove_cmd(int argc, const char **argv, const char *prefix)
 {
        unsigned flag = 0;
+       int from_stdin = 0;
        struct option options[] = {
                OPT_BIT(0, "ignore-missing", &flag,
                        "attempt to remove non-existent note is not an error",
-                       MISSING_OK),
+                       IGNORE_MISSING),
+               OPT_BOOLEAN(0, "stdin", &from_stdin,
+                           "read object names from the standard input"),
                OPT_END()
        };
        struct notes_tree *t;
@@ -986,7 +989,7 @@ static int remove_cmd(int argc, const char **argv, const char *prefix)
 
        t = init_notes_check("remove");
 
-       if (!argc) {
+       if (!argc && !from_stdin) {
                retval = remove_one_note(t, "HEAD", flag);
        } else {
                while (*argv) {
@@ -994,6 +997,14 @@ static int remove_cmd(int argc, const char **argv, const char *prefix)
                        argv++;
                }
        }
+       if (from_stdin) {
+               struct strbuf sb = STRBUF_INIT;
+               while (strbuf_getwholeline(&sb, stdin, '\n') != EOF) {
+                       strbuf_rtrim(&sb);
+                       retval |= remove_one_note(t, sb.buf, flag);
+               }
+               strbuf_release(&sb);
+       }
        if (!retval)
                commit_notes(t, "Notes removed by 'git notes remove'");
        free_notes(t);
index e820a6b..16de05a 100755 (executable)
@@ -475,6 +475,41 @@ test_expect_success 'removing with --ignore-missing but bogus ref' '
        test "$before" = "$after"
 '
 
+test_expect_success 'remove reads from --stdin' '
+       before=$(git rev-parse --verify refs/notes/commits) &&
+       test_when_finished "git update-ref refs/notes/commits $before" &&
+
+       # We have only two -- add another and make sure it stays
+       git notes add -m "extra" &&
+       git notes list HEAD >after-removal-expect &&
+       git rev-parse HEAD^^ HEAD^^^ >input &&
+       git notes remove --stdin <input &&
+       git notes list | sed -e "s/ .*//" >actual &&
+       test_cmp after-removal-expect actual
+'
+
+test_expect_success 'remove --stdin is also atomic' '
+       before=$(git rev-parse --verify refs/notes/commits) &&
+       test_when_finished "git update-ref refs/notes/commits $before" &&
+       git rev-parse HEAD^^ HEAD^^^ HEAD^ >input &&
+       test_must_fail git notes remove --stdin <input &&
+       after=$(git rev-parse --verify refs/notes/commits) &&
+       test "$before" = "$after"
+'
+
+test_expect_success 'removing with --stdin --ignore-missing' '
+       before=$(git rev-parse --verify refs/notes/commits) &&
+       test_when_finished "git update-ref refs/notes/commits $before" &&
+
+       # We have only two -- add another and make sure it stays
+       git notes add -m "extra" &&
+       git notes list HEAD >after-removal-expect &&
+       git rev-parse HEAD^^ HEAD^^^ HEAD^ >input &&
+       git notes remove --ignore-missing --stdin <input &&
+       git notes list | sed -e "s/ .*//" >actual &&
+       test_cmp after-removal-expect actual
+'
+
 test_expect_success 'list notes with "git notes list"' '
        git notes list > output &&
        test_cmp expect output