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