fxos/lib/project.cpp

186 lines
4.0 KiB
C++

#include <fxos/project.h>
#include <fxos/util/log.h>
#include <filesystem>
#include <algorithm>
#include <string>
using namespace std::literals;
namespace fs = std::filesystem;
namespace FxOS {
//=== Project ===//
Project::Project()
{
m_name = "unnamed_project";
}
void Project::setName(std::string const &new_name)
{
m_name = new_name;
}
void Project::setPath(std::string const &new_path)
{
m_path = new_path;
}
bool Project::canSave() const
{
return m_path != "";
}
bool Project::isDirty() const
{
return m_dirty;
}
void Project::setDirty()
{
m_dirty = true;
}
BSON Project::serializeMetadata() const
{
return BSON::mkDocument({
{"*", BSON::mkString("Project")}, {"name", BSON::mkString(m_name)},
// TODO: List of binaries by name
});
}
bool Project::save()
{
fs::path path(m_path);
if(path == "") {
FxOS_log(ERR, "Project “%s” has no path", m_name.c_str());
return false;
}
std::error_code ec;
fs::create_directories(path, ec);
if(ec) {
FxOS_log(ERR, "Could not create path to '%s': %s", path.c_str(),
ec.message());
return false;
}
fs::path metadata_path = path / "project";
FILE *metadata = fopen(metadata_path.c_str(), "w");
if(!metadata) {
FxOS_log(ERR, "cannot write `%s': %m", metadata_path.c_str());
return false;
}
serializeMetadata().serialize(metadata);
fclose(metadata);
m_dirty = false;
return true;
}
bool Project::load(std::string const &path0)
{
fs::path path = path0;
BSON metadata
= BSON::loadDocumentFromFile(path / "project", true, true, "Project");
if(metadata.isNull())
return false;
m_path = path;
m_name = metadata["name"].getString();
m_dirty = false;
return true;
}
//=== RecentProjects ===//
RecentProjects::RecentProjectEntry::RecentProjectEntry(BSON const &b)
{
assert(b["*"].getStringReadOnly() == "RecentProjectEntry"s);
name = b["name"].getStringReadOnly();
path = b["path"].getStringReadOnly();
utime = b["utime"].getI64();
}
BSON RecentProjects::RecentProjectEntry::serialize() const
{
return BSON::mkDocument({
{"*", BSON::mkString("RecentProjectEntry")},
{"name", BSON::mkString(name)},
{"path", BSON::mkString(path)},
{"utime", BSON::mkI64(utime)},
});
}
BSON RecentProjects::serialize() const
{
BSON b = BSON::mkArray(m_entries.size());
for(uint i = 0; i < m_entries.size(); i++)
b[i] = m_entries[i].serialize();
return b;
}
void RecentProjects::deserialize(BSON const &b)
{
assert(b.isArray());
for(uint i = 0; i < b.size(); i++)
m_entries.push_back(RecentProjectEntry(b[i]));
}
std::string RecentProjects::pathFromName(std::string const &name) const
{
for(auto &entry: m_entries) {
if(entry.name == name)
return entry.path;
}
return "";
}
std::string RecentProjects::mostRecentPath() const
{
if(!m_entries.size())
return "";
return std::max_element(m_entries.begin(), m_entries.end(),
[](RecentProjectEntry const &e1, RecentProjectEntry const &e2) {
return e1.utime < e2.utime;
})
->path;
}
void RecentProjects::remove(std::string const &path)
{
auto it = m_entries.begin();
while(it != m_entries.end()) {
if(it->path == path)
it = m_entries.erase(it);
else
++it;
}
}
void RecentProjects::touch(Project const &p)
{
remove(p.path());
struct RecentProjectEntry entry;
entry.name = p.name();
entry.path = p.path();
entry.utime = time(NULL);
m_entries.insert(m_entries.begin(), entry);
}
void RecentProjects::refresh()
{
auto it = std::remove_if(
m_entries.begin(), m_entries.end(), [](RecentProjectEntry const &e) {
std::error_code rc;
fs::file_status st = fs::status(e.path, rc);
return rc || st.type() != fs::file_type::directory;
});
m_entries.erase(it, m_entries.end());
}
} /* namespace FxOS */