12#include "absl/strings/str_format.h"
18namespace fs = std::filesystem;
21 : project_(project) {}
28 if (repo.is_relative() && !project_dir.empty())
29 return project_dir / repo;
58 return absl::InvalidArgumentError(
"No project context");
66 return absl::OkStatus();
72 const std::string& message) {
74 return absl::InvalidArgumentError(
"No project context");
92 if (!commit_status.ok()) {
95 LOG_INFO(
"VersionManager",
"Git commit skipped (no changes?)");
102 auto now = std::chrono::system_clock::now();
103 auto time_t = std::chrono::system_clock::to_time_t(now);
104 std::stringstream ss;
105 ss << std::put_time(std::localtime(&time_t),
"%Y%m%d_%H%M%S");
106 std::string timestamp = ss.str();
109 if (backup_status.ok()) {
110 result.
rom_backup_path =
"backups/snapshots/rom_" + timestamp +
".sfc";
112 LOG_ERROR(
"VersionManager",
"Failed to backup ROM: %s",
113 backup_status.ToString().c_str());
117 result.
message =
"Snapshot created successfully.";
131 absl::StrFormat(
"git log -n %d --pretty=format:\"%%h %%s\"", limit);
137 std::vector<std::string> history;
138 std::istringstream stream(*output);
140 while (std::getline(stream, line)) {
142 history.push_back(line);
162 std::string sanitized_msg = message;
164 std::replace(sanitized_msg.begin(), sanitized_msg.end(),
'"',
'\'');
166 return RunCommand(absl::StrFormat(
"git commit -m \"%s\"", sanitized_msg));
173 std::string hash = *res;
174 hash.erase(hash.find_last_not_of(
" \n\r\t") + 1);
185 const std::string& timestamp_str) {
187 return absl::FailedPreconditionError(
188 "Project output folder or build target not defined");
195 fs::path abs_rom_path = project_dir / rom_path;
197 if (!fs::exists(abs_rom_path)) {
198 return absl::NotFoundError(
199 absl::StrFormat(
"Built ROM not found at %s", abs_rom_path.string()));
203 fs::path backup_dir = project_dir /
"backups" /
"snapshots";
205 fs::create_directories(backup_dir, ec);
207 return absl::InternalError(
"Could not create backup directory");
209 std::string filename = absl::StrFormat(
"rom_%s.sfc", timestamp_str);
210 fs::path backup_path = backup_dir / filename;
213 fs::copy_file(abs_rom_path, backup_path, fs::copy_options::overwrite_existing,
216 return absl::InternalError(
217 absl::StrFormat(
"Failed to copy ROM: %s", ec.message()));
220 return absl::OkStatus();
230 return absl::FailedPreconditionError(
231 "Command execution is not available on iOS");
234 std::string full_cmd;
237 if (!project_dir.empty()) {
238 full_cmd = absl::StrFormat(
"cd \"%s\" && %s", project_dir.string(), cmd);
243 int ret = std::system(full_cmd.c_str());
245 return absl::InternalError(
246 absl::StrFormat(
"Command failed: %s (Exit code %d)", cmd, ret));
248 return absl::OkStatus();
253 const std::string& cmd)
const {
256 return absl::FailedPreconditionError(
257 "Command execution is not available on iOS");
259 std::string full_cmd;
261 if (!project_dir.empty()) {
262 full_cmd = absl::StrFormat(
"cd \"%s\" && %s", project_dir.string(), cmd);
267 std::array<char, 128> buffer;
270 std::unique_ptr<FILE,
decltype(&_pclose)> pipe(_popen(full_cmd.c_str(),
"r"),
273 std::unique_ptr<FILE,
decltype(&pclose)> pipe(popen(full_cmd.c_str(),
"r"),
277 return absl::InternalError(
"popen() failed!");
279 while (fgets(buffer.data(), buffer.size(), pipe.get()) !=
nullptr) {
280 result += buffer.data();
absl::Status BackupRomArtifact(const std::string ×tamp_str)
absl::Status GitCommit(const std::string &message)
std::vector< std::string > GetHistory(int limit=10) const
project::YazeProject * project_
bool AdoptExistingRepository()
VersionManager(project::YazeProject *project)
absl::StatusOr< std::string > RunCommandOutput(const std::string &cmd) const
absl::Status InitializeGit()
std::string GetCurrentHash() const
absl::StatusOr< SnapshotResult > CreateSnapshot(const std::string &message)
absl::Status RunCommand(const std::string &cmd)
std::string GitRevParseHead() const
std::filesystem::path RepositoryRoot() const
bool IsGitInitialized() const
#define LOG_ERROR(category, format,...)
#define LOG_INFO(category, format,...)
std::string rom_backup_path
Modern project structure with comprehensive settings consolidation.
std::string git_repository
std::string output_folder
std::string last_build_hash