std::function<void(unsigned Task, std::unique_ptr<MemoryBuffer> MB)>;
/// Create a local file system cache which uses the given cache name, temporary
-/// file prefix, cache directory and file callback. This function also creates
-/// the cache directory if it does not already exist. The cache name appears in
-/// error messages for errors during caching. The temporary file prefix is used
-/// in the temporary file naming scheme used when writing files atomically.
+/// file prefix, cache directory and file callback. This function does not
+/// immediately create the cache directory if it does not yet exist; this is
+/// done lazily the first time a file is added. The cache name appears in error
+/// messages for errors during caching. The temporary file prefix is used in the
+/// temporary file naming scheme used when writing files atomically.
Expected<FileCache> localCache(
Twine CacheNameRef, Twine TempFilePrefixRef, Twine CacheDirectoryPathRef,
AddBufferFn AddBuffer = [](size_t Task, std::unique_ptr<MemoryBuffer> MB) {
Twine TempFilePrefixRef,
Twine CacheDirectoryPathRef,
AddBufferFn AddBuffer) {
- if (std::error_code EC = sys::fs::create_directories(CacheDirectoryPathRef))
- return errorCodeToError(EC);
// Create local copies which are safely captured-by-copy in lambdas
SmallString<64> CacheName, TempFilePrefix, CacheDirectoryPath;
};
return [=](size_t Task) -> Expected<std::unique_ptr<CachedFileStream>> {
+ // Create the cache directory if not already done. Doing this lazily
+ // ensures the filesystem isn't mutated until the cache is.
+ if (std::error_code EC = sys::fs::create_directories(
+ CacheDirectoryPath, /*IgnoreExisting=*/true))
+ return errorCodeToError(EC);
+
// Write to a temporary to avoid race condition
SmallString<64> TempFilenameModel;
sys::path::append(TempFilenameModel, CacheDirectoryPath,
; RUN: -r=%t2.bc,_main,plx \
; RUN: -r=%t2.bc,_globalfunc,lx \
; RUN: -r=%t.bc,_globalfunc,plx
-; RUN: ls %t.cache.noindex | count 0
+; RUN: not ls %t.cache.noindex
; Repeat again, *with* hash this time.
; RUN: rm -Rf %t.cache
; RUN: llvm-lto2 run -o %t.o %t2.bc %t.bc -cache-dir %t.cache \
; RUN: -r=%t2.bc,_main,plx
-; RUN: ls %t.cache | count 0
+; RUN: not ls %t.cache
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
#define setenv(name, var, ignore) _putenv_s(name, var)
#endif
+#define ASSERT_NO_ERROR(x) \
+ if (std::error_code ASSERT_NO_ERROR_ec = x) { \
+ SmallString<128> MessageStorage; \
+ raw_svector_ostream Message(MessageStorage); \
+ Message << #x ": did not return errc::success.\n" \
+ << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n" \
+ << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \
+ GTEST_FATAL_FAILURE_(MessageStorage.c_str()); \
+ } else { \
+ }
+
using namespace llvm;
// Check that the Debuginfod client can find locally cached artifacts.
// Check that the Debuginfod client returns an Error when it fails to find an
// artifact.
TEST(DebuginfodClient, CacheMiss) {
- // Set the cache path to a temp directory to avoid permissions issues if $HOME
- // is not writable.
- SmallString<32> TempDir;
- sys::path::system_temp_directory(true, TempDir);
- setenv("DEBUGINFOD_CACHE_PATH", TempDir.c_str(),
+ SmallString<32> CacheDir;
+ ASSERT_NO_ERROR(
+ sys::fs::createUniqueDirectory("debuginfod-unittest", CacheDir));
+ sys::path::append(CacheDir, "cachedir");
+ ASSERT_FALSE(sys::fs::exists(CacheDir));
+ setenv("DEBUGINFOD_CACHE_PATH", CacheDir.c_str(),
/*replace=*/1);
// Ensure there are no urls to guarantee a cache miss.
setenv("DEBUGINFOD_URLS", "", /*replace=*/1);
Expected<std::string> PathOrErr = getCachedOrDownloadArtifact(
/*UniqueKey=*/"nonexistent-key", /*UrlPath=*/"/null");
EXPECT_THAT_EXPECTED(PathOrErr, Failed<StringError>());
+ // A cache miss with no possible URLs should not create the cache directory.
+ EXPECT_FALSE(sys::fs::exists(CacheDir));
}