Merge branch 'dk/use-nsec-runtime' into seen

* dk/use-nsec-runtime:
  core: convert build-time USE_NSEC into runtime core.useNanosec
  environment: align repo_config_values_init with struct declaration
  meson: expose knob for xmlto relative links in manuals
This commit is contained in:
Junio C Hamano
2026-08-07 14:48:31 -07:00
12 changed files with 57 additions and 47 deletions

View File

@@ -118,6 +118,12 @@ core.trustctime::
crawlers and some backup systems).
See linkgit:git-update-index[1]. True by default.
core.useNanosec::
If true, use nanosecond precision for ctime and mtime
comparisions between the index and the working tree (if Git
was compiled to store it).
See link:technical/racy-git.html[Racy Git]. False by default.
core.splitIndex::
If true, the split-index feature of the index will be used.
See linkgit:git-update-index[1]. False by default.

View File

@@ -381,13 +381,18 @@ foreach manpage, category : manpages
output: fs.stem(manpage) + '.xml',
)
man_base_url = 'file://' + htmldir + '/'
if get_option('man_base_url') != ''
man_base_url = get_option('man_base_url')
endif
doc_targets += custom_target(
command: [
xmlto,
'-m', '@INPUT0@',
'-m', '@INPUT1@',
'--stringparam',
'man.base.url.for.relative.links=' + get_option('prefix') / get_option('mandir'),
'man.base.url.for.relative.links=' + man_base_url,
'man',
manpage_xml_target,
'-o',

View File

@@ -39,8 +39,8 @@ files) from `st_mode` member, `st_mtime` and `st_ctime`
timestamps, `st_uid`, `st_gid`, `st_ino`, and `st_size` members.
With a `USE_STDEV` compile-time option, `st_dev` is also
compared, but this is not enabled by default because this member
is not stable on network filesystems. With `USE_NSEC`
compile-time option, `st_mtim.tv_nsec` and `st_ctim.tv_nsec`
is not stable on network filesystems. With 'core.useNanosec'
config setting, `st_mtim.tv_nsec` and `st_ctim.tv_nsec`
members are also compared. On Linux, this is not enabled by default
because in-core timestamps can have finer granularity than
on-disk timestamps, resulting in meaningless changes when an
@@ -49,9 +49,10 @@ of git://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git
([PATCH] Sync in core time granularity with filesystems,
2005-01-04). This patch is included in kernel 2.6.11 and newer, but
only fixes the issue for file systems with exactly 1 ns or 1 s
resolution. Other file systems are still broken in current Linux
kernels (e.g. CEPH, CIFS, NTFS, UDF), see
https://lore.kernel.org/lkml/5577240D.7020309@gmail.com/
resolution. As of kernel 4.3, other file systems (CEPH, CIFS, NTFS, UFS, FUSE)
were fixed; see https://public-inbox.org/git/5605D88A.20104%40gmail.com/. FAT
has been fixed since 2015. The usual suspects (ext2, ext4, XFS) are known to
work, too.
Racy Git
--------

View File

@@ -200,18 +200,11 @@ include shared.mak
# Define NO_NORETURN if using buggy versions of gcc 4.6+ and profile feedback,
# as the compiler can crash (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49299)
#
# Define USE_NSEC below if you want git to care about sub-second file mtimes
# and ctimes. Note that you need recent glibc (at least 2.2.4) for this. On
# Linux, kernel 2.6.11 or newer is required for reliable sub-second file times
# on file systems with exactly 1 ns or 1 s resolution. If you intend to use Git
# on other file systems (e.g. CEPH, CIFS, NTFS, UDF), don't enable USE_NSEC. See
# Documentation/technical/racy-git.adoc for details.
#
# Define USE_ST_TIMESPEC if your "struct stat" uses "st_ctimespec" instead of
# "st_ctim"
#
# Define NO_NSEC if your "struct stat" does not have "st_ctim.tv_nsec"
# available. This automatically turns USE_NSEC off.
# available.
#
# Define USE_STDEV below if you want git to care about the underlying device
# change being considered an inode change from the update-index perspective.
@@ -1943,9 +1936,6 @@ endif
ifdef NO_ST_BLOCKS_IN_STRUCT_STAT
BASIC_CFLAGS += -DNO_ST_BLOCKS_IN_STRUCT_STAT
endif
ifdef USE_NSEC
BASIC_CFLAGS += -DUSE_NSEC
endif
ifdef USE_ST_TIMESPEC
BASIC_CFLAGS += -DUSE_ST_TIMESPEC
endif

View File

@@ -130,7 +130,7 @@ static void xrmdir(const char *path)
static void avoid_racy(void)
{
/*
* not use if we could usleep(10) if USE_NSEC is defined. The
* not use if we could usleep(10) if core.useNanosec is defined. The
* field nsec could be there, but the OS could choose to
* ignore it?
*/

View File

@@ -501,7 +501,6 @@ int git_qsort_s(void *base, size_t nmemb, size_t size,
} while (0)
#ifdef NO_NSEC
#undef USE_NSEC
#define ST_CTIME_NSEC(st) 0
#define ST_MTIME_NSEC(st) 0
#else

View File

@@ -351,12 +351,6 @@ GIT_PARSE_WITH(iconv))
## --enable-FEATURE[=ARG] and --disable-FEATURE
#
# Define USE_NSEC below if you want git to care about sub-second file mtimes
# and ctimes. Note that you need recent glibc (at least 2.2.4) for this, and
# it will BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely
# randomly break unless your underlying filesystem supports those sub-second
# times (my ext3 doesn't).
#
# Define USE_STDEV below if you want git to care about the underlying device
# change being considered an inode change from the update-index perspective.

View File

@@ -572,6 +572,11 @@ int git_default_core_config(const char *var, const char *value,
return 0;
}
if (!strcmp(var, "core.usenanosec")) {
cfg->use_nanosec = git_config_bool(var, value);
return 0;
}
/* Add other config variables here and to Documentation/config.adoc. */
return platform_core_config(var, value, ctx, cb);
}
@@ -746,6 +751,7 @@ int git_default_config(const char *var, const char *value,
void repo_config_values_init(struct repo_config_values *cfg)
{
/* section "core" config values */
cfg->attributes_file = NULL;
cfg->excludes_file = NULL;
cfg->editor_program = NULL;
@@ -757,20 +763,25 @@ void repo_config_values_init(struct repo_config_values *cfg)
cfg->autorebase = AUTOREBASE_NEVER;
cfg->object_creation_mode = OBJECT_CREATION_MODE;
cfg->apply_sparse_checkout = 0;
cfg->protect_hfs = PROTECT_HFS_DEFAULT;
cfg->protect_ntfs = PROTECT_NTFS_DEFAULT;
cfg->ignore_case = 0;
cfg->trust_executable_bit = 1;
cfg->has_symlinks = platform_has_symlinks();
cfg->branch_track = BRANCH_TRACK_REMOTE;
cfg->trust_ctime = 1;
cfg->check_stat = 1;
cfg->zlib_compression_level = Z_BEST_SPEED;
cfg->pack_compression_level = Z_DEFAULT_COMPRESSION;
cfg->precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */
cfg->core_sparse_checkout_cone = 0;
cfg->sparse_expect_files_outside_of_patterns = 0;
cfg->warn_on_object_refname_ambiguity = 1;
cfg->protect_hfs = PROTECT_HFS_DEFAULT;
cfg->protect_ntfs = PROTECT_NTFS_DEFAULT;
cfg->ignore_case = 0;
cfg->trust_executable_bit = 1;
cfg->has_symlinks = platform_has_symlinks();
cfg->use_nanosec = 0;
/* section "sparse" config values */
cfg->sparse_expect_files_outside_of_patterns = 0;
/* section "branch" config values */
cfg->branch_track = BRANCH_TRACK_REMOTE;
}
void repo_config_values_clear(struct repo_config_values *cfg)

View File

@@ -138,6 +138,7 @@ struct repo_config_values {
int ignore_case;
int trust_executable_bit;
int has_symlinks;
int use_nanosec;
int sparse_expect_files_outside_of_patterns;
enum branch_track branch_track;
};

View File

@@ -115,6 +115,8 @@ option('default_help_format', type: 'combo', choices: ['man', 'html', 'platform'
description: 'Default format used when executing git-help(1).')
option('docs_backend', type: 'combo', choices: ['asciidoc', 'asciidoctor', 'auto'], value: 'auto',
description: 'Which backend to use to generate documentation.')
option('man_base_url', type: 'string', value: '',
description: 'The base URL to use for relative links in manuals')
# Testing.
option('benchmarks', type: 'feature', value: 'auto',

View File

@@ -353,15 +353,16 @@ 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)
{
int use_nsec = 0;
repo_config_get_bool(the_repository, "core.useNanosec", &use_nsec);
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))
#else
istate->timestamp.sec <= sd->sd_mtime.sec
#endif
/* 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
);
}

View File

@@ -72,13 +72,13 @@ int match_stat_data(const struct stat_data *sd, struct stat *st)
sd->sd_ctime.sec != (unsigned int)st->st_ctime)
changed |= CTIME_CHANGED;
#ifdef USE_NSEC
if (cfg->check_stat && sd->sd_mtime.nsec != ST_MTIME_NSEC(*st))
changed |= MTIME_CHANGED;
if (cfg->trust_ctime && cfg->check_stat &&
sd->sd_ctime.nsec != ST_CTIME_NSEC(*st))
changed |= CTIME_CHANGED;
#endif
if (cfg->use_nanosec) {
if (cfg->check_stat && sd->sd_mtime.nsec != ST_MTIME_NSEC(*st))
changed |= MTIME_CHANGED;
if (cfg->trust_ctime && cfg->check_stat &&
sd->sd_ctime.nsec != ST_CTIME_NSEC(*st))
changed |= CTIME_CHANGED;
}
if (cfg->check_stat) {
if (sd->sd_uid != (unsigned int) st->st_uid ||