restructured some classes, overall improvements
This commit is contained in:
parent
c6d3ea2d8e
commit
fde2f592ed
|
@ -6,12 +6,15 @@
|
|||
|
||||
#include <c++utilities/misc/memory.h>
|
||||
|
||||
#include "alpm.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QJsonObject>
|
||||
#include <QtConcurrent>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace PackageManagement {
|
||||
namespace RepoIndex {
|
||||
|
||||
using namespace Utilities;
|
||||
|
||||
|
@ -21,15 +24,48 @@ using namespace Utilities;
|
|||
* All packages returned by the AlpmDataBase class are AlpmPackage instances.
|
||||
*/
|
||||
|
||||
class LoadPackage
|
||||
{
|
||||
public:
|
||||
LoadPackage(AlpmDatabase *db, QMutex *mutex) :
|
||||
m_db(db),
|
||||
m_mutex(mutex)
|
||||
{}
|
||||
|
||||
void operator()(alpm_pkg_t *pkg)
|
||||
{
|
||||
auto res = make_unique<AlpmPackage>(pkg, m_db);
|
||||
QMutexLocker locker(m_mutex);
|
||||
for(const auto &grpName : res->groups()) {
|
||||
m_db->groups()[grpName] << res.get();
|
||||
}
|
||||
m_db->packages().emplace(res->name(), move(res));
|
||||
}
|
||||
private:
|
||||
AlpmDatabase *m_db;
|
||||
QMutex *m_mutex;
|
||||
};
|
||||
|
||||
PackageLoader::PackageLoader(AlpmDatabase *db)
|
||||
{
|
||||
for(auto *pkg : PackageList(alpm_db_get_pkgcache(db->ptr()))) {
|
||||
m_packages << pkg;
|
||||
}
|
||||
m_future = QtConcurrent::map(m_packages, LoadPackage(db, &m_mutex));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Creates a new instance wrapping the specified database struct.
|
||||
*/
|
||||
PackageManagement::AlpmDataBase::AlpmDataBase(alpm_db_t *dataBase, const QString &dbPath, QObject *parent) :
|
||||
RepoIndex::AlpmDatabase::AlpmDatabase(alpm_db_t *dataBase, const QString &dbPath, QObject *parent) :
|
||||
Repository(QString::fromLocal8Bit(alpm_db_get_name(dataBase)), parent),
|
||||
m_ptr(dataBase),
|
||||
m_dbFile(QStringLiteral("%1/sync/%2").arg(dbPath, m_name))
|
||||
{}
|
||||
|
||||
PackageLoader *AlpmDatabase::init()
|
||||
{
|
||||
if(alpm_db_get_usage(dataBase, &m_usage)) {
|
||||
if(alpm_db_get_usage(m_ptr, &m_usage)) {
|
||||
m_usage = static_cast<decltype(m_usage)>(ALPM_DB_USAGE_ALL);
|
||||
}
|
||||
if(m_name.compare(QLatin1String("local"), Qt::CaseInsensitive) == 0) {
|
||||
|
@ -41,39 +77,48 @@ PackageManagement::AlpmDataBase::AlpmDataBase(alpm_db_t *dataBase, const QString
|
|||
m_description = QStringLiteral("Database »%1«").arg(m_name);
|
||||
}
|
||||
}
|
||||
for(auto *nativePkg : PackageList(alpm_db_get_pkgcache(m_ptr))) {
|
||||
auto pkg = make_unique<AlpmPackage>(nativePkg, this);
|
||||
QString pkgName = pkg->name();
|
||||
for(const auto &grpName : pkg->groups()) {
|
||||
m_groups[grpName] << pkg.get();
|
||||
}
|
||||
m_packages.emplace(pkgName, move(pkg));
|
||||
}
|
||||
// for(auto *nativePkg : PackageList(alpm_db_get_pkgcache(m_ptr))) {
|
||||
// auto pkg = make_unique<AlpmPackage>(nativePkg, this);
|
||||
// QString pkgName = pkg->name();
|
||||
// for(const auto &grpName : pkg->groups()) {
|
||||
// m_groups[grpName] << pkg.get();
|
||||
// }
|
||||
// m_packages.emplace(pkgName, move(pkg));
|
||||
// }
|
||||
for(const char *str : servers()) {
|
||||
m_serverUrls << qstr(str);
|
||||
}
|
||||
m_sigLevel = alpm_db_get_siglevel(m_ptr);
|
||||
|
||||
return new PackageLoader(this);
|
||||
}
|
||||
|
||||
//AlpmDataBase::AlpmDataBase(const QString &dataBaseFile, QObject *parent) :
|
||||
//AlpmDatabase::AlpmDatabase(const QString &dataBaseFile, QObject *parent) :
|
||||
// PackageSource(parent),
|
||||
// m_ptr(nullptr)
|
||||
//{}
|
||||
|
||||
RepositoryType AlpmDataBase::type() const
|
||||
RepositoryType AlpmDatabase::type() const
|
||||
{
|
||||
return RepositoryType::AlpmDataBase;
|
||||
return RepositoryType::AlpmDatabase;
|
||||
}
|
||||
|
||||
bool AlpmDataBase::isSourceOnly() const
|
||||
PackageDetailAvailability AlpmDatabase::requestsRequired(PackageDetail packageDetail) const
|
||||
{
|
||||
return false;
|
||||
switch(packageDetail) {
|
||||
case PackageDetail::Basics:
|
||||
case PackageDetail::Dependencies:
|
||||
case PackageDetail::PackageInfo:
|
||||
return PackageDetailAvailability::Immediately;
|
||||
default:
|
||||
return PackageDetailAvailability::Never;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds the specified server URLs.
|
||||
*/
|
||||
bool AlpmDataBase::addServerUrls(const QStringList &urls)
|
||||
bool AlpmDatabase::addServerUrls(const QStringList &urls)
|
||||
{
|
||||
bool res = true;
|
||||
for(const auto &url : urls) {
|
||||
|
|
|
@ -4,24 +4,48 @@
|
|||
#include "repository.h"
|
||||
#include "list.h"
|
||||
|
||||
#include <alpm.h>
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QMutex>
|
||||
#include <QFuture>
|
||||
|
||||
namespace PackageManagement {
|
||||
#include <memory>
|
||||
|
||||
class AlpmDataBase : public Repository
|
||||
namespace RepoIndex {
|
||||
|
||||
class AlpmPackage;
|
||||
class AlpmDatabase;
|
||||
|
||||
class PackageLoader
|
||||
{
|
||||
public:
|
||||
explicit AlpmDataBase(alpm_db_t *dataBase, const QString &dbPath, QObject *parent = nullptr);
|
||||
// explicit AlpmDataBase(const QString &dataBaseFile, QObject *parent = nullptr);
|
||||
PackageLoader(AlpmDatabase *db);
|
||||
QFuture<void> &future();
|
||||
|
||||
private:
|
||||
QMutex m_mutex;
|
||||
QList<alpm_pkg_t *> m_packages;
|
||||
QFuture<void> m_future;
|
||||
};
|
||||
|
||||
inline QFuture<void> &PackageLoader::future()
|
||||
{
|
||||
return m_future;
|
||||
}
|
||||
|
||||
class AlpmDatabase : public Repository
|
||||
{
|
||||
friend class EmplacePackage;
|
||||
public:
|
||||
explicit AlpmDatabase(alpm_db_t *dataBase, const QString &dbPath, QObject *parent = nullptr);
|
||||
PackageLoader *init();
|
||||
// explicit AlpmDatabase(const QString &dataBaseFile, QObject *parent = nullptr);
|
||||
|
||||
RepositoryType type() const;
|
||||
bool isSourceOnly() const;
|
||||
PackageDetailAvailability requestsRequired(PackageDetail packageDetail) const;
|
||||
|
||||
// operators
|
||||
bool operator ==(const AlpmDataBase &other) const;
|
||||
bool operator !=(const AlpmDataBase &other) const;
|
||||
bool operator ==(const AlpmDatabase &other) const;
|
||||
bool operator !=(const AlpmDatabase &other) const;
|
||||
|
||||
// database meta data
|
||||
alpm_db_t *ptr();
|
||||
|
@ -31,6 +55,9 @@ public:
|
|||
bool addServerUrls(const QStringList &urls);
|
||||
PackageList search(StringList terms) const;
|
||||
|
||||
signals:
|
||||
void initiated();
|
||||
|
||||
private:
|
||||
alpm_db_t *m_ptr;
|
||||
QString m_dbFile;
|
||||
|
@ -39,7 +66,7 @@ private:
|
|||
/*!
|
||||
* \brief Checks whether the specified ALPM database is equal the current instance.
|
||||
*/
|
||||
inline bool AlpmDataBase::operator ==(const AlpmDataBase &other) const
|
||||
inline bool AlpmDatabase::operator ==(const AlpmDatabase &other) const
|
||||
{
|
||||
return m_ptr == other.m_ptr;
|
||||
}
|
||||
|
@ -47,7 +74,7 @@ inline bool AlpmDataBase::operator ==(const AlpmDataBase &other) const
|
|||
/*!
|
||||
* \brief Checks whether the specified ALPM database is not equal to the current instance.
|
||||
*/
|
||||
inline bool AlpmDataBase::operator !=(const AlpmDataBase &other) const
|
||||
inline bool AlpmDatabase::operator !=(const AlpmDatabase &other) const
|
||||
{
|
||||
return m_ptr != other.m_ptr;
|
||||
}
|
||||
|
@ -55,7 +82,7 @@ inline bool AlpmDataBase::operator !=(const AlpmDataBase &other) const
|
|||
/*!
|
||||
* \brief Returns the pointer to the underlying database struct.
|
||||
*/
|
||||
inline alpm_db_t *AlpmDataBase::ptr()
|
||||
inline alpm_db_t *AlpmDatabase::ptr()
|
||||
{
|
||||
return m_ptr;
|
||||
}
|
||||
|
@ -63,7 +90,7 @@ inline alpm_db_t *AlpmDataBase::ptr()
|
|||
/*!
|
||||
* \brief Returns the path of the data base file.
|
||||
*/
|
||||
inline const QString &AlpmDataBase::dataBaseFile() const
|
||||
inline const QString &AlpmDatabase::dataBaseFile() const
|
||||
{
|
||||
return m_dbFile;
|
||||
}
|
||||
|
@ -71,7 +98,7 @@ inline const QString &AlpmDataBase::dataBaseFile() const
|
|||
/*!
|
||||
* \brief Returns the servers of the database.
|
||||
*/
|
||||
inline StringList AlpmDataBase::servers() const
|
||||
inline StringList AlpmDatabase::servers() const
|
||||
{
|
||||
return alpm_db_get_servers(m_ptr);
|
||||
}
|
||||
|
@ -79,7 +106,7 @@ inline StringList AlpmDataBase::servers() const
|
|||
/*!
|
||||
* \brief Sets the servers of the database.
|
||||
*/
|
||||
inline bool AlpmDataBase::setServers(StringList servers)
|
||||
inline bool AlpmDatabase::setServers(StringList servers)
|
||||
{
|
||||
return alpm_db_set_servers(m_ptr, servers.begin().ptr()) == 0;
|
||||
}
|
||||
|
@ -87,7 +114,7 @@ inline bool AlpmDataBase::setServers(StringList servers)
|
|||
/*!
|
||||
* \brief Performs a search using the build in ALPM function.
|
||||
*/
|
||||
inline PackageList AlpmDataBase::search(StringList terms) const
|
||||
inline PackageList AlpmDatabase::search(StringList terms) const
|
||||
{
|
||||
return alpm_db_search(m_ptr, terms.begin().ptr());
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
using namespace ChronoUtilities;
|
||||
|
||||
namespace PackageManagement {
|
||||
namespace RepoIndex {
|
||||
|
||||
/*!
|
||||
* \cond
|
||||
|
@ -38,7 +38,7 @@ using namespace Utilities;
|
|||
/*!
|
||||
* \brief Constructs a new package instance for the specified ALPM \a package.
|
||||
*/
|
||||
AlpmPackage::AlpmPackage(alpm_pkg_t *package, AlpmDataBase *source) :
|
||||
AlpmPackage::AlpmPackage(alpm_pkg_t *package, AlpmDatabase *source) :
|
||||
Package(QString::fromLocal8Bit(alpm_pkg_get_name(package)), source),
|
||||
m_ptr(package)
|
||||
{
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
|
||||
#include "package.h"
|
||||
|
||||
namespace PackageManagement {
|
||||
namespace RepoIndex {
|
||||
|
||||
class AlpmDataBase;
|
||||
class AlpmDatabase;
|
||||
|
||||
class AlpmPackage : public Package
|
||||
{
|
||||
public:
|
||||
AlpmPackage(alpm_pkg_t *package, AlpmDataBase *source = nullptr);
|
||||
AlpmPackage(alpm_pkg_t *package, AlpmDatabase *source = nullptr);
|
||||
|
||||
// ALPM specific meta data
|
||||
const alpm_pkg_t *ptr() const;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
using namespace ChronoUtilities;
|
||||
|
||||
namespace PackageManagement {
|
||||
namespace RepoIndex {
|
||||
|
||||
/*!
|
||||
* \brief The AurPackage class holds information about AUR packages. It allows to convert the information
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "package.h"
|
||||
|
||||
namespace PackageManagement {
|
||||
namespace RepoIndex {
|
||||
|
||||
class UserRepository;
|
||||
|
||||
|
|
|
@ -14,7 +14,10 @@ using namespace std;
|
|||
using namespace ApplicationUtilities;
|
||||
using namespace ConversionUtilities;
|
||||
|
||||
namespace PackageManagement {
|
||||
namespace RepoIndex {
|
||||
|
||||
bool useShSyntax = false;
|
||||
const char *shchar = "";
|
||||
|
||||
/*!
|
||||
* \class Alpm::Config
|
||||
|
@ -28,23 +31,26 @@ ConfigArgs::ConfigArgs(ArgumentParser &parser) :
|
|||
helpArg(parser),
|
||||
buildOrderArg("build-order", "b", "calculates the build order to build the specified packages"),
|
||||
serverArg("server", "s", "runs a websocket server providing the web interface with information"),
|
||||
upgradeLookupArg("upgrade-lookup", "u", "checks available upgrades for the specified repository"),
|
||||
mingwBundleArg("mingw-w64-bundle", "m", "creates an archive with the runtime-relevant files from the specified mingw-w64-packages and their dependencies"),
|
||||
repoindexConfArg("repoindex-conf", "c", "specifies the path of the repo index config file (default is /etc/repoindex.conf"),
|
||||
rootdirArg("root-dir", "r", "specifies the root directory (default is /)"),
|
||||
dbpathArg("db-path", "d", "specifies the pacman database path (default is /var/lib/pacman)"),
|
||||
pacmanConfArg("pacman-conf", "p", "specifies the path of the pacman config file (default is /etc/pacman.conf"),
|
||||
websocketAddrArg("addr", "a", "specifies the listening address for the websocket server, default is 127.0.0.1"),
|
||||
websocketPortArg("port", "p", "specifies the listening port for the websocket server, default is 1234"),
|
||||
websocketAddrArg("addr", string(), "specifies the listening address for the websocket server, default is 127.0.0.1"),
|
||||
websocketPortArg("port", string(), "specifies the listening port for the websocket server, default is 1234"),
|
||||
certFileArg("cert-file", string(), "specifies the SSL certificate"),
|
||||
keyFileArg("key-file", string(), "specifies the private SSL key"),
|
||||
insecureArg("insecure", string(), "forces the server to run in insecure mode"),
|
||||
aurArg("aur", "u", "enables/disables AUR queries"),
|
||||
aurArg("aur", string(), "enables/disables AUR queries"),
|
||||
verboseArg("verbose", "v", "be verbose"),
|
||||
outputFileArg("output-file", "f", "specifies the output file"),
|
||||
targetDirArg("target-dir", "t", "the directory to store the target archive"),
|
||||
targetNameArg("target-name", "n", "specifies the name of the target archive"),
|
||||
targetFormatArg("target-format", "e", "specifies the format of the target archive"),
|
||||
iconThemesArg("icon-packages", "i", "specifies the names of the icon packages to include")
|
||||
iconThemesArg("icon-packages", "i", "specifies the names of the icon packages to include"),
|
||||
shSyntaxArg("sh-syntax", string(), "prints the output using shell syntax: export REPOINDEX_RESULTS=('res1' 'res2' 'res3') or export REPOINDEX_ERROR='some error message'"),
|
||||
repoArg("repo", string(), "specifies the repository")
|
||||
{
|
||||
const initializer_list<string> pathValueName = {"path"};
|
||||
const initializer_list<string> pkgValueNames = {"package 1", "package 2", "package 3"};
|
||||
|
@ -52,6 +58,7 @@ ConfigArgs::ConfigArgs(ArgumentParser &parser) :
|
|||
buildOrderArg.setRequiredValueCount(-1);
|
||||
buildOrderArg.setValueNames(pkgValueNames);
|
||||
serverArg.setDenotesOperation(true);
|
||||
upgradeLookupArg.setDenotesOperation(true);
|
||||
mingwBundleArg.setDenotesOperation(true);
|
||||
mingwBundleArg.setRequiredValueCount(-1);
|
||||
mingwBundleArg.setValueNames(pkgValueNames);
|
||||
|
@ -101,8 +108,12 @@ ConfigArgs::ConfigArgs(ArgumentParser &parser) :
|
|||
iconThemesArg.setCombinable(true);
|
||||
iconThemesArg.setRequiredValueCount(-1);
|
||||
iconThemesArg.setValueNames(pkgValueNames);
|
||||
serverArg.setSecondaryArguments({&rootdirArg, &dbpathArg, &pacmanConfArg, &certFileArg, &keyFileArg, &insecureArg, &aurArg});
|
||||
buildOrderArg.setSecondaryArguments({&aurArg, &verboseArg});
|
||||
shSyntaxArg.setCombinable(true);
|
||||
repoArg.setRequiredValueCount(1);
|
||||
repoArg.setValueNames({"repo name"});
|
||||
serverArg.setSecondaryArguments({&rootdirArg, &dbpathArg, &pacmanConfArg, &certFileArg, &keyFileArg, &websocketAddrArg, &websocketPortArg, &insecureArg, &aurArg});
|
||||
upgradeLookupArg.setSecondaryArguments({&repoArg, &shSyntaxArg});
|
||||
buildOrderArg.setSecondaryArguments({&aurArg, &verboseArg, &shSyntaxArg});
|
||||
mingwBundleArg.setSecondaryArguments({&targetDirArg, &targetNameArg, &targetFormatArg, &iconThemesArg});
|
||||
parser.setMainArguments({&buildOrderArg, &serverArg, &mingwBundleArg, &repoindexConfArg, &repoindexConfArg, &helpArg});
|
||||
}
|
||||
|
@ -139,7 +150,7 @@ inline void assign(quint16 &num, const QJsonValue &val)
|
|||
if(n > 0 && n <= static_cast<quint16>(-1)) {
|
||||
num = static_cast<quint16>(n);
|
||||
} else {
|
||||
cerr << "Error: The specified value \"" << n << "\" is not a number." << endl;
|
||||
cerr << shchar << "Error: The specified value \"" << n << "\" is not a number." << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -147,7 +158,7 @@ inline void assign(quint16 &num, const QJsonValue &val)
|
|||
inline void assign(QHostAddress &addr, const QString &val)
|
||||
{
|
||||
if(!val.isEmpty() && !addr.setAddress(val)) {
|
||||
cerr << "Error: Unable to parse the specified host address \"" << val.toStdString() << "\"." << endl;
|
||||
cerr << shchar << "Error: Unable to parse the specified host address \"" << val.toStdString() << "\"." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,7 +175,7 @@ inline void assign(quint16 &num, const Argument &arg)
|
|||
try {
|
||||
num = stringToNumber<quint16>(arg.values().front());
|
||||
} catch(const ConversionException &) {
|
||||
cerr << "Error: The specified argument value \"" << arg.values().front() << "\" is not a number." << endl;
|
||||
cerr << shchar << "Error: The specified argument value \"" << arg.values().front() << "\" is not a number." << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -208,11 +219,11 @@ void Config::loadFromConfigFile(const QString &configFilePath)
|
|||
m_repoEntries.back().load(repo);
|
||||
}
|
||||
} else {
|
||||
cerr << "Error: Unable to parse config file \"" << configFilePath.toLocal8Bit().data() << "\": "
|
||||
cerr << shchar << "Error: Unable to parse config file \"" << configFilePath.toLocal8Bit().data() << "\": "
|
||||
<< error.errorString().toLocal8Bit().data() << " at character " << error.offset << endl;
|
||||
}
|
||||
} else {
|
||||
cerr << "Error: Unable to open config file \"" << configFilePath.toLocal8Bit().data() << "\"." << endl;
|
||||
cerr << shchar << "Error: Unable to open config file \"" << configFilePath.toLocal8Bit().data() << "\"." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -252,7 +263,7 @@ void Config::loadFromArgs(const ConfigArgs &args)
|
|||
} else if(val == "disabled") {
|
||||
m_aurEnabled = false;
|
||||
} else {
|
||||
cerr << "Warning: The specified value for the argument --aur-enabled is invalid and will be ignored." << endl;
|
||||
cerr << shchar << "Warning: The specified value for the argument --aur-enabled is invalid and will be ignored." << endl;
|
||||
}
|
||||
}
|
||||
assign(m_websocketServerListeningPort, args.websocketPortArg);
|
||||
|
|
|
@ -9,7 +9,11 @@
|
|||
|
||||
QT_FORWARD_DECLARE_CLASS(QJsonValue)
|
||||
|
||||
namespace PackageManagement {
|
||||
namespace RepoIndex {
|
||||
|
||||
// these are needed from the beginning and are initialized in the main()
|
||||
extern bool useShSyntax;
|
||||
extern const char *shchar;
|
||||
|
||||
class ConfigArgs
|
||||
{
|
||||
|
@ -18,6 +22,7 @@ public:
|
|||
ApplicationUtilities::HelpArgument helpArg;
|
||||
ApplicationUtilities::Argument buildOrderArg;
|
||||
ApplicationUtilities::Argument serverArg;
|
||||
ApplicationUtilities::Argument upgradeLookupArg;
|
||||
ApplicationUtilities::Argument mingwBundleArg;
|
||||
ApplicationUtilities::Argument repoindexConfArg;
|
||||
ApplicationUtilities::Argument rootdirArg;
|
||||
|
@ -35,6 +40,8 @@ public:
|
|||
ApplicationUtilities::Argument targetNameArg;
|
||||
ApplicationUtilities::Argument targetFormatArg;
|
||||
ApplicationUtilities::Argument iconThemesArg;
|
||||
ApplicationUtilities::Argument shSyntaxArg;
|
||||
ApplicationUtilities::Argument repoArg;
|
||||
};
|
||||
|
||||
class Config;
|
||||
|
@ -120,6 +127,7 @@ public:
|
|||
bool isAurEnabled() const;
|
||||
bool isVerbose() const;
|
||||
bool runServer() const;
|
||||
const char *shSyntax() const;
|
||||
|
||||
void loadFromConfigFile(const QString &args);
|
||||
void loadFromConfigFile(const ConfigArgs &args);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include <QJsonArray>
|
||||
|
||||
namespace PackageManagement {
|
||||
namespace RepoIndex {
|
||||
|
||||
/*!
|
||||
* \class AlpmGroup
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
QT_FORWARD_DECLARE_CLASS(QJsonArray)
|
||||
|
||||
namespace PackageManagement {
|
||||
namespace RepoIndex {
|
||||
|
||||
class AlpmGroup
|
||||
{
|
||||
|
|
|
@ -3,13 +3,15 @@
|
|||
|
||||
#include <alpm.h>
|
||||
|
||||
namespace PackageManagement {
|
||||
#include <iterator>
|
||||
|
||||
namespace RepoIndex {
|
||||
|
||||
/*!
|
||||
* \brief The ListIterator class is used to iterate Alpm::List instances.
|
||||
*/
|
||||
template <class T = const char *>
|
||||
class AlpmListIterator
|
||||
class AlpmListIterator : public std::iterator<std::output_iterator_tag, T>
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
|
|
174
alpm/manager.cpp
174
alpm/manager.cpp
|
@ -12,8 +12,8 @@
|
|||
|
||||
#include <QList>
|
||||
#include <QSysInfo>
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
#include <QMutexLocker>
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <unordered_map>
|
||||
|
@ -23,7 +23,7 @@ using namespace std;
|
|||
using namespace IoUtilities;
|
||||
using namespace ConversionUtilities;
|
||||
|
||||
namespace PackageManagement {
|
||||
namespace RepoIndex {
|
||||
|
||||
/*!
|
||||
* \cond
|
||||
|
@ -63,7 +63,7 @@ Manager::Manager(const Config &config) :
|
|||
if(!(m_handle = alpm_initialize(config.alpmRootDir().toLocal8Bit().data(), config.alpmDbPath().toLocal8Bit().data(), &err))) {
|
||||
throw runtime_error(string("Cannot initialize ALPM: ") + alpm_strerror(err));
|
||||
}
|
||||
m_localDb = make_unique<AlpmDataBase>(alpm_get_localdb(m_handle), config.alpmDbPath());
|
||||
m_localDb = make_unique<AlpmDatabase>(alpm_get_localdb(m_handle), config.alpmDbPath());
|
||||
if(config.isAurEnabled()) {
|
||||
m_userRepo = make_unique<UserRepository>(m_networkAccessManager);
|
||||
}
|
||||
|
@ -78,11 +78,11 @@ Manager::~Manager()
|
|||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the package with the specified name from the specified database.
|
||||
* \brief Returns the first package with the specified name from the specified database.
|
||||
*/
|
||||
AlpmPackage *Manager::packageFromDataBase(const QString &dbName, const QString &pkgName)
|
||||
AlpmPackage *Manager::packageFromDatabase(const QString &dbName, const QString &pkgName)
|
||||
{
|
||||
if(auto *db = dataBaseByName(dbName)) {
|
||||
if(auto *db = databaseByName(dbName)) {
|
||||
return static_cast<AlpmPackage *>(db->packageByName(pkgName));
|
||||
} else {
|
||||
return nullptr;
|
||||
|
@ -90,11 +90,11 @@ AlpmPackage *Manager::packageFromDataBase(const QString &dbName, const QString &
|
|||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the package with the specified name from the specified database.
|
||||
* \brief Returns the first package with the specified name from the specified database.
|
||||
*/
|
||||
const AlpmPackage *Manager::packageFromDataBase(const QString &dbName, const QString &pkgName) const
|
||||
const AlpmPackage *Manager::packageFromDatabase(const QString &dbName, const QString &pkgName) const
|
||||
{
|
||||
if(const auto *db = dataBaseByName(dbName)) {
|
||||
if(const auto *db = databaseByName(dbName)) {
|
||||
return static_cast<const AlpmPackage *>(db->packageByName(pkgName));
|
||||
} else {
|
||||
return nullptr;
|
||||
|
@ -102,11 +102,11 @@ const AlpmPackage *Manager::packageFromDataBase(const QString &dbName, const QSt
|
|||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the package with the specified \a name from one of the sync databases.
|
||||
* \brief Returns the first package with the specified \a name from one of the sync databases.
|
||||
*/
|
||||
AlpmPackage *Manager::packageFromSyncDataBases(const QString &pkgName)
|
||||
AlpmPackage *Manager::packageFromSyncDatabases(const QString &pkgName)
|
||||
{
|
||||
for(const auto &dbEntry : syncDataBases()) {
|
||||
for(const auto &dbEntry : syncDatabases()) {
|
||||
if(auto *pkg = dbEntry.second->packageByName(pkgName)) {
|
||||
return static_cast<AlpmPackage *>(pkg);
|
||||
}
|
||||
|
@ -115,11 +115,11 @@ AlpmPackage *Manager::packageFromSyncDataBases(const QString &pkgName)
|
|||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the package with the specified \a name from one of the sync databases.
|
||||
* \brief Returns the first package with the specified \a name from one of the sync databases.
|
||||
*/
|
||||
const AlpmPackage *Manager::packageFromSyncDataBases(const QString &pkgName) const
|
||||
const AlpmPackage *Manager::packageFromSyncDatabases(const QString &pkgName) const
|
||||
{
|
||||
for(const auto &dbEntry : syncDataBases()) {
|
||||
for(const auto &dbEntry : syncDatabases()) {
|
||||
if(const auto *pkg = dbEntry.second->packageByName(pkgName)) {
|
||||
return static_cast<const AlpmPackage *>(pkg);
|
||||
}
|
||||
|
@ -142,6 +142,36 @@ unique_ptr<AlpmOwnershipPackage> Manager::packageFromFile(const char *fileName,
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the first package satisfiing the specified dependency from one of the available package sources (excluding the local database).
|
||||
*/
|
||||
Package *Manager::packageProviding(const Dependency &dependency)
|
||||
{
|
||||
for(auto &dbEntry : syncDatabases()) {
|
||||
if(auto *pkg = dbEntry.second->packageProviding(dependency)) {
|
||||
return pkg;
|
||||
}
|
||||
}
|
||||
if(config().isAurEnabled()) {
|
||||
// TODO: check AUR
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the first package satisfiing the specified dependency from one of the available package sources (excluding the local database
|
||||
* and sources requirering requests such as the AUR).
|
||||
*/
|
||||
const Package *Manager::packageProviding(const Dependency &dependency) const
|
||||
{
|
||||
for(const auto &dbEntry : syncDatabases()) {
|
||||
if(const auto *pkg = dbEntry.second->packageProviding(dependency)) {
|
||||
return pkg;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the install reason for the specified \a package.
|
||||
*/
|
||||
|
@ -222,7 +252,7 @@ int Manager::parseSigLevel(const string &sigLevelStr)
|
|||
sigLevel |= ALPM_SIG_DATABASE_MARGINAL_OK | ALPM_SIG_DATABASE_UNKNOWN_OK;
|
||||
}
|
||||
} else {
|
||||
cerr << "Warning: Invalid value \"" << part << "\" for \"SigLevel\" in pacman config file will be ignored." << endl;
|
||||
cerr << shchar << "Warning: Invalid value \"" << part << "\" for \"SigLevel\" in pacman config file will be ignored." << endl;
|
||||
}
|
||||
}
|
||||
return sigLevel;
|
||||
|
@ -245,7 +275,7 @@ int Manager::parseUsage(const string &usageStr)
|
|||
} else if(part == "Upgrade") {
|
||||
usage |= ALPM_DB_USAGE_UPGRADE;
|
||||
} else {
|
||||
cerr << "Warning: Invalid value \"" << part << "\" for \"Usage\" in pacman config file will be ignored." << endl;
|
||||
cerr << shchar << "Warning: Invalid value \"" << part << "\" for \"Usage\" in pacman config file will be ignored." << endl;
|
||||
}
|
||||
}
|
||||
return usage ? usage : ALPM_DB_USAGE_ALL;
|
||||
|
@ -295,11 +325,11 @@ void Manager::applyPacmanConfig()
|
|||
// read and validate database name
|
||||
QString dbName = QString::fromLocal8Bit(scope.first.c_str());
|
||||
if(dbName.compare(QLatin1String("local"), Qt::CaseInsensitive) == 0) {
|
||||
cerr << "Error: Unable to add database from pacman config: The database name mustn't be \"local\" because this name is reserved for the local database." << endl;
|
||||
cerr << shchar << "Error: Unable to add database from pacman config: The database name mustn't be \"local\" because this name is reserved for the local database." << endl;
|
||||
} else if(dbName.startsWith(QLatin1String("aur"), Qt::CaseInsensitive)) {
|
||||
cerr << "Error: Unable to add database from pacman config: The database name mustn't start with \"aur\" because this name is reserved for the Arch Linux User Repository." << endl;
|
||||
cerr << shchar << "Error: Unable to add database from pacman config: The database name mustn't start with \"aur\" because this name is reserved for the Arch Linux User Repository." << endl;
|
||||
} else if(m_syncDbs.count(dbName)) {
|
||||
cerr << "Error: Unable to add database from pacman config: Database names must be unique. Ignoring second occurance of database \"" << scope.first << "\"." << endl;
|
||||
cerr << shchar << "Error: Unable to add database from pacman config: Database names must be unique. Ignoring second occurance of database \"" << scope.first << "\"." << endl;
|
||||
} else {
|
||||
// read sig level and usage
|
||||
const auto &sigLevelStr = lastValue(scope.second, sigLevelKey);
|
||||
|
@ -310,11 +340,11 @@ void Manager::applyPacmanConfig()
|
|||
// set usage
|
||||
if(alpm_db_set_usage(db, static_cast<alpm_db_usage_t>(usage)) == 0) {
|
||||
if(m_config.isVerbose() || m_config.runServer()) {
|
||||
cerr << "Added database [" << scope.first << "]" << endl;
|
||||
cerr << shchar << "Added database [" << scope.first << "]" << endl;
|
||||
}
|
||||
} else {
|
||||
if(m_config.isVerbose() || m_config.runServer()) {
|
||||
cerr << "Warning: Added database [" << scope.first << "] but failed to set usage" << endl;
|
||||
cerr << shchar << "Warning: Added database [" << scope.first << "] but failed to set usage" << endl;
|
||||
}
|
||||
}
|
||||
// add servers
|
||||
|
@ -324,7 +354,7 @@ void Manager::applyPacmanConfig()
|
|||
findAndReplace<string>(url, "$arch", arch);
|
||||
alpm_db_add_server(db, url.c_str());
|
||||
if(m_config.isVerbose() || m_config.runServer()) {
|
||||
cerr << "Added server: " << url << endl;
|
||||
cerr << shchar << "Added server: " << url << endl;
|
||||
}
|
||||
}
|
||||
// add included servers
|
||||
|
@ -338,7 +368,7 @@ void Manager::applyPacmanConfig()
|
|||
includedFile.open(path, ios_base::in);
|
||||
includedIni.parse(includedFile);
|
||||
} catch (const ios_base::failure &) {
|
||||
cerr << "Error: An IO exception occured when parsing the included file \"" << path << "\"." << endl;
|
||||
cerr << shchar << "Error: An IO exception occured when parsing the included file \"" << path << "\"." << endl;
|
||||
}
|
||||
}
|
||||
try {
|
||||
|
@ -349,21 +379,21 @@ void Manager::applyPacmanConfig()
|
|||
findAndReplace<string>(url, "$arch", arch);
|
||||
alpm_db_add_server(db, url.c_str());
|
||||
if(m_config.isVerbose() || m_config.runServer()) {
|
||||
cerr << "Added server: " << url << endl;
|
||||
cerr << shchar << "Added server: " << url << endl;
|
||||
}
|
||||
}
|
||||
} catch (const out_of_range &) {
|
||||
cerr << "Warning: Included file \"" << path << "\" has no values." << endl;
|
||||
cerr << shchar << "Warning: Included file \"" << path << "\" has no values." << endl;
|
||||
}
|
||||
}
|
||||
auto emplaced = m_syncDbs.emplace(dbName, make_unique<AlpmDataBase>(db, m_config.alpmDbPath()));
|
||||
auto emplaced = m_syncDbs.emplace(dbName, make_unique<AlpmDatabase>(db, m_config.alpmDbPath()));
|
||||
// add sync db to internal map
|
||||
if(usage & ALPM_DB_USAGE_UPGRADE) {
|
||||
// -> db is used to upgrade local database
|
||||
localDataBase()->upgradeSources() << emplaced.first->second.get();
|
||||
localDatabase()->upgradeSources() << emplaced.first->second.get();
|
||||
}
|
||||
} else {
|
||||
cerr << "Error: Unable to add sync database [" << scope.first << "]" << endl;
|
||||
cerr << shchar << "Error: Unable to add sync database [" << scope.first << "]" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -380,35 +410,35 @@ void Manager::applyRepoIndexConfig()
|
|||
{
|
||||
// check whether an entry already exists, if not create a new one
|
||||
for(const RepoEntry &repoEntry : m_config.repoEntries()) {
|
||||
AlpmDataBase *syncDb = nullptr;
|
||||
AlpmDatabase *syncDb = nullptr;
|
||||
try {
|
||||
syncDb = m_syncDbs.at(repoEntry.name()).get();
|
||||
cerr << "Applying config for database [" << syncDb->name() << "]" << endl;
|
||||
cerr << shchar << "Applying config for database [" << syncDb->name() << "]" << endl;
|
||||
if(!repoEntry.dataBasePath().isEmpty()) {
|
||||
cerr << "Warning: Can't use data base path specified in repo index config because the repo \""
|
||||
cerr << shchar << "Warning: Can't use data base path specified in repo index config because the repo \""
|
||||
<< repoEntry.name() << "\" has already been added from the Pacman config." << endl;
|
||||
}
|
||||
if(repoEntry.sigLevel()) {
|
||||
cerr << "Warning: Can't use sig level specified in repo index config because the repo \""
|
||||
cerr << shchar << "Warning: Can't use sig level specified in repo index config because the repo \""
|
||||
<< repoEntry.name() << "\" has already been added from the Pacman config." << endl;
|
||||
}
|
||||
syncDb->setPackagesDirectory(repoEntry.packageDir());
|
||||
syncDb->setSourcesDirectory(repoEntry.sourceDir());
|
||||
} catch(const out_of_range &) {
|
||||
if(repoEntry.name().compare(QLatin1String("local"), Qt::CaseInsensitive) == 0) {
|
||||
cerr << "Error: Unable to add database from repo index config: The database name mustn't be \"local\" because this name is reserved for the local database." << endl;
|
||||
cerr << shchar << "Error: Unable to add database from repo index config: The database name mustn't be \"local\" because this name is reserved for the local database." << endl;
|
||||
} else if(repoEntry.name().startsWith(QLatin1String("aur"), Qt::CaseInsensitive)) {
|
||||
cerr << "Error: Unable to add database from repo index config: The database name mustn't start with \"aur\" because this name is reserved for the Arch Linux User Repository." << endl;
|
||||
cerr << shchar << "Error: Unable to add database from repo index config: The database name mustn't start with \"aur\" because this name is reserved for the Arch Linux User Repository." << endl;
|
||||
} else {
|
||||
// TODO: database path
|
||||
auto *db = alpm_register_syncdb(m_handle, repoEntry.name().toLocal8Bit().data(), static_cast<alpm_siglevel_t>(repoEntry.sigLevel()));
|
||||
auto emplaced = m_syncDbs.emplace(repoEntry.name(), make_unique<AlpmDataBase>(db, m_config.alpmDbPath()));
|
||||
auto emplaced = m_syncDbs.emplace(repoEntry.name(), make_unique<AlpmDatabase>(db, m_config.alpmDbPath()));
|
||||
if(emplaced.second) {
|
||||
syncDb = emplaced.first->second.get();
|
||||
syncDb->setSourcesDirectory(repoEntry.sourceDir());
|
||||
syncDb->setPackagesDirectory(repoEntry.packageDir());
|
||||
if(m_config.isVerbose() || m_config.runServer()) {
|
||||
cerr << "Added database [" << repoEntry.name() << "]" << endl;
|
||||
cerr << shchar << "Added database [" << repoEntry.name() << "]" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -425,7 +455,7 @@ void Manager::applyRepoIndexConfig()
|
|||
if(auto *source = repositoryByName(upgradeSourceName)) {
|
||||
upgradeSources << source;
|
||||
} else {
|
||||
cerr << "Warning: The specified upgrade source \"" << upgradeSourceName << "\" can not be found and will be ignored." << endl;
|
||||
cerr << shchar << "Warning: The specified upgrade source \"" << upgradeSourceName << "\" can not be found and will be ignored." << endl;
|
||||
}
|
||||
}
|
||||
} catch(const out_of_range &) {
|
||||
|
@ -435,6 +465,24 @@ void Manager::applyRepoIndexConfig()
|
|||
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Initiates all ALPM data bases.
|
||||
* \remarks Must be called, after all relevant sync data bases have been registered (eg. via applyPacmanConfig()).
|
||||
*/
|
||||
void Manager::initAlpmDataBases()
|
||||
{
|
||||
QList<PackageLoader *> loaders;
|
||||
loaders.reserve(m_syncDbs.size() + 1);
|
||||
loaders << localDatabase()->init();
|
||||
for(auto &syncDbEntry : m_syncDbs) {
|
||||
loaders << syncDbEntry.second->init();
|
||||
}
|
||||
for(auto *loader : loaders) {
|
||||
loader->future().waitForFinished();
|
||||
delete loader;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Unregisters all registred sync databases.
|
||||
*/
|
||||
|
@ -449,7 +497,7 @@ void Manager::unregisterSyncDataBases()
|
|||
* \brief Returns a list of all sync databases.
|
||||
* \remarks Sync databases must be registered with parsePacmanConfig() before.
|
||||
*/
|
||||
const map<QString, unique_ptr<AlpmDataBase> > &Manager::syncDataBases() const
|
||||
const map<QString, unique_ptr<AlpmDatabase> > &Manager::syncDatabases() const
|
||||
{
|
||||
return m_syncDbs; // m_syncDbs has been filled when the databases were registered
|
||||
}
|
||||
|
@ -466,9 +514,9 @@ const QJsonArray &Manager::basicRepoInfo() const
|
|||
QMutexLocker locker(&m_basicRepoInfoMutex);
|
||||
if(m_basicRepoInfo.isEmpty()) {
|
||||
// add local data base
|
||||
m_basicRepoInfo << localDataBase()->basicInfo();
|
||||
m_basicRepoInfo << localDatabase()->basicInfo();
|
||||
// add sync data bases
|
||||
for(const auto &syncDb : syncDataBases()) {
|
||||
for(const auto &syncDb : syncDatabases()) {
|
||||
// check if the "sync" database is actually used for syncing
|
||||
auto usage = syncDb.second->usage();
|
||||
if((usage & ALPM_DB_USAGE_SYNC) || (usage & ALPM_DB_USAGE_INSTALL) || (usage & ALPM_DB_USAGE_UPGRADE)) {
|
||||
|
@ -533,7 +581,7 @@ const QJsonArray &Manager::groupInfo() const
|
|||
if(m_groupInfo.empty()) {
|
||||
QMutexLocker locker(&m_groupInfoMutex);
|
||||
if(m_groupInfo.empty()) {
|
||||
m_groupInfo << localDataBase()->groupInfo();
|
||||
m_groupInfo << localDatabase()->groupInfo();
|
||||
for(const auto &db : m_syncDbs) {
|
||||
m_groupInfo << db.second->groupInfo();
|
||||
}
|
||||
|
@ -545,10 +593,10 @@ const QJsonArray &Manager::groupInfo() const
|
|||
/*!
|
||||
* \brief Returns the ALPM database with the specified name.
|
||||
*/
|
||||
const AlpmDataBase *Manager::dataBaseByName(const QString &dbName) const
|
||||
const AlpmDatabase *Manager::databaseByName(const QString &dbName) const
|
||||
{
|
||||
if(dbName.compare(QLatin1String("local"), Qt::CaseInsensitive) == 0) {
|
||||
return localDataBase();
|
||||
return localDatabase();
|
||||
} else {
|
||||
try {
|
||||
return m_syncDbs.at(dbName).get();
|
||||
|
@ -561,10 +609,10 @@ const AlpmDataBase *Manager::dataBaseByName(const QString &dbName) const
|
|||
/*!
|
||||
* \brief Returns the ALPM database with the specified name.
|
||||
*/
|
||||
AlpmDataBase *Manager::dataBaseByName(const QString &dbName)
|
||||
AlpmDatabase *Manager::databaseByName(const QString &dbName)
|
||||
{
|
||||
if(dbName.compare(QLatin1String("local"), Qt::CaseInsensitive) == 0) {
|
||||
return localDataBase();
|
||||
return localDatabase();
|
||||
} else {
|
||||
try {
|
||||
return m_syncDbs.at(dbName).get();
|
||||
|
@ -580,7 +628,7 @@ AlpmDataBase *Manager::dataBaseByName(const QString &dbName)
|
|||
const Repository *Manager::repositoryByName(const QString &name) const
|
||||
{
|
||||
if(name.compare(QLatin1String("local"), Qt::CaseInsensitive) == 0) {
|
||||
return localDataBase();
|
||||
return localDatabase();
|
||||
} else if(config().isAurEnabled() && (name.compare(QLatin1String("aur"), Qt::CaseInsensitive) == 0)) {
|
||||
return userRepository();
|
||||
} else {
|
||||
|
@ -598,7 +646,7 @@ const Repository *Manager::repositoryByName(const QString &name) const
|
|||
Repository *Manager::repositoryByName(const QString &name)
|
||||
{
|
||||
if(name.compare(QLatin1String("local"), Qt::CaseInsensitive) == 0) {
|
||||
return localDataBase();
|
||||
return localDatabase();
|
||||
} else if(config().isAurEnabled() && (name.compare(QLatin1String("aur"), Qt::CaseInsensitive) == 0)) {
|
||||
return userRepository();
|
||||
} else {
|
||||
|
@ -610,12 +658,40 @@ Repository *Manager::repositoryByName(const QString &name)
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns a list of all repositories excluding the local database.
|
||||
*/
|
||||
QList<const Repository *> Manager::repositories() const
|
||||
{
|
||||
QList<const Repository *> repos;
|
||||
repos.reserve(m_syncDbs.size() + 1);
|
||||
for(const auto &dbEntry : m_syncDbs) {
|
||||
repos << dbEntry.second.get();
|
||||
}
|
||||
repos << m_userRepo.get();
|
||||
return repos;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns a list of all repositories excluding the local database.
|
||||
*/
|
||||
QList<Repository *> Manager::repositories()
|
||||
{
|
||||
QList<Repository *> repos;
|
||||
repos.reserve(m_syncDbs.size() + 1);
|
||||
for(auto &dbEntry : m_syncDbs) {
|
||||
repos << dbEntry.second.get();
|
||||
}
|
||||
repos << m_userRepo.get();
|
||||
return repos;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks the specified database for upgrades.
|
||||
*
|
||||
* Appropriate upgrade sources will be determined automatically; does not check the AUR.
|
||||
*/
|
||||
const UpgradeLookupResults Manager::checkForUpgrades(AlpmDataBase *db) const
|
||||
const UpgradeLookupResults Manager::checkForUpgrades(AlpmDatabase *db) const
|
||||
{
|
||||
UpgradeLookupResults results;
|
||||
db->checkForUpgrades(results);
|
||||
|
|
|
@ -14,11 +14,11 @@
|
|||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
namespace PackageManagement {
|
||||
namespace RepoIndex {
|
||||
|
||||
class Config;
|
||||
class UserRepository;
|
||||
class AlpmDataBase;
|
||||
class AlpmDatabase;
|
||||
|
||||
class Manager
|
||||
{
|
||||
|
@ -40,29 +40,34 @@ public:
|
|||
static int parseUsage(const std::string &usageStr);
|
||||
void applyPacmanConfig();
|
||||
void applyRepoIndexConfig();
|
||||
void initAlpmDataBases();
|
||||
|
||||
void unregisterSyncDataBases();
|
||||
const UserRepository *userRepository() const;
|
||||
UserRepository *userRepository();
|
||||
|
||||
// package lookup
|
||||
AlpmPackage *packageFromDataBase(const QString &dbName, const QString &pkgName);
|
||||
const AlpmPackage *packageFromDataBase(const QString &dbName, const QString &pkgName) const;
|
||||
AlpmPackage *packageFromSyncDataBases(const QString &pkgName);
|
||||
const AlpmPackage *packageFromSyncDataBases(const QString &pkgName) const;
|
||||
AlpmPackage *packageFromDatabase(const QString &dbName, const QString &pkgName);
|
||||
const AlpmPackage *packageFromDatabase(const QString &dbName, const QString &pkgName) const;
|
||||
AlpmPackage *packageFromSyncDatabases(const QString &pkgName);
|
||||
const AlpmPackage *packageFromSyncDatabases(const QString &pkgName) const;
|
||||
std::unique_ptr<AlpmOwnershipPackage> packageFromFile(const char *fileName, bool verifyIntegrity = false);
|
||||
Package *packageProviding(const Dependency &dependency);
|
||||
const Package *packageProviding(const Dependency &dependency) const;
|
||||
bool isPackageIgnored(const AlpmPackage *package) const;
|
||||
void setInstallReason(AlpmPackage *package, alpm_pkgreason_t reason);
|
||||
|
||||
// data base lookup
|
||||
const AlpmDataBase *localDataBase() const;
|
||||
AlpmDataBase *localDataBase();
|
||||
const std::map<QString, std::unique_ptr<AlpmDataBase> > &syncDataBases() const;
|
||||
const AlpmDataBase *dataBaseByName(const QString &dbName) const;
|
||||
AlpmDataBase *dataBaseByName(const QString &dbName);
|
||||
// repository lookup
|
||||
const AlpmDatabase *localDatabase() const;
|
||||
AlpmDatabase *localDatabase();
|
||||
const std::map<QString, std::unique_ptr<AlpmDatabase> > &syncDatabases() const;
|
||||
const AlpmDatabase *databaseByName(const QString &dbName) const;
|
||||
AlpmDatabase *databaseByName(const QString &dbName);
|
||||
const Repository *repositoryByName(const QString &name) const;
|
||||
Repository *repositoryByName(const QString &name);
|
||||
const UpgradeLookupResults checkForUpgrades(AlpmDataBase *db) const;
|
||||
const UserRepository *userRepository() const;
|
||||
UserRepository *userRepository();
|
||||
QList<const Repository *> repositories() const;
|
||||
QList<Repository *> repositories();
|
||||
const UpgradeLookupResults checkForUpgrades(AlpmDatabase *db) const;
|
||||
|
||||
// JSON serialization, handling JSON requests
|
||||
const QJsonObject basicRepoInfo(const Repository *packageSource) const;
|
||||
|
@ -80,8 +85,8 @@ private:
|
|||
QString m_pacmanCacheDir;
|
||||
QNetworkAccessManager m_networkAccessManager;
|
||||
std::unique_ptr<UserRepository> m_userRepo;
|
||||
std::unique_ptr<AlpmDataBase> m_localDb;
|
||||
std::map<QString, std::unique_ptr<AlpmDataBase> > m_syncDbs;
|
||||
std::unique_ptr<AlpmDatabase> m_localDb;
|
||||
std::map<QString, std::unique_ptr<AlpmDatabase> > m_syncDbs;
|
||||
mutable QJsonArray m_basicRepoInfo;
|
||||
mutable QMutex m_basicRepoInfoMutex;
|
||||
mutable QJsonArray m_groupInfo;
|
||||
|
@ -167,7 +172,7 @@ inline UserRepository *Manager::userRepository()
|
|||
/*!
|
||||
* \brief Returns the local data base.
|
||||
*/
|
||||
inline const AlpmDataBase *Manager::localDataBase() const
|
||||
inline const AlpmDatabase *Manager::localDatabase() const
|
||||
{
|
||||
return m_localDb.get();
|
||||
}
|
||||
|
@ -175,7 +180,7 @@ inline const AlpmDataBase *Manager::localDataBase() const
|
|||
/*!
|
||||
* \brief Returns the local data base.
|
||||
*/
|
||||
inline AlpmDataBase *Manager::localDataBase()
|
||||
inline AlpmDatabase *Manager::localDatabase()
|
||||
{
|
||||
return m_localDb.get();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "mingwbundle.h"
|
||||
#include "utilities.h"
|
||||
#include "manager.h"
|
||||
#include "config.h"
|
||||
|
||||
#include <c++utilities/conversion/stringconversion.h>
|
||||
#include <c++utilities/misc/memory.h>
|
||||
|
@ -20,7 +21,7 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
namespace PackageManagement {
|
||||
namespace RepoIndex {
|
||||
|
||||
using namespace Utilities;
|
||||
|
||||
|
@ -29,12 +30,12 @@ const string prefix("mingw-w64-");
|
|||
MingwBundle::MingwBundle(const Manager &manager, const ApplicationUtilities::StringVector &packages, const ApplicationUtilities::StringVector &iconPackages) :
|
||||
m_manager(manager)
|
||||
{
|
||||
cerr << "Resolving dependencies ..." << endl;
|
||||
cerr << shchar << "Resolving dependencies ..." << endl;
|
||||
string missing;
|
||||
// add mingw-w64 packages
|
||||
for(const auto &pkgName : packages) {
|
||||
bool found = false;
|
||||
for(const auto &syncDb : manager.syncDataBases()) {
|
||||
for(const auto &syncDb : manager.syncDatabases()) {
|
||||
if(auto *pkg = syncDb.second->packageByName(QString::fromLocal8Bit(ConversionUtilities::startsWith(pkgName, prefix) ? pkgName.data() : (prefix + pkgName).data()))) {
|
||||
if(missing.empty()) {
|
||||
decltype(m_packages)::value_type entry(syncDb.second.get(), pkg);
|
||||
|
@ -55,7 +56,7 @@ MingwBundle::MingwBundle(const Manager &manager, const ApplicationUtilities::Str
|
|||
// add additional icon packages
|
||||
for(const auto &pkgName : iconPackages) {
|
||||
bool found = false;
|
||||
for(const auto &syncDb : manager.syncDataBases()) {
|
||||
for(const auto &syncDb : manager.syncDatabases()) {
|
||||
if(auto *pkg = syncDb.second->packageByName(QString::fromLocal8Bit(pkgName.data()))) {
|
||||
if(missing.empty()) {
|
||||
decltype(m_packages)::value_type entry(syncDb.second.get(), pkg);
|
||||
|
@ -75,11 +76,11 @@ MingwBundle::MingwBundle(const Manager &manager, const ApplicationUtilities::Str
|
|||
if(!missing.empty()) {
|
||||
throw runtime_error("The following packages can not be found:" + missing);
|
||||
} else {
|
||||
cerr << "Adding the following packages:";
|
||||
cerr << shchar << "Adding the following packages:";
|
||||
for(const auto &pkg : m_packages) {
|
||||
cerr << ' ' << pkg.second->name().toLocal8Bit().data();
|
||||
cerr << shchar << ' ' << pkg.second->name().toLocal8Bit().data();
|
||||
}
|
||||
cerr << endl;
|
||||
cerr << shchar << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,7 +90,7 @@ void MingwBundle::addDependencies(const Package *pkg)
|
|||
for(const auto &dep : pkg->dependencies()) {
|
||||
if(dep.name.startsWith(QLatin1String("mingw-w64-"), Qt::CaseInsensitive)) {
|
||||
bool found = false;
|
||||
for(const auto &syncDbEntry : m_manager.syncDataBases()) {
|
||||
for(const auto &syncDbEntry : m_manager.syncDatabases()) {
|
||||
if(const auto *pkg = syncDbEntry.second->packageProviding(dep)) {
|
||||
if(missing.empty()) {
|
||||
decltype(m_packages)::value_type entry(syncDbEntry.second.get(), pkg);
|
||||
|
@ -284,7 +285,7 @@ void getFiles(PkgFileInfo &pkgFileInfo)
|
|||
|
||||
void MingwBundle::createBundle(const string &targetDir, const string &targetName, const string &targetFormat) const
|
||||
{
|
||||
cerr << "Gathering relevant files ..." << endl;
|
||||
cerr << shchar << "Gathering relevant files ..." << endl;
|
||||
// get package files
|
||||
list<PkgFileInfo> pkgFiles;
|
||||
for(const auto &entry : m_packages) {
|
||||
|
@ -333,7 +334,7 @@ void MingwBundle::createBundle(const string &targetDir, const string &targetName
|
|||
};
|
||||
for(const auto &root : roots) {
|
||||
QString targetPath = qstr(targetDir) % QChar('/') % root.second % QChar('-') % qstr(targetName) % QChar('.') % qstr(targetFormat);
|
||||
cerr << "Making archive \"" << targetPath.toLocal8Bit().data() << "\" ..." << endl;
|
||||
cerr << shchar << "Making archive \"" << targetPath.toLocal8Bit().data() << "\" ..." << endl;
|
||||
unique_ptr<KArchive> targetArchive;
|
||||
if(targetFormat == "7z") {
|
||||
targetArchive = make_unique<K7Zip>(targetPath);
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#include <QList>
|
||||
|
||||
namespace PackageManagement {
|
||||
namespace RepoIndex {
|
||||
|
||||
class Manager;
|
||||
|
||||
|
@ -23,7 +23,7 @@ private:
|
|||
void addDependencies(const Package *pkg);
|
||||
|
||||
const Manager &m_manager;
|
||||
std::list<std::pair<const AlpmDataBase *, const Package *> > m_packages;
|
||||
std::list<std::pair<const AlpmDatabase *, const Package *> > m_packages;
|
||||
};
|
||||
|
||||
} // namespace PackageManagement
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
using namespace std;
|
||||
using namespace ChronoUtilities;
|
||||
|
||||
namespace PackageManagement {
|
||||
namespace RepoIndex {
|
||||
|
||||
/*!
|
||||
* \class The Package class holds meta information about an
|
||||
|
@ -46,13 +46,16 @@ Package::~Package()
|
|||
|
||||
bool Package::matches(const QString &name, const QString &version, const Dependency &dependency)
|
||||
{
|
||||
if(name == QStringLiteral("gst-plugins-base-libs") && dependency.name == QStringLiteral("gst-plugins-base-libs")) {
|
||||
dependency.name.begin();
|
||||
}
|
||||
if(name == dependency.name) {
|
||||
PackageVersionComparsion cmp;
|
||||
switch(dependency.mode) {
|
||||
case ALPM_DEP_MOD_ANY:
|
||||
return true;
|
||||
case ALPM_DEP_MOD_EQ:
|
||||
return version == dependency.version;
|
||||
return PackageVersion(version).compare(PackageVersion(dependency.version)) == PackageVersionComparsion::Equal;
|
||||
case ALPM_DEP_MOD_GE:
|
||||
return (cmp = PackageVersion(version).compare(PackageVersion(dependency.version))) == PackageVersionComparsion::Equal || cmp == PackageVersionComparsion::NewerThenSyncVersion;
|
||||
case ALPM_DEP_MOD_LE:
|
||||
|
@ -234,15 +237,18 @@ PackageVersion::PackageVersion(const QString &versionStr)
|
|||
release = QString::fromUtf16(releaseBeg);
|
||||
} else {
|
||||
version = QString::fromUtf16(versionBeg);
|
||||
release = QStringLiteral("1");
|
||||
}
|
||||
} else {
|
||||
// epoch not present
|
||||
epoch = QStringLiteral("0");
|
||||
if(releaseBeg) {
|
||||
// release present
|
||||
version = QString::fromUtf16(str, releaseBeg - str - 1);
|
||||
release = QString::fromUtf16(releaseBeg);
|
||||
} else {
|
||||
version = QString::fromUtf16(str);
|
||||
release = QStringLiteral("1");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,17 +7,16 @@
|
|||
|
||||
#include <alpm.h>
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
#include <QString>
|
||||
#include <QHash>
|
||||
#include <QJsonArray>
|
||||
|
||||
#include <map>
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QJsonObject)
|
||||
QT_FORWARD_DECLARE_CLASS(QJsonValue)
|
||||
|
||||
namespace PackageManagement {
|
||||
namespace RepoIndex {
|
||||
|
||||
class Repository;
|
||||
|
||||
|
@ -77,7 +76,7 @@ public:
|
|||
class Dependency
|
||||
{
|
||||
public:
|
||||
explicit Dependency(const QString &name, const QString &version, _alpm_depmod_t mode = ALPM_DEP_MOD_ANY);
|
||||
explicit Dependency(const QString &name, const QString &version = QString(), _alpm_depmod_t mode = ALPM_DEP_MOD_ANY);
|
||||
QString name;
|
||||
QString version;
|
||||
_alpm_depmod_t mode;
|
||||
|
@ -145,6 +144,7 @@ public:
|
|||
ChronoUtilities::DateTime firstSubmitted() const;
|
||||
ChronoUtilities::DateTime lastModified() const;
|
||||
const QString &tarUrl() const;
|
||||
const std::map<QString, QByteArray> &sourceFiles() const;
|
||||
|
||||
// version comparsion
|
||||
PackageVersionComparsion compareVersion(const Package *syncPackage) const;
|
||||
|
@ -211,6 +211,7 @@ protected:
|
|||
ChronoUtilities::DateTime m_firstSubmitted;
|
||||
ChronoUtilities::DateTime m_lastModified;
|
||||
QString m_tarUrl;
|
||||
std::map<QString, QByteArray> m_sourceFiles;
|
||||
};
|
||||
|
||||
/*!
|
||||
|
@ -508,7 +509,7 @@ inline const QString &Package::baseName() const
|
|||
|
||||
/*!
|
||||
* \brief Returns the architecutes (from the PKGBUILD file).
|
||||
* \remarks For the architecture of the particular binary package
|
||||
* \remarks For the architecture of the particular package file
|
||||
* see buildArchitecture().
|
||||
*/
|
||||
inline const QStringList &Package::architectures() const
|
||||
|
@ -580,16 +581,33 @@ inline const QString &Package::tarUrl() const
|
|||
return m_tarUrl;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the source files of the package.
|
||||
*/
|
||||
inline const std::map<QString, QByteArray> &Package::sourceFiles() const
|
||||
{
|
||||
return m_sourceFiles;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Compares the version of the package with the specified sync package.
|
||||
*/
|
||||
inline PackageVersionComparsion Package::compareVersion(const Package *syncPackage) const
|
||||
{
|
||||
return PackageVersion(version()).compare(PackageVersion(syncPackage->version()));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Compares the version of the package with the version of the specified \a dependency.
|
||||
*/
|
||||
inline PackageVersionComparsion Package::compareVersion(const Dependency &dependency) const
|
||||
{
|
||||
return PackageVersion(version()).compare(PackageVersion(dependency.version));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the package matches the specified \a dependency.
|
||||
*/
|
||||
inline bool Package::matches(const Dependency &dependency)
|
||||
{
|
||||
return matches(name(), version(), dependency);
|
||||
|
|
|
@ -7,27 +7,40 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
namespace PackageManagement {
|
||||
namespace RepoIndex {
|
||||
|
||||
/*!
|
||||
* \brief Constructs a new reply.
|
||||
* \brief Constructs a new reply for a single network reply.
|
||||
*/
|
||||
Reply::Reply(QNetworkReply *networkReply) :
|
||||
m_networkReply(networkReply)
|
||||
Reply::Reply(QNetworkReply *networkReply)
|
||||
{
|
||||
networkReply->setParent(this);
|
||||
connect(networkReply, &QNetworkReply::finished, this, &Reply::processData);
|
||||
m_networkReplies.reserve(1);
|
||||
m_networkReplies << networkReply;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \fn PackageSource::type()
|
||||
* \brief Constructs a new reply for multiple network replies.
|
||||
*/
|
||||
Reply::Reply(const QList<QNetworkReply *> networkReplies) :
|
||||
m_networkReplies(networkReplies)
|
||||
{
|
||||
for(auto *networkReply : networkReplies) {
|
||||
networkReply->setParent(this);
|
||||
connect(networkReply, &QNetworkReply::finished, this, &Reply::processData);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \fn Repository::type()
|
||||
* \brief Returns the type of the package source.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Returns a list of all package names.
|
||||
*/
|
||||
const QStringList PackageManagement::Repository::packageNames() const
|
||||
const QStringList RepoIndex::Repository::packageNames() const
|
||||
{
|
||||
QStringList names;
|
||||
names.reserve(m_packages.size());
|
||||
|
@ -63,32 +76,26 @@ Repository::Repository(const QString &name, QObject *parent) :
|
|||
{}
|
||||
|
||||
/*!
|
||||
* \brief Destroys the package source.
|
||||
* \brief Destroys the repository.
|
||||
*/
|
||||
Repository::~Repository()
|
||||
{}
|
||||
|
||||
/*!
|
||||
* \brief Returns whether the repository only has sources but no binary packages.
|
||||
*/
|
||||
bool Repository::isSourceOnly() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns whether requests are required.
|
||||
* \brief Returns whether explicit requests are required to get the specified information
|
||||
* about the package of this repository.
|
||||
*
|
||||
* AlpmDataBase instances load all available packages in the cache
|
||||
* at the beginning and hence do not require explicit requests.
|
||||
* at the beginning and hence do not require explicit requests for package names, version,
|
||||
* description, dependencies and most other information. However make dependencies are not available at all.
|
||||
*
|
||||
* UserRepository instances on the other hand have an empty package
|
||||
* cache at the beginning so packages must be requested explicitely
|
||||
* using the requestPackageInfo() method.
|
||||
*/
|
||||
bool Repository::requestsRequired() const
|
||||
PackageDetailAvailability Repository::requestsRequired(PackageDetail ) const
|
||||
{
|
||||
return false;
|
||||
return PackageDetailAvailability::Never;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -116,7 +123,7 @@ PackageReply *Repository::requestPackageInfo(const QStringList &, bool ) const
|
|||
* requested again. If it turns out, that all packages are already cached, nullptr
|
||||
* is returned in this case.
|
||||
*/
|
||||
PackageReply *Repository::requestFullPackageInfo(const QString &, bool ) const
|
||||
PackageReply *Repository::requestFullPackageInfo(const QStringList &, bool ) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -143,6 +150,28 @@ const Package *Repository::packageProviding(const Dependency &dependency) const
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the first package providing the specified \a dependency.
|
||||
* \remarks Returns nullptr if no packages provides the \a dependency.
|
||||
*/
|
||||
Package *Repository::packageProviding(const Dependency &dependency)
|
||||
{
|
||||
for(auto &entry : m_packages) {
|
||||
if(entry.second->matches(dependency)) {
|
||||
// check whether package matches "directly"
|
||||
return entry.second.get();
|
||||
} else {
|
||||
// check whether at least one of the provides matches
|
||||
for(auto &provide : entry.second->provides()) {
|
||||
if(Package::matches(provide.name, provide.version, dependency)) {
|
||||
return entry.second.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns all packages providing the specified \a dependency.
|
||||
*/
|
||||
|
@ -267,7 +296,7 @@ QJsonObject Repository::basicInfo() const
|
|||
put(info, QStringLiteral("sigLevel"), Utilities::sigLevelStrings(sigLevel()));
|
||||
put(info, QStringLiteral("upgradeSources"), upgradeSourcesJsonArray());
|
||||
put(info, QStringLiteral("packages"), packageNamesJsonArray());
|
||||
put(info, QStringLiteral("requestRequired"), requestsRequired());
|
||||
put(info, QStringLiteral("requestRequired"), requestsRequired(PackageDetail::Basics) != PackageDetailAvailability::Immediately);
|
||||
put(info, QStringLiteral("srcOnly"), isSourceOnly());
|
||||
return info;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
QT_FORWARD_DECLARE_CLASS(QNetworkReply)
|
||||
|
||||
namespace PackageManagement {
|
||||
namespace RepoIndex {
|
||||
|
||||
class UpgradeLookupResults;
|
||||
|
||||
|
@ -20,6 +20,7 @@ class Reply : public QObject
|
|||
Q_OBJECT
|
||||
public:
|
||||
Reply(QNetworkReply *networkReply);
|
||||
Reply(const QList<QNetworkReply *> networkReplies);
|
||||
const QString &error() const;
|
||||
|
||||
signals:
|
||||
|
@ -29,7 +30,7 @@ private slots:
|
|||
virtual void processData() = 0;
|
||||
|
||||
protected:
|
||||
QNetworkReply *m_networkReply;
|
||||
QList<QNetworkReply *> m_networkReplies;
|
||||
QString m_error;
|
||||
};
|
||||
|
||||
|
@ -43,6 +44,7 @@ class PackageReply : public Reply
|
|||
Q_OBJECT
|
||||
public:
|
||||
PackageReply(QNetworkReply *networkReply, std::map<QString, std::unique_ptr<Package> > &packages);
|
||||
PackageReply(const QList<QNetworkReply *> &networkReplies, std::map<QString, std::unique_ptr<Package> > &packages);
|
||||
const std::map<QString, std::unique_ptr<Package> > &packages() const;
|
||||
|
||||
protected:
|
||||
|
@ -54,6 +56,11 @@ inline PackageReply::PackageReply(QNetworkReply *networkReply, std::map<QString,
|
|||
m_packages(packages)
|
||||
{}
|
||||
|
||||
inline PackageReply::PackageReply(const QList<QNetworkReply *> &networkReplies, std::map<QString, std::unique_ptr<Package> > &packages) :
|
||||
Reply(networkReplies),
|
||||
m_packages(packages)
|
||||
{}
|
||||
|
||||
inline const std::map<QString, std::unique_ptr<Package> > &PackageReply::packages() const
|
||||
{
|
||||
return m_packages;
|
||||
|
@ -79,13 +86,39 @@ inline const QJsonArray &SuggestionsReply::suggestions() const
|
|||
return m_suggestions;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief The RepositoryType enum specifies the type of a repository object.
|
||||
*/
|
||||
enum class RepositoryType
|
||||
{
|
||||
AlpmDataBase, /*! The repository is an AlpmDataBase instance. */
|
||||
AlpmDatabase, /*! The repository is an AlpmDataBase instance. */
|
||||
UserRepository, /*! The repository is a UserRepository instance. */
|
||||
Other /*! The repository type is unknown. */
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief The PackageDetail enum is used to refer to some kind of information about a package.
|
||||
*/
|
||||
enum class PackageDetail
|
||||
{
|
||||
Basics, /*! Basic information about the package such as knowing it exists, its name, version and description. */
|
||||
Dependencies, /*! The runtime dependencies of the package. */
|
||||
SourceInfo, /*! The source info such as make dependencies of the package. */
|
||||
PackageInfo /*! Information related to a specific package (pkg-file). */
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief The PackageDetailAvailability enum describes when some kind of information about a package
|
||||
* becomes available.
|
||||
*/
|
||||
enum class PackageDetailAvailability
|
||||
{
|
||||
Never, /*! The information is not available and can't be requested. */
|
||||
Immediately, /*! The information is available immediately after the repository object has been constructed. */
|
||||
Request, /*! The information is available after the requestPackageInfo() method has been called for the package. */
|
||||
FullRequest /*! The information is available after the requestFullPackageInfo() method has been called for the package. */
|
||||
};
|
||||
|
||||
class Repository : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -101,21 +134,23 @@ public:
|
|||
std::map<QString, std::unique_ptr<Package> > &packages();
|
||||
const QStringList packageNames() const;
|
||||
alpm_db_usage_t usage() const;
|
||||
virtual bool isSourceOnly() const;
|
||||
bool isSourceOnly() const;
|
||||
std::map<QString, QList<Package *> > &groups();
|
||||
const std::map<QString, QList<Package *> > &groups() const;
|
||||
const QStringList &serverUrls() const;
|
||||
alpm_siglevel_t sigLevel() const;
|
||||
|
||||
// gathering data
|
||||
virtual bool requestsRequired() const;
|
||||
virtual PackageDetailAvailability requestsRequired(PackageDetail packageDetail = PackageDetail::Basics) const;
|
||||
virtual SuggestionsReply *requestSuggestions(const QString &phrase) const;
|
||||
virtual PackageReply *requestPackageInfo(const QStringList &packageNames, bool forceUpdate = false) const;
|
||||
virtual PackageReply *requestFullPackageInfo(const QString &package, bool forceUpdate = false) const;
|
||||
virtual PackageReply *requestFullPackageInfo(const QStringList &package, bool forceUpdate = false) const;
|
||||
|
||||
// package search
|
||||
const Package *packageByName(const QString &name) const;
|
||||
Package *packageByName(const QString &name);
|
||||
const Package *packageProviding(const Dependency &dependency) const;
|
||||
Package *packageProviding(const Dependency &dependency);
|
||||
QList<const Package *> packagesProviding(const Dependency &dependency) const;
|
||||
QList<Package *> packageByFilter(std::function<bool (const Package *)> pred);
|
||||
|
||||
|
@ -168,6 +203,14 @@ inline const QString &Repository::description() const
|
|||
return m_description;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns whether the repository only has sources but no built packages.
|
||||
*/
|
||||
inline bool Repository::isSourceOnly() const
|
||||
{
|
||||
return requestsRequired(PackageDetail::PackageInfo) == PackageDetailAvailability::Never;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the packages.
|
||||
*/
|
||||
|
@ -215,6 +258,11 @@ inline alpm_db_usage_t Repository::usage() const
|
|||
return m_usage;
|
||||
}
|
||||
|
||||
inline std::map<QString, QList<Package *> > &Repository::groups()
|
||||
{
|
||||
return m_groups;
|
||||
}
|
||||
|
||||
inline const std::map<QString, QList<Package *> > &Repository::groups() const
|
||||
{
|
||||
return m_groups;
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
using namespace std;
|
||||
using namespace ApplicationUtilities;
|
||||
|
||||
namespace PackageManagement {
|
||||
namespace RepoIndex {
|
||||
|
||||
class TaskInfo
|
||||
{
|
||||
|
@ -19,6 +19,7 @@ public:
|
|||
TaskInfo(QString name, bool onlyDependency = false, const QList<TaskInfo *> &deps = QList<TaskInfo *>());
|
||||
|
||||
const QString &name() const;
|
||||
void setName(const QString &name);
|
||||
const QList<TaskInfo *> deps() const;
|
||||
void addDep(TaskInfo *dep);
|
||||
bool isDone() const;
|
||||
|
@ -49,6 +50,11 @@ inline const QString &TaskInfo::name() const
|
|||
return m_name;
|
||||
}
|
||||
|
||||
inline void TaskInfo::setName(const QString &name)
|
||||
{
|
||||
m_name = name;
|
||||
}
|
||||
|
||||
inline const QList<TaskInfo *> TaskInfo::deps() const
|
||||
{
|
||||
return m_deps;
|
||||
|
@ -76,26 +82,32 @@ inline bool TaskInfo::isOnlyDependency() const
|
|||
|
||||
void TaskInfo::add(QList<TaskInfo *> &results)
|
||||
{
|
||||
if(!m_done) {
|
||||
if(m_visited) {
|
||||
throw *this; // cyclic dependency
|
||||
if(!isDone()) {
|
||||
if(isVisited()) {
|
||||
// cyclic dependency
|
||||
if(isOnlyDependency()) {
|
||||
// if this is only a dependency (which we don't want to build) don't care about it
|
||||
return;
|
||||
} else {
|
||||
throw *this;
|
||||
}
|
||||
} else {
|
||||
m_visited = true;
|
||||
}
|
||||
for(auto *dep : m_deps) {
|
||||
for(auto *dep : deps()) {
|
||||
dep->add(results);
|
||||
}
|
||||
m_done = true;
|
||||
results << this;
|
||||
if(!isOnlyDependency()) {
|
||||
results << this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TaskInfo::addAll(const QList<TaskInfo *> &tasks, QList<TaskInfo *> &results)
|
||||
{
|
||||
for(auto *task : tasks) {
|
||||
if(!task->m_done) {
|
||||
task->add(results);
|
||||
}
|
||||
task->add(results);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -132,7 +144,7 @@ BuildOrderResolver::BuildOrderResolver(const Manager &manager) :
|
|||
|
||||
QStringList BuildOrderResolver::resolve(const StringVector &packages) const
|
||||
{
|
||||
cerr << "Getting package information ..." << endl;
|
||||
cerr << shchar << "Getting package information ..." << endl;
|
||||
QList<TaskInfo *> tasks;
|
||||
tasks.reserve(packages.size());
|
||||
try {
|
||||
|
@ -141,18 +153,20 @@ QStringList BuildOrderResolver::resolve(const StringVector &packages) const
|
|||
tasks << new TaskInfo(QString::fromLocal8Bit(pkgName.data()));
|
||||
}
|
||||
// find specified packages and their dependencies
|
||||
for(auto *task : tasks) {
|
||||
addDeps(tasks, task);
|
||||
for(int i = 0, size = tasks.size(); i != size; ++i) {
|
||||
addDeps(tasks, tasks.at(i));
|
||||
}
|
||||
cerr << "Relevant packages: ";
|
||||
for(const auto *task : tasks) {
|
||||
cerr << task->name().toLocal8Bit().data() << ' ';
|
||||
if(m_manager.config().isVerbose()) {
|
||||
cerr << shchar << "Relevant packages: ";
|
||||
for(const auto *task : tasks) {
|
||||
cerr << task->name().toLocal8Bit().data() << ' ';
|
||||
}
|
||||
cerr << endl;
|
||||
}
|
||||
cerr << endl;
|
||||
// topo sort
|
||||
QList<TaskInfo *> results;
|
||||
results.reserve(tasks.size());
|
||||
try {
|
||||
results.reserve(packages.size());
|
||||
TaskInfo::addAll(tasks, results);
|
||||
QStringList names;
|
||||
names.reserve(results.size());
|
||||
|
@ -171,30 +185,38 @@ QStringList BuildOrderResolver::resolve(const StringVector &packages) const
|
|||
|
||||
void BuildOrderResolver::addDeps(QList<TaskInfo *> &tasks, TaskInfo *task) const
|
||||
{
|
||||
if(const auto pkg = m_manager.packageFromSyncDataBases(task->name().toLocal8Bit().data())) {
|
||||
for(auto dep : pkg->dependencies()) {
|
||||
if(auto *depTask = addDep(tasks, dep.name)) {
|
||||
task->addDep(depTask);
|
||||
}
|
||||
}
|
||||
if(const auto pkg = m_manager.packageProviding(Dependency(task->name()))) {
|
||||
task->setName(pkg->name()); // update the name to ensure we have the acutal package name and not just a "provides" name
|
||||
addDeps(tasks, task, pkg->dependencies());
|
||||
} else {
|
||||
stringstream ss;
|
||||
ss << "The package \"" << task->name().toLocal8Bit().data() << "\" could not be found; TODO: search AUR for package, add AUR deps to the packages we want to build";
|
||||
ss << "The specified package \"" << task->name().toLocal8Bit().data() << "\" could not be found; TODO: search AUR for package, add AUR deps to the packages we want to build";
|
||||
throw runtime_error(ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
TaskInfo *BuildOrderResolver::addDep(QList<TaskInfo *> &tasks, const QString &depName) const
|
||||
void BuildOrderResolver::addDeps(QList<TaskInfo *> &tasks, TaskInfo *task, const QList<Dependency> &dependencies) const
|
||||
{
|
||||
if(auto *task = TaskInfo::find(tasks, depName)) {
|
||||
// we've already added a task for this dependency
|
||||
return task;
|
||||
} else {
|
||||
// create new task
|
||||
//task = new TaskInfo(QString::fromLocal8Bit(depName));
|
||||
//tasks << task;
|
||||
//return task;
|
||||
return nullptr;
|
||||
for(auto &dep : dependencies) {
|
||||
if(const auto depPkg = m_manager.packageProviding(dep)) {
|
||||
auto *depTask = TaskInfo::find(tasks, depPkg->name());
|
||||
if(depTask) {
|
||||
// we've already added a task for this dependency
|
||||
// adds dependency task to the dependencies of "parent" task
|
||||
task->addDep(depTask);
|
||||
} else {
|
||||
// create new task
|
||||
tasks << (depTask = new TaskInfo(depPkg->name(), true));
|
||||
// adds dependency task to the dependencies of "parent" task
|
||||
task->addDep(depTask);
|
||||
// add dependencies of the dependency
|
||||
addDeps(tasks, depTask, depPkg->dependencies());
|
||||
}
|
||||
} else {
|
||||
stringstream ss;
|
||||
ss << "The dependency \"" << dep.name.toLocal8Bit().data() << "\" could not be found; TODO: search AUR for package, add AUR deps to the packages we want to build";
|
||||
throw runtime_error(ss.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,10 +6,11 @@
|
|||
#include <QString>
|
||||
#include <QList>
|
||||
|
||||
namespace PackageManagement {
|
||||
namespace RepoIndex {
|
||||
|
||||
class Manager;
|
||||
class TaskInfo;
|
||||
class Dependency;
|
||||
|
||||
class BuildOrderResolver
|
||||
{
|
||||
|
@ -20,7 +21,7 @@ public:
|
|||
|
||||
private:
|
||||
void addDeps(QList<TaskInfo *> &tasks, TaskInfo *task) const;
|
||||
TaskInfo *addDep(QList<TaskInfo *> &pkgInfos, const QString &depName) const;
|
||||
void addDeps(QList<TaskInfo *> &tasks, TaskInfo *task, const QList<Dependency> &dependencies) const;
|
||||
const Manager &m_manager;
|
||||
};
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
namespace PackageManagement {
|
||||
namespace RepoIndex {
|
||||
|
||||
QJsonObject UpgradeResult::json() const
|
||||
{
|
||||
|
@ -27,14 +27,26 @@ UpgradeLookupProcess::UpgradeLookupProcess(UpgradeLookup *upgradeLookup, const R
|
|||
m_watcher(new QFutureWatcher<void>(this))
|
||||
{
|
||||
connect(this, &UpgradeLookupProcess::finished, upgradeLookup, &UpgradeLookup::processFinished);
|
||||
if(m_upgradeSource->requestsRequired()) {
|
||||
if((m_reply = m_upgradeSource->requestPackageInfo(m_toCheck->packageNames()))) {
|
||||
m_reply->setParent(this);
|
||||
connect(m_reply, &PackageReply::resultsAvailable, this, &UpgradeLookupProcess::sourceReady);
|
||||
return;
|
||||
}
|
||||
switch(m_upgradeSource->requestsRequired()) {
|
||||
case PackageDetailAvailability::Request:
|
||||
m_reply = m_upgradeSource->requestPackageInfo(m_toCheck->packageNames());
|
||||
break;
|
||||
case PackageDetailAvailability::FullRequest:
|
||||
m_reply = m_upgradeSource->requestFullPackageInfo(m_toCheck->packageNames());
|
||||
break;
|
||||
case PackageDetailAvailability::Never:
|
||||
m_results.errors << QStringLiteral("Repository \"%1\" does not provide the required information.").arg(m_upgradeSource->name());
|
||||
emit finished();
|
||||
return;
|
||||
case PackageDetailAvailability::Immediately:
|
||||
break;
|
||||
}
|
||||
if(m_reply) {
|
||||
m_reply->setParent(this);
|
||||
connect(m_reply, &PackageReply::resultsAvailable, this, &UpgradeLookupProcess::sourceReady);
|
||||
} else {
|
||||
sourceReady();
|
||||
}
|
||||
sourceReady();
|
||||
}
|
||||
|
||||
const UpgradeLookupResults &UpgradeLookupProcess::results() const
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include <QJsonArray>
|
||||
#include <QFutureWatcher>
|
||||
|
||||
namespace PackageManagement {
|
||||
namespace RepoIndex {
|
||||
|
||||
class Manager;
|
||||
class UpgradeLookup;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
namespace PackageManagement {
|
||||
namespace RepoIndex {
|
||||
|
||||
namespace Utilities {
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
QT_FORWARD_DECLARE_CLASS(QJsonArray)
|
||||
|
||||
namespace PackageManagement {
|
||||
namespace RepoIndex {
|
||||
|
||||
namespace Utilities {
|
||||
|
||||
|
|
51
main.cpp
51
main.cpp
|
@ -7,6 +7,7 @@
|
|||
#include "network/server.h"
|
||||
|
||||
#include <c++utilities/application/argumentparser.h>
|
||||
#include <c++utilities/conversion/stringconversion.h>
|
||||
#include <c++utilities/application/failure.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
|
@ -16,11 +17,18 @@
|
|||
|
||||
using namespace std;
|
||||
using namespace ApplicationUtilities;
|
||||
using namespace PackageManagement;
|
||||
using namespace Network;
|
||||
using namespace RepoIndex;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// check whether shell syntax is enabled
|
||||
for(char **arg = argv, **end = argv + argc; arg != end; ++arg) {
|
||||
if(strcmp(*arg, "--sh-syntax") == 0) {
|
||||
useShSyntax = true;
|
||||
shchar = "# ";
|
||||
break;
|
||||
}
|
||||
}
|
||||
// setup the argument parser
|
||||
ArgumentParser parser;
|
||||
ConfigArgs configArgs(parser);
|
||||
|
@ -29,7 +37,7 @@ int main(int argc, char *argv[])
|
|||
try {
|
||||
parser.parseArgs(argc, argv);
|
||||
} catch (Failure &e) {
|
||||
cerr << "Unable to parse arguments: " << e.what() << endl;
|
||||
cerr << shchar << "Unable to parse arguments: " << e.what() << endl;
|
||||
return 2;
|
||||
}
|
||||
try {
|
||||
|
@ -40,13 +48,14 @@ int main(int argc, char *argv[])
|
|||
if(find_if(parser.mainArguments().cbegin(), parser.mainArguments().cend(), [&configArgs] (const Argument *arg) {
|
||||
return arg != &configArgs.helpArg && arg->isPresent();
|
||||
}) != parser.mainArguments().cend()) {
|
||||
cerr << "Loading databases ..." << endl;
|
||||
// create app
|
||||
QCoreApplication application(argc, argv);
|
||||
// setup ALPM
|
||||
Manager manager(config);
|
||||
manager.applyPacmanConfig();
|
||||
manager.applyRepoIndexConfig();
|
||||
cerr << shchar << "Loading databases ..." << endl;
|
||||
manager.initAlpmDataBases();
|
||||
if(configArgs.serverArg.isPresent()) {
|
||||
// setup the server
|
||||
Server server(manager, manager.config());
|
||||
|
@ -57,22 +66,42 @@ int main(int argc, char *argv[])
|
|||
BuildOrderResolver resolver(manager);
|
||||
const QStringList results = resolver.resolve(configArgs.buildOrderArg.values());
|
||||
// print results
|
||||
cout << "Results: ";
|
||||
for(const auto &pkgName : results) {
|
||||
cout << pkgName.toLocal8Bit().data() << ' ';
|
||||
if(useShSyntax) {
|
||||
cout << "export REPOINDEX_RESULTS=(";
|
||||
for(const auto &pkgName : results) {
|
||||
cout << ' ' << '\'' << pkgName.toLocal8Bit().data() << '\'';
|
||||
}
|
||||
cout << ' ' << ')' << endl;
|
||||
} else {
|
||||
cout << "Results: ";
|
||||
for(const auto &pkgName : results) {
|
||||
cout << pkgName.toLocal8Bit().data() << ' ';
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
cout << endl;
|
||||
} else if(configArgs.mingwBundleArg.isPresent()) {
|
||||
MingwBundle bundle(manager, configArgs.mingwBundleArg.values(), configArgs.iconThemesArg.values());
|
||||
bundle.createBundle(configArgs.targetDirArg.isPresent() ? configArgs.targetDirArg.values().front() : string("."),
|
||||
configArgs.targetNameArg.values().front(),
|
||||
configArgs.targetFormatArg.isPresent() ? configArgs.targetFormatArg.values().front() : string("zip"));
|
||||
} else if(configArgs.upgradeLookupArg.isPresent()) {
|
||||
cerr << shchar << "TODO" << endl;
|
||||
}
|
||||
} else if(!configArgs.helpArg.isPresent()) {
|
||||
if(useShSyntax) {
|
||||
cerr << "export REPOINDEX_ERROR='No command line arguments specified. See --help for available commands.'" << endl;
|
||||
} else {
|
||||
cerr << "No command line arguments specified. See --help for available commands." << endl;
|
||||
}
|
||||
} else {
|
||||
cout << "No command line arguments specified. See --help for available commands." << endl;
|
||||
}
|
||||
} catch (std::exception &e) {
|
||||
cerr << "Error: " << e.what() << endl;
|
||||
if(useShSyntax) {
|
||||
string error = e.what();
|
||||
ConversionUtilities::findAndReplace<string>(error, "'", "\'");
|
||||
cerr << "export REPOINDEX_ERROR='" << error << '\'' << endl;
|
||||
} else {
|
||||
cerr << shchar << "Error: " << e.what() << endl;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,9 +8,7 @@
|
|||
#include <QJsonArray>
|
||||
#include <QWebSocket>
|
||||
|
||||
using namespace PackageManagement;
|
||||
|
||||
namespace Network {
|
||||
namespace RepoIndex {
|
||||
|
||||
Connection::Connection(const Manager &alpmManager, QWebSocket *socket, QObject *parent) :
|
||||
QObject(parent),
|
||||
|
|
|
@ -7,18 +7,16 @@
|
|||
|
||||
QT_FORWARD_DECLARE_CLASS(QWebSocket)
|
||||
|
||||
namespace PackageManagement {
|
||||
class Manager;
|
||||
}
|
||||
namespace RepoIndex {
|
||||
|
||||
namespace Network {
|
||||
class Manager;
|
||||
|
||||
class Connection : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Connection(const PackageManagement::Manager &alpmManager, QWebSocket *socket, QObject *parent = nullptr);
|
||||
Connection(const RepoIndex::Manager &alpmManager, QWebSocket *socket, QObject *parent = nullptr);
|
||||
|
||||
private slots:
|
||||
void processTextMessage(const QString &message);
|
||||
|
@ -33,7 +31,7 @@ private:
|
|||
void handleQuery(const QJsonObject &obj);
|
||||
|
||||
QWebSocket *m_socket;
|
||||
const PackageManagement::Manager &m_alpmManager;
|
||||
const RepoIndex::Manager &m_alpmManager;
|
||||
bool m_repoInfoUpdatesRequested;
|
||||
bool m_groupInfoUpdatesRequested;
|
||||
|
||||
|
|
|
@ -12,9 +12,9 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
namespace Network {
|
||||
namespace RepoIndex {
|
||||
|
||||
Server::Server(const PackageManagement::Manager &alpmManager, const PackageManagement::Config &config, QObject *parent) :
|
||||
Server::Server(const RepoIndex::Manager &alpmManager, const RepoIndex::Config &config, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_server(new QWebSocketServer(QStringLiteral("Repository index server"),
|
||||
config.serverInsecure() ? QWebSocketServer::NonSecureMode : QWebSocketServer::SecureMode,
|
||||
|
@ -48,11 +48,11 @@ Server::Server(const PackageManagement::Manager &alpmManager, const PackageManag
|
|||
sslConfiguration.setProtocol(QSsl::TlsV1SslV3);
|
||||
m_server->setSslConfiguration(sslConfiguration);
|
||||
} else {
|
||||
cerr << "Warning: The server is running in insecure mode." << endl;
|
||||
cerr << shchar << "Warning: The server is running in insecure mode." << endl;
|
||||
}
|
||||
// start listening
|
||||
if(m_server->listen(config.websocketServerListeningAddr(), config.websocketServerListeningPort())) {
|
||||
cerr << m_server->serverName().toLocal8Bit().data() << " is listening on port " << m_server->serverPort() << endl;
|
||||
cerr << shchar << m_server->serverName().toLocal8Bit().data() << " is listening on port " << m_server->serverPort() << endl;
|
||||
connect(m_server, &QWebSocketServer::newConnection, this, &Server::incomingConnection);
|
||||
connect(m_server, &QWebSocketServer::closed, this, &Server::closed);
|
||||
} else {
|
||||
|
|
|
@ -6,14 +6,14 @@
|
|||
#include <QHostAddress>
|
||||
#include <QWebSocketServer>
|
||||
|
||||
namespace PackageManagement {
|
||||
namespace RepoIndex {
|
||||
|
||||
class Config;
|
||||
class Manager;
|
||||
|
||||
}
|
||||
|
||||
namespace Network {
|
||||
namespace RepoIndex {
|
||||
|
||||
class Connection;
|
||||
|
||||
|
@ -22,7 +22,7 @@ class Server : public QObject
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Server(const PackageManagement::Manager &alpmManager, const PackageManagement::Config &config, QObject *parent = nullptr);
|
||||
Server(const RepoIndex::Manager &alpmManager, const RepoIndex::Config &config, QObject *parent = nullptr);
|
||||
~Server();
|
||||
|
||||
signals:
|
||||
|
@ -34,7 +34,7 @@ private slots:
|
|||
|
||||
private:
|
||||
QWebSocketServer *m_server;
|
||||
const PackageManagement::Manager &m_alpmManager;
|
||||
const RepoIndex::Manager &m_alpmManager;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
namespace PackageManagement {
|
||||
namespace RepoIndex {
|
||||
|
||||
const char *requestTypeProp = "type";
|
||||
const QString rpcRequestTypeKey(QStringLiteral("type"));
|
||||
|
@ -27,6 +27,7 @@ const QString pkgbuildRequestType(QString("pkgbuild"));
|
|||
QUrl UserRepository::m_aurRpcUrl = QUrl(QStringLiteral("https://aur.archlinux.org/rpc.php"));
|
||||
QUrl UserRepository::m_aurPkgbuildUrl = QUrl(QStringLiteral("https://aur.archlinux.org/cgit/aur.git/plain/PKGBUILD"));
|
||||
QUrl UserRepository::m_aurSrcInfoUrl = QUrl(QStringLiteral("https://aur.archlinux.org/cgit/aur.git/plain/.SRCINFO"));
|
||||
QString UserRepository::m_aurSnapshotPath = QStringLiteral("https://aur.archlinux.org/cgit/aur.git/snapshot/%1.tar.gz");
|
||||
|
||||
AurPackageReply::AurPackageReply(QNetworkReply *networkReply, UserRepository *userRepo) :
|
||||
PackageReply(networkReply, userRepo->packages()),
|
||||
|
@ -35,12 +36,13 @@ AurPackageReply::AurPackageReply(QNetworkReply *networkReply, UserRepository *us
|
|||
|
||||
void AurPackageReply::processData()
|
||||
{
|
||||
if(m_networkReply->error() == QNetworkReply::NoError) {
|
||||
auto *reply = m_networkReplies.front();
|
||||
if(reply->error() == QNetworkReply::NoError) {
|
||||
QJsonParseError error;
|
||||
//QByteArray data = m_networkReply->readAll();
|
||||
//cerr << "AUR reply: " << data.data() << endl;
|
||||
//cerr << shchar << "AUR reply: " << data.data() << endl;
|
||||
//const QJsonDocument doc = QJsonDocument::fromJson(data, &error);
|
||||
const QJsonDocument doc = QJsonDocument::fromJson(m_networkReply->readAll(), &error);
|
||||
const QJsonDocument doc = QJsonDocument::fromJson(reply->readAll(), &error);
|
||||
if(error.error == QJsonParseError::NoError) {
|
||||
for(const auto &result : doc.object().value(QStringLiteral("results")).toArray()) {
|
||||
auto package = make_unique<AurPackage>(result, m_userRepo);
|
||||
|
@ -52,30 +54,42 @@ void AurPackageReply::processData()
|
|||
m_error = QStringLiteral("Error: Unable to parse JSON received from AUR: ") % error.errorString() % QStringLiteral(" at character ") % QString::number(error.offset);
|
||||
}
|
||||
} else {
|
||||
m_error = QStringLiteral("Error: Unable to request data from AUR: ") + m_networkReply->errorString();
|
||||
m_error = QStringLiteral("Error: Unable to request data from AUR: ") + reply->errorString();
|
||||
}
|
||||
emit resultsAvailable();
|
||||
}
|
||||
|
||||
AurFullPackageReply::AurFullPackageReply(const QList<QNetworkReply *> &networkReplies, UserRepository *userRepo) :
|
||||
PackageReply(networkReplies, userRepo->packages()),
|
||||
m_userRepo(userRepo)
|
||||
{}
|
||||
|
||||
void AurFullPackageReply::processData()
|
||||
{
|
||||
//auto *reply = static_cast<QNetworkReply *>(sender());
|
||||
// TODO
|
||||
}
|
||||
|
||||
AurSuggestionsReply::AurSuggestionsReply(QNetworkReply *networkReply) :
|
||||
SuggestionsReply(networkReply)
|
||||
{}
|
||||
|
||||
void AurSuggestionsReply::processData()
|
||||
{
|
||||
if(m_networkReply->error() == QNetworkReply::NoError) {
|
||||
auto *reply = m_networkReplies.front();
|
||||
if(reply->error() == QNetworkReply::NoError) {
|
||||
QJsonParseError error;
|
||||
//QByteArray data = m_networkReply->readAll();
|
||||
//cerr << "AUR reply: " << data.data() << endl;
|
||||
//cerr << shchar << "AUR reply: " << data.data() << endl;
|
||||
//const QJsonDocument doc = QJsonDocument::fromJson(data, &error);
|
||||
const QJsonDocument doc = QJsonDocument::fromJson(m_networkReply->readAll(), &error);
|
||||
const QJsonDocument doc = QJsonDocument::fromJson(reply->readAll(), &error);
|
||||
if(error.error == QJsonParseError::NoError) {
|
||||
m_suggestions = doc.array();
|
||||
} else {
|
||||
m_error = QStringLiteral("Error: Unable to parse JSON received from AUR: ") % error.errorString() % QStringLiteral(" at character ") % QString::number(error.offset);
|
||||
}
|
||||
} else {
|
||||
m_error = QStringLiteral("Error: Unable to request data from AUR: ") + m_networkReply->errorString();
|
||||
m_error = QStringLiteral("Error: Unable to request data from AUR: ") + reply->errorString();
|
||||
}
|
||||
emit resultsAvailable();
|
||||
}
|
||||
|
@ -92,9 +106,17 @@ RepositoryType UserRepository::type() const
|
|||
return RepositoryType::UserRepository;
|
||||
}
|
||||
|
||||
bool UserRepository::requestsRequired() const
|
||||
PackageDetailAvailability UserRepository::requestsRequired(PackageDetail packageDetail) const
|
||||
{
|
||||
return true;
|
||||
switch(packageDetail) {
|
||||
case PackageDetail::Basics:
|
||||
return PackageDetailAvailability::Request;
|
||||
case PackageDetail::Dependencies:
|
||||
case PackageDetail::SourceInfo:
|
||||
return PackageDetailAvailability::FullRequest;
|
||||
case PackageDetail::PackageInfo:
|
||||
return PackageDetailAvailability::Never;
|
||||
}
|
||||
}
|
||||
|
||||
AurSuggestionsReply *UserRepository::requestSuggestions(const QString &phrase) const
|
||||
|
@ -125,20 +147,24 @@ AurPackageReply *UserRepository::requestPackageInfo(const QStringList &packageNa
|
|||
}
|
||||
}
|
||||
|
||||
AurPackageReply *UserRepository::requestFullPackageInfo(const QString &package, bool forceUpdate) const
|
||||
AurFullPackageReply *UserRepository::requestFullPackageInfo(const QStringList &packageNames, bool forceUpdate) const
|
||||
{
|
||||
try {
|
||||
const auto &pkg = m_packages.at(package);
|
||||
if(pkg->hasGeneralInfo() && !forceUpdate) {
|
||||
return nullptr;
|
||||
QList<QNetworkReply *> replies;
|
||||
for(const auto &packageName : packageNames) {
|
||||
try {
|
||||
const auto &pkg = m_packages.at(packageName);
|
||||
if(!pkg->hasGeneralInfo() || !pkg->hasSourceRelatedMetaData() || forceUpdate) {
|
||||
if(pkg->tarUrl().isEmpty()) {
|
||||
replies << m_networkAccessManager.get(QNetworkRequest(m_aurSnapshotPath.arg(pkg->name())));
|
||||
} else {
|
||||
replies << m_networkAccessManager.get(QNetworkRequest(pkg->tarUrl()));
|
||||
}
|
||||
}
|
||||
} catch(const out_of_range &) {
|
||||
replies << m_networkAccessManager.get(QNetworkRequest(m_aurSnapshotPath.arg(packageName)));
|
||||
}
|
||||
} catch(const out_of_range &) {
|
||||
}
|
||||
auto url = m_aurPkgbuildUrl;
|
||||
QUrlQuery query;
|
||||
query.addQueryItem(QStringLiteral("h"), package);
|
||||
url.setQuery(query);
|
||||
return new AurPackageReply(m_networkAccessManager.get(QNetworkRequest(url)), const_cast<UserRepository *>(this));
|
||||
return new AurFullPackageReply(replies, const_cast<UserRepository *>(this));
|
||||
}
|
||||
|
||||
} // namespace Alpm
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
QT_FORWARD_DECLARE_CLASS(QNetworkAccessManager)
|
||||
QT_FORWARD_DECLARE_CLASS(QNetworkReply)
|
||||
|
||||
namespace PackageManagement {
|
||||
namespace RepoIndex {
|
||||
|
||||
class UserRepository;
|
||||
|
||||
|
@ -22,7 +22,19 @@ class AurPackageReply : public PackageReply
|
|||
Q_OBJECT
|
||||
public:
|
||||
AurPackageReply(QNetworkReply *networkReply, UserRepository *userRepo);
|
||||
const std::map<QString, std::unique_ptr<Package> > &packages() const;
|
||||
|
||||
private slots:
|
||||
void processData();
|
||||
|
||||
private:
|
||||
UserRepository *m_userRepo;
|
||||
};
|
||||
|
||||
class AurFullPackageReply : public PackageReply
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AurFullPackageReply(const QList<QNetworkReply *> &networkReplies, UserRepository *userRepo);
|
||||
|
||||
private slots:
|
||||
void processData();
|
||||
|
@ -52,16 +64,17 @@ public:
|
|||
static const QUrl aurRpcUrl();
|
||||
static void setAurRpcUrl(const QUrl &aurRpcUrl);
|
||||
|
||||
bool requestsRequired() const;
|
||||
PackageDetailAvailability requestsRequired(PackageDetail packageDetail) const;
|
||||
AurSuggestionsReply *requestSuggestions(const QString &phrase) const;
|
||||
AurPackageReply *requestPackageInfo(const QStringList &packageNames, bool forceUpdate = false) const;
|
||||
AurPackageReply *requestFullPackageInfo(const QString &package, bool forceUpdate = false) const;
|
||||
AurFullPackageReply *requestFullPackageInfo(const QStringList &packageNames, bool forceUpdate = false) const;
|
||||
|
||||
private:
|
||||
QNetworkAccessManager &m_networkAccessManager;
|
||||
QNetworkAccessManager &m_networkAccessManager;
|
||||
static QUrl m_aurRpcUrl;
|
||||
static QUrl m_aurPkgbuildUrl;
|
||||
static QUrl m_aurSrcInfoUrl;
|
||||
static QString m_aurSnapshotPath;
|
||||
};
|
||||
|
||||
inline const QUrl UserRepository::aurRpcUrl()
|
||||
|
|
Loading…
Reference in New Issue