git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jeff King <peff@peff.net>
To: Noam Postavsky <npostavs@users.sourceforge.net>
Cc: Johannes Sixt <j6t@kdbg.org>,
	Hemmo Nieminen <hemmo.nieminen@iki.fi>,
	git@vger.kernel.org
Subject: Re: [BUG] A part of an edge from an octopus merge gets colored, even with --color=never
Date: Sat, 8 Sep 2018 12:13:16 -0400	[thread overview]
Message-ID: <20180908161316.GA326@sigill.intra.peff.net> (raw)
In-Reply-To: <CAM-tV-_=4WuMGemm6RTB902-m8JfMKGp_OkQFuJMagPE8bOOtg@mail.gmail.com>

On Sat, Sep 01, 2018 at 08:34:41PM -0400, Noam Postavsky wrote:

> On 6 August 2018 at 17:26, Jeff King <peff@peff.net> wrote:
> 
> > I suspect it still has a bug, which is that it is handling this
> > first-parent-goes-left case, but probably gets the straight-parent case
> > wrong. But at least in this form, I think it is obvious to see where
> > that bug is (the "three" in the comment is not accurate in that latter
> > case, and it should be two).
> 
> Yes, thanks, it makes a lot more sense this way. I believe the
> attached handles both parent types correctly.

Great (and sorry for the delayed response).

Let me see if I understand it...

> diff --git a/graph.c b/graph.c
> index e1f6d3bdd..478c86dfb 100644
> --- a/graph.c
> +++ b/graph.c
> @@ -848,21 +848,45 @@ static int graph_draw_octopus_merge(struct git_graph *graph,
>  				    struct strbuf *sb)
>  {
>  	/*
> -	 * Here dashless_commits represents the number of parents
> -	 * which don't need to have dashes (because their edges fit
> -	 * neatly under the commit).
> +	 * Here dashless_commits represents the number of parents which don't
> +	 * need to have dashes (because their edges fit neatly under the
> +	 * commit).  And dashful_commits are the remaining ones.
>  	 */
>  	const int dashless_commits = 2;

Why is dashless commits always going to be 2? I thought at first that it
was representing the merge commit itself, plus the line of development
to the left. But the latter could be arbitrarily sized.

But that's not what it is, because we handle that by using
graph->commit_index in the iteration below. So I get that the merge
commit itself does not need a dash. What's the other one?

> +	int dashful_commits = graph->num_parents - dashless_commits;

OK, this makes sense.

> +	/*
> +	 * Usually, each parent gets its own column, like this:
> +	 *
> +	 * | *-.
> +	 * | |\ \
> +	 * | | | *
> +	 *
> +	 * Sometimes the first parent goes into an existing column, like this:
> +	 *
> +	 * | *-.
> +	 * | |\ \
> +	 * |/ / /
> +	 *
> +	 */
> +	int parent_in_existing_cols = graph->num_parents -
> +		(graph->num_new_columns - graph->num_columns);

Ah, OK, this is the magic part: we compare num_new_columns versus
num_columns to see which case we have. Makes sense. And this comment is
very welcome to explain it visually.

> +	/*
> +	 * Draw the dashes.  We start in the column following the
> +	 * dashless_commits, but subtract out the parent which goes to an
> +	 * existing column: we've already counted that column in commit_index.
> +	 */
> +	int first_col = graph->commit_index + dashless_commits
> +		- parent_in_existing_cols;
> +	int i;

OK, so we start at the commit_index, which makes sense. We skip past the
dashless commits (which includes the merge itself, plus the other
mystery one). And then we go back by the parents in existing columns,
which I think is either 1 or 2.

And I think that may be the root of my confusion. The other "dashless"
commit is the parent we've already printed before hitting this function,
the left-hand line that goes all the way down below where we print the
other parents.

So I think this is doing the right thing. I'm not sure if there's a
better way to explain "dashless" or not.

> +	for (i = 0; i < dashful_commits; i++) {
> +		strbuf_write_column(sb, &graph->new_columns[i+first_col], '-');
> +		strbuf_write_column(sb, &graph->new_columns[i+first_col],
> +				    i == dashful_commits-1 ? '.' : '-');
>  	}

And this loop is nice and simple now. Good.

So I think this patch looks right. This is all sufficiently complex that
we probably want to add something to the test suite. For reference,
here's how I hacked up your original script to put more commits on the
left:

--- test-multiway-merge.sh.orig	2018-09-08 12:04:23.007468601 -0400
+++ test-multiway-merge.sh	2018-09-08 12:11:02.267750789 -0400
@@ -25,6 +25,11 @@
 
 
 "$GIT" init
+for base in 1 2 3 4; do
+    echo base-$base >foo
+    git add foo
+    git commit -m base-$base
+done
 echo 0 > foo
 "$GIT" add foo
 "$GIT" commit -m 0
@@ -47,4 +52,10 @@
 "$GIT" checkout m
 "$GIT" merge -m "merge a b $*" a b "$@"
 
+sleep 1
+for i in 1 2 3 4; do
+    git checkout -b $i-prime master~$i
+    git commit --allow-empty -m side-$i
+done
+
 valgrind "$GIT" log --oneline --graph --all

Then running it as "test-multiway-merge d e f" gives a nice wide graph
that should show any off-by-one mistakes. We should be able to do away
with the "sleep" in a real test if we make use of test_commit(), which
advances GIT_COMMITTER_DATE by one second for each commit.

Do you feel comfortable trying to add something to the test suite for
this?

-Peff

  reply	other threads:[~2018-09-08 16:13 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-05-15 13:05 [BUG] A part of an edge from an octopus merge gets colored, even with --color=never Noam Postavsky
2016-05-17 19:07 ` Johannes Sixt
2016-05-17 19:45   ` Jeff King
2016-05-17 19:51     ` Jeff King
2016-05-17 19:55       ` Jeff King
2016-05-20 22:12         ` Noam Postavsky
2018-06-23 21:45           ` Noam Postavsky
2018-06-25 16:23             ` Jeff King
2018-06-30 12:47               ` Noam Postavsky
2018-08-06 18:34                 ` Noam Postavsky
2018-08-06 21:28                   ` Jeff King
2018-08-06 21:26                 ` Jeff King
2018-09-02  0:34                   ` Noam Postavsky
2018-09-08 16:13                     ` Jeff King [this message]
2018-09-25  0:27                       ` Noam Postavsky
2018-10-03  0:09                         ` Noam Postavsky
2018-10-03  4:24                         ` Jeff King
2018-10-03 22:32                           ` Noam Postavsky
2018-10-09  4:51                             ` Jeff King
2018-10-10  0:42                               ` Noam Postavsky
2016-05-17 20:02     ` Johannes Sixt
2016-05-17 21:57       ` Jeff King

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=20180908161316.GA326@sigill.intra.peff.net \
    --to=peff@peff.net \
    --cc=git@vger.kernel.org \
    --cc=hemmo.nieminen@iki.fi \
    --cc=j6t@kdbg.org \
    --cc=npostavs@users.sourceforge.net \
    /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 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).