[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/vixcpp/cli/dev/src/util/ProjectMutation.cpp [Back]  [Original]

#include 
#include 
#include 
#include 
#include 
#include 
#ifndef _WIN32
#include 
#include 
#include 
#endif
namespace vix::cli::util
{
  namespace fs = std::filesystem;
  namespace {
    std::atomic sequence{0};
    std::optional read_bytes(const fs::path &p) { std::ifstream in(p, std::ios::binary); if (!in) return std::nullopt; return std::string((std::istreambuf_iterator(in)), {}); }
    bool write_bytes(const fs::path &p, const std::string &bytes) { std::ofstream out(p, std::ios::binary | std::ios::trunc); return out && static_cast(out > kind >> existed >> index >> std::quoted(relative)) {
          const fs::path target=root/fs::path(relative);
          if (!under_root(root, target)) { error="unsafe transaction journal path"; return false; }
          if (existed) { const auto bytes=read_bytes(journal/("original-"+std::to_string(index))); if (!bytes || !write_bytes(target, *bytes)) { error="cannot restore unfinished transaction"; return false; } }
          else { fs::remove(target, ec); if (ec) { error="cannot remove unfinished transaction output: "+ec.message(); return false; } }
        }
        if (!in.eof()) { error="invalid transaction journal"; return false; }
        fs::remove_all(journal, ec); if (ec) { error="cannot remove recovered transaction journal: "+ec.message(); return false; }
      }
      return true;
    }
  }
  ProjectMutationLock::ProjectMutationLock(const fs::path &root)
  {
#ifdef _WIN32
    error_ = "Project mutation lock is not implemented on this platform.";
#else
    std::error_code ec; fs::create_directories(root / ".vix" / "locks", ec); if (ec) { error_="cannot create mutation lock directory: "+ec.message(); return; }
    const auto path = root / ".vix" / "locks" / "project-mutation.lock";
    fd_ = ::open(path.c_str(), O_CREAT | O_RDWR, 0600); if (fd_ < 0) { error_="cannot open project mutation lock"; return; }
    if (::flock(fd_, LOCK_EX | LOCK_NB) != 0) { ::close(fd_); fd_=-1; error_="another Vix project mutation is active"; return; }
    if (!recover_transactions(root, error_)) { ::flock(fd_, LOCK_UN); ::close(fd_); fd_=-1; }
#endif
  }
  ProjectMutationLock::~ProjectMutationLock()
  {
#ifndef _WIN32
    if (fd_ >= 0) { ::flock(fd_, LOCK_UN); ::close(fd_); }
#endif
  }
  ProjectMutationTransaction::ProjectMutationTransaction(const fs::path &root) : root_(root) {}
  ProjectMutationTransaction::~ProjectMutationTransaction() { if (!finished_) rollback(); }
  bool ProjectMutationTransaction::stage_write(const fs::path &path, const std::string &bytes, std::string &error)
  {
    if (finished_) { error="transaction is already finished"; return false; }
    std::error_code ec; fs::create_directories(path.parent_path(),ec); if (ec) { error="staging failed: "+ec.message(); return false; }
    Item item; item.path=path; item.original=read_bytes(path); item.temporary=path.string()+".vix-txn-"+std::to_string(++sequence);
    { std::ofstream out(item.temporary,std::ios::binary|std::ios::trunc); if (!out || !(out

Web Proxy Viewer  |  New URL  |  Original Page