6#include "absl/status/status.h"
7#include "absl/status/statusor.h"
8#include "absl/strings/str_cat.h"
9#include "absl/strings/str_format.h"
10#include "absl/time/clock.h"
11#include "absl/time/time.h"
19std::filesystem::path DetermineDefaultRoot() {
20 if (
const char* env_root = std::getenv(
"YAZE_SANDBOX_ROOT")) {
21 return std::filesystem::path(env_root);
24 auto temp_dir = std::filesystem::temp_directory_path(ec);
27 return std::filesystem::current_path() /
"yaze" /
"sandboxes";
29 return temp_dir /
"yaze" /
"sandboxes";
33 absl::string_view
id) {
34 return root / std::string(
id);
45 : root_directory_(DetermineDefaultRoot()) {}
48 std::lock_guard<std::mutex> lock(
mutex_);
61 return absl::InternalError(
62 absl::StrCat(
"Failed to create sandbox root at ",
66 return absl::OkStatus();
70 absl::Time now = absl::Now();
71 std::string time_component =
72 absl::FormatTime(
"%Y%m%dT%H%M%S", now, absl::LocalTimeZone());
74 return absl::StrCat(time_component,
"-", sequence_);
77absl::StatusOr<RomSandboxManager::SandboxMetadata>
80 return absl::FailedPreconditionError(
81 "Cannot create sandbox: ROM is not loaded");
84 std::filesystem::path source_path(rom.
filename());
85 if (source_path.empty()) {
86 return absl::FailedPreconditionError(
87 "Cannot create sandbox: ROM filename is empty");
90 std::unique_lock<std::mutex> lock(
mutex_);
94 std::filesystem::path sandbox_dir =
99 if (!std::filesystem::create_directories(sandbox_dir, ec) && ec) {
100 return absl::InternalError(
101 absl::StrCat(
"Failed to create sandbox directory at ",
102 sandbox_dir.string(),
": ", ec.message()));
105 std::filesystem::path sandbox_rom_path = sandbox_dir / source_path.filename();
108 settings.
filename = sandbox_rom_path.string();
112 absl::Status save_status = rom.
SaveToFile(settings);
113 if (!save_status.ok()) {
114 std::error_code cleanup_ec;
115 std::filesystem::remove_all(sandbox_dir, cleanup_ec);
122 .directory = sandbox_dir,
123 .rom_path = sandbox_rom_path,
124 .source_rom = source_path.string(),
125 .description = std::string(description),
126 .created_at = absl::Now(),
133absl::StatusOr<RomSandboxManager::SandboxMetadata>
135 std::lock_guard<std::mutex> lock(
mutex_);
137 return absl::NotFoundError(
"No active sandbox");
141 return absl::NotFoundError(
"Active sandbox metadata missing");
149 return meta.rom_path;
152std::vector<RomSandboxManager::SandboxMetadata>
154 std::lock_guard<std::mutex> lock(
mutex_);
155 std::vector<SandboxMetadata> list;
157 for (
const auto& [_, metadata] :
sandboxes_) {
158 list.push_back(metadata);
160 std::sort(list.begin(), list.end(),
162 return a.created_at < b.created_at;
168 std::lock_guard<std::mutex> lock(
mutex_);
171 return absl::NotFoundError(
"Sandbox not found");
174 std::filesystem::remove_all(it->second.directory, ec);
176 return absl::InternalError(
177 absl::StrCat(
"Failed to remove sandbox directory: ", ec.message()));
183 return absl::OkStatus();
187 absl::Duration max_age) {
188 std::vector<std::string> to_remove;
190 std::lock_guard<std::mutex> lock(
mutex_);
191 absl::Time threshold = absl::Now() - max_age;
192 for (
const auto& [
id, metadata] :
sandboxes_) {
193 if (metadata.created_at < threshold) {
194 to_remove.push_back(
id);
200 for (
const auto&
id : to_remove) {
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
absl::Status SaveToFile(const SaveSettings &settings)
absl::StatusOr< SandboxMetadata > CreateSandbox(Rom &rom, absl::string_view description)
absl::Status RemoveSandbox(const std::string &id)
void SetRootDirectory(const std::filesystem::path &root)
absl::StatusOr< SandboxMetadata > ActiveSandbox() const
absl::StatusOr< int > CleanupOlderThan(absl::Duration max_age)
std::filesystem::path root_directory_
std::vector< SandboxMetadata > ListSandboxes() const
static RomSandboxManager & Instance()
std::string GenerateSandboxIdLocked()
absl::Status EnsureRootExistsLocked()
std::optional< std::string > active_sandbox_id_
absl::StatusOr< std::filesystem::path > ActiveSandboxRomPath() const
const std::filesystem::path & RootDirectory() const
std::unordered_map< std::string, SandboxMetadata > sandboxes_
#define ASSIGN_OR_RETURN(type_variable_name, expression)
std::filesystem::path ResolveUniqueDirectory(const std::filesystem::path &root, absl::string_view id)
#define RETURN_IF_ERROR(expr)