Re: ["BUG"] builtin add-interactive does not honor 'color.diff. frag'

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Peff & Philippe,

On Fri, 6 Nov 2020, Jeff King wrote:

> On Fri, Nov 06, 2020 at 11:31:32AM -0500, Philippe Blain wrote:
>
> > I tried the builtin add-interactive for the first time today,
> > and noticed a very minor difference with the Perl version.
> > The title says it all.
> >
> > Repro:
> >
> > # Change the default color
> > $ git config color.diff.frag "magenta bold"
> > # Compare
> > $ git add -p
> > # and
> > $ git -c add.interactive.useBuiltin=true add -p
> > # I'm on latest master
> > $ git --version
> > git version 2.29.2.154.g7f7ebe054a
>
> It looks like the code in add-interactive.c uses "fraginfo" instead of
> "frag".


Aaargh, yes, I missed that.

> But there's something much more puzzling, which is that it checks
> color.interactive.frag. AFAIK that has never been a valid config option
> (there are some color.interactive.* values, but they are all for
> interactive-specific things).

And that. This is the code in `git-add--interactive.perl`:

-- snip --
my $menu_use_color = $repo->get_colorbool('color.interactive');
my ($prompt_color, $header_color, $help_color) =
        $menu_use_color ? (
                $repo->get_color('color.interactive.prompt', 'bold blue'),
                $repo->get_color('color.interactive.header', 'bold'),
                $repo->get_color('color.interactive.help', 'red bold'),
        ) : ();
my $error_color = ();
if ($menu_use_color) {
        my $help_color_spec = ($repo->config('color.interactive.help') or
                                'red bold');
        $error_color = $repo->get_color('color.interactive.error',
                                        $help_color_spec);
}

my $diff_use_color = $repo->get_colorbool('color.diff');
my ($fraginfo_color) =
        $diff_use_color ? (
                $repo->get_color('color.diff.frag', 'cyan'),
        ) : ();
my ($diff_plain_color) =
        $diff_use_color ? (
                $repo->get_color('color.diff.plain', ''),
        ) : ();
my ($diff_old_color) =
        $diff_use_color ? (
                $repo->get_color('color.diff.old', 'red'),
        ) : ();
my ($diff_new_color) =
        $diff_use_color ? (
                $repo->get_color('color.diff.new', 'green'),
        ) : ();

my $normal_color = $repo->get_color("", "reset");
-- snap --

> So something like this seems to go in the right direction (and makes
> your example work):
>
> diff --git a/add-interactive.c b/add-interactive.c
> index a14c0feaa2..1eb69c5160 100644
> --- a/add-interactive.c
> +++ b/add-interactive.c
> @@ -12,10 +12,11 @@
>  #include "prompt.h"
>
>  static void init_color(struct repository *r, struct add_i_state *s,
> +		       const char *section,
>  		       const char *slot_name, char *dst,
>  		       const char *default_color)
>  {
> -	char *key = xstrfmt("color.interactive.%s", slot_name);
> +	char *key = xstrfmt("color.%s.%s", section, slot_name);
>  	const char *value;
>
>  	if (!s->use_color)
> @@ -40,18 +41,19 @@ void init_add_i_state(struct add_i_state *s, struct repository *r)
>  			git_config_colorbool("color.interactive", value);
>  	s->use_color = want_color(s->use_color);
>
> -	init_color(r, s, "header", s->header_color, GIT_COLOR_BOLD);
> -	init_color(r, s, "help", s->help_color, GIT_COLOR_BOLD_RED);
> -	init_color(r, s, "prompt", s->prompt_color, GIT_COLOR_BOLD_BLUE);
> -	init_color(r, s, "error", s->error_color, GIT_COLOR_BOLD_RED);
> -	init_color(r, s, "reset", s->reset_color, GIT_COLOR_RESET);
> -	init_color(r, s, "fraginfo", s->fraginfo_color,
> +	init_color(r, s, "interactive", "header", s->header_color, GIT_COLOR_BOLD);
> +	init_color(r, s, "interactive", "help", s->help_color, GIT_COLOR_BOLD_RED);
> +	init_color(r, s, "interactive", "prompt", s->prompt_color, GIT_COLOR_BOLD_BLUE);
> +	init_color(r, s, "interactive", "error", s->error_color, GIT_COLOR_BOLD_RED);
> +
> +	init_color(r, s, "diff", "reset", s->reset_color, GIT_COLOR_RESET);
> +	init_color(r, s, "diff", "frag", s->fraginfo_color,
>  		   diff_get_color(s->use_color, DIFF_FRAGINFO));
> -	init_color(r, s, "context", s->context_color,
> +	init_color(r, s, "diff", "context", s->context_color,
>  		diff_get_color(s->use_color, DIFF_CONTEXT));
> -	init_color(r, s, "old", s->file_old_color,
> +	init_color(r, s, "diff", "old", s->file_old_color,
>  		diff_get_color(s->use_color, DIFF_FILE_OLD));
> -	init_color(r, s, "new", s->file_new_color,
> +	init_color(r, s, "diff", "new", s->file_new_color,
>  		diff_get_color(s->use_color, DIFF_FILE_NEW));
>
>  	FREE_AND_NULL(s->interactive_diff_filter);
>
> but that is missing another thing: for historical reasons we allow both
> color.diff.frag and diff.color.frag. TBH, I wouldn't be too sad to see
> us drop support for the historical versions in this setting. But it
> makes me wonder if we could be reusing the parsing from
> git_diff_basic_config(), which handles both cases.

Hmm. The Perl version uses the Git.pm's `get_color()` function, which in
turn invokes `git config --get-color` with the exact keys I pasted above.

All along the way to `builtin/config.c`'s `git_get_color_config()`, I fail
to see any `color.diff`/`diff.color` munging. So I believe that `git add
--interactive` _never_ looked at the `diff.color` section to begin with.

> I'm not entirely clear on how add-interactive.c invokes the diff, and
> whether it would be unhappy to pick up diff config. But it seems like
> this:
>
> diff --git a/builtin/add.c b/builtin/add.c
> index a825887c50..47bb6ea10b 100644
> --- a/builtin/add.c
> +++ b/builtin/add.c
> @@ -362,7 +362,7 @@ static int add_config(const char *var, const char *value, void *cb)
>  		return 0;
>  	}
>
> -	return git_default_config(var, value, cb);
> +	return git_diff_basic_config(var, value, cb);
>  }
>
>  static const char embedded_advice[] = N_(
>
> might be the simplest thing (and drop the extra diff-config parsing from
> add-interactive.c that I was touching above). It does need to be done in
> each program that calls into the add-interactive code though (so
> checkout, etc). Obviously it would be easy for init_add_i_state() to
> make a similar call, though that may open us up to loading the diff
> config twice. I suspect that would probably be OK, but it could lead to
> weirdness if there are any multi-valued config options.

Hmm. I don't like it. So far, we were very careful to keep respecting
`struct repository *r` in the built-in interactive add command. This would
go the exact opposite way.

Combined with the fact that we never supported `diff.color.*` in the
interactive add command anyway, I would rather continue with the first
variant you presented.

A bigger puzzle for me was: why did we not catch that earlier? I vaguely
remember that we introduced _specifically_ code to test coloring, and to
make those test work on Windows (rather than skipping them all).

*clicketyclick* ah, we only tests the menu of `git add -i`, and we do not
even override the colors...

Will try to set aside some time to work on fixing this,
Dscho




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux