reapack

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

commit 65f18732effc3eef62c8d1014d9a6d6febd839f9
parent fb83614cfebb6a69cb63684c25f114e3ea928659
Author: cfillion <cfillion@users.noreply.github.com>
Date:   Sat, 26 Feb 2022 14:19:26 -0500

add a per-package option to enable pre-release updates [#46]

Closes #46

Diffstat:
Msrc/api_package.cpp | 8++++----
Msrc/archive.cpp | 6+++---
Msrc/archive_tasks.cpp | 2+-
Msrc/browser.cpp | 37+++++++++++++++++++++----------------
Msrc/browser.hpp | 3++-
Msrc/browser_entry.cpp | 31+++++++++++++++++++++++--------
Msrc/browser_entry.hpp | 4++--
Msrc/install.cpp | 8++++----
Msrc/registry.cpp | 25++++++++++++++-----------
Msrc/registry.hpp | 12+++++++++---
Msrc/synchronize.cpp | 8+++++---
Msrc/task.cpp | 8++++----
Msrc/task.hpp | 10+++++-----
Msrc/transaction.cpp | 12++++++------
Msrc/transaction.hpp | 6+++---
Mtest/registry.cpp | 14+++++++-------
16 files changed, 113 insertions(+), 81 deletions(-)

diff --git a/src/api_package.cpp b/src/api_package.cpp @@ -108,8 +108,8 @@ DEFINE_API(bool, GetEntryInfo, ((PackageEntry*, entry)) ((char*, pkgOut))((int, pkgOut_sz))((char*, descOut))((int, descOut_sz)) ((int*, typeOut))((char*, verOut))((int, verOut_sz)) ((char*, authorOut))((int, authorOut_sz)) - ((bool*, pinnedOut))((int*, fileCountOut)), -R"(Get the repository name, category, package name, package description, package type, the currently installed version, author name, pinned status and how many files are owned by the given package entry. + ((int*, flagsOut))((int*, fileCountOut)), +R"(Get the repository name, category, package name, package description, package type, the currently installed version, author name, flags (&1=Pinned, &2=BleedingEdge) and how many files are owned by the given package entry. type: 1=script, 2=extension, 3=effect, 4=data, 5=theme, 6=langpack, 7=webinterface)", { @@ -132,8 +132,8 @@ type: 1=script, 2=extension, 3=effect, 4=data, 5=theme, 6=langpack, 7=webinterfa snprintf(verOut, verOut_sz, "%s", regEntry.version.toString().c_str()); if(authorOut) snprintf(authorOut, authorOut_sz, "%s", regEntry.author.c_str()); - if(pinnedOut) - *pinnedOut = regEntry.pinned; + if(flagsOut) + *flagsOut = regEntry.flags; if(fileCountOut) *fileCountOut = static_cast<int>(entry->files.size()); diff --git a/src/archive.cpp b/src/archive.cpp @@ -141,12 +141,12 @@ void ImportArchive::importPackage(const std::string &data) return; std::string categoryName, packageName, versionName; - bool pinned; + int flags; std::istringstream stream(data); stream >> quoted(categoryName) >> quoted(packageName) >> quoted(versionName) - >> pinned; + >> flags; const Package *pkg = m_lastIndex->find(categoryName, packageName); const Version *ver = pkg ? pkg->findVersion(versionName) : nullptr; @@ -158,7 +158,7 @@ void ImportArchive::importPackage(const std::string &data) packageName.c_str(), versionName.c_str())); } - m_tx->install(ver, pinned, m_reader); + m_tx->install(ver, flags, m_reader); } ArchiveReader::ArchiveReader(const Path &path) diff --git a/src/archive_tasks.cpp b/src/archive_tasks.cpp @@ -68,7 +68,7 @@ bool ExportTask::start() << quoted(entry.category) << '\x20' << quoted(entry.package) << '\x20' << quoted(entry.version.toString()) << '\x20' - << entry.pinned << '\n' + << entry.flags << '\n' ; for(const Registry::File &file : tx()->registry()->getFiles(entry)) diff --git a/src/browser.cpp b/src/browser.cpp @@ -153,7 +153,12 @@ void Browser::onCommand(const int id, const int event) selectionDo(std::bind(&Browser::uninstall, this, _1, false)); break; case ACTION_PIN: - currentDo(std::bind(&Browser::togglePin, this, _1)); + currentDo(std::bind(&Browser::toggleFlag, this, + _1, Registry::Entry::PinnedFlag)); + break; + case ACTION_BLEEDINGEDGE: + currentDo(std::bind(&Browser::toggleFlag, this, + _1, Registry::Entry::BleedingEdgeFlag)); break; case ACTION_ABOUT_PKG: aboutPackage(m_currentIndex); @@ -528,8 +533,8 @@ void Browser::transferActions() entryIt->target = target; } - if(oldEntry->pin) - entryIt->pin = *oldEntry->pin; + if(oldEntry->flags) + entryIt->flags = *oldEntry->flags; m_actions.push_back(&*entryIt); } @@ -705,18 +710,18 @@ void Browser::uninstall(const int index, const bool toggle) toggleTarget(index, nullptr); } -void Browser::togglePin(const int index) +void Browser::toggleFlag(const int index, const int mask) { Entry *entry = getEntry(index); - if(!entry || !entry->test(Entry::CanTogglePin)) + if(!entry || !entry->test(Entry::CanToggleFlags)) return; - const bool newVal = !entry->pin.value_or(entry->regEntry.pinned); + const int newVal = mask ^ entry->flags.value_or(entry->regEntry.flags); - if(newVal == entry->regEntry.pinned) - entry->pin = std::nullopt; + if(newVal == entry->regEntry.flags) + entry->flags = std::nullopt; else - entry->pin = newVal; + entry->flags = newVal; updateAction(index); } @@ -754,8 +759,8 @@ void Browser::resetActions(const int index) if(entry->target) entry->target = std::nullopt; - if(entry->pin) - entry->pin = std::nullopt; + if(entry->flags) + entry->flags = std::nullopt; updateAction(index); } @@ -767,7 +772,7 @@ void Browser::updateAction(const int index) return; const auto &it = find(m_actions.begin(), m_actions.end(), entry); - if(!entry->target && (!entry->pin || !entry->test(Entry::CanTogglePin))) { + if(!entry->target && (!entry->flags || !entry->test(Entry::CanToggleFlags))) { if(it != m_actions.end()) m_actions.erase(it); } @@ -863,15 +868,15 @@ bool Browser::apply() const Version *target = *entry->target; if(target) - tx->install(target, entry->pin.value_or(false)); + tx->install(target, entry->flags.value_or(0)); else tx->uninstall(entry->regEntry); entry->target = std::nullopt; } - else if(entry->pin) { - tx->setPinned(entry->regEntry, *entry->pin); - entry->pin = std::nullopt; + else if(entry->flags) { + tx->setFlags(entry->regEntry, *entry->flags); + entry->flags = std::nullopt; } } diff --git a/src/browser.hpp b/src/browser.hpp @@ -49,6 +49,7 @@ public: ACTION_UNINSTALL, ACTION_UNINSTALL_ALL, ACTION_PIN, + ACTION_BLEEDINGEDGE, ACTION_ABOUT_PKG, ACTION_ABOUT_REMOTE, ACTION_RESET_ALL, @@ -126,7 +127,7 @@ private: void reinstall(int index, bool toggle); void installVersion(int index, size_t verIndex); void uninstall(int index, bool toggle); - void togglePin(int index); + void toggleFlag(int index, int mask); // these can be called directly because they don't use updateAction() void aboutRemote(int index, bool focus = true); diff --git a/src/browser_entry.cpp b/src/browser_entry.cpp @@ -29,7 +29,8 @@ Browser::Entry::Entry(const Package *pkg, const Registry::Entry &re, const Index : m_flags(0), regEntry(re), package(pkg), index(i), current(nullptr) { const auto &instOpts = g_reapack->config()->install; - latest = pkg->lastVersion(instOpts.bleedingEdge, regEntry.version); + const bool pres = instOpts.bleedingEdge || re.test(Registry::Entry::BleedingEdgeFlag); + latest = pkg->lastVersion(pres, regEntry.version); if(regEntry) { m_flags |= InstalledFlag; @@ -69,13 +70,21 @@ std::string Browser::Entry::displayState() const else state += '\x20'; - if(regEntry.pinned) + if(regEntry.test(Registry::Entry::PinnedFlag)) state += 'p'; + if(regEntry.test(Registry::Entry::BleedingEdgeFlag)) + state += 'b'; if(target) state += *target == nullptr ? 'R' : 'I'; - if(pin && test(CanTogglePin)) - state += 'P'; + + if(test(CanToggleFlags) && flags) { + const int flagsDiff = regEntry.flags ^ *flags; + if(flagsDiff & Registry::Entry::PinnedFlag) + state += 'P'; + if(flagsDiff & Registry::Entry::BleedingEdgeFlag) + state += 'B'; + } return state; } @@ -209,11 +218,17 @@ void Browser::Entry::fillMenu(Menu &menu) const } const UINT pinIndex = menu.addAction("&Pin current version", ACTION_PIN); - if(!test(CanTogglePin)) + if(!test(CanToggleFlags)) menu.disable(pinIndex); - if(pin.value_or(regEntry.pinned)) + if(flags.value_or(regEntry.flags) & Registry::Entry::PinnedFlag) menu.check(pinIndex); + const UINT presIndex = menu.addAction("Enable pre-releases (&bleeding-edge)", ACTION_BLEEDINGEDGE); + if(!test(CanToggleFlags)) + menu.disable(presIndex); + if(flags.value_or(regEntry.flags) & Registry::Entry::BleedingEdgeFlag) + menu.check(presIndex); + const UINT uninstallIndex = menu.addAction("&Uninstall", ACTION_UNINSTALL); if(!test(InstalledFlag) || test(ProtectedFlag)) menu.disable(uninstallIndex); @@ -243,8 +258,8 @@ int Browser::Entry::possibleActions(bool allowToggle) const if(test(InstalledFlag) && !test(ProtectedFlag) && canSetTarget(nullptr)) flags |= CanUninstall; if(target ? *target != nullptr : test(InstalledFlag)) - flags |= CanTogglePin; - if(target || pin) + flags |= CanToggleFlags; + if(target || flags) flags |= CanClearQueued; return flags; diff --git a/src/browser_entry.hpp b/src/browser_entry.hpp @@ -47,14 +47,14 @@ public: CanUninstall = 1<<2, CanClearQueued = 1<<3, - CanTogglePin = 1<<10, + CanToggleFlags = 1<<10, }; Entry(const Package *, const Registry::Entry &, const IndexPtr &); Entry(const Registry::Entry &, const IndexPtr &); std::optional<const Version *> target; - std::optional<bool> pin; + std::optional<int> flags; std::string displayState() const; const std::string &indexName() const; diff --git a/src/install.cpp b/src/install.cpp @@ -25,9 +25,9 @@ #include "reapack.hpp" #include "transaction.hpp" -InstallTask::InstallTask(const Version *ver, const bool pin, +InstallTask::InstallTask(const Version *ver, const int flags, const Registry::Entry &re, const ArchiveReaderPtr &reader, Transaction *tx) - : Task(tx), m_version(ver), m_pin(pin), m_oldEntry(std::move(re)), m_reader(reader), + : Task(tx), m_version(ver), m_flags(flags), m_oldEntry(std::move(re)), m_reader(reader), m_fail(false), m_index(ver->package()->category()->index()->shared_from_this()) { } @@ -123,8 +123,8 @@ void InstallTask::commit() const Registry::Entry newEntry = tx()->registry()->push(m_version); - if(m_pin) - tx()->registry()->setPinned(newEntry, true); + if(m_flags) + tx()->registry()->setFlags(newEntry, m_flags); tx()->registerAll(true, newEntry); } diff --git a/src/registry.cpp b/src/registry.cpp @@ -43,22 +43,22 @@ Registry::Registry(const Path &path) "SET desc = ?, type = ?, version = ?, author = ? WHERE id = ?" ); - m_setPinned = m_db.prepare("UPDATE entries SET pinned = ? WHERE id = ?"); + m_setFlags = m_db.prepare("UPDATE entries SET flags = ? WHERE id = ?"); m_findEntry = m_db.prepare( - "SELECT id, remote, category, package, desc, type, version, author, pinned " + "SELECT id, remote, category, package, desc, type, version, author, flags " "FROM entries WHERE remote = ? AND category = ? AND package = ? LIMIT 1" ); m_allEntries = m_db.prepare( - "SELECT id, remote, category, package, desc, type, version, author, pinned " + "SELECT id, remote, category, package, desc, type, version, author, flags " "FROM entries WHERE remote = ?" ); m_forgetEntry = m_db.prepare("DELETE FROM entries WHERE id = ?"); // file queries m_getOwner = m_db.prepare( - "SELECT e.id, remote, category, package, desc, e.type, version, author, pinned " + "SELECT e.id, remote, category, package, desc, e.type, version, author, flags " "FROM entries e JOIN files f ON f.entry = e.id WHERE f.path = ? LIMIT 1" ); m_getFiles = m_db.prepare( @@ -78,7 +78,7 @@ Registry::Registry(const Path &path) void Registry::migrate() { - const Database::Version version{0, 5}; + const Database::Version version{0, 6}; const Database::Version &current = m_db.version(); if(!current) { @@ -93,7 +93,7 @@ void Registry::migrate() " type INTEGER NOT NULL," " version TEXT NOT NULL," " author TEXT NOT NULL," - " pinned INTEGER DEFAULT 0," + " flags INTEGER DEFAULT 0," " UNIQUE(remote, category, package)" ");" @@ -135,6 +135,9 @@ void Registry::migrate() [[fallthrough]]; case 4: convertImplicitSections(); + [[fallthrough]]; + case 5: + m_db.exec("ALTER TABLE entries RENAME COLUMN pinned TO flags;"); break; } @@ -217,11 +220,11 @@ auto Registry::push(const Version *ver, std::vector<Path> *conflicts) -> Entry } } -void Registry::setPinned(const Entry &entry, const bool pinned) +void Registry::setFlags(const Entry &entry, const int flags) { - m_setPinned->bind(1, pinned); - m_setPinned->bind(2, entry.id); - m_setPinned->exec(); + m_setFlags->bind(1, flags); + m_setFlags->bind(2, entry.id); + m_setFlags->exec(); } auto Registry::getEntry(const Package *pkg) const -> Entry @@ -354,5 +357,5 @@ void Registry::fillEntry(const Statement *stmt, Entry *entry) const entry->type = static_cast<Package::Type>(stmt->intColumn(col++)); entry->version.tryParse(stmt->stringColumn(col++)); entry->author = stmt->stringColumn(col++); - entry->pinned = stmt->boolColumn(col++); + entry->flags = static_cast<int>(stmt->intColumn(col++)); } diff --git a/src/registry.hpp b/src/registry.hpp @@ -29,6 +29,11 @@ class Registry { public: struct Entry { + enum Flag { + PinnedFlag = 1<<0, + BleedingEdgeFlag = 1<<1, + }; + typedef int64_t id_t; id_t id; @@ -39,10 +44,11 @@ public: Package::Type type; VersionName version; std::string author; - bool pinned; + int flags; operator bool() const { return id > 0; } bool operator==(const Entry &o) const { return id == o.id; } + bool test(Flag f) const { return (flags & f) == f; } }; struct File { @@ -61,7 +67,7 @@ public: std::vector<File> getFiles(const Entry &) const; std::vector<File> getMainFiles(const Entry &) const; Entry push(const Version *, std::vector<Path> *conflicts = nullptr); - void setPinned(const Entry &, bool pinned); + void setFlags(const Entry &, int flags); void forget(const Entry &); void savepoint() { m_db.savepoint(); } @@ -76,7 +82,7 @@ private: Database m_db; Statement *m_insertEntry; Statement *m_updateEntry; - Statement *m_setPinned; + Statement *m_setFlags; Statement *m_findEntry; Statement *m_allEntries; Statement *m_forgetEntry; diff --git a/src/synchronize.cpp b/src/synchronize.cpp @@ -69,7 +69,8 @@ void SynchronizeTask::commit() if(m_opts.promptObsolete && !m_remote.isProtected()) { for(const auto &entry : tx()->registry()->getEntries(m_remote.name())) { - if(!entry.pinned && !index->find(entry.category, entry.package)) + if(!entry.test(Registry::Entry::PinnedFlag) && + !index->find(entry.category, entry.package)) tx()->addObsolete(entry); } } @@ -82,7 +83,8 @@ void SynchronizeTask::synchronize(const Package *pkg) if(!entry && !m_opts.autoInstall) return; - const Version *latest = pkg->lastVersion(m_opts.bleedingEdge, entry.version); + const bool pres = m_opts.bleedingEdge || entry.test(Registry::Entry::BleedingEdgeFlag); + const Version *latest = pkg->lastVersion(pres, entry.version); if(!latest) return; @@ -91,7 +93,7 @@ void SynchronizeTask::synchronize(const Package *pkg) if(FS::allExists(latest->files())) return; // latest version is really installed, nothing to do here! } - else if(entry.pinned || latest->name() < entry.version) + else if(entry.test(Registry::Entry::PinnedFlag) || latest->name() < entry.version) return; tx()->install(latest, entry); diff --git a/src/task.cpp b/src/task.cpp @@ -55,13 +55,13 @@ void UninstallTask::commit() tx()->registry()->forget(m_entry); } -PinTask::PinTask(const Registry::Entry &re, const bool pin, Transaction *tx) - : Task(tx), m_entry(std::move(re)), m_pin(pin) +FlagsTask::FlagsTask(const Registry::Entry &re, const int flags, Transaction *tx) + : Task(tx), m_entry(std::move(re)), m_flags(flags) { } -void PinTask::commit() +void FlagsTask::commit() { - tx()->registry()->setPinned(m_entry, m_pin); + tx()->registry()->setFlags(m_entry, m_flags); tx()->receipt()->setPackageChanged(); } diff --git a/src/task.hpp b/src/task.hpp @@ -80,7 +80,7 @@ private: class InstallTask : public Task { public: - InstallTask(const Version *ver, bool pin, const Registry::Entry &, + InstallTask(const Version *ver, int flags, const Registry::Entry &, const ArchiveReaderPtr &, Transaction *); bool start() override; @@ -91,7 +91,7 @@ private: void push(ThreadTask *, const TempPath &); const Version *m_version; - bool m_pin; + int m_flags; Registry::Entry m_oldEntry; ArchiveReaderPtr m_reader; @@ -117,16 +117,16 @@ private: std::set<Path> m_removedFiles; }; -class PinTask : public Task { +class FlagsTask : public Task { public: - PinTask(const Registry::Entry &, bool pin, Transaction *); + FlagsTask(const Registry::Entry &, int flags, Transaction *); protected: void commit() override; private: Registry::Entry m_entry; - bool m_pin; + int m_flags; }; class ExportTask : public Task { diff --git a/src/transaction.cpp b/src/transaction.cpp @@ -100,21 +100,21 @@ IndexPtr Transaction::loadIndex(const Remote &remote) } } -void Transaction::install(const Version *ver, const bool pin, +void Transaction::install(const Version *ver, const int flags, const ArchiveReaderPtr &reader) { - install(ver, m_registry.getEntry(ver->package()), pin, reader); + install(ver, m_registry.getEntry(ver->package()), flags, reader); } void Transaction::install(const Version *ver, const Registry::Entry &oldEntry, - const bool pin, const ArchiveReaderPtr &reader) + const int flags, const ArchiveReaderPtr &reader) { - m_nextQueue.push(std::make_shared<InstallTask>(ver, pin, oldEntry, reader, this)); + m_nextQueue.push(std::make_shared<InstallTask>(ver, flags, oldEntry, reader, this)); } -void Transaction::setPinned(const Registry::Entry &entry, const bool pinned) +void Transaction::setFlags(const Registry::Entry &entry, const int flags) { - m_nextQueue.push(std::make_shared<PinTask>(entry, pinned, this)); + m_nextQueue.push(std::make_shared<FlagsTask>(entry, flags, this)); } void Transaction::uninstall(const Remote &remote) diff --git a/src/transaction.hpp b/src/transaction.hpp @@ -55,10 +55,10 @@ public: std::vector<IndexPtr> getIndexes(const std::vector<Remote> &) const; void synchronize(const Remote &, const std::optional<bool> &forceAutoInstall = std::nullopt); - void install(const Version *, bool pin = false, const ArchiveReaderPtr & = nullptr); + void install(const Version *, int flags = 0, const ArchiveReaderPtr & = nullptr); void install(const Version *, const Registry::Entry &oldEntry, - bool pin = false, const ArchiveReaderPtr & = nullptr); - void setPinned(const Registry::Entry &, bool pinned); + int flags = false, const ArchiveReaderPtr & = nullptr); + void setFlags(const Registry::Entry &, int flags); void uninstall(const Remote &); void uninstall(const Registry::Entry &); void exportArchive(const std::string &path); diff --git a/test/registry.cpp b/test/registry.cpp @@ -185,21 +185,21 @@ TEST_CASE("get main files", M) { REQUIRE(current[0].type == Package::EffectType); } -TEST_CASE("pin registry entry", M) { +TEST_CASE("registry entry flags", M) { MAKE_PACKAGE Registry reg; reg.push(&ver); const Registry::Entry &entry = reg.getEntry(&pkg); - REQUIRE_FALSE(entry.pinned); + REQUIRE(entry.flags == 0); - reg.setPinned(entry, true); - REQUIRE(reg.getEntry(&pkg).pinned); - REQUIRE(reg.getEntries(ri.name())[0].pinned); + reg.setFlags(entry, 2); + REQUIRE(reg.getEntry(&pkg).flags == 2); + REQUIRE(reg.getEntries(ri.name())[0].flags == 2); - reg.setPinned(entry, false); - REQUIRE_FALSE(reg.getEntry(&pkg).pinned); + reg.setFlags(entry, 0); + REQUIRE(reg.getEntry(&pkg).flags == 0); } TEST_CASE("get file owner", M) {