From: David Aguilar <davvid@gmail.com>
To: Elijah Newren <newren@gmail.com>
Cc: git@vger.kernel.org, "Junio C Hamano" <gitster@pobox.com>,
"Johannes Schindelin" <Johannes.Schindelin@gmx.de>,
"Patrick Steinhardt" <ps@pks.im>,
"Ævar Arnfjörð Bjarmason" <avarab@gmail.com>
Subject: Re: [PATCH v2 1/3] difftool: eliminate use of global variables
Date: Thu, 6 Feb 2025 20:44:41 -0800 [thread overview]
Message-ID: <Z6WPudTWInXagCYg@gmail.com> (raw)
In-Reply-To: <CABPp-BGnRgDxwgfagyvhwjso_kWVgcR-NxOUwUSJve5RHwyFZQ@mail.gmail.com>
On Thu, Feb 06, 2025 at 12:29:46AM -0800, Elijah Newren wrote:
> On Wed, Feb 5, 2025 at 8:20 PM David Aguilar <davvid@gmail.com> wrote:
> > diff --git a/builtin/difftool.c b/builtin/difftool.c
> > index 03a8bb92a9..0b6b92aee0 100644
> > --- a/builtin/difftool.c
> > +++ b/builtin/difftool.c
> > @@ -36,18 +36,27 @@
> > #include "entry.h"
> > #include "setup.h"
> >
> > -static int trust_exit_code;
> > -
> > static const char *const builtin_difftool_usage[] = {
> > N_("git difftool [<options>] [<commit> [<commit>]] [--] [<path>...]"),
> > NULL
> > };
> >
> > +struct difftool_options {
> > + int has_symlinks;
> > + int symlinks;
> > + int trust_exit_code;
> > +};
> > +
> > static int difftool_config(const char *var, const char *value,
> > const struct config_context *ctx, void *cb)
> > {
> > + struct difftool_options *dt_options = (struct difftool_options *)cb;
> > if (!strcmp(var, "difftool.trustexitcode")) {
> > - trust_exit_code = git_config_bool(var, value);
> > + dt_options->trust_exit_code = git_config_bool(var, value);
> > + return 0;
> > + }
> > + if (!strcmp(var, "core.symlinks")) {
> > + dt_options->has_symlinks = git_config_bool(var, value);
>
> It appears that the only use for has_symlinks....
>
> > return 0;
> > }
> >
> > @@ -291,13 +300,14 @@ static int ensure_leading_directories(char *path)
> > * to compare the readlink(2) result as text, even on a filesystem that is
> > * capable of doing a symbolic link.
> > */
> > -static char *get_symlink(const struct object_id *oid, const char *path)
> > +static char *get_symlink(struct difftool_options *dt_options,
> > + const struct object_id *oid, const char *path)
> > {
> > char *data;
> > if (is_null_oid(oid)) {
> > /* The symlink is unknown to Git so read from the filesystem */
> > struct strbuf link = STRBUF_INIT;
> > - if (has_symlinks) {
> > + if (dt_options->has_symlinks) {
>
> Why is this based on dt_options->has_symlinks rather than dt_options->symlinks?
>
> (I guess this question is equivalent to asking why the preimage code
> was using has_symlinks, instead of the symlinks parameter set from the
> command line option. As far as I can see, has_symlinks is supposed to
> merely function as a default value for symlinks in the case no command
> line parameter is passed...but this is the one counter-example. But
> was it an intentional counter-example, or an accident?)
>
> That said, fixing this, if fixing is needed, doesn't belong in this
> patch; it'd probably be better as a preparatory patch. But, it trips
> up reviewers (looks like Patrick was wondering about the same thing on
> v1 of your series), so it at least would probably be helpful to
> mention in the commit message if no other cleanup is needed with
> these.
Agreed. If we fix this it should be done in a separate patch and
we can explain why they were separate variables as part of that
commit message. I don't necessarily agree that it belongs in this patch.
Combining these two fields leads to test errors which is why
it wasn't touched in this round.
> > @@ -734,8 +749,8 @@ int cmd_difftool(int argc,
> > };
> > struct child_process child = CHILD_PROCESS_INIT;
> >
> > - git_config(difftool_config, NULL);
> > - symlinks = has_symlinks;
> > + git_config(difftool_config, &dt_options);
> > + dt_options.symlinks = dt_options.has_symlinks;
>
> If the get_symlink() function should have been using
> dt_options.symlinks instead of dt_options.has_symlinks, then
> dt_options.has_symlinks is merely functioning as a default, but would
> actually be superfluous. A follow-up patch could remove that extra
> field.
`has_symlinks` is currently providing both a default value and
controlling the behavior of the dir-diff mode, so it's not quite
merely functioning as a default.
My eyes gloss over comments because I completely missed the following
explanation in the comment above `get_symlink()`.
This comment explain why we have a separate `have_symlinks` field:
/*
* Unconditional writing of a plain regular file is what
* "git difftool --dir-diff" wants to do for symlinks. We are preparing two
* temporary directories to be fed to a Git-unaware tool that knows how to
* show a diff of two directories (e.g. "diff -r A B").
*
* Because the tool is Git-unaware, if a symbolic link appears in either of
* these temporary directories, it will try to dereference and show the
* difference of the target of the symbolic link, which is not what we want,
* as the goal of the dir-diff mode is to produce an output that is logically
* equivalent to what "git diff" produces.
*
* Most importantly, we want to get textual comparison of the result of the
* readlink(2). get_symlink() provides that---it returns the contents of
* the symlink that gets written to a regular file to force the external tool
* to compare the readlink(2) result as text, even on a filesystem that is
* capable of doing a symbolic link.
*/
In other words, we intetionally take the extra step to readlink(2)
symlinks in the dir-diff mode irrespective of the command-line option on
systems that support symlinks. That's why `has_symlinks` has to be
tracked separately.
In light of this, I suspect that we won't be combining these fields
because this behavior is intentional and necessary.
`git blame` claims that I wrote this comment 8 years ago, but that's
news to me!
Thanks for the thorough review. I'm not planning a re-roll since it
seems like this is fine as-is, but let me know if y'all feel otherwise.
One thing I would maybe change would be to rename `dt_options` to
`options`, but I also appreciate the verbosity of the dt_ prefix.
Interestingly, the `struct difftool_state` and `dt_state` names in the
original patch were chosen because the struct contained more than just
options. Specifically, it contains the `has_symlinks` field.
I'm not really sure it's worth splitting hairs over that detail,
but I'm all ears. struct difftool_options doesn't really bother me.
cheers,
--
David
next prev parent reply other threads:[~2025-02-07 4:44 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-02-06 4:20 [PATCH v2 1/3] difftool: eliminate use of global variables David Aguilar
2025-02-06 4:20 ` [PATCH v2 2/3] difftool: eliminate use of the_repository David Aguilar
2025-02-06 8:30 ` Elijah Newren
2025-02-06 4:20 ` [PATCH v2 3/3] difftool: eliminate use of USE_THE_REPOSITORY_VARIABLE David Aguilar
2025-02-06 8:31 ` Elijah Newren
2025-02-07 6:28 ` Patrick Steinhardt
2025-02-07 17:49 ` Junio C Hamano
2025-02-06 8:29 ` [PATCH v2 1/3] difftool: eliminate use of global variables Elijah Newren
2025-02-07 4:44 ` David Aguilar [this message]
2025-02-06 13:34 ` Junio C Hamano
2025-02-06 18:08 ` Elijah Newren
2025-02-06 19:07 ` Junio C Hamano
2025-02-07 6:28 ` Patrick Steinhardt
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=Z6WPudTWInXagCYg@gmail.com \
--to=davvid@gmail.com \
--cc=Johannes.Schindelin@gmx.de \
--cc=avarab@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=newren@gmail.com \
--cc=ps@pks.im \
/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).