git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / 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

  List information: http://vger.kernel.org/majordomo-info.html

* 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.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

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 read-only IMAP folder(s) and NNTP newsgroup(s).