Merge branch 'jk/notes-ui-updates'
authorJunio C Hamano <gitster@pobox.com>
Mon, 2 May 2011 22:58:50 +0000 (15:58 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 2 May 2011 22:58:50 +0000 (15:58 -0700)
* jk/notes-ui-updates:
contrib/completion: --notes, --no-notes
log/pretty-options: Document --[no-]notes and deprecate old notes options
revision.c: make --no-notes reset --notes list
revision.c: support --notes command-line option
notes: refactor display notes default handling
notes: refactor display notes extra refs field
revision.c: refactor notes ref expansion
notes: make expand_notes_ref globally accessible

1  2 
builtin/notes.c
contrib/completion/git-completion.bash
t/t3301-notes.sh
diff --combined builtin/notes.c
index 8685d2bda6cbde2fb04fcc29f964c6dd6e444271,62276072fc7d6788b40dc8b27c578dfd8416c385..1fb1f734397668280b444e63dc8d3c129d41e3b9
@@@ -100,16 -100,6 +100,6 @@@ struct msg_arg 
        struct strbuf buf;
  };
  
- static void expand_notes_ref(struct strbuf *sb)
- {
-       if (!prefixcmp(sb->buf, "refs/notes/"))
-               return; /* we're happy */
-       else if (!prefixcmp(sb->buf, "notes/"))
-               strbuf_insert(sb, 0, "refs/", 5);
-       else
-               strbuf_insert(sb, 0, "refs/notes/", 11);
- }
  static int list_each_note(const unsigned char *object_sha1,
                const unsigned char *note_sha1, char *note_path,
                void *cb_data)
@@@ -146,13 -136,13 +136,13 @@@ static void write_commented_object(int 
        show.err = 0;
        show.git_cmd = 1;
        if (start_command(&show))
 -              die("unable to start 'show' for object '%s'",
 +              die(_("unable to start 'show' for object '%s'"),
                    sha1_to_hex(object));
  
        /* Open the output as FILE* so strbuf_getline() can be used. */
        show_out = xfdopen(show.out, "r");
        if (show_out == NULL)
 -              die_errno("can't fdopen 'show' output fd");
 +              die_errno(_("can't fdopen 'show' output fd"));
  
        /* Prepend "# " to each output line and write result to 'fd' */
        while (strbuf_getline(&buf, show_out, '\n') != EOF) {
        }
        strbuf_release(&buf);
        if (fclose(show_out))
 -              die_errno("failed to close pipe to 'show' for object '%s'",
 +              die_errno(_("failed to close pipe to 'show' for object '%s'"),
                          sha1_to_hex(object));
        if (finish_command(&show))
 -              die("failed to finish 'show' for object '%s'",
 +              die(_("failed to finish 'show' for object '%s'"),
                    sha1_to_hex(object));
  }
  
@@@ -182,7 -172,7 +172,7 @@@ static void create_note(const unsigned 
                path = git_pathdup("NOTES_EDITMSG");
                fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
                if (fd < 0)
 -                      die_errno("could not create file '%s'", path);
 +                      die_errno(_("could not create file '%s'"), path);
  
                if (msg->given)
                        write_or_die(fd, msg->buf.buf, msg->buf.len);
                strbuf_reset(&(msg->buf));
  
                if (launch_editor(path, &(msg->buf), NULL)) {
 -                      die("Please supply the note contents using either -m" \
 -                          " or -F option");
 +                      die(_("Please supply the note contents using either -m" \
 +                          " or -F option"));
                }
                stripspace(&(msg->buf), 1);
        }
        }
  
        if (!msg->buf.len) {
 -              fprintf(stderr, "Removing note for object %s\n",
 +              fprintf(stderr, _("Removing note for object %s\n"),
                        sha1_to_hex(object));
                hashclr(result);
        } else {
                if (write_sha1_file(msg->buf.buf, msg->buf.len, blob_type, result)) {
 -                      error("unable to write note object");
 +                      error(_("unable to write note object"));
                        if (path)
 -                              error("The note contents has been left in %s",
 +                              error(_("The note contents has been left in %s"),
                                      path);
                        exit(128);
                }
@@@ -258,9 -248,9 +248,9 @@@ static int parse_file_arg(const struct 
                strbuf_addch(&(msg->buf), '\n');
        if (!strcmp(arg, "-")) {
                if (strbuf_read(&(msg->buf), 0, 1024) < 0)
 -                      die_errno("cannot read '%s'", arg);
 +                      die_errno(_("cannot read '%s'"), arg);
        } else if (strbuf_read_file(&(msg->buf), arg, 1024) < 0)
 -              die_errno("could not open or read '%s'", arg);
 +              die_errno(_("could not open or read '%s'"), arg);
        stripspace(&(msg->buf), 0);
  
        msg->given = 1;
@@@ -279,10 -269,10 +269,10 @@@ static int parse_reuse_arg(const struc
                strbuf_addch(&(msg->buf), '\n');
  
        if (get_sha1(arg, object))
 -              die("Failed to resolve '%s' as a valid ref.", arg);
 +              die(_("Failed to resolve '%s' as a valid ref."), arg);
        if (!(buf = read_sha1_file(object, &type, &len)) || !len) {
                free(buf);
 -              die("Failed to read object '%s'.", arg);;
 +              die(_("Failed to read object '%s'."), arg);;
        }
        strbuf_add(&(msg->buf), buf, len);
        free(buf);
@@@ -306,7 -296,7 +296,7 @@@ void commit_notes(struct notes_tree *t
        if (!t)
                t = &default_notes_tree;
        if (!t->initialized || !t->ref || !*t->ref)
 -              die("Cannot commit uninitialized/unreferenced notes tree");
 +              die(_("Cannot commit uninitialized/unreferenced notes tree"));
        if (!t->dirty)
                return; /* don't have to commit an unchanged tree */
  
@@@ -347,7 -337,7 +337,7 @@@ static int notes_rewrite_config(const c
                        config_error_nonbool(k);
                c->combine = parse_combine_notes_fn(v);
                if (!c->combine) {
 -                      error("Bad notes.rewriteMode value: '%s'", v);
 +                      error(_("Bad notes.rewriteMode value: '%s'"), v);
                        return 1;
                }
                return 0;
                if (!prefixcmp(v, "refs/notes/"))
                        string_list_add_refs_by_glob(c->refs, v);
                else
 -                      warning("Refusing to rewrite notes in %s"
 -                              " (outside of refs/notes/)", v);
 +                      warning(_("Refusing to rewrite notes in %s"
 +                              " (outside of refs/notes/)"), v);
                return 0;
        }
  
@@@ -382,10 -372,8 +372,10 @@@ struct notes_rewrite_cfg *init_copy_not
                c->mode_from_env = 1;
                c->combine = parse_combine_notes_fn(rewrite_mode_env);
                if (!c->combine)
 -                      error("Bad " GIT_NOTES_REWRITE_MODE_ENVIRONMENT
 -                            " value: '%s'", rewrite_mode_env);
 +                      /* TRANSLATORS: The first %s is the name of the
 +                         environment variable, the second %s is its value */
 +                      error(_("Bad %s value: '%s'"), GIT_NOTES_REWRITE_MODE_ENVIRONMENT,
 +                                      rewrite_mode_env);
        }
        if (rewrite_refs_env) {
                c->refs_from_env = 1;
@@@ -448,13 -436,13 +438,13 @@@ static int notes_copy_from_stdin(int fo
  
                split = strbuf_split(&buf, ' ');
                if (!split[0] || !split[1])
 -                      die("Malformed input line: '%s'.", buf.buf);
 +                      die(_("Malformed input line: '%s'."), buf.buf);
                strbuf_rtrim(split[0]);
                strbuf_rtrim(split[1]);
                if (get_sha1(split[0]->buf, from_obj))
 -                      die("Failed to resolve '%s' as a valid ref.", split[0]->buf);
 +                      die(_("Failed to resolve '%s' as a valid ref."), split[0]->buf);
                if (get_sha1(split[1]->buf, to_obj))
 -                      die("Failed to resolve '%s' as a valid ref.", split[1]->buf);
 +                      die(_("Failed to resolve '%s' as a valid ref."), split[1]->buf);
  
                if (rewrite_cmd)
                        err = copy_note_for_rewrite(c, from_obj, to_obj);
                                        combine_notes_overwrite);
  
                if (err) {
 -                      error("Failed to copy notes from '%s' to '%s'",
 +                      error(_("Failed to copy notes from '%s' to '%s'"),
                              split[0]->buf, split[1]->buf);
                        ret = 1;
                }
@@@ -507,20 -495,20 +497,20 @@@ static int list(int argc, const char **
                                     git_notes_list_usage, 0);
  
        if (1 < argc) {
 -              error("too many parameters");
 +              error(_("too many parameters"));
                usage_with_options(git_notes_list_usage, options);
        }
  
        t = init_notes_check("list");
        if (argc) {
                if (get_sha1(argv[0], object))
 -                      die("Failed to resolve '%s' as a valid ref.", argv[0]);
 +                      die(_("Failed to resolve '%s' as a valid ref."), argv[0]);
                note = get_note(t, object);
                if (note) {
                        puts(sha1_to_hex(note));
                        retval = 0;
                } else
 -                      retval = error("No note found for object %s.",
 +                      retval = error(_("No note found for object %s."),
                                       sha1_to_hex(object));
        } else
                retval = for_each_note(t, 0, list_each_note, NULL);
        return retval;
  }
  
 +static int append_edit(int argc, const char **argv, const char *prefix);
 +
  static int add(int argc, const char **argv, const char *prefix)
  {
        int retval = 0, force = 0;
        };
  
        argc = parse_options(argc, argv, prefix, options, git_notes_add_usage,
 -                           0);
 +                           PARSE_OPT_KEEP_ARGV0);
  
 -      if (1 < argc) {
 -              error("too many parameters");
 +      if (2 < argc) {
 +              error(_("too many parameters"));
                usage_with_options(git_notes_add_usage, options);
        }
  
 -      object_ref = argc ? argv[0] : "HEAD";
 +      object_ref = argc > 1 ? argv[1] : "HEAD";
  
        if (get_sha1(object_ref, object))
 -              die("Failed to resolve '%s' as a valid ref.", object_ref);
 +              die(_("Failed to resolve '%s' as a valid ref."), object_ref);
  
        t = init_notes_check("add");
        note = get_note(t, object);
  
        if (note) {
                if (!force) {
 -                      retval = error("Cannot add notes. Found existing notes "
 +                      if (!msg.given) {
 +                              /*
 +                               * Redirect to "edit" subcommand.
 +                               *
 +                               * We only end up here if none of -m/-F/-c/-C
 +                               * or -f are given. The original args are
 +                               * therefore still in argv[0-1].
 +                               */
 +                              argv[0] = "edit";
 +                              free_notes(t);
 +                              return append_edit(argc, argv, prefix);
 +                      }
 +                      retval = error(_("Cannot add notes. Found existing notes "
                                       "for object %s. Use '-f' to overwrite "
 -                                     "existing notes", sha1_to_hex(object));
 +                                     "existing notes"), sha1_to_hex(object));
                        goto out;
                }
 -              fprintf(stderr, "Overwriting existing notes for object %s\n",
 +              fprintf(stderr, _("Overwriting existing notes for object %s\n"),
                        sha1_to_hex(object));
        }
  
@@@ -634,7 -608,7 +624,7 @@@ static int copy(int argc, const char **
  
        if (from_stdin || rewrite_cmd) {
                if (argc) {
 -                      error("too many parameters");
 +                      error(_("too many parameters"));
                        usage_with_options(git_notes_copy_usage, options);
                } else {
                        return notes_copy_from_stdin(force, rewrite_cmd);
        }
  
        if (argc < 2) {
 -              error("too few parameters");
 +              error(_("too few parameters"));
                usage_with_options(git_notes_copy_usage, options);
        }
        if (2 < argc) {
 -              error("too many parameters");
 +              error(_("too many parameters"));
                usage_with_options(git_notes_copy_usage, options);
        }
  
        if (get_sha1(argv[0], from_obj))
 -              die("Failed to resolve '%s' as a valid ref.", argv[0]);
 +              die(_("Failed to resolve '%s' as a valid ref."), argv[0]);
  
        object_ref = 1 < argc ? argv[1] : "HEAD";
  
        if (get_sha1(object_ref, object))
 -              die("Failed to resolve '%s' as a valid ref.", object_ref);
 +              die(_("Failed to resolve '%s' as a valid ref."), object_ref);
  
        t = init_notes_check("copy");
        note = get_note(t, object);
  
        if (note) {
                if (!force) {
 -                      retval = error("Cannot copy notes. Found existing "
 +                      retval = error(_("Cannot copy notes. Found existing "
                                       "notes for object %s. Use '-f' to "
 -                                     "overwrite existing notes",
 +                                     "overwrite existing notes"),
                                       sha1_to_hex(object));
                        goto out;
                }
 -              fprintf(stderr, "Overwriting existing notes for object %s\n",
 +              fprintf(stderr, _("Overwriting existing notes for object %s\n"),
                        sha1_to_hex(object));
        }
  
        from_note = get_note(t, from_obj);
        if (!from_note) {
 -              retval = error("Missing notes on source object %s. Cannot "
 -                             "copy.", sha1_to_hex(from_obj));
 +              retval = error(_("Missing notes on source object %s. Cannot "
 +                             "copy."), sha1_to_hex(from_obj));
                goto out;
        }
  
@@@ -719,19 -693,19 +709,19 @@@ static int append_edit(int argc, const 
                             PARSE_OPT_KEEP_ARGV0);
  
        if (2 < argc) {
 -              error("too many parameters");
 +              error(_("too many parameters"));
                usage_with_options(usage, options);
        }
  
        if (msg.given && edit)
 -              fprintf(stderr, "The -m/-F/-c/-C options have been deprecated "
 +              fprintf(stderr, _("The -m/-F/-c/-C options have been deprecated "
                        "for the 'edit' subcommand.\n"
 -                      "Please use 'git notes add -f -m/-F/-c/-C' instead.\n");
 +                      "Please use 'git notes add -f -m/-F/-c/-C' instead.\n"));
  
        object_ref = 1 < argc ? argv[1] : "HEAD";
  
        if (get_sha1(object_ref, object))
 -              die("Failed to resolve '%s' as a valid ref.", object_ref);
 +              die(_("Failed to resolve '%s' as a valid ref."), object_ref);
  
        t = init_notes_check(argv[0]);
        note = get_note(t, object);
@@@ -766,20 -740,20 +756,20 @@@ static int show(int argc, const char **
                             0);
  
        if (1 < argc) {
 -              error("too many parameters");
 +              error(_("too many parameters"));
                usage_with_options(git_notes_show_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);
 +              die(_("Failed to resolve '%s' as a valid ref."), object_ref);
  
        t = init_notes_check("show");
        note = get_note(t, object);
  
        if (!note)
 -              retval = error("No note found for object %s.",
 +              retval = error(_("No note found for object %s."),
                               sha1_to_hex(object));
        else {
                const char *show_args[3] = {"show", sha1_to_hex(note), NULL};
@@@ -977,22 -951,22 +967,22 @@@ static int remove_cmd(int argc, const c
                             git_notes_remove_usage, 0);
  
        if (1 < argc) {
 -              error("too many parameters");
 +              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);
 +              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));
 +              fprintf(stderr, _("Object %s has no note\n"), sha1_to_hex(object));
        else {
 -              fprintf(stderr, "Removing note for object %s\n",
 +              fprintf(stderr, _("Removing note for object %s\n"),
                        sha1_to_hex(object));
  
                commit_notes(t, "Notes removed by 'git notes remove'");
@@@ -1015,7 -989,7 +1005,7 @@@ static int prune(int argc, const char *
                             0);
  
        if (argc) {
 -              error("too many parameters");
 +              error(_("too many parameters"));
                usage_with_options(git_notes_prune_usage, options);
        }
  
@@@ -1085,7 -1059,7 +1075,7 @@@ int cmd_notes(int argc, const char **ar
        else if (!strcmp(argv[0], "get-ref"))
                result = get_ref(argc, argv, prefix);
        else {
 -              result = error("Unknown subcommand: %s", argv[0]);
 +              result = error(_("Unknown subcommand: %s"), argv[0]);
                usage_with_options(git_notes_usage, options);
        }
  
index 9150ea60267913dd17e749afdf2bca348646a165,7e6a3eee8408c771d77786fcad09f4920e8350cd..0df356decc436fca1ad73ab54ee1c569e06ae5f1
@@@ -1,6 -1,6 +1,6 @@@
  #!bash
  #
 -# bash completion support for core Git.
 +# bash/zsh completion support for core Git.
  #
  # Copyright (C) 2006,2007 Shawn O. Pearce <spearce@spearce.org>
  # Conceptually based on gitcompletion (http://gitweb.hawaga.org.uk/).
  # To use these routines:
  #
  #    1) Copy this file to somewhere (e.g. ~/.git-completion.sh).
 -#    2) Added the following line to your .bashrc:
 -#        source ~/.git-completion.sh
 -#
 -#       Or, add the following lines to your .zshrc:
 -#        autoload bashcompinit
 -#        bashcompinit
 +#    2) Add the following line to your .bashrc/.zshrc:
  #        source ~/.git-completion.sh
  #
  #    3) Consider changing your PS1 to also show the current branch:
 -#        PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
 +#         Bash: PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
 +#         ZSH:  PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ '
  #
  #       The argument to __git_ps1 will be displayed only if you
  #       are currently in a git repository.  The %s token will be
  #       git@vger.kernel.org
  #
  
 +if [[ -n ${ZSH_VERSION-} ]]; then
 +      autoload -U +X bashcompinit && bashcompinit
 +fi
 +
  case "$COMP_WORDBREAKS" in
  *:*) : great ;;
  *)   COMP_WORDBREAKS="$COMP_WORDBREAKS:"
@@@ -1584,7 -1584,7 +1584,7 @@@ __git_log_common_options=
  __git_log_gitk_options="
        --dense --sparse --full-history
        --simplify-merges --simplify-by-decoration
-       --left-right
+       --left-right --notes --no-notes
  "
  # Options that go well for log and shortlog (not gitk)
  __git_log_shortlog_options="
diff --combined t/t3301-notes.sh
index 3448c23776dc867fa0542665f69ccb27ac564337,8600db7edb5c73beb56a9059fa222ce4170d2a7f..28e17c8920cbe9f2b13ff5cc30939eab8171bae2
@@@ -101,8 -101,8 +101,8 @@@ test_expect_success 'edit existing note
        test_must_fail git notes show HEAD^
  '
  
 -test_expect_success 'cannot add note where one exists' '
 -      ! MSG=b2 git notes add &&
 +test_expect_success 'cannot "git notes add -m" where notes already exists' '
 +      test_must_fail git notes add -m "b2" &&
        test ! -f .git/NOTES_EDITMSG &&
        test 1 = $(git ls-tree refs/notes/commits | wc -l) &&
        test b3 = $(git notes show) &&
        test_must_fail git notes show HEAD^
  '
  
 +test_expect_success 'can overwrite existing note with "git notes add -f -m"' '
 +      git notes add -f -m "b1" &&
 +      test ! -f .git/NOTES_EDITMSG &&
 +      test 1 = $(git ls-tree refs/notes/commits | wc -l) &&
 +      test b1 = $(git notes show) &&
 +      git show HEAD^ &&
 +      test_must_fail git notes show HEAD^
 +'
 +
 +test_expect_success 'add w/no options on existing note morphs into edit' '
 +      MSG=b2 git notes add &&
 +      test ! -f .git/NOTES_EDITMSG &&
 +      test 1 = $(git ls-tree refs/notes/commits | wc -l) &&
 +      test b2 = $(git notes show) &&
 +      git show HEAD^ &&
 +      test_must_fail git notes show HEAD^
 +'
 +
  test_expect_success 'can overwrite existing note with "git notes add -f"' '
        MSG=b1 git notes add -f &&
        test ! -f .git/NOTES_EDITMSG &&
@@@ -212,13 -194,6 +212,13 @@@ test_expect_success 'show -F notes' 
        test_cmp expect-F output
  '
  
 +test_expect_success 'Re-adding -F notes without -f fails' '
 +      echo "zyxxy" > note5 &&
 +      test_must_fail git notes add -F note5 &&
 +      git log -3 > output &&
 +      test_cmp expect-F output
 +'
 +
  cat >expect << EOF
  commit 15023535574ded8b1a89052b32673f84cf9582b8
  tree e070e3af51011e47b183c33adf9736736a525709
        '
  done
  
+ test_expect_success 'setup alternate notes ref' '
+       git notes --ref=alternate add -m alternate
+ '
+ test_expect_success 'git log --notes shows default notes' '
+       git log -1 --notes >output &&
+       grep xyzzy output &&
+       ! grep alternate output
+ '
+ test_expect_success 'git log --notes=X shows only X' '
+       git log -1 --notes=alternate >output &&
+       ! grep xyzzy output &&
+       grep alternate output
+ '
+ test_expect_success 'git log --notes --notes=X shows both' '
+       git log -1 --notes --notes=alternate >output &&
+       grep xyzzy output &&
+       grep alternate output
+ '
+ test_expect_success 'git log --no-notes resets default state' '
+       git log -1 --notes --notes=alternate \
+               --no-notes --notes=alternate \
+               >output &&
+       ! grep xyzzy output &&
+       grep alternate output
+ '
+ test_expect_success 'git log --no-notes resets ref list' '
+       git log -1 --notes --notes=alternate \
+               --no-notes --notes \
+               >output &&
+       grep xyzzy output &&
+       ! grep alternate output
+ '
  test_expect_success 'create -m notes (setup)' '
        : > a5 &&
        git add a5 &&