reapack

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

commit 73009429aa7e4c4496d90678f021f5c1744d84de
parent 821f28a96a4cb7060341cdbc34aea4b62d1f5663
Author: cfillion <cfillion@users.noreply.github.com>
Date:   Fri, 28 Oct 2016 04:11:30 -0400

implement per-repository override for the "Install new packages" setting

Diffstat:
Msrc/manager.cpp | 93+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/manager.hpp | 6++++++
Msrc/remote.cpp | 23+++++++++++++++++++----
Msrc/remote.hpp | 10+++++++++-
Msrc/transaction.cpp | 2++
Mtest/remote.cpp | 37+++++++++++++++++++++++++++++--------
6 files changed, 158 insertions(+), 13 deletions(-)

diff --git a/src/manager.cpp b/src/manager.cpp @@ -31,6 +31,7 @@ using namespace std; enum { ACTION_ENABLE = 80, ACTION_DISABLE, ACTION_UNINSTALL, ACTION_ABOUT, ACTION_REFRESH, ACTION_COPYURL, ACTION_SELECT, ACTION_UNSELECT, + ACTION_AUTOINSTALL_GLOBAL, ACTION_AUTOINSTALL_OFF, ACTION_AUTOINSTALL_ON, ACTION_AUTOINSTALL, ACTION_BLEEDINGEDGE, ACTION_PROMPTOBSOLETE, ACTION_NETCONFIG, ACTION_RESETCONFIG }; @@ -92,6 +93,15 @@ void Manager::onCommand(const int id, int) case ACTION_REFRESH: refreshIndex(); break; + case ACTION_AUTOINSTALL_GLOBAL: + setRemoteAutoInstall(boost::logic::indeterminate); + break; + case ACTION_AUTOINSTALL_OFF: + setRemoteAutoInstall(false); + break; + case ACTION_AUTOINSTALL_ON: + setRemoteAutoInstall(true); + break; case ACTION_COPYURL: copyUrl(); break; @@ -166,6 +176,15 @@ bool Manager::fillContextMenu(Menu &menu, const int index) const menu.addSeparator(); menu.addAction(AUTO_STR("&Refresh"), ACTION_REFRESH); + + Menu autoInstallMenu = menu.addMenu("&Install new packages"); + const UINT autoInstallGlobal = + autoInstallMenu.addAction("Use &global setting", ACTION_AUTOINSTALL_GLOBAL); + const UINT autoInstallOff = + autoInstallMenu.addAction("Manually", ACTION_AUTOINSTALL_OFF); + const UINT autoInstallOn = + autoInstallMenu.addAction("When synchronizing", ACTION_AUTOINSTALL_ON); + menu.addAction(AUTO_STR("&Copy URL"), ACTION_COPYURL); const UINT uninstallAction = @@ -182,6 +201,9 @@ bool Manager::fillContextMenu(Menu &menu, const int index) const bool allEnabled = true; bool allDisabled = true; bool allProtected = true; + bool allAutoInstallGlobal = true; + bool allAutoInstallOff = true; + bool allAutoInstallOn = true; for(const int i : m_list->selection()) { const Remote &r = getRemote(i); @@ -192,6 +214,19 @@ bool Manager::fillContextMenu(Menu &menu, const int index) const if(!r.isProtected()) allProtected = false; + + const tribool &autoInstall = remoteAutoInstall(r); + if(boost::logic::indeterminate(autoInstall)) { + allAutoInstallOff = false; + allAutoInstallOn = false; + } + else { + allAutoInstallGlobal = false; + if(autoInstall) + allAutoInstallOff = false; + else if(!autoInstall) + allAutoInstallOn = false; + } }; if(allEnabled) @@ -201,6 +236,13 @@ bool Manager::fillContextMenu(Menu &menu, const int index) const if(allProtected) menu.disable(uninstallAction); + if(allAutoInstallGlobal) + autoInstallMenu.check(autoInstallGlobal); + else if(allAutoInstallOff) + autoInstallMenu.check(autoInstallOff); + else if(allAutoInstallOn) + autoInstallMenu.check(autoInstallOn); + return true; } @@ -280,6 +322,43 @@ bool Manager::isRemoteEnabled(const Remote &remote) const return it->second; } +void Manager::setRemoteAutoInstall(const tribool &enabled) +{ + using namespace boost::logic; + + for(const int index : m_list->selection()) { + const Remote &remote = getRemote(index); + const bool same = remote.autoInstall() == enabled + || (indeterminate(remote.autoInstall()) && indeterminate(enabled)); + + auto it = m_autoInstallOverrides.find(remote); + + if(it == m_autoInstallOverrides.end()) { + if(same) + continue; + + m_autoInstallOverrides.insert({remote, enabled}); + setChange(1); + } + else if(same) { + m_autoInstallOverrides.erase(it); + setChange(-1); + } + else + it->second = enabled; + } +} + +tribool Manager::remoteAutoInstall(const Remote &remote) const +{ + const auto it = m_autoInstallOverrides.find(remote); + + if(it == m_autoInstallOverrides.end()) + return remote.autoInstall(); + else + return it->second; +} + void Manager::refreshIndex() { if(!m_list->hasSelection()) @@ -467,6 +546,19 @@ bool Manager::apply() } } + for(const auto &pair : m_autoInstallOverrides) { + Remote remote = pair.first; + const tribool &enable = pair.second; + + if(m_uninstall.find(remote) == m_uninstall.end()) { + remote.setAutoInstall(enable); + m_config->remotes.add(remote); + + if(isRemoteEnabled(remote) && enable && !syncAll) + tx->synchronize(remote); + } + } + for(const Remote &remote : m_uninstall) m_reapack->uninstall(remote); @@ -483,6 +575,7 @@ bool Manager::apply() void Manager::reset() { m_enableOverrides.clear(); + m_autoInstallOverrides.clear(); m_uninstall.clear(); m_autoInstall = boost::none; m_bleedingEdge = boost::none; diff --git a/src/manager.hpp b/src/manager.hpp @@ -22,6 +22,7 @@ #include "listview.hpp" +#include <boost/logic/tribool.hpp> #include <boost/optional.hpp> #include <map> #include <set> @@ -31,6 +32,8 @@ class ReaPack; class Remote; struct NetworkOpts; +typedef boost::logic::tribool tribool; + class Manager : public Dialog { public: Manager(ReaPack *); @@ -50,6 +53,8 @@ private: bool fillContextMenu(Menu &, int index) const; void setRemoteEnabled(bool); bool isRemoteEnabled(const Remote &) const; + void setRemoteAutoInstall(const tribool &); + tribool remoteAutoInstall(const Remote &) const; void uninstall(); void toggle(boost::optional<bool> &, bool current); void refreshIndex(); @@ -74,6 +79,7 @@ private: std::map<Remote, bool> m_enableOverrides; std::set<Remote> m_uninstall; + std::map<Remote, tribool> m_autoInstallOverrides; boost::optional<bool> m_autoInstall; boost::optional<bool> m_bleedingEdge; boost::optional<bool> m_promptObsolete; diff --git a/src/remote.cpp b/src/remote.cpp @@ -20,6 +20,7 @@ #include "errors.hpp" #include <boost/lexical_cast.hpp> +#include <boost/logic/tribool_io.hpp> #include <regex> #include <sstream> @@ -66,6 +67,9 @@ Remote Remote::fromString(const string &data) string enabled; getline(stream, enabled, DATA_DELIMITER); + string autoInstall; + getline(stream, autoInstall, DATA_DELIMITER); + if(!validateName(name) || !validateUrl(url)) return {}; @@ -76,16 +80,21 @@ Remote Remote::fromString(const string &data) } catch(const boost::bad_lexical_cast &) {} + try { + remote.setAutoInstall(boost::lexical_cast<tribool>(autoInstall)); + } + catch(const boost::bad_lexical_cast &) {} + return remote; } Remote::Remote() - : m_enabled(true), m_protected(false) + : m_enabled(true), m_protected(false), m_autoInstall(boost::logic::indeterminate) { } -Remote::Remote(const string &name, const string &url, const bool enabled) - : m_enabled(enabled), m_protected(false) +Remote::Remote(const string &name, const string &url, const bool enabled, const tribool &autoInstall) + : m_enabled(enabled), m_protected(false), m_autoInstall(autoInstall) { setName(name); setUrl(url); @@ -109,7 +118,13 @@ void Remote::setUrl(const string &url) string Remote::toString() const { - return m_name + DATA_DELIMITER + m_url + DATA_DELIMITER + to_string(m_enabled); + ostringstream out; + out << m_name << DATA_DELIMITER; + out << m_url << DATA_DELIMITER; + out << m_enabled << DATA_DELIMITER; + out << m_autoInstall; + + return out.str(); } void RemoteList::add(const Remote &remote) diff --git a/src/remote.hpp b/src/remote.hpp @@ -18,16 +18,20 @@ #ifndef REAPACK_REMOTE_HPP #define REAPACK_REMOTE_HPP +#include <boost/logic/tribool.hpp> #include <map> #include <string> #include <vector> +typedef boost::logic::tribool tribool; + class Remote { public: static Remote fromString(const std::string &data); Remote(); - Remote(const std::string &name, const std::string &url, bool enabled = true); + Remote(const std::string &name, const std::string &url, bool enabled = true, + const tribool &autoInstall = boost::logic::indeterminate); std::string toString() const; @@ -44,6 +48,9 @@ public: void setEnabled(const bool enabled) { m_enabled = enabled; } bool isEnabled() const { return m_enabled; } + void setAutoInstall(const tribool &autoInstall) { m_autoInstall = autoInstall; } + tribool autoInstall() const { return m_autoInstall; } + void protect() { m_protected = true; } bool isProtected() const { return m_protected; } @@ -55,6 +62,7 @@ private: std::string m_url; bool m_enabled; bool m_protected; + tribool m_autoInstall; }; class RemoteList { diff --git a/src/transaction.cpp b/src/transaction.cpp @@ -57,6 +57,8 @@ void Transaction::synchronize(const Remote &remote, if(forceAutoInstall) opts.autoInstall = *forceAutoInstall; + else if(!boost::logic::indeterminate(remote.autoInstall())) + opts.autoInstall = remote.autoInstall(); fetchIndex(remote, [=] { IndexPtr ri; diff --git a/test/remote.cpp b/test/remote.cpp @@ -192,7 +192,7 @@ TEST_CASE("unserialize remote", M) { SECTION("invalid name") REQUIRE_FALSE(Remote::fromString("name||false")); - SECTION("valid enabled") { + SECTION("enabled") { Remote remote = Remote::fromString("name|url|1"); REQUIRE(remote); @@ -201,24 +201,45 @@ TEST_CASE("unserialize remote", M) { REQUIRE(remote.isEnabled()); } - SECTION("valid disabled") { + SECTION("disabled") { Remote remote = Remote::fromString("name|url|0"); REQUIRE(remote.name() == "name"); REQUIRE(remote.url() == "url"); REQUIRE_FALSE(remote.isEnabled()); } -} -TEST_CASE("serialize remote", M) { - SECTION("enabled") { - REQUIRE(Remote("name", "url", true).toString() == "name|url|1"); + SECTION("missing auto-install") { + Remote remote = Remote::fromString("name|url|1"); + REQUIRE(boost::logic::indeterminate(remote.autoInstall())); } - SECTION("disabled") { - REQUIRE(Remote("name", "url", false).toString() == "name|url|0"); + SECTION("indeterminate auto-install") { + Remote remote = Remote::fromString("name|url|1|2"); + REQUIRE(boost::logic::indeterminate(remote.autoInstall())); + } + + SECTION("auto-install enabled") { + Remote remote = Remote::fromString("name|url|1|1"); + REQUIRE(remote.autoInstall()); + } + + SECTION("auto-install enabled") { + Remote remote = Remote::fromString("name|url|1|0"); + REQUIRE(remote.autoInstall() == false); } } +TEST_CASE("serialize remote", M) { + SECTION("default") + REQUIRE(Remote("name", "url").toString() == "name|url|1|2"); + + SECTION("enabled") + REQUIRE(Remote("name", "url", true, true).toString() == "name|url|1|1"); + + SECTION("disabled") + REQUIRE(Remote("name", "url", false, false).toString() == "name|url|0|0"); +} + TEST_CASE("get enabled remotes", M) { RemoteList list; list.add({"hello", "url1", true});