reapack

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

commit cbb266b821deaa897dfebe121f6c5d58644b623b
parent e408734c1188ed55da3cd813c584dfdb6dfabb61
Author: cfillion <cfillion@users.noreply.github.com>
Date:   Sat,  2 Jan 2016 20:19:47 -0500

more preparation work for remote configuration

Diffstat:
Msrc/config.cpp | 13++++---------
Msrc/config.hpp | 5++---
Msrc/manager.cpp | 94+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
Msrc/manager.hpp | 17+++++++++--------
Msrc/reapack.cpp | 16+++++++++++-----
Asrc/remote.cpp | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/remote.hpp | 54++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/transaction.cpp | 6+++---
Msrc/transaction.hpp | 2+-
Atest/remote.cpp | 81+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10 files changed, 282 insertions(+), 64 deletions(-)

diff --git a/src/config.cpp b/src/config.cpp @@ -54,7 +54,7 @@ Config::Config() void Config::fillDefaults() { - addRemote({"ReaPack", + m_remotes.add({"ReaPack", "https://github.com/cfillion/reapack/raw/master/index.xml"}); } @@ -78,11 +78,6 @@ void Config::write() writeRegistry(); } -void Config::addRemote(const Remote &remote) -{ - m_remotes[remote.first] = remote.second; -} - void Config::readRemotes() { m_remotesIniSize = getUInt(REMOTES_GRP, SIZE_KEY); @@ -92,7 +87,7 @@ void Config::readRemotes() const string url = getString(REMOTES_GRP, ArrayKey(URL_KEY, i)); if(!name.empty() && !url.empty()) - addRemote({name, url}); + m_remotes.add({name, url}); } } @@ -102,8 +97,8 @@ void Config::writeRemotes() m_remotesIniSize = max(m_remotes.size(), m_remotesIniSize); 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); + setString(REMOTES_GRP, ArrayKey(NAME_KEY, i), it->name()); + setString(REMOTES_GRP, ArrayKey(URL_KEY, i), it->url()); } cleanupArray(REMOTES_GRP, NAME_KEY, i, m_remotesIniSize); diff --git a/src/config.hpp b/src/config.hpp @@ -32,8 +32,7 @@ public: void read(const Path &); void write(); - void addRemote(const Remote &); - const RemoteMap &remotes() const { return m_remotes; } + RemoteList *remotes() { return &m_remotes; } Registry *registry() { return &m_registry; } private: @@ -51,7 +50,7 @@ private: void readRemotes(); void writeRemotes(); - RemoteMap m_remotes; + RemoteList m_remotes; size_t m_remotesIniSize; void readRegistry(); diff --git a/src/manager.cpp b/src/manager.cpp @@ -23,6 +23,10 @@ #include "reapack.hpp" #include "resource.hpp" +static const int ACTION_ENABLE = 300; +static const int ACTION_DISABLE = 301; +static const int ACTION_UNINSTALL = 302; + using namespace std; Manager::Manager(ReaPack *reapack) @@ -46,20 +50,22 @@ void Manager::onInit() void Manager::onCommand(WPARAM wParam, LPARAM) { - const int cmdId = LOWORD(wParam); - switch(LOWORD(wParam)) { case IDC_IMPORT: m_reapack->importRemote(); break; - case Enable: - case Disable: - case Uninstall: - markFor(static_cast<Action>(cmdId)); + case ACTION_ENABLE: + setRemoteEnabled(true); + break; + case ACTION_DISABLE: + setRemoteEnabled(false); + break; + case ACTION_UNINSTALL: break; case IDOK: apply(); case IDCANCEL: + reset(); hide(); break; } @@ -81,22 +87,28 @@ void Manager::onContextMenu(HWND target, const int x, const int y) Menu menu; - menu.addAction(AUTO_STR("Enable"), Enable); + const UINT enableAction = + menu.addAction(AUTO_STR("Enable"), ACTION_ENABLE); const UINT disableAction = - menu.addAction(AUTO_STR("Disable"), Disable); + menu.addAction(AUTO_STR("Disable"), ACTION_DISABLE); menu.addSeparator(); const UINT uninstallAction = - menu.addAction(AUTO_STR("Uninstall"), Uninstall); + menu.addAction(AUTO_STR("Uninstall"), ACTION_UNINSTALL); menu.disable(); - const int index = m_list->currentIndex(); + const Remote remote = currentRemote(); + + if(!remote.isNull()) { + if(isRemoteEnabled(remote)) + menu.enable(disableAction); + else + menu.enable(enableAction); - if(index > -1) { - menu.enable(disableAction); - menu.enable(uninstallAction); + if(!remote.isFrozen()) + menu.enable(uninstallAction); } menu.show(x, y, handle()); @@ -106,42 +118,58 @@ void Manager::refresh() { m_list->clear(); - const RemoteMap remotes = m_reapack->config()->remotes(); - for(auto it = remotes.begin(); it != remotes.end(); it++) - m_list->addRow(makeRow(*it)); + for(const Remote &remote : *m_reapack->config()->remotes()) + m_list->addRow(makeRow(remote)); } -void Manager::markFor(const Action action) +void Manager::setRemoteEnabled(const bool enabled) { - const int index = m_list->currentIndex(); + Remote remote = currentRemote(); - if(index < 0) + if(remote.isNull()) return; - const string remoteName = from_autostring(m_list->getRow(index)[0]); + m_enableOverrides[remote.name()] = enabled; - const RemoteMap &remotes = m_reapack->config()->remotes(); - const auto it = remotes.find(remoteName); + m_list->replaceRow(m_list->currentIndex(), makeRow(remote)); +} - if(it == remotes.end()) - return; +bool Manager::isRemoteEnabled(const Remote &remote) const +{ + const auto it = m_enableOverrides.find(remote.name()); - const Remote remote = {"aaaaaaa", it->second}; + if(it == m_enableOverrides.end()) + return remote.isEnabled(); + else + return it->second; +} - MessageBox(handle(), to_autostring(action).c_str(), - m_list->getRow(index)[0].c_str(), MB_OK); +void Manager::apply() +{ +} - m_list->replaceRow(index, makeRow(remote)); +void Manager::reset() +{ + m_enableOverrides.clear(); } -void Manager::apply() +ListView::Row Manager::makeRow(const Remote &remote) const { + const auto_string name = make_autostring(remote.name()); + const auto_string url = make_autostring(remote.url()); + + return {name, url, isRemoteEnabled(remote) ? + AUTO_STR("Enabled") : AUTO_STR("Disabled")}; } -ListView::Row Manager::makeRow(const Remote &remote) +Remote Manager::currentRemote() const { - const auto_string name = make_autostring(remote.first); - const auto_string url = make_autostring(remote.second); + const int index = m_list->currentIndex(); + + if(index < 0) + return {}; + + const string remoteName = from_autostring(m_list->getRow(index)[0]); - return {name, url, AUTO_STR("Enabled")}; + return m_reapack->config()->remotes()->get(remoteName); } diff --git a/src/manager.hpp b/src/manager.hpp @@ -23,7 +23,8 @@ #include "listview.hpp" #include "remote.hpp" -class Menu; +#include <map> + class ReaPack; class Manager : public Dialog { @@ -40,19 +41,19 @@ protected: void onContextMenu(HWND, int x, int y) override; private: - static ListView::Row makeRow(const Remote &remote); + ListView::Row makeRow(const Remote &remote) const; - enum Action { - Enable = 300, - Disable = 301, - Uninstall = 302, - }; + Remote currentRemote() const; + void setRemoteEnabled(const bool); + bool isRemoteEnabled(const Remote &remote) const; - void markFor(Action action); void apply(); + void reset(); ReaPack *m_reapack; ListView *m_list; + + std::map<std::string, bool> m_enableOverrides; }; #endif diff --git a/src/reapack.cpp b/src/reapack.cpp @@ -93,9 +93,9 @@ bool ReaPack::execActions(const int id, const int) void ReaPack::synchronize() { - RemoteMap remotes = m_config->remotes(); + const RemoteList *remotes = m_config->remotes(); - if(remotes.empty()) { + if(remotes->empty()) { ShowMessageBox("No remote repository configured, nothing to do!", "ReaPack", 0); @@ -141,7 +141,11 @@ void ReaPack::importRemote() return; } - if(m_config->remotes().count({name})) { + RemoteList *remotes = m_config->remotes(); + + Remote remote = remotes->get(name); + + if(!remote.isNull()) { const int button = ShowMessageBox( "This remote is already configured.\r\n" "Do you want to overwrite the current remote?" @@ -151,8 +155,10 @@ void ReaPack::importRemote() return; } - const Remote remote{name, url}; - m_config->addRemote(remote); + remote.setName(name); + remote.setUrl(url); + + remotes->add(remote); m_config->write(); m_manager->refresh(); diff --git a/src/remote.cpp b/src/remote.cpp @@ -0,0 +1,58 @@ +/* ReaPack: Package manager for REAPER + * Copyright (C) 2015-2016 Christian Fillion + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "remote.hpp" + +using namespace std; + +Remote::Remote() + : m_enabled(true), m_frozen(false) +{ +} + +Remote::Remote(const string &name, const string &url, const bool enabled) + : m_name(name), m_url(url), m_enabled(enabled), m_frozen(false) +{ +} + +void RemoteList::add(const Remote &remote) +{ + if(remote.isNull()) + return; + + m_remotes[remote.name()] = remote; +} + +Remote RemoteList::get(const string &name) const +{ + const auto it = m_remotes.find(name); + + if(it == m_remotes.end()) + return {}; + else + return it->second; +} + +bool RemoteList::hasUrl(const string &url) const +{ + for(const Remote &r : m_remotes | boost::adaptors::map_values) { + if(r.url() == url) + return true; + } + + return false; +} diff --git a/src/remote.hpp b/src/remote.hpp @@ -18,10 +18,60 @@ #ifndef REAPACK_REMOTE_HPP #define REAPACK_REMOTE_HPP +#include <boost/optional.hpp> +#include <boost/range/adaptor/map.hpp> #include <map> #include <string> -typedef std::map<std::string, std::string> RemoteMap; -typedef RemoteMap::value_type Remote; +class Remote { +public: + Remote(); + Remote(const std::string &name, const std::string &url, + const bool enabled = true); + + void setName(const std::string &name) { m_name = name; } + const std::string &name() const { return m_name; } + + void setUrl(const std::string &url) { m_url = url; } + const std::string &url() const { return m_url; } + + bool isNull() const { return m_name.empty() || m_url.empty(); } + + void enable() { setEnabled(true); } + void disable() { setEnabled(false); } + void setEnabled(const bool enabled) { m_enabled = enabled; } + bool isEnabled() const { return m_enabled; } + + void freeze() { m_frozen = true; } + bool isFrozen() const { return m_frozen; } + +private: + std::string m_name; + std::string m_url; + bool m_enabled; + bool m_frozen; +}; + +class RemoteList { +private: + std::map<std::string, Remote> m_remotes; + +public: + void add(const Remote &); + + bool empty() const { return m_remotes.empty(); } + size_t size() const { return m_remotes.size(); } + bool hasName(const std::string &name) const + { return m_remotes.count(name) > 0; } + bool hasUrl(const std::string &url) const; + + auto begin() const -> decltype(boost::adaptors::values(m_remotes).begin()) + { return boost::adaptors::values(m_remotes).begin(); } + + auto end() const -> decltype(boost::adaptors::values(m_remotes).end()) + { return boost::adaptors::values(m_remotes).end(); } + + Remote get(const std::string &name) const; +}; #endif diff --git a/src/transaction.cpp b/src/transaction.cpp @@ -44,15 +44,15 @@ Transaction::~Transaction() delete db; } -void Transaction::fetch(const RemoteMap &remotes) +void Transaction::fetch(const RemoteList *remotes) { - for(const Remote &remote : remotes) + for(const Remote &remote : *remotes) fetch(remote); } void Transaction::fetch(const Remote &remote) { - Download *dl = new Download(remote.first, remote.second); + Download *dl = new Download(remote.name(), remote.url()); dl->onFinish(bind(&Transaction::saveDatabase, this, dl)); m_queue.push(dl); diff --git a/src/transaction.hpp b/src/transaction.hpp @@ -50,7 +50,7 @@ public: void onFinish(const Callback &callback) { m_onFinish.connect(callback); } void onDestroy(const Callback &callback) { m_onDestroy.connect(callback); } - void fetch(const RemoteMap &); + void fetch(const RemoteList *); void fetch(const Remote &); void run(); void cancel(); diff --git a/test/remote.cpp b/test/remote.cpp @@ -0,0 +1,81 @@ +#include <catch.hpp> + +#include <remote.hpp> + +using namespace std; + +static const char *M = "[remote]"; + +TEST_CASE("construct remote", M) { + Remote remote{"name", "url", true}; + REQUIRE(remote.name() == "name"); + REQUIRE(remote.url() == "url"); + REQUIRE(remote.isEnabled()); + REQUIRE_FALSE(remote.isFrozen()); +} + +TEST_CASE("null remote", M) { + Remote remote; + REQUIRE(remote.isNull()); + + SECTION("set name") { + remote.setName("test"); + REQUIRE(remote.name() == "test"); + REQUIRE(remote.isNull()); + } + + SECTION("set url") { + remote.setUrl("test"); + REQUIRE(remote.url() == "test"); + REQUIRE(remote.isNull()); + } + + SECTION("set both") { + remote.setName("hello"); + remote.setUrl("world"); + REQUIRE_FALSE(remote.isNull()); + } +} + +TEST_CASE("freeze remote", M) { + Remote remote; + REQUIRE_FALSE(remote.isFrozen()); + + remote.freeze(); + REQUIRE(remote.isFrozen()); +} + +TEST_CASE("add remotes to list", M) { + RemoteList list; + + REQUIRE(list.empty()); + REQUIRE(list.size() == 0); + REQUIRE_FALSE(list.hasName("name")); + REQUIRE_FALSE(list.hasUrl("url")); + + list.add({"name", "url"}); + + REQUIRE_FALSE(list.empty()); + REQUIRE(list.size() == 1); + REQUIRE(list.hasName("name")); + REQUIRE(list.hasUrl("url")); +} + +TEST_CASE("replace remote", M) { + RemoteList list; + + list.add({"name", "url1"}); + list.add({"name", "url2"}); + + REQUIRE(list.size() == 1); + REQUIRE_FALSE(list.hasUrl("url1")); + REQUIRE(list.hasUrl("url2")); +}; + +TEST_CASE("get remote by name", M) { + RemoteList list; + REQUIRE(list.get("hello").isNull()); + + list.add({"hello", "world"}); + REQUIRE_FALSE(list.get("hello").isNull()); +}