[llvm] r251784 - [Support] Extend sys::path with user_cache_directory function.

Pawel Bylica via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 2 01:49:17 PST 2015


Author: chfast
Date: Mon Nov  2 03:49:17 2015
New Revision: 251784

URL: http://llvm.org/viewvc/llvm-project?rev=251784&view=rev
Log:
[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

Modified:
    llvm/trunk/include/llvm/Support/Path.h
    llvm/trunk/lib/Support/Path.cpp
    llvm/trunk/lib/Support/Unix/Path.inc
    llvm/trunk/lib/Support/Windows/Path.inc
    llvm/trunk/unittests/Support/Path.cpp

Modified: llvm/trunk/include/llvm/Support/Path.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/Path.h?rev=251784&r1=251783&r2=251784&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/Path.h (original)
+++ llvm/trunk/include/llvm/Support/Path.h Mon Nov  2 03:49:17 2015
@@ -325,6 +325,22 @@ void system_temp_directory(bool erasedOn
 /// @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 != ""

Modified: llvm/trunk/lib/Support/Path.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Path.cpp?rev=251784&r1=251783&r2=251784&view=diff
==============================================================================
--- llvm/trunk/lib/Support/Path.cpp (original)
+++ llvm/trunk/lib/Support/Path.cpp Mon Nov  2 03:49:17 2015
@@ -1094,3 +1094,20 @@ std::error_code directory_entry::status(
 #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

Modified: llvm/trunk/lib/Support/Unix/Path.inc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Unix/Path.inc?rev=251784&r1=251783&r2=251784&view=diff
==============================================================================
--- llvm/trunk/lib/Support/Unix/Path.inc (original)
+++ llvm/trunk/lib/Support/Unix/Path.inc Mon Nov  2 03:49:17 2015
@@ -560,6 +560,57 @@ bool home_directory(SmallVectorImpl<char
   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 ErasedOn
     }
   }
 
-#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));

Modified: llvm/trunk/lib/Support/Windows/Path.inc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Windows/Path.inc?rev=251784&r1=251783&r2=251784&view=diff
==============================================================================
--- llvm/trunk/lib/Support/Windows/Path.inc (original)
+++ llvm/trunk/lib/Support/Windows/Path.inc Mon Nov  2 03:49:17 2015
@@ -765,6 +765,10 @@ bool getKnownFolderPath(KNOWNFOLDERID fo
   ::CoTaskMemFree(path);
   return ok;
 }
+
+bool getUserCacheDir(SmallVectorImpl<char> &Result) {
+  return getKnownFolderPath(FOLDERID_LocalAppData, Result);
+}
 }
 
 bool home_directory(SmallVectorImpl<char> &result) {

Modified: llvm/trunk/unittests/Support/Path.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/Path.cpp?rev=251784&r1=251783&r2=251784&view=diff
==============================================================================
--- llvm/trunk/unittests/Support/Path.cpp (original)
+++ llvm/trunk/unittests/Support/Path.cpp Mon Nov  2 03:49:17 2015
@@ -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




More information about the llvm-commits mailing list