Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Export and import text index #69

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 23 additions & 8 deletions src/archive_tasks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "transaction.hpp"

#include <iomanip>
#include <fstream>
#include <sstream>

static const Path ARCHIVE_TOC("toc");
Expand Down Expand Up @@ -54,16 +55,11 @@ bool ExportTask::start()

std::vector<FileCompressor *> jobs;

for(const Remote &remote : g_reapack->config()->remotes.getEnabled()) {
bool addedRemote = false;
for(const Remote &remote : g_reapack->config()->remotes) {
toc << "REPO " << remote.toString() << '\n';
jobs.push_back(new FileCompressor(Index::pathFor(remote.name()), writer));

for(const Registry::Entry &entry : tx()->registry()->getEntries(remote.name())) {
if(!addedRemote) {
toc << "REPO " << remote.toString() << '\n';
jobs.push_back(new FileCompressor(Index::pathFor(remote.name()), writer));
addedRemote = true;
}

toc << "PACK "
<< quoted(entry.category) << '\x20'
<< quoted(entry.package) << '\x20'
Expand Down Expand Up @@ -107,3 +103,22 @@ void ExportTask::rollback()
{
FS::remove(m_path.temp());
}

void ExportIndexTask::commit()
{
std::ofstream index{m_path, std::ios::out | std::ios::trunc};
if (!index.good())
return tx()->receipt()->addError({"Error opening index file", m_path});

for(const Remote &remote : g_reapack->config()->remotes) {
index << "REPO " << remote.toString() << '\n';

for(const Registry::Entry &entry : tx()->registry()->getEntries(remote.name())) {
index << "PACK "
<< quoted(entry.category) << '\x20'
<< quoted(entry.package) << '\x20'
<< quoted(entry.version.toString()) << '\x20'
<< entry.flags << '\n';
}
}
}
34 changes: 34 additions & 0 deletions src/install.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,37 @@ void InstallTask::rollback()

m_fail = true;
}

InstallFromIndexTask::InstallFromIndexTask(PackageFromIndex&& pkg_, Transaction *tx)
: Task(tx), pkg(std::move(pkg_)) { }

bool InstallFromIndexTask::start()
{
const IndexPtr index = tx()->loadIndex({pkg.remote});
if(!index) return false;

const ErrorInfo err = {
String::format("%s/%s/%s v%s",
pkg.remote.name().c_str(), pkg.category.c_str(), pkg.name.c_str(), pkg.version.c_str()),
"Package cannot be found or is incompatible with your operating system"};

const Package *const pkg_handle = [&]() -> const Package * {
for(const Package *other : index->packages())
if(other->name() == pkg.name && other->category()->name() == pkg.category)
return other;
return nullptr;
}();

if(!pkg_handle) {
tx()->receipt()->addError(err);
return false;
} else if(version = pkg_handle->findVersion({pkg.version}); !version) {
tx()->receipt()->addError(err);
return false;
}
return true;
}

void InstallFromIndexTask::commit() {
tx()->install(version, pkg.flags);
}
83 changes: 80 additions & 3 deletions src/manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,23 @@
#include "transaction.hpp"
#include "win32.hpp"

#include <fstream>
#include <iomanip>

static const Win32::char_type *ARCHIVE_FILTER =
L("ReaPack Offline Archive (*.ReaPackArchive)\0*.ReaPackArchive\0");
static const Win32::char_type *ARCHIVE_EXT = L("ReaPackArchive");
static const Win32::char_type *INDEX_FILTER =
L("ReaPack Index (*.txt)\0*.txt\0");
static const Win32::char_type *INDEX_EXT = L("txt");

enum {
ACTION_UNINSTALL = 80, 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_SYNONYMS, ACTION_NETCONFIG,
ACTION_RESETCONFIG, ACTION_IMPORT_REPO, ACTION_IMPORT_ARCHIVE,
ACTION_EXPORT_ARCHIVE,
ACTION_EXPORT_ARCHIVE, ACTION_IMPORT_INDEX, ACTION_EXPORT_INDEX
};

enum { TIMER_ABOUT = 1, };
Expand Down Expand Up @@ -150,6 +156,13 @@ void Manager::onCommand(const int id, int)
case ACTION_EXPORT_ARCHIVE:
exportArchive();
break;
case ACTION_IMPORT_INDEX:
importIndex();
refresh();
break;
case ACTION_EXPORT_INDEX:
exportIndex();
break;
case ACTION_AUTOINSTALL:
toggle(m_autoInstall, g_reapack->config()->install.autoInstall);
break;
Expand Down Expand Up @@ -470,6 +483,9 @@ void Manager::importExport()
Menu menu;
menu.addAction("Import &repositories...", ACTION_IMPORT_REPO);
menu.addSeparator();
menu.addAction("Import index", ACTION_IMPORT_INDEX);
menu.addAction("Export index", ACTION_EXPORT_INDEX);
menu.addSeparator();
menu.addAction("Import offline archive...", ACTION_IMPORT_ARCHIVE);
menu.addAction("&Export offline archive...", ACTION_EXPORT_ARCHIVE);

Expand All @@ -492,7 +508,7 @@ void Manager::importArchive()
{
const char *title = "Import offline archive";

const std::string &path = FileDialog::getOpenFileName(handle(), instance(),
const std::string path = FileDialog::getOpenFileName(handle(), instance(),
title, Path::DATA.prependRoot(), ARCHIVE_FILTER, ARCHIVE_EXT);

if(path.empty())
Expand All @@ -510,7 +526,7 @@ void Manager::importArchive()

void Manager::exportArchive()
{
const std::string &path = FileDialog::getSaveFileName(handle(), instance(),
const std::string path = FileDialog::getSaveFileName(handle(), instance(),
"Export offline archive", Path::DATA.prependRoot(), ARCHIVE_FILTER, ARCHIVE_EXT);

if(!path.empty()) {
Expand All @@ -521,6 +537,67 @@ void Manager::exportArchive()
}
}

void Manager::importIndex()
{
Transaction * const tx = g_reapack->setupTransaction();
if(!tx) return;
Receipt * const receipt = tx->receipt();

const std::string path = FileDialog::getOpenFileName(handle(), instance(),
"Import index", Path::root(), INDEX_FILTER, INDEX_EXT);

std::ifstream index{path};
if(!index.good()) {
receipt->addError({"Error opening index file", path});
tx->runTasks();
return;
}

Remote remote;
std::string line;
std::vector<PackageFromIndex> packages;

while(std::getline(index, line)) {
switch(line[0]) {
case 'R':
if(remote = Remote::fromString(line.substr(5)); remote.isNull())
receipt->addError({"Error adding remote", remote.toString()});
else {
g_reapack->addSetRemote(remote);
// strange but above function doesn't fetch index files despite issuing same SynchronizeTask
tx->fetchIndexes({remote}, true);
}
break;
case 'P': {
auto& ref = packages.emplace_back(PackageFromIndex{remote});
std::istringstream{line.substr(5)}
>> quoted(ref.category) >> quoted(ref.name) >> quoted(ref.version)
>> ref.flags;
break;
}
default:
receipt->addError({line, "Invalid index entry"});
}
}

g_reapack->commitConfig(true); // runs tx

for(PackageFromIndex& pkg : packages)
tx->installFromIndex(std::move(pkg));
tx->runTasks();
}

void Manager::exportIndex()
{
const std::string path = FileDialog::getSaveFileName(handle(), instance(),
"Export index", Path::root(), INDEX_FILTER, INDEX_EXT);

if(Transaction *tx = g_reapack->setupTransaction()) {
tx->exportIndex(path);
tx->runTasks();
}
}

void Manager::launchBrowser()
{
const auto promptApply = [this] {
Expand Down
2 changes: 2 additions & 0 deletions src/manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ class Manager : public Dialog {
void setupNetwork();
void importArchive();
void exportArchive();
void importIndex();
void exportIndex();
void aboutRepo(bool focus = true);

void setChange(int);
Expand Down
27 changes: 27 additions & 0 deletions src/task.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,24 @@ class InstallTask : public Task {
std::unordered_set<ThreadTask *> m_waiting;
};

struct PackageFromIndex {
Remote remote;
std::string name, category, version;
int flags;
};

class InstallFromIndexTask : public Task {
public:
InstallFromIndexTask(PackageFromIndex &&, Transaction *);

bool start() override;
void commit() override;

private:
PackageFromIndex pkg;
const Version * version = nullptr;
};

class UninstallTask : public Task {
public:
UninstallTask(const Registry::Entry &, Transaction *);
Expand Down Expand Up @@ -142,4 +160,13 @@ class ExportTask : public Task {
TempPath m_path;
};

class ExportIndexTask : public Task {
public:
inline ExportIndexTask(std::string_view path, Transaction *tx): Task(tx), m_path(path) {}

protected:
void commit() final;
std::string m_path;
};

#endif
10 changes: 10 additions & 0 deletions src/transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@ void Transaction::install(const Version *ver, const Registry::Entry &oldEntry,
m_nextQueue.push(std::make_shared<InstallTask>(ver, flags, oldEntry, reader, this));
}

void Transaction::installFromIndex(PackageFromIndex&& pkg)
{
m_nextQueue.push(std::make_shared<InstallFromIndexTask>(std::move(pkg), this));
}

void Transaction::setFlags(const Registry::Entry &entry, const int flags)
{
m_nextQueue.push(std::make_shared<FlagsTask>(entry, flags, this));
Expand Down Expand Up @@ -142,6 +147,11 @@ void Transaction::exportArchive(const std::string &path)
m_nextQueue.push(std::make_shared<ExportTask>(path, this));
}

void Transaction::exportIndex(std::string_view path)
{
m_nextQueue.push(std::make_shared<ExportIndexTask>(path, this));
}

bool Transaction::runTasks()
{
do {
Expand Down
3 changes: 3 additions & 0 deletions src/transaction.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,12 @@ class Transaction {
void install(const Version *, int flags = 0, const ArchiveReaderPtr & = nullptr);
void install(const Version *, const Registry::Entry &oldEntry,
int flags = false, const ArchiveReaderPtr & = nullptr);
void installFromIndex(PackageFromIndex&& pkg);
void setFlags(const Registry::Entry &, int flags);
void uninstall(const Remote &);
void uninstall(const Registry::Entry &);
void exportArchive(const std::string &path);
void exportIndex(std::string_view path);
bool runTasks();

bool isCancelled() const { return m_isCancelled; }
Expand All @@ -75,6 +77,7 @@ class Transaction {
protected:
friend SynchronizeTask;
friend InstallTask;
friend InstallFromIndexTask;
friend UninstallTask;

IndexPtr loadIndex(const Remote &);
Expand Down