From 3f5b7ec4a5898e01ad84f8b63949374b4d730970 Mon Sep 17 00:00:00 2001 From: Andy Koppe Date: Mon, 23 Oct 2023 23:11:37 +0100 Subject: [PATCH 1/7] config: restructure color.decorate documentation List color.decorate slots in git-config documentation one-by-one in the same way as color.grep slots, to aid readability and make it easier to add slots. Signed-off-by: Andy Koppe Signed-off-by: Junio C Hamano --- Documentation/config/color.txt | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/Documentation/config/color.txt b/Documentation/config/color.txt index 1795b2d16b..3453703f9b 100644 --- a/Documentation/config/color.txt +++ b/Documentation/config/color.txt @@ -74,10 +74,25 @@ color.diff.:: `oldBold`, and `newBold` (see linkgit:git-range-diff[1] for details). color.decorate.:: - Use customized color for 'git log --decorate' output. `` is one - of `branch`, `remoteBranch`, `tag`, `stash` or `HEAD` for local - branches, remote-tracking branches, tags, stash and HEAD, respectively - and `grafted` for grafted commits. + Use customized color for the output of 'git log --decorate' as well as + the `%d`, `%D` and `%(decorate)` placeholders in custom log formats, + whereby `` specifies which decoration elements the color applies + to: ++ +-- +`HEAD`;; + the current HEAD +`branch`;; + local branches +`remoteBranch`;; + remote-tracking branches +`tag`;; + lightweight and annotated tags +`stash`;; + the stash ref +`grafted`;; + grafted and replaced commits +-- color.grep:: When set to `always`, always highlight matches. When `false` (or From 35506f5681b2332399d5ab84c7a2f7c04c46dfe4 Mon Sep 17 00:00:00 2001 From: Andy Koppe Date: Mon, 23 Oct 2023 23:11:38 +0100 Subject: [PATCH 2/7] log: use designated inits for decoration_colors Use designated initializers instead of comments to denote the slots in the decoration_colors array for holding color settings, to make it consistent with the immediately following color_decorate_slots array and reduce the likelihood of mistakes when extending them. Signed-off-by: Andy Koppe Signed-off-by: Junio C Hamano --- log-tree.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/log-tree.c b/log-tree.c index 504da6b519..8bdf889f02 100644 --- a/log-tree.c +++ b/log-tree.c @@ -34,13 +34,13 @@ static int decoration_loaded; static int decoration_flags; static char decoration_colors[][COLOR_MAXLEN] = { - GIT_COLOR_RESET, - GIT_COLOR_BOLD_GREEN, /* REF_LOCAL */ - GIT_COLOR_BOLD_RED, /* REF_REMOTE */ - GIT_COLOR_BOLD_YELLOW, /* REF_TAG */ - GIT_COLOR_BOLD_MAGENTA, /* REF_STASH */ - GIT_COLOR_BOLD_CYAN, /* REF_HEAD */ - GIT_COLOR_BOLD_BLUE, /* GRAFTED */ + [DECORATION_NONE] = GIT_COLOR_RESET, + [DECORATION_REF_LOCAL] = GIT_COLOR_BOLD_GREEN, + [DECORATION_REF_REMOTE] = GIT_COLOR_BOLD_RED, + [DECORATION_REF_TAG] = GIT_COLOR_BOLD_YELLOW, + [DECORATION_REF_STASH] = GIT_COLOR_BOLD_MAGENTA, + [DECORATION_REF_HEAD] = GIT_COLOR_BOLD_CYAN, + [DECORATION_GRAFTED] = GIT_COLOR_BOLD_BLUE, }; static const char *color_decorate_slots[] = { From 5a446c38a7caa2f5ff13401a3600f7275a8f7562 Mon Sep 17 00:00:00 2001 From: Andy Koppe Date: Mon, 23 Oct 2023 23:11:39 +0100 Subject: [PATCH 3/7] log: add color.decorate.symbol config variable Add new color.decorate.symbol config variable for determining the color of the prefix, suffix, separator and pointer symbols used in log --decorate output and related log format placeholders, to allow them to be colored differently from commit hashes. For backward compatibility, fall back to the commit hash color that can be specified with the color.diff.commit variable if the new variable is not provided. Add the variable to the color.decorate. documentation. Amend t4207-log-decoration-colors.sh to test it. Put ${c_reset} elements in the expected output at the end of lines for consistency. Signed-off-by: Andy Koppe Signed-off-by: Junio C Hamano --- Documentation/config/color.txt | 2 ++ commit.h | 1 + log-tree.c | 15 ++++++--- t/t4207-log-decoration-colors.sh | 58 +++++++++++++++++--------------- 4 files changed, 43 insertions(+), 33 deletions(-) diff --git a/Documentation/config/color.txt b/Documentation/config/color.txt index 3453703f9b..cc0a881125 100644 --- a/Documentation/config/color.txt +++ b/Documentation/config/color.txt @@ -92,6 +92,8 @@ color.decorate.:: the stash ref `grafted`;; grafted and replaced commits +`symbol`;; + punctuation symbols surrounding the other elements -- color.grep:: diff --git a/commit.h b/commit.h index 28928833c5..cb13e4d5ba 100644 --- a/commit.h +++ b/commit.h @@ -56,6 +56,7 @@ enum decoration_type { DECORATION_REF_STASH, DECORATION_REF_HEAD, DECORATION_GRAFTED, + DECORATION_SYMBOL, }; void add_name_decoration(enum decoration_type type, const char *name, struct object *obj); diff --git a/log-tree.c b/log-tree.c index 8bdf889f02..890024f205 100644 --- a/log-tree.c +++ b/log-tree.c @@ -41,6 +41,7 @@ static char decoration_colors[][COLOR_MAXLEN] = { [DECORATION_REF_STASH] = GIT_COLOR_BOLD_MAGENTA, [DECORATION_REF_HEAD] = GIT_COLOR_BOLD_CYAN, [DECORATION_GRAFTED] = GIT_COLOR_BOLD_BLUE, + [DECORATION_SYMBOL] = GIT_COLOR_NIL, }; static const char *color_decorate_slots[] = { @@ -50,6 +51,7 @@ static const char *color_decorate_slots[] = { [DECORATION_REF_STASH] = "stash", [DECORATION_REF_HEAD] = "HEAD", [DECORATION_GRAFTED] = "grafted", + [DECORATION_SYMBOL] = "symbol", }; static const char *decorate_get_color(int decorate_use_color, enum decoration_type ix) @@ -312,7 +314,7 @@ void format_decorations(struct strbuf *sb, { const struct name_decoration *decoration; const struct name_decoration *current_and_HEAD; - const char *color_commit, *color_reset; + const char *color_symbol, *color_reset; const char *prefix = " ("; const char *suffix = ")"; @@ -337,7 +339,10 @@ void format_decorations(struct strbuf *sb, tag = opts->tag; } - color_commit = diff_get_color(use_color, DIFF_COMMIT); + color_symbol = decorate_get_color(use_color, DECORATION_SYMBOL); + if (color_is_nil(color_symbol)) + color_symbol = diff_get_color(use_color, DIFF_COMMIT); + color_reset = decorate_get_color(use_color, DECORATION_NONE); current_and_HEAD = current_pointed_by_HEAD(decoration); @@ -352,7 +357,7 @@ void format_decorations(struct strbuf *sb, decorate_get_color(use_color, decoration->type); if (*prefix) { - strbuf_addstr(sb, color_commit); + strbuf_addstr(sb, color_symbol); strbuf_addstr(sb, prefix); strbuf_addstr(sb, color_reset); } @@ -369,7 +374,7 @@ void format_decorations(struct strbuf *sb, if (current_and_HEAD && decoration->type == DECORATION_REF_HEAD) { - strbuf_addstr(sb, color_commit); + strbuf_addstr(sb, color_symbol); strbuf_addstr(sb, pointer); strbuf_addstr(sb, color_reset); strbuf_addstr(sb, decorate_get_color(use_color, current_and_HEAD->type)); @@ -382,7 +387,7 @@ void format_decorations(struct strbuf *sb, decoration = decoration->next; } if (*suffix) { - strbuf_addstr(sb, color_commit); + strbuf_addstr(sb, color_symbol); strbuf_addstr(sb, suffix); strbuf_addstr(sb, color_reset); } diff --git a/t/t4207-log-decoration-colors.sh b/t/t4207-log-decoration-colors.sh index 21986a866d..f4173b6114 100755 --- a/t/t4207-log-decoration-colors.sh +++ b/t/t4207-log-decoration-colors.sh @@ -18,6 +18,7 @@ test_expect_success setup ' git config color.decorate.tag "reverse bold yellow" && git config color.decorate.stash magenta && git config color.decorate.grafted black && + git config color.decorate.symbol white && git config color.decorate.HEAD cyan && c_reset="" && @@ -29,6 +30,7 @@ test_expect_success setup ' c_stash="" && c_HEAD="" && c_grafted="" && + c_symbol="" && test_commit A && git clone . other && @@ -53,17 +55,17 @@ cmp_filtered_decorations () { # to this test since it does not contain any decoration, hence --first-parent test_expect_success 'commit decorations colored correctly' ' cat >expect <<-EOF && - ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD${c_reset}\ -${c_commit} -> ${c_reset}${c_branch}main${c_reset}${c_commit}, \ -${c_reset}${c_tag}tag: ${c_reset}${c_tag}v1.0${c_reset}${c_commit}, \ -${c_reset}${c_tag}tag: ${c_reset}${c_tag}B${c_reset}${c_commit})${c_reset} B -${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\ -${c_tag}tag: ${c_reset}${c_tag}A1${c_reset}${c_commit}, \ -${c_reset}${c_remoteBranch}other/main${c_reset}${c_commit})${c_reset} A1 - ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\ -${c_stash}refs/stash${c_reset}${c_commit})${c_reset} On main: Changes to A.t - ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\ -${c_tag}tag: ${c_reset}${c_tag}A${c_reset}${c_commit})${c_reset} A + ${c_commit}COMMIT_ID${c_reset}${c_symbol} (${c_reset}${c_HEAD}HEAD${c_reset}\ +${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}B${c_reset}${c_symbol})${c_reset} B +${c_commit}COMMIT_ID${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_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_commit}COMMIT_ID${c_reset}${c_symbol} (${c_reset}\ +${c_tag}tag: ${c_reset}${c_tag}A${c_reset}${c_symbol})${c_reset} A EOF git log --first-parent --no-abbrev --decorate --oneline --color=always --all >actual && @@ -78,14 +80,14 @@ test_expect_success 'test coloring with replace-objects' ' git replace HEAD~1 HEAD~2 && cat >expect <<-EOF && - ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD${c_reset}\ -${c_commit} -> ${c_reset}${c_branch}main${c_reset}${c_commit}, \ -${c_reset}${c_tag}tag: ${c_reset}${c_tag}D${c_reset}${c_commit})${c_reset} D - ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\ -${c_tag}tag: ${c_reset}${c_tag}C${c_reset}${c_commit}, \ -${c_reset}${c_grafted}replaced${c_reset}${c_commit})${c_reset} B - ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\ -${c_tag}tag: ${c_reset}${c_tag}A${c_reset}${c_commit})${c_reset} A + ${c_commit}COMMIT_ID${c_reset}${c_symbol} (${c_reset}${c_HEAD}HEAD${c_reset}\ +${c_symbol} -> ${c_reset}${c_branch}main${c_reset}${c_symbol}, ${c_reset}\ +${c_tag}tag: ${c_reset}${c_tag}D${c_reset}${c_symbol})${c_reset} D + ${c_commit}COMMIT_ID${c_reset}${c_symbol} (${c_reset}\ +${c_tag}tag: ${c_reset}${c_tag}C${c_reset}${c_symbol}, ${c_reset}\ +${c_grafted}replaced${c_reset}${c_symbol})${c_reset} B + ${c_commit}COMMIT_ID${c_reset}${c_symbol} (${c_reset}\ +${c_tag}tag: ${c_reset}${c_tag}A${c_reset}${c_symbol})${c_reset} A EOF git log --first-parent --no-abbrev --decorate --oneline --color=always HEAD >actual && @@ -104,15 +106,15 @@ test_expect_success 'test coloring with grafted commit' ' git replace --graft HEAD HEAD~2 && cat >expect <<-EOF && - ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD${c_reset}\ -${c_commit} -> ${c_reset}${c_branch}main${c_reset}${c_commit}, \ -${c_reset}${c_tag}tag: ${c_reset}${c_tag}D${c_reset}${c_commit}, \ -${c_reset}${c_grafted}replaced${c_reset}${c_commit})${c_reset} D - ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\ -${c_tag}tag: ${c_reset}${c_tag}v1.0${c_reset}${c_commit}, \ -${c_reset}${c_tag}tag: ${c_reset}${c_tag}B${c_reset}${c_commit})${c_reset} B - ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\ -${c_tag}tag: ${c_reset}${c_tag}A${c_reset}${c_commit})${c_reset} A + ${c_commit}COMMIT_ID${c_reset}${c_symbol} (${c_reset}${c_HEAD}HEAD${c_reset}\ +${c_symbol} -> ${c_reset}${c_branch}main${c_reset}${c_symbol}, ${c_reset}\ +${c_tag}tag: ${c_reset}${c_tag}D${c_reset}${c_symbol}, ${c_reset}\ +${c_grafted}replaced${c_reset}${c_symbol})${c_reset} D + ${c_commit}COMMIT_ID${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_commit}COMMIT_ID${c_reset}${c_symbol} (${c_reset}\ +${c_tag}tag: ${c_reset}${c_tag}A${c_reset}${c_symbol})${c_reset} A EOF git log --first-parent --no-abbrev --decorate --oneline --color=always HEAD >actual && From c6bcc49d69824ff143bb4c2d5a26c35ec1c1a723 Mon Sep 17 00:00:00 2001 From: Andy Koppe Date: Mon, 23 Oct 2023 23:11:40 +0100 Subject: [PATCH 4/7] log: add color.decorate.ref config variable Refs other than branches, remote-tracking branches, tags and the stash do not appear in log decorations by default, but they can be shown by using decoration filter options such as --clear-decorations or log.initialDecorationSet. However, they would appear without color. Add config variable color.decorate.ref for such refs, defaulting to bold magenta, which is the same as refs/stash. Document the new variable on the git-config page and amend t4207-log-decoration-colors.sh to test it. Signed-off-by: Andy Koppe Signed-off-by: Junio C Hamano --- Documentation/config/color.txt | 5 +++++ commit.h | 1 + log-tree.c | 4 +++- t/t4207-log-decoration-colors.sh | 9 +++++++-- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Documentation/config/color.txt b/Documentation/config/color.txt index cc0a881125..005a2bdb03 100644 --- a/Documentation/config/color.txt +++ b/Documentation/config/color.txt @@ -90,11 +90,16 @@ color.decorate.:: lightweight and annotated tags `stash`;; the stash ref +`ref`;; + any other refs (not shown by default) `grafted`;; grafted and replaced commits `symbol`;; punctuation symbols surrounding the other elements -- ++ +(Variable `log.initialDecorationSet` or linkgit:git-log[1] option +`--clear-decorations` can be used to show all refs.) color.grep:: When set to `always`, always highlight matches. When `false` (or diff --git a/commit.h b/commit.h index cb13e4d5ba..f6b2125fc4 100644 --- a/commit.h +++ b/commit.h @@ -54,6 +54,7 @@ enum decoration_type { DECORATION_REF_REMOTE, DECORATION_REF_TAG, DECORATION_REF_STASH, + DECORATION_REF, DECORATION_REF_HEAD, DECORATION_GRAFTED, DECORATION_SYMBOL, diff --git a/log-tree.c b/log-tree.c index 890024f205..fb3d87b83d 100644 --- a/log-tree.c +++ b/log-tree.c @@ -39,6 +39,7 @@ static char decoration_colors[][COLOR_MAXLEN] = { [DECORATION_REF_REMOTE] = GIT_COLOR_BOLD_RED, [DECORATION_REF_TAG] = GIT_COLOR_BOLD_YELLOW, [DECORATION_REF_STASH] = GIT_COLOR_BOLD_MAGENTA, + [DECORATION_REF] = GIT_COLOR_BOLD_MAGENTA, [DECORATION_REF_HEAD] = GIT_COLOR_BOLD_CYAN, [DECORATION_GRAFTED] = GIT_COLOR_BOLD_BLUE, [DECORATION_SYMBOL] = GIT_COLOR_NIL, @@ -49,6 +50,7 @@ static const char *color_decorate_slots[] = { [DECORATION_REF_REMOTE] = "remoteBranch", [DECORATION_REF_TAG] = "tag", [DECORATION_REF_STASH] = "stash", + [DECORATION_REF] = "ref", [DECORATION_REF_HEAD] = "HEAD", [DECORATION_GRAFTED] = "grafted", [DECORATION_SYMBOL] = "symbol", @@ -151,7 +153,7 @@ static int add_ref_decoration(const char *refname, const struct object_id *oid, int i; struct object *obj; enum object_type objtype; - enum decoration_type deco_type = DECORATION_NONE; + enum decoration_type deco_type = DECORATION_REF; struct decoration_filter *filter = (struct decoration_filter *)cb_data; const char *git_replace_ref_base = ref_namespace[NAMESPACE_REPLACE].ref; diff --git a/t/t4207-log-decoration-colors.sh b/t/t4207-log-decoration-colors.sh index f4173b6114..4b51e34f8b 100755 --- a/t/t4207-log-decoration-colors.sh +++ b/t/t4207-log-decoration-colors.sh @@ -17,6 +17,7 @@ test_expect_success setup ' git config color.decorate.remoteBranch red && git config color.decorate.tag "reverse bold yellow" && git config color.decorate.stash magenta && + git config color.decorate.ref blue && git config color.decorate.grafted black && git config color.decorate.symbol white && git config color.decorate.HEAD cyan && @@ -28,11 +29,13 @@ test_expect_success setup ' c_remoteBranch="" && c_tag="" && c_stash="" && + c_ref="" && c_HEAD="" && c_grafted="" && c_symbol="" && test_commit A && + git update-ref refs/foo A && git clone . other && ( cd other && @@ -65,10 +68,12 @@ ${c_remoteBranch}other/main${c_reset}${c_symbol})${c_reset} A1 ${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_commit}COMMIT_ID${c_reset}${c_symbol} (${c_reset}\ -${c_tag}tag: ${c_reset}${c_tag}A${c_reset}${c_symbol})${c_reset} A +${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 EOF - git log --first-parent --no-abbrev --decorate --oneline --color=always --all >actual && + git log --first-parent --no-abbrev --decorate --clear-decorations \ + --oneline --color=always --all >actual && cmp_filtered_decorations ' From 3a5c981df9f5ded9e12b9d4a7baad27633575283 Mon Sep 17 00:00:00 2001 From: Andy Koppe Date: Mon, 23 Oct 2023 23:11:41 +0100 Subject: [PATCH 5/7] refs: add pseudorefs array and iteration functions Define const array 'pseudorefs' with the names of the pseudorefs that are documented in gitrevisions.1, and add functions for_each_pseudoref() and refs_for_each_pseudoref() for iterating over them. The functions process the pseudorefs in the same way as head_ref() and refs_head_ref() process HEAD, invoking an each_ref_fn callback on each pseudoref that exists. This is in preparation for adding pseudorefs to log decorations. Signed-off-by: Andy Koppe Signed-off-by: Junio C Hamano --- refs.c | 42 ++++++++++++++++++++++++++++++++++++++++++ refs.h | 5 +++++ 2 files changed, 47 insertions(+) diff --git a/refs.c b/refs.c index fcae5dddc6..aa7e4c02c5 100644 --- a/refs.c +++ b/refs.c @@ -65,6 +65,21 @@ static unsigned char refname_disposition[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 4, 4 }; +/* + * List of documented pseudorefs. This needs to be kept in sync with the list + * in Documentation/revisions.txt. + */ +static const char *const pseudorefs[] = { + "FETCH_HEAD", + "ORIG_HEAD", + "MERGE_HEAD", + "REBASE_HEAD", + "CHERRY_PICK_HEAD", + "REVERT_HEAD", + "BISECT_HEAD", + "AUTO_MERGE", +}; + struct ref_namespace_info ref_namespace[] = { [NAMESPACE_HEAD] = { .ref = "HEAD", @@ -1549,6 +1564,33 @@ int head_ref(each_ref_fn fn, void *cb_data) return refs_head_ref(get_main_ref_store(the_repository), fn, cb_data); } +int refs_for_each_pseudoref(struct ref_store *refs, + each_ref_fn fn, void *cb_data) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(pseudorefs); i++) { + struct object_id oid; + int flag; + + if (refs_resolve_ref_unsafe(refs, pseudorefs[i], + RESOLVE_REF_READING, &oid, &flag)) { + int ret = fn(pseudorefs[i], &oid, flag, cb_data); + + if (ret) + return ret; + } + } + + return 0; +} + +int for_each_pseudoref(each_ref_fn fn, void *cb_data) +{ + return refs_for_each_pseudoref(get_main_ref_store(the_repository), + fn, cb_data); +} + struct ref_iterator *refs_ref_iterator_begin( struct ref_store *refs, const char *prefix, diff --git a/refs.h b/refs.h index 23211a5ea1..7b55cced31 100644 --- a/refs.h +++ b/refs.h @@ -320,6 +320,8 @@ typedef int each_repo_ref_fn(struct repository *r, */ int refs_head_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data); +int refs_for_each_pseudoref(struct ref_store *refs, + each_ref_fn fn, void *cb_data); int refs_for_each_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data); int refs_for_each_ref_in(struct ref_store *refs, const char *prefix, @@ -334,6 +336,9 @@ int refs_for_each_remote_ref(struct ref_store *refs, /* just iterates the head ref. */ int head_ref(each_ref_fn fn, void *cb_data); +/* iterates pseudorefs. */ +int for_each_pseudoref(each_ref_fn fn, void *cb_data); + /* iterates all refs. */ int for_each_ref(each_ref_fn fn, void *cb_data); From e19f171be896443c74b566e49575f75954c0458e Mon Sep 17 00:00:00 2001 From: Andy Koppe Date: Mon, 23 Oct 2023 23:11:42 +0100 Subject: [PATCH 6/7] refs: exempt pseudorefs from pattern prefixing In normalize_glob_ref(), don't prefix pseudorefs with "refs/", thereby implementing a NEEDSWORK from b877e617e6e5. This is in preparation for showing pseudorefs in log decorations, as they are not matched as intended in decoration filters otherwise. The function is only used in load_ref_decorations(). Signed-off-by: Andy Koppe Signed-off-by: Junio C Hamano --- refs.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/refs.c b/refs.c index aa7e4c02c5..fbd15a8cff 100644 --- a/refs.c +++ b/refs.c @@ -565,13 +565,16 @@ void normalize_glob_ref(struct string_list_item *item, const char *prefix, if (prefix) strbuf_addstr(&normalized_pattern, prefix); - else if (!starts_with(pattern, "refs/") && - strcmp(pattern, "HEAD")) - strbuf_addstr(&normalized_pattern, "refs/"); - /* - * NEEDSWORK: Special case other symrefs such as REBASE_HEAD, - * MERGE_HEAD, etc. - */ + else if (!starts_with(pattern, "refs/") && strcmp(pattern, "HEAD")) { + int i; + + for (i = 0; i < ARRAY_SIZE(pseudorefs); i++) + if (!strcmp(pattern, pseudorefs[i])) + break; + + if (i == ARRAY_SIZE(pseudorefs)) + strbuf_addstr(&normalized_pattern, "refs/"); + } strbuf_addstr(&normalized_pattern, pattern); strbuf_strip_suffix(&normalized_pattern, "/"); From 7dc6f5ada8442f12c0135469ed8400483fc6ebf1 Mon Sep 17 00:00:00 2001 From: Andy Koppe Date: Mon, 23 Oct 2023 23:11:43 +0100 Subject: [PATCH 7/7] 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 Signed-off-by: Junio C Hamano --- Documentation/config/color.txt | 4 +++- commit.h | 1 + log-tree.c | 24 +++++++++++++++++++ ..._--decorate=full_--clear-decorations_--all | 4 ++-- ...f.log_--decorate_--clear-decorations_--all | 4 ++-- t/t4202-log.sh | 21 +++++++++------- t/t4207-log-decoration-colors.sh | 13 +++++++--- 7 files changed, 54 insertions(+), 17 deletions(-) diff --git a/Documentation/config/color.txt b/Documentation/config/color.txt index 005a2bdb03..7af7d65f76 100644 --- a/Documentation/config/color.txt +++ b/Documentation/config/color.txt @@ -92,6 +92,8 @@ color.decorate.:: the stash ref `ref`;; any other refs (not shown by default) +`pseudoref`;; + pseudorefs such as ORIG_HEAD or MERGE_HEAD (not shown by default) `grafted`;; grafted and replaced commits `symbol`;; @@ -99,7 +101,7 @@ color.decorate.:: -- + (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:: When set to `always`, always highlight matches. When `false` (or diff --git a/commit.h b/commit.h index f6b2125fc4..44dd3ce19b 100644 --- a/commit.h +++ b/commit.h @@ -56,6 +56,7 @@ enum decoration_type { DECORATION_REF_STASH, DECORATION_REF, DECORATION_REF_HEAD, + DECORATION_REF_PSEUDO, DECORATION_GRAFTED, DECORATION_SYMBOL, }; diff --git a/log-tree.c b/log-tree.c index fb3d87b83d..65ebb74d40 100644 --- a/log-tree.c +++ b/log-tree.c @@ -41,6 +41,7 @@ static char decoration_colors[][COLOR_MAXLEN] = { [DECORATION_REF_STASH] = GIT_COLOR_BOLD_MAGENTA, [DECORATION_REF] = GIT_COLOR_BOLD_MAGENTA, [DECORATION_REF_HEAD] = GIT_COLOR_BOLD_CYAN, + [DECORATION_REF_PSEUDO] = GIT_COLOR_BOLD_CYAN, [DECORATION_GRAFTED] = GIT_COLOR_BOLD_BLUE, [DECORATION_SYMBOL] = GIT_COLOR_NIL, }; @@ -52,6 +53,7 @@ static const char *color_decorate_slots[] = { [DECORATION_REF_STASH] = "stash", [DECORATION_REF] = "ref", [DECORATION_REF_HEAD] = "HEAD", + [DECORATION_REF_PSEUDO] = "pseudoref", [DECORATION_GRAFTED] = "grafted", [DECORATION_SYMBOL] = "symbol", }; @@ -208,6 +210,27 @@ static int add_ref_decoration(const char *refname, const struct object_id *oid, 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, void *cb_data UNUSED) { @@ -236,6 +259,7 @@ void load_ref_decorations(struct decoration_filter *filter, int flags) decoration_loaded = 1; decoration_flags = flags; for_each_ref(add_ref_decoration, filter); + for_each_pseudoref(add_pseudoref_decoration, filter); head_ref(add_ref_decoration, filter); for_each_commit_graft(add_graft_decoration, filter); } diff --git a/t/t4013/diff.log_--decorate=full_--clear-decorations_--all b/t/t4013/diff.log_--decorate=full_--clear-decorations_--all index 1c030a6554..7d16978e7f 100644 --- a/t/t4013/diff.log_--decorate=full_--clear-decorations_--all +++ b/t/t4013/diff.log_--decorate=full_--clear-decorations_--all @@ -33,13 +33,13 @@ Date: Mon Jun 26 00:04:00 2006 +0000 Merge branch 'side' -commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (refs/heads/side) +commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (FETCH_HEAD, refs/heads/side) Author: A U Thor Date: Mon Jun 26 00:03:00 2006 +0000 Side -commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 +commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 (ORIG_HEAD) Author: A U Thor Date: Mon Jun 26 00:02:00 2006 +0000 diff --git a/t/t4013/diff.log_--decorate_--clear-decorations_--all b/t/t4013/diff.log_--decorate_--clear-decorations_--all index 88be82cce3..4f9be50ce0 100644 --- a/t/t4013/diff.log_--decorate_--clear-decorations_--all +++ b/t/t4013/diff.log_--decorate_--clear-decorations_--all @@ -33,13 +33,13 @@ Date: Mon Jun 26 00:04:00 2006 +0000 Merge branch 'side' -commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (side) +commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (FETCH_HEAD, side) Author: A U Thor Date: Mon Jun 26 00:03:00 2006 +0000 Side -commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 +commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 (ORIG_HEAD) Author: A U Thor Date: Mon Jun 26 00:02:00 2006 +0000 diff --git a/t/t4202-log.sh b/t/t4202-log.sh index af4a123cd2..b14da62e3e 100755 --- a/t/t4202-log.sh +++ b/t/t4202-log.sh @@ -927,7 +927,7 @@ test_expect_success 'multiple decorate-refs' ' test_expect_success 'decorate-refs-exclude with glob' ' cat >expect.decorate <<-\EOF && Merge-tag-reach (HEAD -> main) - Merge-tags-octopus-a-and-octopus-b + Merge-tags-octopus-a-and-octopus-b (ORIG_HEAD) seventh (tag: seventh) octopus-b (tag: octopus-b) 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' ' cat >expect.decorate <<-\EOF && Merge-tag-reach (HEAD -> main) - Merge-tags-octopus-a-and-octopus-b + Merge-tags-octopus-a-and-octopus-b (ORIG_HEAD) seventh (tag: seventh) octopus-b (tag: octopus-b, octopus-b) 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' ' cat >expect.decorate <<-\EOF && Merge-tag-reach (HEAD -> main) - Merge-tags-octopus-a-and-octopus-b + Merge-tags-octopus-a-and-octopus-b (ORIG_HEAD) seventh (tag: seventh) octopus-b (tag: octopus-b) octopus-a (tag: octopus-a) @@ -1022,10 +1022,12 @@ test_expect_success 'decorate-refs-exclude and simplify-by-decoration' ' EOF git log -n6 --decorate=short --pretty="tformat:%f%d" \ --decorate-refs-exclude="*octopus*" \ + --decorate-refs-exclude="ORIG_HEAD" \ --simplify-by-decoration >actual && test_cmp expect.decorate actual && - git -c log.excludeDecoration="*octopus*" log \ - -n6 --decorate=short --pretty="tformat:%f%d" \ + git -c log.excludeDecoration="*octopus*" \ + -c log.excludeDecoration="ORIG_HEAD" \ + log -n6 --decorate=short --pretty="tformat:%f%d" \ --simplify-by-decoration >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_expect_success 'decorate-refs-exclude HEAD' ' +test_expect_success 'decorate-refs-exclude HEAD ORIG_HEAD' ' git log --decorate=full --oneline \ - --decorate-refs-exclude="HEAD" >actual && + --decorate-refs-exclude="HEAD" \ + --decorate-refs-exclude="ORIG_HEAD" >actual && ! grep HEAD actual ' @@ -1107,7 +1110,7 @@ test_expect_success '--clear-decorations overrides defaults' ' cat >expect.all <<-\EOF && 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) octopus-b (tag: refs/tags/octopus-b, refs/heads/octopus-b) 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 && Merge-tag-reach (HEAD -> refs/heads/main) 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-a (tag: refs/tags/octopus-a, refs/heads/octopus-a) seventh (tag: refs/tags/seventh) diff --git a/t/t4207-log-decoration-colors.sh b/t/t4207-log-decoration-colors.sh index 4b51e34f8b..0b32e0bb8e 100755 --- a/t/t4207-log-decoration-colors.sh +++ b/t/t4207-log-decoration-colors.sh @@ -18,6 +18,7 @@ test_expect_success setup ' git config color.decorate.tag "reverse bold yellow" && git config color.decorate.stash magenta && git config color.decorate.ref blue && + git config color.decorate.pseudoref "bold cyan" && git config color.decorate.grafted black && git config color.decorate.symbol white && git config color.decorate.HEAD cyan && @@ -30,6 +31,7 @@ test_expect_success setup ' c_tag="" && c_stash="" && c_ref="" && + c_pseudoref="" && c_HEAD="" && c_grafted="" && c_symbol="" && @@ -46,7 +48,10 @@ test_expect_success setup ' test_commit B && git tag v1.0 && 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 () { @@ -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}B${c_reset}${c_symbol})${c_reset} B ${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_remoteBranch}other/main${c_reset}${c_symbol})${c_reset} A1 ${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_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_ref}refs/foo${c_reset}${c_symbol})${c_reset} A EOF - git log --first-parent --no-abbrev --decorate --clear-decorations \ - --oneline --color=always --all >actual && + git log --first-parent --no-abbrev --decorate --color=always \ + --decorate-refs-exclude=FETCH_HEAD --oneline --all >actual && cmp_filtered_decorations '