log: add color.decorate.pseudoref config variable

Add the ability to show pseudorefs such as ORIG_HEAD and MERGE_HEAD in
log decorations. Add config variable color.decorate.pseudoref to
determine their color, defaulting to bold cyan, which is the same as
HEAD.

They will not be shown unless the default decoration filtering is
overridden with relevant log options such as --clear-decorations or
log.initialDecorationSet.

Signed-off-by: Andy Koppe <andy.koppe@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Andy Koppe
2023-10-23 23:11:43 +01:00
committed by Junio C Hamano
parent e19f171be8
commit 7dc6f5ada8
7 changed files with 54 additions and 17 deletions

View File

@ -92,6 +92,8 @@ color.decorate.<slot>::
the stash ref the stash ref
`ref`;; `ref`;;
any other refs (not shown by default) any other refs (not shown by default)
`pseudoref`;;
pseudorefs such as ORIG_HEAD or MERGE_HEAD (not shown by default)
`grafted`;; `grafted`;;
grafted and replaced commits grafted and replaced commits
`symbol`;; `symbol`;;
@ -99,7 +101,7 @@ color.decorate.<slot>::
-- --
+ +
(Variable `log.initialDecorationSet` or linkgit:git-log[1] option (Variable `log.initialDecorationSet` or linkgit:git-log[1] option
`--clear-decorations` can be used to show all refs.) `--clear-decorations` can be used to show all refs and pseudorefs.)
color.grep:: color.grep::
When set to `always`, always highlight matches. When `false` (or When set to `always`, always highlight matches. When `false` (or

View File

@ -56,6 +56,7 @@ enum decoration_type {
DECORATION_REF_STASH, DECORATION_REF_STASH,
DECORATION_REF, DECORATION_REF,
DECORATION_REF_HEAD, DECORATION_REF_HEAD,
DECORATION_REF_PSEUDO,
DECORATION_GRAFTED, DECORATION_GRAFTED,
DECORATION_SYMBOL, DECORATION_SYMBOL,
}; };

View File

@ -41,6 +41,7 @@ static char decoration_colors[][COLOR_MAXLEN] = {
[DECORATION_REF_STASH] = GIT_COLOR_BOLD_MAGENTA, [DECORATION_REF_STASH] = GIT_COLOR_BOLD_MAGENTA,
[DECORATION_REF] = GIT_COLOR_BOLD_MAGENTA, [DECORATION_REF] = GIT_COLOR_BOLD_MAGENTA,
[DECORATION_REF_HEAD] = GIT_COLOR_BOLD_CYAN, [DECORATION_REF_HEAD] = GIT_COLOR_BOLD_CYAN,
[DECORATION_REF_PSEUDO] = GIT_COLOR_BOLD_CYAN,
[DECORATION_GRAFTED] = GIT_COLOR_BOLD_BLUE, [DECORATION_GRAFTED] = GIT_COLOR_BOLD_BLUE,
[DECORATION_SYMBOL] = GIT_COLOR_NIL, [DECORATION_SYMBOL] = GIT_COLOR_NIL,
}; };
@ -52,6 +53,7 @@ static const char *color_decorate_slots[] = {
[DECORATION_REF_STASH] = "stash", [DECORATION_REF_STASH] = "stash",
[DECORATION_REF] = "ref", [DECORATION_REF] = "ref",
[DECORATION_REF_HEAD] = "HEAD", [DECORATION_REF_HEAD] = "HEAD",
[DECORATION_REF_PSEUDO] = "pseudoref",
[DECORATION_GRAFTED] = "grafted", [DECORATION_GRAFTED] = "grafted",
[DECORATION_SYMBOL] = "symbol", [DECORATION_SYMBOL] = "symbol",
}; };
@ -208,6 +210,27 @@ static int add_ref_decoration(const char *refname, const struct object_id *oid,
return 0; return 0;
} }
static int add_pseudoref_decoration(const char *refname,
const struct object_id *oid,
int flags UNUSED,
void *cb_data)
{
struct object *obj;
enum object_type objtype;
struct decoration_filter *filter = (struct decoration_filter *)cb_data;
if (filter && !ref_filter_match(refname, filter))
return 0;
objtype = oid_object_info(the_repository, oid, NULL);
if (objtype < 0)
return 0;
obj = lookup_object_by_type(the_repository, oid, objtype);
add_name_decoration(DECORATION_REF_PSEUDO, refname, obj);
return 0;
}
static int add_graft_decoration(const struct commit_graft *graft, static int add_graft_decoration(const struct commit_graft *graft,
void *cb_data UNUSED) void *cb_data UNUSED)
{ {
@ -236,6 +259,7 @@ void load_ref_decorations(struct decoration_filter *filter, int flags)
decoration_loaded = 1; decoration_loaded = 1;
decoration_flags = flags; decoration_flags = flags;
for_each_ref(add_ref_decoration, filter); for_each_ref(add_ref_decoration, filter);
for_each_pseudoref(add_pseudoref_decoration, filter);
head_ref(add_ref_decoration, filter); head_ref(add_ref_decoration, filter);
for_each_commit_graft(add_graft_decoration, filter); for_each_commit_graft(add_graft_decoration, filter);
} }

View File

@ -33,13 +33,13 @@ Date: Mon Jun 26 00:04:00 2006 +0000
Merge branch 'side' Merge branch 'side'
commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (refs/heads/side) commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (FETCH_HEAD, refs/heads/side)
Author: A U Thor <author@example.com> Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:03:00 2006 +0000 Date: Mon Jun 26 00:03:00 2006 +0000
Side Side
commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 (ORIG_HEAD)
Author: A U Thor <author@example.com> Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000 Date: Mon Jun 26 00:02:00 2006 +0000

View File

@ -33,13 +33,13 @@ Date: Mon Jun 26 00:04:00 2006 +0000
Merge branch 'side' Merge branch 'side'
commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (side) commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (FETCH_HEAD, side)
Author: A U Thor <author@example.com> Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:03:00 2006 +0000 Date: Mon Jun 26 00:03:00 2006 +0000
Side Side
commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 (ORIG_HEAD)
Author: A U Thor <author@example.com> Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000 Date: Mon Jun 26 00:02:00 2006 +0000

View File

@ -927,7 +927,7 @@ test_expect_success 'multiple decorate-refs' '
test_expect_success 'decorate-refs-exclude with glob' ' test_expect_success 'decorate-refs-exclude with glob' '
cat >expect.decorate <<-\EOF && cat >expect.decorate <<-\EOF &&
Merge-tag-reach (HEAD -> main) Merge-tag-reach (HEAD -> main)
Merge-tags-octopus-a-and-octopus-b Merge-tags-octopus-a-and-octopus-b (ORIG_HEAD)
seventh (tag: seventh) seventh (tag: seventh)
octopus-b (tag: octopus-b) octopus-b (tag: octopus-b)
octopus-a (tag: octopus-a) octopus-a (tag: octopus-a)
@ -944,7 +944,7 @@ test_expect_success 'decorate-refs-exclude with glob' '
test_expect_success 'decorate-refs-exclude without globs' ' test_expect_success 'decorate-refs-exclude without globs' '
cat >expect.decorate <<-\EOF && cat >expect.decorate <<-\EOF &&
Merge-tag-reach (HEAD -> main) Merge-tag-reach (HEAD -> main)
Merge-tags-octopus-a-and-octopus-b Merge-tags-octopus-a-and-octopus-b (ORIG_HEAD)
seventh (tag: seventh) seventh (tag: seventh)
octopus-b (tag: octopus-b, octopus-b) octopus-b (tag: octopus-b, octopus-b)
octopus-a (tag: octopus-a, octopus-a) octopus-a (tag: octopus-a, octopus-a)
@ -961,7 +961,7 @@ test_expect_success 'decorate-refs-exclude without globs' '
test_expect_success 'multiple decorate-refs-exclude' ' test_expect_success 'multiple decorate-refs-exclude' '
cat >expect.decorate <<-\EOF && cat >expect.decorate <<-\EOF &&
Merge-tag-reach (HEAD -> main) Merge-tag-reach (HEAD -> main)
Merge-tags-octopus-a-and-octopus-b Merge-tags-octopus-a-and-octopus-b (ORIG_HEAD)
seventh (tag: seventh) seventh (tag: seventh)
octopus-b (tag: octopus-b) octopus-b (tag: octopus-b)
octopus-a (tag: octopus-a) octopus-a (tag: octopus-a)
@ -1022,10 +1022,12 @@ test_expect_success 'decorate-refs-exclude and simplify-by-decoration' '
EOF EOF
git log -n6 --decorate=short --pretty="tformat:%f%d" \ git log -n6 --decorate=short --pretty="tformat:%f%d" \
--decorate-refs-exclude="*octopus*" \ --decorate-refs-exclude="*octopus*" \
--decorate-refs-exclude="ORIG_HEAD" \
--simplify-by-decoration >actual && --simplify-by-decoration >actual &&
test_cmp expect.decorate actual && test_cmp expect.decorate actual &&
git -c log.excludeDecoration="*octopus*" log \ git -c log.excludeDecoration="*octopus*" \
-n6 --decorate=short --pretty="tformat:%f%d" \ -c log.excludeDecoration="ORIG_HEAD" \
log -n6 --decorate=short --pretty="tformat:%f%d" \
--simplify-by-decoration >actual && --simplify-by-decoration >actual &&
test_cmp expect.decorate actual test_cmp expect.decorate actual
' '
@ -1067,9 +1069,10 @@ test_expect_success 'decorate-refs and simplify-by-decoration without output' '
test_cmp expect actual test_cmp expect actual
' '
test_expect_success 'decorate-refs-exclude HEAD' ' test_expect_success 'decorate-refs-exclude HEAD ORIG_HEAD' '
git log --decorate=full --oneline \ git log --decorate=full --oneline \
--decorate-refs-exclude="HEAD" >actual && --decorate-refs-exclude="HEAD" \
--decorate-refs-exclude="ORIG_HEAD" >actual &&
! grep HEAD actual ! grep HEAD actual
' '
@ -1107,7 +1110,7 @@ test_expect_success '--clear-decorations overrides defaults' '
cat >expect.all <<-\EOF && cat >expect.all <<-\EOF &&
Merge-tag-reach (HEAD -> refs/heads/main) Merge-tag-reach (HEAD -> refs/heads/main)
Merge-tags-octopus-a-and-octopus-b Merge-tags-octopus-a-and-octopus-b (ORIG_HEAD)
seventh (tag: refs/tags/seventh) seventh (tag: refs/tags/seventh)
octopus-b (tag: refs/tags/octopus-b, refs/heads/octopus-b) octopus-b (tag: refs/tags/octopus-b, refs/heads/octopus-b)
octopus-a (tag: refs/tags/octopus-a, refs/heads/octopus-a) octopus-a (tag: refs/tags/octopus-a, refs/heads/octopus-a)
@ -1139,7 +1142,7 @@ test_expect_success '--clear-decorations clears previous exclusions' '
cat >expect.all <<-\EOF && cat >expect.all <<-\EOF &&
Merge-tag-reach (HEAD -> refs/heads/main) Merge-tag-reach (HEAD -> refs/heads/main)
reach (tag: refs/tags/reach, refs/heads/reach) reach (tag: refs/tags/reach, refs/heads/reach)
Merge-tags-octopus-a-and-octopus-b Merge-tags-octopus-a-and-octopus-b (ORIG_HEAD)
octopus-b (tag: refs/tags/octopus-b, refs/heads/octopus-b) octopus-b (tag: refs/tags/octopus-b, refs/heads/octopus-b)
octopus-a (tag: refs/tags/octopus-a, refs/heads/octopus-a) octopus-a (tag: refs/tags/octopus-a, refs/heads/octopus-a)
seventh (tag: refs/tags/seventh) seventh (tag: refs/tags/seventh)

View File

@ -18,6 +18,7 @@ test_expect_success setup '
git config color.decorate.tag "reverse bold yellow" && git config color.decorate.tag "reverse bold yellow" &&
git config color.decorate.stash magenta && git config color.decorate.stash magenta &&
git config color.decorate.ref blue && git config color.decorate.ref blue &&
git config color.decorate.pseudoref "bold cyan" &&
git config color.decorate.grafted black && git config color.decorate.grafted black &&
git config color.decorate.symbol white && git config color.decorate.symbol white &&
git config color.decorate.HEAD cyan && git config color.decorate.HEAD cyan &&
@ -30,6 +31,7 @@ test_expect_success setup '
c_tag="<BOLD;REVERSE;YELLOW>" && c_tag="<BOLD;REVERSE;YELLOW>" &&
c_stash="<MAGENTA>" && c_stash="<MAGENTA>" &&
c_ref="<BLUE>" && c_ref="<BLUE>" &&
c_pseudoref="<BOLD;CYAN>" &&
c_HEAD="<CYAN>" && c_HEAD="<CYAN>" &&
c_grafted="<BLACK>" && c_grafted="<BLACK>" &&
c_symbol="<WHITE>" && c_symbol="<WHITE>" &&
@ -46,7 +48,10 @@ test_expect_success setup '
test_commit B && test_commit B &&
git tag v1.0 && git tag v1.0 &&
echo >>A.t && echo >>A.t &&
git stash save Changes to A.t git stash save Changes to A.t &&
git reset other/main &&
git reset ORIG_HEAD &&
git revert --no-commit @~
' '
cmp_filtered_decorations () { cmp_filtered_decorations () {
@ -63,17 +68,19 @@ ${c_symbol} -> ${c_reset}${c_branch}main${c_reset}${c_symbol}, ${c_reset}\
${c_tag}tag: ${c_reset}${c_tag}v1.0${c_reset}${c_symbol}, ${c_reset}\ ${c_tag}tag: ${c_reset}${c_tag}v1.0${c_reset}${c_symbol}, ${c_reset}\
${c_tag}tag: ${c_reset}${c_tag}B${c_reset}${c_symbol})${c_reset} B ${c_tag}tag: ${c_reset}${c_tag}B${c_reset}${c_symbol})${c_reset} B
${c_commit}COMMIT_ID${c_reset}${c_symbol} (${c_reset}\ ${c_commit}COMMIT_ID${c_reset}${c_symbol} (${c_reset}\
${c_pseudoref}ORIG_HEAD${c_reset}${c_symbol}, ${c_reset}\
${c_tag}tag: ${c_reset}${c_tag}A1${c_reset}${c_symbol}, ${c_reset}\ ${c_tag}tag: ${c_reset}${c_tag}A1${c_reset}${c_symbol}, ${c_reset}\
${c_remoteBranch}other/main${c_reset}${c_symbol})${c_reset} A1 ${c_remoteBranch}other/main${c_reset}${c_symbol})${c_reset} A1
${c_commit}COMMIT_ID${c_reset}${c_symbol} (${c_reset}\ ${c_commit}COMMIT_ID${c_reset}${c_symbol} (${c_reset}\
${c_stash}refs/stash${c_reset}${c_symbol})${c_reset} On main: Changes to A.t ${c_stash}refs/stash${c_reset}${c_symbol})${c_reset} On main: Changes to A.t
${c_commit}COMMIT_ID${c_reset}${c_symbol} (${c_reset}\ ${c_commit}COMMIT_ID${c_reset}${c_symbol} (${c_reset}\
${c_pseudoref}REVERT_HEAD${c_reset}${c_symbol}, ${c_reset}\
${c_tag}tag: ${c_reset}${c_tag}A${c_reset}${c_symbol}, ${c_reset}\ ${c_tag}tag: ${c_reset}${c_tag}A${c_reset}${c_symbol}, ${c_reset}\
${c_ref}refs/foo${c_reset}${c_symbol})${c_reset} A ${c_ref}refs/foo${c_reset}${c_symbol})${c_reset} A
EOF EOF
git log --first-parent --no-abbrev --decorate --clear-decorations \ git log --first-parent --no-abbrev --decorate --color=always \
--oneline --color=always --all >actual && --decorate-refs-exclude=FETCH_HEAD --oneline --all >actual &&
cmp_filtered_decorations cmp_filtered_decorations
' '