All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Lê Duy Quang" <leduyquang753@gmail.com>
To: git@vger.kernel.org
Cc: "Lê Duy Quang" <leduyquang753@gmail.com>
Subject: [RFC PATCH 1/1] Add separator lines into `git log --graph`.
Date: Sun,  7 Apr 2024 12:10:31 +0700	[thread overview]
Message-ID: <20240407051031.6018-2-leduyquang753@gmail.com> (raw)
In-Reply-To: <20240407051031.6018-1-leduyquang753@gmail.com>

This is to separate out connected regions of the resulting commit graph so as
to not have them confused as belonging to the same timeline.
---
 graph.c                                |  55 +++++++++++-
 t/t4218-log-graph-connected-regions.sh | 119 +++++++++++++++++++++++++
 2 files changed, 170 insertions(+), 4 deletions(-)
 create mode 100755 t/t4218-log-graph-connected-regions.sh

diff --git a/graph.c b/graph.c
index 1ca34770ee..c0107c02fa 100644
--- a/graph.c
+++ b/graph.c
@@ -69,6 +69,12 @@ enum graph_state {
 	GRAPH_COLLAPSING
 };
 
+enum connected_region_state {
+	CONNECTED_REGION_FIRST_COMMIT,
+	CONNECTED_REGION_USE_CURRENT,
+	CONNECTED_REGION_NEW_REGION
+};
+
 static void graph_show_line_prefix(const struct diff_options *diffopt)
 {
 	if (!diffopt || !diffopt->line_prefix)
@@ -310,6 +316,12 @@ struct git_graph {
 	 * stored as an index into the array column_colors.
 	 */
 	unsigned short default_column_color;
+	/*
+	 * The state of which connected region the current commit belongs to.
+	 * This is used to output a clarifying separator line between
+	 * connected regions.
+	 */
+	enum connected_region_state connected_region_state;
 };
 
 static struct strbuf *diff_output_prefix_callback(struct diff_options *opt, void *data)
@@ -380,6 +392,7 @@ struct git_graph *graph_init(struct rev_info *opt)
 	 * This way we start at 0 for the first commit.
 	 */
 	graph->default_column_color = column_colors_max - 1;
+	graph->connected_region_state = CONNECTED_REGION_FIRST_COMMIT;
 
 	/*
 	 * Allocate a reasonably large default number of columns
@@ -729,9 +742,9 @@ static int graph_num_expansion_rows(struct git_graph *graph)
 
 static int graph_needs_pre_commit_line(struct git_graph *graph)
 {
-	return graph->num_parents >= 3 &&
+	return graph->connected_region_state == CONNECTED_REGION_NEW_REGION || (graph->num_parents >= 3 &&
 	       graph->commit_index < (graph->num_columns - 1) &&
-	       graph->expansion_row < graph_num_expansion_rows(graph);
+	       graph->expansion_row < graph_num_expansion_rows(graph));
 }
 
 void graph_update(struct git_graph *graph, struct commit *commit)
@@ -760,6 +773,12 @@ void graph_update(struct git_graph *graph, struct commit *commit)
 	 * commit.
 	 */
 	graph->prev_commit_index = graph->commit_index;
+	
+	/*
+	 * Determine whether this commit belongs to a new connected region.
+	 */
+	graph->connected_region_state = (graph->connected_region_state != CONNECTED_REGION_FIRST_COMMIT &&
+		graph->num_new_columns == 0) ? CONNECTED_REGION_NEW_REGION : CONNECTED_REGION_USE_CURRENT;
 
 	/*
 	 * Call graph_update_columns() to update
@@ -865,8 +884,28 @@ static void graph_output_skip_line(struct git_graph *graph, struct graph_line *l
 		graph_update_state(graph, GRAPH_COMMIT);
 }
 
-static void graph_output_pre_commit_line(struct git_graph *graph,
-					 struct graph_line *line)
+static void graph_output_separator_line(struct git_graph *graph, struct graph_line *line)
+{
+	/*
+	 * This function adds a row that separates two disconnected graphs,
+	 * as the appearance of multiple separate commits on top of each other
+	 * may cause a misunderstanding that they belong to a timeline.
+	 */
+	assert(graph->connected_region_state == CONNECTED_REGION_NEW_REGION);
+
+	/*
+	 * Output the row.
+	 */
+	graph_line_addstr(line, "---");
+
+	/*
+	 * Immediately move to GRAPH_COMMIT state as there for sure aren't going to be
+	 * any more pre-commit lines.
+	 */
+	graph_update_state(graph, GRAPH_COMMIT);
+}
+
+static void graph_output_parent_expansion_line(struct git_graph *graph, struct graph_line *line)
 {
 	int i, seen_this;
 
@@ -928,6 +967,14 @@ static void graph_output_pre_commit_line(struct git_graph *graph,
 		graph_update_state(graph, GRAPH_COMMIT);
 }
 
+static void graph_output_pre_commit_line(struct git_graph *graph, struct graph_line *line)
+{
+	if (graph->connected_region_state == CONNECTED_REGION_NEW_REGION)
+		graph_output_separator_line(graph, line);
+	else
+		graph_output_parent_expansion_line(graph, line);
+}
+
 static void graph_output_commit_char(struct git_graph *graph, struct graph_line *line)
 {
 	/*
diff --git a/t/t4218-log-graph-connected-regions.sh b/t/t4218-log-graph-connected-regions.sh
new file mode 100755
index 0000000000..4efe17827e
--- /dev/null
+++ b/t/t4218-log-graph-connected-regions.sh
@@ -0,0 +1,119 @@
+#!/bin/sh
+
+test_description="git log --graph connected regions"
+
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY/lib-terminal.sh"
+. "$TEST_DIRECTORY/lib-log-graph.sh"
+
+test_cmp_graph () {
+	lib_test_cmp_graph --format=%s "$@"
+}
+
+add_commit () {
+	touch $1 &&
+	git add $1 &&
+	git commit -m $1
+	git tag "$1-commit"
+}
+
+test_expect_success setup '
+	git checkout -b a &&
+	add_commit root &&
+	
+	add_commit a1 &&
+	add_commit a2 &&
+	add_commit a3 &&
+	
+	git checkout -b b root-commit &&
+	add_commit b1 &&
+	add_commit b2 &&
+	git checkout -b c &&
+	add_commit c3 &&
+	git checkout b &&
+	add_commit b3 &&
+	git merge c -m b4 &&
+	
+	git checkout -b d root-commit &&
+	add_commit d1 &&
+	add_commit d2 &&
+	git checkout -b e &&
+	add_commit e3 &&
+	git checkout d &&
+	add_commit d3 &&
+	add_commit d4
+'
+
+cat > expect <<\EOF
+* a3
+* a2
+* a1
+| *   b4
+| |\
+| | * c3
+| * | b3
+| |/
+| * b2
+| * b1
+|/
+| * d4
+| * d3
+| | * e3
+| |/
+| * d2
+| * d1
+|/
+* root
+EOF
+
+test_expect_success 'all commits' '
+	test_cmp_graph a b c d e
+'
+
+cat > expect <<\EOF
+* a3
+* a2
+* a1
+---
+*   b4
+|\
+| * c3
+* | b3
+|/
+* b2
+* b1
+---
+* d4
+* d3
+| * e3
+|/
+* d2
+* d1
+EOF
+
+test_expect_success 'without root commit' '
+	test_cmp_graph a b c d e ^root-commit
+'
+
+cat > expect <<\EOF
+* a3
+---
+*   b4
+|\
+| * c3
+* b3
+---
+* d4
+* d3
+---
+* e3
+EOF
+
+test_expect_success "branches' tips" '
+	test_cmp_graph a b c d e ^a2-commit ^b2-commit ^d2-commit
+'
+
+test_done
-- 
2.44.0


  reply	other threads:[~2024-04-07  5:10 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-04-07  5:10 [RFC PATCH 0/1] Add lines to `git log --graph` to separate connected regions Lê Duy Quang
2024-04-07  5:10 ` Lê Duy Quang [this message]
2024-04-07  5:47   ` [RFC PATCH 1/1] Add separator lines into `git log --graph` Eric Sunshine
2024-04-07  5:52     ` Eric Sunshine
2024-04-07  7:06       ` Quang Lê Duy
2024-04-07  8:35         ` Dragan Simic
2024-04-07  7:03     ` Quang Lê Duy
2024-04-07  9:07       ` Eric Sunshine
2024-04-07  5:30 ` [RFC PATCH 0/1] Add lines to `git log --graph` to separate connected regions Eric Sunshine
2024-04-07  5:37   ` Junio C Hamano
2024-04-07  6:40     ` Quang Lê Duy
2024-04-07  8:34       ` Dragan Simic
2024-04-07  8:46         ` Quang Lê Duy
2024-04-07  9:13           ` Dragan Simic
2024-04-08 15:49     ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240407051031.6018-2-leduyquang753@gmail.com \
    --to=leduyquang753@gmail.com \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.