Support showing notes from more than one notes tree
authorThomas Rast <trast@student.ethz.ch>
Fri, 12 Mar 2010 17:04:26 +0000 (18:04 +0100)
committerJunio C Hamano <gitster@pobox.com>
Sat, 13 Mar 2010 05:55:39 +0000 (21:55 -0800)
With this patch, you can set notes.displayRef to a glob that points at
your favourite notes refs, e.g.,

[notes]
displayRef = refs/notes/*

Then git-log and friends will show notes from all trees.

Thanks to Junio C Hamano for lots of feedback, which greatly
influenced the design of the entire series and this commit in
particular.

Signed-off-by: Thomas Rast <trast@student.ethz.ch>
Acked-by: Johan Herland <johan@herland.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
14 files changed:
Documentation/config.txt
Documentation/git-notes.txt
Documentation/pretty-options.txt
builtin-log.c
cache.h
notes.c
notes.h
pretty.c
refs.c
refs.h
revision.c
revision.h
t/t3301-notes.sh
t/test-lib.sh
index 8dcb19156623277a31992b5ee6818eca08bb9195..503942a2e4e929d999e1b483fc9862b1ef2e726d 100644 (file)
@@ -500,10 +500,12 @@ check that makes sure that existing object files will not get overwritten.
 core.notesRef::
        When showing commit messages, also show notes which are stored in
        the given ref.  This ref is expected to contain files named
 core.notesRef::
        When showing commit messages, also show notes which are stored in
        the given ref.  This ref is expected to contain files named
-       after the full SHA-1 of the commit they annotate.
+       after the full SHA-1 of the commit they annotate.  The ref
+       must be fully qualified.
 +
 If such a file exists in the given ref, the referenced blob is read, and
 +
 If such a file exists in the given ref, the referenced blob is read, and
-appended to the commit message, separated by a "Notes:" line.  If the
+appended to the commit message, separated by a "Notes (<refname>):"
+line (shortened to "Notes:" in the case of "refs/notes/commits").  If the
 given ref itself does not exist, it is not an error, but means that no
 notes should be printed.
 +
 given ref itself does not exist, it is not an error, but means that no
 notes should be printed.
 +
@@ -1286,6 +1288,23 @@ mergetool.keepTemporaries::
 mergetool.prompt::
        Prompt before each invocation of the merge resolution program.
 
 mergetool.prompt::
        Prompt before each invocation of the merge resolution program.
 
+notes.displayRef::
+       The (fully qualified) refname from which to show notes when
+       showing commit messages.  The value of this variable can be set
+       to a glob, in which case notes from all matching refs will be
+       shown.  You may also specify this configuration variable
+       several times.  A warning will be issued for refs that do not
+       exist, but a glob that does not match any refs is silently
+       ignored.
++
+This setting can be overridden with the `GIT_NOTES_DISPLAY_REF`
+environment variable, which must be a colon separated list of refs or
+globs.
++
+The effective value of "core.notesRef" (possibly overridden by
+GIT_NOTES_REF) is also implicitly added to the list of refs to be
+displayed.
+
 pack.window::
        The size of the window used by linkgit:git-pack-objects[1] when no
        window size is given on the command line. Defaults to 10.
 pack.window::
        The size of the window used by linkgit:git-pack-objects[1] when no
        window size is given on the command line. Defaults to 10.
index 14f73b988e556ecce1bea8a1dacf7284966832ae..7abd0fbd2373b737fbdbdac3f4cc1616a6c7fbbf 100644 (file)
@@ -27,12 +27,13 @@ A typical use of notes is to extend a commit message without having
 to change the commit itself. Such commit notes can be shown by `git log`
 along with the original commit message. To discern these notes from the
 message stored in the commit object, the notes are indented like the
 to change the commit itself. Such commit notes can be shown by `git log`
 along with the original commit message. To discern these notes from the
 message stored in the commit object, the notes are indented like the
-message, after an unindented line saying "Notes:".
+message, after an unindented line saying "Notes (<refname>):" (or
+"Notes:" for the default setting).
 
 
-To disable notes, you have to set the config variable core.notesRef to
-the empty string.  Alternatively, you can set it to a different ref,
-something like "refs/notes/bugzilla".  This setting can be overridden
-by the environment variable "GIT_NOTES_REF".
+This command always manipulates the notes specified in "core.notesRef"
+(see linkgit:git-config[1]), which can be overridden by GIT_NOTES_REF.
+To change which notes are shown by 'git-log', see the
+"notes.displayRef" configuration.
 
 
 SUBCOMMANDS
 
 
 SUBCOMMANDS
index aa96caeab26ee6132adbef03d2ca17e91f634208..af6d2b995a050007ae088dec8e2c3474e9f06ad5 100644 (file)
@@ -30,9 +30,18 @@ people using 80-column terminals.
        defaults to UTF-8.
 
 --no-notes::
        defaults to UTF-8.
 
 --no-notes::
---show-notes::
+--show-notes[=<ref>]::
        Show the notes (see linkgit:git-notes[1]) that annotate the
        commit, when showing the commit log message.  This is the default
        for `git log`, `git show` and `git whatchanged` commands when
        there is no `--pretty`, `--format` nor `--oneline` option is
        given on the command line.
        Show the notes (see linkgit:git-notes[1]) that annotate the
        commit, when showing the commit log message.  This is the default
        for `git log`, `git show` and `git whatchanged` commands when
        there is no `--pretty`, `--format` nor `--oneline` option is
        given on the command line.
++
+With an optional argument, add this ref to the list of notes.  The ref
+is taken to be in `refs/notes/` if it is not qualified.
+
+--[no-]standard-notes::
+       Enable or disable populating the notes ref list from the
+       'core.notesRef' and 'notes.displayRef' variables (or
+       corresponding environment overrides).  Enabled by default.
+       See linkgit:git-config[1].
index 8d16832f7e9483f7903009459a72efc39e267c98..dc09253ef107bcfba4ea41d872e963150da90d77 100644 (file)
@@ -60,6 +60,8 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix,
 
        if (!rev->show_notes_given && !rev->pretty_given)
                rev->show_notes = 1;
 
        if (!rev->show_notes_given && !rev->pretty_given)
                rev->show_notes = 1;
+       if (rev->show_notes)
+               init_display_notes(&rev->notes_opt);
 
        if (rev->diffopt.pickaxe || rev->diffopt.filter)
                rev->always_show_header = 0;
 
        if (rev->diffopt.pickaxe || rev->diffopt.filter)
                rev->always_show_header = 0;
@@ -1059,6 +1061,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
        if (!DIFF_OPT_TST(&rev.diffopt, TEXT) && !no_binary_diff)
                DIFF_OPT_SET(&rev.diffopt, BINARY);
 
        if (!DIFF_OPT_TST(&rev.diffopt, TEXT) && !no_binary_diff)
                DIFF_OPT_SET(&rev.diffopt, BINARY);
 
+       if (rev.show_notes)
+               init_display_notes(&rev.notes_opt);
+
        if (!use_stdout)
                output_directory = set_outdir(prefix, output_directory);
 
        if (!use_stdout)
                output_directory = set_outdir(prefix, output_directory);
 
diff --git a/cache.h b/cache.h
index 4b15042c08afb2ba34ca6d08ebc5ca9b196ab7c8..fab53d66e4add0747c32086cfc91084869c19c0d 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -385,6 +385,7 @@ static inline enum object_type object_type(unsigned int mode)
 #define ATTRIBUTE_MACRO_PREFIX "[attr]"
 #define GIT_NOTES_REF_ENVIRONMENT "GIT_NOTES_REF"
 #define GIT_NOTES_DEFAULT_REF "refs/notes/commits"
 #define ATTRIBUTE_MACRO_PREFIX "[attr]"
 #define GIT_NOTES_REF_ENVIRONMENT "GIT_NOTES_REF"
 #define GIT_NOTES_DEFAULT_REF "refs/notes/commits"
+#define GIT_NOTES_DISPLAY_REF_ENVIRONMENT "GIT_NOTES_DISPLAY_REF"
 
 extern int is_bare_repository_cfg;
 extern int is_bare_repository(void);
 
 extern int is_bare_repository_cfg;
 extern int is_bare_repository(void);
diff --git a/notes.c b/notes.c
index 3ba3e6de17a562f309e6d8c64d609768fd740110..225a16608a516f6a4f9563727874174dbe03287b 100644 (file)
--- a/notes.c
+++ b/notes.c
@@ -5,6 +5,8 @@
 #include "utf8.h"
 #include "strbuf.h"
 #include "tree-walk.h"
 #include "utf8.h"
 #include "strbuf.h"
 #include "tree-walk.h"
+#include "string-list.h"
+#include "refs.h"
 
 /*
  * Use a non-balancing simple 16-tree structure with struct int_node as
 
 /*
  * Use a non-balancing simple 16-tree structure with struct int_node as
@@ -68,6 +70,9 @@ struct non_note {
 
 struct notes_tree default_notes_tree;
 
 
 struct notes_tree default_notes_tree;
 
+static struct string_list display_notes_refs;
+static struct notes_tree **display_notes_trees;
+
 static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,
                struct int_node *node, unsigned int n);
 
 static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,
                struct int_node *node, unsigned int n);
 
@@ -828,6 +833,83 @@ int combine_notes_ignore(unsigned char *cur_sha1,
        return 0;
 }
 
        return 0;
 }
 
+static int string_list_add_one_ref(const char *path, const unsigned char *sha1,
+                                  int flag, void *cb)
+{
+       struct string_list *refs = cb;
+       if (!unsorted_string_list_has_string(refs, path))
+               string_list_append(path, refs);
+       return 0;
+}
+
+void string_list_add_refs_by_glob(struct string_list *list, const char *glob)
+{
+       if (has_glob_specials(glob)) {
+               for_each_glob_ref(string_list_add_one_ref, glob, list);
+       } else {
+               unsigned char sha1[20];
+               if (get_sha1(glob, sha1))
+                       warning("notes ref %s is invalid", glob);
+               if (!unsorted_string_list_has_string(list, glob))
+                       string_list_append(glob, list);
+       }
+}
+
+void string_list_add_refs_from_colon_sep(struct string_list *list,
+                                        const char *globs)
+{
+       struct strbuf globbuf = STRBUF_INIT;
+       struct strbuf **split;
+       int i;
+
+       strbuf_addstr(&globbuf, globs);
+       split = strbuf_split(&globbuf, ':');
+
+       for (i = 0; split[i]; i++) {
+               if (!split[i]->len)
+                       continue;
+               if (split[i]->buf[split[i]->len-1] == ':')
+                       strbuf_setlen(split[i], split[i]->len-1);
+               string_list_add_refs_by_glob(list, split[i]->buf);
+       }
+
+       strbuf_list_free(split);
+       strbuf_release(&globbuf);
+}
+
+static int string_list_add_refs_from_list(struct string_list_item *item,
+                                         void *cb)
+{
+       struct string_list *list = cb;
+       string_list_add_refs_by_glob(list, item->string);
+       return 0;
+}
+
+static int notes_display_config(const char *k, const char *v, void *cb)
+{
+       int *load_refs = cb;
+
+       if (*load_refs && !strcmp(k, "notes.displayref")) {
+               if (!v)
+                       config_error_nonbool(k);
+               string_list_add_refs_by_glob(&display_notes_refs, v);
+       }
+
+       return 0;
+}
+
+static const char *default_notes_ref(void)
+{
+       const char *notes_ref = NULL;
+       if (!notes_ref)
+               notes_ref = getenv(GIT_NOTES_REF_ENVIRONMENT);
+       if (!notes_ref)
+               notes_ref = notes_ref_name; /* value of core.notesRef config */
+       if (!notes_ref)
+               notes_ref = GIT_NOTES_DEFAULT_REF;
+       return notes_ref;
+}
+
 void init_notes(struct notes_tree *t, const char *notes_ref,
                combine_notes_fn combine_notes, int flags)
 {
 void init_notes(struct notes_tree *t, const char *notes_ref,
                combine_notes_fn combine_notes, int flags)
 {
@@ -840,11 +922,7 @@ void init_notes(struct notes_tree *t, const char *notes_ref,
        assert(!t->initialized);
 
        if (!notes_ref)
        assert(!t->initialized);
 
        if (!notes_ref)
-               notes_ref = getenv(GIT_NOTES_REF_ENVIRONMENT);
-       if (!notes_ref)
-               notes_ref = notes_ref_name; /* value of core.notesRef config */
-       if (!notes_ref)
-               notes_ref = GIT_NOTES_DEFAULT_REF;
+               notes_ref = default_notes_ref();
 
        if (!combine_notes)
                combine_notes = combine_notes_concatenate;
 
        if (!combine_notes)
                combine_notes = combine_notes_concatenate;
@@ -868,6 +946,63 @@ void init_notes(struct notes_tree *t, const char *notes_ref,
        load_subtree(t, &root_tree, t->root, 0);
 }
 
        load_subtree(t, &root_tree, t->root, 0);
 }
 
+struct load_notes_cb_data {
+       int counter;
+       struct notes_tree **trees;
+};
+
+static int load_one_display_note_ref(struct string_list_item *item,
+                                    void *cb_data)
+{
+       struct load_notes_cb_data *c = cb_data;
+       struct notes_tree *t = xcalloc(1, sizeof(struct notes_tree));
+       init_notes(t, item->string, combine_notes_ignore, 0);
+       c->trees[c->counter++] = t;
+       return 0;
+}
+
+struct notes_tree **load_notes_trees(struct string_list *refs)
+{
+       struct notes_tree **trees;
+       struct load_notes_cb_data cb_data;
+       trees = xmalloc((refs->nr+1) * sizeof(struct notes_tree *));
+       cb_data.counter = 0;
+       cb_data.trees = trees;
+       for_each_string_list(load_one_display_note_ref, refs, &cb_data);
+       trees[cb_data.counter] = NULL;
+       return trees;
+}
+
+void init_display_notes(struct display_notes_opt *opt)
+{
+       char *display_ref_env;
+       int load_config_refs = 0;
+       display_notes_refs.strdup_strings = 1;
+
+       assert(!display_notes_trees);
+
+       if (!opt || !opt->suppress_default_notes) {
+               string_list_append(default_notes_ref(), &display_notes_refs);
+               display_ref_env = getenv(GIT_NOTES_DISPLAY_REF_ENVIRONMENT);
+               if (display_ref_env) {
+                       string_list_add_refs_from_colon_sep(&display_notes_refs,
+                                                           display_ref_env);
+                       load_config_refs = 0;
+               } else
+                       load_config_refs = 1;
+       }
+
+       git_config(notes_display_config, &load_config_refs);
+
+       if (opt && opt->extra_notes_refs)
+               for_each_string_list(string_list_add_refs_from_list,
+                                    opt->extra_notes_refs,
+                                    &display_notes_refs);
+
+       display_notes_trees = load_notes_trees(&display_notes_refs);
+       string_list_clear(&display_notes_refs, 0);
+}
+
 void add_note(struct notes_tree *t, const unsigned char *object_sha1,
                const unsigned char *note_sha1, combine_notes_fn combine_notes)
 {
 void add_note(struct notes_tree *t, const unsigned char *object_sha1,
                const unsigned char *note_sha1, combine_notes_fn combine_notes)
 {
@@ -1016,8 +1151,18 @@ void format_note(struct notes_tree *t, const unsigned char *object_sha1,
        if (msglen && msg[msglen - 1] == '\n')
                msglen--;
 
        if (msglen && msg[msglen - 1] == '\n')
                msglen--;
 
-       if (flags & NOTES_SHOW_HEADER)
-               strbuf_addstr(sb, "\nNotes:\n");
+       if (flags & NOTES_SHOW_HEADER) {
+               const char *ref = t->ref;
+               if (!ref || !strcmp(ref, GIT_NOTES_DEFAULT_REF)) {
+                       strbuf_addstr(sb, "\nNotes:\n");
+               } else {
+                       if (!prefixcmp(ref, "refs/"))
+                               ref += 5;
+                       if (!prefixcmp(ref, "notes/"))
+                               ref += 6;
+                       strbuf_addf(sb, "\nNotes (%s):\n", ref);
+               }
+       }
 
        for (msg_p = msg; msg_p < msg + msglen; msg_p += linelen + 1) {
                linelen = strchrnul(msg_p, '\n') - msg_p;
 
        for (msg_p = msg; msg_p < msg + msglen; msg_p += linelen + 1) {
                linelen = strchrnul(msg_p, '\n') - msg_p;
@@ -1030,3 +1175,13 @@ void format_note(struct notes_tree *t, const unsigned char *object_sha1,
 
        free(msg);
 }
 
        free(msg);
 }
+
+void format_display_notes(const unsigned char *object_sha1,
+                         struct strbuf *sb, const char *output_encoding, int flags)
+{
+       int i;
+       assert(display_notes_trees);
+       for (i = 0; display_notes_trees[i]; i++)
+               format_note(display_notes_trees[i], object_sha1, sb,
+                           output_encoding, flags);
+}
diff --git a/notes.h b/notes.h
index bad03ccab776d837751803623394667bfd1c7d11..2cc07409dbcfe36c71d25ae26dc20eff9bf89b6f 100644 (file)
--- a/notes.h
+++ b/notes.h
@@ -198,4 +198,59 @@ void free_notes(struct notes_tree *t);
 void format_note(struct notes_tree *t, const unsigned char *object_sha1,
                struct strbuf *sb, const char *output_encoding, int flags);
 
 void format_note(struct notes_tree *t, const unsigned char *object_sha1,
                struct strbuf *sb, const char *output_encoding, int flags);
 
+
+struct string_list;
+
+struct display_notes_opt {
+       int suppress_default_notes:1;
+       struct string_list *extra_notes_refs;
+};
+
+/*
+ * Load the notes machinery for displaying several notes trees.
+ *
+ * If 'opt' is not NULL, then it specifies additional settings for the
+ * displaying:
+ *
+ * - suppress_default_notes indicates that the notes from
+ *   core.notesRef and notes.displayRef should not be loaded.
+ *
+ * - extra_notes_refs may contain a list of globs (in the same style
+ *   as notes.displayRef) where notes should be loaded from.
+ */
+void init_display_notes(struct display_notes_opt *opt);
+
+/*
+ * Append notes for the given 'object_sha1' from all trees set up by
+ * init_display_notes() to 'sb'.  The 'flags' are a bitwise
+ * combination of
+ *
+ * - NOTES_SHOW_HEADER: add a 'Notes (refname):' header
+ *
+ * - NOTES_INDENT: indent the notes by 4 places
+ *
+ * You *must* call init_display_notes() before using this function.
+ */
+void format_display_notes(const unsigned char *object_sha1,
+                         struct strbuf *sb, const char *output_encoding, int flags);
+
+/*
+ * Load the notes tree from each ref listed in 'refs'.  The output is
+ * an array of notes_tree*, terminated by a NULL.
+ */
+struct notes_tree **load_notes_trees(struct string_list *refs);
+
+/*
+ * Add all refs that match 'glob' to the 'list'.
+ */
+void string_list_add_refs_by_glob(struct string_list *list, const char *glob);
+
+/*
+ * Add all refs from a colon-separated glob list 'globs' to the end of
+ * 'list'.  Empty components are ignored.  This helper is used to
+ * parse GIT_NOTES_DISPLAY_REF style environment variables.
+ */
+void string_list_add_refs_from_colon_sep(struct string_list *list,
+                                        const char *globs);
+
 #endif
 #endif
index f999485a54acdb63c699ee1fce00f80433889e81..6ba3da89b7d29ef35a6ac9215b4f3e0abe7a582f 100644 (file)
--- a/pretty.c
+++ b/pretty.c
@@ -775,7 +775,7 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
                }
                return 0;       /* unknown %g placeholder */
        case 'N':
                }
                return 0;       /* unknown %g placeholder */
        case 'N':
-               format_note(NULL, commit->object.sha1, sb,
+               format_display_notes(commit->object.sha1, sb,
                            git_log_output_encoding ? git_log_output_encoding
                                                    : git_commit_encoding, 0);
                return 1;
                            git_log_output_encoding ? git_log_output_encoding
                                                    : git_commit_encoding, 0);
                return 1;
@@ -1096,8 +1096,8 @@ void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,
                strbuf_addch(sb, '\n');
 
        if (context->show_notes)
                strbuf_addch(sb, '\n');
 
        if (context->show_notes)
-               format_note(NULL, commit->object.sha1, sb, encoding,
-                           NOTES_SHOW_HEADER | NOTES_INDENT);
+               format_display_notes(commit->object.sha1, sb, encoding,
+                                    NOTES_SHOW_HEADER | NOTES_INDENT);
 
        free(reencoded);
 }
 
        free(reencoded);
 }
diff --git a/refs.c b/refs.c
index 503a8c2bd0fa7e4fb825d543e007995701150948..5a860c41eb53b22f43163a86ccee71b24edfc099 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -695,7 +695,6 @@ int for_each_glob_ref_in(each_ref_fn fn, const char *pattern,
 {
        struct strbuf real_pattern = STRBUF_INIT;
        struct ref_filter filter;
 {
        struct strbuf real_pattern = STRBUF_INIT;
        struct ref_filter filter;
-       const char *has_glob_specials;
        int ret;
 
        if (!prefix && prefixcmp(pattern, "refs/"))
        int ret;
 
        if (!prefix && prefixcmp(pattern, "refs/"))
@@ -704,9 +703,8 @@ int for_each_glob_ref_in(each_ref_fn fn, const char *pattern,
                strbuf_addstr(&real_pattern, prefix);
        strbuf_addstr(&real_pattern, pattern);
 
                strbuf_addstr(&real_pattern, prefix);
        strbuf_addstr(&real_pattern, pattern);
 
-       has_glob_specials = strpbrk(pattern, "?*[");
-       if (!has_glob_specials) {
-               /* Append impiled '/' '*' if not present. */
+       if (!has_glob_specials(pattern)) {
+               /* Append implied '/' '*' if not present. */
                if (real_pattern.buf[real_pattern.len - 1] != '/')
                        strbuf_addch(&real_pattern, '/');
                /* No need to check for '*', there is none. */
                if (real_pattern.buf[real_pattern.len - 1] != '/')
                        strbuf_addch(&real_pattern, '/');
                /* No need to check for '*', there is none. */
diff --git a/refs.h b/refs.h
index f7648b9bd3b719936024678246d0603028e72aa7..4a18b083f52a15e5216d583644e590d666cae097 100644 (file)
--- a/refs.h
+++ b/refs.h
@@ -28,6 +28,11 @@ extern int for_each_replace_ref(each_ref_fn, void *);
 extern int for_each_glob_ref(each_ref_fn, const char *pattern, void *);
 extern int for_each_glob_ref_in(each_ref_fn, const char *pattern, const char* prefix, void *);
 
 extern int for_each_glob_ref(each_ref_fn, const char *pattern, void *);
 extern int for_each_glob_ref_in(each_ref_fn, const char *pattern, const char* prefix, void *);
 
+static inline const char *has_glob_specials(const char *pattern)
+{
+       return strpbrk(pattern, "?*[");
+}
+
 /* can be used to learn about broken ref and symref */
 extern int for_each_rawref(each_ref_fn, void *);
 
 /* can be used to learn about broken ref and symref */
 extern int for_each_rawref(each_ref_fn, void *);
 
index 1d3457cb6a296e5c4ff8f7452f8a12bdfcbaaa75..1c514d120bc1d54e2bfd2ebb094d5ee06a95a6fd 100644 (file)
@@ -12,6 +12,7 @@
 #include "patch-ids.h"
 #include "decorate.h"
 #include "log-tree.h"
 #include "patch-ids.h"
 #include "decorate.h"
 #include "log-tree.h"
+#include "string-list.h"
 
 volatile show_early_output_fn_t show_early_output;
 
 
 volatile show_early_output_fn_t show_early_output;
 
@@ -1176,9 +1177,29 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
        } else if (!strcmp(arg, "--show-notes")) {
                revs->show_notes = 1;
                revs->show_notes_given = 1;
        } else if (!strcmp(arg, "--show-notes")) {
                revs->show_notes = 1;
                revs->show_notes_given = 1;
+       } else if (!prefixcmp(arg, "--show-notes=")) {
+               struct strbuf buf = STRBUF_INIT;
+               revs->show_notes = 1;
+               revs->show_notes_given = 1;
+               if (!revs->notes_opt.extra_notes_refs)
+                       revs->notes_opt.extra_notes_refs = xcalloc(1, sizeof(struct string_list));
+               if (!prefixcmp(arg+13, "refs/"))
+                       /* happy */;
+               else if (!prefixcmp(arg+13, "notes/"))
+                       strbuf_addstr(&buf, "refs/");
+               else
+                       strbuf_addstr(&buf, "refs/notes/");
+               strbuf_addstr(&buf, arg+13);
+               string_list_append(strbuf_detach(&buf, NULL),
+                                  revs->notes_opt.extra_notes_refs);
        } else if (!strcmp(arg, "--no-notes")) {
                revs->show_notes = 0;
                revs->show_notes_given = 1;
        } else if (!strcmp(arg, "--no-notes")) {
                revs->show_notes = 0;
                revs->show_notes_given = 1;
+       } else if (!strcmp(arg, "--standard-notes")) {
+               revs->show_notes_given = 1;
+               revs->notes_opt.suppress_default_notes = 0;
+       } else if (!strcmp(arg, "--no-standard-notes")) {
+               revs->notes_opt.suppress_default_notes = 1;
        } else if (!strcmp(arg, "--oneline")) {
                revs->verbose_header = 1;
                get_commit_format("oneline", revs);
        } else if (!strcmp(arg, "--oneline")) {
                revs->verbose_header = 1;
                get_commit_format("oneline", revs);
index a14deefc252bd641fba5e16f7859b4a985a72578..580f6eccee9158ed6db4cda4deb26ee5dec4182c 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "parse-options.h"
 #include "grep.h"
 
 #include "parse-options.h"
 #include "grep.h"
+#include "notes.h"
 
 #define SEEN           (1u<<0)
 #define UNINTERESTING   (1u<<1)
 
 #define SEEN           (1u<<0)
 #define UNINTERESTING   (1u<<1)
@@ -20,6 +21,7 @@
 
 struct rev_info;
 struct log_info;
 
 struct rev_info;
 struct log_info;
+struct string_list;
 
 struct rev_info {
        /* Starting list */
 
 struct rev_info {
        /* Starting list */
@@ -126,6 +128,9 @@ struct rev_info {
        struct reflog_walk_info *reflog_info;
        struct decoration children;
        struct decoration merge_simplification;
        struct reflog_walk_info *reflog_info;
        struct decoration children;
        struct decoration merge_simplification;
+
+       /* notes-specific options: which refs to show */
+       struct display_notes_opt notes_opt;
 };
 
 #define REV_TREE_SAME          0
 };
 
 #define REV_TREE_SAME          0
index 90178f96d29597a886da1f64f95176116294554a..cb7166f6ecc77056d6a5a1626cb97c22b99db5f9 100755 (executable)
@@ -415,7 +415,7 @@ Date:   Thu Apr 7 15:18:13 2005 -0700
 
     6th
 
 
     6th
 
-Notes:
+Notes (other):
     other note
 EOF
 
     other note
 EOF
 
@@ -448,7 +448,139 @@ test_expect_success 'Do not show note when core.notesRef is overridden' '
        test_cmp expect-not-other output
 '
 
        test_cmp expect-not-other output
 '
 
+cat > expect-both << EOF
+commit 387a89921c73d7ed72cd94d179c1c7048ca47756
+Author: A U Thor <author@example.com>
+Date:   Thu Apr 7 15:18:13 2005 -0700
+
+    6th
+
+Notes:
+    order test
+
+Notes (other):
+    other note
+
+commit bd1753200303d0a0344be813e504253b3d98e74d
+Author: A U Thor <author@example.com>
+Date:   Thu Apr 7 15:17:13 2005 -0700
+
+    5th
+
+Notes:
+    replacement for deleted note
+EOF
+
+test_expect_success 'Show all notes when notes.displayRef=refs/notes/*' '
+       GIT_NOTES_REF=refs/notes/commits git notes add \
+               -m"replacement for deleted note" HEAD^ &&
+       GIT_NOTES_REF=refs/notes/commits git notes add -m"order test" &&
+       git config --unset core.notesRef &&
+       git config notes.displayRef "refs/notes/*" &&
+       git log -2 > output &&
+       test_cmp expect-both output
+'
+
+test_expect_success 'core.notesRef is implicitly in notes.displayRef' '
+       git config core.notesRef refs/notes/commits &&
+       git config notes.displayRef refs/notes/other &&
+       git log -2 > output &&
+       test_cmp expect-both output
+'
+
+test_expect_success 'notes.displayRef can be given more than once' '
+       git config --unset core.notesRef &&
+       git config notes.displayRef refs/notes/commits &&
+       git config --add notes.displayRef refs/notes/other &&
+       git log -2 > output &&
+       test_cmp expect-both output
+'
+
+cat > expect-both-reversed << EOF
+commit 387a89921c73d7ed72cd94d179c1c7048ca47756
+Author: A U Thor <author@example.com>
+Date:   Thu Apr 7 15:18:13 2005 -0700
+
+    6th
+
+Notes (other):
+    other note
+
+Notes:
+    order test
+EOF
+
+test_expect_success 'notes.displayRef respects order' '
+       git config core.notesRef refs/notes/other &&
+       git config --unset-all notes.displayRef &&
+       git config notes.displayRef refs/notes/commits &&
+       git log -1 > output &&
+       test_cmp expect-both-reversed output
+'
+
+test_expect_success 'GIT_NOTES_DISPLAY_REF works' '
+       git config --unset-all core.notesRef &&
+       git config --unset-all notes.displayRef &&
+       GIT_NOTES_DISPLAY_REF=refs/notes/commits:refs/notes/other \
+               git log -2 > output &&
+       test_cmp expect-both output
+'
+
+cat > expect-none << EOF
+commit 387a89921c73d7ed72cd94d179c1c7048ca47756
+Author: A U Thor <author@example.com>
+Date:   Thu Apr 7 15:18:13 2005 -0700
+
+    6th
+
+commit bd1753200303d0a0344be813e504253b3d98e74d
+Author: A U Thor <author@example.com>
+Date:   Thu Apr 7 15:17:13 2005 -0700
+
+    5th
+EOF
+
+test_expect_success 'GIT_NOTES_DISPLAY_REF overrides config' '
+       git config notes.displayRef "refs/notes/*" &&
+       GIT_NOTES_REF= GIT_NOTES_DISPLAY_REF= git log -2 > output &&
+       test_cmp expect-none output
+'
+
+test_expect_success '--show-notes=* adds to GIT_NOTES_DISPLAY_REF' '
+       GIT_NOTES_REF= GIT_NOTES_DISPLAY_REF= git log --show-notes=* -2 > output &&
+       test_cmp expect-both output
+'
+
+cat > expect-commits << EOF
+commit 387a89921c73d7ed72cd94d179c1c7048ca47756
+Author: A U Thor <author@example.com>
+Date:   Thu Apr 7 15:18:13 2005 -0700
+
+    6th
+
+Notes:
+    order test
+EOF
+
+test_expect_success '--no-standard-notes' '
+       git log --no-standard-notes --show-notes=commits -1 > output &&
+       test_cmp expect-commits output
+'
+
+test_expect_success '--standard-notes' '
+       git log --no-standard-notes --show-notes=commits \
+               --standard-notes -2 > output &&
+       test_cmp expect-both output
+'
+
+test_expect_success '--show-notes=ref accumulates' '
+       git log --show-notes=other --show-notes=commits \
+                --no-standard-notes -1 > output &&
+       test_cmp expect-both-reversed output
+'
+
 test_expect_success 'Allow notes on non-commits (trees, blobs, tags)' '
 test_expect_success 'Allow notes on non-commits (trees, blobs, tags)' '
+       git config core.notesRef refs/notes/other &&
        echo "Note on a tree" > expect
        git notes add -m "Note on a tree" HEAD: &&
        git notes show HEAD: > actual &&
        echo "Note on a tree" > expect
        git notes add -m "Note on a tree" HEAD: &&
        git notes show HEAD: > actual &&
@@ -472,7 +604,7 @@ Date:   Thu Apr 7 15:19:13 2005 -0700
 
     7th
 
 
     7th
 
-Notes:
+Notes (other):
     other note
 EOF
 
     other note
 EOF
 
@@ -503,7 +635,7 @@ Date:   Thu Apr 7 15:21:13 2005 -0700
 
     9th
 
 
     9th
 
-Notes:
+Notes (other):
     yet another note
 EOF
 
     yet another note
 EOF
 
@@ -533,7 +665,7 @@ Date:   Thu Apr 7 15:21:13 2005 -0700
 
     9th
 
 
     9th
 
-Notes:
+Notes (other):
     yet another note
 $whitespace
     yet another note
     yet another note
 $whitespace
     yet another note
@@ -552,7 +684,7 @@ Date:   Thu Apr 7 15:22:13 2005 -0700
 
     10th
 
 
     10th
 
-Notes:
+Notes (other):
     other note
 EOF
 
     other note
 EOF
 
@@ -569,7 +701,7 @@ Date:   Thu Apr 7 15:22:13 2005 -0700
 
     10th
 
 
     10th
 
-Notes:
+Notes (other):
     other note
 $whitespace
     yet another note
     other note
 $whitespace
     yet another note
@@ -588,7 +720,7 @@ Date:   Thu Apr 7 15:23:13 2005 -0700
 
     11th
 
 
     11th
 
-Notes:
+Notes (other):
     other note
 $whitespace
     yet another note
     other note
 $whitespace
     yet another note
@@ -619,7 +751,7 @@ Date:   Thu Apr 7 15:23:13 2005 -0700
 
     11th
 
 
     11th
 
-Notes:
+Notes (other):
     yet another note
 $whitespace
     yet another note
     yet another note
 $whitespace
     yet another note
index 49f06d2b844548cc23d52a9b9e56648bdc0c52c5..90115863bcd7682faefda9fab336e86bd8527163 100644 (file)
@@ -55,6 +55,7 @@ unset GIT_CEILING_DIRECTORIES
 unset SHA1_FILE_DIRECTORIES
 unset SHA1_FILE_DIRECTORY
 unset GIT_NOTES_REF
 unset SHA1_FILE_DIRECTORIES
 unset SHA1_FILE_DIRECTORY
 unset GIT_NOTES_REF
+unset GIT_NOTES_DISPLAY_REF
 GIT_MERGE_VERBOSITY=5
 export GIT_MERGE_VERBOSITY
 export GIT_AUTHOR_EMAIL GIT_AUTHOR_NAME
 GIT_MERGE_VERBOSITY=5
 export GIT_MERGE_VERBOSITY
 export GIT_AUTHOR_EMAIL GIT_AUTHOR_NAME