reapack

Package manager for REAPER
Log | Files | Refs | Submodules | README | LICENSE

commit bb1b5719c4b386808605ac8821c71c6bf0639619
parent d98e2d672ac5aecffaf8d441df4bb11e68d59e15
Author: cfillion <cfillion@users.noreply.github.com>
Date:   Fri,  2 Jun 2017 02:28:36 -0400

api: implement AboutInstalledPackage function

Diffstat:
Msrc/api.cpp | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
Msrc/api.hpp | 3++-
Msrc/main.cpp | 3++-
Msrc/registry.cpp | 11+++++------
Msrc/registry.hpp | 4++--
Mtest/registry.cpp | 4++--
6 files changed, 84 insertions(+), 33 deletions(-)

diff --git a/src/api.cpp b/src/api.cpp @@ -21,17 +21,21 @@ #include <reaper_plugin_functions.h> +#include "about.hpp" #include "errors.hpp" +#include "index.hpp" #include "reapack.hpp" #include "registry.hpp" #include "remote.hpp" -#include "version.hpp" +#include "transaction.hpp" using namespace API; using namespace std; ReaPack *API::reapack = nullptr; +static set<Registry::Entry *> s_entries; + #define API_PREFIX "ReaPack_" APIDef::APIDef(const APIFunc *func) @@ -80,15 +84,45 @@ void APIDef::unregister(const char *key, void *ptr) "APIdef_" API_PREFIX #name, (void *)name::definition, \ } -DEFINE_API(bool, AboutPackage, ((int, id)), - "Show the about dialog of the given package. Returns true on success.", -{ - return false; +DEFINE_API(bool, AboutInstalledPackage, ((Registry::Entry*, entry)), R"( + Show the about dialog of the given package entry. + The repository index is downloaded asynchronously if the cached copy doesn't exist or is older than one week. +)", { + if(!s_entries.count(entry)) + return false; + + // the one given by the user may be deleted while we download the idnex + const Registry::Entry entryCopy = *entry; + + const Remote &repo = reapack->remote(entry->remote); + if(!repo) + return false; + + Transaction *tx = reapack->setupTransaction(); + if(!tx) + return false; + + const vector<Remote> repos = {repo}; + + tx->fetchIndexes(repos); + tx->onFinish([=] { + const auto &indexes = tx->getIndexes(repos); + if(indexes.empty()) + return; + + const Package *pkg = indexes.front()->find(entryCopy.category, entryCopy.package); + if(pkg) + reapack->about()->setDelegate(make_shared<AboutPackageDelegate>(pkg, entryCopy.version)); + }); + tx->runTasks(); + + return true; }); -DEFINE_API(bool, AboutRepository, ((const char*, repoName)), - "Show the about dialog of the given repository. Returns true on success.", -{ +DEFINE_API(bool, AboutRepository, ((const char*, repoName)), R"( + Show the about dialog of the given repository. + The repository index is downloaded asynchronously if the cached copy doesn't exist or is older than one week. +)", { if(const Remote &repo = reapack->remote(repoName)) { reapack->about(repo); return true; @@ -98,11 +132,9 @@ DEFINE_API(bool, AboutRepository, ((const char*, repoName)), }); DEFINE_API(bool, CompareVersions, ((const char*, ver1))((const char*, ver2)) - ((int*, resultOut))((char*, errorOut))((int, errorOut_sz)), - "Returns 0 if both versions are equal," - " a positive value if ver1 is higher than ver2" - " and a negative value otherwise.", -{ + ((int*, resultOut))((char*, errorOut))((int, errorOut_sz)), R"( + Returns 0 if both versions are equal, a positive value if ver1 is higher than ver2 and a negative value otherwise. +)", { VersionName a, b; string error; @@ -119,9 +151,10 @@ DEFINE_API(bool, CompareVersions, ((const char*, ver1))((const char*, ver2)) return false; }); -DEFINE_API(int, GetOwner, ((const char*, fn))((char*, errorOut))((int, errorOut_sz)), - "Returns ID of the package owning the given file or 0 on error.", -{ +DEFINE_API(Registry::Entry*, GetOwner, ((const char*, fn))((char*, errorOut))((int, errorOut_sz)), R"( + Returns the package entry owning the given file. + Delete the returned object from memory after use with <a href="#ReaPack_FreeEntry">ReaPack_FreeEntry</a>. +)", { Path path(fn); const Path &rp = ReaPack::resourcePath(); @@ -131,18 +164,35 @@ DEFINE_API(int, GetOwner, ((const char*, fn))((char*, errorOut))((int, errorOut_ try { const Registry reg(Path::prefixRoot(Path::REGISTRY)); - const int owner = (int)reg.getOwner(path); + const auto &owner = reg.getOwner(path); - if(!owner && errorOut) - snprintf(errorOut, errorOut_sz, "file is not owned by any package"); + if(owner) { + auto entry = new Registry::Entry(owner); + s_entries.insert(entry); + return entry; + } + else if(errorOut) + snprintf(errorOut, errorOut_sz, "the file is not owned by any package entry"); - return owner; + return nullptr; } catch(const reapack_error &e) { if(errorOut) snprintf(errorOut, errorOut_sz, "%s", e.what()); - return 0; + return nullptr; } }); + +DEFINE_API(bool, FreeEntry, ((Registry::Entry*, entry)), R"( + Free resources allocated for the given package entry. +)", { + if(s_entries.count(entry)) { + s_entries.erase(entry); + delete entry; + return true; + } + + return false; +}); diff --git a/src/api.hpp b/src/api.hpp @@ -46,9 +46,10 @@ private: namespace API { extern ReaPack *reapack; - extern APIFunc AboutPackage; + extern APIFunc AboutInstalledPackage; extern APIFunc AboutRepository; extern APIFunc CompareVersions; + extern APIFunc FreeEntry; extern APIFunc GetOwner; }; diff --git a/src/main.cpp b/src/main.cpp @@ -160,9 +160,10 @@ static void setupActions() static void setupAPI() { - reapack->setupAPI(&API::AboutPackage); + reapack->setupAPI(&API::AboutInstalledPackage); reapack->setupAPI(&API::AboutRepository); reapack->setupAPI(&API::CompareVersions); + reapack->setupAPI(&API::FreeEntry); reapack->setupAPI(&API::GetOwner); } diff --git a/src/registry.cpp b/src/registry.cpp @@ -58,7 +58,8 @@ Registry::Registry(const Path &path) // file queries m_getOwner = m_db.prepare( - "SELECT entry FROM files WHERE path = ? LIMIT 1" + "SELECT e.id, remote, category, package, desc, e.type, version, author, pinned " + "FROM entries e JOIN files f ON f.entry = e.id WHERE f.path = ? LIMIT 1" ); m_getFiles = m_db.prepare( "SELECT path, main, type FROM files WHERE entry = ? ORDER BY path" @@ -295,20 +296,18 @@ auto Registry::getMainFiles(const Entry &entry) const -> vector<File> return mainFiles; } -auto Registry::getOwner(const Path &path) const -> Entry::id_t +auto Registry::getOwner(const Path &path) const -> Entry { Entry entry{}; m_getOwner->bind(1, path.join('/')); - Entry::id_t id = 0; - m_getOwner->exec([&] { - id = m_getOwner->intColumn(0); + fillEntry(m_getOwner, &entry); return false; }); - return id; + return entry; } void Registry::forget(const Entry &entry) diff --git a/src/registry.hpp b/src/registry.hpp @@ -56,10 +56,10 @@ public: Registry(const Path &path = {}); Entry getEntry(const Package *) const; + Entry getOwner(const Path &) const; std::vector<Entry> getEntries(const std::string &) const; std::vector<File> getFiles(const Entry &) const; std::vector<File> getMainFiles(const Entry &) const; - Entry::id_t getOwner(const Path &) const; Entry push(const Version *, std::vector<Path> *conflicts = nullptr); void setPinned(const Entry &, bool pinned); void forget(const Entry &); @@ -80,8 +80,8 @@ private: Statement *m_findEntry; Statement *m_allEntries; Statement *m_forgetEntry; - Statement *m_getOwner; + Statement *m_getFiles; Statement *m_insertFile; Statement *m_clearFiles; diff --git a/test/registry.cpp b/test/registry.cpp @@ -210,8 +210,8 @@ TEST_CASE("get file owner", M) { MAKE_PACKAGE Registry reg; - REQUIRE(reg.getOwner({}) == 0); + REQUIRE_FALSE(reg.getOwner({})); const Registry::Entry &entry = reg.push(&ver); - REQUIRE(reg.getOwner(src->targetPath()) == entry.id); + REQUIRE(reg.getOwner(src->targetPath()) == entry); }