Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package ccache for openSUSE:Factory checked in at 2022-12-07 17:34:27 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/ccache (Old) and /work/SRC/openSUSE:Factory/.ccache.new.1835 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ccache" Wed Dec 7 17:34:27 2022 rev:70 rq:1040613 version:4.7.4 Changes: -------- --- /work/SRC/openSUSE:Factory/ccache/ccache.changes 2022-11-19 18:08:54.994301380 +0100 +++ /work/SRC/openSUSE:Factory/.ccache.new.1835/ccache.changes 2022-12-07 17:35:34.648740346 +0100 @@ -1,0 +2,21 @@ +Mon Dec 5 12:36:18 UTC 2022 - Dirk Müller <dmuel...@suse.com> + +- update to 4.7.4: + * Fixed an inode cache race condition. + * The default temporary directory is now `$XDG_RUNTIME_DIR/ccache-tmp` + instead of a hardcoded `/run/user/<UID>/ccache-tmp`. If `XDG_RUNTIME_DIR` + is not set, `<cache_dir>/tmp` is used. This avoids creating `/run/user/<UID>` + on systems that don't have it if compiling as root. + * Added a fallback in case `posix_fallocate` returns `EINVAL` when + creating the + inode cache file. + * Connection timeout for an HTTP connection is now reported as a timeout + instead + * Temporary files found in the cache are no longer counted in + `--show-compression`. + * Removed duplicate magic header in output from `--inspect`. + * Ccache now properly waits for all recompression jobs to finish when + there is no `f` subdirectory in the cache. + * Documentation improvements + +------------------------------------------------------------------- Old: ---- ccache-4.7.3.tar.xz ccache-4.7.3.tar.xz.asc New: ---- ccache-4.7.4.tar.xz ccache-4.7.4.tar.xz.asc ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ ccache.spec ++++++ --- /var/tmp/diff_new_pack.zrjp3b/_old 2022-12-07 17:35:36.412750005 +0100 +++ /var/tmp/diff_new_pack.zrjp3b/_new 2022-12-07 17:35:36.416750027 +0100 @@ -17,7 +17,7 @@ Name: ccache -Version: 4.7.3 +Version: 4.7.4 Release: 0 Summary: A Fast C/C++ Compiler Cache License: GPL-3.0-or-later ++++++ ccache-4.7.3.tar.xz -> ccache-4.7.4.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ccache-4.7.3/.github/workflows/codeql-analysis.yaml new/ccache-4.7.4/.github/workflows/codeql-analysis.yaml --- old/ccache-4.7.3/.github/workflows/codeql-analysis.yaml 2022-11-05 16:49:59.000000000 +0100 +++ new/ccache-4.7.4/.github/workflows/codeql-analysis.yaml 2022-11-21 19:53:32.000000000 +0100 @@ -51,6 +51,7 @@ env: RUN_TESTS: none CMAKE_GENERATOR: Ninja + EXTRA_CMAKE_BUILD_FLAGS: --target ccache - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v2 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ccache-4.7.3/ci/build new/ccache-4.7.4/ci/build --- old/ccache-4.7.3/ci/build 2022-11-05 16:49:59.000000000 +0100 +++ new/ccache-4.7.4/ci/build 2022-11-21 19:53:32.000000000 +0100 @@ -4,32 +4,40 @@ set -eu -if [ -n "${VERBOSE:-}" ]; then +# Set default values. +: ${BUILDDIR:=build} +: ${CCACHE_LOC:=..} +: ${CMAKE_PARAMS:=} +: ${CMAKE_PREFIX:=} +: ${EXTRA_CMAKE_BUILD_FLAGS:=} +: ${JOBS:=$(getconf _NPROCESSORS_ONLN 2>/dev/null || echo 2)} +: ${SPECIAL:=} +: ${TEST_CC:=${CC:-}} +: ${VERBOSE:=} + +if [ -n "${VERBOSE}" ]; then set -x fi -if [ -n "${SPECIAL:-}" ]; then +if [ -n "${SPECIAL}" ]; then exec "ci/$SPECIAL" else - [ -z ${JOBS:+x} ] && JOBS=$(getconf _NPROCESSORS_ONLN 2>/dev/null) - [ -z ${JOBS:+x} ] && JOBS=2 - - mkdir -p ${BUILDDIR:-build} - cd ${BUILDDIR:-build} - ${CMAKE_PREFIX:-} cmake ${CMAKE_PARAMS:-} ${CCACHE_LOC:-..} + mkdir -p "${BUILDDIR}" + cd "${BUILDDIR}" + ${CMAKE_PREFIX} cmake ${CMAKE_PARAMS} ${CCACHE_LOC} case "${CMAKE_GENERATOR}" in [Vv]isual" "[Ss]tudio*) # MSBuild, use all CPUs. - ${CMAKE_PREFIX:-} cmake --build . ${EXTRA_CMAKE_BUILD_FLAGS:-} -- -m + ${CMAKE_PREFIX} cmake --build . ${EXTRA_CMAKE_BUILD_FLAGS} -- -m ;; *) # Ninja automatically uses all available CPUs. - ${CMAKE_PREFIX:-} cmake --build . ${EXTRA_CMAKE_BUILD_FLAGS:-} + ${CMAKE_PREFIX} cmake --build . ${EXTRA_CMAKE_BUILD_FLAGS} ;; esac case "${RUN_TESTS:-all}" in all) - CC=${TEST_CC:-${CC}} ctest --output-on-failure -j$JOBS "$@" + CC="${TEST_CC}" ctest --output-on-failure -j"${JOBS}" "$@" ;; unittest-in-wine) wine ccache.exe --version diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ccache-4.7.3/cmake/CcacheVersion.cmake new/ccache-4.7.4/cmake/CcacheVersion.cmake --- old/ccache-4.7.3/cmake/CcacheVersion.cmake 2022-11-05 16:49:59.000000000 +0100 +++ new/ccache-4.7.4/cmake/CcacheVersion.cmake 2022-11-21 19:53:32.000000000 +0100 @@ -22,7 +22,7 @@ # CCACHE_VERSION_ORIGIN is set to "archive" in scenario 1 and "git" in scenario # 3. -set(version_info "0dca9dddef6dc4e780ba0357eea49b62e3815ff6 HEAD, tag: v4.7.3, origin/master, origin/HEAD, master") +set(version_info "1527040bc2a278b9d3d51badb732ecf5841d8bb5 HEAD, tag: v4.7.4, origin/master, origin/HEAD, master") set(CCACHE_VERSION "unknown") if(version_info MATCHES "^([0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f])[0-9a-f]* (.*)") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ccache-4.7.3/cmake/Findhiredis.cmake new/ccache-4.7.4/cmake/Findhiredis.cmake --- old/ccache-4.7.3/cmake/Findhiredis.cmake 2022-11-05 16:49:59.000000000 +0100 +++ new/ccache-4.7.4/cmake/Findhiredis.cmake 2022-11-21 19:53:32.000000000 +0100 @@ -33,7 +33,7 @@ elseif(HIREDIS_FROM_INTERNET) message(STATUS "*** WARNING ***: Using hiredis from the internet because it was NOT found and HIREDIS_FROM_INTERNET is TRUE") - set(hiredis_version "1.0.2") + set(hiredis_version "1.1.0") set(hiredis_dir ${CMAKE_BINARY_DIR}/hiredis-${hiredis_version}) set(hiredis_build ${CMAKE_BINARY_DIR}/hiredis-build) @@ -43,7 +43,7 @@ FetchContent_Declare( hiredis URL https://github.com/redis/hiredis/archive/v${hiredis_version}.tar.gz - URL_HASH SHA256=e0ab696e2f07deb4252dda45b703d09854e53b9703c7d52182ce5a22616c3819 + URL_HASH SHA256=fe6d21741ec7f3fc9df409d921f47dfc73a4d8ff64f4ac6f1d95f951bf7f53d6 SOURCE_DIR ${hiredis_dir} BINARY_DIR ${hiredis_build} ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ccache-4.7.3/cmake/GenerateConfigurationFile.cmake new/ccache-4.7.4/cmake/GenerateConfigurationFile.cmake --- old/ccache-4.7.3/cmake/GenerateConfigurationFile.cmake 2022-11-05 16:49:59.000000000 +0100 +++ new/ccache-4.7.4/cmake/GenerateConfigurationFile.cmake 2022-11-21 19:53:32.000000000 +0100 @@ -26,7 +26,6 @@ include(CheckFunctionExists) set(functions asctime_r - geteuid getopt_long getpwuid posix_fallocate diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ccache-4.7.3/cmake/config.h.in new/ccache-4.7.4/cmake/config.h.in --- old/ccache-4.7.3/cmake/config.h.in 2022-11-05 16:49:59.000000000 +0100 +++ new/ccache-4.7.4/cmake/config.h.in 2022-11-21 19:53:32.000000000 +0100 @@ -76,9 +76,6 @@ // Define if your compiler supports AVX2. #cmakedefine HAVE_AVX2 -// Define if you have the "geteuid" function. -#cmakedefine HAVE_GETEUID - // Define if you have the "getopt_long" function. #cmakedefine HAVE_GETOPT_LONG diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ccache-4.7.3/doc/MANUAL.adoc new/ccache-4.7.4/doc/MANUAL.adoc --- old/ccache-4.7.3/doc/MANUAL.adoc 2022-11-05 16:49:59.000000000 +0100 +++ new/ccache-4.7.4/doc/MANUAL.adoc 2022-11-21 19:53:32.000000000 +0100 @@ -139,7 +139,7 @@ Recompress the cache to level _LEVEL_ using the Zstandard algorithm. The level can be an integer, with the same semantics as the - <<config_compression_level,*compression_level*>> configuration option), or + <<config_compression_level,*compression_level*>> configuration option, or the special value *uncompressed* for no compression. See _<<Cache compression>>_ for more information. This can potentionally take a long time since all files in the cache need to be visited. Only files that @@ -191,17 +191,17 @@ *--trim-dir* _PATH_:: - Remove old files from directory _PATH_ until it is at most the size specified - by `--trim-max-size`. + Remove old files from directory _PATH_ until it is at most the size + specified by `--trim-max-size`. + WARNING: Don't use this option to trim the local cache. To trim the local cache directory to a certain size, use `CCACHE_MAXSIZE=_SIZE_ ccache -c`. *--trim-max-size* _SIZE_:: - Specify the maximum size for `--trim-dir`. _SIZE_ should be a number followed - by an optional suffix: k, M, G, T (decimal), Ki, Mi, Gi or Ti (binary). The - default suffix is G. + Specify the maximum size for `--trim-dir`. _SIZE_ should be a number + followed by an optional suffix: k, M, G, T (decimal), Ki, Mi, Gi or Ti + (binary). The default suffix is G. *--trim-method* _METHOD_:: @@ -553,8 +553,6 @@ NVCC (CUDA) compiler. *other*:: Any compiler other than the known types. -*pump*:: - distcc's "`pump`" script. -- [#config_compression] @@ -1038,7 +1036,8 @@ *temporary_dir* (*CCACHE_TEMPDIR*):: This option specifies where ccache will put temporary files. The default is - `/run/user/<UID>/ccache-tmp` if `/run/user/<UID>` exists, otherwise + `$XDG_RUNTIME_DIR/ccache-tmp` (typically `/run/user/<UID>/ccache-tmp`) if + `XDG_RUNTIME_DIR` is set and the directory exists, otherwise `<cache_dir>/tmp`. + NOTE: In previous versions of ccache, *CCACHE_TEMPDIR* had to be on the same @@ -1591,8 +1590,8 @@ == Handling of newly created header files If modification time (mtime) or status change time (ctime) of one of the include -files is the same second as the time compilation is being done, ccache disables -the direct mode (or, in the case of a <<Precompiled headers,precompiled +files is equal to (or newer than) the time compilation is being done, ccache +disables the direct mode (or, in the case of a <<Precompiled headers,precompiled header>>, disables caching completely). This done as a safety measure to avoid a race condition (see below). @@ -1710,8 +1709,8 @@ == Precompiled headers -Ccache has support for GCC's precompiled headers. However, you have to do some -things to make it work properly: +Ccache has support for precompiled headers with GCC and Clang. However, you have +to do some things to make it work properly: * You must set <<config_sloppiness,*sloppiness*>> to *pch_defines,time_macros*. The reason is that ccache can't tell whether `+__TIME__+`, `+__DATE__+` or @@ -1734,6 +1733,8 @@ compiling. -- + +* If you use Clang, you must compile with `-fno-pch-timestamp`. + If you don't do this, either the non-precompiled version of the header file will be used (if available) or ccache will fall back to running the real compiler and increase the statistics counter "`Preprocessing failed`" (if the non-precompiled diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ccache-4.7.3/doc/NEWS.adoc new/ccache-4.7.4/doc/NEWS.adoc --- old/ccache-4.7.3/doc/NEWS.adoc 2022-11-05 16:49:59.000000000 +0100 +++ new/ccache-4.7.4/doc/NEWS.adoc 2022-11-21 19:53:32.000000000 +0100 @@ -1,5 +1,64 @@ = Ccache news +== Ccache 4.7.4 + +Release date: 2022-11-21 + + +=== Bug fixes + +- Fixed an inode cache race condition. + + [small]#_[contributed by Joel Rosdahl]_# + +- The default temporary directory is now `$XDG_RUNTIME_DIR/ccache-tmp` instead + of a hardcoded `/run/user/<UID>/ccache-tmp`. If `XDG_RUNTIME_DIR` is not set, + `<cache_dir>/tmp` is used. This avoids creating `/run/user/<UID>` on systems + that don't have it if compiling as root. + + [small]#_[contributed by Joel Rosdahl and Oleg Sidorkin]_# + +- Added a fallback in case `posix_fallocate` returns `EINVAL` when creating the + inode cache file. + + [small]#_[contributed by Oleg Sidorkin]_# + +- Connection timeout for an HTTP connection is now reported as a timeout instead + of an error. + + [small]#_[contributed by Joel Rosdahl]_# + +- Temporary files found in the cache are no longer counted in + `--show-compression`. + + [small]#_[contributed by Joel Rosdahl]_# + +- Removed duplicate magic header in output from `--inspect`. + + [small]#_[contributed by Joel Rosdahl]_# + +- Ccache now properly waits for all recompression jobs to finish when there is + no `f` subdirectory in the cache. + + [small]#_[contributed by Joel Rosdahl]_# + + +=== Other minor improvements + +- Improved inode cache logging. + + [small]#_[contributed by Joel Rosdahl]_# + + +=== Documentation improvements + +- Removed stray parenthesis. + + [small]#_[contributed by Joel Rosdahl]_# + +- Improved description of how header files are handled. + + [small]#_[contributed by Joel Rosdahl]_# + +- Added a hint about using `-fno-pch-timestamp` for precompiled headers with + Clang. + + [small]#_[contributed by Joel Rosdahl]_# + +- Removed obsolete description of compiler type "`pump`". + + [small]#_[contributed by Joel Rosdahl]_# + + + == Ccache 4.7.3 Release date: 2022-11-05 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ccache-4.7.3/src/Config.cpp new/ccache-4.7.4/src/Config.cpp --- old/ccache-4.7.3/src/Config.cpp 2022-11-05 16:49:59.000000000 +0100 +++ new/ccache-4.7.4/src/Config.cpp 2022-11-21 19:53:32.000000000 +0100 @@ -1114,10 +1114,13 @@ Config::default_temporary_dir() const { static const std::string run_user_tmp_dir = [] { -#ifdef HAVE_GETEUID - auto dir = FMT("/run/user/{}/ccache-tmp", geteuid()); - if (Util::create_dir(dir) && access(dir.c_str(), W_OK) == 0) { - return dir; +#ifndef _WIN32 + const char* const xdg_runtime_dir = getenv("XDG_RUNTIME_DIR"); + if (xdg_runtime_dir && Stat::stat(xdg_runtime_dir).is_directory()) { + auto dir = FMT("{}/ccache-tmp", xdg_runtime_dir); + if (Util::create_dir(dir) && access(dir.c_str(), W_OK) == 0) { + return dir; + } } #endif return std::string(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ccache-4.7.3/src/InodeCache.cpp new/ccache-4.7.4/src/InodeCache.cpp --- old/ccache-4.7.3/src/InodeCache.cpp 2022-11-05 16:49:59.000000000 +0100 +++ new/ccache-4.7.4/src/InodeCache.cpp 2022-11-21 19:53:32.000000000 +0100 @@ -29,6 +29,8 @@ #include "Util.hpp" #include "fmtmacros.hpp" +#include <util/TimePoint.hpp> + #include <fcntl.h> #include <libgen.h> #include <sys/mman.h> @@ -225,6 +227,13 @@ return false; } + // See comment for InodeCache::InodeCache why this check is done. + auto now = util::TimePoint::now(); + if (now - stat.ctime() < m_min_age || now - stat.mtime() < m_min_age) { + LOG("Too new ctime or mtime of {}, not considering for inode cache", path); + return false; + } + Key key; memset(&key, 0, sizeof(Key)); key.type = type; @@ -375,7 +384,12 @@ return false; } -InodeCache::InodeCache(const Config& config) : m_config(config) +InodeCache::InodeCache(const Config& config, util::Duration min_age) + : m_config(config), + // CCACHE_DISABLE_INODE_CACHE_MIN_AGE is only for testing purposes; see + // test/suites/inode_cache.bash. + m_min_age(getenv("CCACHE_DISABLE_INODE_CACHE_MIN_AGE") ? util::Duration(0) + : min_age) { } @@ -474,8 +488,9 @@ return false; } - LOG("Inode cache insert: {}", path); - + if (m_config.debug()) { + LOG("Inode cache insert: {}", path); + } return true; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ccache-4.7.3/src/InodeCache.hpp new/ccache-4.7.4/src/InodeCache.hpp --- old/ccache-4.7.3/src/InodeCache.hpp 2022-11-05 16:49:59.000000000 +0100 +++ new/ccache-4.7.4/src/InodeCache.hpp 2022-11-21 19:53:32.000000000 +0100 @@ -18,6 +18,8 @@ #pragma once +#include <util/Duration.hpp> + #include <cstdint> #include <functional> #include <string> @@ -41,7 +43,26 @@ checked_for_temporal_macros = 1, }; - InodeCache(const Config& config); + // `min_age` specifies how old a file must be to be put in the cache. The + // reason for this is that there is a race condition that consists of these + // events: + // + // 1. A file is written with content C1, size S and timestamp (ctime/mtime) T. + // 2. Ccache hashes the file content and asks the inode cache to store the + // digest with a hash of S and T (and some other data) as the key. + // 3. The file is quickly thereafter written with content C2 without changing + // size S and timestamp T. The timestamp is not updated since the file + // writes are made within a time interval smaller than the granularity of + // the clock used for file system timestamps. At the time of writing, a + // common granularity on a Linux system is 0.004 s (250 Hz). + // 4. The inode cache is asked for the file digest and the inode cache + // delivers a digest of C1 even though the file's content is C2. + // + // To avoid the race condition, the inode cache only caches inodes whose + // timestamp was updated more than `min_age` ago. The default value is a + // conservative 2 seconds since not all file systems have subsecond + // resolution. + InodeCache(const Config& config, util::Duration min_age = util::Duration(2)); ~InodeCache(); // Return whether it's possible to use the inode cache on the filesystem @@ -101,14 +122,14 @@ using BucketHandler = std::function<void(Bucket* bucket)>; bool mmap_file(const std::string& inode_cache_file); - static bool - hash_inode(const std::string& path, ContentType type, Digest& digest); + bool hash_inode(const std::string& path, ContentType type, Digest& digest); bool with_bucket(const Digest& key_digest, const BucketHandler& bucket_handler); static bool create_new_file(const std::string& filename); bool initialize(); const Config& m_config; + util::Duration m_min_age; struct SharedRegion* m_sr = nullptr; bool m_failed = false; }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ccache-4.7.3/src/ThreadPool.cpp new/ccache-4.7.4/src/ThreadPool.cpp --- old/ccache-4.7.3/src/ThreadPool.cpp 2022-11-05 16:49:59.000000000 +0100 +++ new/ccache-4.7.4/src/ThreadPool.cpp 2022-11-21 19:53:32.000000000 +0100 @@ -51,6 +51,10 @@ { { std::unique_lock<std::mutex> lock(m_mutex); + if (m_shutting_down) { + // Already called shut_down. + return; + } m_shutting_down = true; } m_task_enqueued_or_shutting_down_condition.notify_all(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ccache-4.7.3/src/Util.cpp new/ccache-4.7.4/src/Util.cpp --- old/ccache-4.7.3/src/Util.cpp 2022-11-05 16:49:59.000000000 +0100 +++ new/ccache-4.7.4/src/Util.cpp 2022-11-21 19:53:32.000000000 +0100 @@ -438,7 +438,8 @@ { std::string result; const char* left = str.c_str(); - for (const char* right = left; *right; ++right) { + const char* right = left; + while (*right) { if (*right == '$') { result.append(left, right - left); @@ -471,6 +472,7 @@ left = right + 1; } } + ++right; } result += left; return result; @@ -480,8 +482,13 @@ fallocate(int fd, long new_size) { #ifdef HAVE_POSIX_FALLOCATE - return posix_fallocate(fd, 0, new_size); -#else + const int posix_fallocate_err = posix_fallocate(fd, 0, new_size); + if (posix_fallocate_err == 0 || posix_fallocate_err != EINVAL) { + return posix_fallocate_err; + } + // the underlying filesystem does not support the operation so fallback to + // lseeks +#endif off_t saved_pos = lseek(fd, 0, SEEK_END); off_t old_size = lseek(fd, 0, SEEK_END); if (old_size == -1) { @@ -508,7 +515,6 @@ lseek(fd, saved_pos, SEEK_SET); free(buf); return err; -#endif } std::string diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ccache-4.7.3/src/ccache.cpp new/ccache-4.7.4/src/ccache.cpp --- old/ccache-4.7.3/src/ccache.cpp 2022-11-05 16:49:59.000000000 +0100 +++ new/ccache-4.7.4/src/ccache.cpp 2022-11-21 19:53:32.000000000 +0100 @@ -166,10 +166,11 @@ auto prefix = debug_dir.empty() ? output_obj : debug_dir + util::to_absolute_path_no_drive(output_obj); - if (!Util::create_dir(Util::dir_name(prefix))) { - // Ignore since we can't handle an error in another way in this context. The - // caller takes care of logging when trying to open the path for writing. - } + + // Ignore any error from create_dir since we can't handle an error in another + // way in this context. The caller takes care of logging when trying to open + // the path for writing. + Util::create_dir(Util::dir_name(prefix)); char timestamp[100]; const auto tm = Util::localtime(time_of_invocation); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ccache-4.7.3/src/core/CMakeLists.txt new/ccache-4.7.4/src/core/CMakeLists.txt --- old/ccache-4.7.3/src/core/CMakeLists.txt 2022-11-05 16:49:59.000000000 +0100 +++ new/ccache-4.7.4/src/core/CMakeLists.txt 2022-11-21 19:53:32.000000000 +0100 @@ -2,11 +2,11 @@ sources CacheEntry.cpp Manifest.cpp + MsvcShowIncludesOutput.cpp Result.cpp ResultExtractor.cpp ResultInspector.cpp ResultRetriever.cpp - MsvcShowIncludesOutput.cpp Statistics.cpp StatisticsCounters.cpp StatsLog.cpp diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ccache-4.7.3/src/core/CacheEntry.cpp new/ccache-4.7.4/src/core/CacheEntry.cpp --- old/ccache-4.7.3/src/core/CacheEntry.cpp 2022-11-05 16:49:59.000000000 +0100 +++ new/ccache-4.7.4/src/core/CacheEntry.cpp 2022-11-21 19:53:32.000000000 +0100 @@ -117,7 +117,7 @@ CacheEntry::Header::inspect() const { std::string result; - result += result += FMT("Magic: {:04x}\n", magic); + result += FMT("Magic: {:04x}\n", magic); result += FMT("Entry format version: {}\n", entry_format_version); result += FMT("Entry type: {} ({})\n", static_cast<uint8_t>(entry_type), diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ccache-4.7.3/src/storage/local/LocalStorage_compress.cpp new/ccache-4.7.4/src/storage/local/LocalStorage_compress.cpp --- old/ccache-4.7.3/src/storage/local/LocalStorage_compress.cpp 2022-11-05 16:49:59.000000000 +0100 +++ new/ccache-4.7.4/src/storage/local/LocalStorage_compress.cpp 2022-11-21 19:53:32.000000000 +0100 @@ -22,6 +22,7 @@ #include <Context.hpp> #include <File.hpp> #include <Logging.hpp> +#include <TemporaryFile.hpp> #include <ThreadPool.hpp> #include <assertions.hpp> #include <core/CacheEntry.hpp> @@ -219,7 +220,7 @@ // Ignore for now. } }); - } else { + } else if (!TemporaryFile::is_tmp_file(file.path())) { statistics.update(0, 0, 0, file.lstat().size()); } @@ -234,6 +235,9 @@ }, progress_receiver); + // In case there was no f subdir, shut down the thread pool now. + thread_pool.shut_down(); + if (isatty(STDOUT_FILENO)) { PRINT_RAW(stdout, "\n\n"); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ccache-4.7.3/src/storage/remote/HttpStorage.cpp new/ccache-4.7.4/src/storage/remote/HttpStorage.cpp --- old/ccache-4.7.3/src/storage/remote/HttpStorage.cpp 2022-11-05 16:49:59.000000000 +0100 +++ new/ccache-4.7.4/src/storage/remote/HttpStorage.cpp 2022-11-21 19:53:32.000000000 +0100 @@ -94,6 +94,14 @@ return get_partial_url(url).str(); } +RemoteStorage::Backend::Failure +failure_from_httplib_error(httplib::Error error) +{ + return error == httplib::Error::ConnectionTimeout + ? RemoteStorage::Backend::Failure::timeout + : RemoteStorage::Backend::Failure::error; +} + HttpStorageBackend::HttpStorageBackend(const Params& params) : m_url_path(get_url_path(params.url)), m_http_client(get_url(params.url)) @@ -155,7 +163,7 @@ url_path, to_string(result.error()), static_cast<int>(result.error())); - return nonstd::make_unexpected(Failure::error); + return nonstd::make_unexpected(failure_from_httplib_error(result.error())); } if (result->status < 200 || result->status >= 300) { @@ -181,7 +189,8 @@ url_path, to_string(result.error()), static_cast<int>(result.error())); - return nonstd::make_unexpected(Failure::error); + return nonstd::make_unexpected( + failure_from_httplib_error(result.error())); } if (result->status >= 200 && result->status < 300) { @@ -204,14 +213,14 @@ url_path, to_string(result.error()), static_cast<int>(result.error())); - return nonstd::make_unexpected(Failure::error); + return nonstd::make_unexpected(failure_from_httplib_error(result.error())); } if (result->status < 200 || result->status >= 300) { LOG("Failed to put {} to http storage: status code: {}", url_path, result->status); - return nonstd::make_unexpected(Failure::error); + return nonstd::make_unexpected(failure_from_httplib_error(result.error())); } return true; @@ -228,14 +237,14 @@ url_path, to_string(result.error()), static_cast<int>(result.error())); - return nonstd::make_unexpected(Failure::error); + return nonstd::make_unexpected(failure_from_httplib_error(result.error())); } if (result->status < 200 || result->status >= 300) { LOG("Failed to delete {} from http storage: status code: {}", url_path, result->status); - return nonstd::make_unexpected(Failure::error); + return nonstd::make_unexpected(failure_from_httplib_error(result.error())); } return true; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ccache-4.7.3/src/util/Duration.hpp new/ccache-4.7.4/src/util/Duration.hpp --- old/ccache-4.7.3/src/util/Duration.hpp 2022-11-05 16:49:59.000000000 +0100 +++ new/ccache-4.7.4/src/util/Duration.hpp 2022-11-21 19:53:32.000000000 +0100 @@ -93,25 +93,25 @@ inline Duration Duration::operator+(const Duration& other) const { - return Duration(m_ns + other.m_ns); + return Duration(0, m_ns + other.m_ns); } inline Duration Duration::operator-(const Duration& other) const { - return Duration(m_ns - other.m_ns); + return Duration(0, m_ns - other.m_ns); } inline Duration Duration::operator*(double factor) const { - return Duration(factor * m_ns); + return Duration(0, factor * m_ns); } inline Duration Duration::operator/(double factor) const { - return Duration(m_ns / factor); + return Duration(0, m_ns / factor); } inline int64_t diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ccache-4.7.3/src/util/file.cpp new/ccache-4.7.4/src/util/file.cpp --- old/ccache-4.7.3/src/util/file.cpp 2022-11-05 16:49:59.000000000 +0100 +++ new/ccache-4.7.4/src/util/file.cpp 2022-11-21 19:53:32.000000000 +0100 @@ -296,7 +296,7 @@ write_fd(int fd, const void* data, size_t size) { int64_t written = 0; - do { + while (static_cast<size_t>(written) < size) { const auto count = write(fd, static_cast<const uint8_t*>(data) + written, size - written); if (count == -1) { @@ -306,7 +306,7 @@ } else { written += count; } - } while (static_cast<size_t>(written) < size); + } return {}; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ccache-4.7.3/src/util/string.cpp new/ccache-4.7.4/src/util/string.cpp --- old/ccache-4.7.3/src/util/string.cpp 2022-11-05 16:49:59.000000000 +0100 +++ new/ccache-4.7.4/src/util/string.cpp 2022-11-21 19:53:32.000000000 +0100 @@ -134,7 +134,8 @@ std::string result; result.reserve(string.size()); - for (size_t i = 0; i < string.size(); ++i) { + size_t i = 0; + while (i < string.size()) { if (string[i] != '%') { result += string[i]; } else if (i + 2 >= string.size() || !std::isxdigit(string[i + 1]) @@ -147,6 +148,7 @@ result += ch; i += 2; } + ++i; } return result; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ccache-4.7.3/test/suites/inode_cache.bash new/ccache-4.7.4/test/suites/inode_cache.bash --- old/ccache-4.7.3/test/suites/inode_cache.bash 2022-11-05 16:49:59.000000000 +0100 +++ new/ccache-4.7.4/test/suites/inode_cache.bash 2022-11-21 19:53:32.000000000 +0100 @@ -19,6 +19,11 @@ export CCACHE_DEBUG=1 unset CCACHE_NODIRECT export CCACHE_TEMPDIR="${CCACHE_DIR}/tmp" # isolate inode cache file + + # Disable safety guard against race condition in InodeCache. This is OK + # since files used in the tests have different sizes and thus will have + # different cache keys even if ctime/mtime are not updated quickly enough. + export CCACHE_DISABLE_INODE_CACHE_MIN_AGE=1 } SUITE_inode_cache() { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ccache-4.7.3/unittest/CMakeLists.txt new/ccache-4.7.4/unittest/CMakeLists.txt --- old/ccache-4.7.3/unittest/CMakeLists.txt 2022-11-05 16:49:59.000000000 +0100 +++ new/ccache-4.7.4/unittest/CMakeLists.txt 2022-11-21 19:53:32.000000000 +0100 @@ -21,6 +21,7 @@ test_storage_local_StatsFile.cpp test_storage_local_util.cpp test_util_Bytes.cpp + test_util_Duration.cpp test_util_LockFile.cpp test_util_TextTable.cpp test_util_TimePoint.cpp diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ccache-4.7.3/unittest/test_InodeCache.cpp new/ccache-4.7.4/unittest/test_InodeCache.cpp --- old/ccache-4.7.3/unittest/test_InodeCache.cpp 2022-11-05 16:49:59.000000000 +0100 +++ new/ccache-4.7.4/unittest/test_InodeCache.cpp 2022-11-21 19:53:32.000000000 +0100 @@ -74,7 +74,7 @@ Config config; init(config); config.set_inode_cache(false); - InodeCache inode_cache(config); + InodeCache inode_cache(config, util::Duration(0)); Digest digest; int return_value; @@ -99,7 +99,7 @@ Config config; init(config); - InodeCache inode_cache(config); + InodeCache inode_cache(config, util::Duration(0)); util::write_file("a", ""); Digest digest; @@ -121,7 +121,7 @@ Config config; init(config); - InodeCache inode_cache(config); + InodeCache inode_cache(config, util::Duration(0)); util::write_file("a", "a text"); CHECK(put(inode_cache, "a", "a text", 1)); @@ -169,7 +169,7 @@ Config config; init(config); - InodeCache inode_cache(config); + InodeCache inode_cache(config, util::Duration(0)); Digest digest; @@ -187,7 +187,7 @@ Config config; init(config); - InodeCache inode_cache(config); + InodeCache inode_cache(config, util::Duration(0)); util::write_file("a", "a text"); Digest binary_digest = Hash().hash("binary").digest(); Digest code_digest = Hash().hash("code").digest(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ccache-4.7.3/unittest/test_util_Duration.cpp new/ccache-4.7.4/unittest/test_util_Duration.cpp --- old/ccache-4.7.3/unittest/test_util_Duration.cpp 1970-01-01 01:00:00.000000000 +0100 +++ new/ccache-4.7.4/unittest/test_util_Duration.cpp 2022-11-21 19:53:32.000000000 +0100 @@ -0,0 +1,131 @@ +// Copyright (C) 2022 Joel Rosdahl and other contributors +// +// See doc/AUTHORS.adoc for a complete list of contributors. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, write to the Free Software Foundation, Inc., 51 +// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +#include <util/Duration.hpp> + +#include <third_party/doctest.h> + +TEST_SUITE_BEGIN("util::Duration"); + +using util::Duration; + +TEST_CASE("Basics") +{ + Duration d0(4711, 2042); + + CHECK(d0.sec() == 4711); + CHECK(d0.nsec() == 4711000002042); + CHECK(d0.nsec_decimal_part() == 2042); +} + +TEST_CASE("Comparison operators") +{ + Duration d0(1000, 0); + Duration d1(1000, 42); + Duration d2(1001, 0); + + SUBCASE("operator==") + { + CHECK(d0 == d0); + CHECK(!(d0 == d1)); + CHECK(!(d1 == d0)); + CHECK(!(d0 == d2)); + CHECK(!(d2 == d0)); + } + + SUBCASE("operator!=") + { + CHECK(!(d0 != d0)); + CHECK(d0 != d1); + CHECK(d1 != d0); + } + + SUBCASE("operator<") + { + CHECK(d0 < d1); + CHECK(d0 < d2); + CHECK(d1 < d2); + CHECK(!(d1 < d0)); + CHECK(!(d2 < d0)); + CHECK(!(d2 < d1)); + } + + SUBCASE("operator>") + { + CHECK(d2 > d1); + CHECK(d2 > d0); + CHECK(d1 > d0); + CHECK(!(d1 > d2)); + CHECK(!(d0 > d2)); + CHECK(!(d0 > d1)); + } + + SUBCASE("operator<=") + { + CHECK(d0 <= d0); + CHECK(d0 <= d1); + CHECK(d0 <= d2); + CHECK(!(d1 <= d0)); + CHECK(!(d2 <= d0)); + } + + SUBCASE("operator>=") + { + CHECK(d2 >= d1); + CHECK(d2 >= d0); + CHECK(d1 >= d0); + CHECK(!(d1 >= d2)); + CHECK(!(d0 >= d2)); + } +} + +TEST_CASE("Arithmetic operators") +{ + Duration d0(1, 2); + Duration d1(3, 9); + + SUBCASE("operator+") + { + Duration d = d0 + d1; + CHECK(d.sec() == 4); + CHECK(d.nsec_decimal_part() == 11); + } + + SUBCASE("operator-") + { + Duration d = d0 - d1; + CHECK(d.sec() == -2); + CHECK(d.nsec_decimal_part() == -7); + } + + SUBCASE("operator*") + { + Duration d = d1 * 4; + CHECK(d.sec() == 12); + CHECK(d.nsec_decimal_part() == 36); + } + + SUBCASE("operator/") + { + Duration d = d1 / 0.8; + CHECK(d.sec() == 3); + CHECK(d.nsec_decimal_part() == 750'000'011); + } +} + +TEST_SUITE_END(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ccache-4.7.3/unittest/test_util_TimePoint.cpp new/ccache-4.7.4/unittest/test_util_TimePoint.cpp --- old/ccache-4.7.3/unittest/test_util_TimePoint.cpp 2022-11-05 16:49:59.000000000 +0100 +++ new/ccache-4.7.4/unittest/test_util_TimePoint.cpp 2022-11-21 19:53:32.000000000 +0100 @@ -30,6 +30,7 @@ CHECK(t0.sec() == 4711); CHECK(t0.nsec() == 4711000002042); + CHECK(t0.nsec_decimal_part() == 2042); } TEST_CASE("Conversions")