reapack

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

commit 081cab31c7012255d11225c73fc695f8cec169d3
parent fdda0ed0fc4ab5b81b3a28f3cfacd0e5f7cc2ec9
Author: cfillion <cfillion@users.noreply.github.com>
Date:   Thu,  3 Dec 2015 22:13:50 -0500

remember installed versions and only update outdated or missing packages

Diffstat:
Msrc/config.cpp | 71++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
Msrc/config.hpp | 9+++++++++
Msrc/package.cpp | 21+++++++++------------
Msrc/package.hpp | 4+---
Msrc/reapack.cpp | 4+++-
Asrc/registry.cpp | 27+++++++++++++++++++++++++++
Asrc/registry.hpp | 25+++++++++++++++++++++++++
Msrc/transaction.cpp | 18++++++++++++------
Msrc/transaction.hpp | 7++++++-
Mtest/package.cpp | 17+++++++++++------
10 files changed, 155 insertions(+), 48 deletions(-)

diff --git a/src/config.cpp b/src/config.cpp @@ -8,21 +8,35 @@ using namespace std; -static const char *REMOTES_GROUP = "remotes"; +static const char *REMOTES_GRP = "remotes"; +static const char *NAME_KEY = "name"; +static const char *URL_KEY = "url"; -static string RemoteNameKey(const int i) +static const char *REGISTRY_GRP = "registry"; +static const char *PACK_KEY = "reapack"; +static const char *VER_KEY = "version"; + +static string ArrayKey(const string &key, const int i) { - static const string key = "name"; return key + to_string(i); } -static string RemoteUrlKey(const int i) +static const int BUFFER_SIZE = 2083; + +string Config::getString(const char *group, const string &key) const { - static const string key = "url"; - return key + to_string(i); + char buffer[BUFFER_SIZE]; + GetPrivateProfileString(group, key.c_str(), "", + buffer, sizeof(buffer), m_path.c_str()); + + return buffer; } -static const int URL_SIZE = 2083; +void Config::setString(const char *group, + const string &key, const string &val) const +{ + WritePrivateProfileString(group, key.c_str(), val.c_str(), m_path.c_str()); +} void Config::fillDefaults() { @@ -41,11 +55,13 @@ void Config::read(const Path &path) } readRemotes(); + readRegistry(); } void Config::write() const { writeRemotes(); + writeRegistry(); } void Config::readRemotes() @@ -53,15 +69,10 @@ void Config::readRemotes() int i = 0; do { - char name[URL_SIZE]; - GetPrivateProfileString(REMOTES_GROUP, RemoteNameKey(i).c_str(), - "", name, sizeof(name), m_path.c_str()); + const string name = getString(REMOTES_GRP, ArrayKey(NAME_KEY, i)); + const string url = getString(REMOTES_GRP, ArrayKey(URL_KEY, i)); - char url[URL_SIZE]; - GetPrivateProfileString(REMOTES_GROUP, RemoteUrlKey(i).c_str(), - "", url, sizeof(url), m_path.c_str()); - - if(!strlen(name) || !strlen(url)) + if(name.empty() || url.empty()) break; m_remotes.push_back({name, url}); @@ -75,10 +86,32 @@ void Config::writeRemotes() const for(int i = 0; i < size; i++) { const Remote &remote = m_remotes[i]; - WritePrivateProfileString(REMOTES_GROUP, RemoteNameKey(i).c_str(), - remote.name().c_str(), m_path.c_str()); + setString(REMOTES_GRP, ArrayKey(NAME_KEY, i), remote.name()); + setString(REMOTES_GRP, ArrayKey(URL_KEY, i), remote.url()); + } +} + +void Config::readRegistry() +{ + int i = 0; + + do { + const string pack = getString(REGISTRY_GRP, ArrayKey(PACK_KEY, i)); + const string ver = getString(REGISTRY_GRP, ArrayKey(VER_KEY, i)); + + if(pack.empty() || ver.empty()) + break; + + m_registry.push(pack, ver); + } while(++i); +} + +void Config::writeRegistry() const +{ + int i = 0; - WritePrivateProfileString(REMOTES_GROUP, RemoteUrlKey(i).c_str(), - remote.url().c_str(), m_path.c_str()); + for(auto it = m_registry.begin(); it != m_registry.end(); it++, i++) { + setString(REGISTRY_GRP, ArrayKey(PACK_KEY, i), it->first); + setString(REGISTRY_GRP, ArrayKey(VER_KEY, i), it->second); } } diff --git a/src/config.hpp b/src/config.hpp @@ -3,6 +3,7 @@ #include <string> +#include "registry.hpp" #include "remote.hpp" class Path; @@ -13,8 +14,12 @@ public: void write() const; const RemoteList &remotes() const { return m_remotes; } + Registry *registry() { return &m_registry; } private: + std::string getString(const char *, const std::string &) const; + void setString(const char *, const std::string &, const std::string &) const; + void fillDefaults(); std::string m_path; @@ -22,6 +27,10 @@ private: void readRemotes(); void writeRemotes() const; RemoteList m_remotes; + + void readRegistry(); + void writeRegistry() const; + Registry m_registry; }; #endif diff --git a/src/package.cpp b/src/package.cpp @@ -47,20 +47,9 @@ Version *Package::lastVersion() const return *prev(m_versions.end()); } -Path Package::targetLocation() const -{ - switch(m_type) { - case ScriptType: - return scriptLocation(); - default: - throw reapack_error("unsupported package type"); - } -} - -Path Package::scriptLocation() const +Path Package::targetPath() const { Path path; - path.append("Scripts"); if(!m_category || !m_category->database()) throw reapack_error("category or database is unset"); @@ -69,5 +58,13 @@ Path Package::scriptLocation() const path.append(m_category->name()); path.append(m_name); + switch(m_type) { + case ScriptType: + path.prepend("Scripts"); + break; + default: + throw reapack_error("unsupported package type"); + } + return path; } diff --git a/src/package.hpp b/src/package.hpp @@ -33,11 +33,9 @@ public: Version *version(const int i) const; Version *lastVersion() const; - Path targetLocation() const; + Path targetPath() const; private: - Path scriptLocation() const; - Category *m_category; Type m_type; diff --git a/src/reapack.cpp b/src/reapack.cpp @@ -62,7 +62,7 @@ void ReaPack::synchronize() return; } - m_transaction = new Transaction(m_resourcePath); + m_transaction = new Transaction(m_config.registry(), m_resourcePath); m_transaction->onReady([=] { // TODO: display the package list with the changelogs @@ -72,6 +72,8 @@ void ReaPack::synchronize() m_transaction->onFinish([=] { delete m_transaction; m_transaction = 0; + + m_config.write(); }); m_transaction->fetch(remotes); diff --git a/src/registry.cpp b/src/registry.cpp @@ -0,0 +1,27 @@ +#include "registry.hpp" + +#include "package.hpp" +#include "path.hpp" + +using namespace std; + +void Registry::push(Package *pkg) +{ + push(pkg->targetPath().join(), pkg->lastVersion()->name()); +} + +void Registry::push(const std::string &key, const std::string &value) +{ + m_map.insert({key, value}); +} + +string Registry::versionOf(Package *pkg) const +{ + const string key = pkg->targetPath().join(); + + const auto it = m_map.find(key); + if(it == m_map.end()) + return std::string(); + + return it->second; +} diff --git a/src/registry.hpp b/src/registry.hpp @@ -0,0 +1,25 @@ +#ifndef REAPACK_REGISTRY_HPP +#define REAPACK_REGISTRY_HPP + +#include <map> +#include <string> + +class Package; + +class Registry { +public: + typedef std::map<std::string, std::string> Map; + + void push(Package *pkg); + void push(const std::string &key, const std::string &value); + + std::string versionOf(Package *pkg) const; + + Map::const_iterator begin() const { return m_map.begin(); } + Map::const_iterator end() const { return m_map.end(); } + +private: + Map m_map; +}; + +#endif diff --git a/src/transaction.cpp b/src/transaction.cpp @@ -8,8 +8,8 @@ using namespace std; -Transaction::Transaction(const Path &root) - : m_root(root) +Transaction::Transaction(Registry *reg, const Path &root) + : m_registry(reg), m_root(root) { m_dbPath = m_root + "ReaPack"; RecursiveCreateDirectory(m_dbPath.join().c_str(), 0); @@ -36,7 +36,7 @@ void Transaction::fetch(const Remote &remote) return; } - const Path path = m_dbPath + (remote.name() + ".xml"); + const Path path = m_dbPath + ("remote_" + remote.name() + ".xml"); ofstream file(path.join()); if(file.bad()) { @@ -65,8 +65,12 @@ void Transaction::prepare() if(!m_queue.empty()) return; - // TODO: make a list of uninstalled or out of date packages only - m_packages = m_databases[0]->packages(); + for(Database *db : m_databases) { + for(Package *pkg : db->packages()) { + if(m_registry->versionOf(pkg) != pkg->lastVersion()->name()) + m_packages.push_back(pkg); + } + } if(m_packages.empty()) { ShowMessageBox("Nothing to do!", "ReaPack", 0); @@ -92,7 +96,7 @@ void Transaction::run() void Transaction::install(Package *pkg) { const string &url = pkg->lastVersion()->source(0)->url(); - const Path path = m_root + pkg->targetLocation(); + const Path path = m_root + pkg->targetPath(); Download *dl = new Download(pkg->name(), url); dl->addCallback([=] { @@ -111,6 +115,8 @@ void Transaction::install(Package *pkg) file << dl->contents(); file.close(); + + m_registry->push(pkg); }); m_queue.push(dl); diff --git a/src/transaction.hpp b/src/transaction.hpp @@ -4,6 +4,7 @@ #include "database.hpp" #include "download.hpp" #include "path.hpp" +#include "registry.hpp" #include "remote.hpp" #include <boost/signals2.hpp> @@ -15,7 +16,7 @@ public: typedef boost::signals2::signal<void ()> Signal; typedef Signal::slot_type Callback; - Transaction(const Path &root); + Transaction(Registry *reg, const Path &root); ~Transaction(); void onReady(const Callback &callback) { m_onReady.connect(callback); } @@ -28,10 +29,14 @@ public: void run(); void finish(); + const PackageList &packages() const { return m_packages; } + private: void install(Package *); void addError(const std::string &, const std::string &); + Registry *m_registry; + DatabaseList m_databases; PackageList m_packages; diff --git a/test/package.cpp b/test/package.cpp @@ -53,11 +53,16 @@ TEST_CASE("drop empty version", M) { REQUIRE(pack.versions().empty()); } -TEST_CASE("unknown target location", M) { +TEST_CASE("unknown target path", M) { + Database db; + Category cat("name"); + cat.setDatabase(&db); + Package pack(Package::UnknownType, "a"); + pack.setCategory(&cat); try { - pack.targetLocation(); + pack.targetPath(); FAIL(); } catch(const reapack_error &e) { @@ -65,7 +70,7 @@ TEST_CASE("unknown target location", M) { } } -TEST_CASE("script target location", M) { +TEST_CASE("script target path", M) { Database db; db.setName("Database Name"); @@ -75,7 +80,7 @@ TEST_CASE("script target location", M) { Package pack(Package::ScriptType, "file.name"); pack.setCategory(&cat); - const Path path = pack.targetLocation(); + const Path path = pack.targetPath(); Path expected; expected.append("Scripts"); @@ -86,11 +91,11 @@ TEST_CASE("script target location", M) { REQUIRE(path == expected); } -TEST_CASE("script target location without category", M) { +TEST_CASE("script target path without category", M) { Package pack(Package::ScriptType, "file.name"); try { - pack.targetLocation(); + pack.targetPath(); FAIL(); } catch(const reapack_error &e) {