forked from RobotLocomotion/drake
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfind_cache.cc
102 lines (88 loc) · 3.02 KB
/
find_cache.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include "drake/common/find_cache.h"
#include <cstdlib>
#include <filesystem>
#include <optional>
#include <utility>
#include <fmt/format.h>
#include "drake/common/drake_assert.h"
#include "drake/common/text_logging.h"
namespace drake {
namespace internal {
namespace {
namespace fs = std::filesystem;
#if defined(__APPLE__)
constexpr bool kApple = true;
#else
constexpr bool kApple = false;
#endif
/* If var_name is set, returns its value. Otherwise, returns nullopt. */
std::optional<std::string> GetStringEnv(const char* var_name) {
const char* const var_value = std::getenv(var_name);
if (var_value != nullptr) {
return var_value;
}
return std::nullopt;
}
/* If var_name is set to a directory that exists, returns that path.
Otherwise, returns nullopt. */
std::optional<fs::path> GetPathEnv(const char* var_name) {
const char* const var_value = std::getenv(var_name);
if (var_value != nullptr) {
auto path = fs::path{var_value};
std::error_code ec;
if (fs::is_directory(path, ec)) {
return path;
}
}
return std::nullopt;
}
/* If path exists, returns it. Otherwise, creates it and returns it. */
PathOrError CreateDirectory(fs::path path) {
std::error_code ec;
fs::create_directory(path, ec);
if (ec) {
return {.error = fmt::format("Could not create {}: {}", path.string(),
ec.message())};
}
return {.abspath = fs::canonical(path)};
}
} // namespace
PathOrError FindOrCreateCache(std::string_view subdir) {
// We'll try the following options to find the ~/.cache, in order:
// - ${TEST_TMPDIR}/.cache
// - ${XDG_CACHE_HOME}
// - /private/var/tmp/.cache_${USER} (on Apple only)
// - ${HOME}/.cache
const std::optional<fs::path> test_tmpdir = GetPathEnv("TEST_TMPDIR");
const std::optional<fs::path> xdg_cache_home = GetPathEnv("XDG_CACHE_HOME");
const std::optional<std::string> user = GetStringEnv("USER");
const std::optional<fs::path> home = GetPathEnv("HOME");
PathOrError cache_dir;
if (test_tmpdir.has_value()) {
cache_dir = CreateDirectory(*test_tmpdir / ".cache");
} else if (xdg_cache_home.has_value()) {
cache_dir.abspath = *xdg_cache_home;
} else if (kApple && user.has_value()) {
cache_dir = CreateDirectory(fs::path("/private/var/tmp") /
fmt::format(".cache_{}", *user));
} else if (home.has_value()) {
cache_dir = CreateDirectory(*home / ".cache");
} else {
return {.error =
"Could not determine an appropriate cache_dir to use. "
"Set $XDG_CACHE_HOME to a valid scratch directory."};
}
if (!cache_dir.error.empty()) {
return cache_dir;
}
// Create the Drake-specific subdirectory.
auto cache_dir_drake = CreateDirectory(cache_dir.abspath / "drake");
if (!cache_dir_drake.error.empty()) {
return cache_dir_drake;
}
log()->debug("FindCache found {}", cache_dir_drake.abspath.string());
// Create the requested subdirectory.
return CreateDirectory(cache_dir_drake.abspath / subdir);
}
} // namespace internal
} // namespace drake