reapack

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

commit e3cf77c35d18ac90a3d2d4c4d7a1bba6d11ea1a0
parent 687f52f5e78ebe4d32b1fedb0ad8145eae7fd0d9
Author: cfillion <cfillion@users.noreply.github.com>
Date:   Fri,  8 Apr 2016 18:50:22 -0400

don't lose queued actions when reloading the browser

Diffstat:
Msrc/browser.cpp | 67+++++++++++++++++++++++++++++++++++++++++++++++++------------------
Msrc/browser.hpp | 3+++
Msrc/package.cpp | 13++++++++++++-
Msrc/package.hpp | 7++++---
Mtest/package.cpp | 19+++++++++++++++++++
5 files changed, 87 insertions(+), 22 deletions(-)

diff --git a/src/browser.cpp b/src/browser.cpp @@ -338,9 +338,12 @@ void Browser::refresh(const bool stale) m_loading = true; - m_reapack->fetchIndexes(remotes, [=] (const vector<IndexPtr> &indexes) { + m_reapack->fetchIndexes(remotes, [=] (vector<IndexPtr> indexes) { m_loading = false; - m_indexes = indexes; + + // keep the old indexes around a little bit longer for use by populate + indexes.swap(m_indexes); + populate(); if(!m_loaded) { @@ -355,33 +358,56 @@ void Browser::populate() try { Registry reg(Path::prefixRoot(Path::REGISTRY)); - m_currentIndex = -1; - m_actions.clear(); - m_entries.clear(); + std::vector<Entry> entries; for(IndexPtr index : m_indexes) { for(const Package *pkg : index->packages()) - m_entries.push_back(makeEntry(pkg, reg.getEntry(pkg))); + entries.push_back(makeEntry(pkg, reg.getEntry(pkg))); // obsolete packages - for(const Registry::Entry &entry : reg.getEntries(index->name())) { - const Category *cat = index->category(entry.category); + for(const Registry::Entry &regEntry : reg.getEntries(index->name())) { + const Category *cat = index->category(regEntry.category); - if(cat && cat->package(entry.package)) + if(cat && cat->package(regEntry.package)) continue; - m_entries.push_back({InstalledFlag | ObsoleteFlag, entry}); + entries.push_back({InstalledFlag | ObsoleteFlag, regEntry}); + } + } + + auto actionIt = m_actions.begin(); + while(actionIt != m_actions.end()) + { + const Entry &oldEntry = *actionIt->first; + const Version *target = actionIt->second; + + const auto &entryIt = find(entries.begin(), entries.end(), oldEntry); + + actionIt = m_actions.erase(actionIt); + + if(entryIt == entries.end()) + continue; + + if(target) { + const Package *pkg = entryIt->package; + if(!pkg || !(target = pkg->findVersion(*target))) + continue; } + + m_actions[&*entryIt] = target; } + m_currentIndex = -1; + m_entries.swap(entries); + fillList(); } catch(const reapack_error &e) { const auto_string &desc = make_autostring(e.what()); auto_char msg[255] = {}; auto_snprintf(msg, sizeof(msg), - AUTO_STR("ReaPack could not open its package registry.\r\n") - AUTO_STR("Retry later when all installation task are completed.\r\n") + AUTO_STR("ReaPack could not read from its package registry.\r\n") + AUTO_STR("Retry later once all installation task are completed.\r\n") AUTO_STR("\r\nError description: %s"), desc.c_str()); MessageBox(handle(), msg, AUTO_STR("ReaPack"), MB_OK); @@ -402,12 +428,7 @@ auto Browser::makeEntry(const Package *pkg, const Registry::Entry &regEntry) if(regEntry.version < *latest) flags |= OutOfDateFlag; - for(const Version *ver : pkg->versions()) { - if(*ver == regEntry.version) { - current = ver; - break; - } - } + current = pkg->findVersion(regEntry.version); } else flags |= UninstalledFlag; @@ -699,3 +720,13 @@ void Browser::apply() fillList(); // update state column } + +auto Browser::Entry::hash() const -> Hash +{ + if(package) { + return make_tuple(package->category()->index()->name(), + package->category()->name(), package->name()); + } + else + return make_tuple(regEntry.remote, regEntry.category, regEntry.package); +} diff --git a/src/browser.hpp b/src/browser.hpp @@ -56,13 +56,16 @@ private: }; struct Entry { + typedef std::tuple<std::string, std::string, std::string> Hash; int flags; Registry::Entry regEntry; const Package *package; const Version *latest; const Version *current; + Hash hash() const; bool test(Flag f) const { return (flags & f) != 0; } + bool operator==(const Entry &o) const { return hash() == o.hash(); } }; enum Column { diff --git a/src/package.cpp b/src/package.cpp @@ -52,7 +52,7 @@ string Package::displayType(const Type type) return {}; // MSVC is stupid } -Package::Package(const Type type, const string &name, Category *cat) +Package::Package(const Type type, const string &name, const Category *cat) : m_category(cat), m_type(type), m_name(name) { if(m_name.empty()) @@ -104,6 +104,17 @@ const Version *Package::lastVersion() const return *m_versions.rbegin(); } +const Version *Package::findVersion(const Version &ver) const +{ + const auto &it = find_if(m_versions.begin(), m_versions.end(), + [=] (const Version *cur) { return *cur == ver; }); + + if(it == m_versions.end()) + return nullptr; + else + return *it; +} + Path Package::makeTargetPath(const string &file) const { Path path; diff --git a/src/package.hpp b/src/package.hpp @@ -38,10 +38,10 @@ public: static Type typeFor(const char *); static std::string displayType(Type); - Package(const Type, const std::string &name, Category * = nullptr); + Package(const Type, const std::string &name, const Category * = nullptr); ~Package(); - Category *category() const { return m_category; } + const Category *category() const { return m_category; } Type type() const { return m_type; } std::string displayType() const; const std::string &name() const { return m_name; } @@ -51,11 +51,12 @@ public: const VersionSet &versions() const { return m_versions; } const Version *version(size_t index) const; const Version *lastVersion() const; + const Version *findVersion(const Version &) const; Path makeTargetPath(const std::string &file = {}) const; private: - Category *m_category; + const Category *m_category; Type m_type; std::string m_name; diff --git a/test/package.cpp b/test/package.cpp @@ -107,6 +107,25 @@ TEST_CASE("add owned version", M) { } } +TEST_CASE("find matching version", M) { + Index ri("Remote Name"); + Category cat("Category Name", &ri); + + Package pack(Package::ScriptType, "a", &cat); + CHECK(pack.versions().size() == 0); + + Version *ver = new Version("1", &pack); + ver->addSource(new Source(Source::GenericPlatform, {}, "google.com", ver)); + + REQUIRE(pack.findVersion(Version("1")) == nullptr); + REQUIRE(pack.findVersion(Version("2")) == nullptr); + + pack.addVersion(ver); + + REQUIRE(pack.findVersion(Version("1")) == ver); + REQUIRE(pack.findVersion(Version("2")) == nullptr); +} + TEST_CASE("target path for unknown package type", M) { Index ri("name"); Category cat("name", &ri);