From 890d70856cbab8af641bffd3a878272aac70f438 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Tue, 31 Dec 2024 11:29:41 +0000 Subject: [PATCH] cmake: update nanosecond selection For consistency, specify the nanosecond option in the same way as other options, and identify it as such. Split the detection of platform support (`FindStatNsec`) and its selection (`SelectNsec`). --- CMakeLists.txt | 4 +- cmake/FindStatNsec.cmake | 14 ------ cmake/SelectNsec.cmake | 58 +++++++++++++++++++++++ src/CMakeLists.txt | 17 +------ src/libgit2/index.c | 2 +- src/libgit2/index.h | 4 +- src/libgit2/iterator.c | 2 +- src/libgit2/libgit2.c | 14 +++--- src/util/futils.c | 6 +-- src/util/git2_features.h.in | 10 ++-- src/util/unix/posix.h | 8 ++-- src/util/win32/w32_util.h | 4 +- tests/libgit2/checkout/checkout_helpers.h | 1 + tests/libgit2/core/features.c | 14 +++--- tests/libgit2/merge/workdir/dirty.c | 2 +- 15 files changed, 97 insertions(+), 63 deletions(-) create mode 100644 cmake/SelectNsec.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 060d8b7e3..b90e7c127 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,9 +27,8 @@ option(BUILD_FUZZERS "Build the fuzz targets" # Suggested functionality that may not be available on a per-platform basis option(USE_THREADS "Use threads for parallel processing when possible" ON) -option(USE_NSEC "Support nanosecond precision file mtimes and ctimes" ON) -# Backend selection +# Feature enablement and backend selection set(USE_SSH "" CACHE STRING "Enables SSH support and optionally selects provider. One of ON, OFF, or a specific provider: libssh2 or exec. (Defaults to OFF.)") set(USE_HTTPS "" CACHE STRING "Enable HTTPS support and optionally selects the provider. One of ON, OFF, or a specific provider: OpenSSL, OpenSSL-FIPS, OpenSSL-Dynamic, mbedTLS, SecureTransport, Schannel, or WinHTTP. (Defaults to ON.)") set(USE_SHA1 "" CACHE STRING "Selects SHA1 provider. One of builtin, HTTPS, or a specific provider. (Defaults to builtin.)") @@ -40,6 +39,7 @@ option(USE_NSEC "Support nanosecond precision file mtimes and cti # set(USE_XDIFF "" CACHE STRING "Specifies the xdiff implementation; either system or builtin.") set(USE_REGEX "" CACHE STRING "Selects regex provider. One of regcomp_l, pcre2, pcre, regcomp, or builtin.") set(USE_COMPRESSION "" CACHE STRING "Selects compression backend. Either builtin or zlib.") + set(USE_NSEC "" CACHE STRING "Enable nanosecond precision timestamps. One of ON, OFF, or a specific provider: mtimespec, mtim, mtime, or win32. (Defaults to ON).") if(APPLE) # Currently only available on macOS for `precomposeUnicode` support diff --git a/cmake/FindStatNsec.cmake b/cmake/FindStatNsec.cmake index 9dfdf51c4..368cfedc1 100644 --- a/cmake/FindStatNsec.cmake +++ b/cmake/FindStatNsec.cmake @@ -1,20 +1,6 @@ -include(FeatureSummary) - check_struct_has_member("struct stat" st_mtim "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIM LANGUAGE C) check_struct_has_member("struct stat" st_mtimespec "sys/types.h;sys/stat.h" HAVE_STRUCT_STAT_ST_MTIMESPEC LANGUAGE C) check_struct_has_member("struct stat" st_mtime_nsec sys/stat.h HAVE_STRUCT_STAT_MTIME_NSEC LANGUAGE C) - -if(HAVE_STRUCT_STAT_ST_MTIM) - check_struct_has_member("struct stat" st_mtim.tv_nsec sys/stat.h - HAVE_STRUCT_STAT_NSEC LANGUAGE C) -elseif(HAVE_STRUCT_STAT_ST_MTIMESPEC) - check_struct_has_member("struct stat" st_mtimespec.tv_nsec sys/stat.h - HAVE_STRUCT_STAT_NSEC LANGUAGE C) -else() - set(HAVE_STRUCT_STAT_NSEC ON ) -endif() - -add_feature_info(nanoseconds USE_NSEC "support nanosecond precision file mtimes and ctimes") diff --git a/cmake/SelectNsec.cmake b/cmake/SelectNsec.cmake new file mode 100644 index 000000000..392b92bc4 --- /dev/null +++ b/cmake/SelectNsec.cmake @@ -0,0 +1,58 @@ +include(SanitizeBool) +include(FeatureSummary) + +sanitizebool(USE_NSEC) + +if((USE_NSEC STREQUAL ON OR USE_NSEC STREQUAL "") AND HAVE_STRUCT_STAT_ST_MTIM) + set(USE_NSEC "mtim") +elseif((USE_NSEC STREQUAL ON OR USE_NSEC STREQUAL "") AND HAVE_STRUCT_STAT_ST_MTIMESPEC) + set(USE_NSEC "mtimespec") +elseif((USE_NSEC STREQUAL ON OR USE_NSEC STREQUAL "") AND HAVE_STRUCT_STAT_MTIME_NSEC) + set(USE_NSEC "mtime_nsec") +elseif((USE_NSEC STREQUAL ON OR USE_NSEC STREQUAL "") AND WIN32) + set(USE_NSEC "win32") +elseif(USE_NSEC STREQUAL "") + message(WARNING "nanosecond timestamp precision was not detected") + set(USE_NSEC OFF) +elseif(USE_NSEC STREQUAL ON) + message(FATAL_ERROR "nanosecond support was requested but no platform support is available") +endif() + +if(USE_NSEC STREQUAL "mtim") + if(NOT HAVE_STRUCT_STAT_ST_MTIM) + message(FATAL_ERROR "stat mtim could not be found") + endif() + + set(GIT_NSEC 1) + set(GIT_NSEC_MTIM 1) + add_feature_info("Nanosecond support" ON "using mtim") +elseif(USE_NSEC STREQUAL "mtimespec") + if(NOT HAVE_STRUCT_STAT_ST_MTIMESPEC) + message(FATAL_ERROR "mtimespec could not be found") + endif() + + set(GIT_NSEC 1) + set(GIT_NSEC_MTIMESPEC 1) + add_feature_info("Nanosecond support" ON "using mtimespec") +elseif(USE_NSEC STREQUAL "mtime_nsec") + if(NOT HAVE_STRUCT_STAT_MTIME_NSEC) + message(FATAL_ERROR "mtime_nsec could not be found") + endif() + + set(GIT_NSEC 1) + set(GIT_NSEC_MTIME_NSEC 1) + add_feature_info("Nanosecond support" ON "using mtime_nsec") +elseif(USE_NSEC STREQUAL "win32") + if(NOT WIN32) + message(FATAL_ERROR "Win32 API support is not available on this platform") + endif() + + set(GIT_NSEC 1) + set(GIT_NSEC_WIN32 1) + add_feature_info("Nanosecond support" ON "using Win32 APIs") +elseif(USE_NSEC STREQUAL OFF) + set(GIT_NSEC 0) + add_feature_info("Nanosecond support" OFF "Nanosecond timestamp resolution is disabled") +else() + message(FATAL_ERROR "unknown nanosecond option: ${USE_NSEC}") +endif() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3921489a5..4aa062e7e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -36,6 +36,7 @@ add_feature_info(debugopen GIT_DEBUG_STRICT_OPEN "path validation in open") # Optional feature enablement # +include(SelectNsec) include(SelectHTTPSBackend) include(SelectHashes) include(SelectHTTPParser) @@ -110,22 +111,6 @@ else() message(FATAL_ERROR "Unsupported architecture (CMAKE_SIZEOF_VOID_P is unset)") endif() -# nanosecond mtime/ctime support - -if(USE_NSEC) - set(GIT_USE_NSEC 1) -endif() - -# high-resolution stat support - -if(HAVE_STRUCT_STAT_ST_MTIM) - set(GIT_USE_STAT_MTIM 1) -elseif(HAVE_STRUCT_STAT_ST_MTIMESPEC) - set(GIT_USE_STAT_MTIMESPEC 1) -elseif(HAVE_STRUCT_STAT_ST_MTIME_NSEC) - set(GIT_USE_STAT_MTIME_NSEC 1) -endif() - # realtime support check_library_exists(rt clock_gettime "time.h" NEED_LIBRT) diff --git a/src/libgit2/index.c b/src/libgit2/index.c index a3142c8bc..625315184 100644 --- a/src/libgit2/index.c +++ b/src/libgit2/index.c @@ -902,7 +902,7 @@ void git_index_entry__init_from_stat( { entry->ctime.seconds = (int32_t)st->st_ctime; entry->mtime.seconds = (int32_t)st->st_mtime; -#if defined(GIT_USE_NSEC) +#if defined(GIT_NSEC) entry->mtime.nanoseconds = st->st_mtime_nsec; entry->ctime.nanoseconds = st->st_ctime_nsec; #endif diff --git a/src/libgit2/index.h b/src/libgit2/index.h index 601e98f1c..57222a8c6 100644 --- a/src/libgit2/index.h +++ b/src/libgit2/index.h @@ -85,7 +85,7 @@ GIT_INLINE(bool) git_index_time_eq(const git_index_time *one, const git_index_ti if (one->seconds != two->seconds) return false; -#ifdef GIT_USE_NSEC +#ifdef GIT_NSEC if (one->nanoseconds != two->nanoseconds) return false; #endif @@ -106,7 +106,7 @@ GIT_INLINE(bool) git_index_entry_newer_than_index( return false; /* If the timestamp is the same or newer than the index, it's racy */ -#if defined(GIT_USE_NSEC) +#if defined(GIT_NSEC) if ((int32_t)index->stamp.mtime.tv_sec < entry->mtime.seconds) return true; else if ((int32_t)index->stamp.mtime.tv_sec > entry->mtime.seconds) diff --git a/src/libgit2/iterator.c b/src/libgit2/iterator.c index 5b3e02485..4eca11f7c 100644 --- a/src/libgit2/iterator.c +++ b/src/libgit2/iterator.c @@ -1520,7 +1520,7 @@ static void filesystem_iterator_set_current( iter->entry.ctime.seconds = (int32_t)entry->st.st_ctime; iter->entry.mtime.seconds = (int32_t)entry->st.st_mtime; -#if defined(GIT_USE_NSEC) +#if defined(GIT_NSEC) iter->entry.ctime.nanoseconds = entry->st.st_ctime_nsec; iter->entry.mtime.nanoseconds = entry->st.st_mtime_nsec; #else diff --git a/src/libgit2/libgit2.c b/src/libgit2/libgit2.c index 537a839a1..5e0aaf678 100644 --- a/src/libgit2/libgit2.c +++ b/src/libgit2/libgit2.c @@ -90,7 +90,7 @@ int git_libgit2_features(void) #ifdef GIT_SSH | GIT_FEATURE_SSH #endif -#ifdef GIT_USE_NSEC +#ifdef GIT_NSEC | GIT_FEATURE_NSEC #endif | GIT_FEATURE_HTTP_PARSER @@ -152,15 +152,15 @@ const char *git_libgit2_feature_backend(git_feature_t feature) break; case GIT_FEATURE_NSEC: -#if defined(GIT_USE_NSEC) && defined(GIT_USE_STAT_MTIMESPEC) +#if defined(GIT_NSEC_MTIMESPEC) return "mtimespec"; -#elif defined(GIT_USE_NSEC) && defined(GIT_USE_STAT_MTIM) +#elif defined(GIT_NSEC_MTIM) return "mtim"; -#elif defined(GIT_USE_NSEC) && defined(GIT_USE_STAT_MTIME_NSEC) - return "mtime"; -#elif defined(GIT_USE_NSEC) && defined(GIT_WIN32) +#elif defined(GIT_NSEC_MTIME_NSEC) + return "mtime_nsec"; +#elif defined(GIT_NSEC_WIN32) return "win32"; -#elif defined(GIT_USE_NSEC) +#elif defined(GIT_NSEC) GIT_ASSERT_WITH_RETVAL(!"Unknown high-resolution time backend", NULL); #endif break; diff --git a/src/util/futils.c b/src/util/futils.c index eb32cbb12..25c3a1be1 100644 --- a/src/util/futils.c +++ b/src/util/futils.c @@ -1158,7 +1158,7 @@ int git_futils_filestamp_check( return GIT_ENOTFOUND; if (stamp->mtime.tv_sec == st.st_mtime && -#if defined(GIT_USE_NSEC) +#if defined(GIT_NSEC) stamp->mtime.tv_nsec == st.st_mtime_nsec && #endif stamp->size == (uint64_t)st.st_size && @@ -1166,7 +1166,7 @@ int git_futils_filestamp_check( return 0; stamp->mtime.tv_sec = st.st_mtime; -#if defined(GIT_USE_NSEC) +#if defined(GIT_NSEC) stamp->mtime.tv_nsec = st.st_mtime_nsec; #endif stamp->size = (uint64_t)st.st_size; @@ -1190,7 +1190,7 @@ void git_futils_filestamp_set_from_stat( { if (st) { stamp->mtime.tv_sec = st->st_mtime; -#if defined(GIT_USE_NSEC) +#if defined(GIT_NSEC) stamp->mtime.tv_nsec = st->st_mtime_nsec; #else stamp->mtime.tv_nsec = 0; diff --git a/src/util/git2_features.h.in b/src/util/git2_features.h.in index a5cf6a9e0..f7c4e33f5 100644 --- a/src/util/git2_features.h.in +++ b/src/util/git2_features.h.in @@ -14,10 +14,12 @@ #cmakedefine GIT_I18N 1 #cmakedefine GIT_I18N_ICONV 1 -#cmakedefine GIT_USE_NSEC 1 -#cmakedefine GIT_USE_STAT_MTIM 1 -#cmakedefine GIT_USE_STAT_MTIMESPEC 1 -#cmakedefine GIT_USE_STAT_MTIME_NSEC 1 +#cmakedefine GIT_NSEC 1 +#cmakedefine GIT_NSEC_MTIM 1 +#cmakedefine GIT_NSEC_MTIMESPEC 1 +#cmakedefine GIT_NSEC_MTIME_NSEC 1 +#cmakedefine GIT_NSEC_WIN32 1 + #cmakedefine GIT_USE_FUTIMENS 1 #cmakedefine GIT_REGEX_REGCOMP_L 1 diff --git a/src/util/unix/posix.h b/src/util/unix/posix.h index 60f27d3d3..d1fc19e45 100644 --- a/src/util/unix/posix.h +++ b/src/util/unix/posix.h @@ -23,16 +23,16 @@ typedef int GIT_SOCKET; #define p_lstat(p,b) lstat(p,b) #define p_stat(p,b) stat(p, b) -#if defined(GIT_USE_STAT_MTIMESPEC) +#if defined(GIT_NSEC_MTIMESPEC) # define st_atime_nsec st_atimespec.tv_nsec # define st_mtime_nsec st_mtimespec.tv_nsec # define st_ctime_nsec st_ctimespec.tv_nsec -#elif defined(GIT_USE_STAT_MTIM) +#elif defined(GIT_NSEC_MTIM) # define st_atime_nsec st_atim.tv_nsec # define st_mtime_nsec st_mtim.tv_nsec # define st_ctime_nsec st_ctim.tv_nsec -#elif !defined(GIT_USE_STAT_MTIME_NSEC) && defined(GIT_USE_NSEC) -# error GIT_USE_NSEC defined but unknown struct stat nanosecond type +#elif !defined(GIT_NSEC_MTIME_NSEC) && defined(GIT_NSEC) +# error GIT_NSEC defined but unknown struct stat nanosecond type #endif #define p_utimes(f, t) utimes(f, t) diff --git a/src/util/win32/w32_util.h b/src/util/win32/w32_util.h index 519663720..dfdf69cd0 100644 --- a/src/util/win32/w32_util.h +++ b/src/util/win32/w32_util.h @@ -77,8 +77,10 @@ GIT_INLINE(void) git_win32__filetime_to_timespec( int64_t winTime = ((int64_t)ft->dwHighDateTime << 32) + ft->dwLowDateTime; winTime -= INT64_C(116444736000000000); /* Windows to Unix Epoch conversion */ ts->tv_sec = (time_t)(winTime / 10000000); -#ifdef GIT_USE_NSEC +#ifdef GIT_NSEC_WIN32 ts->tv_nsec = (winTime % 10000000) * 100; +#elif GIT_NSEC +# error GIT_NSEC defined but GIT_NSEC_WIN32 not defined #else ts->tv_nsec = 0; #endif diff --git a/tests/libgit2/checkout/checkout_helpers.h b/tests/libgit2/checkout/checkout_helpers.h index 879b48b06..6c723ffdf 100644 --- a/tests/libgit2/checkout/checkout_helpers.h +++ b/tests/libgit2/checkout/checkout_helpers.h @@ -1,5 +1,6 @@ #include "git2/object.h" #include "git2/repository.h" +#include "git2_features.h" extern void assert_on_branch(git_repository *repo, const char *branch); extern void reset_index_to_treeish(git_object *treeish); diff --git a/tests/libgit2/core/features.c b/tests/libgit2/core/features.c index 9eaa9f350..4fcce91fd 100644 --- a/tests/libgit2/core/features.c +++ b/tests/libgit2/core/features.c @@ -20,7 +20,7 @@ void test_core_features__basic(void) cl_assert((caps & GIT_FEATURE_SSH) == 0); #endif -#if defined(GIT_USE_NSEC) +#if defined(GIT_NSEC) cl_assert((caps & GIT_FEATURE_NSEC) != 0); #else cl_assert((caps & GIT_FEATURE_NSEC) == 0); @@ -118,15 +118,15 @@ void test_core_features__backends(void) cl_assert(ssh == NULL); #endif -#if defined(GIT_USE_NSEC) && defined(GIT_USE_STAT_MTIMESPEC) +#if defined(GIT_NSEC_MTIMESPEC) cl_assert_equal_s("mtimespec", nsec); -#elif defined(GIT_USE_NSEC) && defined(GIT_USE_STAT_MTIM) +#elif defined(GIT_NSEC_MTIM) cl_assert_equal_s("mtim", nsec); -#elif defined(GIT_USE_NSEC) && defined(GIT_USE_STAT_MTIME_NSEC) - cl_assert_equal_s("mtime", nsec); -#elif defined(GIT_USE_NSEC) && defined(GIT_WIN32) +#elif defined(GIT_NSEC_MTIME_NSEC) + cl_assert_equal_s("mtime_nsec", nsec); +#elif defined(GIT_NSEC_WIN32) cl_assert_equal_s("win32", nsec); -#elif defined(GIT_USE_NSEC) +#elif defined(GIT_NSEC) cl_assert(0); #else cl_assert(nsec == NULL); diff --git a/tests/libgit2/merge/workdir/dirty.c b/tests/libgit2/merge/workdir/dirty.c index 570e7c759..723b259ea 100644 --- a/tests/libgit2/merge/workdir/dirty.c +++ b/tests/libgit2/merge/workdir/dirty.c @@ -162,7 +162,7 @@ static void hack_index(char *files[]) entry->ctime.seconds = (int32_t)statbuf.st_ctime; entry->mtime.seconds = (int32_t)statbuf.st_mtime; -#if defined(GIT_USE_NSEC) +#if defined(GIT_NSEC) entry->ctime.nanoseconds = statbuf.st_ctime_nsec; entry->mtime.nanoseconds = statbuf.st_mtime_nsec; #else