Re: [PATCH v3 3/3] core: convert build-time USE_NSEC into runtime core.useNanosec
- From
Junio C Hamano <gitster@pobox.com>
- Date
- Aug 18, 2026, 18:51 UTC
- Message-ID
- <xmqqh5krxnwd.fsf@gitster.g>
- In-Reply-To
- <48fceb4b575ca39346cf2f59f621584a19049008.1787065125.git.ben.knoble@gmail.com>
"D. Ben Knoble" <ben.knoble@gmail.com> writes:
Show 14 quoted lines
> 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;
> + }
> +#endifWhat 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.
Show 7 quoted lines
> @@ -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 ...
Show 12 quoted lines
>
> /* 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.
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 ;-).
Show 28 quoted lines
> diff --git a/read-cache.c b/read-cache.c
> index 6c449f393d..31888f77ee 100644
> --- a/read-cache.c
> +++ b/read-cache.c
> @@ -353,12 +353,18 @@ static int ce_match_stat_basic(const struct cache_entry *ce, struct stat *st)
> static int is_racy_stat(const struct index_state *istate,
> const struct stat_data *sd)
> {
> +#ifndef NO_NSEC
> + int use_nsec = repo_config_values(istate->repo)->use_nanosec;
> +#endif
> +
> return (istate->timestamp.sec &&
> -#ifdef USE_NSEC
> - /* nanosecond timestamped files can also be racy! */
> - (istate->timestamp.sec < sd->sd_mtime.sec ||
> - (istate->timestamp.sec == sd->sd_mtime.sec &&
> - istate->timestamp.nsec <= sd->sd_mtime.nsec))
> +#ifndef NO_NSEC
> + /* nanosecond timestamped files can also be racy! */
> + use_nsec
> + ? (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
> #else
> istate->timestamp.sec <= sd->sd_mtime.sec
> #endifUgly. 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.