1
0
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:
Pawel Bylica 2015-11-02 09:49:17 +00:00
parent dd070c17bb
commit 669b84345b
5 changed files with 119 additions and 21 deletions

View File

@ -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 != ""

View File

@ -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

View File

@ -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));

View File

@ -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) {

View File

@ -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