Re: [PATCH v3 3/3] core: convert build-time USE_NSEC into runtime core.useNanosec
- From
D. Ben Knoble <ben.knoble@gmail.com>
- Date
- Aug 19, 2026, 12:53 UTC
- Message-ID
- <CALnO6CAZ-_k=+xTZwi-+s2aeKwgkoY5Z_iJjF6_sBDreKEsTaw@mail.gmail.com>
- In-Reply-To
- <xmqqh5krxnwd.fsf@gitster.g>
[Patrick, the below probably helps answer some of your questions as well.]
On Tue, Aug 18, 2026 at 2:51 PM Junio C Hamano <gitster@pobox.com> wrote:
Show 48 quoted lines
>
> "D. Ben Knoble" <ben.knoble@gmail.com> writes:
>
> > diff --git a/environment.c b/environment.c
> > index 6676e6f5ae..c7f6b801f4 100644
> > --- a/environment.c
> > +++ b/environment.c
> > @@ -571,6 +571,13 @@ int git_default_core_config(const char *var, const char *value,
> > return 0;
> > }
> >
> > +#ifndef NO_NSEC
> > + if (!strcmp(var, "core.usenanosec")) {
> > + cfg->use_nanosec = git_config_bool(var, value);
> > + return 0;
> > + }
> > +#endif
>
> What this hunk tells us: At build time, you could choose to ignore
> core.usenanosec configuration variable, preventing cfg->use_nanosec
> from getting flipped to true by the configured value.
>
> > @@ -769,6 +776,9 @@ void repo_config_values_init(struct repo_config_values *cfg)
> > cfg->ignore_case = 0;
> > cfg->trust_executable_bit = 1;
> > cfg->has_symlinks = platform_has_symlinks();
> > +#ifndef NO_NSEC
> > + cfg->use_nanosec = 0;
> > +#endif
>
> I think we want to unconditionally initialize it to 0, unless the
> definition of the .use_nanosec member itself in the structure is
> conditional on NO_NSEC. And ...
>
> >
> > /* section "sparse" config values */
> > cfg->sparse_expect_files_outside_of_patterns = 0;
> > diff --git a/environment.h b/environment.h
> > index e7ec5b0437..a35534afe5 100644
> > --- a/environment.h
> > +++ b/environment.h
> > @@ -139,6 +139,7 @@ struct repo_config_values {
> > int ignore_case;
> > int trust_executable_bit;
> > int has_symlinks;
> > + int use_nanosec;
>
> ... that is not the case.Doh! I actually intended to send this version with a compiled-out member when NO_NSEC, since that was the only path I had come up with. No point in running around with code that's been asked to be ignored, eh? However…
> Which means that git_default_core_config() does keep the initial > value of the member without getting affected by the configuration, > but it does not necessarily be keeping "false". It may be keeping > the uninitialized state instead ;-).
[ugly #ifdef trimmed]
Show 19 quoted lines
> Ugly. How about getting rid of the latter #ifndef/#else/#endif and > instead keeping the "if use_nsec, pay attention to nsec, otherwise > only the seconds part" ternary? As to the early part, as you can > arrange cfg's '.use_nanosec' to always hold a sensible value, the > function can become > > return (istate->timestamp.sec && > (repo_config_values(istate->repo)->use_nanosec > ? (istate->timestamp.sec < sd->sd_mtime.sec || > (istate->timestamp.sec == sd->sd_mtime.sec && > istate->timestamp.nsec <= sd->sd_mtime.nsec)) > : istate->timestamp.sec <= sd->sd_mtime.sec)); > > I think. > > The code you presented here for is_racy_stat() sprinkled with > #ifndef/#else/#endif would be sensible if repo_config_values struct > defined the '.use_nanosec' member conditionally. But that is not > what is happening here.
…I now see a world where we could avoid quite a bit of headache:
- use #if[n]def NO_NSEC to ignore the config variable, but otherwise - unconditionally compile the cfg->use_nanosec checks
That is, future readers/writers won't have to remember that they can only use the use_nanosec member under compiler conditionals; it will always be initialized to a safe value (either always false or from config). If we're lucky, the compiler will optimize the checks away in NO_NSEC builds ;)
I think this is what you are suggesting Junio, so let me see what I can come up with.
-- D. Ben Knoble