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:
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);
}