From c3ab1a8e4cb8a84967efcf45c5e6bee41b17f9f9 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 18 May 2011 15:44:37 -0700 Subject: notes remove: allow removing more than one While "xargs -n1 git notes rm" is certainly a possible way to remove notes from many objects, this would create one notes "commit" per removal, which is not quite suitable for seasonal housekeeping. Allow taking more than one on the command line, and record their removal as a single atomic event if everthing goes well. Even though the old code insisted that "git notes rm" must be given only one object (or zero, in which case it would default to HEAD), this condition was not tested. Add tests to handle the new case where we feed multiple objects, and also make sure if there is a bad input, no change is recorded. Signed-off-by: Junio C Hamano --- builtin/notes.c | 47 +++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 22 deletions(-) (limited to 'builtin/notes.c') diff --git a/builtin/notes.c b/builtin/notes.c index 1fb1f7343..30cee0fd3 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -29,7 +29,7 @@ static const char * const git_notes_usage[] = { "git notes [--ref ] merge [-v | -q] [-s ] ", "git notes merge --commit [-v | -q]", "git notes merge --abort [-v | -q]", - "git notes [--ref ] remove []", + "git notes [--ref ] remove [...]", "git notes [--ref ] prune [-n | -v]", "git notes [--ref ] get-ref", NULL @@ -953,40 +953,43 @@ static int merge(int argc, const char **argv, const char *prefix) return result < 0; /* return non-zero on conflicts */ } +static int remove_one_note(struct notes_tree *t, const char *name) +{ + int status; + unsigned char sha1[20]; + if (get_sha1(name, sha1)) + return error(_("Failed to resolve '%s' as a valid ref."), name); + status = remove_note(t, sha1); + if (status) + fprintf(stderr, _("Object %s has no note\n"), name); + else + fprintf(stderr, _("Removing note for object %s\n"), name); + return status; +} + static int remove_cmd(int argc, const char **argv, const char *prefix) { struct option options[] = { OPT_END() }; - const char *object_ref; struct notes_tree *t; - unsigned char object[20]; - int retval; + int retval = 0; argc = parse_options(argc, argv, prefix, options, git_notes_remove_usage, 0); - if (1 < argc) { - error(_("too many parameters")); - usage_with_options(git_notes_remove_usage, options); - } - - object_ref = argc ? argv[0] : "HEAD"; - - if (get_sha1(object_ref, object)) - die(_("Failed to resolve '%s' as a valid ref."), object_ref); - t = init_notes_check("remove"); - retval = remove_note(t, object); - if (retval) - fprintf(stderr, _("Object %s has no note\n"), sha1_to_hex(object)); - else { - fprintf(stderr, _("Removing note for object %s\n"), - sha1_to_hex(object)); - - commit_notes(t, "Notes removed by 'git notes remove'"); + if (!argc) { + retval = remove_one_note(t, "HEAD"); + } else { + while (*argv) { + retval |= remove_one_note(t, *argv); + argv++; + } } + if (!retval) + commit_notes(t, "Notes removed by 'git notes remove'"); free_notes(t); return retval; } -- cgit v1.2.1 From 2d370d2fbcf896912cc0739b806224f9a270bb5e Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 18 May 2011 16:02:58 -0700 Subject: notes remove: --ignore-missing Depending on the application, it is not necessarily an error for an object to lack a note, especially if the only thing the caller wants to make sure is that notes are cleared for an object. By passing this option from the command line, the "git notes remove" command considers it a success if the object did not have any note to begin with. Signed-off-by: Junio C Hamano --- builtin/notes.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'builtin/notes.c') diff --git a/builtin/notes.c b/builtin/notes.c index 30cee0fd3..541f776eb 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -953,7 +953,9 @@ static int merge(int argc, const char **argv, const char *prefix) return result < 0; /* return non-zero on conflicts */ } -static int remove_one_note(struct notes_tree *t, const char *name) +#define MISSING_OK 1 + +static int remove_one_note(struct notes_tree *t, const char *name, unsigned flag) { int status; unsigned char sha1[20]; @@ -964,12 +966,16 @@ static int remove_one_note(struct notes_tree *t, const char *name) fprintf(stderr, _("Object %s has no note\n"), name); else fprintf(stderr, _("Removing note for object %s\n"), name); - return status; + return (flag & MISSING_OK) ? 0 : status; } static int remove_cmd(int argc, const char **argv, const char *prefix) { + unsigned flag = 0; struct option options[] = { + OPT_BIT(0, "ignore-missing", &flag, + "attempt to remove non-existent note is not an error", + MISSING_OK), OPT_END() }; struct notes_tree *t; @@ -981,10 +987,10 @@ static int remove_cmd(int argc, const char **argv, const char *prefix) t = init_notes_check("remove"); if (!argc) { - retval = remove_one_note(t, "HEAD"); + retval = remove_one_note(t, "HEAD", flag); } else { while (*argv) { - retval |= remove_one_note(t, *argv); + retval |= remove_one_note(t, *argv, flag); argv++; } } -- cgit v1.2.1 From 46538012d943156ead4024fb510a1ce5d4ff443a Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 18 May 2011 16:44:30 -0700 Subject: 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 --- builtin/notes.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'builtin/notes.c') diff --git a/builtin/notes.c b/builtin/notes.c index 541f776eb..f8e437db0 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -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); -- cgit v1.2.1