git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] decorate: add color.decorate.symbols config option
@ 2023-10-03 20:54 Andy Koppe
  2023-10-19 19:39 ` [PATCH 0/7] log: decorate pseudorefs and other refs Andy Koppe
                   ` (7 more replies)
  0 siblings, 8 replies; 31+ messages in thread
From: Andy Koppe @ 2023-10-03 20:54 UTC (permalink / raw)
  To: git; +Cc: derrickstolee, Andy Koppe

Add new 'color.decorate.symbols' config option for determining the color
of the prefix, suffix, separator and arrow symbols used in --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' option if the new option is
not provided.

Add the setting to the color.decorate.<slot> documentation, rewording
that a bit to try to improve readability.

Amend t4207-log-decoration-colors.sh to test the option.

Signed-off-by: Andy Koppe <andy.koppe@gmail.com>
---
 Documentation/config/color.txt   |  7 ++--
 commit.h                         |  1 +
 log-tree.c                       | 15 ++++++---
 t/t4207-log-decoration-colors.sh | 58 +++++++++++++++++---------------
 4 files changed, 45 insertions(+), 36 deletions(-)

diff --git a/Documentation/config/color.txt b/Documentation/config/color.txt
index 1795b2d16b..5d3612ff09 100644
--- a/Documentation/config/color.txt
+++ b/Documentation/config/color.txt
@@ -75,9 +75,10 @@ color.diff.<slot>::
 
 color.decorate.<slot>::
 	Use customized color for 'git log --decorate' output.  `<slot>` 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.
+	of `HEAD` for the current HEAD ref, `branch` for local branches,
+	`remoteBranch` for remote-tracking branches, `tag` for tags, `stash`
+	for the top stash entry, `grafted` for grafted commits, and `symbols`
+	for the punctuation surrounding the other elements.
 
 color.grep::
 	When set to `always`, always highlight matches.  When `false` (or
diff --git a/commit.h b/commit.h
index 28928833c5..cefcb7c490 100644
--- a/commit.h
+++ b/commit.h
@@ -56,6 +56,7 @@ enum decoration_type {
 	DECORATION_REF_STASH,
 	DECORATION_REF_HEAD,
 	DECORATION_GRAFTED,
+	DECORATION_SYMBOLS,
 };
 
 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 504da6b519..a5dd4292fc 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -41,6 +41,7 @@ static char decoration_colors[][COLOR_MAXLEN] = {
 	GIT_COLOR_BOLD_MAGENTA,	/* REF_STASH */
 	GIT_COLOR_BOLD_CYAN,	/* REF_HEAD */
 	GIT_COLOR_BOLD_BLUE,	/* GRAFTED */
+	GIT_COLOR_NIL,		/* SYMBOLS */
 };
 
 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_SYMBOLS]	= "symbols",
 };
 
 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_symbols, *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_symbols = decorate_get_color(use_color, DECORATION_SYMBOLS);
+	if (color_is_nil(color_symbols))
+		color_symbols = 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_symbols);
 				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_symbols);
 				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_symbols);
 		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..663ae49d34 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.symbols white &&
 	git config color.decorate.HEAD cyan &&
 
 	c_reset="<RESET>" &&
@@ -29,6 +30,7 @@ test_expect_success setup '
 	c_stash="<MAGENTA>" &&
 	c_HEAD="<CYAN>" &&
 	c_grafted="<BLACK>" &&
+	c_symbols="<WHITE>" &&
 
 	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_symbols} (${c_reset}${c_HEAD}HEAD${c_reset}\
+${c_symbols} -> ${c_reset}${c_branch}main${c_reset}${c_symbols}, \
+${c_reset}${c_tag}tag: ${c_reset}${c_tag}v1.0${c_reset}${c_symbols}, \
+${c_reset}${c_tag}tag: ${c_reset}${c_tag}B${c_reset}${c_symbols})${c_reset} B
+${c_commit}COMMIT_ID${c_reset}${c_symbols} (${c_reset}\
+${c_tag}tag: ${c_reset}${c_tag}A1${c_reset}${c_symbols}, \
+${c_reset}${c_remoteBranch}other/main${c_reset}${c_symbols})${c_reset} A1
+	${c_commit}COMMIT_ID${c_reset}${c_symbols} (${c_reset}\
+${c_stash}refs/stash${c_reset}${c_symbols})${c_reset} On main: Changes to A.t
+	${c_commit}COMMIT_ID${c_reset}${c_symbols} (${c_reset}\
+${c_tag}tag: ${c_reset}${c_tag}A${c_reset}${c_symbols})${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_symbols} (${c_reset}${c_HEAD}HEAD${c_reset}\
+${c_symbols} -> ${c_reset}${c_branch}main${c_reset}${c_symbols}, \
+${c_reset}${c_tag}tag: ${c_reset}${c_tag}D${c_reset}${c_symbols})${c_reset} D
+	${c_commit}COMMIT_ID${c_reset}${c_symbols} (${c_reset}\
+${c_tag}tag: ${c_reset}${c_tag}C${c_reset}${c_symbols}, \
+${c_reset}${c_grafted}replaced${c_reset}${c_symbols})${c_reset} B
+	${c_commit}COMMIT_ID${c_reset}${c_symbols} (${c_reset}\
+${c_tag}tag: ${c_reset}${c_tag}A${c_reset}${c_symbols})${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_symbols} (${c_reset}${c_HEAD}HEAD${c_reset}\
+${c_symbols} -> ${c_reset}${c_branch}main${c_reset}${c_symbols}, \
+${c_reset}${c_tag}tag: ${c_reset}${c_tag}D${c_reset}${c_symbols}, \
+${c_reset}${c_grafted}replaced${c_reset}${c_symbols})${c_reset} D
+	${c_commit}COMMIT_ID${c_reset}${c_symbols} (${c_reset}\
+${c_tag}tag: ${c_reset}${c_tag}v1.0${c_reset}${c_symbols}, \
+${c_reset}${c_tag}tag: ${c_reset}${c_tag}B${c_reset}${c_symbols})${c_reset} B
+	${c_commit}COMMIT_ID${c_reset}${c_symbols} (${c_reset}\
+${c_tag}tag: ${c_reset}${c_tag}A${c_reset}${c_symbols})${c_reset} A
 	EOF
 
 	git log --first-parent --no-abbrev --decorate --oneline --color=always HEAD >actual &&
-- 
2.42.GIT


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 0/7] log: decorate pseudorefs and other refs
  2023-10-03 20:54 [PATCH] decorate: add color.decorate.symbols config option Andy Koppe
@ 2023-10-19 19:39 ` Andy Koppe
  2023-10-22  0:13   ` Junio C Hamano
  2023-10-22 21:44   ` [PATCH v2 0/6] " Andy Koppe
  2023-10-19 19:39 ` [PATCH 1/7] config: restructure color.decorate documentation Andy Koppe
                   ` (6 subsequent siblings)
  7 siblings, 2 replies; 31+ messages in thread
From: Andy Koppe @ 2023-10-19 19:39 UTC (permalink / raw)
  To: git; +Cc: Andy Koppe

This patch series adds three slots to the color.decorate.<slot> config
option:
- 'symbol' for coloring the punctuation symbols used around the refs in
  decorations, which currently use the same color as the commit hash.
- 'ref' for coloring refs other than branches, remote-tracking branches,
  tags and the stash, which currently are not colored when included in
  decorations through custom decoration filter options.
- 'pseudoref' for coloring pseudorefs such as ORIG_HEAD or MERGE_HEAD.
  Include them in decorations by default.

This series is to replace the 'decorate: add color.decorate.symbols
config option' patch proposed at:
https://lore.kernel.org/git/20231003205442.22963-1-andy.koppe@gmail.com

Andy Koppe (7):
  config: restructure color.decorate documentation
  log: use designated inits for decoration_colors
  log: add color.decorate.symbol config option
  refs: separate decoration type from default filter
  log: add color.decorate.ref option for other refs
  refs: exempt pseudoref patterns from prefixing
  log: show pseudorefs in decorations

 Documentation/config/color.txt                | 30 +++++++-
 Documentation/git-log.txt                     |  7 +-
 builtin/log.c                                 |  6 +-
 commit.h                                      |  3 +
 log-tree.c                                    | 60 ++++++++++++---
 refs.c                                        | 62 ++++++++++++++--
 refs.h                                        | 14 ++++
 t/t4013/diff.log_--decorate=full_--all        |  2 +-
 ..._--decorate=full_--clear-decorations_--all |  4 +-
 t/t4013/diff.log_--decorate_--all             |  2 +-
 ...f.log_--decorate_--clear-decorations_--all |  4 +-
 t/t4202-log.sh                                | 23 +++---
 t/t4207-log-decoration-colors.sh              | 74 +++++++++++--------
 13 files changed, 216 insertions(+), 75 deletions(-)

-- 
2.42.GIT


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 1/7] config: restructure color.decorate documentation
  2023-10-03 20:54 [PATCH] decorate: add color.decorate.symbols config option Andy Koppe
  2023-10-19 19:39 ` [PATCH 0/7] log: decorate pseudorefs and other refs Andy Koppe
@ 2023-10-19 19:39 ` Andy Koppe
  2023-10-19 19:39 ` [PATCH 2/7] log: use designated inits for decoration_colors Andy Koppe
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 31+ messages in thread
From: Andy Koppe @ 2023-10-19 19:39 UTC (permalink / raw)
  To: git; +Cc: Andy Koppe

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 <andy.koppe@gmail.com>
---
 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 1795b2d16be..b0e2eccad95 100644
--- a/Documentation/config/color.txt
+++ b/Documentation/config/color.txt
@@ -74,10 +74,25 @@ color.diff.<slot>::
 	`oldBold`, and `newBold` (see linkgit:git-range-diff[1] for details).
 
 color.decorate.<slot>::
-	Use customized color for 'git log --decorate' output.  `<slot>` 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 `<slot>` 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 commits (used to implement shallow clones)
+--
 
 color.grep::
 	When set to `always`, always highlight matches.  When `false` (or
-- 
2.42.GIT


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 2/7] log: use designated inits for decoration_colors
  2023-10-03 20:54 [PATCH] decorate: add color.decorate.symbols config option Andy Koppe
  2023-10-19 19:39 ` [PATCH 0/7] log: decorate pseudorefs and other refs Andy Koppe
  2023-10-19 19:39 ` [PATCH 1/7] config: restructure color.decorate documentation Andy Koppe
@ 2023-10-19 19:39 ` Andy Koppe
  2023-10-19 19:39 ` [PATCH 3/7] log: add color.decorate.symbol config option Andy Koppe
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 31+ messages in thread
From: Andy Koppe @ 2023-10-19 19:39 UTC (permalink / raw)
  To: git; +Cc: Andy Koppe

Use designated initializers instead of comments to denote the slots in
the decoration_colors array for holding color settings, to reduce the
likelihood of mistakes when extending the array.

Signed-off-by: Andy Koppe <andy.koppe@gmail.com>
---
 log-tree.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/log-tree.c b/log-tree.c
index 504da6b519e..8bdf889f022 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[] = {
-- 
2.42.GIT


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 3/7] log: add color.decorate.symbol config option
  2023-10-03 20:54 [PATCH] decorate: add color.decorate.symbols config option Andy Koppe
                   ` (2 preceding siblings ...)
  2023-10-19 19:39 ` [PATCH 2/7] log: use designated inits for decoration_colors Andy Koppe
@ 2023-10-19 19:39 ` Andy Koppe
  2023-10-19 19:39 ` [PATCH 4/7] refs: separate decoration type from default filter Andy Koppe
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 31+ messages in thread
From: Andy Koppe @ 2023-10-19 19:39 UTC (permalink / raw)
  To: git; +Cc: Andy Koppe

Add new 'color.decorate.symbol' config option for determining the color
of the prefix, suffix, separator and arrow symbols used in --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' option if the new option is
not provided.

Add the setting to the color.decorate.<slot> 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 <andy.koppe@gmail.com>
---
 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 b0e2eccad95..ba9f56885e3 100644
--- a/Documentation/config/color.txt
+++ b/Documentation/config/color.txt
@@ -92,6 +92,8 @@ color.decorate.<slot>::
 	the stash ref
 `grafted`;;
 	grafted commits (used to implement shallow clones)
+`symbol`;;
+	punctuation surrounding the other elements
 --
 
 color.grep::
diff --git a/commit.h b/commit.h
index 28928833c54..cb13e4d5baa 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 8bdf889f022..890024f205b 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 21986a866df..f4173b61141 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="<RESET>" &&
@@ -29,6 +30,7 @@ test_expect_success setup '
 	c_stash="<MAGENTA>" &&
 	c_HEAD="<CYAN>" &&
 	c_grafted="<BLACK>" &&
+	c_symbol="<WHITE>" &&
 
 	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 &&
-- 
2.42.GIT


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 4/7] refs: separate decoration type from default filter
  2023-10-03 20:54 [PATCH] decorate: add color.decorate.symbols config option Andy Koppe
                   ` (3 preceding siblings ...)
  2023-10-19 19:39 ` [PATCH 3/7] log: add color.decorate.symbol config option Andy Koppe
@ 2023-10-19 19:39 ` Andy Koppe
  2023-10-19 19:39 ` [PATCH 5/7] log: add color.decorate.ref option for other refs Andy Koppe
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 31+ messages in thread
From: Andy Koppe @ 2023-10-19 19:39 UTC (permalink / raw)
  To: git; +Cc: Andy Koppe

Add 'include' bit to struct ref_namespace_info to determine whether a
ref namespace is to be included in the default decoration filters,
instead of using the decoration type for the purpose.

This is to allow adding ref namespaces that do have a decoration type
but that are not shown by default.

Signed-off-by: Andy Koppe <andy.koppe@gmail.com>
---
 builtin/log.c | 6 ++----
 refs.c        | 6 ++++++
 refs.h        | 4 ++++
 3 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/builtin/log.c b/builtin/log.c
index ba775d7b5cf..25d73c25697 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -227,10 +227,8 @@ static void set_default_decoration_filter(struct decoration_filter *decoration_f
 	 * populate with sensible defaults.
 	 */
 	for (i = 0; i < ARRAY_SIZE(ref_namespace); i++) {
-		if (!ref_namespace[i].decoration)
-			continue;
-
-		string_list_append(include, ref_namespace[i].ref);
+		if (ref_namespace[i].include)
+			string_list_append(include, ref_namespace[i].ref);
 	}
 }
 
diff --git a/refs.c b/refs.c
index fcae5dddc60..416c35f0c2f 100644
--- a/refs.c
+++ b/refs.c
@@ -70,14 +70,17 @@ struct ref_namespace_info ref_namespace[] = {
 		.ref = "HEAD",
 		.decoration = DECORATION_REF_HEAD,
 		.exact = 1,
+		.include = 1,
 	},
 	[NAMESPACE_BRANCHES] = {
 		.ref = "refs/heads/",
 		.decoration = DECORATION_REF_LOCAL,
+		.include = 1,
 	},
 	[NAMESPACE_TAGS] = {
 		.ref = "refs/tags/",
 		.decoration = DECORATION_REF_TAG,
+		.include = 1,
 	},
 	[NAMESPACE_REMOTE_REFS] = {
 		/*
@@ -87,6 +90,7 @@ struct ref_namespace_info ref_namespace[] = {
 		 */
 		.ref = "refs/remotes/",
 		.decoration = DECORATION_REF_REMOTE,
+		.include = 1,
 	},
 	[NAMESPACE_STASH] = {
 		/*
@@ -96,6 +100,7 @@ struct ref_namespace_info ref_namespace[] = {
 		.ref = "refs/stash",
 		.exact = 1,
 		.decoration = DECORATION_REF_STASH,
+		.include = 1,
 	},
 	[NAMESPACE_REPLACE] = {
 		/*
@@ -107,6 +112,7 @@ struct ref_namespace_info ref_namespace[] = {
 		 */
 		.ref = "refs/replace/",
 		.decoration = DECORATION_GRAFTED,
+		.include = 1,
 	},
 	[NAMESPACE_NOTES] = {
 		/*
diff --git a/refs.h b/refs.h
index 23211a5ea1c..4b054d30fe5 100644
--- a/refs.h
+++ b/refs.h
@@ -987,10 +987,14 @@ struct ref_namespace_info {
 	 * If 'exact' is true, then we must match the 'ref' exactly.
 	 * Otherwise, use a prefix match.
 	 *
+	 * If 'include' is true, the namespace is included in the
+	 * default decoration filters.
+	 *
 	 * 'ref_updated' is for internal use. It represents whether the
 	 * 'ref' value was replaced from its original literal version.
 	 */
 	unsigned exact:1,
+		 include:1,
 		 ref_updated:1;
 };
 
-- 
2.42.GIT


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 5/7] log: add color.decorate.ref option for other refs
  2023-10-03 20:54 [PATCH] decorate: add color.decorate.symbols config option Andy Koppe
                   ` (4 preceding siblings ...)
  2023-10-19 19:39 ` [PATCH 4/7] refs: separate decoration type from default filter Andy Koppe
@ 2023-10-19 19:39 ` Andy Koppe
  2023-10-19 19:39 ` [PATCH 6/7] refs: exempt pseudoref patterns from prefixing Andy Koppe
  2023-10-19 19:39 ` [PATCH 7/7] log: show pseudorefs in decorations Andy Koppe
  7 siblings, 0 replies; 31+ messages in thread
From: Andy Koppe @ 2023-10-19 19:39 UTC (permalink / raw)
  To: git; +Cc: Andy Koppe

Refs other than those with builtin special meaning do not appear in log
decorations by default, but they can be made to appear using the
decoration filter options. However, they would do so without coloring.

Add config option color.decorate.ref to address this, defaulting to bold
magenta, which is the same as refs/stash.

To implement this, add NAMESPACE_REF with pattern "refs/", but do not
set its .include bit, so as to leave it out of the default decoration
filter.

Document the color.decorate slot on the git-config page and amend
t4207-log-decoration-colors.sh to test it.

Signed-off-by: Andy Koppe <andy.koppe@gmail.com>
---
 Documentation/config/color.txt   | 3 +++
 commit.h                         | 1 +
 log-tree.c                       | 2 ++
 refs.c                           | 7 +++++++
 refs.h                           | 1 +
 t/t4207-log-decoration-colors.sh | 9 +++++++--
 6 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/Documentation/config/color.txt b/Documentation/config/color.txt
index ba9f56885e3..086efebbe5d 100644
--- a/Documentation/config/color.txt
+++ b/Documentation/config/color.txt
@@ -92,6 +92,9 @@ color.decorate.<slot>::
 	the stash ref
 `grafted`;;
 	grafted commits (used to implement shallow clones)
+`ref`;;
+	any other refs (not shown unless enabled with one of the decoration
+	filter options such as `--decorate-refs=<pattern>`)
 `symbol`;;
 	punctuation surrounding the other elements
 --
diff --git a/commit.h b/commit.h
index cb13e4d5baa..f6b2125fc42 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 890024f205b..fd99eb88d95 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",
diff --git a/refs.c b/refs.c
index 416c35f0c2f..b03cccab909 100644
--- a/refs.c
+++ b/refs.c
@@ -142,6 +142,13 @@ struct ref_namespace_info ref_namespace[] = {
 		 */
 		.ref = "refs/rewritten/",
 	},
+	[NAMESPACE_REFS] = {
+		/*
+		 * Catch-all for any other refs.
+		 */
+		.ref = "refs/",
+		.decoration = DECORATION_REF,
+	},
 };
 
 void update_ref_namespace(enum ref_namespace namespace, char *ref)
diff --git a/refs.h b/refs.h
index 4b054d30fe5..82aecd37a2b 100644
--- a/refs.h
+++ b/refs.h
@@ -1008,6 +1008,7 @@ enum ref_namespace {
 	NAMESPACE_NOTES,
 	NAMESPACE_PREFETCH,
 	NAMESPACE_REWRITTEN,
+	NAMESPACE_REFS,
 
 	/* Must be last */
 	NAMESPACE__COUNT
diff --git a/t/t4207-log-decoration-colors.sh b/t/t4207-log-decoration-colors.sh
index f4173b61141..4b51e34f8b2 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="<RED>" &&
 	c_tag="<BOLD;REVERSE;YELLOW>" &&
 	c_stash="<MAGENTA>" &&
+	c_ref="<BLUE>" &&
 	c_HEAD="<CYAN>" &&
 	c_grafted="<BLACK>" &&
 	c_symbol="<WHITE>" &&
 
 	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
 '
 
-- 
2.42.GIT


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 6/7] refs: exempt pseudoref patterns from prefixing
  2023-10-03 20:54 [PATCH] decorate: add color.decorate.symbols config option Andy Koppe
                   ` (5 preceding siblings ...)
  2023-10-19 19:39 ` [PATCH 5/7] log: add color.decorate.ref option for other refs Andy Koppe
@ 2023-10-19 19:39 ` Andy Koppe
  2023-10-19 19:39 ` [PATCH 7/7] log: show pseudorefs in decorations Andy Koppe
  7 siblings, 0 replies; 31+ messages in thread
From: Andy Koppe @ 2023-10-19 19:39 UTC (permalink / raw)
  To: git; +Cc: Andy Koppe

In normalize_glob_ref(), don't prefix patterns that look like pseudorefs
with "refs/". This is in preparation for showing pseudorefs such as
ORIG_HEAD in log decorations, as they are not matched as intended in
decoration filters otherwise.

Use existing function is_pseudoref_syntax() to do this, declaring it in
refs.h to make it available to normalize_glob_ref() and anything else
that might need it. As the function returns true for HEAD as well, the
special case for that is no longer needed.

Signed-off-by: Andy Koppe <andy.koppe@gmail.com>
---
 refs.c | 8 ++------
 refs.h | 2 ++
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/refs.c b/refs.c
index b03cccab909..492b9f7d4e5 100644
--- a/refs.c
+++ b/refs.c
@@ -564,12 +564,8 @@ 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"))
+		 !is_pseudoref_syntax(pattern))
 		strbuf_addstr(&normalized_pattern, "refs/");
-	/*
-	 * NEEDSWORK: Special case other symrefs such as REBASE_HEAD,
-	 * MERGE_HEAD, etc.
-	 */
 
 	strbuf_addstr(&normalized_pattern, pattern);
 	strbuf_strip_suffix(&normalized_pattern, "/");
@@ -840,7 +836,7 @@ int is_per_worktree_ref(const char *refname)
 	       starts_with(refname, "refs/rewritten/");
 }
 
-static int is_pseudoref_syntax(const char *refname)
+int is_pseudoref_syntax(const char *refname)
 {
 	const char *c;
 
diff --git a/refs.h b/refs.h
index 82aecd37a2b..b77691d787a 100644
--- a/refs.h
+++ b/refs.h
@@ -123,6 +123,8 @@ int should_autocreate_reflog(const char *refname);
 
 int is_branch(const char *refname);
 
+int is_pseudoref_syntax(const char *refname);
+
 int refs_init_db(struct strbuf *err);
 
 /*
-- 
2.42.GIT


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 7/7] log: show pseudorefs in decorations
  2023-10-03 20:54 [PATCH] decorate: add color.decorate.symbols config option Andy Koppe
                   ` (6 preceding siblings ...)
  2023-10-19 19:39 ` [PATCH 6/7] refs: exempt pseudoref patterns from prefixing Andy Koppe
@ 2023-10-19 19:39 ` Andy Koppe
  7 siblings, 0 replies; 31+ messages in thread
From: Andy Koppe @ 2023-10-19 19:39 UTC (permalink / raw)
  To: git; +Cc: Andy Koppe

Show various pseudorefs in log decorations. This includes pseudorefs for
ongoing operations such as MERGE_HEAD and REBASE_HEAD, as well as
ORIG_HEAD for the HEAD position before any "drastic" operations.

Do not include FETCH_HEAD in the default decoration filter though,
because it would appear a lot in user's logs, often right alongside
HEAD, while providing little value as usually a remote-tracking branch
already points at what's been fetched.

To implement this, introduce decoration type DECORATION_REF_PSEUDO with
corresponding color.decorate.pseudoref setting that defaults to bold
blue. (This makes it similar to but not the same as HEAD, which defaults
to bold cyan.)

Add entries for each pseudoref to the ref_namespace array in refs.c.
Process them in new function add_pseudoref_decorations(). They also get
picked up by set_default_decoration_filter().

Document the showing of pseudorefs on the git-log page and the
color.decorate.pseudoref setting on the git-config page.

Amend t4207-log-decoration-colors.sh to test color.decorate.pseudoref,
and tweak various other tests to reflect the appearance of ORIG_HEAD in
decorations.

Signed-off-by: Andy Koppe <andy.koppe@gmail.com>
---
 Documentation/config/color.txt                |  2 +
 Documentation/git-log.txt                     |  7 ++--
 commit.h                                      |  1 +
 log-tree.c                                    | 29 +++++++++++++
 refs.c                                        | 41 +++++++++++++++++++
 refs.h                                        |  7 ++++
 t/t4013/diff.log_--decorate=full_--all        |  2 +-
 ..._--decorate=full_--clear-decorations_--all |  4 +-
 t/t4013/diff.log_--decorate_--all             |  2 +-
 ...f.log_--decorate_--clear-decorations_--all |  4 +-
 t/t4202-log.sh                                | 23 ++++++-----
 t/t4207-log-decoration-colors.sh              | 13 ++++--
 12 files changed, 113 insertions(+), 22 deletions(-)

diff --git a/Documentation/config/color.txt b/Documentation/config/color.txt
index 086efebbe5d..139fb90498a 100644
--- a/Documentation/config/color.txt
+++ b/Documentation/config/color.txt
@@ -95,6 +95,8 @@ color.decorate.<slot>::
 `ref`;;
 	any other refs (not shown unless enabled with one of the decoration
 	filter options such as `--decorate-refs=<pattern>`)
+`pseudoref`;;
+	pseudorefs such as ORIG_HEAD or MERGE_HEAD
 `symbol`;;
 	punctuation surrounding the other elements
 --
diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt
index 2a66cf88807..f217d16c439 100644
--- a/Documentation/git-log.txt
+++ b/Documentation/git-log.txt
@@ -52,9 +52,10 @@ OPTIONS
 	the decorations, but an explicit `--decorate-refs` pattern will
 	override a match in `log.excludeDecoration`.
 +
-If none of these options or config settings are given, then references are
-used as decoration if they match `HEAD`, `refs/heads/`, `refs/remotes/`,
-`refs/stash/`, or `refs/tags/`.
+If none of these options or config settings are given, then refs matching
+`refs/heads/`, `refs/remotes/`, `refs/stash/`, or `refs/tags/`, as well as
+the `HEAD` ref and the pseudorefs `ORIG_HEAD`, `MERGE_HEAD`, `REBASE_HEAD`,
+`CHERRY_PICK_HEAD`, `REVERT_HEAD` and `BISECT_HEAD` are shown.
 
 --clear-decorations::
 	When specified, this option clears all previous `--decorate-refs`
diff --git a/commit.h b/commit.h
index f6b2125fc42..44dd3ce19b4 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 fd99eb88d95..eae288599d0 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_BLUE,
 	[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",
 };
@@ -146,6 +148,32 @@ static int ref_filter_match(const char *refname,
 	return 1;
 }
 
+static void add_pseudoref_decorations(const struct decoration_filter *filter)
+{
+	struct ref_store *store = get_main_ref_store(the_repository);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ref_namespace); i++) {
+		struct object_id oid;
+		struct object *obj;
+		enum object_type objtype;
+		const struct ref_namespace_info *info = &ref_namespace[i];
+
+		if (info->decoration != DECORATION_REF_PSEUDO ||
+		    !refs_resolve_ref_unsafe(store, info->ref,
+					     RESOLVE_REF_READING, &oid, NULL) ||
+		    (filter && !ref_filter_match(info->ref, filter)))
+			continue;
+
+		objtype = oid_object_info(the_repository, &oid, NULL);
+		if (objtype < 0)
+			continue;
+
+		obj = lookup_object_by_type(the_repository, &oid, objtype);
+		add_name_decoration(DECORATION_REF_PSEUDO, info->ref, obj);
+	}
+}
+
 static int add_ref_decoration(const char *refname, const struct object_id *oid,
 			      int flags UNUSED,
 			      void *cb_data)
@@ -236,6 +264,7 @@ void load_ref_decorations(struct decoration_filter *filter, int flags)
 		decoration_loaded = 1;
 		decoration_flags = flags;
 		for_each_ref(add_ref_decoration, filter);
+		add_pseudoref_decorations(filter);
 		head_ref(add_ref_decoration, filter);
 		for_each_commit_graft(add_graft_decoration, filter);
 	}
diff --git a/refs.c b/refs.c
index 492b9f7d4e5..d960997aed1 100644
--- a/refs.c
+++ b/refs.c
@@ -149,6 +149,47 @@ struct ref_namespace_info ref_namespace[] = {
 		.ref = "refs/",
 		.decoration = DECORATION_REF,
 	},
+	[NAMESPACE_ORIG_HEAD] = {
+		.ref = "ORIG_HEAD",
+		.exact = 1,
+		.decoration = DECORATION_REF_PSEUDO,
+		.include = 1,
+	},
+	[NAMESPACE_MERGE_HEAD] = {
+		.ref = "MERGE_HEAD",
+		.exact = 1,
+		.decoration = DECORATION_REF_PSEUDO,
+		.include = 1,
+	},
+	[NAMESPACE_REBASE_HEAD] = {
+		.ref = "REBASE_HEAD",
+		.exact = 1,
+		.decoration = DECORATION_REF_PSEUDO,
+		.include = 1,
+	},
+	[NAMESPACE_CHERRY_PICK_HEAD] = {
+		.ref = "CHERRY_PICK_HEAD",
+		.exact = 1,
+		.decoration = DECORATION_REF_PSEUDO,
+		.include = 1,
+	},
+	[NAMESPACE_REVERT_HEAD] = {
+		.ref = "REVERT_HEAD",
+		.exact = 1,
+		.decoration = DECORATION_REF_PSEUDO,
+		.include = 1,
+	},
+	[NAMESPACE_BISECT_HEAD] = {
+		.ref = "BISECT_HEAD",
+		.exact = 1,
+		.decoration = DECORATION_REF_PSEUDO,
+		.include = 1,
+	},
+	[NAMESPACE_FETCH_HEAD] = {
+		.ref = "FETCH_HEAD",
+		.exact = 1,
+		.decoration = DECORATION_REF_PSEUDO,
+	},
 };
 
 void update_ref_namespace(enum ref_namespace namespace, char *ref)
diff --git a/refs.h b/refs.h
index b77691d787a..5ac1f308d07 100644
--- a/refs.h
+++ b/refs.h
@@ -1011,6 +1011,13 @@ enum ref_namespace {
 	NAMESPACE_PREFETCH,
 	NAMESPACE_REWRITTEN,
 	NAMESPACE_REFS,
+	NAMESPACE_ORIG_HEAD,
+	NAMESPACE_MERGE_HEAD,
+	NAMESPACE_REBASE_HEAD,
+	NAMESPACE_CHERRY_PICK_HEAD,
+	NAMESPACE_REVERT_HEAD,
+	NAMESPACE_BISECT_HEAD,
+	NAMESPACE_FETCH_HEAD,
 
 	/* Must be last */
 	NAMESPACE__COUNT
diff --git a/t/t4013/diff.log_--decorate=full_--all b/t/t4013/diff.log_--decorate=full_--all
index 6b0b334a5d6..9ebdd9b14fa 100644
--- a/t/t4013/diff.log_--decorate=full_--all
+++ b/t/t4013/diff.log_--decorate=full_--all
@@ -39,7 +39,7 @@ Date:   Mon Jun 26 00:03:00 2006 +0000
 
     Side
 
-commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 (ORIG_HEAD)
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:02:00 2006 +0000
 
diff --git a/t/t4013/diff.log_--decorate=full_--clear-decorations_--all b/t/t4013/diff.log_--decorate=full_--clear-decorations_--all
index 1c030a6554e..7d16978e7f6 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 <author@example.com>
 Date:   Mon Jun 26 00:03:00 2006 +0000
 
     Side
 
-commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 (ORIG_HEAD)
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:02:00 2006 +0000
 
diff --git a/t/t4013/diff.log_--decorate_--all b/t/t4013/diff.log_--decorate_--all
index c7df1f58141..46dde03cffa 100644
--- a/t/t4013/diff.log_--decorate_--all
+++ b/t/t4013/diff.log_--decorate_--all
@@ -39,7 +39,7 @@ Date:   Mon Jun 26 00:03:00 2006 +0000
 
     Side
 
-commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 (ORIG_HEAD)
 Author: A U Thor <author@example.com>
 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 88be82cce31..4f9be50ce02 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 <author@example.com>
 Date:   Mon Jun 26 00:03:00 2006 +0000
 
     Side
 
-commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 (ORIG_HEAD)
 Author: A U Thor <author@example.com>
 Date:   Mon Jun 26 00:02:00 2006 +0000
 
diff --git a/t/t4202-log.sh b/t/t4202-log.sh
index af4a123cd22..ea048cb4a29 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
 '
 
@@ -1082,7 +1085,7 @@ test_expect_success 'decorate-refs focus from default' '
 test_expect_success '--clear-decorations overrides defaults' '
 	cat >expect.default <<-\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)
@@ -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 4b51e34f8b2..0b32e0bb8e9 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="<BOLD;REVERSE;YELLOW>" &&
 	c_stash="<MAGENTA>" &&
 	c_ref="<BLUE>" &&
+	c_pseudoref="<BOLD;CYAN>" &&
 	c_HEAD="<CYAN>" &&
 	c_grafted="<BLACK>" &&
 	c_symbol="<WHITE>" &&
@@ -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
 '
 
-- 
2.42.GIT


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* Re: [PATCH 0/7] log: decorate pseudorefs and other refs
  2023-10-19 19:39 ` [PATCH 0/7] log: decorate pseudorefs and other refs Andy Koppe
@ 2023-10-22  0:13   ` Junio C Hamano
  2023-10-22 21:49     ` Andy Koppe
  2023-10-22 21:44   ` [PATCH v2 0/6] " Andy Koppe
  1 sibling, 1 reply; 31+ messages in thread
From: Junio C Hamano @ 2023-10-22  0:13 UTC (permalink / raw)
  To: Andy Koppe; +Cc: git

Andy Koppe <andy.koppe@gmail.com> writes:

> This patch series adds three slots to the color.decorate.<slot> config
> option:
> - 'symbol' for coloring the punctuation symbols used around the refs in
>   decorations, which currently use the same color as the commit hash.
> - 'ref' for coloring refs other than branches, remote-tracking branches,
>   tags and the stash, which currently are not colored when included in
>   decorations through custom decoration filter options.
> - 'pseudoref' for coloring pseudorefs such as ORIG_HEAD or MERGE_HEAD.
>   Include them in decorations by default.
>
> This series is to replace the 'decorate: add color.decorate.symbols
> config option' patch proposed at:
> https://lore.kernel.org/git/20231003205442.22963-1-andy.koppe@gmail.com

If that is the case, it probably would have been nicer to mark the
series as [PATCH v2].

Also, can you make messages [1/7]..[7/7] replies to [0/7] when you
send them out?  It seems that all 8 of them (including the cover
letter) are replies to the previous round, which looked a bit
unusual.


As to the contents of the series:

 [1/7] nicely lays out the color documentation; I do not think the
       extra verbosity was absolutely needed for existing ones
       (e.g., when a reader sees 'tag', the reader knows the color
       will be applied to tags), but the more exotic ones the series
       will be adding may deserve extra explanation on what they
       are, so I guess it is OK.

 [2/7] is a trivial readability improvement.  It obviously should be
       left outside the scope of this series, but we should notice
       the same pattern in similar color tables (e.g., wt-status.c
       has one, diff.c has another) and perform the same clean-up as
       a #leftoverbits item.

 [3/7] They way _NIL color is used to control the defaulting looked
       a bit unusual, but clever way to use a non-constant color
       defined elsewhere as its default.  A similar trick is used in
       wt-status.c:color() for STATUS_ONBRANCH, so this is nothing
       new.

 [4/7] The name of new member .include added to ref_namespace_info
       will not be understood by anybody unless they are too deeply
       obsessed by decoration mechansim.  As the namespace_info
       covers far wider interest, so a name that *shouts* that it is
       about decoration filter must be used to be understood by
       readers of the code.

       To be quite honest, "decoration filter" is probably a name
       that will not be understood by anybody, but coming up with a
       better name for it is probably outside the scope of this
       series.

 [5/7] I am not sure if "other refs" should be an item in the
       namespace_info array.  If it is truly "catch-all", then
       shouldn't the refs in other namespaces without their own
       decoration (e.g. ones in refs/notes/ and refs/prefetch/) be
       colored in the same way as this new class?  And if so, having
       it as an independent element that sits next to these other
       classes smells like a strange design.

       Another more worrying thing is that existing .ref members are
       designed to never overlap with each other, but this one
       obviously does.  When a caller with a ref (or a pseudoref)
       asks "which namespace does this one belong to", does the
       existing code still do the right thing with this new element?
       Without it, because there was no overlap, an implementation
       can randomly search in the namespace_info table and stop at
       the first hit, but now with the overlapping and widely open
       .ref = "refs/", the implementation of the search must know
       that it is a fallback position (i.e. if it found a match with
       the fallback .ref = "refs/" , unless it looked at all other
       entries that could begin with "refs/" and are more specific,
       it needs to keep going).

 [6/7] This is pretty straight-forward, assuming that the existing
       is_pseudoref_syntax() function does the right thing.  I am
       not sure about that, though.  A refname with '-' is allowed
       to be called a pseudoref???

       Also, not a fault of this patch, but the "_syntax" in its
       name is totally unnecessary, I would think.  At first glance,
       I suspected that the excuse to append _syntax may have been
       to signal the fact that the helper function does not check if
       there actually is such a ref, but examining a few helpers
       defined nearby tells us that such an excuse does not make
       sense:

           int is_per_worktree_ref(const char *) {
		   return starts_with(refname, "refs/worktree/") ||
			  starts_with(refname, "refs/bisect/") ||
			  starts_with(refname, "refs/rewritten/");
	   }
           int is_pseudoref_syntax(const char *);
           int is_current_worktree_ref(const char *ref) {
                   return is_pseudoref_syntax(ref) || is_per_worktree_ref(ref);
           }

       All these three work on the refname and based on what is in
       that refname string, decides what kind of ref it is.  There
       is nothing especially "syntax" about the second one, and we
       should rename it as part of #leftoverbits clean-up effort.

       Another unrelated tangent is that is_per_worktree_ref() shown
       above and the namespace_info array we saw earlier are not
       even aware of each other, which is maintenance nightmare
       waiting to happen.

 [7/7] Allowing pseudorefs to optionally used when decorating might
       be a good idea, but I do not think it is particularly a good
       design decision to enable it by default.  

       Each of them forming a separate "namespace" also looks like a
       poor design, as being able to group multiple things into one
       family and treat them the same way is the primary point of
       "namespace", I would think.  You do not want to say "I want
       to decorate off of ORIG_HEAD and FETCH_HEAD"; instead you
       would want to say "I want to decorate off of any pseudoref".



^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v2 0/6] log: decorate pseudorefs and other refs
  2023-10-19 19:39 ` [PATCH 0/7] log: decorate pseudorefs and other refs Andy Koppe
  2023-10-22  0:13   ` Junio C Hamano
@ 2023-10-22 21:44   ` Andy Koppe
  2023-10-22 21:44     ` [PATCH v2 1/6] config: restructure color.decorate documentation Andy Koppe
                       ` (6 more replies)
  1 sibling, 7 replies; 31+ messages in thread
From: Andy Koppe @ 2023-10-22 21:44 UTC (permalink / raw)
  To: git; +Cc: gitster, Andy Koppe

This patch series implements decoration with pseudorefs and adds three
slots to the color.decorate.<slot> config:
- 'symbol' for coloring the punctuation symbols used around the refs in
  decorations, which currently use the same color as the commit hash.
- 'ref' for coloring refs other than branches, remote-tracking branches,
  tags and the stash, which currently are not colored when included in
  decorations through custom decoration filter options.
- 'pseudoref' for coloring pseudorefs such as ORIG_HEAD or MERGE_HEAD.

CI: https://github.com/ak2/git/actions/runs/6605893645

Andy Koppe (6):
  config: restructure color.decorate documentation
  log: add color.decorate.symbol config variable
  log: add color.decorate.ref config variable
  refs: add pseudorefs array and iteration functions
  refs: exempt pseudorefs from pattern prefixing
  log: add color.decorate.pseudoref config variable

 Documentation/config/color.txt                | 32 +++++++-
 commit.h                                      |  3 +
 log-tree.c                                    | 43 +++++++++--
 refs.c                                        | 59 +++++++++++++--
 refs.h                                        |  5 ++
 ..._--decorate=full_--clear-decorations_--all |  4 +-
 ...f.log_--decorate_--clear-decorations_--all |  4 +-
 t/t4202-log.sh                                | 21 +++---
 t/t4207-log-decoration-colors.sh              | 74 +++++++++++--------
 9 files changed, 185 insertions(+), 60 deletions(-)

-- 
2.42.GIT


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v2 1/6] config: restructure color.decorate documentation
  2023-10-22 21:44   ` [PATCH v2 0/6] " Andy Koppe
@ 2023-10-22 21:44     ` Andy Koppe
  2023-10-22 21:44     ` [PATCH v2 2/6] log: add color.decorate.symbol config variable Andy Koppe
                       ` (5 subsequent siblings)
  6 siblings, 0 replies; 31+ messages in thread
From: Andy Koppe @ 2023-10-22 21:44 UTC (permalink / raw)
  To: git; +Cc: gitster, Andy Koppe

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 <andy.koppe@gmail.com>
---
 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.<slot>::
 	`oldBold`, and `newBold` (see linkgit:git-range-diff[1] for details).
 
 color.decorate.<slot>::
-	Use customized color for 'git log --decorate' output.  `<slot>` 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 `<slot>` 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
-- 
2.42.GIT


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v2 2/6] log: add color.decorate.symbol config variable
  2023-10-22 21:44   ` [PATCH v2 0/6] " Andy Koppe
  2023-10-22 21:44     ` [PATCH v2 1/6] config: restructure color.decorate documentation Andy Koppe
@ 2023-10-22 21:44     ` Andy Koppe
  2023-10-22 21:44     ` [PATCH v2 3/6] log: add color.decorate.ref " Andy Koppe
                       ` (4 subsequent siblings)
  6 siblings, 0 replies; 31+ messages in thread
From: Andy Koppe @ 2023-10-22 21:44 UTC (permalink / raw)
  To: git; +Cc: gitster, Andy Koppe

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.<slot> 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 <andy.koppe@gmail.com>
---
 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.<slot>::
 	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 504da6b519..5ad168458e 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -41,6 +41,7 @@ static char decoration_colors[][COLOR_MAXLEN] = {
 	GIT_COLOR_BOLD_MAGENTA,	/* REF_STASH */
 	GIT_COLOR_BOLD_CYAN,	/* REF_HEAD */
 	GIT_COLOR_BOLD_BLUE,	/* GRAFTED */
+	GIT_COLOR_NIL,		/* SYMBOL */
 };
 
 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="<RESET>" &&
@@ -29,6 +30,7 @@ test_expect_success setup '
 	c_stash="<MAGENTA>" &&
 	c_HEAD="<CYAN>" &&
 	c_grafted="<BLACK>" &&
+	c_symbol="<WHITE>" &&
 
 	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 &&
-- 
2.42.GIT


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v2 3/6] log: add color.decorate.ref config variable
  2023-10-22 21:44   ` [PATCH v2 0/6] " Andy Koppe
  2023-10-22 21:44     ` [PATCH v2 1/6] config: restructure color.decorate documentation Andy Koppe
  2023-10-22 21:44     ` [PATCH v2 2/6] log: add color.decorate.symbol config variable Andy Koppe
@ 2023-10-22 21:44     ` Andy Koppe
  2023-10-22 21:44     ` [PATCH v2 4/6] refs: add pseudorefs array and iteration functions Andy Koppe
                       ` (3 subsequent siblings)
  6 siblings, 0 replies; 31+ messages in thread
From: Andy Koppe @ 2023-10-22 21:44 UTC (permalink / raw)
  To: git; +Cc: gitster, Andy Koppe

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 <andy.koppe@gmail.com>
---
 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.<slot>::
 	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 5ad168458e..36558f3008 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -39,6 +39,7 @@ static char decoration_colors[][COLOR_MAXLEN] = {
 	GIT_COLOR_BOLD_RED,	/* REF_REMOTE */
 	GIT_COLOR_BOLD_YELLOW,	/* REF_TAG */
 	GIT_COLOR_BOLD_MAGENTA,	/* REF_STASH */
+	GIT_COLOR_BOLD_MAGENTA, /* REF */
 	GIT_COLOR_BOLD_CYAN,	/* REF_HEAD */
 	GIT_COLOR_BOLD_BLUE,	/* GRAFTED */
 	GIT_COLOR_NIL,		/* SYMBOL */
@@ -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="<RED>" &&
 	c_tag="<BOLD;REVERSE;YELLOW>" &&
 	c_stash="<MAGENTA>" &&
+	c_ref="<BLUE>" &&
 	c_HEAD="<CYAN>" &&
 	c_grafted="<BLACK>" &&
 	c_symbol="<WHITE>" &&
 
 	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
 '
 
-- 
2.42.GIT


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v2 4/6] refs: add pseudorefs array and iteration functions
  2023-10-22 21:44   ` [PATCH v2 0/6] " Andy Koppe
                       ` (2 preceding siblings ...)
  2023-10-22 21:44     ` [PATCH v2 3/6] log: add color.decorate.ref " Andy Koppe
@ 2023-10-22 21:44     ` Andy Koppe
  2023-10-22 21:44     ` [PATCH v2 5/6] refs: exempt pseudorefs from pattern prefixing Andy Koppe
                       ` (2 subsequent siblings)
  6 siblings, 0 replies; 31+ messages in thread
From: Andy Koppe @ 2023-10-22 21:44 UTC (permalink / raw)
  To: git; +Cc: gitster, Andy Koppe

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 <andy.koppe@gmail.com>
---
 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);
 
-- 
2.42.GIT


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v2 5/6] refs: exempt pseudorefs from pattern prefixing
  2023-10-22 21:44   ` [PATCH v2 0/6] " Andy Koppe
                       ` (3 preceding siblings ...)
  2023-10-22 21:44     ` [PATCH v2 4/6] refs: add pseudorefs array and iteration functions Andy Koppe
@ 2023-10-22 21:44     ` Andy Koppe
  2023-10-22 21:44     ` [PATCH v2 6/6] log: add color.decorate.pseudoref config variable Andy Koppe
  2023-10-23 22:11     ` [PATCH v3 0/7] log: decorate pseudorefs and other refs Andy Koppe
  6 siblings, 0 replies; 31+ messages in thread
From: Andy Koppe @ 2023-10-22 21:44 UTC (permalink / raw)
  To: git; +Cc: gitster, Andy Koppe

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 <andy.koppe@gmail.com>
---
 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, "/");
-- 
2.42.GIT


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v2 6/6] log: add color.decorate.pseudoref config variable
  2023-10-22 21:44   ` [PATCH v2 0/6] " Andy Koppe
                       ` (4 preceding siblings ...)
  2023-10-22 21:44     ` [PATCH v2 5/6] refs: exempt pseudorefs from pattern prefixing Andy Koppe
@ 2023-10-22 21:44     ` Andy Koppe
  2023-10-23 22:11     ` [PATCH v3 0/7] log: decorate pseudorefs and other refs Andy Koppe
  6 siblings, 0 replies; 31+ messages in thread
From: Andy Koppe @ 2023-10-22 21:44 UTC (permalink / raw)
  To: git; +Cc: gitster, Andy Koppe

Add the ability to show pseudorefs in log decorations, and add config
variable color.decorate.pseudoref to determine their color. They will
not be shown unless the default decoration filtering is overridden with
the relevant log options such as --clear-decorations or
log.initialDecorationSet.

Signed-off-by: Andy Koppe <andy.koppe@gmail.com>
---
 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.<slot>::
 	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.<slot>::
 --
 +
 (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 36558f3008..4091b55532 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -41,6 +41,7 @@ static char decoration_colors[][COLOR_MAXLEN] = {
 	GIT_COLOR_BOLD_MAGENTA,	/* REF_STASH */
 	GIT_COLOR_BOLD_MAGENTA, /* REF */
 	GIT_COLOR_BOLD_CYAN,	/* REF_HEAD */
+	GIT_COLOR_BOLD_BLUE,	/* REF_PSEUDO */
 	GIT_COLOR_BOLD_BLUE,	/* GRAFTED */
 	GIT_COLOR_NIL,		/* SYMBOL */
 };
@@ -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 <author@example.com>
 Date:   Mon Jun 26 00:03:00 2006 +0000
 
     Side
 
-commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 (ORIG_HEAD)
 Author: A U Thor <author@example.com>
 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 <author@example.com>
 Date:   Mon Jun 26 00:03:00 2006 +0000
 
     Side
 
-commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 (ORIG_HEAD)
 Author: A U Thor <author@example.com>
 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="<BOLD;REVERSE;YELLOW>" &&
 	c_stash="<MAGENTA>" &&
 	c_ref="<BLUE>" &&
+	c_pseudoref="<BOLD;CYAN>" &&
 	c_HEAD="<CYAN>" &&
 	c_grafted="<BLACK>" &&
 	c_symbol="<WHITE>" &&
@@ -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
 '
 
-- 
2.42.GIT


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* Re: [PATCH 0/7] log: decorate pseudorefs and other refs
  2023-10-22  0:13   ` Junio C Hamano
@ 2023-10-22 21:49     ` Andy Koppe
  2023-10-23  0:20       ` Junio C Hamano
  0 siblings, 1 reply; 31+ messages in thread
From: Andy Koppe @ 2023-10-22 21:49 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

On 22/10/2023 01:13, Junio C Hamano wrote:
> Andy Koppe <andy.koppe@gmail.com> writes:
>> This series is to replace the 'decorate: add color.decorate.symbols
>> config option' patch proposed at:
>> https://lore.kernel.org/git/20231003205442.22963-1-andy.koppe@gmail.com
> 
> If that is the case, it probably would have been nicer to mark the
> series as [PATCH v2].

Thanks, I wasn't sure about that due to the change in title and increase 
in scope. I shall err towards version-bumping in any future such cases.

> Also, can you make messages [1/7]..[7/7] replies to [0/7] when you
> send them out?  It seems that all 8 of them (including the cover
> letter) are replies to the previous round, which looked a bit
> unusual.

Not quite sure how that happened, but I think my mistake was passing 
--in-reply-to to git-format-patch instead of git-send-email.

>   [2/7] is a trivial readability improvement.  It obviously should be
>         left outside the scope of this series, but we should notice
>         the same pattern in similar color tables (e.g., wt-status.c
>         has one, diff.c has another) and perform the same clean-up as
>         a #leftoverbits item.

Okay, I've removed that commit in v2. (I should have mentioned in the 
commit message that it was triggered by the inconsistency with the 
immediately following color_decorate_slots array, which uses designated 
initializers.)

>   [4/7] The name of new member .include added to ref_namespace_info
>         will not be understood by anybody unless they are too deeply
>         obsessed by decoration mechansim.  As the namespace_info
>         covers far wider interest, so a name that *shouts* that it is
>         about decoration filter must be used to be understood by
>         readers of the code

Agreed.

>   [5/7] I am not sure if "other refs" should be an item in the
>         namespace_info array.  If it is truly "catch-all", then
>         shouldn't the refs in other namespaces without their own
>         decoration (e.g. ones in refs/notes/ and refs/prefetch/) be
>         colored in the same way as this new class?

They would, because add_ref_decoration() skips ref_namespace entries 
without a decoration type, so they would fall through to "refs/" and 
pick up the DECORATION_REF type.

>         And if so, having
>         it as an independent element that sits next to these other
>         classes smells like a strange design. >
>         Another more worrying thing is that existing .ref members are
>         designed to never overlap with each other, but this one
>         obviously does.  When a caller with a ref (or a pseudoref)
>         asks "which namespace does this one belong to", does the
>         existing code still do the right thing with this new element?
>         Without it, because there was no overlap, an implementation
>         can randomly search in the namespace_info table and stop at
>         the first hit, but now with the overlapping and widely open
>         .ref = "refs/", the implementation of the search must know
>         that it is a fallback position (i.e. if it found a match with
>         the fallback .ref = "refs/" , unless it looked at all other
>         entries that could begin with "refs/" and are more specific,
>         it needs to keep going).

Fair points. I've rewritten things to not touch the ref_namespace array.
>   [6/7] This is pretty straight-forward, assuming that the existing
>         is_pseudoref_syntax() function does the right thing.  I am
>         not sure about that, though.  A refname with '-' is allowed
>         to be called a pseudoref???
> 
>         Also, not a fault of this patch, but the "_syntax" in its
>         name is totally unnecessary, I would think.  At first glance,
>         I suspected that the excuse to append _syntax may have been
>         to signal the fact that the helper function does not check if
>         there actually is such a ref, but examining a few helpers
>         defined nearby tells us that such an excuse does not make
>         sense:

I've dropped the use of that function from the change, checking against 
the actual pseudoref names instead.

>   [7/7] Allowing pseudorefs to optionally used when decorating might
>         be a good idea, but I do not think it is particularly a good
>         design decision to enable it by default.

Okay!

>         Each of them forming a separate "namespace" also looks like a
>         poor design, as being able to group multiple things into one
>         family and treat them the same way is the primary point of
>         "namespace", I would think.

Fair enough, although the array already contains HEAD and refs/stash as 
singletons. I had vacillated about shoe-horning the pseudorefs in there, 
and was swayed by having a single place to define which (pseudo)refs 
should be included in decorations by default. That motivation goes away 
with all the pseudorefs off by default.

I've rewritten things to handle the pseudorefs separately from the 
ref_namespace array, with iteration functions similar to the ones used 
for HEAD and proper refs.

 >         You do not want to say "I want
 >         to decorate off of ORIG_HEAD and FETCH_HEAD"; instead you
 >         would want to say "I want to decorate off of any pseudoref".

They can now all be enabled with --clear-decorations or 
log.initialDecorationSet=all, or be controlled individually with the 
other filter options.

Thank you very much for the review!
Andy

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 0/7] log: decorate pseudorefs and other refs
  2023-10-22 21:49     ` Andy Koppe
@ 2023-10-23  0:20       ` Junio C Hamano
  2023-10-23 22:15         ` Andy Koppe
  0 siblings, 1 reply; 31+ messages in thread
From: Junio C Hamano @ 2023-10-23  0:20 UTC (permalink / raw)
  To: Andy Koppe; +Cc: git

Andy Koppe <andy.koppe@gmail.com> writes:

>>   [2/7] is a trivial readability improvement.  It obviously should be
>>         left outside the scope of this series, but we should notice
>>         the same pattern in similar color tables (e.g., wt-status.c
>>         has one, diff.c has another) and perform the same clean-up as
>>         a #leftoverbits item.
>
> Okay, I've removed that commit in v2. (I should have mentioned in the
> commit message that it was triggered by the inconsistency with the
> immediately following color_decorate_slots array, which uses
> designated initializers.)

Sorry, that is not what I meant.  [2/7] as a preliminary clean-up to
work in the same area does make very much sense.  What I meant to be
"outside the scope" was to make similar fixes to other color tables
that this series does not care about.

>>         .ref = "refs/", the implementation of the search must know
>>         that it is a fallback position (i.e. if it found a match with
>>         the fallback .ref = "refs/" , unless it looked at all other
>>         entries that could begin with "refs/" and are more specific,
>>         it needs to keep going).
>
> Fair points. I've rewritten things to not touch the ref_namespace array.

Well, the namespace_info mechanism still may be a good place to have
the necessary information; it may be that the current implementation
detail of how a given ref is classified to one of the namespaces is
too limiting---it essentially allows the string match with the .ref
member.  But we can imagine that it could be extended a bit, e.g.

	struct ref_namespace_info {
		char *ref;
		int (*membership)(const char *, const struct ref_namespace_info *);
		... other members ...;
	};

where the .membership member is used in add_ref_decoration() to
determine the membership of a given "refname" to the namespace "i"
perhaps like so:

	struct ref_namespace_info *info = &ref_namespace[i];

	if (!info->decoration)
		continue;
+	if (info->membership) {
+		if (info->membership(refname, info)) {
+			deco_type = info->decoration;
+			break;
+		}
+	} else if (info->exact) {
-	if (info->exact) {
		if (!strcmp(refname, info->ref)) {
			deco_type = info_decoration;
			break;
	}

Then you can arrange the pseudoref class to use .membership function
perhaps like this:

	static int pseudoref_namespace_membership(
		const char *refname, const struct ref_namespace_info *info UNUSED
	)
	{
		return is_pseudoref(refname);
	}

and make them all into a single class.

What I called a bad design was to reuse the namespace_info code
without extending it to suit our needs.

This comment will probably affect everything below.

>>   [6/7] This is pretty straight-forward, assuming that the existing
>>         is_pseudoref_syntax() function does the right thing.  I am
>>         not sure about that, though.  A refname with '-' is allowed
>>         to be called a pseudoref???
>>         Also, not a fault of this patch, but the "_syntax" in its
>>         name is totally unnecessary, I would think.  At first glance,
>>         I suspected that the excuse to append _syntax may have been
>>         to signal the fact that the helper function does not check if
>>         there actually is such a ref, but examining a few helpers
>>         defined nearby tells us that such an excuse does not make
>>         sense:
>
> I've dropped the use of that function from the change, checking
> against the actual pseudoref names instead.
>
>>   [7/7] Allowing pseudorefs to optionally used when decorating might
>>         be a good idea, but I do not think it is particularly a good
>>         design decision to enable it by default.
>
> Okay!
>
>>         Each of them forming a separate "namespace" also looks like a
>>         poor design, as being able to group multiple things into one
>>         family and treat them the same way is the primary point of
>>         "namespace", I would think.
>
> Fair enough, although the array already contains HEAD and refs/stash
> as singletons.

But these deserve to be singletons, don't they?  There is no other
thing that behaves like HEAD; there is no other thing that behaves
like stash; and they do not behave like each other.

Having said that, I do not think it makes much sense to decorate a
commit off of refs/stash, as the true richeness of the stash is not
in its history but in its reflog, which the decoration code does not
dig into.  But obviously it is not a part of the topic we are
discussing (unless, of course, we are not "adding" new decoration
sources and colors, but we are improving the decoration sources and
colors by adding new useful ones while retiring existing useless
ones).

Thanks.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v3 0/7] log: decorate pseudorefs and other refs
  2023-10-22 21:44   ` [PATCH v2 0/6] " Andy Koppe
                       ` (5 preceding siblings ...)
  2023-10-22 21:44     ` [PATCH v2 6/6] log: add color.decorate.pseudoref config variable Andy Koppe
@ 2023-10-23 22:11     ` Andy Koppe
  2023-10-23 22:11       ` [PATCH v3 1/7] config: restructure color.decorate documentation Andy Koppe
                         ` (6 more replies)
  6 siblings, 7 replies; 31+ messages in thread
From: Andy Koppe @ 2023-10-23 22:11 UTC (permalink / raw)
  To: git; +Cc: gitster, stolee, Andy Koppe

This patch series implements decoration with pseudorefs and adds three
slots to the color.decorate.<slot> config:
- 'symbol' for coloring the punctuation symbols used around the refs in
  decorations, which currently use the same color as the commit hash.
- 'ref' for coloring refs other than branches, remote-tracking branches,
  tags and the stash, which currently are not colored when included in
  decorations through custom decoration filter options.
- 'pseudoref' for coloring pseudorefs such as ORIG_HEAD or MERGE_HEAD.

CI: https://github.com/ak2/git/actions/runs/6618230811

Andy Koppe (7):
  config: restructure color.decorate documentation
  log: use designated inits for decoration_colors
  log: add color.decorate.symbol config variable
  log: add color.decorate.ref config variable
  refs: add pseudorefs array and iteration functions
  refs: exempt pseudorefs from pattern prefixing
  log: add color.decorate.pseudoref config variable

 Documentation/config/color.txt                | 32 +++++++-
 commit.h                                      |  3 +
 log-tree.c                                    | 57 ++++++++++----
 refs.c                                        | 59 +++++++++++++--
 refs.h                                        |  5 ++
 ..._--decorate=full_--clear-decorations_--all |  4 +-
 ...f.log_--decorate_--clear-decorations_--all |  4 +-
 t/t4202-log.sh                                | 21 +++---
 t/t4207-log-decoration-colors.sh              | 74 +++++++++++--------
 9 files changed, 192 insertions(+), 67 deletions(-)

-- 
2.42.GIT


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v3 1/7] config: restructure color.decorate documentation
  2023-10-23 22:11     ` [PATCH v3 0/7] log: decorate pseudorefs and other refs Andy Koppe
@ 2023-10-23 22:11       ` Andy Koppe
  2023-10-23 22:11       ` [PATCH v3 2/7] log: use designated inits for decoration_colors Andy Koppe
                         ` (5 subsequent siblings)
  6 siblings, 0 replies; 31+ messages in thread
From: Andy Koppe @ 2023-10-23 22:11 UTC (permalink / raw)
  To: git; +Cc: gitster, stolee, Andy Koppe

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 <andy.koppe@gmail.com>
---
 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.<slot>::
 	`oldBold`, and `newBold` (see linkgit:git-range-diff[1] for details).
 
 color.decorate.<slot>::
-	Use customized color for 'git log --decorate' output.  `<slot>` 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 `<slot>` 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
-- 
2.42.GIT


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v3 2/7] log: use designated inits for decoration_colors
  2023-10-23 22:11     ` [PATCH v3 0/7] log: decorate pseudorefs and other refs Andy Koppe
  2023-10-23 22:11       ` [PATCH v3 1/7] config: restructure color.decorate documentation Andy Koppe
@ 2023-10-23 22:11       ` Andy Koppe
  2023-10-23 22:11       ` [PATCH v3 3/7] log: add color.decorate.symbol config variable Andy Koppe
                         ` (4 subsequent siblings)
  6 siblings, 0 replies; 31+ messages in thread
From: Andy Koppe @ 2023-10-23 22:11 UTC (permalink / raw)
  To: git; +Cc: gitster, stolee, Andy Koppe

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 <andy.koppe@gmail.com>
---
 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[] = {
-- 
2.42.GIT


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v3 3/7] log: add color.decorate.symbol config variable
  2023-10-23 22:11     ` [PATCH v3 0/7] log: decorate pseudorefs and other refs Andy Koppe
  2023-10-23 22:11       ` [PATCH v3 1/7] config: restructure color.decorate documentation Andy Koppe
  2023-10-23 22:11       ` [PATCH v3 2/7] log: use designated inits for decoration_colors Andy Koppe
@ 2023-10-23 22:11       ` Andy Koppe
  2023-10-23 22:11       ` [PATCH v3 4/7] log: add color.decorate.ref " Andy Koppe
                         ` (3 subsequent siblings)
  6 siblings, 0 replies; 31+ messages in thread
From: Andy Koppe @ 2023-10-23 22:11 UTC (permalink / raw)
  To: git; +Cc: gitster, stolee, Andy Koppe

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.<slot> 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 <andy.koppe@gmail.com>
---
 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.<slot>::
 	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="<RESET>" &&
@@ -29,6 +30,7 @@ test_expect_success setup '
 	c_stash="<MAGENTA>" &&
 	c_HEAD="<CYAN>" &&
 	c_grafted="<BLACK>" &&
+	c_symbol="<WHITE>" &&
 
 	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 &&
-- 
2.42.GIT


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v3 4/7] log: add color.decorate.ref config variable
  2023-10-23 22:11     ` [PATCH v3 0/7] log: decorate pseudorefs and other refs Andy Koppe
                         ` (2 preceding siblings ...)
  2023-10-23 22:11       ` [PATCH v3 3/7] log: add color.decorate.symbol config variable Andy Koppe
@ 2023-10-23 22:11       ` Andy Koppe
  2023-10-23 22:11       ` [PATCH v3 5/7] refs: add pseudorefs array and iteration functions Andy Koppe
                         ` (2 subsequent siblings)
  6 siblings, 0 replies; 31+ messages in thread
From: Andy Koppe @ 2023-10-23 22:11 UTC (permalink / raw)
  To: git; +Cc: gitster, stolee, Andy Koppe

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 <andy.koppe@gmail.com>
---
 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.<slot>::
 	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="<RED>" &&
 	c_tag="<BOLD;REVERSE;YELLOW>" &&
 	c_stash="<MAGENTA>" &&
+	c_ref="<BLUE>" &&
 	c_HEAD="<CYAN>" &&
 	c_grafted="<BLACK>" &&
 	c_symbol="<WHITE>" &&
 
 	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
 '
 
-- 
2.42.GIT


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v3 5/7] refs: add pseudorefs array and iteration functions
  2023-10-23 22:11     ` [PATCH v3 0/7] log: decorate pseudorefs and other refs Andy Koppe
                         ` (3 preceding siblings ...)
  2023-10-23 22:11       ` [PATCH v3 4/7] log: add color.decorate.ref " Andy Koppe
@ 2023-10-23 22:11       ` Andy Koppe
  2023-10-24  0:08         ` Junio C Hamano
  2024-02-05 18:55         ` Kousik Sanagavarapu
  2023-10-23 22:11       ` [PATCH v3 6/7] refs: exempt pseudorefs from pattern prefixing Andy Koppe
  2023-10-23 22:11       ` [PATCH v3 7/7] log: add color.decorate.pseudoref config variable Andy Koppe
  6 siblings, 2 replies; 31+ messages in thread
From: Andy Koppe @ 2023-10-23 22:11 UTC (permalink / raw)
  To: git; +Cc: gitster, stolee, Andy Koppe

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 <andy.koppe@gmail.com>
---
 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);
 
-- 
2.42.GIT


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v3 6/7] refs: exempt pseudorefs from pattern prefixing
  2023-10-23 22:11     ` [PATCH v3 0/7] log: decorate pseudorefs and other refs Andy Koppe
                         ` (4 preceding siblings ...)
  2023-10-23 22:11       ` [PATCH v3 5/7] refs: add pseudorefs array and iteration functions Andy Koppe
@ 2023-10-23 22:11       ` Andy Koppe
  2023-10-23 22:11       ` [PATCH v3 7/7] log: add color.decorate.pseudoref config variable Andy Koppe
  6 siblings, 0 replies; 31+ messages in thread
From: Andy Koppe @ 2023-10-23 22:11 UTC (permalink / raw)
  To: git; +Cc: gitster, stolee, Andy Koppe

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 <andy.koppe@gmail.com>
---
 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, "/");
-- 
2.42.GIT


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v3 7/7] log: add color.decorate.pseudoref config variable
  2023-10-23 22:11     ` [PATCH v3 0/7] log: decorate pseudorefs and other refs Andy Koppe
                         ` (5 preceding siblings ...)
  2023-10-23 22:11       ` [PATCH v3 6/7] refs: exempt pseudorefs from pattern prefixing Andy Koppe
@ 2023-10-23 22:11       ` Andy Koppe
  6 siblings, 0 replies; 31+ messages in thread
From: Andy Koppe @ 2023-10-23 22:11 UTC (permalink / raw)
  To: git; +Cc: gitster, stolee, Andy Koppe

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>
---
 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.<slot>::
 	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.<slot>::
 --
 +
 (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 <author@example.com>
 Date:   Mon Jun 26 00:03:00 2006 +0000
 
     Side
 
-commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 (ORIG_HEAD)
 Author: A U Thor <author@example.com>
 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 <author@example.com>
 Date:   Mon Jun 26 00:03:00 2006 +0000
 
     Side
 
-commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 (ORIG_HEAD)
 Author: A U Thor <author@example.com>
 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="<BOLD;REVERSE;YELLOW>" &&
 	c_stash="<MAGENTA>" &&
 	c_ref="<BLUE>" &&
+	c_pseudoref="<BOLD;CYAN>" &&
 	c_HEAD="<CYAN>" &&
 	c_grafted="<BLACK>" &&
 	c_symbol="<WHITE>" &&
@@ -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
 '
 
-- 
2.42.GIT


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* Re: [PATCH 0/7] log: decorate pseudorefs and other refs
  2023-10-23  0:20       ` Junio C Hamano
@ 2023-10-23 22:15         ` Andy Koppe
  0 siblings, 0 replies; 31+ messages in thread
From: Andy Koppe @ 2023-10-23 22:15 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, stolee

On 23/10/2023 01:20, Junio C Hamano wrote:
> Andy Koppe <andy.koppe@gmail.com> writes:
> 
>>>    [2/7] is a trivial readability improvement.  It obviously should be
>>>          left outside the scope of this series, but we should notice
>>>          the same pattern in similar color tables (e.g., wt-status.c
>>>          has one, diff.c has another) and perform the same clean-up as
>>>          a #leftoverbits item.
>>
>> Okay, I've removed that commit in v2. (I should have mentioned in the
>> commit message that it was triggered by the inconsistency with the
>> immediately following color_decorate_slots array, which uses
>> designated initializers.)
> 
> Sorry, that is not what I meant.  [2/7] as a preliminary clean-up to
> work in the same area does make very much sense.  What I meant to be
> "outside the scope" was to make similar fixes to other color tables
> that this series does not care about.

Ah, sorry for misreading. Commit reinstated in v3.


>> Fair enough, although the array already contains HEAD and refs/stash
>> as singletons.
> 
> But these deserve to be singletons, don't they?  There is no other
> thing that behaves like HEAD; there is no other thing that behaves
> like stash; and they do not behave like each other.

They do indeed, but arguably the pseudorefs are singletons rather than a 
namespace like refs/heads as well, as there is a defined and documented 
set of them.


>> I've rewritten things to not touch the ref_namespace array.
> 
> Well, the namespace_info mechanism still may be a good place to have
> the necessary information; it may be that the current implementation
> detail of how a given ref is classified to one of the namespaces is
> too limiting---it essentially allows the string match with the .ref
> member.  But we can imagine that it could be extended a bit, e.g.
> 
> 	struct ref_namespace_info {
> 		char *ref;
> 		int (*membership)(const char *, const struct ref_namespace_info *);
> 		... other members ...;
> 	};
> 
> where the .membership member is used in add_ref_decoration() to
> determine the membership of a given "refname" to the namespace "i"
> perhaps like so:
> 
> 	struct ref_namespace_info *info = &ref_namespace[i];
> 
> 	if (!info->decoration)
> 		continue;
> +	if (info->membership) {
> +		if (info->membership(refname, info)) {
> +			deco_type = info->decoration;
> +			break;
> +		}
> +	} else if (info->exact) {
> -	if (info->exact) {
> 		if (!strcmp(refname, info->ref)) {
> 			deco_type = info_decoration;
> 			break;
> 	}
> 
> Then you can arrange the pseudoref class to use .membership function
> perhaps like this:
> 
> 	static int pseudoref_namespace_membership(
> 		const char *refname, const struct ref_namespace_info *info UNUSED
> 	)
> 	{
> 		return is_pseudoref(refname);
> 	}
> 
> and make them all into a single class.

That's an interesting idea, but I'm not convinced it would buy us much, 
while also potentially complicating things for any other uses of the 
ref_namespace array.

My premise here is that we do need a list of the documented pseudorefs, 
so that we can iterate through them and add the ones that do exist to 
the decorations, whereby I admit that shoe-horning that list into the 
ref_namespace array wasn't a good idea. If that premise is wrong, and 
there's a better way to discover the pseudorefs, the following might be 
moot.

Sending each found pseudoref through add_ref_decoration() and its lookup 
of ref_namespace would just confirm what we already know: it's a 
pseudoref. Which is why both my initial attempt and the current one 
don't actually invoke add_ref_decoration() for them.

Could you have a closer look at the current design? It handles the 
pseudorefs separately from proper refs, with their own iteration and 
callback functions, which I think makes for simpler more self-contained 
changes than v1 or the approach suggested above.


> Having said that, I do not think it makes much sense to decorate a
> commit off of refs/stash, as the true richeness of the stash is not
> in its history but in its reflog, which the decoration code does not
> dig into.  But obviously it is not a part of the topic we are
> discussing (unless, of course, we are not "adding" new decoration
> sources and colors, but we are improving the decoration sources and
> colors by adding new useful ones while retiring existing useless
> ones).

I agree refs/stash is a weird one, and that it could be subsumed into 
the color.decoration.ref setting for 'refs/*' that I'm adding here, 
which is also why I chose the same default color for it. I'd be happy to 
drop color.decoration.stash if the minor break in compatibility for 
anyone who has customized it is acceptable. The setting would be quietly 
ignored.

Another related thought: the '--clear-decorations' option of git-log 
seems unfortunately named as it suggests the opposite of what it 
actually does, which is to enable all decorations (unless subsequently 
constrained with '--decorate-refs{,--exclude}=...').

Regards,
Andy

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 5/7] refs: add pseudorefs array and iteration functions
  2023-10-23 22:11       ` [PATCH v3 5/7] refs: add pseudorefs array and iteration functions Andy Koppe
@ 2023-10-24  0:08         ` Junio C Hamano
  2024-02-05 18:55         ` Kousik Sanagavarapu
  1 sibling, 0 replies; 31+ messages in thread
From: Junio C Hamano @ 2023-10-24  0:08 UTC (permalink / raw)
  To: Andy Koppe; +Cc: git, stolee

Andy Koppe <andy.koppe@gmail.com> writes:

> 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.

Makes sense, and we can later (ab|re)use the same mechanism to
extend "git for-each-ref" that currently only knows how to show
things under "refs/" hierarchy.

> 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.

Good.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 5/7] refs: add pseudorefs array and iteration functions
  2023-10-23 22:11       ` [PATCH v3 5/7] refs: add pseudorefs array and iteration functions Andy Koppe
  2023-10-24  0:08         ` Junio C Hamano
@ 2024-02-05 18:55         ` Kousik Sanagavarapu
  2024-02-07 22:02           ` Junio C Hamano
  1 sibling, 1 reply; 31+ messages in thread
From: Kousik Sanagavarapu @ 2024-02-05 18:55 UTC (permalink / raw)
  To: Andy Koppe; +Cc: git, Junio C Hamano

Andy Koppe <andy.koppe@gmail.com> wrote:

> 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 <andy.koppe@gmail.com>
> ---

[...]

> +/*
> + * 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);
>  }

The first thing that popped up in my head was "Should we somehow use
is_pseudoref_syntax() instead of manually listing these?" (although I
read in this thread later that Junio was okay with the listing) but then ...

I thought I saw something similar in some other thread (which entered
the mailing list much after this patch series was submitted) ...

	https://lore.kernel.org/git/20231221170715.110565-2-karthik.188@gmail.com/T/

The whole thread is really interesting but some points that are worth to
be mentioned in this context are

	" ... Patrick's reftable work based on Han-Wen's work revealed
	the need to treat FETCH_HEAD and MERGE_HEAD as "even more
	pecurilar than pseudorefs" that need different term (tentatively
	called "special refs") ... "

So since we are introducing this array in refs.c, which acts as a "refs
API" currently

	"A lot more reasonable thing to do may be to scan the
	$GIT_DIR for files whose name satisfy refs.c:is_pseudoref_syntax()
	and list them, instead of having a hardcoded list of these special
	refs.  In addition, when reftable and other backends that can
	natively store things outside refs/ hierarchy is in use, they ought
	to know what they have so enumerating these would not be an issue
	for them without having such a hardcoded table of names."

All that said, the above mentioned thread led to a series of patches for
a different purpose than this [1] (which are currently on their way to
"master" according to the latest "What's Cooking" email on Feb 2).  The
ones that have significance w.r.t. to THIS patch series though, are

	https://lore.kernel.org/git/20240129113527.607022-2-karthik.188@gmail.com/
	https://lore.kernel.org/git/20240129113527.607022-4-karthik.188@gmail.com/

(ignoring the reftable part).

I find these to make sense HERE because using the functions introduced
THERE are much more robust when dealing with pseudorefs and can be used
HERE.

I haven't given it much thought but I think we would still end up
writing "for_each_pseudoref()", although much differently from below
(and can't use "refs_for_each_all_refs()" directly) because of how we
call this function in PATCH 7/7 when actually doing the decoration - that
is the decoration for pseudorefs is different (?)

Another approach would be I think to refactor the whole of how
decorations with refs work and somehow use "refs_for_each_all_refs()"
with its callback handling how we decorate the various refs - I need to
dig deeper :) - since the end goal is to support showing all kinds of
refs when showing the log

	$ git log -1 --clear-decorations --oneline master
	2a540e432f (ORIG_HEAD, FETCH_HEAD, upstream/master, upstream/HEAD, master) The thirteenth batch

(with color enabled)

> +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);
>  
> -- 
> 2.42.GIT

So yeah, I just wanted to point out the above things as we would need to
refactor this commit and the commits following this - patches 6/7 and 7/7.

Thanks

[1]: https://lore.kernel.org/git/20240129113527.607022-1-karthik.188@gmail.com/

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v3 5/7] refs: add pseudorefs array and iteration functions
  2024-02-05 18:55         ` Kousik Sanagavarapu
@ 2024-02-07 22:02           ` Junio C Hamano
  0 siblings, 0 replies; 31+ messages in thread
From: Junio C Hamano @ 2024-02-07 22:02 UTC (permalink / raw)
  To: Kousik Sanagavarapu; +Cc: Andy Koppe, git

Kousik Sanagavarapu <five231003@gmail.com> writes:

> Andy Koppe <andy.koppe@gmail.com> wrote:
> ...
>> +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);
>>  }
>
> The first thing that popped up in my head was "Should we somehow use
> is_pseudoref_syntax() instead of manually listing these?" (although I
> read in this thread later that Junio was okay with the listing) but then ...
>
> I thought I saw something similar in some other thread (which entered
> the mailing list much after this patch series was submitted) ...
>
> 	https://lore.kernel.org/git/20231221170715.110565-2-karthik.188@gmail.com/T/

We are halting Karthik's topic to rethink its UI for now, but your
point stands.  We should use a unified definition of what pseudorefs
there are across the codebase for consistency, and Karthik's topic
would be a better place to do so.

Andy, let me drop this topic for now from my tree, and let's wait
until Karthik's "iterate over all refs" topic solidifies, at which
time an updated iteration (v4?)  of this topic hopefully can build
on top of it.

Thanks.

^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2024-02-07 22:03 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-10-03 20:54 [PATCH] decorate: add color.decorate.symbols config option Andy Koppe
2023-10-19 19:39 ` [PATCH 0/7] log: decorate pseudorefs and other refs Andy Koppe
2023-10-22  0:13   ` Junio C Hamano
2023-10-22 21:49     ` Andy Koppe
2023-10-23  0:20       ` Junio C Hamano
2023-10-23 22:15         ` Andy Koppe
2023-10-22 21:44   ` [PATCH v2 0/6] " Andy Koppe
2023-10-22 21:44     ` [PATCH v2 1/6] config: restructure color.decorate documentation Andy Koppe
2023-10-22 21:44     ` [PATCH v2 2/6] log: add color.decorate.symbol config variable Andy Koppe
2023-10-22 21:44     ` [PATCH v2 3/6] log: add color.decorate.ref " Andy Koppe
2023-10-22 21:44     ` [PATCH v2 4/6] refs: add pseudorefs array and iteration functions Andy Koppe
2023-10-22 21:44     ` [PATCH v2 5/6] refs: exempt pseudorefs from pattern prefixing Andy Koppe
2023-10-22 21:44     ` [PATCH v2 6/6] log: add color.decorate.pseudoref config variable Andy Koppe
2023-10-23 22:11     ` [PATCH v3 0/7] log: decorate pseudorefs and other refs Andy Koppe
2023-10-23 22:11       ` [PATCH v3 1/7] config: restructure color.decorate documentation Andy Koppe
2023-10-23 22:11       ` [PATCH v3 2/7] log: use designated inits for decoration_colors Andy Koppe
2023-10-23 22:11       ` [PATCH v3 3/7] log: add color.decorate.symbol config variable Andy Koppe
2023-10-23 22:11       ` [PATCH v3 4/7] log: add color.decorate.ref " Andy Koppe
2023-10-23 22:11       ` [PATCH v3 5/7] refs: add pseudorefs array and iteration functions Andy Koppe
2023-10-24  0:08         ` Junio C Hamano
2024-02-05 18:55         ` Kousik Sanagavarapu
2024-02-07 22:02           ` Junio C Hamano
2023-10-23 22:11       ` [PATCH v3 6/7] refs: exempt pseudorefs from pattern prefixing Andy Koppe
2023-10-23 22:11       ` [PATCH v3 7/7] log: add color.decorate.pseudoref config variable Andy Koppe
2023-10-19 19:39 ` [PATCH 1/7] config: restructure color.decorate documentation Andy Koppe
2023-10-19 19:39 ` [PATCH 2/7] log: use designated inits for decoration_colors Andy Koppe
2023-10-19 19:39 ` [PATCH 3/7] log: add color.decorate.symbol config option Andy Koppe
2023-10-19 19:39 ` [PATCH 4/7] refs: separate decoration type from default filter Andy Koppe
2023-10-19 19:39 ` [PATCH 5/7] log: add color.decorate.ref option for other refs Andy Koppe
2023-10-19 19:39 ` [PATCH 6/7] refs: exempt pseudoref patterns from prefixing Andy Koppe
2023-10-19 19:39 ` [PATCH 7/7] log: show pseudorefs in decorations Andy Koppe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).