reapack

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

commit 18f546204686f3e5c9f1af76eac6bcd802971042
parent 829875e621575e493b0a46ff3166221d7182bbd1
Author: cfillion <cfillion@users.noreply.github.com>
Date:   Sat,  5 Dec 2015 00:26:03 -0500

implement the "import remote repository" feature

Diffstat:
Msrc/config.cpp | 21++++++++++++---------
Msrc/config.hpp | 5+++--
Msrc/main.cpp | 5++++-
Msrc/reapack.cpp | 97++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
Msrc/reapack.hpp | 12++++++++----
Msrc/remote.hpp | 20+++-----------------
Msrc/transaction.cpp | 12++++++------
Msrc/transaction.hpp | 4+---
8 files changed, 116 insertions(+), 60 deletions(-)

diff --git a/src/config.cpp b/src/config.cpp @@ -18,7 +18,7 @@ static const char *VER_KEY = "version"; static string ArrayKey(const string &key, const size_t i) { - return key + to_string(i); + return to_string(i) + key; } static const int BUFFER_SIZE = 2083; @@ -40,7 +40,7 @@ void Config::setString(const char *group, void Config::fillDefaults() { - m_remotes.push_back({"ReaScripts", + addRemote({"ReaScripts", "https://github.com/ReaTeam/ReaScripts/raw/master/index.xml"}); } @@ -64,6 +64,11 @@ void Config::write() const writeRegistry(); } +void Config::addRemote(Remote remote) +{ + m_remotes[remote.first] = remote.second; +} + void Config::readRemotes() { size_t i = 0; @@ -75,19 +80,17 @@ void Config::readRemotes() if(name.empty() || url.empty()) break; - m_remotes.push_back({name, url}); + addRemote({name, url}); } while(++i); } void Config::writeRemotes() const { - const size_t size = m_remotes.size(); - - for(size_t i = 0; i < size; i++) { - const Remote &remote = m_remotes[i]; + size_t i = 0; - setString(REMOTES_GRP, ArrayKey(NAME_KEY, i), remote.name()); - setString(REMOTES_GRP, ArrayKey(URL_KEY, i), remote.url()); + for(auto it = m_remotes.begin(); it != m_remotes.end(); it++, i++) { + setString(REMOTES_GRP, ArrayKey(NAME_KEY, i), it->first); + setString(REMOTES_GRP, ArrayKey(URL_KEY, i), it->second); } } diff --git a/src/config.hpp b/src/config.hpp @@ -13,7 +13,8 @@ public: void read(const Path &); void write() const; - const RemoteList &remotes() const { return m_remotes; } + void addRemote(Remote); + const RemoteMap &remotes() const { return m_remotes; } Registry *registry() { return &m_registry; } private: @@ -26,7 +27,7 @@ private: void readRemotes(); void writeRemotes() const; - RemoteList m_remotes; + RemoteMap m_remotes; void readRegistry(); void writeRegistry() const; diff --git a/src/main.cpp b/src/main.cpp @@ -42,7 +42,10 @@ extern "C" REAPER_PLUGIN_DLL_EXPORT int REAPER_PLUGIN_ENTRYPOINT( reapack.init(instance, rec); reapack.setupAction("REAPACK_SYNC", "ReaPack: Synchronize Packages", - &reapack.action, std::bind(&ReaPack::synchronize, reapack)); + &reapack.syncAction, std::bind(&ReaPack::synchronize, reapack)); + + reapack.setupAction("REAPACK_IMPORT", + std::bind(&ReaPack::importRemote, reapack)); rec->Register("hookcommand", (void *)commandHook); rec->Register("hookcustommenu", (void *)menuHook); diff --git a/src/reapack.cpp b/src/reapack.cpp @@ -4,6 +4,8 @@ #include <reaper_plugin_functions.h> +#include <fstream> + using namespace std; ReaPack::ReaPack() @@ -18,24 +20,39 @@ void ReaPack::init(REAPER_PLUGIN_HINSTANCE instance, reaper_plugin_info_t *rec) m_mainHandle = GetMainHwnd(); m_resourcePath.append(GetResourcePath()); - m_config.read(m_resourcePath + "reapack.ini"); + // wtf? If m_config is a member object different instances will be used + // in importRemote(), synchronize() and cleanup() + m_config = new Config; + m_config->read(m_resourcePath + "reapack.ini"); } void ReaPack::cleanup() { // for some reasons ~ReaPack() is called many times during startup // and two times during shutdown on osx... cleanup() is called only once - m_config.write(); + m_config->write(); + delete m_config; +} + +int ReaPack::setupAction(const char *name, const ActionCallback &callback) +{ + const int id = m_rec->Register("command_id", (void *)name); + m_actions[id] = callback; + + return id; } -void ReaPack::setupAction(const char *name, const char *desc, - gaccel_register_t *action, ActionCallback callback) +int ReaPack::setupAction(const char *name, const char *desc, + gaccel_register_t *action, const ActionCallback &callback) { + const int id = setupAction(name, callback); + action->desc = desc; - action->accel.cmd = m_rec->Register("command_id", (void *)name); + action->accel.cmd = id; m_rec->Register("gaccel", action); - m_actions[action->accel.cmd] = callback; + + return id; } bool ReaPack::execActions(const int id, const int) @@ -48,12 +65,34 @@ bool ReaPack::execActions(const int id, const int) return true; } +Transaction *ReaPack::createTransaction() +{ + if(m_transaction) + return 0; + + m_transaction = new Transaction(m_config->registry(), m_resourcePath); + + m_transaction->onReady([=] { + // TODO: display the package list with the changelogs + m_transaction->run(); + }); + + m_transaction->onFinish([=] { + delete m_transaction; + m_transaction = 0; + + m_config->write(); + }); + + return m_transaction; +} + void ReaPack::synchronize() { if(m_transaction) return; - RemoteList remotes = m_config.remotes(); + RemoteMap remotes = m_config->remotes(); if(remotes.empty()) { ShowMessageBox("No remote repository configured, nothing to do!", @@ -62,19 +101,41 @@ void ReaPack::synchronize() return; } - m_transaction = new Transaction(m_config.registry(), m_resourcePath); + m_transaction->fetch(remotes); +} - m_transaction->onReady([=] { - // TODO: display the package list with the changelogs - m_transaction->run(); - }); +void ReaPack::importRemote() +{ + char path[4096]; - m_transaction->onFinish([=] { - delete m_transaction; - m_transaction = 0; + const char *title = "ReaPack: Import remote repository"; + if(!GetUserFileNameForRead(path, title, "ReaPackRemote")) + return; - m_config.write(); - }); + ifstream file(path); + if(!file.good()) { + ShowMessageBox(strerror(errno), title, 0); + return; + } - m_transaction->fetch(remotes); + string name; + file >> name; + + string url; + file >> url; + + file.close(); + + if(m_config->remotes().count({name})) { + ShowMessageBox("This remote is already configured.", title, 0); + return; + } + + const Remote remote{name, url}; + m_config->addRemote(remote); + m_config->write(); + + Transaction *t = createTransaction(); + if(t) + t->fetch(remote); } diff --git a/src/reapack.hpp b/src/reapack.hpp @@ -15,23 +15,27 @@ class Transaction; class ReaPack { public: - gaccel_register_t action; + gaccel_register_t syncAction; ReaPack(); void init(REAPER_PLUGIN_HINSTANCE, reaper_plugin_info_t *); void cleanup(); - void setupAction(const char *name, const char *desc, - gaccel_register_t *action, ActionCallback callback); + int setupAction(const char *name, const ActionCallback &); + int setupAction(const char *name, const char *desc, + gaccel_register_t *action, const ActionCallback &); bool execActions(const int id, const int); void synchronize(); + void importRemote(); private: + Transaction *createTransaction(); + std::map<int, ActionCallback> m_actions; - Config m_config; + Config *m_config; Transaction *m_transaction; REAPER_PLUGIN_HINSTANCE m_instance; diff --git a/src/remote.hpp b/src/remote.hpp @@ -1,24 +1,10 @@ #ifndef REAPACK_REMOTE_HPP #define REAPACK_REMOTE_HPP +#include <map> #include <string> -#include <vector> -class Remote; -typedef std::vector<Remote> RemoteList; - -class Remote { -public: - Remote(const std::string &name, const std::string &url) - : m_name(name), m_url(url) - {} - - const std::string &name() const { return m_name; } - const std::string &url() const { return m_url; } - -private: - std::string m_name; - std::string m_url; -}; +typedef std::map<std::string, std::string> RemoteMap; +typedef RemoteMap::value_type Remote; #endif diff --git a/src/transaction.cpp b/src/transaction.cpp @@ -21,7 +21,7 @@ Transaction::~Transaction() delete db; } -void Transaction::fetch(const RemoteList &remotes) +void Transaction::fetch(const RemoteMap &remotes) { for(const Remote &remote : remotes) fetch(remote); @@ -29,18 +29,18 @@ void Transaction::fetch(const RemoteList &remotes) void Transaction::fetch(const Remote &remote) { - Download *dl = new Download(remote.name(), remote.url()); + Download *dl = new Download(remote.first, remote.second); dl->addCallback([=]() { if(dl->status() != 200) { - addError(dl->contents(), remote.name()); + addError(dl->contents(), dl->name()); return; } - const Path path = m_dbPath + ("remote_" + remote.name() + ".xml"); + const Path path = m_dbPath + ("remote_" + dl->name() + ".xml"); ofstream file(path.join()); if(file.bad()) { - addError(strerror(errno), remote.name()); + addError(strerror(errno), dl->name()); return; } @@ -48,7 +48,7 @@ void Transaction::fetch(const Remote &remote) file.close(); Database *db = Database::load(path.join().c_str()); - db->setName(remote.name()); + db->setName(dl->name()); m_databases.push_back(db); }); diff --git a/src/transaction.hpp b/src/transaction.hpp @@ -9,8 +9,6 @@ #include <boost/signals2.hpp> -class Remote; - class Transaction { public: typedef boost::signals2::signal<void ()> Signal; @@ -22,7 +20,7 @@ public: void onReady(const Callback &callback) { m_onReady.connect(callback); } void onFinish(const Callback &callback) { m_onFinish.connect(callback); } - void fetch(const RemoteList &); + void fetch(const RemoteMap &); void fetch(const Remote &); void prepare();