mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
Add a facility to get system cache directory and use it in clangd
Summary: This patch adds a function that is similar to `llvm::sys::path::home_directory`, but provides access to the system cache directory. For Windows, that is %LOCALAPPDATA%, and applications should put their files under %LOCALAPPDATA%\Organization\Product\. For *nixes, it adheres to the XDG Base Directory Specification, so it first looks at the XDG_CACHE_HOME environment variable and falls back to ~/.cache/. Subsequently, the Clangd Index storage leverages this new API to put index files somewhere else than the users home directory. Fixes https://github.com/clangd/clangd/issues/341 Reviewers: sammccall, chandlerc, Bigcheese Reviewed By: sammccall Subscribers: hiraditya, ilya-biryukov, MaskRay, jkorous, dexonsmith, arphaman, kadircet, ormris, usaxena95, cfe-commits, llvm-commits Tags: #clang-tools-extra, #clang, #llvm Differential Revision: https://reviews.llvm.org/D78501
This commit is contained in:
parent
ee9dafae48
commit
8c739867e7
@ -368,6 +368,13 @@ void system_temp_directory(bool erasedOnReboot, SmallVectorImpl<char> &result);
|
||||
/// @result True if a home directory is set, false otherwise.
|
||||
bool home_directory(SmallVectorImpl<char> &result);
|
||||
|
||||
/// Get the directory where installed packages should put their
|
||||
/// machine-local cache, e.g. $XDG_CACHE_HOME.
|
||||
///
|
||||
/// @param result Holds the resulting path name.
|
||||
/// @result True if the appropriate path was determined, it need not exist.
|
||||
bool cache_directory(SmallVectorImpl<char> &result);
|
||||
|
||||
/// Has root name?
|
||||
///
|
||||
/// root_name != ""
|
||||
|
@ -1138,6 +1138,19 @@ bool home_directory(SmallVectorImpl<char> &result) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cache_directory(SmallVectorImpl<char> &result) {
|
||||
if (const char *RequestedDir = getenv("XDG_CACHE_HOME")) {
|
||||
result.clear();
|
||||
result.append(RequestedDir, RequestedDir + strlen(RequestedDir));
|
||||
return true;
|
||||
}
|
||||
if (!home_directory(result)) {
|
||||
return false;
|
||||
}
|
||||
append(result, ".cache");
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool getDarwinConfDir(bool TempDir, SmallVectorImpl<char> &Result) {
|
||||
#if defined(_CS_DARWIN_USER_TEMP_DIR) && defined(_CS_DARWIN_USER_CACHE_DIR)
|
||||
// On Darwin, use DARWIN_USER_TEMP_DIR or DARWIN_USER_CACHE_DIR.
|
||||
|
@ -1372,6 +1372,10 @@ bool home_directory(SmallVectorImpl<char> &result) {
|
||||
return getKnownFolderPath(FOLDERID_Profile, result);
|
||||
}
|
||||
|
||||
bool cache_directory(SmallVectorImpl<char> &result) {
|
||||
return getKnownFolderPath(FOLDERID_LocalAppData, result);
|
||||
}
|
||||
|
||||
static bool getTempDirEnvVar(const wchar_t *Var, SmallVectorImpl<char> &Res) {
|
||||
SmallVector<wchar_t, 1024> Buf;
|
||||
size_t Size = 1024;
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/BinaryFormat/Magic.h"
|
||||
#include "llvm/Config/llvm-config.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/ConvertUTF.h"
|
||||
#include "llvm/Support/Errc.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
@ -305,15 +306,46 @@ TEST(Support, AbsolutePathIteratorEnd) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Support, HomeDirectory) {
|
||||
std::string expected;
|
||||
#ifdef _WIN32
|
||||
if (wchar_t const *path = ::_wgetenv(L"USERPROFILE")) {
|
||||
std::string getEnvWin(const wchar_t *Var) {
|
||||
std::string expected;
|
||||
if (wchar_t const *path = ::_wgetenv(Var)) {
|
||||
auto pathLen = ::wcslen(path);
|
||||
ArrayRef<char> ref{reinterpret_cast<char const *>(path),
|
||||
pathLen * sizeof(wchar_t)};
|
||||
convertUTF16ToUTF8String(ref, expected);
|
||||
}
|
||||
return expected;
|
||||
}
|
||||
#else
|
||||
// RAII helper to set and restore an environment variable.
|
||||
class WithEnv {
|
||||
const char *Var;
|
||||
llvm::Optional<std::string> OriginalValue;
|
||||
|
||||
public:
|
||||
WithEnv(const char *Var, const char *Value) : Var(Var) {
|
||||
if (const char *V = ::getenv(Var))
|
||||
OriginalValue.emplace(V);
|
||||
if (Value)
|
||||
::setenv(Var, Value, 1);
|
||||
else
|
||||
::unsetenv(Var);
|
||||
set(Value);
|
||||
}
|
||||
~WithEnv() {
|
||||
if (OriginalValue)
|
||||
::setenv(Var, OriginalValue->c_str(), 1);
|
||||
else
|
||||
::unsetenv(Var);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
TEST(Support, HomeDirectory) {
|
||||
std::string expected;
|
||||
#ifdef _WIN32
|
||||
expected = getEnvWin(L"USERPROFILE");
|
||||
#else
|
||||
if (char const *path = ::getenv("HOME"))
|
||||
expected = path;
|
||||
@ -330,31 +362,48 @@ TEST(Support, HomeDirectory) {
|
||||
|
||||
#ifdef LLVM_ON_UNIX
|
||||
TEST(Support, HomeDirectoryWithNoEnv) {
|
||||
std::string OriginalStorage;
|
||||
char const *OriginalEnv = ::getenv("HOME");
|
||||
if (OriginalEnv) {
|
||||
// We're going to unset it, so make a copy and save a pointer to the copy
|
||||
// so that we can reset it at the end of the test.
|
||||
OriginalStorage = OriginalEnv;
|
||||
OriginalEnv = OriginalStorage.c_str();
|
||||
}
|
||||
WithEnv Env("HOME", nullptr);
|
||||
|
||||
// Don't run the test if we have nothing to compare against.
|
||||
struct passwd *pw = getpwuid(getuid());
|
||||
if (!pw || !pw->pw_dir) return;
|
||||
|
||||
::unsetenv("HOME");
|
||||
EXPECT_EQ(nullptr, ::getenv("HOME"));
|
||||
std::string PwDir = pw->pw_dir;
|
||||
|
||||
SmallString<128> HomeDir;
|
||||
auto status = path::home_directory(HomeDir);
|
||||
EXPECT_TRUE(status);
|
||||
EXPECT_TRUE(path::home_directory(HomeDir));
|
||||
EXPECT_EQ(PwDir, HomeDir);
|
||||
}
|
||||
|
||||
// Now put the environment back to its original state (meaning that if it was
|
||||
// unset before, we don't reset it).
|
||||
if (OriginalEnv) ::setenv("HOME", OriginalEnv, 1);
|
||||
TEST(Support, CacheDirectoryWithEnv) {
|
||||
WithEnv Env("XDG_CACHE_HOME", "/xdg/cache");
|
||||
|
||||
SmallString<128> CacheDir;
|
||||
EXPECT_TRUE(path::cache_directory(CacheDir));
|
||||
EXPECT_EQ("/xdg/cache", CacheDir);
|
||||
}
|
||||
|
||||
TEST(Support, CacheDirectoryNoEnv) {
|
||||
WithEnv Env("XDG_CACHE_HOME", nullptr);
|
||||
|
||||
SmallString<128> Fallback;
|
||||
ASSERT_TRUE(path::home_directory(Fallback));
|
||||
path::append(Fallback, ".cache");
|
||||
|
||||
SmallString<128> CacheDir;
|
||||
EXPECT_TRUE(path::cache_directory(CacheDir));
|
||||
EXPECT_EQ(Fallback, CacheDir);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
TEST(Support, CacheDirectory) {
|
||||
std::string Expected = getEnvWin(L"LOCALAPPDATA");
|
||||
// Do not try to test it if we don't know what to expect.
|
||||
if (!Expected.empty()) {
|
||||
SmallString<128> CacheDir;
|
||||
EXPECT_TRUE(path::cache_directory(CacheDir));
|
||||
EXPECT_EQ(Expected, CacheDir);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user