Skip to content

Commit 9215629

Browse files
derrickstoleegitster
authored andcommitted
log: add default decoration filter
When a user runs 'git log', they expect a certain set of helpful decorations. This includes: * The HEAD ref * Branches (refs/heads/) * Stashes (refs/stash) * Tags (refs/tags/) * Remote branches (refs/remotes/) * Replace refs (refs/replace/ or $GIT_REPLACE_REF_BASE) Each of these namespaces was selected due to existing test cases that verify these namespaces appear in the decorations. In particular, stashes and replace refs can have custom colors from the color.decorate.<slot> config option. While one test checks for a decoration from notes, it only applies to the tip of refs/notes/commit (or its configured ref name). Notes form their own kind of decoration instead. Modify the expected output for the tests in t4013 that expect this note decoration. There are several tests throughout the codebase that verify that --decorate-refs, --decorate-refs-exclude, and log.excludeDecoration work as designed and the tests continue to pass without intervention. However, there are other refs that are less helpful to show as decoration: * Prefetch refs (refs/prefetch/) * Rebase refs (refs/rebase-merge/ and refs/rebase-apply/) * Bundle refs (refs/bundle/) [!] [!] The bundle refs are part of a parallel series that bootstraps a repo from a bundle file, storing the bundle's refs into the repo's refs/bundle/ namespace. In the case of prefetch refs, 96eaffe (maintenance: set log.excludeDecoration durin prefetch, 2021-01-19) added logic to add refs/prefetch/ to the log.excludeDecoration config option. Additional feedback pointed out that having such a side-effect can be confusing and perhaps not helpful to users. Instead, we should hide these ref namespaces that are being used by Git for internal reasons but are not helpful for the users to see. The way to provide a seamless user experience without setting the config is to modify the default decoration filters to match our expectation of what refs the user actually wants to see. In builtin/log.c, after parsing the --decorate-refs and --decorate-refs-exclude options from the command-line, call set_default_decoration_filter(). This method populates the exclusions from log.excludeDecoration, then checks if the list of pattern modifications are empty. If none are specified, then the default set is restricted to the set of inclusions mentioned earlier (HEAD, branches, etc.). A previous change introduced the ref_namespaces array, which includes all of these currently-used namespaces. The 'decoration' value is non-zero when that namespace is associated with a special coloring and fits into the list of "expected" decorations as described above, which makes the implementation of this filter very simple. Note that the logic in ref_filter_match() in log-tree.c follows this matching pattern: 1. If there are exclusion patterns and the ref matches one, then ignore the decoration. 2. If there are inclusion patterns and the ref matches one, then definitely include the decoration. 3. If there are config-based exclusions from log.excludeDecoration and the ref matches one, then ignore the decoration. With this logic in mind, we need to ensure that we do not populate our new defaults if any of these filters are manually set. Specifically, if a user runs git -c log.excludeDecoration=HEAD log then we expect the HEAD decoration to not appear. If we left the default inclusions in the set, then HEAD would match that inclusion before reaching the config-based exclusions. A potential alternative would be to check the list of default inclusions at the end, after the config-based exclusions. This would still create a behavior change for some uses of --decorate-refs-exclude=<X>, and could be overwritten somewhat with --decorate-refs=refs/ and --decorate-refs=HEAD. However, it no longer becomes possible to include refs outside of the defaults while also excluding some using log.excludeDecoration. Another alternative would be to exclude the known namespaces that are not intended to be shown. This would reduce the visible effect of the change for expert users who use their own custom ref namespaces. The implementation change would be very simple to swap due to our use of ref_namespaces: int i; struct string_list *exclude = decoration_filter->exclude_ref_pattern; /* * No command-line or config options were given, so * populate with sensible defaults. */ for (i = 0; i < NAMESPACE__COUNT; i++) { if (ref_namespaces[i].decoration) continue; string_list_append(exclude, ref_namespaces[i].ref); } The main downside of this approach is that we expect to add new hidden namespaces in the future, and that means that Git versions will be less stable in how they behave as those namespaces are added. It is critical that we provide ways for expert users to disable this behavior change via command-line options and config keys. These changes will be implemented in a future change. Add a test that checks that the defaults are not added when --decorate-refs is specified. We verify this by showing that HEAD is not included as it normally would. Also add a test that shows that the default filter avoids the unwanted decorations from refs/prefetch, refs/rebase-merge, and refs/bundle. Signed-off-by: Derrick Stolee <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 94d421b commit 9215629

File tree

5 files changed

+64
-17
lines changed

5 files changed

+64
-17
lines changed

Documentation/git-log.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,16 @@ OPTIONS
4545

4646
--decorate-refs=<pattern>::
4747
--decorate-refs-exclude=<pattern>::
48-
If no `--decorate-refs` is given, pretend as if all refs were
49-
included. For each candidate, do not use it for decoration if it
48+
For each candidate reference, do not use it for decoration if it
5049
matches any patterns given to `--decorate-refs-exclude` or if it
5150
doesn't match any of the patterns given to `--decorate-refs`. The
5251
`log.excludeDecoration` config option allows excluding refs from
5352
the decorations, but an explicit `--decorate-refs` pattern will
5453
override a match in `log.excludeDecoration`.
54+
+
55+
If none of these options or config settings are given, then references are
56+
used as decoration if they match `HEAD`, `refs/heads/`, `refs/remotes/`,
57+
`refs/stash/`, or `refs/tags/`.
5558

5659
--source::
5760
Print out the ref name given on the command line by which each

builtin/log.c

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,37 @@ static void cmd_log_init_defaults(struct rev_info *rev)
162162
parse_date_format(default_date_mode, &rev->date_mode);
163163
}
164164

165+
static void set_default_decoration_filter(struct decoration_filter *decoration_filter)
166+
{
167+
int i;
168+
struct string_list *include = decoration_filter->include_ref_pattern;
169+
const struct string_list *config_exclude =
170+
git_config_get_value_multi("log.excludeDecoration");
171+
172+
if (config_exclude) {
173+
struct string_list_item *item;
174+
for_each_string_list_item(item, config_exclude)
175+
string_list_append(decoration_filter->exclude_ref_config_pattern,
176+
item->string);
177+
}
178+
179+
if (decoration_filter->exclude_ref_pattern->nr ||
180+
decoration_filter->include_ref_pattern->nr ||
181+
decoration_filter->exclude_ref_config_pattern->nr)
182+
return;
183+
184+
/*
185+
* No command-line or config options were given, so
186+
* populate with sensible defaults.
187+
*/
188+
for (i = 0; i < ARRAY_SIZE(ref_namespace); i++) {
189+
if (!ref_namespace[i].decoration)
190+
continue;
191+
192+
string_list_append(include, ref_namespace[i].ref);
193+
}
194+
}
195+
165196
static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
166197
struct rev_info *rev, struct setup_revision_opt *opt)
167198
{
@@ -171,9 +202,11 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
171202
static struct string_list decorate_refs_exclude = STRING_LIST_INIT_NODUP;
172203
static struct string_list decorate_refs_exclude_config = STRING_LIST_INIT_NODUP;
173204
static struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP;
174-
struct decoration_filter decoration_filter = {&decorate_refs_include,
175-
&decorate_refs_exclude,
176-
&decorate_refs_exclude_config};
205+
struct decoration_filter decoration_filter = {
206+
.exclude_ref_pattern = &decorate_refs_exclude,
207+
.include_ref_pattern = &decorate_refs_include,
208+
.exclude_ref_config_pattern = &decorate_refs_exclude_config,
209+
};
177210
static struct revision_sources revision_sources;
178211

179212
const struct option builtin_log_options[] = {
@@ -265,16 +298,7 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
265298
}
266299

267300
if (decoration_style || rev->simplify_by_decoration) {
268-
const struct string_list *config_exclude =
269-
repo_config_get_value_multi(the_repository,
270-
"log.excludeDecoration");
271-
272-
if (config_exclude) {
273-
struct string_list_item *item;
274-
for_each_string_list_item(item, config_exclude)
275-
string_list_append(&decorate_refs_exclude_config,
276-
item->string);
277-
}
301+
set_default_decoration_filter(&decoration_filter);
278302

279303
if (decoration_style)
280304
rev->show_decorations = 1;

t/t4013/diff.log_--decorate=full_--all

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Date: Mon Jun 26 00:06:00 2006 +0000
2020

2121
Rearranged lines in dir/sub
2222

23-
commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0 (refs/notes/commits)
23+
commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0
2424
Author: A U Thor <[email protected]>
2525
Date: Mon Jun 26 00:06:00 2006 +0000
2626

t/t4013/diff.log_--decorate_--all

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Date: Mon Jun 26 00:06:00 2006 +0000
2020

2121
Rearranged lines in dir/sub
2222

23-
commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0 (refs/notes/commits)
23+
commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0
2424
Author: A U Thor <[email protected]>
2525
Date: Mon Jun 26 00:06:00 2006 +0000
2626

t/t4202-log.sh

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,6 +1031,12 @@ test_expect_success 'decorate-refs-exclude HEAD' '
10311031
! grep HEAD actual
10321032
'
10331033

1034+
test_expect_success 'decorate-refs focus from default' '
1035+
git log --decorate=full --oneline \
1036+
--decorate-refs="refs/heads" >actual &&
1037+
! grep HEAD actual
1038+
'
1039+
10341040
test_expect_success 'log.decorate config parsing' '
10351041
git log --oneline --decorate=full >expect.full &&
10361042
git log --oneline --decorate=short >expect.short &&
@@ -2198,6 +2204,20 @@ test_expect_success 'log --decorate includes all levels of tag annotated tags' '
21982204
test_cmp expect actual
21992205
'
22002206

2207+
test_expect_success 'log --decorate does not include things outside filter' '
2208+
reflist="refs/prefetch refs/rebase-merge refs/bundle" &&
2209+
2210+
for ref in $reflist
2211+
do
2212+
git update-ref $ref/fake HEAD || return 1
2213+
done &&
2214+
2215+
git log --decorate=full --oneline >actual &&
2216+
2217+
# None of the refs are visible:
2218+
! grep /fake actual
2219+
'
2220+
22012221
test_expect_success 'log --end-of-options' '
22022222
git update-ref refs/heads/--source HEAD &&
22032223
git log --end-of-options --source >actual &&

0 commit comments

Comments
 (0)