@matheusbsbs / matheus-bagliano / commits / 74884b524e
Fork 0

notes: rework subcommands and parse options

Running 'git notes copy -h' is not very helfpul right now. It lists the options for all the git notes subcommands and is rather confusing. Fix this by splitting cmd_notes() into separate functions for each subcommand (besides append and edit since they're very similar) and only providing a usage message for the subcommand. This has an added benefit of reducing the code complexity while making it safer and easier to read. The downside is we get some code bloat from similar setup and teardown needed for notes and options parsing. We also get a bit stricter in options parsing by only allowing the ref option to come before the subcommand. Acked-by: Johan Herland <johan@herland.net> Cc: Thomas Rast <trast@student.ethz.ch> Signed-off-by: Stephen Boyd <bebarino@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Stephen Boyd committed Feb 27, 2010 at 00:59 UTC 74884b524e7e12b3419264d3180de785a9e39fa5
2 files changed +394 -166
builtin-notes.c
+383 -166
@@ -19,13 +19,54 @@
19 #include "string-list.h"
20
21 static const char * const git_notes_usage[] = {
22 + "git notes [--ref <notes_ref>] [list [<object>]]",
23 + "git notes [--ref <notes_ref>] add [-f] [-m <msg> | -F <file> | (-c | -C) <object>] [<object>]",
24 + "git notes [--ref <notes_ref>] copy [-f] <from-object> <to-object>",
25 + "git notes [--ref <notes_ref>] append [-m <msg> | -F <file> | (-c | -C) <object>] [<object>]",
26 + "git notes [--ref <notes_ref>] edit [<object>]",
27 + "git notes [--ref <notes_ref>] show [<object>]",
28 + "git notes [--ref <notes_ref>] remove [<object>]",
29 + "git notes [--ref <notes_ref>] prune",
30 + NULL
31 +};
32 +
33 +static const char * const git_notes_list_usage[] = {
34 "git notes [list [<object>]]",
23 - "git notes add [-f] [-m <msg> | -F <file> | (-c | -C) <object>] [<object>]",
24 - "git notes copy [-f] <from-object> <to-object>",
25 - "git notes append [-m <msg> | -F <file> | (-c | -C) <object>] [<object>]",
35 + NULL
36 +};
37 +
38 +static const char * const git_notes_add_usage[] = {
39 + "git notes add [<options>] [<object>]",
40 + NULL
41 +};
42 +
43 +static const char * const git_notes_copy_usage[] = {
44 + "git notes copy [<options>] <from-object> <to-object>",
45 + "git notes copy --stdin [<from-object> <to-object>]...",
46 + NULL
47 +};
48 +
49 +static const char * const git_notes_append_usage[] = {
50 + "git notes append [<options>] [<object>]",
51 + NULL
52 +};
53 +
54 +static const char * const git_notes_edit_usage[] = {
55 "git notes edit [<object>]",
56 + NULL
57 +};
58 +
59 +static const char * const git_notes_show_usage[] = {
60 "git notes show [<object>]",
61 + NULL
62 +};
63 +
64 +static const char * const git_notes_remove_usage[] = {
65 "git notes remove [<object>]",
66 + NULL
67 +};
68 +
69 +static const char * const git_notes_prune_usage[] = {
70 "git notes prune",
71 NULL
72 };
@@ -281,7 +322,6 @@ int commit_notes(struct notes_tree *t, const char *msg)
322 return 0;
323 }
324
284 -
325 combine_notes_fn *parse_combine_notes_fn(const char *v)
326 {
327 if (!strcasecmp(v, "overwrite"))
@@ -436,219 +476,396 @@ int notes_copy_from_stdin(int force, const char *rewrite_cmd)
476 return ret;
477 }
478
439 -int cmd_notes(int argc, const char **argv, const char *prefix)
479 +static struct notes_tree *init_notes_check(const char *subcommand)
480 {
481 struct notes_tree *t;
442 - unsigned char object[20], from_obj[20], new_note[20];
443 - const unsigned char *note;
444 - const char *object_ref;
445 - char logmsg[100];
482 + init_notes(NULL, NULL, NULL, 0);
483 + t = &default_notes_tree;
484
447 - int list = 0, add = 0, copy = 0, append = 0, edit = 0, show = 0,
448 - remove = 0, prune = 0, force = 0, from_stdin = 0;
449 - int given_object = 0, i = 1, retval = 0;
450 - struct msg_arg msg = { 0, 0, STRBUF_INIT };
451 - const char *rewrite_cmd = NULL;
452 - const char *override_notes_ref = NULL;
485 + if (prefixcmp(t->ref, "refs/notes/"))
486 + die("Refusing to %s notes in %s (outside of refs/notes/)",
487 + subcommand, t->ref);
488 + return t;
489 +}
490 +
491 +static int list(int argc, const char **argv, const char *prefix)
492 +{
493 + struct notes_tree *t;
494 + unsigned char object[20];
495 + const unsigned char *note;
496 + int retval = -1;
497 struct option options[] = {
454 - OPT_GROUP("Notes options"),
455 - OPT_CALLBACK('m', "message", &msg, "MSG",
456 - "note contents as a string", parse_msg_arg),
457 - OPT_CALLBACK('F', "file", &msg, "FILE",
458 - "note contents in a file", parse_file_arg),
459 - OPT_CALLBACK('c', "reedit-message", &msg, "OBJECT",
460 - "reuse and edit specified note object", parse_reedit_arg),
461 - OPT_CALLBACK('C', "reuse-message", &msg, "OBJECT",
462 - "reuse specified note object", parse_reuse_arg),
463 - OPT_BOOLEAN('f', "force", &force, "replace existing notes"),
464 - OPT_BOOLEAN(0, "stdin", &from_stdin, "read objects from stdin"),
465 - OPT_STRING(0, "ref", &override_notes_ref, "notes_ref",
466 - "use notes from <notes_ref>"),
467 - OPT_STRING(0, "for-rewrite", &rewrite_cmd, "command",
468 - "load rewriting config for <command> (implies --stdin)"),
498 OPT_END()
499 };
500
472 - git_config(git_default_config, NULL);
473 -
474 - argc = parse_options(argc, argv, prefix, options, git_notes_usage, 0);
501 + if (argc)
502 + argc = parse_options(argc, argv, prefix, options,
503 + git_notes_list_usage, 0);
504
476 - if (override_notes_ref) {
477 - struct strbuf sb = STRBUF_INIT;
478 - if (!prefixcmp(override_notes_ref, "refs/notes/"))
479 - /* we're happy */;
480 - else if (!prefixcmp(override_notes_ref, "notes/"))
481 - strbuf_addstr(&sb, "refs/");
482 - else
483 - strbuf_addstr(&sb, "refs/notes/");
484 - strbuf_addstr(&sb, override_notes_ref);
485 - setenv("GIT_NOTES_REF", sb.buf, 1);
486 - strbuf_release(&sb);
505 + if (1 < argc) {
506 + error("too many parameters");
507 + usage_with_options(git_notes_list_usage, options);
508 }
509
489 - if (argc && !strcmp(argv[0], "list"))
490 - list = 1;
491 - else if (argc && !strcmp(argv[0], "add"))
492 - add = 1;
493 - else if (argc && !strcmp(argv[0], "copy"))
494 - copy = 1;
495 - else if (argc && !strcmp(argv[0], "append"))
496 - append = 1;
497 - else if (argc && !strcmp(argv[0], "edit"))
498 - edit = 1;
499 - else if (argc && !strcmp(argv[0], "show"))
500 - show = 1;
501 - else if (argc && !strcmp(argv[0], "remove"))
502 - remove = 1;
503 - else if (argc && !strcmp(argv[0], "prune"))
504 - prune = 1;
505 - else if (!argc) {
506 - list = 1; /* Default to 'list' if no other subcommand given */
507 - i = 0;
508 - }
510 + t = init_notes_check("list");
511 + if (argc) {
512 + if (get_sha1(argv[0], object))
513 + die("Failed to resolve '%s' as a valid ref.", argv[0]);
514 + note = get_note(t, object);
515 + if (note) {
516 + puts(sha1_to_hex(note));
517 + retval = 0;
518 + } else
519 + retval = error("No note found for object %s.",
520 + sha1_to_hex(object));
521 + } else
522 + retval = for_each_note(t, 0, list_each_note, NULL);
523
510 - if (list + add + copy + append + edit + show + remove + prune != 1)
511 - usage_with_options(git_notes_usage, options);
524 + free_notes(t);
525 + return retval;
526 +}
527
513 - if (msg.given && !(add || append || edit)) {
514 - error("cannot use -m/-F/-c/-C options with %s subcommand.",
515 - argv[0]);
516 - usage_with_options(git_notes_usage, options);
517 - }
528 +static int add(int argc, const char **argv, const char *prefix)
529 +{
530 + int retval = 0, force = 0;
531 + const char *object_ref;
532 + struct notes_tree *t;
533 + unsigned char object[20], new_note[20];
534 + char logmsg[100];
535 + const unsigned char *note;
536 + struct msg_arg msg = { 0, 0, STRBUF_INIT };
537 + struct option options[] = {
538 + { OPTION_CALLBACK, 'm', "message", &msg, "MSG",
539 + "note contents as a string", PARSE_OPT_NONEG,
540 + parse_msg_arg},
541 + { OPTION_CALLBACK, 'F', "file", &msg, "FILE",
542 + "note contents in a file", PARSE_OPT_NONEG,
543 + parse_file_arg},
544 + { OPTION_CALLBACK, 'c', "reedit-message", &msg, "OBJECT",
545 + "reuse and edit specified note object", PARSE_OPT_NONEG,
546 + parse_reedit_arg},
547 + { OPTION_CALLBACK, 'C', "reuse-message", &msg, "OBJECT",
548 + "reuse specified note object", PARSE_OPT_NONEG,
549 + parse_reuse_arg},
550 + OPT_BOOLEAN('f', "force", &force, "replace existing notes"),
551 + OPT_END()
552 + };
553
519 - if (msg.given && edit) {
520 - fprintf(stderr, "The -m/-F/-c/-C options have been deprecated "
521 - "for the 'edit' subcommand.\n"
522 - "Please use 'git notes add -f -m/-F/-c/-C' instead.\n");
523 - }
554 + argc = parse_options(argc, argv, prefix, options, git_notes_add_usage,
555 + 0);
556
525 - if (force && !(add || copy)) {
526 - error("cannot use -f option with %s subcommand.", argv[0]);
527 - usage_with_options(git_notes_usage, options);
557 + if (1 < argc) {
558 + error("too many parameters");
559 + usage_with_options(git_notes_add_usage, options);
560 }
561
530 - if (!copy && rewrite_cmd) {
531 - error("cannot use --for-rewrite with %s subcommand.", argv[0]);
532 - usage_with_options(git_notes_usage, options);
533 - }
534 - if (!copy && from_stdin) {
535 - error("cannot use --stdin with %s subcommand.", argv[0]);
536 - usage_with_options(git_notes_usage, options);
537 - }
562 + object_ref = argc ? argv[0] : "HEAD";
563
539 - if (copy) {
540 - const char *from_ref;
541 - if (from_stdin || rewrite_cmd) {
542 - if (argc > 1) {
543 - error("too many parameters");
544 - usage_with_options(git_notes_usage, options);
545 - } else {
546 - return notes_copy_from_stdin(force, rewrite_cmd);
547 - }
548 - }
549 - if (argc < 3) {
550 - error("too few parameters");
551 - usage_with_options(git_notes_usage, options);
552 - }
553 - from_ref = argv[i++];
554 - if (get_sha1(from_ref, from_obj))
555 - die("Failed to resolve '%s' as a valid ref.", from_ref);
556 - }
564 + if (get_sha1(object_ref, object))
565 + die("Failed to resolve '%s' as a valid ref.", object_ref);
566
558 - given_object = argc > i;
559 - object_ref = given_object ? argv[i++] : "HEAD";
567 + t = init_notes_check("add");
568 + note = get_note(t, object);
569
561 - if (argc > i || (prune && given_object)) {
562 - error("too many parameters");
563 - usage_with_options(git_notes_usage, options);
570 + if (note) {
571 + if (!force) {
572 + retval = error("Cannot add notes. Found existing notes "
573 + "for object %s. Use '-f' to overwrite "
574 + "existing notes", sha1_to_hex(object));
575 + goto out;
576 + }
577 + fprintf(stderr, "Overwriting existing notes for object %s\n",
578 + sha1_to_hex(object));
579 }
580
566 - if (get_sha1(object_ref, object))
567 - die("Failed to resolve '%s' as a valid ref.", object_ref);
581 + create_note(object, &msg, 0, note, new_note);
582
569 - init_notes(NULL, NULL, NULL, 0);
570 - t = &default_notes_tree;
583 + if (is_null_sha1(new_note))
584 + remove_note(t, object);
585 + else
586 + add_note(t, object, new_note, combine_notes_overwrite);
587
572 - if (prefixcmp(t->ref, "refs/notes/"))
573 - die("Refusing to %s notes in %s (outside of refs/notes/)",
574 - argv[0], t->ref);
588 + snprintf(logmsg, sizeof(logmsg), "Notes %s by 'git notes %s'",
589 + is_null_sha1(new_note) ? "removed" : "added", "add");
590 + commit_notes(t, logmsg);
591 +out:
592 + free_notes(t);
593 + strbuf_release(&(msg.buf));
594 + return retval;
595 +}
596
576 - note = get_note(t, object);
597 +static int copy(int argc, const char **argv, const char *prefix)
598 +{
599 + int retval = 0, force = 0, from_stdin = 0;
600 + const unsigned char *from_note, *note;
601 + const char *object_ref;
602 + unsigned char object[20], from_obj[20];
603 + struct notes_tree *t;
604 + const char *rewrite_cmd = NULL;
605 + struct option options[] = {
606 + OPT_BOOLEAN('f', "force", &force, "replace existing notes"),
607 + OPT_BOOLEAN(0, "stdin", &from_stdin, "read objects from stdin"),
608 + OPT_STRING(0, "for-rewrite", &rewrite_cmd, "command",
609 + "load rewriting config for <command> (implies "
610 + "--stdin)"),
611 + OPT_END()
612 + };
613
578 - /* list command */
614 + argc = parse_options(argc, argv, prefix, options, git_notes_copy_usage,
615 + 0);
616
580 - if (list) {
581 - if (given_object) {
582 - if (note) {
583 - puts(sha1_to_hex(note));
584 - goto end;
585 - }
617 + if (from_stdin || rewrite_cmd) {
618 + if (argc) {
619 + error("too many parameters");
620 + usage_with_options(git_notes_copy_usage, options);
621 } else {
587 - retval = for_each_note(t, 0, list_each_note, NULL);
588 - goto end;
622 + return notes_copy_from_stdin(force, rewrite_cmd);
623 }
624 }
625
592 - /* show command */
593 -
594 - if ((list || show) && !note) {
595 - error("No note found for object %s.", sha1_to_hex(object));
596 - retval = 1;
597 - goto end;
598 - } else if (show) {
599 - const char *show_args[3] = {"show", sha1_to_hex(note), NULL};
600 - retval = execv_git_cmd(show_args);
601 - goto end;
626 + if (2 < argc) {
627 + error("too many parameters");
628 + usage_with_options(git_notes_copy_usage, options);
629 }
630
604 - /* add/append/edit/remove/prune command */
631 + if (get_sha1(argv[0], from_obj))
632 + die("Failed to resolve '%s' as a valid ref.", argv[0]);
633 +
634 + object_ref = 1 < argc ? argv[1] : "HEAD";
635 +
636 + if (get_sha1(object_ref, object))
637 + die("Failed to resolve '%s' as a valid ref.", object_ref);
638
606 - if ((add || copy) && note) {
639 + t = init_notes_check("copy");
640 + note = get_note(t, object);
641 +
642 + if (note) {
643 if (!force) {
608 - error("Cannot %s notes. Found existing notes for object"
609 - " %s. Use '-f' to overwrite existing notes",
610 - argv[0], sha1_to_hex(object));
611 - retval = 1;
612 - goto end;
644 + retval = error("Cannot copy notes. Found existing "
645 + "notes for object %s. Use '-f' to "
646 + "overwrite existing notes",
647 + sha1_to_hex(object));
648 + goto out;
649 }
650 fprintf(stderr, "Overwriting existing notes for object %s\n",
651 sha1_to_hex(object));
652 }
653
618 - if (remove) {
619 - msg.given = 1;
620 - msg.use_editor = 0;
621 - strbuf_reset(&(msg.buf));
654 + from_note = get_note(t, from_obj);
655 + if (!from_note) {
656 + retval = error("Missing notes on source object %s. Cannot "
657 + "copy.", sha1_to_hex(from_obj));
658 + goto out;
659 }
660
624 - if (prune) {
625 - hashclr(new_note);
626 - prune_notes(t);
627 - goto commit;
628 - } else if (copy) {
629 - const unsigned char *from_note = get_note(t, from_obj);
630 - if (!from_note) {
631 - error("Missing notes on source object %s. Cannot copy.",
632 - sha1_to_hex(from_obj));
633 - retval = 1;
634 - goto end;
635 - }
636 - hashcpy(new_note, from_note);
637 - } else
638 - create_note(object, &msg, append, note, new_note);
661 + add_note(t, object, from_note, combine_notes_overwrite);
662 + commit_notes(t, "Notes added by 'git notes copy'");
663 +out:
664 + free_notes(t);
665 + return retval;
666 +}
667 +
668 +static int append_edit(int argc, const char **argv, const char *prefix)
669 +{
670 + const char *object_ref;
671 + struct notes_tree *t;
672 + unsigned char object[20], new_note[20];
673 + const unsigned char *note;
674 + char logmsg[100];
675 + const char * const *usage;
676 + struct msg_arg msg = { 0, 0, STRBUF_INIT };
677 + struct option options[] = {
678 + { OPTION_CALLBACK, 'm', "message", &msg, "MSG",
679 + "note contents as a string", PARSE_OPT_NONEG,
680 + parse_msg_arg},
681 + { OPTION_CALLBACK, 'F', "file", &msg, "FILE",
682 + "note contents in a file", PARSE_OPT_NONEG,
683 + parse_file_arg},
684 + { OPTION_CALLBACK, 'c', "reedit-message", &msg, "OBJECT",
685 + "reuse and edit specified note object", PARSE_OPT_NONEG,
686 + parse_reedit_arg},
687 + { OPTION_CALLBACK, 'C', "reuse-message", &msg, "OBJECT",
688 + "reuse specified note object", PARSE_OPT_NONEG,
689 + parse_reuse_arg},
690 + OPT_END()
691 + };
692 + int edit = !strcmp(argv[0], "edit");
693 +
694 + usage = edit ? git_notes_edit_usage : git_notes_append_usage;
695 + argc = parse_options(argc, argv, prefix, options, usage,
696 + PARSE_OPT_KEEP_ARGV0);
697 +
698 + if (2 < argc) {
699 + error("too many parameters");
700 + usage_with_options(usage, options);
701 + }
702 +
703 + if (msg.given && edit)
704 + fprintf(stderr, "The -m/-F/-c/-C options have been deprecated "
705 + "for the 'edit' subcommand.\n"
706 + "Please use 'git notes add -f -m/-F/-c/-C' instead.\n");
707 +
708 + object_ref = 1 < argc ? argv[1] : "HEAD";
709 +
710 + if (get_sha1(object_ref, object))
711 + die("Failed to resolve '%s' as a valid ref.", object_ref);
712 +
713 + t = init_notes_check(argv[0]);
714 + note = get_note(t, object);
715 +
716 + create_note(object, &msg, !edit, note, new_note);
717
718 if (is_null_sha1(new_note))
719 remove_note(t, object);
720 else
721 add_note(t, object, new_note, combine_notes_overwrite);
722
645 -commit:
723 snprintf(logmsg, sizeof(logmsg), "Notes %s by 'git notes %s'",
724 is_null_sha1(new_note) ? "removed" : "added", argv[0]);
725 commit_notes(t, logmsg);
649 -
650 -end:
726 free_notes(t);
727 strbuf_release(&(msg.buf));
728 + return 0;
729 +}
730 +
731 +static int show(int argc, const char **argv, const char *prefix)
732 +{
733 + const char *object_ref;
734 + struct notes_tree *t;
735 + unsigned char object[20];
736 + const unsigned char *note;
737 + int retval;
738 + struct option options[] = {
739 + OPT_END()
740 + };
741 +
742 + argc = parse_options(argc, argv, prefix, options, git_notes_show_usage,
743 + 0);
744 +
745 + if (1 < argc) {
746 + error("too many parameters");
747 + usage_with_options(git_notes_show_usage, options);
748 + }
749 +
750 + object_ref = argc ? argv[0] : "HEAD";
751 +
752 + if (get_sha1(object_ref, object))
753 + die("Failed to resolve '%s' as a valid ref.", object_ref);
754 +
755 + t = init_notes_check("show");
756 + note = get_note(t, object);
757 +
758 + if (!note)
759 + retval = error("No note found for object %s.",
760 + sha1_to_hex(object));
761 + else {
762 + const char *show_args[3] = {"show", sha1_to_hex(note), NULL};
763 + retval = execv_git_cmd(show_args);
764 + }
765 + free_notes(t);
766 return retval;
767 }
768 +
769 +static int remove_cmd(int argc, const char **argv, const char *prefix)
770 +{
771 + struct option options[] = {
772 + OPT_END()
773 + };
774 + const char *object_ref;
775 + struct notes_tree *t;
776 + unsigned char object[20];
777 +
778 + argc = parse_options(argc, argv, prefix, options,
779 + git_notes_remove_usage, 0);
780 +
781 + if (1 < argc) {
782 + error("too many parameters");
783 + usage_with_options(git_notes_remove_usage, options);
784 + }
785 +
786 + object_ref = argc ? argv[0] : "HEAD";
787 +
788 + if (get_sha1(object_ref, object))
789 + die("Failed to resolve '%s' as a valid ref.", object_ref);
790 +
791 + t = init_notes_check("remove");
792 +
793 + fprintf(stderr, "Removing note for object %s\n", sha1_to_hex(object));
794 + remove_note(t, object);
795 +
796 + commit_notes(t, "Notes removed by 'git notes remove'");
797 + free_notes(t);
798 + return 0;
799 +}
800 +
801 +static int prune(int argc, const char **argv, const char *prefix)
802 +{
803 + struct notes_tree *t;
804 + struct option options[] = {
805 + OPT_END()
806 + };
807 +
808 + argc = parse_options(argc, argv, prefix, options, git_notes_prune_usage,
809 + 0);
810 +
811 + if (argc) {
812 + error("too many parameters");
813 + usage_with_options(git_notes_prune_usage, options);
814 + }
815 +
816 + t = init_notes_check("prune");
817 +
818 + prune_notes(t);
819 + commit_notes(t, "Notes removed by 'git notes prune'");
820 + free_notes(t);
821 + return 0;
822 +}
823 +
824 +int cmd_notes(int argc, const char **argv, const char *prefix)
825 +{
826 + int result;
827 + const char *override_notes_ref = NULL;
828 + struct option options[] = {
829 + OPT_STRING(0, "ref", &override_notes_ref, "notes_ref",
830 + "use notes from <notes_ref>"),
831 + OPT_END()
832 + };
833 +
834 + git_config(git_default_config, NULL);
835 + argc = parse_options(argc, argv, prefix, options, git_notes_usage,
836 + PARSE_OPT_STOP_AT_NON_OPTION);
837 +
838 + if (override_notes_ref) {
839 + struct strbuf sb = STRBUF_INIT;
840 + if (!prefixcmp(override_notes_ref, "refs/notes/"))
841 + /* we're happy */;
842 + else if (!prefixcmp(override_notes_ref, "notes/"))
843 + strbuf_addstr(&sb, "refs/");
844 + else
845 + strbuf_addstr(&sb, "refs/notes/");
846 + strbuf_addstr(&sb, override_notes_ref);
847 + setenv("GIT_NOTES_REF", sb.buf, 1);
848 + strbuf_release(&sb);
849 + }
850 +
851 + if (argc < 1 || !strcmp(argv[0], "list"))
852 + result = list(argc, argv, prefix);
853 + else if (!strcmp(argv[0], "add"))
854 + result = add(argc, argv, prefix);
855 + else if (!strcmp(argv[0], "copy"))
856 + result = copy(argc, argv, prefix);
857 + else if (!strcmp(argv[0], "append") || !strcmp(argv[0], "edit"))
858 + result = append_edit(argc, argv, prefix);
859 + else if (!strcmp(argv[0], "show"))
860 + result = show(argc, argv, prefix);
861 + else if (!strcmp(argv[0], "remove"))
862 + result = remove_cmd(argc, argv, prefix);
863 + else if (!strcmp(argv[0], "prune"))
864 + result = prune(argc, argv, prefix);
865 + else {
866 + result = error("Unknown subcommand: %s", argv[0]);
867 + usage_with_options(git_notes_usage, options);
868 + }
869 +
870 + return result ? 1 : 0;
871 +}
t/t3301-notes.sh
+11
@@ -377,6 +377,17 @@ test_expect_success 'append to existing note with "git notes append"' '
377 test_cmp expect output
378 '
379
380 +cat > expect_list << EOF
381 +c18dc024e14f08d18d14eea0d747ff692d66d6a3 1584215f1d29c65e99c6c6848626553fdd07fd75
382 +c9c6af7f78bc47490dbf3e822cf2f3c24d4b9061 268048bfb8a1fb38e703baceb8ab235421bf80c5
383 +4b6ad22357cc8a1296720574b8d2fbc22fab0671 bd1753200303d0a0344be813e504253b3d98e74d
384 +EOF
385 +
386 +test_expect_success '"git notes list" does not expand to "git notes list HEAD"' '
387 + git notes list > output &&
388 + test_cmp expect_list output
389 +'
390 +
391 test_expect_success 'appending empty string does not change existing note' '
392 git notes append -m "" &&
393 git notes show > output &&