]> git.ipfire.org Git - thirdparty/git.git/commitdiff
log: add log.excludeDecoration config option
authorDerrick Stolee <dstolee@microsoft.com>
Thu, 16 Apr 2020 14:15:49 +0000 (14:15 +0000)
committerJunio C Hamano <gitster@pobox.com>
Thu, 16 Apr 2020 18:05:48 +0000 (11:05 -0700)
In 'git log', the --decorate-refs-exclude option appends a pattern
to a string_list. This list is used to prevent showing some refs
in the decoration output, or even by --simplify-by-decoration.

Users may want to use their refs space to store utility refs that
should not appear in the decoration output. For example, Scalar [1]
runs a background fetch but places the "new" refs inside the
refs/scalar/hidden/<remote>/* refspace instead of refs/<remote>/*
to avoid updating remote refs when the user is not looking. However,
these "hidden" refs appear during regular 'git log' queries.

A similar idea to use "hidden" refs is under consideration for core
Git [2].

Add the 'log.excludeDecoration' config option so users can exclude
some refs from decorations by default instead of needing to use
--decorate-refs-exclude manually. The config value is multi-valued
much like the command-line option. The documentation is careful to
point out that the config value can be overridden by the
--decorate-refs option, even though --decorate-refs-exclude would
always "win" over --decorate-refs.

Since the 'log.excludeDecoration' takes lower precedence to
--decorate-refs, and --decorate-refs-exclude takes higher
precedence, the struct decoration_filter needed another field.
This led also to new logic in load_ref_decorations() and
ref_filter_match().

There are several tests in t4202-log.sh that test the
--decorate-refs-(include|exclude) options, so these are extended.
Since the expected output is already stored as a file, most tests
could simply replace a "--decorate-refs-exclude" option with an
in-line config setting. Other tests involve the precedence of
the config option compared to command-line options and needed more
modification.

[1] https://github.com/microsoft/scalar
[2] https://lore.kernel.org/git/77b1da5d3063a2404cd750adfe3bb8be9b6c497d.1585946894.git.gitgitgadget@gmail.com/

Helped-by: Junio C Hamano <gister@pobox.com>
Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/config/log.txt
Documentation/git-log.txt
builtin/log.c
log-tree.c
log-tree.h
t/t4202-log.sh

index e9e1e397f3fd154511931f8c88e66c728b3cc07a..208d5fdcaa6894f6cc10177d8379afac6ff12e37 100644 (file)
@@ -18,6 +18,12 @@ log.decorate::
        names are shown. This is the same as the `--decorate` option
        of the `git log`.
 
+log.excludeDecoration::
+       Exclude the specified patterns from the log decorations. This is
+       similar to the `--decorate-refs-exclude` command-line option, but
+       the config option can be overridden by the `--decorate-refs`
+       option.
+
 log.follow::
        If `true`, `git log` will act as if the `--follow` option was used when
        a single <path> is given.  This has the same limitations as `--follow`,
index bed09bb09e52c6ddc0923e6173f6f5b5dceceb4a..17592234ba4d73514de3853dadca0a82a99d7401 100644 (file)
@@ -43,7 +43,10 @@ OPTIONS
        If no `--decorate-refs` is given, pretend as if all refs were
        included.  For each candidate, do not use it for decoration if it
        matches any patterns given to `--decorate-refs-exclude` or if it
-       doesn't match any of the patterns given to `--decorate-refs`.
+       doesn't match any of the patterns given to `--decorate-refs`. The
+       `log.excludeDecoration` config option allows excluding refs from
+       the decorations, but an explicit `--decorate-refs` pattern will
+       override a match in `log.excludeDecoration`.
 
 --source::
        Print out the ref name given on the command line by which each
index 83a4a6188e221caefc5028e59cb7c95c2f1d1e0c..72192710dcd93bcb4c4cead18b05f2354679cf56 100644 (file)
@@ -164,9 +164,11 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
        int quiet = 0, source = 0, mailmap;
        static struct line_opt_callback_data line_cb = {NULL, NULL, STRING_LIST_INIT_DUP};
        static struct string_list decorate_refs_exclude = STRING_LIST_INIT_NODUP;
+       static struct string_list decorate_refs_exclude_config = STRING_LIST_INIT_NODUP;
        static struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP;
        struct decoration_filter decoration_filter = {&decorate_refs_include,
-                                                     &decorate_refs_exclude};
+                                                     &decorate_refs_exclude,
+                                                     &decorate_refs_exclude_config};
        static struct revision_sources revision_sources;
 
        const struct option builtin_log_options[] = {
@@ -236,7 +238,19 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
        }
 
        if (decoration_style) {
+               const struct string_list *config_exclude =
+                       repo_config_get_value_multi(the_repository,
+                                                   "log.excludeDecoration");
+
+               if (config_exclude) {
+                       struct string_list_item *item;
+                       for_each_string_list_item(item, config_exclude)
+                               string_list_append(&decorate_refs_exclude_config,
+                                                  item->string);
+               }
+
                rev->show_decorations = 1;
+
                load_ref_decorations(&decoration_filter, decoration_style);
        }
 
index fa6af69da387269a07d69cebd757eafafe24c01c..1cfd34586118c86faec4b60b4cefdb30127f0e0d 100644 (file)
@@ -103,6 +103,8 @@ static int ref_filter_match(const char *refname,
        struct string_list_item *item;
        const struct string_list *exclude_patterns = filter->exclude_ref_pattern;
        const struct string_list *include_patterns = filter->include_ref_pattern;
+       const struct string_list *exclude_patterns_config =
+                               filter->exclude_ref_config_pattern;
 
        if (exclude_patterns && exclude_patterns->nr) {
                for_each_string_list_item(item, exclude_patterns) {
@@ -112,17 +114,20 @@ static int ref_filter_match(const char *refname,
        }
 
        if (include_patterns && include_patterns->nr) {
-               int found = 0;
                for_each_string_list_item(item, include_patterns) {
-                       if (match_ref_pattern(refname, item)) {
-                               found = 1;
-                               break;
-                       }
+                       if (match_ref_pattern(refname, item))
+                               return 1;
                }
+               return 0;
+       }
 
-               if (!found)
-                       return 0;
+       if (exclude_patterns_config && exclude_patterns_config->nr) {
+               for_each_string_list_item(item, exclude_patterns_config) {
+                       if (match_ref_pattern(refname, item))
+                               return 0;
+               }
        }
+
        return 1;
 }
 
@@ -198,6 +203,9 @@ void load_ref_decorations(struct decoration_filter *filter, int flags)
                        for_each_string_list_item(item, filter->include_ref_pattern) {
                                normalize_glob_ref(item, NULL, item->string);
                        }
+                       for_each_string_list_item(item, filter->exclude_ref_config_pattern) {
+                               normalize_glob_ref(item, NULL, item->string);
+                       }
                }
                decoration_loaded = 1;
                decoration_flags = flags;
index e66862807463a12e28573be04cbcfcf2d200e6f3..8fa79289ec6b6cb27e68534845d345caf40137ea 100644 (file)
@@ -8,7 +8,9 @@ struct log_info {
 };
 
 struct decoration_filter {
-       struct string_list *include_ref_pattern, *exclude_ref_pattern;
+       struct string_list *include_ref_pattern;
+       struct string_list *exclude_ref_pattern;
+       struct string_list *exclude_ref_config_pattern;
 };
 
 int parse_decorate_color_config(const char *var, const char *slot_name, const char *value);
index 5eeb739f3ed4bb44a8951fb223445ead15dc61c8..f1ea7d97f589c7746cf3a19908cdb23927c09067 100755 (executable)
@@ -742,7 +742,23 @@ test_expect_success 'decorate-refs with glob' '
        octopus-a (octopus-a)
        reach
        EOF
+       cat >expect.no-decorate <<-\EOF &&
+       Merge-tag-reach
+       Merge-tags-octopus-a-and-octopus-b
+       seventh
+       octopus-b
+       octopus-a
+       reach
+       EOF
+       git log -n6 --decorate=short --pretty="tformat:%f%d" \
+               --decorate-refs="heads/octopus*" >actual &&
+       test_cmp expect.decorate actual &&
        git log -n6 --decorate=short --pretty="tformat:%f%d" \
+               --decorate-refs-exclude="heads/octopus*" \
+               --decorate-refs="heads/octopus*" >actual &&
+       test_cmp expect.no-decorate actual &&
+       git -c log.excludeDecoration="heads/octopus*" log \
+               -n6 --decorate=short --pretty="tformat:%f%d" \
                --decorate-refs="heads/octopus*" >actual &&
        test_cmp expect.decorate actual
 '
@@ -787,6 +803,9 @@ test_expect_success 'decorate-refs-exclude with glob' '
        EOF
        git log -n6 --decorate=short --pretty="tformat:%f%d" \
                --decorate-refs-exclude="heads/octopus*" >actual &&
+       test_cmp expect.decorate actual &&
+       git -c log.excludeDecoration="heads/octopus*" log \
+               -n6 --decorate=short --pretty="tformat:%f%d" >actual &&
        test_cmp expect.decorate actual
 '
 
@@ -801,6 +820,9 @@ test_expect_success 'decorate-refs-exclude without globs' '
        EOF
        git log -n6 --decorate=short --pretty="tformat:%f%d" \
                --decorate-refs-exclude="tags/reach" >actual &&
+       test_cmp expect.decorate actual &&
+       git -c log.excludeDecoration="tags/reach" log \
+               -n6 --decorate=short --pretty="tformat:%f%d" >actual &&
        test_cmp expect.decorate actual
 '
 
@@ -816,11 +838,19 @@ test_expect_success 'multiple decorate-refs-exclude' '
        git log -n6 --decorate=short --pretty="tformat:%f%d" \
                --decorate-refs-exclude="heads/octopus*" \
                --decorate-refs-exclude="tags/reach" >actual &&
+       test_cmp expect.decorate actual &&
+       git -c log.excludeDecoration="heads/octopus*" \
+               -c log.excludeDecoration="tags/reach" log \
+               -n6 --decorate=short --pretty="tformat:%f%d" >actual &&
+       test_cmp expect.decorate actual &&
+       git -c log.excludeDecoration="heads/octopus*" log \
+               --decorate-refs-exclude="tags/reach" \
+               -n6 --decorate=short --pretty="tformat:%f%d" >actual &&
        test_cmp expect.decorate actual
 '
 
 test_expect_success 'decorate-refs and decorate-refs-exclude' '
-       cat >expect.decorate <<-\EOF &&
+       cat >expect.no-decorate <<-\EOF &&
        Merge-tag-reach (master)
        Merge-tags-octopus-a-and-octopus-b
        seventh
@@ -831,6 +861,21 @@ test_expect_success 'decorate-refs and decorate-refs-exclude' '
        git log -n6 --decorate=short --pretty="tformat:%f%d" \
                --decorate-refs="heads/*" \
                --decorate-refs-exclude="heads/oc*" >actual &&
+       test_cmp expect.no-decorate actual
+'
+
+test_expect_success 'deocrate-refs and log.excludeDecoration' '
+       cat >expect.decorate <<-\EOF &&
+       Merge-tag-reach (master)
+       Merge-tags-octopus-a-and-octopus-b
+       seventh
+       octopus-b (octopus-b)
+       octopus-a (octopus-a)
+       reach (reach)
+       EOF
+       git -c log.excludeDecoration="heads/oc*" log \
+               --decorate-refs="heads/*" \
+               -n6 --decorate=short --pretty="tformat:%f%d" >actual &&
        test_cmp expect.decorate actual
 '
 
@@ -846,6 +891,10 @@ test_expect_success 'decorate-refs-exclude and simplify-by-decoration' '
        git log -n6 --decorate=short --pretty="tformat:%f%d" \
                --decorate-refs-exclude="*octopus*" \
                --simplify-by-decoration >actual &&
+       test_cmp expect.decorate actual &&
+       git -c log.excludeDecoration="*octopus*" log \
+               -n6 --decorate=short --pretty="tformat:%f%d" \
+               --simplify-by-decoration >actual &&
        test_cmp expect.decorate actual
 '