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