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 8bbffdf64858a2f462d8a47d4db136b4d0477dc4..6a187f2e2336575fb4974b8c492359913a8c7a9e 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' 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
 
 '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.
 
        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
 -n::
 --dry-run::
        Do not remove anything; just report the object names whose notes
index 541f776ebb18ef7acbddee17299470538f4415f7..f8e437db0156043f1586e66adf343e34ef6cf4dc 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 */
 }
 
        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)
 {
 
 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);
                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;
 }
 
 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",
        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;
                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");
 
 
        t = init_notes_check("remove");
 
-       if (!argc) {
+       if (!argc && !from_stdin) {
                retval = remove_one_note(t, "HEAD", flag);
        } else {
                while (*argv) {
                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++;
                }
        }
                        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);
        if (!retval)
                commit_notes(t, "Notes removed by 'git notes remove'");
        free_notes(t);
index e820a6bc708a85ef05416d090bebe6039ac9ebfe..16de05aff941c73b3e5f5371bd4739959f679efa 100755 (executable)
@@ -475,6 +475,41 @@ test_expect_success 'removing with --ignore-missing but bogus ref' '
        test "$before" = "$after"
 '
 
        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
 test_expect_success 'list notes with "git notes list"' '
        git notes list > output &&
        test_cmp expect output