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:
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) {