mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
[Support] Extend sys::path with user_cache_directory function.
Summary: The new function sys::path::user_cache_directory tries to discover a directory suitable for cache storage for current system user. On Windows and Darwin it returns a path to system-specific user cache directory. On Linux it follows XDG Base Directory Specification, what is: - use non-empty $XDG_CACHE_HOME env var, - use $HOME/.cache. Reviewers: chapuni, aaron.ballman, rafael Subscribers: rafael, aaron.ballman, llvm-commits Differential Revision: http://reviews.llvm.org/D13801 llvm-svn: 251784
This commit is contained in:
parent
dd070c17bb
commit
669b84345b
@ -325,6 +325,22 @@ 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);
|
||||
|
||||
/// @brief Get the user's cache directory.
|
||||
///
|
||||
/// Expect the resulting path to be a directory shared with other
|
||||
/// applications/services used by the user. Params \p Path1 to \p Path3 can be
|
||||
/// used to append additional directory names to the resulting path. Recommended
|
||||
/// pattern is <user_cache_directory>/<vendor>/<application>.
|
||||
///
|
||||
/// @param Result Holds the resulting path.
|
||||
/// @param Path1 Additional path to be appended to the user's cache directory
|
||||
/// path. "" can be used to append nothing.
|
||||
/// @param Path2 Second additional path to be appended.
|
||||
/// @param Path3 Third additional path to be appended.
|
||||
/// @result True if a cache directory path is set, false otherwise.
|
||||
bool user_cache_directory(SmallVectorImpl<char> &Result, const Twine &Path1,
|
||||
const Twine &Path2 = "", const Twine &Path3 = "");
|
||||
|
||||
/// @brief Has root name?
|
||||
///
|
||||
/// root_name != ""
|
||||
|
@ -1094,3 +1094,20 @@ std::error_code directory_entry::status(file_status &result) const {
|
||||
#if defined(LLVM_ON_WIN32)
|
||||
#include "Windows/Path.inc"
|
||||
#endif
|
||||
|
||||
namespace llvm {
|
||||
namespace sys {
|
||||
namespace path {
|
||||
|
||||
bool user_cache_directory(SmallVectorImpl<char> &Result, const Twine &Path1,
|
||||
const Twine &Path2, const Twine &Path3) {
|
||||
if (getUserCacheDir(Result)) {
|
||||
append(Result, Path1, Path2, Path3);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // end namespace path
|
||||
} // end namsspace sys
|
||||
} // end namespace llvm
|
||||
|
@ -560,6 +560,57 @@ bool home_directory(SmallVectorImpl<char> &result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace {
|
||||
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.
|
||||
// macros defined in <unistd.h> on darwin >= 9
|
||||
int ConfName = TempDir ? _CS_DARWIN_USER_TEMP_DIR
|
||||
: _CS_DARWIN_USER_CACHE_DIR;
|
||||
size_t ConfLen = confstr(ConfName, nullptr, 0);
|
||||
if (ConfLen > 0) {
|
||||
do {
|
||||
Result.resize(ConfLen);
|
||||
ConfLen = confstr(ConfName, Result.data(), Result.size());
|
||||
} while (ConfLen > 0 && ConfLen != Result.size());
|
||||
|
||||
if (ConfLen > 0) {
|
||||
assert(Result.back() == 0);
|
||||
Result.pop_back();
|
||||
return true;
|
||||
}
|
||||
|
||||
Result.clear();
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
bool getUserCacheDir(SmallVectorImpl<char> &Result) {
|
||||
// First try using XDS_CACHE_HOME env variable,
|
||||
// as specified in XDG Base Directory Specification at
|
||||
// http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
|
||||
if (const char *XdsCacheDir = std::getenv("XDS_CACHE_HOME")) {
|
||||
Result.clear();
|
||||
Result.append(XdsCacheDir, XdsCacheDir + strlen(XdsCacheDir));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try Darwin configuration query
|
||||
if (getDarwinConfDir(false, Result))
|
||||
return true;
|
||||
|
||||
// Use "$HOME/.cache" if $HOME is available
|
||||
if (home_directory(Result)) {
|
||||
append(Result, ".cache");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const char *getEnvTempDir() {
|
||||
// Check whether the temporary directory is specified by an environment
|
||||
// variable.
|
||||
@ -594,27 +645,8 @@ void system_temp_directory(bool ErasedOnReboot, 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.
|
||||
// macros defined in <unistd.h> on darwin >= 9
|
||||
int ConfName = ErasedOnReboot? _CS_DARWIN_USER_TEMP_DIR
|
||||
: _CS_DARWIN_USER_CACHE_DIR;
|
||||
size_t ConfLen = confstr(ConfName, nullptr, 0);
|
||||
if (ConfLen > 0) {
|
||||
do {
|
||||
Result.resize(ConfLen);
|
||||
ConfLen = confstr(ConfName, Result.data(), Result.size());
|
||||
} while (ConfLen > 0 && ConfLen != Result.size());
|
||||
|
||||
if (ConfLen > 0) {
|
||||
assert(Result.back() == 0);
|
||||
Result.pop_back();
|
||||
return;
|
||||
}
|
||||
|
||||
Result.clear();
|
||||
}
|
||||
#endif
|
||||
if (getDarwinConfDir(ErasedOnReboot, Result))
|
||||
return;
|
||||
|
||||
const char *RequestedDir = getDefaultTempDir(ErasedOnReboot);
|
||||
Result.append(RequestedDir, RequestedDir + strlen(RequestedDir));
|
||||
|
@ -765,6 +765,10 @@ bool getKnownFolderPath(KNOWNFOLDERID folderId, SmallVectorImpl<char> &result) {
|
||||
::CoTaskMemFree(path);
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool getUserCacheDir(SmallVectorImpl<char> &Result) {
|
||||
return getKnownFolderPath(FOLDERID_LocalAppData, Result);
|
||||
}
|
||||
}
|
||||
|
||||
bool home_directory(SmallVectorImpl<char> &result) {
|
||||
|
@ -322,6 +322,35 @@ TEST(Support, HomeDirectory) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Support, UserCacheDirectory) {
|
||||
SmallString<13> CacheDir;
|
||||
SmallString<20> CacheDir2;
|
||||
auto Status = path::user_cache_directory(CacheDir, "");
|
||||
EXPECT_TRUE(Status ^ CacheDir.empty());
|
||||
|
||||
if (Status) {
|
||||
EXPECT_TRUE(path::user_cache_directory(CacheDir2, "")); // should succeed
|
||||
EXPECT_EQ(CacheDir, CacheDir2); // and return same paths
|
||||
|
||||
EXPECT_TRUE(path::user_cache_directory(CacheDir, "A", "B", "file.c"));
|
||||
auto It = path::rbegin(CacheDir);
|
||||
EXPECT_EQ("file.c", *It);
|
||||
EXPECT_EQ("B", *++It);
|
||||
EXPECT_EQ("A", *++It);
|
||||
auto ParentDir = *++It;
|
||||
|
||||
// Test Unicode: "<user_cache_dir>/(pi)r^2/aleth.0"
|
||||
EXPECT_TRUE(path::user_cache_directory(CacheDir2, "\xCF\x80r\xC2\xB2",
|
||||
"\xE2\x84\xB5.0"));
|
||||
auto It2 = path::rbegin(CacheDir2);
|
||||
EXPECT_EQ("\xE2\x84\xB5.0", *It2);
|
||||
EXPECT_EQ("\xCF\x80r\xC2\xB2", *++It2);
|
||||
auto ParentDir2 = *++It2;
|
||||
|
||||
EXPECT_EQ(ParentDir, ParentDir2);
|
||||
}
|
||||
}
|
||||
|
||||
class FileSystemTest : public testing::Test {
|
||||
protected:
|
||||
/// Unique temporary directory in which all created filesystem entities must
|
||||
|
Loading…
Reference in New Issue
Block a user