restructured a lot of classes
This commit is contained in:
parent
8f32dd0da0
commit
c6d3ea2d8e
|
@ -0,0 +1,90 @@
|
||||||
|
#include "alpmdatabase.h"
|
||||||
|
#include "group.h"
|
||||||
|
#include "upgradelookup.h"
|
||||||
|
#include "alpmpackage.h"
|
||||||
|
#include "utilities.h"
|
||||||
|
|
||||||
|
#include <c++utilities/misc/memory.h>
|
||||||
|
|
||||||
|
#include <QList>
|
||||||
|
#include <QJsonObject>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace PackageManagement {
|
||||||
|
|
||||||
|
using namespace Utilities;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief The AlpmDataBase class wraps an ALPM data base struct and holds additional meta information.
|
||||||
|
*
|
||||||
|
* All packages returned by the AlpmDataBase class are AlpmPackage instances.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Creates a new instance wrapping the specified database struct.
|
||||||
|
*/
|
||||||
|
PackageManagement::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))
|
||||||
|
{
|
||||||
|
if(alpm_db_get_usage(dataBase, &m_usage)) {
|
||||||
|
m_usage = static_cast<decltype(m_usage)>(ALPM_DB_USAGE_ALL);
|
||||||
|
}
|
||||||
|
if(m_name.compare(QLatin1String("local"), Qt::CaseInsensitive) == 0) {
|
||||||
|
m_description = QStringLiteral("The local database");
|
||||||
|
} else {
|
||||||
|
if((m_usage & ALPM_DB_USAGE_SYNC) || (m_usage & ALPM_DB_USAGE_INSTALL) || (m_usage & ALPM_DB_USAGE_UPGRADE)) {
|
||||||
|
m_description = QStringLiteral("Sync database »%1«").arg(m_name);
|
||||||
|
} else {
|
||||||
|
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(const char *str : servers()) {
|
||||||
|
m_serverUrls << qstr(str);
|
||||||
|
}
|
||||||
|
m_sigLevel = alpm_db_get_siglevel(m_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
//AlpmDataBase::AlpmDataBase(const QString &dataBaseFile, QObject *parent) :
|
||||||
|
// PackageSource(parent),
|
||||||
|
// m_ptr(nullptr)
|
||||||
|
//{}
|
||||||
|
|
||||||
|
RepositoryType AlpmDataBase::type() const
|
||||||
|
{
|
||||||
|
return RepositoryType::AlpmDataBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AlpmDataBase::isSourceOnly() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Adds the specified server URLs.
|
||||||
|
*/
|
||||||
|
bool AlpmDataBase::addServerUrls(const QStringList &urls)
|
||||||
|
{
|
||||||
|
bool res = true;
|
||||||
|
for(const auto &url : urls) {
|
||||||
|
if(alpm_db_add_server(m_ptr, url.toLocal8Bit().data()) != 0) {
|
||||||
|
res = false;
|
||||||
|
} else {
|
||||||
|
m_serverUrls << url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Alpm
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
#ifndef ALPM_DATABASE_H
|
||||||
|
#define ALPM_DATABASE_H
|
||||||
|
|
||||||
|
#include "repository.h"
|
||||||
|
#include "list.h"
|
||||||
|
|
||||||
|
#include <alpm.h>
|
||||||
|
|
||||||
|
#include <QJsonArray>
|
||||||
|
|
||||||
|
namespace PackageManagement {
|
||||||
|
|
||||||
|
class AlpmDataBase : public Repository
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit AlpmDataBase(alpm_db_t *dataBase, const QString &dbPath, QObject *parent = nullptr);
|
||||||
|
// explicit AlpmDataBase(const QString &dataBaseFile, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
RepositoryType type() const;
|
||||||
|
bool isSourceOnly() const;
|
||||||
|
|
||||||
|
// operators
|
||||||
|
bool operator ==(const AlpmDataBase &other) const;
|
||||||
|
bool operator !=(const AlpmDataBase &other) const;
|
||||||
|
|
||||||
|
// database meta data
|
||||||
|
alpm_db_t *ptr();
|
||||||
|
const QString &dataBaseFile() const;
|
||||||
|
StringList servers() const;
|
||||||
|
bool setServers(StringList servers);
|
||||||
|
bool addServerUrls(const QStringList &urls);
|
||||||
|
PackageList search(StringList terms) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
alpm_db_t *m_ptr;
|
||||||
|
QString m_dbFile;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Checks whether the specified ALPM database is equal the current instance.
|
||||||
|
*/
|
||||||
|
inline bool AlpmDataBase::operator ==(const AlpmDataBase &other) const
|
||||||
|
{
|
||||||
|
return m_ptr == other.m_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Checks whether the specified ALPM database is not equal to the current instance.
|
||||||
|
*/
|
||||||
|
inline bool AlpmDataBase::operator !=(const AlpmDataBase &other) const
|
||||||
|
{
|
||||||
|
return m_ptr != other.m_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the pointer to the underlying database struct.
|
||||||
|
*/
|
||||||
|
inline alpm_db_t *AlpmDataBase::ptr()
|
||||||
|
{
|
||||||
|
return m_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the path of the data base file.
|
||||||
|
*/
|
||||||
|
inline const QString &AlpmDataBase::dataBaseFile() const
|
||||||
|
{
|
||||||
|
return m_dbFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the servers of the database.
|
||||||
|
*/
|
||||||
|
inline StringList AlpmDataBase::servers() const
|
||||||
|
{
|
||||||
|
return alpm_db_get_servers(m_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Sets the servers of the database.
|
||||||
|
*/
|
||||||
|
inline bool AlpmDataBase::setServers(StringList servers)
|
||||||
|
{
|
||||||
|
return alpm_db_set_servers(m_ptr, servers.begin().ptr()) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Performs a search using the build in ALPM function.
|
||||||
|
*/
|
||||||
|
inline PackageList AlpmDataBase::search(StringList terms) const
|
||||||
|
{
|
||||||
|
return alpm_db_search(m_ptr, terms.begin().ptr());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Alpm
|
||||||
|
|
||||||
|
#endif // ALPM_DATABASE_H
|
|
@ -0,0 +1,92 @@
|
||||||
|
#include "alpmpackage.h"
|
||||||
|
#include "alpmdatabase.h"
|
||||||
|
#include "utilities.h"
|
||||||
|
|
||||||
|
#include <QJsonObject>
|
||||||
|
|
||||||
|
using namespace ChronoUtilities;
|
||||||
|
|
||||||
|
namespace PackageManagement {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \cond
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Utilities {
|
||||||
|
|
||||||
|
inline QList<Dependency> depinfos(DependencyList list)
|
||||||
|
{
|
||||||
|
QList<Dependency> infos;
|
||||||
|
for(const auto *dep : list) {
|
||||||
|
infos << Dependency(qstr(dep->name), qstr(dep->version), dep->mod);
|
||||||
|
}
|
||||||
|
return infos;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \endcond
|
||||||
|
*/
|
||||||
|
|
||||||
|
using namespace Utilities;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief The AlpmPackage class wraps an ALPM package struct and holds additional meta information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Constructs a new package instance for the specified ALPM \a package.
|
||||||
|
*/
|
||||||
|
AlpmPackage::AlpmPackage(alpm_pkg_t *package, AlpmDataBase *source) :
|
||||||
|
Package(QString::fromLocal8Bit(alpm_pkg_get_name(package)), source),
|
||||||
|
m_ptr(package)
|
||||||
|
{
|
||||||
|
m_origin = static_cast<PackageOrigin>(alpm_pkg_get_origin(package));
|
||||||
|
m_hasGeneralInfo = m_hasBuildRelatedMetaData = m_hasInstallRelatedMetaData = true;
|
||||||
|
m_version = qstr(alpm_pkg_get_version(package));
|
||||||
|
m_description = qstr(alpm_pkg_get_desc(package));
|
||||||
|
m_upstreamUrl = qstr(alpm_pkg_get_url(package));
|
||||||
|
m_licenses = qstrlist(alpm_pkg_get_licenses(package));
|
||||||
|
m_groups = qstrlist(alpm_pkg_get_groups(package));
|
||||||
|
m_dependencies = depinfos(alpm_pkg_get_depends(package));
|
||||||
|
m_optionalDependencies = depinfos(alpm_pkg_get_optdepends(package));
|
||||||
|
m_conflicts = depinfos(alpm_pkg_get_conflicts(package));
|
||||||
|
m_provides = depinfos(alpm_pkg_get_provides(package));
|
||||||
|
m_replaces = depinfos(alpm_pkg_get_replaces(package));
|
||||||
|
alpm_list_t *tmp;
|
||||||
|
m_requiredBy = qstrlist(tmp = alpm_pkg_compute_requiredby(package));
|
||||||
|
FREELIST(tmp);
|
||||||
|
m_optionalFor = qstrlist(tmp = alpm_pkg_compute_optionalfor(package));
|
||||||
|
FREELIST(tmp);
|
||||||
|
m_hasInstallScript = alpm_pkg_has_scriptlet(package);
|
||||||
|
m_fileName = qstr(alpm_pkg_get_filename(package));
|
||||||
|
m_buildDate = DateTime::fromTimeStamp(alpm_pkg_get_builddate(package));
|
||||||
|
m_packer = qstr(alpm_pkg_get_packager(package));
|
||||||
|
m_md5 = qstr(alpm_pkg_get_md5sum(package));
|
||||||
|
m_sha256 = qstr(alpm_pkg_get_sha256sum(package));
|
||||||
|
m_buildArchitecture = qstr(alpm_pkg_get_arch(package));
|
||||||
|
m_packageSize = alpm_pkg_get_size(package);
|
||||||
|
m_installDate = DateTime::fromTimeStamp(alpm_pkg_get_installdate(package));
|
||||||
|
m_installedSize = alpm_pkg_get_isize(package);
|
||||||
|
for(const auto *backupEntry : BackupList(alpm_pkg_get_backup(package))) {
|
||||||
|
m_backupFiles << qstr(backupEntry->name);
|
||||||
|
}
|
||||||
|
m_validationMethods = alpm_pkg_get_validation(package);
|
||||||
|
m_installReason = alpm_pkg_get_reason(package);
|
||||||
|
alpm_filelist_t *fileList = alpm_pkg_get_files(package);
|
||||||
|
for(alpm_file_t *file = fileList->files, *end = fileList->files + fileList->count; file != end; ++file) {
|
||||||
|
QJsonObject fileInfo;
|
||||||
|
fileInfo.insert(QStringLiteral("name"), qstr(file->name));
|
||||||
|
if(file->mode) {
|
||||||
|
fileInfo.insert(QStringLiteral("mode"), static_cast<int>(file->mode));
|
||||||
|
}
|
||||||
|
if(file->size) {
|
||||||
|
fileInfo.insert(QStringLiteral("size"), static_cast<int>(file->size));
|
||||||
|
}
|
||||||
|
m_files << fileInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace PackageManagement
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
#ifndef PACKAGEMANAGEMENT_ALPMPACKAGE_H
|
||||||
|
#define PACKAGEMANAGEMENT_ALPMPACKAGE_H
|
||||||
|
|
||||||
|
#include "package.h"
|
||||||
|
|
||||||
|
namespace PackageManagement {
|
||||||
|
|
||||||
|
class AlpmDataBase;
|
||||||
|
|
||||||
|
class AlpmPackage : public Package
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AlpmPackage(alpm_pkg_t *package, AlpmDataBase *source = nullptr);
|
||||||
|
|
||||||
|
// ALPM specific meta data
|
||||||
|
const alpm_pkg_t *ptr() const;
|
||||||
|
alpm_pkg_t *ptr();
|
||||||
|
const char *base64Signature() const;
|
||||||
|
void *openChangelog() const;
|
||||||
|
size_t readChangelog(void *changelog, void *buffer, size_t bufferSize);
|
||||||
|
bool closeChangelog(void *changelog);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
alpm_pkg_t *m_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline uint qHash(const AlpmPackage &key)
|
||||||
|
{
|
||||||
|
return qHash(key.ptr());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns a pointer to the underlying alpm_pkg_t.
|
||||||
|
*/
|
||||||
|
inline const alpm_pkg_t *AlpmPackage::ptr() const
|
||||||
|
{
|
||||||
|
return m_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns a pointer to the underlying alpm_pkg_t.
|
||||||
|
*/
|
||||||
|
inline alpm_pkg_t *AlpmPackage::ptr()
|
||||||
|
{
|
||||||
|
return m_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const char *AlpmPackage::base64Signature() const
|
||||||
|
{
|
||||||
|
return alpm_pkg_get_base64_sig(m_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void *AlpmPackage::openChangelog() const
|
||||||
|
{
|
||||||
|
return alpm_pkg_changelog_open(m_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t AlpmPackage::readChangelog(void *changelog, void *buffer, size_t bufferSize)
|
||||||
|
{
|
||||||
|
return alpm_pkg_changelog_read(buffer, bufferSize, m_ptr, changelog);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool AlpmPackage::closeChangelog(void *changelog)
|
||||||
|
{
|
||||||
|
return alpm_pkg_changelog_close(m_ptr, changelog);
|
||||||
|
}
|
||||||
|
|
||||||
|
class AlpmOwnershipPackage : public AlpmPackage
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructor, destructor
|
||||||
|
AlpmOwnershipPackage(alpm_pkg_t *package);
|
||||||
|
AlpmOwnershipPackage(const AlpmOwnershipPackage &other) = delete;
|
||||||
|
AlpmOwnershipPackage(AlpmOwnershipPackage &&other);
|
||||||
|
~AlpmOwnershipPackage();
|
||||||
|
|
||||||
|
// assignment operator
|
||||||
|
AlpmOwnershipPackage &operator =(const AlpmOwnershipPackage &other) = delete;
|
||||||
|
AlpmOwnershipPackage &operator =(AlpmOwnershipPackage &&other);
|
||||||
|
};
|
||||||
|
|
||||||
|
inline AlpmOwnershipPackage::AlpmOwnershipPackage(alpm_pkg_t *package) :
|
||||||
|
AlpmPackage(package)
|
||||||
|
{}
|
||||||
|
|
||||||
|
inline AlpmOwnershipPackage::AlpmOwnershipPackage(AlpmOwnershipPackage &&other) :
|
||||||
|
AlpmPackage(other.m_ptr)
|
||||||
|
{
|
||||||
|
other.m_ptr = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline AlpmOwnershipPackage &AlpmOwnershipPackage::operator =(AlpmOwnershipPackage &&other)
|
||||||
|
{
|
||||||
|
if(this != &other) {
|
||||||
|
m_ptr = other.m_ptr;
|
||||||
|
other.m_ptr = nullptr;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline AlpmOwnershipPackage::~AlpmOwnershipPackage()
|
||||||
|
{
|
||||||
|
alpm_pkg_free(ptr());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace PackageManagement
|
||||||
|
|
||||||
|
#endif // PACKAGEMANAGEMENT_ALPMPACKAGE_H
|
|
@ -0,0 +1,41 @@
|
||||||
|
#include "aurpackage.h"
|
||||||
|
|
||||||
|
#include "network/userrepository.h"
|
||||||
|
|
||||||
|
#include <QJsonObject>
|
||||||
|
|
||||||
|
using namespace ChronoUtilities;
|
||||||
|
|
||||||
|
namespace PackageManagement {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief The AurPackage class holds information about AUR packages. It allows to convert the information
|
||||||
|
* to JSON objects used by the network classes and the web interface.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Creates a new instance from the specified "AurJson value".
|
||||||
|
*/
|
||||||
|
AurPackage::AurPackage(const QJsonValue &aurJsonValue, UserRepository *source) :
|
||||||
|
Package(QString(), source)
|
||||||
|
{
|
||||||
|
m_origin = PackageOrigin::Aur;
|
||||||
|
QJsonObject obj = aurJsonValue.toObject();
|
||||||
|
m_name = obj.value(QStringLiteral("Name")).toString();
|
||||||
|
m_hasGeneralInfo = true;
|
||||||
|
m_id = obj.value(QStringLiteral("ID")).toInt(-1);
|
||||||
|
m_categoryId = obj.value(QStringLiteral("CategoryID")).toInt(-1);
|
||||||
|
m_version = obj.value(QStringLiteral("Version")).toString();
|
||||||
|
m_description = obj.value(QStringLiteral("Description")).toString();
|
||||||
|
m_upstreamUrl = obj.value(QStringLiteral("URL")).toString();
|
||||||
|
m_votes = obj.value(QStringLiteral("NumVotes")).toInt(0);
|
||||||
|
m_outOfDate = DateTime::fromTimeStamp(obj.value(QStringLiteral("OutOfDate")).toInt());
|
||||||
|
m_maintainer = obj.value(QStringLiteral("Maintainer")).toString();
|
||||||
|
m_firstSubmitted = DateTime::fromTimeStamp(obj.value(QStringLiteral("FirstSubmitted")).toInt());
|
||||||
|
m_lastModified = DateTime::fromTimeStamp(obj.value(QStringLiteral("LastModified")).toInt());
|
||||||
|
m_licenses << obj.value(QStringLiteral("License")).toString();
|
||||||
|
m_tarUrl = obj.value(QStringLiteral("URLPath")).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace PackageManagement
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
#ifndef PACKAGEMANAGEMENT_AURPACKAGE_H
|
||||||
|
#define PACKAGEMANAGEMENT_AURPACKAGE_H
|
||||||
|
|
||||||
|
#include "package.h"
|
||||||
|
|
||||||
|
namespace PackageManagement {
|
||||||
|
|
||||||
|
class UserRepository;
|
||||||
|
|
||||||
|
class AurPackage : public Package
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AurPackage(const QJsonValue &aurJsonValue, UserRepository *source);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace PackageManagement
|
||||||
|
|
||||||
|
#endif // PACKAGEMANAGEMENT_AURPACKAGE_H
|
|
@ -40,7 +40,11 @@ ConfigArgs::ConfigArgs(ArgumentParser &parser) :
|
||||||
insecureArg("insecure", string(), "forces the server to run in insecure mode"),
|
insecureArg("insecure", string(), "forces the server to run in insecure mode"),
|
||||||
aurArg("aur", "u", "enables/disables AUR queries"),
|
aurArg("aur", "u", "enables/disables AUR queries"),
|
||||||
verboseArg("verbose", "v", "be verbose"),
|
verboseArg("verbose", "v", "be verbose"),
|
||||||
outputFileArg("output-file", "f", "specifies the output file")
|
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")
|
||||||
{
|
{
|
||||||
const initializer_list<string> pathValueName = {"path"};
|
const initializer_list<string> pathValueName = {"path"};
|
||||||
const initializer_list<string> pkgValueNames = {"package 1", "package 2", "package 3"};
|
const initializer_list<string> pkgValueNames = {"package 1", "package 2", "package 3"};
|
||||||
|
@ -83,10 +87,23 @@ ConfigArgs::ConfigArgs(ArgumentParser &parser) :
|
||||||
outputFileArg.setCombinable(true);
|
outputFileArg.setCombinable(true);
|
||||||
outputFileArg.setRequired(true);
|
outputFileArg.setRequired(true);
|
||||||
outputFileArg.setRequiredValueCount(1);
|
outputFileArg.setRequiredValueCount(1);
|
||||||
outputFileArg.setValueNames({"path"});
|
outputFileArg.setValueNames(pathValueName);
|
||||||
|
targetDirArg.setCombinable(true);
|
||||||
|
targetDirArg.setRequiredValueCount(1);
|
||||||
|
targetDirArg.setValueNames(pathValueName);
|
||||||
|
targetNameArg.setCombinable(true);
|
||||||
|
targetNameArg.setRequired(true);
|
||||||
|
targetNameArg.setRequiredValueCount(1);
|
||||||
|
targetNameArg.setValueNames({"name"});
|
||||||
|
targetFormatArg.setCombinable(true);
|
||||||
|
targetFormatArg.setRequiredValueCount(1);
|
||||||
|
targetFormatArg.setValueNames({"zip/7z/tar.gz/tar.bz/tar.xz"});
|
||||||
|
iconThemesArg.setCombinable(true);
|
||||||
|
iconThemesArg.setRequiredValueCount(-1);
|
||||||
|
iconThemesArg.setValueNames(pkgValueNames);
|
||||||
serverArg.setSecondaryArguments({&rootdirArg, &dbpathArg, &pacmanConfArg, &certFileArg, &keyFileArg, &insecureArg, &aurArg});
|
serverArg.setSecondaryArguments({&rootdirArg, &dbpathArg, &pacmanConfArg, &certFileArg, &keyFileArg, &insecureArg, &aurArg});
|
||||||
buildOrderArg.setSecondaryArguments({&aurArg, &verboseArg});
|
buildOrderArg.setSecondaryArguments({&aurArg, &verboseArg});
|
||||||
mingwBundleArg.setSecondaryArguments({&outputFileArg});
|
mingwBundleArg.setSecondaryArguments({&targetDirArg, &targetNameArg, &targetFormatArg, &iconThemesArg});
|
||||||
parser.setMainArguments({&buildOrderArg, &serverArg, &mingwBundleArg, &repoindexConfArg, &repoindexConfArg, &helpArg});
|
parser.setMainArguments({&buildOrderArg, &serverArg, &mingwBundleArg, &repoindexConfArg, &repoindexConfArg, &helpArg});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,7 +288,10 @@ void RepoEntry::load(const QJsonValue &jsonValue)
|
||||||
m_upgradeSources << str;
|
m_upgradeSources << str;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_sigLevel = Manager::parseSigLevel(obj.value(QStringLiteral("sigLevel")).toString().toLocal8Bit().data());
|
const auto sigLevelValue = obj.value(QStringLiteral("sigLevel"));
|
||||||
|
if(sigLevelValue.isString()) {
|
||||||
|
m_sigLevel = Manager::parseSigLevel(sigLevelValue.toString().toLocal8Bit().data());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Alpm
|
} // namespace Alpm
|
||||||
|
|
|
@ -7,9 +7,7 @@
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QHostAddress>
|
#include <QHostAddress>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_FORWARD_DECLARE_CLASS(QJsonValue)
|
||||||
class QJsonValue;
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
namespace PackageManagement {
|
namespace PackageManagement {
|
||||||
|
|
||||||
|
@ -33,6 +31,10 @@ public:
|
||||||
ApplicationUtilities::Argument aurArg;
|
ApplicationUtilities::Argument aurArg;
|
||||||
ApplicationUtilities::Argument verboseArg;
|
ApplicationUtilities::Argument verboseArg;
|
||||||
ApplicationUtilities::Argument outputFileArg;
|
ApplicationUtilities::Argument outputFileArg;
|
||||||
|
ApplicationUtilities::Argument targetDirArg;
|
||||||
|
ApplicationUtilities::Argument targetNameArg;
|
||||||
|
ApplicationUtilities::Argument targetFormatArg;
|
||||||
|
ApplicationUtilities::Argument iconThemesArg;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Config;
|
class Config;
|
||||||
|
|
|
@ -1,149 +0,0 @@
|
||||||
#include "database.h"
|
|
||||||
#include "group.h"
|
|
||||||
#include "updatelookup.h"
|
|
||||||
|
|
||||||
#include <QList>
|
|
||||||
#include <QJsonObject>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace PackageManagement {
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief The AlpmDataBase class wraps an ALPM database.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns the usage of the database.
|
|
||||||
*/
|
|
||||||
alpm_db_usage_t AlpmDataBase::usage() const
|
|
||||||
{
|
|
||||||
alpm_db_usage_t usage;
|
|
||||||
if(!alpm_db_get_usage(m_ptr, &usage)) {
|
|
||||||
return usage;
|
|
||||||
} else {
|
|
||||||
return static_cast<alpm_db_usage_t>(ALPM_DB_USAGE_ALL); // return default usage
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns the server URLs.
|
|
||||||
*/
|
|
||||||
const QJsonArray &AlpmDataBase::serverUrls() const
|
|
||||||
{
|
|
||||||
if(m_serverUrls.empty()) {
|
|
||||||
for(const char *str : servers()) {
|
|
||||||
m_serverUrls << str;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return m_serverUrls;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Adds the specified server URLs.
|
|
||||||
*/
|
|
||||||
bool AlpmDataBase::addServerUrls(const QStringList &urls)
|
|
||||||
{
|
|
||||||
m_serverUrls = QJsonArray();
|
|
||||||
for(const auto &url : urls) {
|
|
||||||
if(alpm_db_add_server(m_ptr, url.toLocal8Bit().data()) != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns the packages of the database.
|
|
||||||
*/
|
|
||||||
const std::map<QString, AlpmPackage> &AlpmDataBase::packages() const
|
|
||||||
{
|
|
||||||
if(m_packages.empty()) {
|
|
||||||
for(const AlpmPackage &pkg : PackageList(alpm_db_get_pkgcache(m_ptr))) {
|
|
||||||
m_packages.emplace(QString::fromLocal8Bit(pkg.name()), pkg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return m_packages;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns the package names of the data base as QStringList.
|
|
||||||
*/
|
|
||||||
QStringList AlpmDataBase::packageNames() const
|
|
||||||
{
|
|
||||||
QStringList packageNames;
|
|
||||||
packageNames.reserve(packages().size());
|
|
||||||
for(const auto &pkg : packages()) {
|
|
||||||
packageNames << pkg.first;
|
|
||||||
}
|
|
||||||
return packageNames;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns the package names of the data base as a QJsonArray.
|
|
||||||
*/
|
|
||||||
const QJsonArray &AlpmDataBase::packageNameJsonArray() const
|
|
||||||
{
|
|
||||||
if(m_packageNamesJsonArray.empty()) {
|
|
||||||
for(const auto &pkg : packages()) {
|
|
||||||
m_packageNamesJsonArray << pkg.first;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return m_packageNamesJsonArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns group info (group name + package names).
|
|
||||||
*/
|
|
||||||
QJsonObject AlpmDataBase::groupInfo() const
|
|
||||||
{
|
|
||||||
QJsonObject groupInfo;
|
|
||||||
groupInfo.insert(QStringLiteral("repo"), QString::fromLocal8Bit(name()));
|
|
||||||
QJsonArray groupsArray;
|
|
||||||
for(const AlpmGroup group : groups()) {
|
|
||||||
QJsonObject info;
|
|
||||||
info.insert(QStringLiteral("name"), QString::fromLocal8Bit(group.name()));
|
|
||||||
info.insert(QStringLiteral("pkgs"), group.packageNames());
|
|
||||||
groupsArray << info;
|
|
||||||
}
|
|
||||||
groupInfo.insert(QStringLiteral("groups"), groupsArray);
|
|
||||||
return groupInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AlpmDataBase::checkForUpgrades(const QList<const AlpmDataBase *> &syncDbs, UpdateLookupResults<AlpmPackage> &results) const
|
|
||||||
{
|
|
||||||
if(syncDbs.isEmpty()) {
|
|
||||||
results.noSources = true;
|
|
||||||
} else {
|
|
||||||
for(const auto &dbPkg : packages()) {
|
|
||||||
bool orphaned = true;
|
|
||||||
for(const auto *syncDb : syncDbs) {
|
|
||||||
const auto &syncDbPkgs = syncDb->packages();
|
|
||||||
try {
|
|
||||||
const auto &syncPkg = syncDbPkgs.at(dbPkg.first);
|
|
||||||
switch(dbPkg.second.compareVersion(syncPkg)) {
|
|
||||||
case PackageVersionComparsion::Equal:
|
|
||||||
break; // ignore equal packages
|
|
||||||
case PackageVersionComparsion::SoftwareUpgrade:
|
|
||||||
results.newVersions << makeUpdateResult(syncPkg, dbPkg.second.version());
|
|
||||||
break;
|
|
||||||
case PackageVersionComparsion::PackageUpgradeOnly:
|
|
||||||
results.newReleases << makeUpdateResult(syncPkg, dbPkg.second.version());
|
|
||||||
break;
|
|
||||||
case PackageVersionComparsion::NewerThenSyncVersion:
|
|
||||||
results.downgrades << makeUpdateResult(syncPkg, dbPkg.second.version());
|
|
||||||
}
|
|
||||||
orphaned = false;
|
|
||||||
} catch(out_of_range &) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(orphaned) {
|
|
||||||
results.orphaned << dbPkg.second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Alpm
|
|
||||||
|
|
256
alpm/database.h
256
alpm/database.h
|
@ -1,256 +0,0 @@
|
||||||
#ifndef ALPM_DATABASE_H
|
|
||||||
#define ALPM_DATABASE_H
|
|
||||||
|
|
||||||
#include "list.h"
|
|
||||||
#include "updatelookup.h"
|
|
||||||
|
|
||||||
#include <alpm.h>
|
|
||||||
|
|
||||||
#include <QJsonArray>
|
|
||||||
#include <QList>
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
namespace PackageManagement {
|
|
||||||
|
|
||||||
class AlpmDataBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AlpmDataBase(alpm_db_t *dataBase = nullptr, const QString &dbFile = QString(), const QString &srcDir = QString(), const QString &pkgDir = QString());
|
|
||||||
|
|
||||||
// operators
|
|
||||||
operator bool() const;
|
|
||||||
bool operator ==(const AlpmDataBase &other) const;
|
|
||||||
bool operator !=(const AlpmDataBase &other) const;
|
|
||||||
|
|
||||||
// database properties
|
|
||||||
alpm_db_t *ptr() const;
|
|
||||||
const char *name() const;
|
|
||||||
const QString &dataBaseFile() const;
|
|
||||||
const QString &sourcesDirectory() const;
|
|
||||||
void setSourcesDirectory(const QString &dir);
|
|
||||||
const QString &packagesDirectory() const;
|
|
||||||
void setPackagesDirectory(const QString &dir);
|
|
||||||
alpm_siglevel_t sigLevel() const;
|
|
||||||
alpm_db_usage_t usage() const;
|
|
||||||
StringList servers() const;
|
|
||||||
bool setServers(StringList servers);
|
|
||||||
const QJsonArray &serverUrls() const;
|
|
||||||
bool addServerUrls(const QStringList &urls);
|
|
||||||
alpm_pkg_t *package(const char *name) const;
|
|
||||||
const std::map<QString, AlpmPackage> &packages() const;
|
|
||||||
QStringList packageNames() const;
|
|
||||||
const QJsonArray &packageNameJsonArray() const;
|
|
||||||
alpm_group_t *group(const char *name) const;
|
|
||||||
GroupList groups() const;
|
|
||||||
QJsonObject groupInfo() const;
|
|
||||||
PackageList search(StringList terms) const;
|
|
||||||
|
|
||||||
// upgrade lookup
|
|
||||||
const QStringList &upgradeSources() const;
|
|
||||||
QStringList &upgradeSources();
|
|
||||||
template<class SyncPackageType>
|
|
||||||
void checkForUpgrades(const std::map<QString, SyncPackageType> &syncDbPkgs, UpdateLookupResults<SyncPackageType> &results) const;
|
|
||||||
void checkForUpgrades(const QList<const AlpmDataBase *> &syncDbs, UpdateLookupResults<AlpmPackage> &results) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
alpm_db_t *m_ptr;
|
|
||||||
QString m_dbFile;
|
|
||||||
QString m_srcDir;
|
|
||||||
QString m_pkgDir;
|
|
||||||
QStringList m_upgradeSources;
|
|
||||||
mutable QJsonArray m_serverUrls;
|
|
||||||
mutable std::map<QString, AlpmPackage> m_packages;
|
|
||||||
mutable QJsonArray m_packageNamesJsonArray;
|
|
||||||
mutable QJsonArray m_groupInfo;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Creates a new instance wrapping the specified database struct.
|
|
||||||
*/
|
|
||||||
inline AlpmDataBase::AlpmDataBase(alpm_db_t *dataBase, const QString &dbFile, const QString &srcDir, const QString &pkgDir) :
|
|
||||||
m_ptr(dataBase),
|
|
||||||
m_dbFile(dbFile),
|
|
||||||
m_srcDir(srcDir),
|
|
||||||
m_pkgDir(pkgDir)
|
|
||||||
{}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Checks whether the specified ALPM database is equal to the current instance.
|
|
||||||
*/
|
|
||||||
inline bool AlpmDataBase::operator ==(const AlpmDataBase &other) const
|
|
||||||
{
|
|
||||||
return m_ptr == other.m_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Checks whether the specified ALPM database is not equal to the current instance.
|
|
||||||
*/
|
|
||||||
inline bool AlpmDataBase::operator !=(const AlpmDataBase &other) const
|
|
||||||
{
|
|
||||||
return m_ptr != other.m_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns the pointer to the underlying database struct.
|
|
||||||
*/
|
|
||||||
inline alpm_db_t *AlpmDataBase::ptr() const
|
|
||||||
{
|
|
||||||
return m_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns the name of the database.
|
|
||||||
*/
|
|
||||||
inline const char *AlpmDataBase::name() const
|
|
||||||
{
|
|
||||||
return alpm_db_get_name(m_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns the path of the data base file.
|
|
||||||
*/
|
|
||||||
inline const QString &AlpmDataBase::dataBaseFile() const
|
|
||||||
{
|
|
||||||
return m_dbFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns the path of the local sources directory.
|
|
||||||
*/
|
|
||||||
inline const QString &AlpmDataBase::sourcesDirectory() const
|
|
||||||
{
|
|
||||||
return m_srcDir;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Sets the path of the local sources directory.
|
|
||||||
*/
|
|
||||||
inline void AlpmDataBase::setSourcesDirectory(const QString &dir)
|
|
||||||
{
|
|
||||||
m_srcDir = dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns the path of the local packages directory.
|
|
||||||
*/
|
|
||||||
inline const QString &AlpmDataBase::packagesDirectory() const
|
|
||||||
{
|
|
||||||
return m_pkgDir;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Sets the path of the local packages directory.
|
|
||||||
*/
|
|
||||||
inline void AlpmDataBase::setPackagesDirectory(const QString &dir)
|
|
||||||
{
|
|
||||||
m_pkgDir = dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns the signature level of the database.
|
|
||||||
*/
|
|
||||||
inline alpm_siglevel_t AlpmDataBase::sigLevel() const
|
|
||||||
{
|
|
||||||
return alpm_db_get_siglevel(m_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns the servers of the database.
|
|
||||||
*/
|
|
||||||
inline StringList AlpmDataBase::servers() const
|
|
||||||
{
|
|
||||||
return alpm_db_get_servers(m_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Sets the servers of the database.
|
|
||||||
*/
|
|
||||||
inline bool AlpmDataBase::setServers(StringList servers)
|
|
||||||
{
|
|
||||||
return alpm_db_set_servers(m_ptr, servers.begin().ptr()) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns the package with the specified \a name.
|
|
||||||
*/
|
|
||||||
inline alpm_pkg_t *AlpmDataBase::package(const char *name) const
|
|
||||||
{
|
|
||||||
return alpm_db_get_pkg(m_ptr, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns the groups.
|
|
||||||
*/
|
|
||||||
inline alpm_group_t *AlpmDataBase::group(const char *name) const
|
|
||||||
{
|
|
||||||
return alpm_db_get_group(m_ptr, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns the groups.
|
|
||||||
*/
|
|
||||||
inline GroupList AlpmDataBase::groups() const
|
|
||||||
{
|
|
||||||
return alpm_db_get_groupcache(m_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Performs a search using the build in ALPM function.
|
|
||||||
*/
|
|
||||||
inline PackageList AlpmDataBase::search(StringList terms) const
|
|
||||||
{
|
|
||||||
return alpm_db_search(m_ptr, terms.begin().ptr());
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns a list of databases which are used (by default) to upgrade this database.
|
|
||||||
*/
|
|
||||||
inline const QStringList &AlpmDataBase::upgradeSources() const
|
|
||||||
{
|
|
||||||
return m_upgradeSources;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns a list of databases which are used (by default) to upgrade this database.
|
|
||||||
*/
|
|
||||||
inline QStringList &AlpmDataBase::upgradeSources()
|
|
||||||
{
|
|
||||||
return m_upgradeSources;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns whether the database instance is valid or null.
|
|
||||||
*/
|
|
||||||
inline PackageManagement::AlpmDataBase::operator bool() const
|
|
||||||
{
|
|
||||||
return m_ptr != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class SyncPackageType>
|
|
||||||
void AlpmDataBase::checkForUpgrades(const std::map<QString, SyncPackageType> &syncDbPkgs, UpdateLookupResults<SyncPackageType> &results) const
|
|
||||||
{
|
|
||||||
for(const auto &dbPkg : packages()) {
|
|
||||||
try {
|
|
||||||
const auto &syncPkg = syncDbPkgs.at(dbPkg.first);
|
|
||||||
switch(dbPkg.second.compareVersion(syncPkg)) {
|
|
||||||
case PackageVersionComparsion::Equal:
|
|
||||||
break; // ignore equal packages
|
|
||||||
case PackageVersionComparsion::SoftwareUpgrade:
|
|
||||||
results.newVersions << makeUpdateResult(syncPkg, dbPkg.second.version());
|
|
||||||
break;
|
|
||||||
case PackageVersionComparsion::PackageUpgradeOnly:
|
|
||||||
results.newReleases << makeUpdateResult(syncPkg, dbPkg.second.version());
|
|
||||||
break;
|
|
||||||
case PackageVersionComparsion::NewerThenSyncVersion:
|
|
||||||
results.downgrades << makeUpdateResult(syncPkg, dbPkg.second.version());
|
|
||||||
}
|
|
||||||
} catch(std::out_of_range &) {
|
|
||||||
results.orphaned << dbPkg.second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Alpm
|
|
||||||
|
|
||||||
#endif // ALPM_DATABASE_H
|
|
|
@ -6,15 +6,16 @@
|
||||||
namespace PackageManagement {
|
namespace PackageManagement {
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Returns the package names of the group as QJsonArray.
|
* \class AlpmGroup
|
||||||
|
* \brief The AlpmGroup class wraps an ALPM group struct.
|
||||||
*/
|
*/
|
||||||
QJsonArray AlpmGroup::packageNames() const
|
|
||||||
|
GroupInfo::GroupInfo(const AlpmGroup &group)
|
||||||
{
|
{
|
||||||
QJsonArray pkgNames;
|
name = QString::fromLocal8Bit(group.name());
|
||||||
for(AlpmPackage pkg : packages()) {
|
for(auto *pkg : PackageList(group.packages())) {
|
||||||
pkgNames << QString::fromLocal8Bit(pkg.name());
|
packages << QString::fromLocal8Bit(alpm_pkg_get_name(pkg));
|
||||||
}
|
}
|
||||||
return pkgNames;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Alpm
|
} // namespace Alpm
|
||||||
|
|
25
alpm/group.h
25
alpm/group.h
|
@ -2,14 +2,13 @@
|
||||||
#define ALPM_GROUP_H
|
#define ALPM_GROUP_H
|
||||||
|
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
|
#include "package.h"
|
||||||
|
|
||||||
#include <alpm.h>
|
#include <alpm.h>
|
||||||
|
|
||||||
#include <QtGlobal>
|
#include <QStringList>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_FORWARD_DECLARE_CLASS(QJsonArray)
|
||||||
class QJsonArray;
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
namespace PackageManagement {
|
namespace PackageManagement {
|
||||||
|
|
||||||
|
@ -21,11 +20,9 @@ public:
|
||||||
// group properties
|
// group properties
|
||||||
const char *name() const;
|
const char *name() const;
|
||||||
PackageList packages() const;
|
PackageList packages() const;
|
||||||
QJsonArray packageNames() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const alpm_group_t *m_ptr;
|
const alpm_group_t *m_ptr;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -51,6 +48,20 @@ inline PackageList AlpmGroup::packages() const
|
||||||
return m_ptr->packages;
|
return m_ptr->packages;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Alpm
|
class GroupInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GroupInfo(const QString &name, const QStringList &packages = QStringList());
|
||||||
|
GroupInfo(const AlpmGroup &group);
|
||||||
|
QString name;
|
||||||
|
QStringList packages;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline GroupInfo::GroupInfo(const QString &name, const QStringList &packages) :
|
||||||
|
name(name),
|
||||||
|
packages(packages)
|
||||||
|
{}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endif // ALPM_GROUP_H
|
#endif // ALPM_GROUP_H
|
||||||
|
|
|
@ -111,6 +111,7 @@ typedef AlpmList<const char *> StringList;
|
||||||
typedef AlpmList<alpm_depend_t *> DependencyList;
|
typedef AlpmList<alpm_depend_t *> DependencyList;
|
||||||
typedef AlpmList<alpm_pkg_t *> PackageList;
|
typedef AlpmList<alpm_pkg_t *> PackageList;
|
||||||
typedef AlpmList<alpm_group_t *> GroupList;
|
typedef AlpmList<alpm_group_t *> GroupList;
|
||||||
|
typedef AlpmList<alpm_backup_t *> BackupList;
|
||||||
|
|
||||||
} // namespace Alpm
|
} // namespace Alpm
|
||||||
|
|
||||||
|
|
314
alpm/manager.cpp
314
alpm/manager.cpp
|
@ -1,11 +1,14 @@
|
||||||
#include "manager.h"
|
#include "manager.h"
|
||||||
#include "database.h"
|
#include "alpmdatabase.h"
|
||||||
#include "utilities.h"
|
#include "utilities.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "network/userrepository.h"
|
||||||
|
|
||||||
#include <c++utilities/io/inifile.h>
|
#include <c++utilities/io/inifile.h>
|
||||||
#include <c++utilities/conversion/stringconversion.h>
|
#include <c++utilities/conversion/stringconversion.h>
|
||||||
|
#include <c++utilities/misc/memory.h>
|
||||||
|
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QSysInfo>
|
#include <QSysInfo>
|
||||||
|
@ -22,9 +25,23 @@ using namespace ConversionUtilities;
|
||||||
|
|
||||||
namespace PackageManagement {
|
namespace PackageManagement {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \cond
|
||||||
|
*/
|
||||||
|
|
||||||
constexpr int defaultSigLevel = ALPM_SIG_PACKAGE | ALPM_SIG_PACKAGE_OPTIONAL |
|
constexpr int defaultSigLevel = ALPM_SIG_PACKAGE | ALPM_SIG_PACKAGE_OPTIONAL |
|
||||||
ALPM_SIG_DATABASE | ALPM_SIG_DATABASE_OPTIONAL;
|
ALPM_SIG_DATABASE | ALPM_SIG_DATABASE_OPTIONAL;
|
||||||
|
|
||||||
|
inline ostream &operator <<(ostream &stream, const QString &str)
|
||||||
|
{
|
||||||
|
stream << str.toLocal8Bit().data();
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \endcond
|
||||||
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief The Manager class helps accessing ALPM.
|
* \brief The Manager class helps accessing ALPM.
|
||||||
*
|
*
|
||||||
|
@ -40,12 +57,15 @@ constexpr int defaultSigLevel = ALPM_SIG_PACKAGE | ALPM_SIG_PACKAGE_OPTIONAL |
|
||||||
Manager::Manager(const Config &config) :
|
Manager::Manager(const Config &config) :
|
||||||
m_config(config),
|
m_config(config),
|
||||||
m_sigLevel(defaultSigLevel),
|
m_sigLevel(defaultSigLevel),
|
||||||
m_localFileSigLevel(ALPM_SIG_USE_DEFAULT),
|
m_localFileSigLevel(ALPM_SIG_USE_DEFAULT)
|
||||||
m_aur(m_networkAccessManager)
|
|
||||||
{
|
{
|
||||||
alpm_errno_t err;
|
alpm_errno_t err;
|
||||||
if(!(m_handle = alpm_initialize(config.alpmRootDir().toLocal8Bit().data(), config.alpmDbPath().toLocal8Bit().data(), &err))) {
|
if(!(m_handle = alpm_initialize(config.alpmRootDir().toLocal8Bit().data(), config.alpmDbPath().toLocal8Bit().data(), &err))) {
|
||||||
throw runtime_error(string("Cannot initialize alpm: ") + alpm_strerror(err));
|
throw runtime_error(string("Cannot initialize ALPM: ") + alpm_strerror(err));
|
||||||
|
}
|
||||||
|
m_localDb = make_unique<AlpmDataBase>(alpm_get_localdb(m_handle), config.alpmDbPath());
|
||||||
|
if(config.isAurEnabled()) {
|
||||||
|
m_userRepo = make_unique<UserRepository>(m_networkAccessManager);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,41 +80,75 @@ Manager::~Manager()
|
||||||
/*!
|
/*!
|
||||||
* \brief Returns the package with the specified name from the specified database.
|
* \brief Returns the package with the specified name from the specified database.
|
||||||
*/
|
*/
|
||||||
AlpmPackage Manager::packageFromSyncDataBase(const QString &dbName, const QString &pkgName) const
|
AlpmPackage *Manager::packageFromDataBase(const QString &dbName, const QString &pkgName)
|
||||||
{
|
{
|
||||||
try {
|
if(auto *db = dataBaseByName(dbName)) {
|
||||||
if(dbName == QLatin1String("local")) {
|
return static_cast<AlpmPackage *>(db->packageByName(pkgName));
|
||||||
return localDataBase().packages().at(pkgName);
|
} else {
|
||||||
} else {
|
return nullptr;
|
||||||
return syncDataBases().at(dbName).packages().at(pkgName);
|
|
||||||
}
|
|
||||||
} catch(out_of_range &) {
|
|
||||||
return AlpmPackage();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the package with the specified name from the specified database.
|
||||||
|
*/
|
||||||
|
const AlpmPackage *Manager::packageFromDataBase(const QString &dbName, const QString &pkgName) const
|
||||||
|
{
|
||||||
|
if(const auto *db = dataBaseByName(dbName)) {
|
||||||
|
return static_cast<const AlpmPackage *>(db->packageByName(pkgName));
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets the package with the specified \a name from one of the sync databases.
|
||||||
|
*/
|
||||||
|
AlpmPackage *Manager::packageFromSyncDataBases(const QString &pkgName)
|
||||||
|
{
|
||||||
|
for(const auto &dbEntry : syncDataBases()) {
|
||||||
|
if(auto *pkg = dbEntry.second->packageByName(pkgName)) {
|
||||||
|
return static_cast<AlpmPackage *>(pkg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets the package with the specified \a name from one of the sync databases.
|
||||||
|
*/
|
||||||
|
const AlpmPackage *Manager::packageFromSyncDataBases(const QString &pkgName) const
|
||||||
|
{
|
||||||
|
for(const auto &dbEntry : syncDataBases()) {
|
||||||
|
if(const auto *pkg = dbEntry.second->packageByName(pkgName)) {
|
||||||
|
return static_cast<const AlpmPackage *>(pkg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Creates a new package instance for the specified package file.
|
* \brief Creates a new package instance for the specified package file.
|
||||||
*
|
*
|
||||||
* Verifies the integrity of the file if the option is set.
|
* Verifies the integrity of the file if the option is set.
|
||||||
*/
|
*/
|
||||||
AlpmOwnershipPackage Manager::packageFromFile(const char *fileName, bool verifyIntegrity)
|
unique_ptr<AlpmOwnershipPackage> Manager::packageFromFile(const char *fileName, bool verifyIntegrity)
|
||||||
{
|
{
|
||||||
alpm_pkg_t *pkg;
|
alpm_pkg_t *pkg;
|
||||||
if(alpm_pkg_load(m_handle, fileName, verifyIntegrity, static_cast<alpm_siglevel_t>(m_localFileSigLevel), &pkg) != 0) {
|
if(alpm_pkg_load(m_handle, fileName, verifyIntegrity, static_cast<alpm_siglevel_t>(m_localFileSigLevel), &pkg) != 0) {
|
||||||
throw runtime_error(string("Unable to load package file: ") + alpm_strerror(alpm_errno(m_handle)));
|
throw runtime_error(string("Unable to load package file: ") + alpm_strerror(alpm_errno(m_handle)));
|
||||||
} else {
|
} else {
|
||||||
return AlpmOwnershipPackage(pkg);
|
return make_unique<AlpmOwnershipPackage>(pkg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Sets the install reason for the specified \a package.
|
* \brief Sets the install reason for the specified \a package.
|
||||||
*/
|
*/
|
||||||
void Manager::setInstallReason(AlpmPackage package, alpm_pkgreason_t reason)
|
void Manager::setInstallReason(AlpmPackage *package, alpm_pkgreason_t reason)
|
||||||
{
|
{
|
||||||
if(alpm_pkg_set_reason(package.ptr(), reason)) {
|
if(alpm_pkg_set_reason(package->ptr(), reason)) {
|
||||||
throw runtime_error(string("Unable to set install reason of the package ") + package.name() + ": " + alpm_strerror(alpm_errno(m_handle)));
|
throw runtime_error(string("Unable to set install reason of the package ") + package->name().toLocal8Bit().data() + ": " + alpm_strerror(alpm_errno(m_handle)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,12 +356,12 @@ void Manager::applyPacmanConfig()
|
||||||
cerr << "Warning: Included file \"" << path << "\" has no values." << endl;
|
cerr << "Warning: Included file \"" << path << "\" has no values." << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
auto emplaced = m_syncDbs.emplace(dbName, make_unique<AlpmDataBase>(db, m_config.alpmDbPath()));
|
||||||
// add sync db to internal map
|
// add sync db to internal map
|
||||||
if(usage & ALPM_DB_USAGE_UPGRADE) {
|
if(usage & ALPM_DB_USAGE_UPGRADE) {
|
||||||
// -> db is used to upgrade local database
|
// -> db is used to upgrade local database
|
||||||
localDataBase().upgradeSources() << dbName;
|
localDataBase()->upgradeSources() << emplaced.first->second.get();
|
||||||
}
|
}
|
||||||
m_syncDbs.emplace(dbName, AlpmDataBase(db, QStringLiteral("%1/sync/%2").arg(m_config.alpmDbPath(), dbName)));
|
|
||||||
} else {
|
} else {
|
||||||
cerr << "Error: Unable to add sync database [" << scope.first << "]" << endl;
|
cerr << "Error: Unable to add sync database [" << scope.first << "]" << endl;
|
||||||
}
|
}
|
||||||
|
@ -324,18 +378,19 @@ void Manager::applyPacmanConfig()
|
||||||
*/
|
*/
|
||||||
void Manager::applyRepoIndexConfig()
|
void Manager::applyRepoIndexConfig()
|
||||||
{
|
{
|
||||||
|
// check whether an entry already exists, if not create a new one
|
||||||
for(const RepoEntry &repoEntry : m_config.repoEntries()) {
|
for(const RepoEntry &repoEntry : m_config.repoEntries()) {
|
||||||
AlpmDataBase *syncDb;
|
AlpmDataBase *syncDb = nullptr;
|
||||||
try {
|
try {
|
||||||
syncDb = &m_syncDbs.at(repoEntry.name());
|
syncDb = m_syncDbs.at(repoEntry.name()).get();
|
||||||
cerr << "Applying config for database [" << syncDb->name() << "]" << endl;
|
cerr << "Applying config for database [" << syncDb->name() << "]" << endl;
|
||||||
if(!repoEntry.dataBasePath().isEmpty()) {
|
if(!repoEntry.dataBasePath().isEmpty()) {
|
||||||
cerr << "Warning: Can't use data base path specified in repo index config because the repo \""
|
cerr << "Warning: Can't use data base path specified in repo index config because the repo \""
|
||||||
<< repoEntry.name().toLocal8Bit().data() << "\" has already been added from the Pacman config." << endl;
|
<< repoEntry.name() << "\" has already been added from the Pacman config." << endl;
|
||||||
}
|
}
|
||||||
if(repoEntry.sigLevel()) {
|
if(repoEntry.sigLevel()) {
|
||||||
cerr << "Warning: Can't use sig level path specified in repo index config because the repo \""
|
cerr << "Warning: Can't use sig level specified in repo index config because the repo \""
|
||||||
<< repoEntry.name().toLocal8Bit().data() << "\" has already been added from the Pacman config." << endl;
|
<< repoEntry.name() << "\" has already been added from the Pacman config." << endl;
|
||||||
}
|
}
|
||||||
syncDb->setPackagesDirectory(repoEntry.packageDir());
|
syncDb->setPackagesDirectory(repoEntry.packageDir());
|
||||||
syncDb->setSourcesDirectory(repoEntry.sourceDir());
|
syncDb->setSourcesDirectory(repoEntry.sourceDir());
|
||||||
|
@ -345,21 +400,39 @@ void Manager::applyRepoIndexConfig()
|
||||||
} else if(repoEntry.name().startsWith(QLatin1String("aur"), Qt::CaseInsensitive)) {
|
} 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 << "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 {
|
} else {
|
||||||
|
// TODO: database path
|
||||||
auto *db = alpm_register_syncdb(m_handle, repoEntry.name().toLocal8Bit().data(), static_cast<alpm_siglevel_t>(repoEntry.sigLevel()));
|
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(), AlpmDataBase(db, repoEntry.dataBasePath(), repoEntry.sourceDir(), repoEntry.packageDir()));
|
auto emplaced = m_syncDbs.emplace(repoEntry.name(), make_unique<AlpmDataBase>(db, m_config.alpmDbPath()));
|
||||||
if(emplaced.second) {
|
if(emplaced.second) {
|
||||||
syncDb = &emplaced.first->second;
|
syncDb = emplaced.first->second.get();
|
||||||
|
syncDb->setSourcesDirectory(repoEntry.sourceDir());
|
||||||
|
syncDb->setPackagesDirectory(repoEntry.packageDir());
|
||||||
if(m_config.isVerbose() || m_config.runServer()) {
|
if(m_config.isVerbose() || m_config.runServer()) {
|
||||||
cerr << "Added database [" << repoEntry.name().toLocal8Bit().data() << "]" << endl;
|
cerr << "Added database [" << repoEntry.name() << "]" << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(syncDb) {
|
if(syncDb) {
|
||||||
syncDb->addServerUrls(repoEntry.servers());
|
syncDb->addServerUrls(repoEntry.servers());
|
||||||
syncDb->upgradeSources() << repoEntry.upgradeSources();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// add upgrade sources
|
||||||
|
for(const RepoEntry &repoEntry : m_config.repoEntries()) {
|
||||||
|
try {
|
||||||
|
auto &upgradeSources = m_syncDbs.at(repoEntry.name())->upgradeSources();
|
||||||
|
for(const auto &upgradeSourceName : repoEntry.upgradeSources()) {
|
||||||
|
if(auto *source = repositoryByName(upgradeSourceName)) {
|
||||||
|
upgradeSources << source;
|
||||||
|
} else {
|
||||||
|
cerr << "Warning: The specified upgrade source \"" << upgradeSourceName << "\" can not be found and will be ignored." << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(const out_of_range &) {
|
||||||
|
// entry should have been added before
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -372,56 +445,15 @@ void Manager::unregisterSyncDataBases()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns the local data base.
|
|
||||||
*/
|
|
||||||
const AlpmDataBase &Manager::localDataBase() const
|
|
||||||
{
|
|
||||||
if(!m_localDb) {
|
|
||||||
QMutexLocker locker(&m_localDbMutex);
|
|
||||||
if(!m_localDb) {
|
|
||||||
m_localDb = alpm_get_localdb(m_handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return m_localDb;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns the local data base.
|
|
||||||
*/
|
|
||||||
AlpmDataBase &Manager::localDataBase()
|
|
||||||
{
|
|
||||||
if(!m_localDb) {
|
|
||||||
m_localDb = alpm_get_localdb(m_handle);
|
|
||||||
}
|
|
||||||
return m_localDb;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Returns a list of all sync databases.
|
* \brief Returns a list of all sync databases.
|
||||||
* \remarks Sync databases must be registered with parsePacmanConfig() before.
|
* \remarks Sync databases must be registered with parsePacmanConfig() before.
|
||||||
*/
|
*/
|
||||||
const std::map<QString, 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
|
return m_syncDbs; // m_syncDbs has been filled when the databases were registered
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns basic information about the specified repository.
|
|
||||||
*/
|
|
||||||
QJsonObject Manager::basicRepoInfo(AlpmDataBase db, const QString &name, const QString &desc) const
|
|
||||||
{
|
|
||||||
QJsonObject repoInfo;
|
|
||||||
repoInfo.insert(QStringLiteral("name"), name);
|
|
||||||
repoInfo.insert(QStringLiteral("desc"), desc);
|
|
||||||
repoInfo.insert(QStringLiteral("servers"), db.serverUrls());
|
|
||||||
repoInfo.insert(QStringLiteral("usage"), Utilities::usageStrings(db.usage()));
|
|
||||||
repoInfo.insert(QStringLiteral("sigLevel"), Utilities::sigLevelStrings(db.sigLevel()));
|
|
||||||
repoInfo.insert(QStringLiteral("upgradeSources"), QJsonArray::fromStringList(db.upgradeSources()));
|
|
||||||
repoInfo.insert(QStringLiteral("packages"), db.packageNameJsonArray());
|
|
||||||
return repoInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Returns basic information about all repositories known to the manager.
|
* \brief Returns basic information about all repositories known to the manager.
|
||||||
*
|
*
|
||||||
|
@ -433,17 +465,22 @@ const QJsonArray &Manager::basicRepoInfo() const
|
||||||
if(m_basicRepoInfo.isEmpty()) {
|
if(m_basicRepoInfo.isEmpty()) {
|
||||||
QMutexLocker locker(&m_basicRepoInfoMutex);
|
QMutexLocker locker(&m_basicRepoInfoMutex);
|
||||||
if(m_basicRepoInfo.isEmpty()) {
|
if(m_basicRepoInfo.isEmpty()) {
|
||||||
m_basicRepoInfo << basicRepoInfo(localDataBase(), QStringLiteral("local"), QStringLiteral("The local database."));
|
// add local data base
|
||||||
auto const &syncDbs = syncDataBases();
|
m_basicRepoInfo << localDataBase()->basicInfo();
|
||||||
for(const auto &syncDb : syncDbs) {
|
// add sync data bases
|
||||||
|
for(const auto &syncDb : syncDataBases()) {
|
||||||
// check if the "sync" database is actually used for syncing
|
// check if the "sync" database is actually used for syncing
|
||||||
auto usage = syncDb.second.usage();
|
auto usage = syncDb.second->usage();
|
||||||
if((usage & ALPM_DB_USAGE_SYNC) || (usage & ALPM_DB_USAGE_INSTALL) || (usage & ALPM_DB_USAGE_UPGRADE)) {
|
if((usage & ALPM_DB_USAGE_SYNC) || (usage & ALPM_DB_USAGE_INSTALL) || (usage & ALPM_DB_USAGE_UPGRADE)) {
|
||||||
m_basicRepoInfo << basicRepoInfo(syncDb.second, syncDb.first, QStringLiteral("The sync database »%1«.").arg(syncDb.first));
|
m_basicRepoInfo << syncDb.second->basicInfo();
|
||||||
} else {
|
} else {
|
||||||
m_basicRepoInfo << basicRepoInfo(syncDb.second, syncDb.first, QStringLiteral("The database »%1«.").arg(syncDb.first));
|
m_basicRepoInfo << syncDb.second->basicInfo();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// add AUR
|
||||||
|
if(config().isAurEnabled()) {
|
||||||
|
m_basicRepoInfo << userRepository()->basicInfo();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return m_basicRepoInfo;
|
return m_basicRepoInfo;
|
||||||
|
@ -452,26 +489,38 @@ const QJsonArray &Manager::basicRepoInfo() const
|
||||||
/*!
|
/*!
|
||||||
* \brief Returns package information for the specified selection of packages.
|
* \brief Returns package information for the specified selection of packages.
|
||||||
*/
|
*/
|
||||||
const QJsonArray Manager::packageInfo(const QJsonArray &pkgSelection, bool full) const
|
const QJsonArray Manager::packageInfo(const QJsonObject &pkgSelection, bool full) const
|
||||||
{
|
{
|
||||||
QJsonArray pkgInfos;
|
QJsonArray pkgInfos;
|
||||||
for(const auto &pkgSelJsonVal : pkgSelection) {
|
for(auto i = pkgSelection.constBegin(), end = pkgSelection.constEnd(); i != end; ++i) {
|
||||||
QJsonObject pkgSel = pkgSelJsonVal.toObject();
|
if(auto *repo = repositoryByName(i.key())) {
|
||||||
if(!pkgSel.isEmpty()) {
|
for(const auto &entry : i.value().toArray()) {
|
||||||
QString repoName = pkgSel.value(QStringLiteral("repo")).toString();
|
const auto entryObj = entry.toObject();
|
||||||
QString pkgName = pkgSel.value(QStringLiteral("name")).toString();
|
const auto pkgName = entryObj.value(QStringLiteral("name")).toString();
|
||||||
AlpmPackage pkg;
|
if(!pkgName.isEmpty()) {
|
||||||
QJsonObject pkgInfo;
|
QJsonObject pkgInfo;
|
||||||
if(!repoName.isEmpty() && !pkgName.isEmpty() && (pkg = packageFromSyncDataBase(repoName, pkgName))) {
|
if(auto *pkg = repo->packageByName(pkgName)) {
|
||||||
pkgInfo = full ? pkg.fullInfo() : pkg.basicInfo();
|
pkgInfo = full ? pkg->fullInfo() : pkg->basicInfo();
|
||||||
} else {
|
} else {
|
||||||
pkgInfo.insert(QStringLiteral("error"), QStringLiteral("na"));
|
pkgInfo.insert(QStringLiteral("error"), QStringLiteral("na"));
|
||||||
|
}
|
||||||
|
pkgInfo.insert(QStringLiteral("name"), pkgName);
|
||||||
|
pkgInfo.insert(QStringLiteral("repo"), repo->name());
|
||||||
|
const auto index = entryObj.value(QStringLiteral("index"));
|
||||||
|
if(!index.isNull() && !index.isUndefined()) {
|
||||||
|
pkgInfo.insert(QStringLiteral("index"), index);
|
||||||
|
}
|
||||||
|
pkgInfos << pkgInfo;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pkgInfo.insert(QStringLiteral("name"), pkgName);
|
} else {
|
||||||
pkgInfo.insert(QStringLiteral("repo"), repoName);
|
// specified repository can not be found
|
||||||
pkgInfo.insert(QStringLiteral("index"), pkgSel.value(QStringLiteral("index")));
|
QJsonObject errorObj;
|
||||||
pkgInfos << pkgInfo;
|
errorObj.insert(QStringLiteral("repo"), i.key());
|
||||||
|
errorObj.insert(QStringLiteral("error"), QStringLiteral("na"));
|
||||||
|
pkgInfos << errorObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return pkgInfos;
|
return pkgInfos;
|
||||||
}
|
}
|
||||||
|
@ -484,9 +533,9 @@ const QJsonArray &Manager::groupInfo() const
|
||||||
if(m_groupInfo.empty()) {
|
if(m_groupInfo.empty()) {
|
||||||
QMutexLocker locker(&m_groupInfoMutex);
|
QMutexLocker locker(&m_groupInfoMutex);
|
||||||
if(m_groupInfo.empty()) {
|
if(m_groupInfo.empty()) {
|
||||||
m_groupInfo << localDataBase().groupInfo();
|
m_groupInfo << localDataBase()->groupInfo();
|
||||||
for(const auto &db : m_syncDbs) {
|
for(const auto &db : m_syncDbs) {
|
||||||
m_groupInfo << db.second.groupInfo();
|
m_groupInfo << db.second->groupInfo();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -495,41 +544,70 @@ const QJsonArray &Manager::groupInfo() const
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Returns the ALPM database with the specified name.
|
* \brief Returns the ALPM database with the specified name.
|
||||||
* \throws Throws std::out_of_range if the specified database is unknown to the manager.
|
|
||||||
*/
|
*/
|
||||||
const AlpmDataBase &Manager::dataBaseByName(const QString &dbName) const
|
const AlpmDataBase *Manager::dataBaseByName(const QString &dbName) const
|
||||||
{
|
{
|
||||||
if(dbName == QLatin1String("local")) {
|
if(dbName.compare(QLatin1String("local"), Qt::CaseInsensitive) == 0) {
|
||||||
return localDataBase();
|
return localDataBase();
|
||||||
} else {
|
} else {
|
||||||
return m_syncDbs.at(dbName);
|
try {
|
||||||
|
return m_syncDbs.at(dbName).get();
|
||||||
|
} catch(const out_of_range &) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Returns the ALPM database with the specified name.
|
* \brief Returns the ALPM database with the specified name.
|
||||||
* \throws Throws std::out_of_range if the specified database is unknown to the manager.
|
|
||||||
*/
|
*/
|
||||||
AlpmDataBase &Manager::dataBaseByName(const QString &dbName)
|
AlpmDataBase *Manager::dataBaseByName(const QString &dbName)
|
||||||
{
|
{
|
||||||
if(dbName == QLatin1String("local")) {
|
if(dbName.compare(QLatin1String("local"), Qt::CaseInsensitive) == 0) {
|
||||||
return localDataBase();
|
return localDataBase();
|
||||||
} else {
|
} else {
|
||||||
return m_syncDbs.at(dbName);
|
try {
|
||||||
|
return m_syncDbs.at(dbName).get();
|
||||||
|
} catch(const out_of_range &) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Checks for upgrades availabel to the specified database.
|
* \brief Returns the package source with the specified name.
|
||||||
*
|
|
||||||
* The \a request must have the following values:
|
|
||||||
* - db: Specifies the name of the database to check for upgrades.
|
|
||||||
* - syncdbs: Array with the names of the databases used as upgrade sources.
|
|
||||||
* If not present, appropriate upgrade sources will be determined automatically.
|
|
||||||
*/
|
*/
|
||||||
void Manager::invokeUpgradeLookup(const QJsonObject &request, UpdateLookupCallback callback) const
|
const Repository *Manager::repositoryByName(const QString &name) const
|
||||||
{
|
{
|
||||||
new UpdateLookup(*this, request, callback); // this object will delete itself
|
if(name.compare(QLatin1String("local"), Qt::CaseInsensitive) == 0) {
|
||||||
|
return localDataBase();
|
||||||
|
} else if(config().isAurEnabled() && (name.compare(QLatin1String("aur"), Qt::CaseInsensitive) == 0)) {
|
||||||
|
return userRepository();
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
return m_syncDbs.at(name).get();
|
||||||
|
} catch(const out_of_range &) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the package source with the specified name.
|
||||||
|
*/
|
||||||
|
Repository *Manager::repositoryByName(const QString &name)
|
||||||
|
{
|
||||||
|
if(name.compare(QLatin1String("local"), Qt::CaseInsensitive) == 0) {
|
||||||
|
return localDataBase();
|
||||||
|
} else if(config().isAurEnabled() && (name.compare(QLatin1String("aur"), Qt::CaseInsensitive) == 0)) {
|
||||||
|
return userRepository();
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
return m_syncDbs.at(name).get();
|
||||||
|
} catch(const out_of_range &) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -537,18 +615,10 @@ void Manager::invokeUpgradeLookup(const QJsonObject &request, UpdateLookupCallba
|
||||||
*
|
*
|
||||||
* Appropriate upgrade sources will be determined automatically; does not check the AUR.
|
* Appropriate upgrade sources will be determined automatically; does not check the AUR.
|
||||||
*/
|
*/
|
||||||
const UpdateLookupResults<AlpmPackage> Manager::checkForUpgrades(const AlpmDataBase &db) const
|
const UpgradeLookupResults Manager::checkForUpgrades(AlpmDataBase *db) const
|
||||||
{
|
{
|
||||||
UpdateLookupResults<AlpmPackage> results;
|
UpgradeLookupResults results;
|
||||||
QList<const AlpmDataBase *> syncDbSel;
|
db->checkForUpgrades(results);
|
||||||
for(const auto &syncDbName : db.upgradeSources()) {
|
|
||||||
try {
|
|
||||||
syncDbSel << &(syncDataBases().at(syncDbName));
|
|
||||||
} catch(out_of_range &) {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
db.checkForUpgrades(syncDbSel, results);
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
#ifndef ALPM_MANAGER_H
|
#ifndef ALPM_MANAGER_H
|
||||||
#define ALPM_MANAGER_H
|
#define ALPM_MANAGER_H
|
||||||
|
|
||||||
#include "database.h"
|
#include "upgradelookup.h"
|
||||||
#include "updatelookup.h"
|
#include "alpmpackage.h"
|
||||||
|
|
||||||
#include "network/aurquery.h"
|
|
||||||
|
|
||||||
#include <alpm.h>
|
#include <alpm.h>
|
||||||
|
|
||||||
|
@ -14,11 +12,13 @@
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace PackageManagement {
|
namespace PackageManagement {
|
||||||
|
|
||||||
class Config;
|
class Config;
|
||||||
template<class Package> class UpdateLookupResults;
|
class UserRepository;
|
||||||
|
class AlpmDataBase;
|
||||||
|
|
||||||
class Manager
|
class Manager
|
||||||
{
|
{
|
||||||
|
@ -42,30 +42,33 @@ public:
|
||||||
void applyRepoIndexConfig();
|
void applyRepoIndexConfig();
|
||||||
|
|
||||||
void unregisterSyncDataBases();
|
void unregisterSyncDataBases();
|
||||||
const AurQuery &aurQuery() const;
|
const UserRepository *userRepository() const;
|
||||||
AurQuery &aurQuery();
|
UserRepository *userRepository();
|
||||||
|
|
||||||
// package lookup
|
// package lookup
|
||||||
AlpmPackage packageFromSyncDataBase(const QString &dbName, const QString &pkgName) const;
|
AlpmPackage *packageFromDataBase(const QString &dbName, const QString &pkgName);
|
||||||
AlpmPackage packageFromSyncDataBases(const char *name) const;
|
const AlpmPackage *packageFromDataBase(const QString &dbName, const QString &pkgName) const;
|
||||||
AlpmOwnershipPackage packageFromFile(const char *fileName, bool verifyIntegrity = false);
|
AlpmPackage *packageFromSyncDataBases(const QString &pkgName);
|
||||||
bool isPackageIgnored(AlpmPackage package) const;
|
const AlpmPackage *packageFromSyncDataBases(const QString &pkgName) const;
|
||||||
void setInstallReason(AlpmPackage package, alpm_pkgreason_t reason);
|
std::unique_ptr<AlpmOwnershipPackage> packageFromFile(const char *fileName, bool verifyIntegrity = false);
|
||||||
|
bool isPackageIgnored(const AlpmPackage *package) const;
|
||||||
|
void setInstallReason(AlpmPackage *package, alpm_pkgreason_t reason);
|
||||||
|
|
||||||
// database lookup
|
// data base lookup
|
||||||
const AlpmDataBase &localDataBase() const;
|
const AlpmDataBase *localDataBase() const;
|
||||||
AlpmDataBase &localDataBase();
|
AlpmDataBase *localDataBase();
|
||||||
const std::map<QString, AlpmDataBase> &syncDataBases() const;
|
const std::map<QString, std::unique_ptr<AlpmDataBase> > &syncDataBases() const;
|
||||||
const AlpmDataBase &dataBaseByName(const QString &dbName) const;
|
const AlpmDataBase *dataBaseByName(const QString &dbName) const;
|
||||||
AlpmDataBase &dataBaseByName(const QString &dbName);
|
AlpmDataBase *dataBaseByName(const QString &dbName);
|
||||||
const UpdateLookupResults<AlpmPackage> checkForUpgrades(const AlpmDataBase &db) const;
|
const Repository *repositoryByName(const QString &name) const;
|
||||||
|
Repository *repositoryByName(const QString &name);
|
||||||
|
const UpgradeLookupResults checkForUpgrades(AlpmDataBase *db) const;
|
||||||
|
|
||||||
// JSON serialization, handling JSON requests
|
// JSON serialization, handling JSON requests
|
||||||
QJsonObject basicRepoInfo(AlpmDataBase db, const QString &name, const QString &desc = QString()) const;
|
const QJsonObject basicRepoInfo(const Repository *packageSource) const;
|
||||||
const QJsonArray &basicRepoInfo() const;
|
const QJsonArray &basicRepoInfo() const;
|
||||||
const QJsonArray packageInfo(const QJsonArray &pkgSelection, bool full = true) const;
|
const QJsonArray packageInfo(const QJsonObject &pkgSelection, bool full = true) const;
|
||||||
const QJsonArray &groupInfo() const;
|
const QJsonArray &groupInfo() const;
|
||||||
void invokeUpgradeLookup(const QJsonObject &request, UpdateLookupCallback callback) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void cleanup();
|
void cleanup();
|
||||||
|
@ -76,10 +79,9 @@ private:
|
||||||
int m_localFileSigLevel;
|
int m_localFileSigLevel;
|
||||||
QString m_pacmanCacheDir;
|
QString m_pacmanCacheDir;
|
||||||
QNetworkAccessManager m_networkAccessManager;
|
QNetworkAccessManager m_networkAccessManager;
|
||||||
AurQuery m_aur;
|
std::unique_ptr<UserRepository> m_userRepo;
|
||||||
mutable AlpmDataBase m_localDb;
|
std::unique_ptr<AlpmDataBase> m_localDb;
|
||||||
mutable QMutex m_localDbMutex;
|
std::map<QString, std::unique_ptr<AlpmDataBase> > m_syncDbs;
|
||||||
mutable std::map<QString, AlpmDataBase> m_syncDbs;
|
|
||||||
mutable QJsonArray m_basicRepoInfo;
|
mutable QJsonArray m_basicRepoInfo;
|
||||||
mutable QMutex m_basicRepoInfoMutex;
|
mutable QMutex m_basicRepoInfoMutex;
|
||||||
mutable QJsonArray m_groupInfo;
|
mutable QJsonArray m_groupInfo;
|
||||||
|
@ -135,20 +137,12 @@ inline void Manager::setLocalFileSigLevel(int sigLevel)
|
||||||
m_localFileSigLevel = sigLevel;
|
m_localFileSigLevel = sigLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Gets the package with the specified \a name from one of the sync databases.
|
|
||||||
*/
|
|
||||||
inline AlpmPackage Manager::packageFromSyncDataBases(const char *name) const
|
|
||||||
{
|
|
||||||
return alpm_find_dbs_satisfier(m_handle, alpm_get_syncdbs(m_handle), name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Returns whether the specified \a package is ignored.
|
* \brief Returns whether the specified \a package is ignored.
|
||||||
*/
|
*/
|
||||||
inline bool Manager::isPackageIgnored(AlpmPackage package) const
|
inline bool Manager::isPackageIgnored(const AlpmPackage *package) const
|
||||||
{
|
{
|
||||||
return alpm_pkg_should_ignore(m_handle, package.ptr());
|
return alpm_pkg_should_ignore(m_handle, const_cast<alpm_pkg_t *>(package->ptr()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -160,14 +154,30 @@ inline const QString &Manager::pacmanCacheDir() const
|
||||||
return m_pacmanCacheDir;
|
return m_pacmanCacheDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const AurQuery &Manager::aurQuery() const
|
inline const UserRepository *Manager::userRepository() const
|
||||||
{
|
{
|
||||||
return m_aur;
|
return m_userRepo.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline AurQuery &Manager::aurQuery()
|
inline UserRepository *Manager::userRepository()
|
||||||
{
|
{
|
||||||
return m_aur;
|
return m_userRepo.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the local data base.
|
||||||
|
*/
|
||||||
|
inline const AlpmDataBase *Manager::localDataBase() const
|
||||||
|
{
|
||||||
|
return m_localDb.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the local data base.
|
||||||
|
*/
|
||||||
|
inline AlpmDataBase *Manager::localDataBase()
|
||||||
|
{
|
||||||
|
return m_localDb.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,19 @@
|
||||||
#include "mingwbundle.h"
|
#include "mingwbundle.h"
|
||||||
|
#include "utilities.h"
|
||||||
#include "manager.h"
|
#include "manager.h"
|
||||||
|
|
||||||
#include <c++utilities/conversion/stringconversion.h>
|
#include <c++utilities/conversion/stringconversion.h>
|
||||||
#include <c++utilities/misc/memory.h>
|
#include <c++utilities/misc/memory.h>
|
||||||
|
|
||||||
#include <KTar>
|
#include <KTar>
|
||||||
|
#include <K7Zip>
|
||||||
|
#include <KZip>
|
||||||
|
|
||||||
#include <QFile>
|
|
||||||
#include <QtConcurrent/QtConcurrent>
|
#include <QtConcurrent/QtConcurrent>
|
||||||
|
#include <QStringBuilder>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QFile>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -16,18 +22,25 @@ using namespace std;
|
||||||
|
|
||||||
namespace PackageManagement {
|
namespace PackageManagement {
|
||||||
|
|
||||||
|
using namespace Utilities;
|
||||||
|
|
||||||
const string prefix("mingw-w64-");
|
const string prefix("mingw-w64-");
|
||||||
|
|
||||||
MingwBundle::MingwBundle(const Manager &manager, const ApplicationUtilities::StringVector &packages) :
|
MingwBundle::MingwBundle(const Manager &manager, const ApplicationUtilities::StringVector &packages, const ApplicationUtilities::StringVector &iconPackages) :
|
||||||
m_manager(manager)
|
m_manager(manager)
|
||||||
{
|
{
|
||||||
|
cerr << "Resolving dependencies ..." << endl;
|
||||||
string missing;
|
string missing;
|
||||||
|
// add mingw-w64 packages
|
||||||
for(const auto &pkgName : packages) {
|
for(const auto &pkgName : packages) {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for(const auto &syncDb : manager.syncDataBases()) {
|
for(const auto &syncDb : manager.syncDataBases()) {
|
||||||
if(auto pkg = syncDb.second.package(ConversionUtilities::startsWith(pkgName, prefix) ? pkgName.data() : (prefix + pkgName).data())) {
|
if(auto *pkg = syncDb.second->packageByName(QString::fromLocal8Bit(ConversionUtilities::startsWith(pkgName, prefix) ? pkgName.data() : (prefix + pkgName).data()))) {
|
||||||
if(missing.empty()) {
|
if(missing.empty()) {
|
||||||
m_packages.emplace_back(syncDb.second, pkg);
|
decltype(m_packages)::value_type entry(syncDb.second.get(), pkg);
|
||||||
|
if(find(m_packages.cbegin(), m_packages.cend(), entry) == m_packages.cend()) {
|
||||||
|
m_packages.emplace_back(entry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
addDependencies(pkg);
|
addDependencies(pkg);
|
||||||
found = true;
|
found = true;
|
||||||
|
@ -39,50 +52,125 @@ MingwBundle::MingwBundle(const Manager &manager, const ApplicationUtilities::Str
|
||||||
missing.append(pkgName);
|
missing.append(pkgName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// add additional icon packages
|
||||||
|
for(const auto &pkgName : iconPackages) {
|
||||||
|
bool found = false;
|
||||||
|
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);
|
||||||
|
if(find(m_packages.cbegin(), m_packages.cend(), entry) == m_packages.cend()) {
|
||||||
|
m_packages.emplace_back(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!found) {
|
||||||
|
missing.push_back(' ');
|
||||||
|
missing.append(pkgName);
|
||||||
|
}
|
||||||
|
}
|
||||||
if(!missing.empty()) {
|
if(!missing.empty()) {
|
||||||
throw runtime_error("The following packages can not be found:" + missing);
|
throw runtime_error("The following packages can not be found:" + missing);
|
||||||
} else {
|
} else {
|
||||||
cerr << "Adding the following packages:";
|
cerr << "Adding the following packages:";
|
||||||
for(const auto &pkg : m_packages) {
|
for(const auto &pkg : m_packages) {
|
||||||
cerr << ' ' << pkg.second.name();
|
cerr << ' ' << pkg.second->name().toLocal8Bit().data();
|
||||||
}
|
}
|
||||||
cerr << endl;
|
cerr << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MingwBundle::addDependencies(const Package *pkg)
|
||||||
|
{
|
||||||
|
string missing;
|
||||||
|
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()) {
|
||||||
|
if(const auto *pkg = syncDbEntry.second->packageProviding(dep)) {
|
||||||
|
if(missing.empty()) {
|
||||||
|
decltype(m_packages)::value_type entry(syncDbEntry.second.get(), pkg);
|
||||||
|
if(find(m_packages.cbegin(), m_packages.cend(), entry) == m_packages.cend()) {
|
||||||
|
m_packages.emplace_back(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addDependencies(pkg);
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!found) {
|
||||||
|
missing.push_back(' ');
|
||||||
|
missing.append(dep.name.toLocal8Bit().data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!missing.empty()) {
|
||||||
|
throw runtime_error("The following dependencies of the " + string(pkg->name().toLocal8Bit().data()) + " package can not be resolved:" + missing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum class RelevantFileType
|
enum class RelevantFileType
|
||||||
{
|
{
|
||||||
Binary,
|
Binary,
|
||||||
Translation
|
Translation,
|
||||||
|
QtTranslation,
|
||||||
|
QtPlugin,
|
||||||
|
Icon
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class RelevantFileArch
|
enum class RelevantFileArch
|
||||||
{
|
{
|
||||||
x86_64,
|
x86_64,
|
||||||
i686
|
i686,
|
||||||
|
Any
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RelevantFile
|
struct RelevantFile
|
||||||
{
|
{
|
||||||
RelevantFile(const KArchiveFile *file, const RelevantFileType type, const RelevantFileArch arch) :
|
RelevantFile(const KArchiveFile *file, const RelevantFileType type, const RelevantFileArch arch, const QString &subDir = QString()) :
|
||||||
file(file),
|
file(file),
|
||||||
fileType(type),
|
fileType(type),
|
||||||
arch(arch)
|
arch(arch),
|
||||||
|
subDir(subDir)
|
||||||
{}
|
{}
|
||||||
const KArchiveFile *file;
|
const KArchiveFile *file;
|
||||||
RelevantFileType fileType;
|
RelevantFileType fileType;
|
||||||
RelevantFileArch arch;
|
RelevantFileArch arch;
|
||||||
|
QString subDir;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PkgFileInfo
|
struct PkgFileInfo
|
||||||
{
|
{
|
||||||
PkgFileInfo(const QString &path) : path(path), failure(false) {}
|
PkgFileInfo(const QString &name, const QString &path) :
|
||||||
|
name(name),
|
||||||
|
path(path),
|
||||||
|
failure(false)
|
||||||
|
{}
|
||||||
|
QString name;
|
||||||
QString path;
|
QString path;
|
||||||
unique_ptr<KTar> archive;
|
unique_ptr<KTar> archive;
|
||||||
list<RelevantFile> relevantFiles;
|
list<RelevantFile> relevantFiles;
|
||||||
bool failure;
|
bool failure;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void addEntries(PkgFileInfo &pkgFileInfo, RelevantFileType fileType, const KArchiveDirectory *dir, const QString &relPath = QString())
|
||||||
|
{
|
||||||
|
QString newPath = relPath.isEmpty() ? dir->name() : relPath % QChar('/') % dir->name();
|
||||||
|
for(const auto &entryName : dir->entries()) {
|
||||||
|
if(auto *entry = dir->entry(entryName)) {
|
||||||
|
if(entry->isDirectory()) {
|
||||||
|
addEntries(pkgFileInfo, fileType, static_cast<const KArchiveDirectory *>(entry), newPath);
|
||||||
|
} else if(entry->isFile()) {
|
||||||
|
pkgFileInfo.relevantFiles.emplace_back(static_cast<const KArchiveFile *>(entry), fileType, RelevantFileArch::Any, newPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void getFiles(PkgFileInfo &pkgFileInfo)
|
void getFiles(PkgFileInfo &pkgFileInfo)
|
||||||
{
|
{
|
||||||
pkgFileInfo.archive = make_unique<KTar>(pkgFileInfo.path);
|
pkgFileInfo.archive = make_unique<KTar>(pkgFileInfo.path);
|
||||||
|
@ -104,65 +192,190 @@ void getFiles(PkgFileInfo &pkgFileInfo)
|
||||||
if(entry->isFile()) {
|
if(entry->isFile()) {
|
||||||
const auto *binFile = static_cast<const KArchiveFile *>(entry);
|
const auto *binFile = static_cast<const KArchiveFile *>(entry);
|
||||||
pkgFileInfo.relevantFiles.emplace_back(binFile, RelevantFileType::Binary, root.first);
|
pkgFileInfo.relevantFiles.emplace_back(binFile, RelevantFileType::Binary, root.first);
|
||||||
cerr << entryName.toLocal8Bit().data() << endl;
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const auto *libEntry = rootDir->entry(QStringLiteral("lib"));
|
||||||
|
if(libEntry && libEntry->isDirectory()) {
|
||||||
|
const auto *libDir = static_cast<const KArchiveDirectory *>(libEntry);
|
||||||
|
const auto *qtEntry = libDir->entry("qt");
|
||||||
|
if(qtEntry && qtEntry->isDirectory()) {
|
||||||
|
const auto *qtDir = static_cast<const KArchiveDirectory *>(qtEntry);
|
||||||
|
const auto *pluginsEntry = qtDir->entry(QStringLiteral("plugins"));
|
||||||
|
if(pluginsEntry && pluginsEntry->isDirectory()) {
|
||||||
|
const auto *pluginsDir = static_cast<const KArchiveDirectory *>(pluginsEntry);
|
||||||
|
for(const auto &pluginCategory : pluginsDir->entries()) {
|
||||||
|
const auto *categoryEntry = pluginsDir->entry(pluginCategory);
|
||||||
|
if(categoryEntry && categoryEntry->isDirectory()) {
|
||||||
|
const auto *categoryDir = static_cast<const KArchiveDirectory *>(categoryEntry);
|
||||||
|
for(const auto &entryName : categoryDir->entries()) {
|
||||||
|
if(const auto *pluginEntry = categoryDir->entry(entryName)) {
|
||||||
|
if(pluginEntry->isFile()) {
|
||||||
|
const auto *pluginFile = static_cast<const KArchiveFile *>(pluginEntry);
|
||||||
|
pkgFileInfo.relevantFiles.emplace_back(pluginFile, RelevantFileType::QtPlugin, root.first, categoryDir->name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const auto *shareEntry = rootDir->entry(QStringLiteral("share"));
|
||||||
|
if(shareEntry && shareEntry->isDirectory()) {
|
||||||
|
const auto *shareDir = static_cast<const KArchiveDirectory *>(shareEntry);
|
||||||
|
const auto *qtEntry = shareDir->entry(QStringLiteral("qt"));
|
||||||
|
if(qtEntry && qtEntry->isDirectory()) {
|
||||||
|
const auto *qtDir = static_cast<const KArchiveDirectory *>(qtEntry);
|
||||||
|
const auto *trEntry = qtDir->entry(QStringLiteral("translations"));
|
||||||
|
if(trEntry && trEntry->isDirectory()) {
|
||||||
|
const auto trDir = static_cast<const KArchiveDirectory *>(trEntry);
|
||||||
|
for(const auto &entryName : trDir->entries()) {
|
||||||
|
if(entryName.endsWith(QLatin1String(".qm"))) {
|
||||||
|
if(const auto *qmEntry = trDir->entry(entryName)) {
|
||||||
|
if(qmEntry->isFile()) {
|
||||||
|
const auto *qmFile = static_cast<const KArchiveFile *>(qmEntry);
|
||||||
|
pkgFileInfo.relevantFiles.emplace_back(qmFile, RelevantFileType::QtTranslation, root.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(pkgFileInfo.name.compare(QLatin1String("qt"))) {
|
||||||
|
const auto *appEntry = shareDir->entry(pkgFileInfo.name);
|
||||||
|
if(appEntry && appEntry->isDirectory()) {
|
||||||
|
const auto *appDir = static_cast<const KArchiveDirectory *>(appEntry);
|
||||||
|
const auto *trEntry = appDir->entry(QStringLiteral("translations"));
|
||||||
|
if(trEntry && trEntry->isDirectory()) {
|
||||||
|
const auto trDir = static_cast<const KArchiveDirectory *>(trEntry);
|
||||||
|
for(const auto &entryName : trDir->entries()) {
|
||||||
|
if(entryName.endsWith(QLatin1String(".qm"))) {
|
||||||
|
if(const auto *qmEntry = trDir->entry(entryName)) {
|
||||||
|
if(qmEntry->isFile()) {
|
||||||
|
const auto *qmFile = static_cast<const KArchiveFile *>(qmEntry);
|
||||||
|
pkgFileInfo.relevantFiles.emplace_back(qmFile, RelevantFileType::Translation, root.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
const auto *iconsEntry = pkgFileInfo.archive->directory()->entry(QStringLiteral("usr/share/icons"));
|
||||||
|
if(iconsEntry && iconsEntry->isDirectory()) {
|
||||||
|
const auto *iconsDir = static_cast<const KArchiveDirectory *>(iconsEntry);
|
||||||
|
for(const auto &themeName : iconsDir->entries()) {
|
||||||
|
const auto *themeEntry = iconsDir->entry(themeName);
|
||||||
|
if(themeEntry && themeEntry->isDirectory()) {
|
||||||
|
addEntries(pkgFileInfo, RelevantFileType::Icon, static_cast<const KArchiveDirectory *>(themeEntry));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
pkgFileInfo.failure = true;
|
pkgFileInfo.failure = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MingwBundle::createBundle(const string &path) const
|
void MingwBundle::createBundle(const string &targetDir, const string &targetName, const string &targetFormat) const
|
||||||
{
|
{
|
||||||
|
cerr << "Gathering relevant files ..." << endl;
|
||||||
|
// get package files
|
||||||
list<PkgFileInfo> pkgFiles;
|
list<PkgFileInfo> pkgFiles;
|
||||||
for(const auto &entry : m_packages) {
|
for(const auto &entry : m_packages) {
|
||||||
QString pkgFile;
|
QString pkgFile;
|
||||||
if(!entry.first.packagesDirectory().isEmpty()) {
|
if(!entry.first->packagesDirectory().isEmpty()) {
|
||||||
pkgFile = QStringLiteral("%1/%2").arg(entry.first.packagesDirectory(), QString::fromLocal8Bit(entry.second.fileName()));
|
pkgFile = entry.first->packagesDirectory() % QChar('/') % entry.second->fileName();
|
||||||
}
|
}
|
||||||
if(pkgFile.isEmpty() || !QFile::exists(pkgFile)) {
|
if(pkgFile.isEmpty() || !QFile::exists(pkgFile)) {
|
||||||
if(!m_manager.pacmanCacheDir().isEmpty()) {
|
if(!m_manager.pacmanCacheDir().isEmpty()) {
|
||||||
pkgFile = QStringLiteral("%1/%2").arg(m_manager.pacmanCacheDir(), QString::fromLocal8Bit(entry.second.fileName()));
|
pkgFile = m_manager.pacmanCacheDir() % QChar('/') % entry.second->fileName();
|
||||||
}
|
}
|
||||||
if(pkgFile.isEmpty() || !QFile::exists(pkgFile)) {
|
if(pkgFile.isEmpty() || !QFile::exists(pkgFile)) {
|
||||||
throw runtime_error("The package file " + string(entry.second.fileName()) + " can't be found.");
|
throw runtime_error("The package file " + string(entry.second->fileName().toLocal8Bit().data()) + " can't be found.");
|
||||||
// TODO: download package from mirror
|
// TODO: download package from mirror
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pkgFiles.emplace_back(pkgFile);
|
pkgFiles.emplace_back(entry.second->name().startsWith(QLatin1String("mingw-w64-")) ? entry.second->name().mid(10) : entry.second->name(), pkgFile);
|
||||||
}
|
}
|
||||||
|
// get relevant files from packages
|
||||||
QtConcurrent::blockingMap(pkgFiles, getFiles);
|
QtConcurrent::blockingMap(pkgFiles, getFiles);
|
||||||
}
|
// check whether all packages could be opened
|
||||||
|
string failed;
|
||||||
void MingwBundle::addDependencies(const AlpmPackage &pkg)
|
for(const auto &pkgFile : pkgFiles) {
|
||||||
{
|
if(pkgFile.failure) {
|
||||||
string missing;
|
failed.push_back(' ');
|
||||||
for(const auto &depInfo : pkg.dependencies()) {
|
failed.append(pkgFile.path.toLocal8Bit().data());
|
||||||
bool found = false;
|
|
||||||
for(const auto &syncDb : m_manager.syncDataBases()) {
|
|
||||||
if(auto pkg = syncDb.second.package(depInfo->name)) {
|
|
||||||
if(missing.empty()) {
|
|
||||||
m_packages.emplace_back(syncDb.second, pkg);
|
|
||||||
}
|
|
||||||
addDependencies(pkg);
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!found) {
|
|
||||||
missing.push_back(' ');
|
|
||||||
missing.append(depInfo->name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!missing.empty()) {
|
if(!failed.empty()) {
|
||||||
throw runtime_error("The following dependencies of the " + string(pkg.name()) + " package can not be resolved:" + missing);
|
throw runtime_error("Unable to open the following package files:" + failed);
|
||||||
|
}
|
||||||
|
// make a list with package info to be included in the target archive
|
||||||
|
QJsonArray pkgArray;
|
||||||
|
for(const auto &entry : m_packages) {
|
||||||
|
pkgArray << entry.second->basicInfo(true);
|
||||||
|
}
|
||||||
|
QJsonDocument pkgList;
|
||||||
|
pkgList.setArray(pkgArray);
|
||||||
|
QByteArray pkgListBytes = pkgList.toJson();
|
||||||
|
// make target archive
|
||||||
|
static const QString user(QStringLiteral("root"));
|
||||||
|
static const QString &group = user;
|
||||||
|
static const pair<RelevantFileArch, QString> roots[] = {
|
||||||
|
make_pair(RelevantFileArch::x86_64, QStringLiteral("x86_64-w64-mingw32")),
|
||||||
|
make_pair(RelevantFileArch::i686, QStringLiteral("i686-w64-mingw32"))
|
||||||
|
};
|
||||||
|
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;
|
||||||
|
unique_ptr<KArchive> targetArchive;
|
||||||
|
if(targetFormat == "7z") {
|
||||||
|
targetArchive = make_unique<K7Zip>(targetPath);
|
||||||
|
} else if(targetFormat == "zip") {
|
||||||
|
targetArchive = make_unique<KZip>(targetPath);
|
||||||
|
} else if(ConversionUtilities::startsWith<string>(targetFormat, "tar")) {
|
||||||
|
targetArchive = make_unique<KTar>(targetPath);
|
||||||
|
} else {
|
||||||
|
throw runtime_error("Specified archive format \"" + targetFormat + "\" is unknown.");
|
||||||
|
}
|
||||||
|
if(targetArchive->open(QIODevice::WriteOnly)) {
|
||||||
|
// add package list
|
||||||
|
targetArchive->writeFile(root.second % QStringLiteral("/var/lib/repoindex/packages.list"), pkgListBytes, 0100644, user, group);
|
||||||
|
// add relevant files from packages
|
||||||
|
for(const auto &pkgFile : pkgFiles) {
|
||||||
|
for(const RelevantFile &relevantFile : pkgFile.relevantFiles) {
|
||||||
|
if(relevantFile.arch == RelevantFileArch::Any || relevantFile.arch == root.first) {
|
||||||
|
switch(relevantFile.fileType) {
|
||||||
|
case RelevantFileType::Binary:
|
||||||
|
targetArchive->writeFile(root.second % QStringLiteral("/bin/") % relevantFile.file->name(), relevantFile.file->data(), 0100755, user, group);
|
||||||
|
break;
|
||||||
|
case RelevantFileType::Translation:
|
||||||
|
targetArchive->writeFile(root.second % QStringLiteral("/share/") % pkgFile.name % QStringLiteral("/translations/") % relevantFile.file->name(), relevantFile.file->data(), 0100644, user, group);
|
||||||
|
break;
|
||||||
|
case RelevantFileType::QtTranslation:
|
||||||
|
targetArchive->writeFile(root.second % QStringLiteral("/share/qt/translations/") % relevantFile.file->name(), relevantFile.file->data(), 0100644, user, group);
|
||||||
|
break;
|
||||||
|
case RelevantFileType::QtPlugin:
|
||||||
|
targetArchive->writeFile(root.second % QStringLiteral("/bin/") % relevantFile.subDir % QChar('/') % relevantFile.file->name(), relevantFile.file->data(), 0100755, user, group);
|
||||||
|
break;
|
||||||
|
case RelevantFileType::Icon:
|
||||||
|
targetArchive->writeFile(root.second % QStringLiteral("/share/icons/") % relevantFile.subDir % QChar('/') % relevantFile.file->name(), relevantFile.file->data(), 0100644, user, group);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if(targetArchive->device()) {
|
||||||
|
throw runtime_error("Unable to open target archive: " + string(targetArchive->device()->errorString().toLocal8Bit().data()));
|
||||||
|
} else {
|
||||||
|
throw runtime_error("Unable to open target archive.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define PACKAGEMANAGEMENT_MINGWBUNDLE_H
|
#define PACKAGEMANAGEMENT_MINGWBUNDLE_H
|
||||||
|
|
||||||
#include "package.h"
|
#include "package.h"
|
||||||
#include "database.h"
|
#include "alpmdatabase.h"
|
||||||
|
|
||||||
#include <c++utilities/application/argumentparser.h>
|
#include <c++utilities/application/argumentparser.h>
|
||||||
|
|
||||||
|
@ -15,15 +15,15 @@ class Manager;
|
||||||
class MingwBundle
|
class MingwBundle
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MingwBundle(const Manager &manager, const ApplicationUtilities::StringVector &packages);
|
MingwBundle(const Manager &manager, const ApplicationUtilities::StringVector &packages, const ApplicationUtilities::StringVector &iconPackages);
|
||||||
|
|
||||||
void createBundle(const std::string &path) const;
|
void createBundle(const std::string &targetDir, const std::string &targetName, const std::string &targetFormat) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void addDependencies(const AlpmPackage &pkg);
|
void addDependencies(const Package *pkg);
|
||||||
|
|
||||||
const Manager &m_manager;
|
const Manager &m_manager;
|
||||||
std::list<std::pair<const AlpmDataBase &, AlpmPackage> > m_packages;
|
std::list<std::pair<const AlpmDataBase *, const Package *> > m_packages;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace PackageManagement
|
} // namespace PackageManagement
|
||||||
|
|
404
alpm/package.cpp
404
alpm/package.cpp
|
@ -1,5 +1,7 @@
|
||||||
#include "package.h"
|
#include "package.h"
|
||||||
#include "database.h"
|
#include "alpmdatabase.h"
|
||||||
|
#include "utilities.h"
|
||||||
|
#include "repository.h"
|
||||||
|
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QJsonValue>
|
#include <QJsonValue>
|
||||||
|
@ -11,82 +13,191 @@ using namespace ChronoUtilities;
|
||||||
|
|
||||||
namespace PackageManagement {
|
namespace PackageManagement {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \class The Package class holds meta information about an
|
||||||
|
* Arch Linux package.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Constructs a new package instance.
|
||||||
|
*
|
||||||
|
* Since it is intenced to use the Package class as base class only,
|
||||||
|
* this constructor is protected.
|
||||||
|
*/
|
||||||
|
Package::Package(const QString &name, Repository *source) :
|
||||||
|
m_origin(PackageOrigin::Unknown),
|
||||||
|
m_source(source),
|
||||||
|
m_hasGeneralInfo(false),
|
||||||
|
m_name(name),
|
||||||
|
m_hasInstallScript(false),
|
||||||
|
m_hasBuildRelatedMetaData(false),
|
||||||
|
m_hasInstallRelatedMetaData(false),
|
||||||
|
m_validationMethods(ALPM_PKG_VALIDATION_UNKNOWN),
|
||||||
|
m_installReason(ALPM_PKG_REASON_EXPLICIT),
|
||||||
|
m_id(-1),
|
||||||
|
m_categoryId(-1),
|
||||||
|
m_votes(-1)
|
||||||
|
{
|
||||||
|
// initialization must be done in derived class
|
||||||
|
}
|
||||||
|
|
||||||
|
Package::~Package()
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool Package::matches(const QString &name, const QString &version, const Dependency &dependency)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
case ALPM_DEP_MOD_GE:
|
||||||
|
return (cmp = PackageVersion(version).compare(PackageVersion(dependency.version))) == PackageVersionComparsion::Equal || cmp == PackageVersionComparsion::NewerThenSyncVersion;
|
||||||
|
case ALPM_DEP_MOD_LE:
|
||||||
|
return (cmp = PackageVersion(version).compare(PackageVersion(dependency.version))) == PackageVersionComparsion::Equal || cmp == PackageVersionComparsion::PackageUpgradeOnly || cmp == PackageVersionComparsion::SoftwareUpgrade;
|
||||||
|
case ALPM_DEP_MOD_GT:
|
||||||
|
return PackageVersion(version).compare(PackageVersion(dependency.version)) == PackageVersionComparsion::NewerThenSyncVersion;
|
||||||
|
case ALPM_DEP_MOD_LT:
|
||||||
|
return (cmp = PackageVersion(version).compare(PackageVersion(dependency.version))) == PackageVersionComparsion::PackageUpgradeOnly || cmp == PackageVersionComparsion::SoftwareUpgrade;
|
||||||
|
default:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \cond
|
* \cond
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline QString qstr(const char *str)
|
namespace Utilities {
|
||||||
{
|
|
||||||
return QString::fromLocal8Bit(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline QJsonArray qjarry(StringList list)
|
inline void put(QJsonObject &obj, const QString &key, const QJsonValue &value)
|
||||||
{
|
{
|
||||||
QJsonArray jsonArray;
|
if(!value.isNull()) {
|
||||||
for(const char *str : list) {
|
obj.insert(key, value);
|
||||||
jsonArray << qstr(str);
|
|
||||||
}
|
}
|
||||||
return jsonArray;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline QJsonArray qjarry(DependencyList list)
|
inline void put(QJsonObject &obj, const QString &key, const DateTime dateTime)
|
||||||
{
|
{
|
||||||
QJsonArray jsonArray;
|
if(!dateTime.isNull()) {
|
||||||
for(alpm_depend_t *dep : list) {
|
put(obj, key, QString::fromLocal8Bit(dateTime.toString().data()));
|
||||||
QJsonObject depObj;
|
}
|
||||||
depObj.insert(QStringLiteral("name"), dep->name);
|
}
|
||||||
depObj.insert(QStringLiteral("desc"), dep->desc);
|
|
||||||
depObj.insert(QStringLiteral("ver"), dep->version);
|
inline void put(QJsonObject &obj, const QString &key, const QStringList &values)
|
||||||
switch(dep->mod) {
|
{
|
||||||
case ALPM_DEP_MOD_ANY:
|
if(!values.isEmpty()) {
|
||||||
depObj.insert(QStringLiteral("mod"), QStringLiteral("any"));
|
put(obj, key, QJsonArray::fromStringList(values));
|
||||||
break;
|
}
|
||||||
case ALPM_DEP_MOD_EQ:
|
}
|
||||||
depObj.insert(QStringLiteral("mod"), QStringLiteral("eq"));
|
|
||||||
break;
|
void put(QJsonObject &obj, const QString &key, const QList<Dependency> &dependencies)
|
||||||
case ALPM_DEP_MOD_GE:
|
{
|
||||||
depObj.insert(QStringLiteral("mod"), QStringLiteral("ge"));
|
if(!dependencies.isEmpty()) {
|
||||||
break;
|
QJsonArray jsonArray;
|
||||||
case ALPM_DEP_MOD_LE:
|
for(const auto &dep : dependencies) {
|
||||||
depObj.insert(QStringLiteral("mod"), QStringLiteral("le"));
|
QJsonObject depObj;
|
||||||
break;
|
depObj.insert(QStringLiteral("name"), dep.name);
|
||||||
case ALPM_DEP_MOD_GT:
|
depObj.insert(QStringLiteral("ver"), dep.version);
|
||||||
depObj.insert(QStringLiteral("mod"), QStringLiteral("gt"));
|
switch(dep.mode) {
|
||||||
break;
|
case ALPM_DEP_MOD_ANY:
|
||||||
case ALPM_DEP_MOD_LT:
|
depObj.insert(QStringLiteral("mod"), QStringLiteral("any"));
|
||||||
depObj.insert(QStringLiteral("mod"), QStringLiteral("lt"));
|
break;
|
||||||
break;
|
case ALPM_DEP_MOD_EQ:
|
||||||
|
depObj.insert(QStringLiteral("mod"), QStringLiteral("eq"));
|
||||||
|
break;
|
||||||
|
case ALPM_DEP_MOD_GE:
|
||||||
|
depObj.insert(QStringLiteral("mod"), QStringLiteral("ge"));
|
||||||
|
break;
|
||||||
|
case ALPM_DEP_MOD_LE:
|
||||||
|
depObj.insert(QStringLiteral("mod"), QStringLiteral("le"));
|
||||||
|
break;
|
||||||
|
case ALPM_DEP_MOD_GT:
|
||||||
|
depObj.insert(QStringLiteral("mod"), QStringLiteral("gt"));
|
||||||
|
break;
|
||||||
|
case ALPM_DEP_MOD_LT:
|
||||||
|
depObj.insert(QStringLiteral("mod"), QStringLiteral("lt"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
jsonArray << depObj;
|
||||||
}
|
}
|
||||||
jsonArray << depObj;
|
put(obj, key, jsonArray);
|
||||||
}
|
}
|
||||||
return jsonArray;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline QJsonArray qjarry(_alpm_pkgvalidation_t validation)
|
|
||||||
{
|
|
||||||
QJsonArray jsonArray;
|
|
||||||
if(validation & 0x1) {
|
|
||||||
jsonArray << QStringLiteral("none");
|
|
||||||
}
|
|
||||||
if(validation & 0x2) {
|
|
||||||
jsonArray << QStringLiteral("MD5");
|
|
||||||
}
|
|
||||||
if(validation & 0x4) {
|
|
||||||
jsonArray << QStringLiteral("SHA256");
|
|
||||||
}
|
|
||||||
if(validation & 0x8) {
|
|
||||||
jsonArray << QStringLiteral("signature");
|
|
||||||
}
|
|
||||||
if(jsonArray.empty()) {
|
|
||||||
jsonArray << QStringLiteral("unknown");
|
|
||||||
}
|
|
||||||
return jsonArray;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \endcond
|
* \endcond
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using namespace Utilities;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns basic information about the packages as JSON object.
|
||||||
|
*/
|
||||||
|
QJsonObject Package::basicInfo(bool includeRepoAndName) const
|
||||||
|
{
|
||||||
|
QJsonObject info;
|
||||||
|
if(includeRepoAndName) {
|
||||||
|
if(source()) {
|
||||||
|
put(info, QStringLiteral("repo"), source()->name());
|
||||||
|
}
|
||||||
|
put(info, QStringLiteral("name"), name());
|
||||||
|
}
|
||||||
|
put(info, QStringLiteral("archs"), architectures());
|
||||||
|
put(info, QStringLiteral("arch"), buildArchitecture());
|
||||||
|
put(info, QStringLiteral("ver"), version());
|
||||||
|
put(info, QStringLiteral("desc"), description());
|
||||||
|
put(info, QStringLiteral("bdate"), buildDate());
|
||||||
|
put(info, QStringLiteral("flagdate"), outOfDate());
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns full information about the package as JSON object.
|
||||||
|
*/
|
||||||
|
QJsonObject Package::fullInfo(bool includeRepoAndName) const
|
||||||
|
{
|
||||||
|
QJsonObject info;
|
||||||
|
if(includeRepoAndName) {
|
||||||
|
if(source()) {
|
||||||
|
put(info, QStringLiteral("repo"), source()->name());
|
||||||
|
}
|
||||||
|
put(info, QStringLiteral("name"), name());
|
||||||
|
}
|
||||||
|
put(info, QStringLiteral("archs"), architectures());
|
||||||
|
put(info, QStringLiteral("arch"), buildArchitecture());
|
||||||
|
put(info, QStringLiteral("ver"), version());
|
||||||
|
put(info, QStringLiteral("desc"), description());
|
||||||
|
put(info, QStringLiteral("bdate"), buildDate());
|
||||||
|
put(info, QStringLiteral("bdate"), buildDate());
|
||||||
|
put(info, QStringLiteral("flagdate"), outOfDate());
|
||||||
|
put(info, QStringLiteral("idate"), installDate());
|
||||||
|
put(info, QStringLiteral("isize"), QJsonValue(static_cast<long long int>(installedSize())));
|
||||||
|
put(info, QStringLiteral("url"), upstreamUrl());
|
||||||
|
put(info, QStringLiteral("lic"), licenses());
|
||||||
|
put(info, QStringLiteral("grp"), groups());
|
||||||
|
put(info, QStringLiteral("prov"), provides());
|
||||||
|
put(info, QStringLiteral("optd"), optionalDependencies());
|
||||||
|
put(info, QStringLiteral("deps"), dependencies());
|
||||||
|
put(info, QStringLiteral("requ"), requiredBy());
|
||||||
|
put(info, QStringLiteral("optf"), optionalFor());
|
||||||
|
put(info, QStringLiteral("conf"), conflicts());
|
||||||
|
put(info, QStringLiteral("repl"), replaces());
|
||||||
|
put(info, QStringLiteral("pack"), packer());
|
||||||
|
put(info, QStringLiteral("expl"), QJsonValue(installReason() == ALPM_PKG_REASON_EXPLICIT));
|
||||||
|
put(info, QStringLiteral("scri"), QJsonValue(hasInstallScript()));
|
||||||
|
put(info, QStringLiteral("sig"), Utilities::validationMethodsStrings(validationMethods()));
|
||||||
|
put(info, QStringLiteral("file"), fileName());
|
||||||
|
put(info, QStringLiteral("files"), files());
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief The PackageVersion class helps parsing package versions.
|
* \brief The PackageVersion class helps parsing package versions.
|
||||||
*/
|
*/
|
||||||
|
@ -94,18 +205,11 @@ inline QJsonArray qjarry(_alpm_pkgvalidation_t validation)
|
||||||
/*!
|
/*!
|
||||||
* \brief Constructs a new PackageVersion instance from the specified \a versionStr.
|
* \brief Constructs a new PackageVersion instance from the specified \a versionStr.
|
||||||
*/
|
*/
|
||||||
PackageVersion::PackageVersion(const QString &versionStr) :
|
PackageVersion::PackageVersion(const QString &versionStr)
|
||||||
PackageVersion(versionStr.toLocal8Bit().data())
|
|
||||||
{}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Constructs a new PackageVersion instance from the specified \a versionStr.
|
|
||||||
*/
|
|
||||||
PackageVersion::PackageVersion(const char *versionStr)
|
|
||||||
{
|
{
|
||||||
// determine start offsets of version and release
|
// determine start offsets of version and release
|
||||||
const char *versionBeg = nullptr, *releaseBeg = nullptr;
|
const ushort *str = versionStr.utf16(), *versionBeg = nullptr, *releaseBeg = nullptr;
|
||||||
for(const char *i = versionStr; ; ++i) {
|
for(const auto *i = str; ; ++i) {
|
||||||
switch(*i) {
|
switch(*i) {
|
||||||
case 0:
|
case 0:
|
||||||
goto terminationFound;
|
goto terminationFound;
|
||||||
|
@ -123,22 +227,22 @@ PackageVersion::PackageVersion(const char *versionStr)
|
||||||
terminationFound:
|
terminationFound:
|
||||||
if(versionBeg) {
|
if(versionBeg) {
|
||||||
// epoch present
|
// epoch present
|
||||||
epoch = QString::fromLocal8Bit(versionStr, versionBeg - versionStr - 1);
|
epoch = QString::fromUtf16(str, versionBeg - str - 1);
|
||||||
if(releaseBeg) {
|
if(releaseBeg) {
|
||||||
// release present
|
// release present
|
||||||
version = QString::fromLocal8Bit(versionBeg, releaseBeg - versionBeg - 1);
|
version = QString::fromUtf16(versionBeg, releaseBeg - versionBeg - 1);
|
||||||
release = QString::fromLocal8Bit(releaseBeg);
|
release = QString::fromUtf16(releaseBeg);
|
||||||
} else {
|
} else {
|
||||||
version = QString::fromLocal8Bit(versionBeg);
|
version = QString::fromUtf16(versionBeg);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// epoch not present
|
// epoch not present
|
||||||
if(releaseBeg) {
|
if(releaseBeg) {
|
||||||
// release present
|
// release present
|
||||||
version = QString::fromLocal8Bit(versionStr, releaseBeg - versionStr - 1);
|
version = QString::fromUtf16(str, releaseBeg - str - 1);
|
||||||
release = QString::fromLocal8Bit(releaseBeg);
|
release = QString::fromUtf16(releaseBeg);
|
||||||
} else {
|
} else {
|
||||||
version = QString::fromLocal8Bit(versionStr);
|
version = QString::fromUtf16(str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -227,157 +331,5 @@ PackageVersionComparsion PackageVersion::compare(const PackageVersion &other) co
|
||||||
return PackageVersionComparsion::Equal;
|
return PackageVersionComparsion::Equal;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief The AurPackage class holds information about AUR packages. It allows to convert the information
|
|
||||||
* to JSON objects used by the network classes and the web interface.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Creates a new instance from the specified "AurJson value".
|
|
||||||
*/
|
|
||||||
AurPackage::AurPackage(const QJsonValue &aurJsonValue) :
|
|
||||||
AurPackage()
|
|
||||||
{
|
|
||||||
QJsonObject obj = aurJsonValue.toObject();
|
|
||||||
m_id = obj.value(QStringLiteral("ID")).toInt(-1);
|
|
||||||
m_categoryId = obj.value(QStringLiteral("CategoryID")).toInt(-1);
|
|
||||||
m_name = obj.value(QStringLiteral("Name")).toString();
|
|
||||||
m_version = obj.value(QStringLiteral("Version")).toString();
|
|
||||||
m_description = obj.value(QStringLiteral("Description")).toString();
|
|
||||||
m_upstreamUrl = obj.value(QStringLiteral("URL")).toString();
|
|
||||||
m_votes = obj.value(QStringLiteral("NumVotes")).toInt(0);
|
|
||||||
m_outOfDate = DateTime::fromTimeStamp(obj.value(QStringLiteral("OutOfDate")).toInt());
|
|
||||||
m_maintainer = obj.value(QStringLiteral("Maintainer")).toString();
|
|
||||||
m_firstSubmitted = DateTime::fromTimeStamp(obj.value(QStringLiteral("FirstSubmitted")).toInt());
|
|
||||||
m_lastModified = DateTime::fromTimeStamp(obj.value(QStringLiteral("LastModified")).toInt());
|
|
||||||
m_license = obj.value(QStringLiteral("License")).toString();
|
|
||||||
m_tarUrl = obj.value(QStringLiteral("URLPath")).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns basic information about the packages as JSON object.
|
|
||||||
*/
|
|
||||||
QJsonObject AurPackage::basicInfo(bool includeRepoAndName) const
|
|
||||||
{
|
|
||||||
QJsonObject packageInfo;
|
|
||||||
if(includeRepoAndName) {
|
|
||||||
packageInfo.insert(QStringLiteral("repo"), QStringLiteral("aur"));
|
|
||||||
packageInfo.insert(QStringLiteral("name"), name());
|
|
||||||
}
|
|
||||||
packageInfo.insert(QStringLiteral("arch"), QStringLiteral("n.a."));
|
|
||||||
packageInfo.insert(QStringLiteral("ver"), version());
|
|
||||||
packageInfo.insert(QStringLiteral("desc"), description());
|
|
||||||
packageInfo.insert(QStringLiteral("bdate"), QStringLiteral("n.a."));
|
|
||||||
packageInfo.insert(QStringLiteral("flagdate"), outOfDate().isNull() ? QStringLiteral("none") : qstr(outOfDate().toString().data()));
|
|
||||||
return packageInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns full information about the package as JSON object.
|
|
||||||
*/
|
|
||||||
QJsonObject AurPackage::fullInfo(bool includeRepoAndName) const
|
|
||||||
{
|
|
||||||
QJsonObject packageInfo;
|
|
||||||
if(includeRepoAndName) {
|
|
||||||
packageInfo.insert(QStringLiteral("repo"), QStringLiteral("aur"));
|
|
||||||
packageInfo.insert(QStringLiteral("name"), name());
|
|
||||||
}
|
|
||||||
packageInfo.insert(QStringLiteral("arch"), QStringLiteral("n.a."));
|
|
||||||
packageInfo.insert(QStringLiteral("ver"), version());
|
|
||||||
packageInfo.insert(QStringLiteral("desc"), description());
|
|
||||||
packageInfo.insert(QStringLiteral("bdate"), QStringLiteral("n.a."));
|
|
||||||
packageInfo.insert(QStringLiteral("idate"), QStringLiteral("n.a."));
|
|
||||||
packageInfo.insert(QStringLiteral("isize"), QStringLiteral("n.a."));
|
|
||||||
packageInfo.insert(QStringLiteral("url"), upstreamUrl());
|
|
||||||
packageInfo.insert(QStringLiteral("lic"), license());
|
|
||||||
packageInfo.insert(QStringLiteral("grp"), QStringLiteral("TODO"));
|
|
||||||
packageInfo.insert(QStringLiteral("prov"), QStringLiteral("TODO"));
|
|
||||||
packageInfo.insert(QStringLiteral("optd"), QStringLiteral("TODO"));
|
|
||||||
packageInfo.insert(QStringLiteral("deps"), QStringLiteral("TODO"));
|
|
||||||
packageInfo.insert(QStringLiteral("requ"), QStringLiteral("TODO"));
|
|
||||||
packageInfo.insert(QStringLiteral("optf"), QStringLiteral("TODO"));
|
|
||||||
packageInfo.insert(QStringLiteral("conf"), QStringLiteral("TODO"));
|
|
||||||
packageInfo.insert(QStringLiteral("repl"), QStringLiteral("TODO"));
|
|
||||||
packageInfo.insert(QStringLiteral("pack"), QStringLiteral("n.a."));
|
|
||||||
packageInfo.insert(QStringLiteral("expl"), QStringLiteral("n.a."));
|
|
||||||
packageInfo.insert(QStringLiteral("scri"), QStringLiteral("TODO"));
|
|
||||||
packageInfo.insert(QStringLiteral("sig"), QStringLiteral("TODO"));
|
|
||||||
packageInfo.insert(QStringLiteral("file"), QStringLiteral("n.a."));
|
|
||||||
return packageInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief The AlpmPackage class helps getting information about ALPM packages. It allows to convert the
|
|
||||||
* information to JSON objects used by the network classes and the web interface.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns basic information about the packages as JSON object.
|
|
||||||
*/
|
|
||||||
QJsonObject AlpmPackage::basicInfo(bool includeRepoAndName) const
|
|
||||||
{
|
|
||||||
QJsonObject packageInfo;
|
|
||||||
if(includeRepoAndName) {
|
|
||||||
packageInfo.insert(QStringLiteral("repo"), qstr(AlpmDataBase(associatedDatabase()).name()));
|
|
||||||
packageInfo.insert(QStringLiteral("name"), qstr(name()));
|
|
||||||
}
|
|
||||||
packageInfo.insert(QStringLiteral("arch"), qstr(architecture()));
|
|
||||||
packageInfo.insert(QStringLiteral("ver"), qstr(version()));
|
|
||||||
packageInfo.insert(QStringLiteral("desc"), qstr(description()));
|
|
||||||
packageInfo.insert(QStringLiteral("bdate"), qstr(buildDate().toString().c_str()));
|
|
||||||
packageInfo.insert(QStringLiteral("flagdate"), QStringLiteral("n.a."));
|
|
||||||
return packageInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns full information about the package as JSON object.
|
|
||||||
*/
|
|
||||||
QJsonObject AlpmPackage::fullInfo(bool includeRepoAndName) const
|
|
||||||
{
|
|
||||||
QJsonObject packageInfo;
|
|
||||||
if(includeRepoAndName) {
|
|
||||||
packageInfo.insert(QStringLiteral("repo"), qstr(AlpmDataBase(associatedDatabase()).name()));
|
|
||||||
packageInfo.insert(QStringLiteral("name"), qstr(name()));
|
|
||||||
}
|
|
||||||
packageInfo.insert(QStringLiteral("arch"), qstr(architecture()));
|
|
||||||
packageInfo.insert(QStringLiteral("ver"), qstr(version()));
|
|
||||||
packageInfo.insert(QStringLiteral("desc"), qstr(description()));
|
|
||||||
packageInfo.insert(QStringLiteral("bdate"), qstr(buildDate().toString().c_str()));
|
|
||||||
packageInfo.insert(QStringLiteral("idate"), qstr(installDate().toString().c_str()));
|
|
||||||
packageInfo.insert(QStringLiteral("isize"), static_cast<long long int>(installedSize()));
|
|
||||||
packageInfo.insert(QStringLiteral("url"), qstr(upstreamUrl()));
|
|
||||||
packageInfo.insert(QStringLiteral("lic"), qjarry(licenses()));
|
|
||||||
packageInfo.insert(QStringLiteral("grp"), qjarry(groups()));
|
|
||||||
packageInfo.insert(QStringLiteral("prov"), qjarry(provides()));
|
|
||||||
packageInfo.insert(QStringLiteral("optd"), qjarry(optionalDependencies()));
|
|
||||||
packageInfo.insert(QStringLiteral("deps"), qjarry(dependencies()));
|
|
||||||
packageInfo.insert(QStringLiteral("requ"), qjarry(requiredBy()));
|
|
||||||
packageInfo.insert(QStringLiteral("optf"), qjarry(optionalFor()));
|
|
||||||
packageInfo.insert(QStringLiteral("conf"), qjarry(conflicts()));
|
|
||||||
packageInfo.insert(QStringLiteral("repl"), qjarry(replaces()));
|
|
||||||
packageInfo.insert(QStringLiteral("pack"), qstr(packager()));
|
|
||||||
packageInfo.insert(QStringLiteral("expl"), installReason() == ALPM_PKG_REASON_EXPLICIT);
|
|
||||||
packageInfo.insert(QStringLiteral("scri"), hasInstallScript());
|
|
||||||
packageInfo.insert(QStringLiteral("sig"), qjarry(validation()));
|
|
||||||
packageInfo.insert(QStringLiteral("file"), qstr(fileName()));
|
|
||||||
QJsonArray fileInfos;
|
|
||||||
alpm_filelist_t *fileList = files();
|
|
||||||
for(alpm_file_t *file = fileList->files, *end = fileList->files + fileList->count; file != end; ++file) {
|
|
||||||
QJsonObject fileInfo;
|
|
||||||
fileInfo.insert(QStringLiteral("name"), qstr(file->name));
|
|
||||||
if(file->mode) {
|
|
||||||
fileInfo.insert(QStringLiteral("mode"), static_cast<int>(file->mode));
|
|
||||||
}
|
|
||||||
if(file->size) {
|
|
||||||
fileInfo.insert(QStringLiteral("size"), static_cast<int>(file->size));
|
|
||||||
}
|
|
||||||
fileInfos << fileInfo;
|
|
||||||
}
|
|
||||||
packageInfo.insert(QStringLiteral("files"), fileInfos);
|
|
||||||
return packageInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
795
alpm/package.h
795
alpm/package.h
|
@ -12,14 +12,15 @@
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
|
#include <QJsonArray>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_FORWARD_DECLARE_CLASS(QJsonObject)
|
||||||
class QJsonObject;
|
QT_FORWARD_DECLARE_CLASS(QJsonValue)
|
||||||
class QJsonValue;
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
namespace PackageManagement {
|
namespace PackageManagement {
|
||||||
|
|
||||||
|
class Repository;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief The PackageVersionComparsion enum defines possible results of packages version comparison.
|
* \brief The PackageVersionComparsion enum defines possible results of packages version comparison.
|
||||||
*/
|
*/
|
||||||
|
@ -41,11 +42,29 @@ enum class PackageVersionPartComparsion
|
||||||
Older /*!< Part 2 is newer then part 1. */
|
Older /*!< Part 2 is newer then part 1. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief The PackageOrigin enum describes where a Package instance comes from.
|
||||||
|
*/
|
||||||
|
enum class PackageOrigin
|
||||||
|
{
|
||||||
|
Unknown = 20, /*! The origin is unknown. */
|
||||||
|
File = ALPM_PKG_FROM_FILE, /*!< The instance has been created from a package file; source() returns nullptr in this case. */
|
||||||
|
LocalDb = ALPM_PKG_FROM_LOCALDB, /*! The instance is from the local data base; source() is an AlpmDataBase instance. */
|
||||||
|
SyncDb = ALPM_PKG_FROM_SYNCDB, /*! The instance is from a sync data base; source() is an AlpmDataBase instance. */
|
||||||
|
Aur = 21 /*! The instance is from the AUR; source() is a UserRepository instance. */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class InstallStatus
|
||||||
|
{
|
||||||
|
Explicit = ALPM_PKG_REASON_EXPLICIT,
|
||||||
|
AsDependency = ALPM_PKG_REASON_DEPEND,
|
||||||
|
None = 20
|
||||||
|
};
|
||||||
|
|
||||||
class PackageVersion
|
class PackageVersion
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PackageVersion(const QString &versionStr);
|
explicit PackageVersion(const QString &versionStr);
|
||||||
PackageVersion(const char *versionStr);
|
|
||||||
|
|
||||||
static PackageVersionPartComparsion compareParts(const QString &part1, const QString &part2);
|
static PackageVersionPartComparsion compareParts(const QString &part1, const QString &part2);
|
||||||
PackageVersionComparsion compare(const PackageVersion &other) const;
|
PackageVersionComparsion compare(const PackageVersion &other) const;
|
||||||
|
@ -55,487 +74,525 @@ public:
|
||||||
QString release;
|
QString release;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AurPackage
|
class Dependency
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AurPackage();
|
explicit Dependency(const QString &name, const QString &version, _alpm_depmod_t mode = ALPM_DEP_MOD_ANY);
|
||||||
AurPackage(const QJsonValue &aurJsonValue);
|
QString name;
|
||||||
|
QString version;
|
||||||
|
_alpm_depmod_t mode;
|
||||||
|
};
|
||||||
|
|
||||||
bool isValid() const;
|
inline Dependency::Dependency(const QString &name, const QString &version, _alpm_depmod_t mode) :
|
||||||
bool hasFullInfo() const;
|
name(name),
|
||||||
int id() const;
|
version(version),
|
||||||
int categoryId() const;
|
mode(mode)
|
||||||
|
{}
|
||||||
|
|
||||||
|
class Package
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~Package();
|
||||||
|
|
||||||
|
// general package meta data
|
||||||
|
PackageOrigin origin() const;
|
||||||
|
Repository *source() const;
|
||||||
|
bool hasGeneralInfo() const;
|
||||||
const QString &name() const;
|
const QString &name() const;
|
||||||
const QString &version() const;
|
const QString &version() const;
|
||||||
template<class Package>
|
|
||||||
PackageVersionComparsion compareVersion(const Package &syncPackage) const;
|
|
||||||
const QString &description() const;
|
const QString &description() const;
|
||||||
const QString &upstreamUrl() const;
|
const QString &upstreamUrl() const;
|
||||||
|
const QStringList &licenses() const;
|
||||||
|
const QStringList &groups() const;
|
||||||
|
const QList<Dependency> &dependencies() const;
|
||||||
|
const QList<Dependency> &optionalDependencies() const;
|
||||||
|
const QList<Dependency> &conflicts() const;
|
||||||
|
const QList<Dependency> &provides() const;
|
||||||
|
const QList<Dependency> &replaces() const;
|
||||||
|
const QStringList &requiredBy() const;
|
||||||
|
const QStringList &optionalFor() const;
|
||||||
|
bool hasInstallScript() const;
|
||||||
|
|
||||||
|
// build related meta data
|
||||||
|
bool hasBuildRelatedMetaData() const;
|
||||||
|
const QString &fileName() const;
|
||||||
|
const QJsonArray &files() const;
|
||||||
|
ChronoUtilities::DateTime buildDate() const;
|
||||||
|
const QString &packer() const;
|
||||||
|
const QString &md5() const;
|
||||||
|
const QString &sha256() const;
|
||||||
|
const QString &buildArchitecture() const;
|
||||||
|
uint32 packageSize() const;
|
||||||
|
const QList<Dependency> &makeDependencies() const;
|
||||||
|
|
||||||
|
// installation related meta data
|
||||||
|
bool hasInstallRelatedMetaData() const;
|
||||||
|
ChronoUtilities::DateTime installDate() const;
|
||||||
|
uint32 installedSize() const;
|
||||||
|
const QStringList &backupFiles() const;
|
||||||
|
alpm_pkgvalidation_t validationMethods() const;
|
||||||
|
alpm_pkgreason_t installReason() const;
|
||||||
|
|
||||||
|
// source related meta data
|
||||||
|
bool hasSourceRelatedMetaData() const;
|
||||||
|
const QString &baseName() const;
|
||||||
|
const QStringList &architectures() const;
|
||||||
|
int id() const;
|
||||||
|
int categoryId() const;
|
||||||
int votes() const;
|
int votes() const;
|
||||||
ChronoUtilities::DateTime outOfDate() const;
|
ChronoUtilities::DateTime outOfDate() const;
|
||||||
const QString &maintainer() const;
|
const QString &maintainer() const;
|
||||||
ChronoUtilities::DateTime firstSubmitted() const;
|
ChronoUtilities::DateTime firstSubmitted() const;
|
||||||
ChronoUtilities::DateTime lastModified() const;
|
ChronoUtilities::DateTime lastModified() const;
|
||||||
const QString &license() const;
|
|
||||||
const QString &tarUrl() const;
|
const QString &tarUrl() const;
|
||||||
|
|
||||||
// JSON serialization
|
// version comparsion
|
||||||
QJsonObject basicInfo(bool includeRepoAndName) const;
|
PackageVersionComparsion compareVersion(const Package *syncPackage) const;
|
||||||
QJsonObject fullInfo(bool includeRepoAndName = false) const;
|
PackageVersionComparsion compareVersion(const Dependency &dependency) const;
|
||||||
|
static bool matches(const QString &name, const QString &version, const Dependency &dependency);
|
||||||
private:
|
bool matches(const Dependency &dependency);
|
||||||
bool m_fullInfo;
|
|
||||||
int m_id;
|
|
||||||
int m_categoryId;
|
|
||||||
QString m_name;
|
|
||||||
QString m_version;
|
|
||||||
QString m_description;
|
|
||||||
QString m_upstreamUrl;
|
|
||||||
int m_votes;
|
|
||||||
ChronoUtilities::DateTime m_outOfDate;
|
|
||||||
QString m_maintainer;
|
|
||||||
ChronoUtilities::DateTime m_firstSubmitted;
|
|
||||||
ChronoUtilities::DateTime m_lastModified;
|
|
||||||
QString m_license;
|
|
||||||
QString m_tarUrl;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Constructs a empty, invalid AUR package.
|
|
||||||
*/
|
|
||||||
inline AurPackage::AurPackage() :
|
|
||||||
m_fullInfo(false),
|
|
||||||
m_id(-1),
|
|
||||||
m_categoryId(-1),
|
|
||||||
m_votes(-1),
|
|
||||||
m_outOfDate(false)
|
|
||||||
{}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns an indication whether the package is valid.
|
|
||||||
*/
|
|
||||||
inline bool AurPackage::isValid() const
|
|
||||||
{
|
|
||||||
return m_id >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns an indication whether full package info is available.
|
|
||||||
*/
|
|
||||||
inline bool AurPackage::hasFullInfo() const
|
|
||||||
{
|
|
||||||
return m_fullInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns the ID of the package in the AUR.
|
|
||||||
*/
|
|
||||||
inline int AurPackage::id() const
|
|
||||||
{
|
|
||||||
return m_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns the category ID of the package in the AUR.
|
|
||||||
*/
|
|
||||||
inline int AurPackage::categoryId() const
|
|
||||||
{
|
|
||||||
return m_categoryId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns the name of the package.
|
|
||||||
*/
|
|
||||||
inline const QString &AurPackage::name() const
|
|
||||||
{
|
|
||||||
return m_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns the version of the package.
|
|
||||||
*/
|
|
||||||
inline const QString &AurPackage::version() const
|
|
||||||
{
|
|
||||||
return m_version;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Package>
|
|
||||||
inline PackageVersionComparsion AurPackage::compareVersion(const Package &syncPackage) const
|
|
||||||
{
|
|
||||||
return PackageVersion(version()).compare(PackageVersion(syncPackage.version()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns the description of the package.
|
|
||||||
*/
|
|
||||||
inline const QString &AurPackage::description() const
|
|
||||||
{
|
|
||||||
return m_description;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns the upstream URL of the package.
|
|
||||||
*/
|
|
||||||
inline const QString &AurPackage::upstreamUrl() const
|
|
||||||
{
|
|
||||||
return m_upstreamUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns the votes of the package in the AUR.
|
|
||||||
*/
|
|
||||||
inline int AurPackage::votes() const
|
|
||||||
{
|
|
||||||
return m_votes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns wheter the package is flagged as out-of-date.
|
|
||||||
*/
|
|
||||||
inline ChronoUtilities::DateTime AurPackage::outOfDate() const
|
|
||||||
{
|
|
||||||
return m_outOfDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns the maintainer of the package.
|
|
||||||
*/
|
|
||||||
inline const QString &AurPackage::maintainer() const
|
|
||||||
{
|
|
||||||
return m_maintainer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns the time the package was first submitted.
|
|
||||||
*/
|
|
||||||
inline ChronoUtilities::DateTime AurPackage::firstSubmitted() const
|
|
||||||
{
|
|
||||||
return m_firstSubmitted;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns the time the package was last modified.
|
|
||||||
*/
|
|
||||||
inline ChronoUtilities::DateTime AurPackage::lastModified() const
|
|
||||||
{
|
|
||||||
return m_lastModified;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns the license.
|
|
||||||
*/
|
|
||||||
inline const QString &AurPackage::license() const
|
|
||||||
{
|
|
||||||
return m_license;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Returns a URL to the tar file from AUR.
|
|
||||||
*/
|
|
||||||
inline const QString &AurPackage::tarUrl() const
|
|
||||||
{
|
|
||||||
return m_tarUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
class AlpmPackage
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AlpmPackage(alpm_pkg_t *package = nullptr);
|
|
||||||
|
|
||||||
// package properties
|
|
||||||
const alpm_pkg_t *ptr() const;
|
|
||||||
alpm_pkg_t *ptr();
|
|
||||||
bool hasInstallScript() const;
|
|
||||||
const char *fileName() const;
|
|
||||||
const char *name() const;
|
|
||||||
const char *version() const;
|
|
||||||
template<class Package>
|
|
||||||
PackageVersionComparsion compareVersion(const Package &syncPackage) const;
|
|
||||||
alpm_pkgfrom_t origin() const;
|
|
||||||
const char *description() const;
|
|
||||||
const char *upstreamUrl() const;
|
|
||||||
ChronoUtilities::DateTime buildDate() const;
|
|
||||||
ChronoUtilities::DateTime installDate() const;
|
|
||||||
const char *packager() const;
|
|
||||||
const char *md5() const;
|
|
||||||
const char *sha256() const;
|
|
||||||
const char *architecture() const;
|
|
||||||
off_t packageSize() const;
|
|
||||||
off_t installedSize() const;
|
|
||||||
alpm_pkgreason_t installReason() const;
|
|
||||||
void setInstallReason(alpm_pkgreason_t reason);
|
|
||||||
StringList licenses() const;
|
|
||||||
StringList groups() const;
|
|
||||||
DependencyList dependencies() const;
|
|
||||||
DependencyList optionalDependencies() const;
|
|
||||||
DependencyList conflicts() const;
|
|
||||||
DependencyList provides() const;
|
|
||||||
StringList deltas() const;
|
|
||||||
DependencyList replaces() const;
|
|
||||||
alpm_filelist_t *files() const;
|
|
||||||
AlpmList<alpm_backup_t *> backupFiles() const;
|
|
||||||
alpm_db_t *associatedDatabase() const;
|
|
||||||
const char *base64Signature() const;
|
|
||||||
alpm_pkgvalidation_t validation() const;
|
|
||||||
StringList requiredBy() const;
|
|
||||||
StringList optionalFor() const;
|
|
||||||
void *openChangelog() const;
|
|
||||||
size_t readChangelog(void *changelog, void *buffer, size_t bufferSize);
|
|
||||||
bool closeChangelog(void *changelog);
|
|
||||||
operator bool() const;
|
|
||||||
|
|
||||||
// JSON serialization
|
// JSON serialization
|
||||||
QJsonObject basicInfo(bool includeRepoAndName = false) const;
|
QJsonObject basicInfo(bool includeRepoAndName = false) const;
|
||||||
QJsonObject fullInfo(bool includeRepoAndName = false) const;
|
QJsonObject fullInfo(bool includeRepoAndName = false) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
alpm_pkg_t *m_ptr;
|
explicit Package(const QString &name, Repository *source);
|
||||||
|
|
||||||
|
PackageOrigin m_origin;
|
||||||
|
Repository *m_source;
|
||||||
|
|
||||||
|
// general package meta data
|
||||||
|
bool m_hasGeneralInfo;
|
||||||
|
QString m_name;
|
||||||
|
QString m_version;
|
||||||
|
QString m_description;
|
||||||
|
QString m_upstreamUrl;
|
||||||
|
QStringList m_licenses;
|
||||||
|
QStringList m_groups;
|
||||||
|
QList<Dependency> m_dependencies;
|
||||||
|
QList<Dependency> m_optionalDependencies;
|
||||||
|
QList<Dependency> m_conflicts;
|
||||||
|
QList<Dependency> m_provides;
|
||||||
|
QList<Dependency> m_replaces;
|
||||||
|
QStringList m_requiredBy;
|
||||||
|
QStringList m_optionalFor;
|
||||||
|
bool m_hasInstallScript;
|
||||||
|
|
||||||
|
// build related meta data
|
||||||
|
bool m_hasBuildRelatedMetaData;
|
||||||
|
QString m_fileName;
|
||||||
|
QJsonArray m_files;
|
||||||
|
ChronoUtilities::DateTime m_buildDate;
|
||||||
|
QString m_packer;
|
||||||
|
QString m_md5;
|
||||||
|
QString m_sha256;
|
||||||
|
QString m_buildArchitecture;
|
||||||
|
uint32 m_packageSize;
|
||||||
|
QList<Dependency> m_makeDependencies;
|
||||||
|
|
||||||
|
// installation related meta data
|
||||||
|
bool m_hasInstallRelatedMetaData;
|
||||||
|
ChronoUtilities::DateTime m_installDate;
|
||||||
|
uint32 m_installedSize;
|
||||||
|
QStringList m_backupFiles;
|
||||||
|
alpm_pkgvalidation_t m_validationMethods;
|
||||||
|
alpm_pkgreason_t m_installReason;
|
||||||
|
|
||||||
|
// source related meta data
|
||||||
|
bool m_hasSourceRelatedMetaData;
|
||||||
|
QString m_baseName;
|
||||||
|
QStringList m_architectures;
|
||||||
|
int m_id;
|
||||||
|
int m_categoryId;
|
||||||
|
int m_votes;
|
||||||
|
ChronoUtilities::DateTime m_outOfDate;
|
||||||
|
QString m_maintainer;
|
||||||
|
ChronoUtilities::DateTime m_firstSubmitted;
|
||||||
|
ChronoUtilities::DateTime m_lastModified;
|
||||||
|
QString m_tarUrl;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline uint qHash(const AlpmPackage &key)
|
|
||||||
{
|
|
||||||
return qHash(key.ptr());
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Constructs a new package instance for the specified ALPM \a package.
|
* \brief Returns where the package instance comes from (local db, sync db, pkg file, AUR).
|
||||||
*/
|
*/
|
||||||
inline AlpmPackage::AlpmPackage(alpm_pkg_t *package) :
|
inline PackageOrigin Package::origin() const
|
||||||
m_ptr(package)
|
|
||||||
{}
|
|
||||||
|
|
||||||
inline const alpm_pkg_t *AlpmPackage::ptr() const
|
|
||||||
{
|
{
|
||||||
return m_ptr;
|
return m_origin;
|
||||||
}
|
|
||||||
|
|
||||||
inline alpm_pkg_t *AlpmPackage::ptr()
|
|
||||||
{
|
|
||||||
return m_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool AlpmPackage::hasInstallScript() const
|
|
||||||
{
|
|
||||||
return alpm_pkg_has_scriptlet(m_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const char *AlpmPackage::fileName() const
|
|
||||||
{
|
|
||||||
return alpm_pkg_get_filename(m_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const char *AlpmPackage::name() const
|
|
||||||
{
|
|
||||||
return alpm_pkg_get_name(m_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const char *AlpmPackage::version() const
|
|
||||||
{
|
|
||||||
return alpm_pkg_get_version(m_ptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Compares the version of this package with the version of the specified package.
|
* \brief Returns the package source.
|
||||||
|
* \remarks Might be nullptr if no source is associated.
|
||||||
|
*/
|
||||||
|
inline Repository *Package::source() const
|
||||||
|
{
|
||||||
|
return m_source;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns whether general information is available for the package.
|
||||||
|
*/
|
||||||
|
inline bool Package::hasGeneralInfo() const
|
||||||
|
{
|
||||||
|
return m_hasGeneralInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the name.
|
||||||
|
*/
|
||||||
|
inline const QString &Package::name() const
|
||||||
|
{
|
||||||
|
return m_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the version.
|
||||||
|
*/
|
||||||
|
inline const QString &Package::version() const
|
||||||
|
{
|
||||||
|
return m_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the description.
|
||||||
|
*/
|
||||||
|
inline const QString &Package::description() const
|
||||||
|
{
|
||||||
|
return m_description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the upstream URL.
|
||||||
|
*/
|
||||||
|
inline const QString &Package::upstreamUrl() const
|
||||||
|
{
|
||||||
|
return m_upstreamUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the licenses.
|
||||||
|
*/
|
||||||
|
inline const QStringList &Package::licenses() const
|
||||||
|
{
|
||||||
|
return m_licenses;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the groups.
|
||||||
|
*/
|
||||||
|
inline const QStringList &Package::groups() const
|
||||||
|
{
|
||||||
|
return m_groups;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the dependencies.
|
||||||
|
*/
|
||||||
|
inline const QList<Dependency> &Package::dependencies() const
|
||||||
|
{
|
||||||
|
return m_dependencies;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the optional dependencies.
|
||||||
|
*/
|
||||||
|
inline const QList<Dependency> &Package::optionalDependencies() const
|
||||||
|
{
|
||||||
|
return m_optionalDependencies;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns conflicting packages.
|
||||||
|
*/
|
||||||
|
inline const QList<Dependency> &Package::conflicts() const
|
||||||
|
{
|
||||||
|
return m_conflicts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns provides.
|
||||||
|
*/
|
||||||
|
inline const QList<Dependency> &Package::provides() const
|
||||||
|
{
|
||||||
|
return m_provides;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns packages which are replaced by this package.
|
||||||
|
*/
|
||||||
|
inline const QList<Dependency> &Package::replaces() const
|
||||||
|
{
|
||||||
|
return m_replaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns packages requiring this packages.
|
||||||
|
*/
|
||||||
|
inline const QStringList &Package::requiredBy() const
|
||||||
|
{
|
||||||
|
return m_requiredBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns packages having this package as optional dependency.
|
||||||
|
*/
|
||||||
|
inline const QStringList &Package::optionalFor() const
|
||||||
|
{
|
||||||
|
return m_optionalFor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns whether the package has an install script.
|
||||||
|
*/
|
||||||
|
inline bool Package::hasInstallScript() const
|
||||||
|
{
|
||||||
|
return m_hasInstallScript;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns whether the package has build-related meta data.
|
||||||
*
|
*
|
||||||
* This method distinguishes between software upgrades and package releases. See Alpm::PackageVersionComparsion enum.
|
* Build-related meta data is information about a particular package file such
|
||||||
|
* as architecture, file name, build date, ....
|
||||||
*/
|
*/
|
||||||
template<class Package>
|
inline bool Package::hasBuildRelatedMetaData() const
|
||||||
inline PackageVersionComparsion AlpmPackage::compareVersion(const Package &syncPackage) const
|
|
||||||
{
|
{
|
||||||
return PackageVersion(version()).compare(PackageVersion(syncPackage.version()));
|
return m_hasBuildRelatedMetaData;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline alpm_pkgfrom_t AlpmPackage::origin() const
|
/*!
|
||||||
|
* \brief Returns the file name of the package file.
|
||||||
|
*/
|
||||||
|
inline const QString &Package::fileName() const
|
||||||
{
|
{
|
||||||
return alpm_pkg_get_origin(m_ptr);
|
return m_fileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const char *AlpmPackage::description() const
|
/*!
|
||||||
|
* \brief Returns the file of the package as JSON array.
|
||||||
|
*/
|
||||||
|
inline const QJsonArray &Package::files() const
|
||||||
{
|
{
|
||||||
return alpm_pkg_get_desc(m_ptr);
|
return m_files;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const char *AlpmPackage::upstreamUrl() const
|
/*!
|
||||||
|
* \brief Returns the build date of the package file.
|
||||||
|
*/
|
||||||
|
inline ChronoUtilities::DateTime Package::buildDate() const
|
||||||
{
|
{
|
||||||
return alpm_pkg_get_url(m_ptr);
|
return m_buildDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ChronoUtilities::DateTime AlpmPackage::buildDate() const
|
/*!
|
||||||
|
* \brief Returns the packer of the package file.
|
||||||
|
*/
|
||||||
|
inline const QString &Package::packer() const
|
||||||
{
|
{
|
||||||
return ChronoUtilities::DateTime::fromTimeStamp(static_cast<time_t>(alpm_pkg_get_builddate(m_ptr)));
|
return m_packer;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ChronoUtilities::DateTime AlpmPackage::installDate() const
|
/*!
|
||||||
|
* \brief Returns the MD5 hash of the package file.
|
||||||
|
*/
|
||||||
|
inline const QString &Package::md5() const
|
||||||
{
|
{
|
||||||
return ChronoUtilities::DateTime::fromTimeStamp(static_cast<time_t>(alpm_pkg_get_installdate(m_ptr)));
|
return m_md5;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const char *AlpmPackage::packager() const
|
/*!
|
||||||
|
* \brief Returns the SHA-256 hash of the package file.
|
||||||
|
*/
|
||||||
|
inline const QString &Package::sha256() const
|
||||||
{
|
{
|
||||||
return alpm_pkg_get_packager(m_ptr);
|
return m_sha256;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const char *AlpmPackage::md5() const
|
/*!
|
||||||
|
* \brief Returns the architecture of the package file.
|
||||||
|
*/
|
||||||
|
inline const QString &Package::buildArchitecture() const
|
||||||
{
|
{
|
||||||
return alpm_pkg_get_md5sum(m_ptr);
|
return m_buildArchitecture;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const char *AlpmPackage::sha256() const
|
/*!
|
||||||
|
* \brief Returns the size of the package file.
|
||||||
|
*/
|
||||||
|
inline uint32 Package::packageSize() const
|
||||||
{
|
{
|
||||||
return alpm_pkg_get_sha256sum(m_ptr);
|
return m_packageSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const char *AlpmPackage::architecture() const
|
/*!
|
||||||
|
* \brief Returns make dependencies.
|
||||||
|
*/
|
||||||
|
inline const QList<Dependency> &Package::makeDependencies() const
|
||||||
{
|
{
|
||||||
return alpm_pkg_get_arch(m_ptr);
|
return m_makeDependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline off_t AlpmPackage::packageSize() const
|
/*!
|
||||||
|
* \brief Returns whether install-related meta data is available.
|
||||||
|
*
|
||||||
|
* Install-related meta data is information such as the install date,
|
||||||
|
* the installed size, files backuped during installation, ...
|
||||||
|
*
|
||||||
|
* Most of the install-related meta data is only available for packages
|
||||||
|
* from the local data base (see origin()).
|
||||||
|
*/
|
||||||
|
inline bool Package::hasInstallRelatedMetaData() const
|
||||||
{
|
{
|
||||||
return alpm_pkg_get_size(m_ptr);
|
return m_hasInstallRelatedMetaData;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline off_t AlpmPackage::installedSize() const
|
/*!
|
||||||
|
* \brief Returns the install date.
|
||||||
|
*/
|
||||||
|
inline ChronoUtilities::DateTime Package::installDate() const
|
||||||
{
|
{
|
||||||
return alpm_pkg_get_isize(m_ptr);
|
return m_installDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline alpm_pkgreason_t AlpmPackage::installReason() const
|
/*!
|
||||||
|
* \brief Returns the installed size.
|
||||||
|
*/
|
||||||
|
inline uint32 Package::installedSize() const
|
||||||
{
|
{
|
||||||
return alpm_pkg_get_reason(m_ptr);
|
return m_installedSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline StringList AlpmPackage::licenses() const
|
/*!
|
||||||
|
* \brief Returns the files which have been backued up during installation.
|
||||||
|
*/
|
||||||
|
inline const QStringList &Package::backupFiles() const
|
||||||
{
|
{
|
||||||
return alpm_pkg_get_licenses(m_ptr);
|
return m_backupFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline StringList AlpmPackage::groups() const
|
/*!
|
||||||
|
* \brief Returns the validation methods used during installation.
|
||||||
|
*/
|
||||||
|
inline alpm_pkgvalidation_t Package::validationMethods() const
|
||||||
{
|
{
|
||||||
return alpm_pkg_get_groups(m_ptr);
|
return m_validationMethods;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DependencyList AlpmPackage::dependencies() const
|
/*!
|
||||||
|
* \brief Returns whether the package has been installed explicitely or as a dependency.
|
||||||
|
*/
|
||||||
|
inline alpm_pkgreason_t Package::installReason() const
|
||||||
{
|
{
|
||||||
return alpm_pkg_get_depends(m_ptr);
|
return m_installReason;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DependencyList AlpmPackage::optionalDependencies() const
|
/*!
|
||||||
|
* \brief Returns whether source-related meta data is available.
|
||||||
|
*
|
||||||
|
* Source-related meta data is information about the PKGBUILD file such has
|
||||||
|
* its AUR IDs, AUR votes, maintainer, flag date, ...
|
||||||
|
*/
|
||||||
|
inline bool Package::hasSourceRelatedMetaData() const
|
||||||
{
|
{
|
||||||
return alpm_pkg_get_optdepends(m_ptr);
|
return m_hasSourceRelatedMetaData;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DependencyList AlpmPackage::conflicts() const
|
/*!
|
||||||
|
* \brief Returns the base name.
|
||||||
|
*/
|
||||||
|
inline const QString &Package::baseName() const
|
||||||
{
|
{
|
||||||
return alpm_pkg_get_conflicts(m_ptr);
|
return m_baseName;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DependencyList AlpmPackage::provides() const
|
/*!
|
||||||
|
* \brief Returns the architecutes (from the PKGBUILD file).
|
||||||
|
* \remarks For the architecture of the particular binary package
|
||||||
|
* see buildArchitecture().
|
||||||
|
*/
|
||||||
|
inline const QStringList &Package::architectures() const
|
||||||
{
|
{
|
||||||
return alpm_pkg_get_provides(m_ptr);
|
return m_architectures;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline StringList AlpmPackage::deltas() const
|
/*!
|
||||||
|
* \brief Returns the ID.
|
||||||
|
*/
|
||||||
|
inline int Package::id() const
|
||||||
{
|
{
|
||||||
return alpm_pkg_get_deltas(m_ptr);
|
return m_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DependencyList AlpmPackage::replaces() const
|
/*!
|
||||||
|
* \brief Returns the category ID.
|
||||||
|
*/
|
||||||
|
inline int Package::categoryId() const
|
||||||
{
|
{
|
||||||
return alpm_pkg_get_replaces(m_ptr);
|
return m_categoryId;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline alpm_filelist_t *AlpmPackage::files() const
|
/*!
|
||||||
|
* \brief Returns the votes of the package.
|
||||||
|
*/
|
||||||
|
inline int Package::votes() const
|
||||||
{
|
{
|
||||||
return alpm_pkg_get_files(m_ptr);
|
return m_votes;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline AlpmList<alpm_backup_t *> AlpmPackage::backupFiles() const
|
/*!
|
||||||
|
* \brief Returns the flag date.
|
||||||
|
*/
|
||||||
|
inline ChronoUtilities::DateTime Package::outOfDate() const
|
||||||
{
|
{
|
||||||
return alpm_pkg_get_backup(m_ptr);
|
return m_outOfDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline alpm_db_t *AlpmPackage::associatedDatabase() const
|
/*!
|
||||||
|
* \brief Returns the maintainer.
|
||||||
|
*/
|
||||||
|
inline const QString &Package::maintainer() const
|
||||||
{
|
{
|
||||||
return alpm_pkg_get_db(m_ptr);
|
return m_maintainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const char *AlpmPackage::base64Signature() const
|
/*!
|
||||||
|
* \brief Returns when the package was first submitted.
|
||||||
|
*/
|
||||||
|
inline ChronoUtilities::DateTime Package::firstSubmitted() const
|
||||||
{
|
{
|
||||||
return alpm_pkg_get_base64_sig(m_ptr);
|
return m_firstSubmitted;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline alpm_pkgvalidation_t AlpmPackage::validation() const
|
/*!
|
||||||
|
* \brief Returns the last time when the package was modified.
|
||||||
|
*/
|
||||||
|
inline ChronoUtilities::DateTime Package::lastModified() const
|
||||||
{
|
{
|
||||||
return alpm_pkg_get_validation(m_ptr);
|
return m_lastModified;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline StringList AlpmPackage::requiredBy() const
|
/*!
|
||||||
|
* \brief Returns a URL to a tar file with the sources.
|
||||||
|
*/
|
||||||
|
inline const QString &Package::tarUrl() const
|
||||||
{
|
{
|
||||||
return alpm_pkg_compute_requiredby(m_ptr);
|
return m_tarUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline StringList AlpmPackage::optionalFor() const
|
inline PackageVersionComparsion Package::compareVersion(const Package *syncPackage) const
|
||||||
{
|
{
|
||||||
return alpm_pkg_compute_optionalfor(m_ptr);
|
return PackageVersion(version()).compare(PackageVersion(syncPackage->version()));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void *AlpmPackage::openChangelog() const
|
inline PackageVersionComparsion Package::compareVersion(const Dependency &dependency) const
|
||||||
{
|
{
|
||||||
return alpm_pkg_changelog_open(m_ptr);
|
return PackageVersion(version()).compare(PackageVersion(dependency.version));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t AlpmPackage::readChangelog(void *changelog, void *buffer, size_t bufferSize)
|
inline bool Package::matches(const Dependency &dependency)
|
||||||
{
|
{
|
||||||
return alpm_pkg_changelog_read(buffer, bufferSize, m_ptr, changelog);
|
return matches(name(), version(), dependency);
|
||||||
}
|
|
||||||
|
|
||||||
inline bool AlpmPackage::closeChangelog(void *changelog)
|
|
||||||
{
|
|
||||||
return alpm_pkg_changelog_close(m_ptr, changelog);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline PackageManagement::AlpmPackage::operator bool() const
|
|
||||||
{
|
|
||||||
return m_ptr != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
class AlpmOwnershipPackage : public AlpmPackage
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// constructor, destructor
|
|
||||||
AlpmOwnershipPackage(alpm_pkg_t *package);
|
|
||||||
AlpmOwnershipPackage(const AlpmOwnershipPackage &other) = delete;
|
|
||||||
AlpmOwnershipPackage(AlpmOwnershipPackage &&other);
|
|
||||||
~AlpmOwnershipPackage();
|
|
||||||
|
|
||||||
// assignment operator
|
|
||||||
AlpmOwnershipPackage &operator =(const AlpmOwnershipPackage &other) = delete;
|
|
||||||
AlpmOwnershipPackage &operator =(AlpmOwnershipPackage &&other);
|
|
||||||
};
|
|
||||||
|
|
||||||
inline AlpmOwnershipPackage::AlpmOwnershipPackage(alpm_pkg_t *package) :
|
|
||||||
AlpmPackage(package)
|
|
||||||
{}
|
|
||||||
|
|
||||||
inline AlpmOwnershipPackage::AlpmOwnershipPackage(AlpmOwnershipPackage &&other) :
|
|
||||||
AlpmPackage(other.m_ptr)
|
|
||||||
{
|
|
||||||
other.m_ptr = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline AlpmOwnershipPackage &AlpmOwnershipPackage::operator =(AlpmOwnershipPackage &&other)
|
|
||||||
{
|
|
||||||
if(this != &other) {
|
|
||||||
m_ptr = other.m_ptr;
|
|
||||||
other.m_ptr = nullptr;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline AlpmOwnershipPackage::~AlpmOwnershipPackage()
|
|
||||||
{
|
|
||||||
alpm_pkg_free(ptr());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,298 @@
|
||||||
|
#include "repository.h"
|
||||||
|
#include "upgradelookup.h"
|
||||||
|
#include "utilities.h"
|
||||||
|
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace PackageManagement {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Constructs a new reply.
|
||||||
|
*/
|
||||||
|
Reply::Reply(QNetworkReply *networkReply) :
|
||||||
|
m_networkReply(networkReply)
|
||||||
|
{
|
||||||
|
networkReply->setParent(this);
|
||||||
|
connect(networkReply, &QNetworkReply::finished, this, &Reply::processData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \fn PackageSource::type()
|
||||||
|
* \brief Returns the type of the package source.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns a list of all package names.
|
||||||
|
*/
|
||||||
|
const QStringList PackageManagement::Repository::packageNames() const
|
||||||
|
{
|
||||||
|
QStringList names;
|
||||||
|
names.reserve(m_packages.size());
|
||||||
|
for(const auto &entry : m_packages) {
|
||||||
|
names << entry.first;
|
||||||
|
}
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Requests suggestions for the specified search phrase.
|
||||||
|
* \returns Returns a reply object used for the request. The reply must be destroyed by the caller
|
||||||
|
* using destroyLater() after resultsAvailable() has been emitted.
|
||||||
|
*/
|
||||||
|
SuggestionsReply *Repository::requestSuggestions(const QString &) const
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \class Repository
|
||||||
|
* \brief The Repository class represents a repository (binary repositories as well as source-only repos).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Constructs a new repository (protected since this is a pure virtual class).
|
||||||
|
*/
|
||||||
|
Repository::Repository(const QString &name, QObject *parent) :
|
||||||
|
QObject(parent),
|
||||||
|
m_name(name),
|
||||||
|
m_usage(static_cast<alpm_db_usage_t>(0)),
|
||||||
|
m_sigLevel(static_cast<alpm_siglevel_t>(ALPM_SIGSTATUS_INVALID))
|
||||||
|
{}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Destroys the package source.
|
||||||
|
*/
|
||||||
|
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.
|
||||||
|
*
|
||||||
|
* AlpmDataBase instances load all available packages in the cache
|
||||||
|
* at the beginning and hence do not require explicit requests.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Requests package information for the specified package.
|
||||||
|
* \returns Returns a reply object used for the request. The reply must be destroyed by the caller
|
||||||
|
* using destroyLater() after resultsAvailable() has been emitted.
|
||||||
|
* \remarks
|
||||||
|
* If \a forceUpdate is true, package information which has already been retrieved
|
||||||
|
* and is still cached is requested again. Otherwise these packages will not be
|
||||||
|
* requested again. If it turns out, that all packages are already cached, nullptr
|
||||||
|
* is returned in this case.
|
||||||
|
*/
|
||||||
|
PackageReply *Repository::requestPackageInfo(const QStringList &, bool ) const
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Requests full package information for the specified package.
|
||||||
|
* \returns Returns a reply object used for the request. The reply must be destroyed by the caller
|
||||||
|
* using destroyLater() after resultsAvailable() has been emitted.
|
||||||
|
* \remarks
|
||||||
|
* If \a forceUpdate is true, package information which has already been retrieved
|
||||||
|
* and is still cached is requested again. Otherwise these packages will not be
|
||||||
|
* 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
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the first package providing the specified \a dependency.
|
||||||
|
* \remarks Returns nullptr if no packages provides the \a dependency.
|
||||||
|
*/
|
||||||
|
const Package *Repository::packageProviding(const Dependency &dependency) const
|
||||||
|
{
|
||||||
|
for(const 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(const 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.
|
||||||
|
*/
|
||||||
|
QList<const Package *> Repository::packagesProviding(const Dependency &dependency) const
|
||||||
|
{
|
||||||
|
QList<const Package *> res;
|
||||||
|
for(const auto &entry : m_packages) {
|
||||||
|
if(entry.second->matches(dependency)) {
|
||||||
|
// check whether package matches "directly"
|
||||||
|
res << entry.second.get();
|
||||||
|
} else {
|
||||||
|
// check whether at least one of the provides matches
|
||||||
|
for(const auto &provide : entry.second->provides()) {
|
||||||
|
if(Package::matches(provide.name, provide.version, dependency)) {
|
||||||
|
res << entry.second.get();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns all packages matching the specified predicate.
|
||||||
|
*/
|
||||||
|
QList<Package *> Repository::packageByFilter(std::function<bool (const Package *)> pred)
|
||||||
|
{
|
||||||
|
QList<Package *> packages;
|
||||||
|
for(const auto &entry : m_packages) {
|
||||||
|
if(pred(entry.second.get())) {
|
||||||
|
packages << entry.second.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return packages;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonArray Repository::upgradeSourcesJsonArray() const
|
||||||
|
{
|
||||||
|
QJsonArray sources;
|
||||||
|
for(const auto *source : upgradeSources()) {
|
||||||
|
sources << source->name();
|
||||||
|
}
|
||||||
|
return sources;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Repository::checkForUpgrades(UpgradeLookupResults &results, const QList<const Repository *> &upgradeSources) const
|
||||||
|
{
|
||||||
|
if(upgradeSources.isEmpty()) {
|
||||||
|
results.noSources = true;
|
||||||
|
} else {
|
||||||
|
for(const auto &pkgEntry : packages()) {
|
||||||
|
bool orphaned = true;
|
||||||
|
for(const auto *src : upgradeSources) {
|
||||||
|
if(const auto *syncPkg = src->packageByName(pkgEntry.first)) {
|
||||||
|
switch(pkgEntry.second->compareVersion(syncPkg)) {
|
||||||
|
case PackageVersionComparsion::Equal:
|
||||||
|
break; // ignore equal packages
|
||||||
|
case PackageVersionComparsion::SoftwareUpgrade:
|
||||||
|
results.newVersions << UpgradeResult(syncPkg, pkgEntry.second->version());
|
||||||
|
break;
|
||||||
|
case PackageVersionComparsion::PackageUpgradeOnly:
|
||||||
|
results.newReleases << UpgradeResult(syncPkg, pkgEntry.second->version());
|
||||||
|
break;
|
||||||
|
case PackageVersionComparsion::NewerThenSyncVersion:
|
||||||
|
results.downgrades << UpgradeResult(syncPkg, pkgEntry.second->version());
|
||||||
|
}
|
||||||
|
orphaned = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(orphaned) {
|
||||||
|
results.orphaned << pkgEntry.second.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns all package names as JSON array.
|
||||||
|
*/
|
||||||
|
QJsonArray Repository::packageNamesJsonArray() const
|
||||||
|
{
|
||||||
|
QJsonArray names;
|
||||||
|
for(const auto &entry : m_packages) {
|
||||||
|
names << entry.first;
|
||||||
|
}
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \cond
|
||||||
|
*/
|
||||||
|
|
||||||
|
inline void put(QJsonObject &obj, const QString &key, const QJsonValue &value)
|
||||||
|
{
|
||||||
|
if(!value.isNull()) {
|
||||||
|
obj.insert(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void put(QJsonObject &obj, const QString &key, const QStringList &values)
|
||||||
|
{
|
||||||
|
if(!values.isEmpty()) {
|
||||||
|
put(obj, key, QJsonArray::fromStringList(values));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \endcond
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns basic information about the repository.
|
||||||
|
*/
|
||||||
|
QJsonObject Repository::basicInfo() const
|
||||||
|
{
|
||||||
|
QJsonObject info;
|
||||||
|
put(info, QStringLiteral("name"), name());
|
||||||
|
put(info, QStringLiteral("desc"), description());
|
||||||
|
put(info, QStringLiteral("servers"), serverUrls());
|
||||||
|
put(info, QStringLiteral("usage"), Utilities::usageStrings(usage()));
|
||||||
|
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("srcOnly"), isSourceOnly());
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns group information as JSON object.
|
||||||
|
*/
|
||||||
|
QJsonObject Repository::groupInfo() const
|
||||||
|
{
|
||||||
|
QJsonObject info;
|
||||||
|
put(info, QStringLiteral("repo"), name());
|
||||||
|
QJsonArray groupsArray;
|
||||||
|
for(const auto &groupEntry : groups()) {
|
||||||
|
QJsonObject info;
|
||||||
|
put(info, QStringLiteral("name"), groupEntry.first);
|
||||||
|
QJsonArray pkgNames;
|
||||||
|
for(const auto *pkg : groupEntry.second) {
|
||||||
|
pkgNames << pkg->name();
|
||||||
|
}
|
||||||
|
put(info, QStringLiteral("pkgs"), pkgNames);
|
||||||
|
groupsArray << info;
|
||||||
|
}
|
||||||
|
info.insert(QStringLiteral("groups"), groupsArray);
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace PackageManagement
|
||||||
|
|
|
@ -0,0 +1,288 @@
|
||||||
|
#ifndef PACKAGEMANAGEMENT_PACKAGESOURCE_H
|
||||||
|
#define PACKAGEMANAGEMENT_PACKAGESOURCE_H
|
||||||
|
|
||||||
|
#include "package.h"
|
||||||
|
#include "group.h"
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
QT_FORWARD_DECLARE_CLASS(QNetworkReply)
|
||||||
|
|
||||||
|
namespace PackageManagement {
|
||||||
|
|
||||||
|
class UpgradeLookupResults;
|
||||||
|
|
||||||
|
class Reply : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
Reply(QNetworkReply *networkReply);
|
||||||
|
const QString &error() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void resultsAvailable();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
virtual void processData() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QNetworkReply *m_networkReply;
|
||||||
|
QString m_error;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline const QString &Reply::error() const
|
||||||
|
{
|
||||||
|
return m_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
class PackageReply : public Reply
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
PackageReply(QNetworkReply *networkReply, std::map<QString, std::unique_ptr<Package> > &packages);
|
||||||
|
const std::map<QString, std::unique_ptr<Package> > &packages() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::map<QString, std::unique_ptr<Package> > &m_packages;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline PackageReply::PackageReply(QNetworkReply *networkReply, std::map<QString, std::unique_ptr<Package> > &packages) :
|
||||||
|
Reply(networkReply),
|
||||||
|
m_packages(packages)
|
||||||
|
{}
|
||||||
|
|
||||||
|
inline const std::map<QString, std::unique_ptr<Package> > &PackageReply::packages() const
|
||||||
|
{
|
||||||
|
return m_packages;
|
||||||
|
}
|
||||||
|
|
||||||
|
class SuggestionsReply : public Reply
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
SuggestionsReply(QNetworkReply *networkReply);
|
||||||
|
const QJsonArray &suggestions() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QJsonArray m_suggestions;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline SuggestionsReply::SuggestionsReply(QNetworkReply *networkReply) :
|
||||||
|
Reply(networkReply)
|
||||||
|
{}
|
||||||
|
|
||||||
|
inline const QJsonArray &SuggestionsReply::suggestions() const
|
||||||
|
{
|
||||||
|
return m_suggestions;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class RepositoryType
|
||||||
|
{
|
||||||
|
AlpmDataBase, /*! The repository is an AlpmDataBase instance. */
|
||||||
|
UserRepository, /*! The repository is a UserRepository instance. */
|
||||||
|
Other /*! The repository type is unknown. */
|
||||||
|
};
|
||||||
|
|
||||||
|
class Repository : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
~Repository();
|
||||||
|
|
||||||
|
virtual RepositoryType type() const = 0;
|
||||||
|
|
||||||
|
// general meta data
|
||||||
|
const QString &name() const;
|
||||||
|
const QString &description() const;
|
||||||
|
const std::map<QString, std::unique_ptr<Package> > &packages() const;
|
||||||
|
std::map<QString, std::unique_ptr<Package> > &packages();
|
||||||
|
const QStringList packageNames() const;
|
||||||
|
alpm_db_usage_t usage() const;
|
||||||
|
virtual bool isSourceOnly() const;
|
||||||
|
const std::map<QString, QList<Package *> > &groups() const;
|
||||||
|
const QStringList &serverUrls() const;
|
||||||
|
alpm_siglevel_t sigLevel() const;
|
||||||
|
|
||||||
|
// gathering data
|
||||||
|
virtual bool requestsRequired() 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;
|
||||||
|
|
||||||
|
// package search
|
||||||
|
const Package *packageByName(const QString &name) const;
|
||||||
|
Package *packageByName(const QString &name);
|
||||||
|
const Package *packageProviding(const Dependency &dependency) const;
|
||||||
|
QList<const Package *> packagesProviding(const Dependency &dependency) const;
|
||||||
|
QList<Package *> packageByFilter(std::function<bool (const Package *)> pred);
|
||||||
|
|
||||||
|
// upgrade lookup
|
||||||
|
const QList<const Repository *> &upgradeSources() const;
|
||||||
|
QList<const Repository *> &upgradeSources();
|
||||||
|
QJsonArray upgradeSourcesJsonArray() const;
|
||||||
|
void checkForUpgrades(UpgradeLookupResults &results) const;
|
||||||
|
void checkForUpgrades(UpgradeLookupResults &results, const QList<const Repository *> &upgradeSources) const;
|
||||||
|
|
||||||
|
// build system
|
||||||
|
const QString &sourcesDirectory() const;
|
||||||
|
void setSourcesDirectory(const QString &dir);
|
||||||
|
const QString &packagesDirectory() const;
|
||||||
|
void setPackagesDirectory(const QString &dir);
|
||||||
|
|
||||||
|
// JSON serialization
|
||||||
|
QJsonArray packageNamesJsonArray() const;
|
||||||
|
QJsonObject basicInfo() const;
|
||||||
|
QJsonObject groupInfo() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
explicit Repository(const QString &name, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
QString m_name;
|
||||||
|
QString m_description;
|
||||||
|
std::map<QString, std::unique_ptr<Package> > m_packages;
|
||||||
|
alpm_db_usage_t m_usage;
|
||||||
|
std::map<QString, QList<Package *> > m_groups;
|
||||||
|
QStringList m_serverUrls;
|
||||||
|
alpm_siglevel_t m_sigLevel;
|
||||||
|
QList<const Repository *> m_upgradeSources;
|
||||||
|
QString m_srcDir;
|
||||||
|
QString m_pkgDir;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the name.
|
||||||
|
*/
|
||||||
|
inline const QString &Repository::name() const
|
||||||
|
{
|
||||||
|
return m_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the description.
|
||||||
|
*/
|
||||||
|
inline const QString &Repository::description() const
|
||||||
|
{
|
||||||
|
return m_description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the packages.
|
||||||
|
*/
|
||||||
|
inline const std::map<QString, std::unique_ptr<Package> > &Repository::packages() const
|
||||||
|
{
|
||||||
|
return m_packages;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the packages.
|
||||||
|
*/
|
||||||
|
inline std::map<QString, std::unique_ptr<Package> > &Repository::packages()
|
||||||
|
{
|
||||||
|
return m_packages;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the package with the specified \a name or nullptr if the package can not be found.
|
||||||
|
* \remarks Ownership remains by this instance.
|
||||||
|
*/
|
||||||
|
inline const Package *Repository::packageByName(const QString &name) const
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return m_packages.at(name).get();
|
||||||
|
} catch(const std::out_of_range &) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the package with the specified \a name or nullptr if the package can not be found.
|
||||||
|
* \remarks Ownership remains by this instance.
|
||||||
|
*/
|
||||||
|
inline Package *Repository::packageByName(const QString &name)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return m_packages.at(name).get();
|
||||||
|
} catch(const std::out_of_range &) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline alpm_db_usage_t Repository::usage() const
|
||||||
|
{
|
||||||
|
return m_usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const std::map<QString, QList<Package *> > &Repository::groups() const
|
||||||
|
{
|
||||||
|
return m_groups;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the server URLs.
|
||||||
|
*/
|
||||||
|
inline const QStringList &Repository::serverUrls() const
|
||||||
|
{
|
||||||
|
return m_serverUrls;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the signature level of the database.
|
||||||
|
*/
|
||||||
|
inline alpm_siglevel_t Repository::sigLevel() const
|
||||||
|
{
|
||||||
|
return m_sigLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const QList<const Repository *> &Repository::upgradeSources() const
|
||||||
|
{
|
||||||
|
return m_upgradeSources;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QList<const Repository *> &Repository::upgradeSources()
|
||||||
|
{
|
||||||
|
return m_upgradeSources;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Repository::checkForUpgrades(UpgradeLookupResults &results) const
|
||||||
|
{
|
||||||
|
checkForUpgrades(results, upgradeSources());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the path of the local sources directory.
|
||||||
|
*/
|
||||||
|
inline const QString &Repository::sourcesDirectory() const
|
||||||
|
{
|
||||||
|
return m_srcDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Sets the path of the local sources directory.
|
||||||
|
*/
|
||||||
|
inline void Repository::setSourcesDirectory(const QString &dir)
|
||||||
|
{
|
||||||
|
m_srcDir = dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the path of the local packages directory.
|
||||||
|
*/
|
||||||
|
inline const QString &Repository::packagesDirectory() const
|
||||||
|
{
|
||||||
|
return m_pkgDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Sets the path of the local packages directory.
|
||||||
|
*/
|
||||||
|
inline void Repository::setPackagesDirectory(const QString &dir)
|
||||||
|
{
|
||||||
|
m_pkgDir = dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace PackageManagement
|
||||||
|
|
||||||
|
#endif // PACKAGEMANAGEMENT_PACKAGESOURCE_H
|
|
@ -172,8 +172,8 @@ QStringList BuildOrderResolver::resolve(const StringVector &packages) const
|
||||||
void BuildOrderResolver::addDeps(QList<TaskInfo *> &tasks, TaskInfo *task) const
|
void BuildOrderResolver::addDeps(QList<TaskInfo *> &tasks, TaskInfo *task) const
|
||||||
{
|
{
|
||||||
if(const auto pkg = m_manager.packageFromSyncDataBases(task->name().toLocal8Bit().data())) {
|
if(const auto pkg = m_manager.packageFromSyncDataBases(task->name().toLocal8Bit().data())) {
|
||||||
for(auto dep : pkg.dependencies()) {
|
for(auto dep : pkg->dependencies()) {
|
||||||
if(auto *depTask = addDep(tasks, dep->name)) {
|
if(auto *depTask = addDep(tasks, dep.name)) {
|
||||||
task->addDep(depTask);
|
task->addDep(depTask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -184,7 +184,7 @@ void BuildOrderResolver::addDeps(QList<TaskInfo *> &tasks, TaskInfo *task) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TaskInfo *BuildOrderResolver::addDep(QList<TaskInfo *> &tasks, const char *depName) const
|
TaskInfo *BuildOrderResolver::addDep(QList<TaskInfo *> &tasks, const QString &depName) const
|
||||||
{
|
{
|
||||||
if(auto *task = TaskInfo::find(tasks, depName)) {
|
if(auto *task = TaskInfo::find(tasks, depName)) {
|
||||||
// we've already added a task for this dependency
|
// we've already added a task for this dependency
|
||||||
|
|
|
@ -20,7 +20,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void addDeps(QList<TaskInfo *> &tasks, TaskInfo *task) const;
|
void addDeps(QList<TaskInfo *> &tasks, TaskInfo *task) const;
|
||||||
TaskInfo *addDep(QList<TaskInfo *> &pkgInfos, const char *depName) const;
|
TaskInfo *addDep(QList<TaskInfo *> &pkgInfos, const QString &depName) const;
|
||||||
const Manager &m_manager;
|
const Manager &m_manager;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,185 +0,0 @@
|
||||||
#include "updatelookup.h"
|
|
||||||
#include "manager.h"
|
|
||||||
#include "database.h"
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <QNetworkReply>
|
|
||||||
#include <QtConcurrent/QtConcurrent>
|
|
||||||
|
|
||||||
#include <initializer_list>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace PackageManagement {
|
|
||||||
|
|
||||||
UpdateLookup::UpdateLookup(const Manager &manager, const QJsonObject &request, const UpdateLookupCallback callback, QObject *parent) :
|
|
||||||
QObject(parent),
|
|
||||||
m_manager(manager),
|
|
||||||
m_request(request),
|
|
||||||
m_callback(callback),
|
|
||||||
m_db(nullptr),
|
|
||||||
m_syncDbsWatcher(new QFutureWatcher<UpdateLookupResults<AlpmPackage> >(this)),
|
|
||||||
m_aurWatcher(new QFutureWatcher<UpdateLookupResults<AurPackage> >(this)),
|
|
||||||
m_aurReply(nullptr),
|
|
||||||
m_sourcesAvailable(false)
|
|
||||||
{
|
|
||||||
QJsonArray errors;
|
|
||||||
const auto dbName = request.value(QStringLiteral("db")).toString();
|
|
||||||
try {
|
|
||||||
m_db = &manager.dataBaseByName(dbName);
|
|
||||||
} catch (const out_of_range &) {
|
|
||||||
errors << QStringLiteral("Database \"%1\" can not be found.").arg(dbName);
|
|
||||||
}
|
|
||||||
if(errors.isEmpty()) {
|
|
||||||
// invoke syncdb lookup
|
|
||||||
connect(m_syncDbsWatcher, &QFutureWatcher<UpdateLookupResults<AlpmPackage> >::finished, this, &UpdateLookup::lookupDone);
|
|
||||||
m_syncDbsWatcher->setFuture(QtConcurrent::run(this, &UpdateLookup::checkSyncDbs, request.value(QStringLiteral("syncdbs"))));
|
|
||||||
// invoke AUR lookup
|
|
||||||
if(m_db->upgradeSources().contains(QStringLiteral("aur"), Qt::CaseInsensitive) || request.value(QStringLiteral("aur")).toBool(false)) {
|
|
||||||
if(manager.config().isAurEnabled()) {
|
|
||||||
connect(&m_manager.aurQuery(), &AurQuery::packageInfoAvailable, this, &UpdateLookup::aurPackageInfoAvailable);
|
|
||||||
connect(m_aurWatcher, &QFutureWatcher<UpdateLookupResults<AurPackage> >::finished, this, &UpdateLookup::lookupDone);
|
|
||||||
if(!(m_aurReply = m_manager.aurQuery().requestPackageInfo(m_db->packageNames()))) {
|
|
||||||
aurPackageInfoAvailable(nullptr);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
errors << QStringLiteral("The AUR is configured as upgrade source for the database \"%1\" but AUR queries are not enabled.").arg(dbName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
QJsonObject results;
|
|
||||||
results.insert(QStringLiteral("errors"), errors);
|
|
||||||
callback(move(results));
|
|
||||||
deleteLater();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateLookupResults<AlpmPackage> UpdateLookup::checkSyncDbs(const QJsonValue &syncDbsValue)
|
|
||||||
{
|
|
||||||
UpdateLookupResults<AlpmPackage> results;
|
|
||||||
const auto &syncDbs = m_manager.syncDataBases();
|
|
||||||
QList<const AlpmDataBase *> syncDbSel;
|
|
||||||
if(syncDbsValue.type() == QJsonValue::Array) {
|
|
||||||
for(const auto &syncDbVal : syncDbsValue.toArray()) {
|
|
||||||
const auto syncDbName = syncDbVal.toString();
|
|
||||||
if(syncDbName == QLatin1String("local")) {
|
|
||||||
syncDbSel << &(m_manager.localDataBase());
|
|
||||||
} else if(syncDbName == QLatin1String("aur")) {
|
|
||||||
continue; // the AUR is checked separately
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
syncDbSel << &(syncDbs.at(syncDbName));
|
|
||||||
} catch(out_of_range &) {
|
|
||||||
results.warnings << QStringLiteral("The specified sync database \"%1\" can not be found.").arg(syncDbName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for(const auto &syncDbName : m_db->upgradeSources()) {
|
|
||||||
if(syncDbName == QLatin1String("local")) {
|
|
||||||
syncDbSel << &(m_manager.localDataBase());
|
|
||||||
} else if(syncDbName == QLatin1String("aur")) {
|
|
||||||
continue; // the AUR is checked separately
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
syncDbSel << &(syncDbs.at(syncDbName));
|
|
||||||
} catch(out_of_range &) {
|
|
||||||
results.warnings << QStringLiteral("The associated upgrade database \"%1\" can not be found.").arg(syncDbName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_db->checkForUpgrades(syncDbSel, results);
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateLookup::aurPackageInfoAvailable(const QNetworkReply *reply)
|
|
||||||
{
|
|
||||||
// check whether the package info requested by THIS INSTANCE is available
|
|
||||||
if(m_aurReply == reply) {
|
|
||||||
m_aurWatcher->setFuture(QtConcurrent::run(this, &UpdateLookup::checkAur));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateLookupResults<AurPackage> UpdateLookup::checkAur()
|
|
||||||
{
|
|
||||||
UpdateLookupResults<AurPackage> results;
|
|
||||||
m_db->checkForUpgrades(m_manager.aurQuery().packages(), results);
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateLookup::lookupDone()
|
|
||||||
{
|
|
||||||
const auto *sender = this->sender();
|
|
||||||
if(sender == static_cast<QObject *>(m_syncDbsWatcher)) {
|
|
||||||
// add results from syncdb lookup
|
|
||||||
m_syncDbsResults = m_syncDbsWatcher->result();
|
|
||||||
if(!m_syncDbsResults.noSources) {
|
|
||||||
m_sourcesAvailable = true;
|
|
||||||
for(const auto pkg : m_syncDbsResults.newVersions) {
|
|
||||||
m_softwareUpdates << pkg.json();
|
|
||||||
}
|
|
||||||
for(const auto pkg : m_syncDbsResults.newReleases) {
|
|
||||||
m_packageOnlyUpdates << pkg.json();
|
|
||||||
}
|
|
||||||
for(const auto pkg : m_syncDbsResults.downgrades) {
|
|
||||||
m_downgrades << pkg.json();
|
|
||||||
}
|
|
||||||
for(const auto &warning : m_syncDbsResults.warnings) {
|
|
||||||
m_warnings << warning;
|
|
||||||
}
|
|
||||||
for(const auto &error : m_syncDbsResults.errors) {
|
|
||||||
m_errors << error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if(sender == static_cast<QObject *>(m_aurWatcher)) {
|
|
||||||
// add results from AUR lookup
|
|
||||||
m_aurResults = m_aurWatcher->result();
|
|
||||||
if(!m_aurResults.noSources) {
|
|
||||||
m_sourcesAvailable = true;
|
|
||||||
for(const auto pkg : m_aurResults.newVersions) {
|
|
||||||
m_softwareUpdates << pkg.json();
|
|
||||||
}
|
|
||||||
for(const auto pkg : m_aurResults.newReleases) {
|
|
||||||
m_packageOnlyUpdates << pkg.json();
|
|
||||||
}
|
|
||||||
for(const auto pkg : m_aurResults.downgrades) {
|
|
||||||
m_downgrades << pkg.json();
|
|
||||||
}
|
|
||||||
for(const auto &warning : m_aurResults.warnings) {
|
|
||||||
m_warnings << warning;
|
|
||||||
}
|
|
||||||
for(const auto &error : m_aurResults.errors) {
|
|
||||||
m_errors << error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// check whether everything is done
|
|
||||||
if(m_syncDbsWatcher->isFinished() && (!m_aurReply || m_aurWatcher->isFinished())) {
|
|
||||||
QJsonObject results;
|
|
||||||
// determine orphaned packages
|
|
||||||
for(const auto pkg : m_aurReply ? m_aurResults.orphaned.intersect(m_syncDbsResults.orphaned) : m_syncDbsResults.orphaned) {
|
|
||||||
m_orphanedPackages << pkg.basicInfo(true);
|
|
||||||
}
|
|
||||||
// add results to results QJsonObject
|
|
||||||
results.insert(QStringLiteral("softwareUpdates"), m_softwareUpdates);
|
|
||||||
results.insert(QStringLiteral("packageOnlyUpdates"), m_packageOnlyUpdates);
|
|
||||||
results.insert(QStringLiteral("downgrades"), m_downgrades);
|
|
||||||
results.insert(QStringLiteral("orphanedPackages"), m_orphanedPackages);
|
|
||||||
if(!m_sourcesAvailable) {
|
|
||||||
m_errors << QStringLiteral("No update sources associated for database \"%1\".").arg(QString::fromLocal8Bit(m_db->name()));
|
|
||||||
}
|
|
||||||
if(!m_warnings.isEmpty()) {
|
|
||||||
results.insert(QStringLiteral("warnings"), m_warnings);
|
|
||||||
}
|
|
||||||
if(!m_errors.isEmpty()) {
|
|
||||||
results.insert(QStringLiteral("errors"), m_errors);
|
|
||||||
}
|
|
||||||
m_callback(move(results));
|
|
||||||
// lookup done, delete this helper object
|
|
||||||
deleteLater();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace PackageManagement
|
|
||||||
|
|
|
@ -1,145 +0,0 @@
|
||||||
#ifndef PACKAGEMANAGEMENT_UPDATELOOKUP_H
|
|
||||||
#define PACKAGEMANAGEMENT_UPDATELOOKUP_H
|
|
||||||
|
|
||||||
#include "package.h"
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QJsonArray>
|
|
||||||
#include <QFutureWatcher>
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
QT_FORWARD_DECLARE_CLASS(QNetworkReply)
|
|
||||||
|
|
||||||
namespace PackageManagement {
|
|
||||||
|
|
||||||
class Manager;
|
|
||||||
class AlpmDataBase;
|
|
||||||
|
|
||||||
typedef std::function<void (const QJsonObject &&results)> UpdateLookupCallback;
|
|
||||||
|
|
||||||
template<class Package, class VersionType = QString>
|
|
||||||
class UpdateResult
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
UpdateResult(const Package &package, const VersionType &previousVersion);
|
|
||||||
Package package;
|
|
||||||
VersionType previousVersion;
|
|
||||||
QJsonObject json() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class Package, class VersionType>
|
|
||||||
inline UpdateResult<Package, VersionType>::UpdateResult(const Package &package, const VersionType &previousVersion) :
|
|
||||||
package(package),
|
|
||||||
previousVersion(previousVersion)
|
|
||||||
{}
|
|
||||||
|
|
||||||
template<class Package, class VersionType>
|
|
||||||
QJsonObject UpdateResult<Package, VersionType>::json() const
|
|
||||||
{
|
|
||||||
QJsonObject obj;
|
|
||||||
obj.insert(QStringLiteral("pkg"), package.basicInfo(true));
|
|
||||||
obj.insert(QStringLiteral("prevVersion"), previousVersion);
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Package>
|
|
||||||
inline UpdateResult<Package> makeUpdateResult(const Package &package, const QString &previousVersion)
|
|
||||||
{
|
|
||||||
return UpdateResult<Package>(package, previousVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Package>
|
|
||||||
inline UpdateResult<Package> makeUpdateResult(const Package &package, const char *previousVersion)
|
|
||||||
{
|
|
||||||
return UpdateResult<Package>(package, QString::fromLocal8Bit(previousVersion));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<class Package>
|
|
||||||
class UpdateLookupResults
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
UpdateLookupResults();
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Indicates that there are no upgrade sources available.
|
|
||||||
*/
|
|
||||||
bool noSources;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Packages providing a software upgrade (new version).
|
|
||||||
*/
|
|
||||||
QList<UpdateResult<Package> > newVersions;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Package upgrades only (new release).
|
|
||||||
*/
|
|
||||||
QList<UpdateResult<Package> > newReleases;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Downgrades (older version in sync db).
|
|
||||||
*/
|
|
||||||
QList<UpdateResult<Package> > downgrades;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Orphaned packages (could not be found in any of the sync dbs).
|
|
||||||
*/
|
|
||||||
QSet<AlpmPackage> orphaned;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Warnings occured when checking for updates.
|
|
||||||
*/
|
|
||||||
QStringList warnings;
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Errors occured when checking for updates.
|
|
||||||
*/
|
|
||||||
QStringList errors;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Constructs new update lookup results.
|
|
||||||
*/
|
|
||||||
template<class Package>
|
|
||||||
inline UpdateLookupResults<Package>::UpdateLookupResults() :
|
|
||||||
noSources(false)
|
|
||||||
{}
|
|
||||||
|
|
||||||
class UpdateLookup : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit UpdateLookup(const Manager &manager, const QJsonObject &request, const UpdateLookupCallback callback, QObject *parent = nullptr);
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
UpdateLookupResults<AlpmPackage> checkSyncDbs(const QJsonValue &syncDbsValue);
|
|
||||||
void aurPackageInfoAvailable(const QNetworkReply *reply);
|
|
||||||
UpdateLookupResults<AurPackage> checkAur();
|
|
||||||
|
|
||||||
void lookupDone();
|
|
||||||
|
|
||||||
private:
|
|
||||||
const Manager &m_manager;
|
|
||||||
const QJsonObject m_request;
|
|
||||||
const UpdateLookupCallback m_callback;
|
|
||||||
const AlpmDataBase *m_db;
|
|
||||||
QFutureWatcher<UpdateLookupResults<AlpmPackage> > *m_syncDbsWatcher;
|
|
||||||
QFutureWatcher<UpdateLookupResults<AurPackage> > *m_aurWatcher;
|
|
||||||
UpdateLookupResults<AlpmPackage> m_syncDbsResults;
|
|
||||||
UpdateLookupResults<AurPackage> m_aurResults;
|
|
||||||
QNetworkReply *m_aurReply;
|
|
||||||
bool m_sourcesAvailable;
|
|
||||||
QJsonArray m_warnings;
|
|
||||||
QJsonArray m_errors;
|
|
||||||
QJsonArray m_softwareUpdates;
|
|
||||||
QJsonArray m_packageOnlyUpdates;
|
|
||||||
QJsonArray m_downgrades;
|
|
||||||
QJsonArray m_orphanedPackages;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace PackageManagement
|
|
||||||
|
|
||||||
#endif // PACKAGEMANAGEMENT_UPDATELOOKUP_H
|
|
|
@ -0,0 +1,155 @@
|
||||||
|
#include "upgradelookup.h"
|
||||||
|
#include "manager.h"
|
||||||
|
#include "alpmdatabase.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <QtConcurrent/QtConcurrent>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace PackageManagement {
|
||||||
|
|
||||||
|
QJsonObject UpgradeResult::json() const
|
||||||
|
{
|
||||||
|
QJsonObject obj;
|
||||||
|
obj.insert(QStringLiteral("pkg"), package->basicInfo(true));
|
||||||
|
obj.insert(QStringLiteral("prevVersion"), previousVersion);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpgradeLookupProcess::UpgradeLookupProcess(UpgradeLookup *upgradeLookup, const Repository *upgradeSource) :
|
||||||
|
QObject(upgradeLookup),
|
||||||
|
m_toCheck(upgradeLookup->toCheck()),
|
||||||
|
m_upgradeSource(upgradeSource),
|
||||||
|
m_reply(nullptr),
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sourceReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
const UpgradeLookupResults &UpgradeLookupProcess::results() const
|
||||||
|
{
|
||||||
|
return m_results;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpgradeLookupProcess::sourceReady()
|
||||||
|
{
|
||||||
|
// if a request was required, check whether there occured an error
|
||||||
|
if(m_reply && !m_reply->error().isEmpty()) {
|
||||||
|
m_results.errors << m_reply->error();
|
||||||
|
emit finished();
|
||||||
|
} else {
|
||||||
|
connect(m_watcher, &QFutureWatcher<void>::finished, this, &UpgradeLookupProcess::finished);
|
||||||
|
m_watcher->setFuture(QtConcurrent::run(this, &UpgradeLookupProcess::checkUpgrades));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpgradeLookupProcess::checkUpgrades()
|
||||||
|
{
|
||||||
|
m_toCheck->checkForUpgrades(m_results, QList<const Repository *>() << m_upgradeSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
UpgradeLookup::UpgradeLookup(const Manager &manager, const QJsonObject &request, QObject *parent) :
|
||||||
|
QObject(parent),
|
||||||
|
m_request(request),
|
||||||
|
m_toCheck(nullptr),
|
||||||
|
m_remainingProcesses(0),
|
||||||
|
m_firstFinished(false)
|
||||||
|
{
|
||||||
|
const auto toCheckName = request.value(QStringLiteral("db")).toString();
|
||||||
|
if((m_toCheck = manager.repositoryByName(toCheckName))) {
|
||||||
|
// construct upgrade lookup processes
|
||||||
|
const auto syncDbsArray = request.value(QStringLiteral("syncdbs")).toArray();
|
||||||
|
if(syncDbsArray.isEmpty()) {
|
||||||
|
for(const auto *src : m_toCheck->upgradeSources()) {
|
||||||
|
new UpgradeLookupProcess(this, src);
|
||||||
|
++m_remainingProcesses;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for(const auto &syncDbValue : syncDbsArray) {
|
||||||
|
const auto syncDbName = syncDbValue.toString();
|
||||||
|
if(const auto *src = manager.repositoryByName(syncDbName)) {
|
||||||
|
new UpgradeLookupProcess(this, src);
|
||||||
|
++m_remainingProcesses;
|
||||||
|
} else {
|
||||||
|
m_warningsArray << QStringLiteral("The specified upgrade source \"%1\" can not be found.").arg(syncDbName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// check whether any processes could be constructed
|
||||||
|
if(!m_remainingProcesses) {
|
||||||
|
m_errorsArray << QStringLiteral("No upgrade sources associated for repository \"%1\".").arg(m_toCheck->name());
|
||||||
|
} else {
|
||||||
|
return; // no errors so far
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m_errorsArray << QStringLiteral("Repository \"%1\" can not be found.").arg(toCheckName);
|
||||||
|
}
|
||||||
|
// there are errors
|
||||||
|
QJsonObject results;
|
||||||
|
results.insert(QStringLiteral("errors"), m_errorsArray);
|
||||||
|
emit resultsAvailable(request.value(QStringLiteral("what")), request.value(QStringLiteral("id")), results);
|
||||||
|
deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpgradeLookup::processFinished()
|
||||||
|
{
|
||||||
|
assert(m_remainingProcesses);
|
||||||
|
// add results
|
||||||
|
const auto &results = static_cast<UpgradeLookupProcess *>(sender())->results();
|
||||||
|
for(const auto pkg : results.newVersions) {
|
||||||
|
m_softwareUpdatesArray << pkg.json();
|
||||||
|
}
|
||||||
|
for(const auto pkg : results.newReleases) {
|
||||||
|
m_packageOnlyUpdatesArray << pkg.json();
|
||||||
|
}
|
||||||
|
for(const auto pkg : results.downgrades) {
|
||||||
|
m_downgradesArray << pkg.json();
|
||||||
|
}
|
||||||
|
for(const auto &warning : results.warnings) {
|
||||||
|
m_warningsArray << warning;
|
||||||
|
}
|
||||||
|
for(const auto &error : results.errors) {
|
||||||
|
m_errorsArray << error;
|
||||||
|
}
|
||||||
|
if(m_firstFinished) {
|
||||||
|
m_orphanedPackages = m_orphanedPackages.intersect(results.orphaned);
|
||||||
|
} else {
|
||||||
|
m_firstFinished = true;
|
||||||
|
m_orphanedPackages = results.orphaned;
|
||||||
|
}
|
||||||
|
// check whether all processes are finished
|
||||||
|
if(--m_remainingProcesses == 0) {
|
||||||
|
// finally make info for orphanded packages
|
||||||
|
for(const auto *pkg : m_orphanedPackages) {
|
||||||
|
m_orphanedPackagesArray << pkg->basicInfo(true);
|
||||||
|
}
|
||||||
|
// add results to results QJsonObject
|
||||||
|
QJsonObject results;
|
||||||
|
results.insert(QStringLiteral("softwareUpdates"), m_softwareUpdatesArray);
|
||||||
|
results.insert(QStringLiteral("packageOnlyUpdates"), m_packageOnlyUpdatesArray);
|
||||||
|
results.insert(QStringLiteral("downgrades"), m_downgradesArray);
|
||||||
|
results.insert(QStringLiteral("orphanedPackages"), m_orphanedPackagesArray);
|
||||||
|
if(!m_warningsArray.isEmpty()) {
|
||||||
|
results.insert(QStringLiteral("warnings"), m_warningsArray);
|
||||||
|
}
|
||||||
|
if(!m_errorsArray.isEmpty()) {
|
||||||
|
results.insert(QStringLiteral("errors"), m_errorsArray);
|
||||||
|
}
|
||||||
|
emit resultsAvailable(m_request.value(QStringLiteral("what")), m_request.value(QStringLiteral("id")), results);
|
||||||
|
// lookup done, delete this helper object
|
||||||
|
deleteLater();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace PackageManagement
|
|
@ -0,0 +1,137 @@
|
||||||
|
#ifndef PACKAGEMANAGEMENT_UPDATELOOKUP_H
|
||||||
|
#define PACKAGEMANAGEMENT_UPDATELOOKUP_H
|
||||||
|
|
||||||
|
#include "package.h"
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QFutureWatcher>
|
||||||
|
|
||||||
|
namespace PackageManagement {
|
||||||
|
|
||||||
|
class Manager;
|
||||||
|
class UpgradeLookup;
|
||||||
|
class UpgradeLookupProcess;
|
||||||
|
class PackageReply;
|
||||||
|
|
||||||
|
class UpgradeResult
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
UpgradeResult(const Package *package, const QString &previousVersion);
|
||||||
|
const Package *package;
|
||||||
|
QString previousVersion;
|
||||||
|
QJsonObject json() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline UpgradeResult::UpgradeResult(const Package *package, const QString &previousVersion) :
|
||||||
|
package(package),
|
||||||
|
previousVersion(previousVersion)
|
||||||
|
{}
|
||||||
|
|
||||||
|
class UpgradeLookupResults
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
UpgradeLookupResults();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Indicates that there are no upgrade sources available.
|
||||||
|
*/
|
||||||
|
bool noSources;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Packages providing a software upgrade (new version).
|
||||||
|
*/
|
||||||
|
QList<UpgradeResult> newVersions;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Package upgrades only (new release).
|
||||||
|
*/
|
||||||
|
QList<UpgradeResult> newReleases;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Downgrades (older version in sync db).
|
||||||
|
*/
|
||||||
|
QList<UpgradeResult> downgrades;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Orphaned packages (could not be found in any of the sync dbs).
|
||||||
|
*/
|
||||||
|
QSet<const Package *> orphaned;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Warnings occured when checking for updates.
|
||||||
|
*/
|
||||||
|
QStringList warnings;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Errors occured when checking for updates.
|
||||||
|
*/
|
||||||
|
QStringList errors;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Constructs new update lookup results.
|
||||||
|
*/
|
||||||
|
inline UpgradeLookupResults::UpgradeLookupResults() :
|
||||||
|
noSources(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
class UpgradeLookupProcess : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit UpgradeLookupProcess(UpgradeLookup *upgradeLookup, const Repository *upgradeSource);
|
||||||
|
const UpgradeLookupResults &results() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void finished();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void sourceReady();
|
||||||
|
void checkUpgrades();
|
||||||
|
|
||||||
|
private:
|
||||||
|
const Repository *m_toCheck;
|
||||||
|
const Repository *m_upgradeSource;
|
||||||
|
PackageReply *m_reply;
|
||||||
|
QFutureWatcher<void> *m_watcher;
|
||||||
|
UpgradeLookupResults m_results;
|
||||||
|
};
|
||||||
|
|
||||||
|
class UpgradeLookup : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
friend class UpgradeLookupProcess;
|
||||||
|
public:
|
||||||
|
explicit UpgradeLookup(const Manager &manager, const QJsonObject &request, QObject *parent = nullptr);
|
||||||
|
const Repository *toCheck() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void resultsAvailable(const QJsonValue &what, const QJsonValue &id, const QJsonValue &value);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void processFinished();
|
||||||
|
|
||||||
|
private:
|
||||||
|
const QJsonObject m_request;
|
||||||
|
const Repository *m_toCheck;
|
||||||
|
unsigned int m_remainingProcesses;
|
||||||
|
bool m_firstFinished;
|
||||||
|
QSet<const Package *> m_orphanedPackages;
|
||||||
|
QJsonArray m_warningsArray;
|
||||||
|
QJsonArray m_errorsArray;
|
||||||
|
QJsonArray m_softwareUpdatesArray;
|
||||||
|
QJsonArray m_packageOnlyUpdatesArray;
|
||||||
|
QJsonArray m_downgradesArray;
|
||||||
|
QJsonArray m_orphanedPackagesArray;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline const Repository *UpgradeLookup::toCheck() const
|
||||||
|
{
|
||||||
|
return m_toCheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace PackageManagement
|
||||||
|
|
||||||
|
#endif // PACKAGEMANAGEMENT_UPDATELOOKUP_H
|
|
@ -1,7 +1,8 @@
|
||||||
#include "utilities.h"
|
#include "utilities.h"
|
||||||
|
|
||||||
#include <QString>
|
#include <QJsonObject>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -105,6 +106,102 @@ QString sigStatusString(alpm_sigstatus_t sigStatus)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the string representation for the specified \a validationMethods.
|
||||||
|
*/
|
||||||
|
QJsonArray validationMethodsStrings(alpm_pkgvalidation_t validationMethods)
|
||||||
|
{
|
||||||
|
QJsonArray jsonArray;
|
||||||
|
if(validationMethods & 0x1) {
|
||||||
|
jsonArray << QStringLiteral("none");
|
||||||
|
}
|
||||||
|
if(validationMethods & 0x2) {
|
||||||
|
jsonArray << QStringLiteral("MD5");
|
||||||
|
}
|
||||||
|
if(validationMethods & 0x4) {
|
||||||
|
jsonArray << QStringLiteral("SHA256");
|
||||||
|
}
|
||||||
|
if(validationMethods & 0x8) {
|
||||||
|
jsonArray << QStringLiteral("signature");
|
||||||
|
}
|
||||||
|
if(jsonArray.empty()) {
|
||||||
|
jsonArray << QStringLiteral("unknown");
|
||||||
|
}
|
||||||
|
return jsonArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonArray qjarry(StringList list)
|
||||||
|
{
|
||||||
|
QJsonArray jsonArray;
|
||||||
|
for(const char *str : list) {
|
||||||
|
jsonArray << qstr(str);
|
||||||
|
}
|
||||||
|
return jsonArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonArray qjarry(DependencyList list)
|
||||||
|
{
|
||||||
|
QJsonArray jsonArray;
|
||||||
|
for(alpm_depend_t *dep : list) {
|
||||||
|
QJsonObject depObj;
|
||||||
|
depObj.insert(QStringLiteral("name"), dep->name);
|
||||||
|
depObj.insert(QStringLiteral("desc"), dep->desc);
|
||||||
|
depObj.insert(QStringLiteral("ver"), dep->version);
|
||||||
|
switch(dep->mod) {
|
||||||
|
case ALPM_DEP_MOD_ANY:
|
||||||
|
depObj.insert(QStringLiteral("mod"), QStringLiteral("any"));
|
||||||
|
break;
|
||||||
|
case ALPM_DEP_MOD_EQ:
|
||||||
|
depObj.insert(QStringLiteral("mod"), QStringLiteral("eq"));
|
||||||
|
break;
|
||||||
|
case ALPM_DEP_MOD_GE:
|
||||||
|
depObj.insert(QStringLiteral("mod"), QStringLiteral("ge"));
|
||||||
|
break;
|
||||||
|
case ALPM_DEP_MOD_LE:
|
||||||
|
depObj.insert(QStringLiteral("mod"), QStringLiteral("le"));
|
||||||
|
break;
|
||||||
|
case ALPM_DEP_MOD_GT:
|
||||||
|
depObj.insert(QStringLiteral("mod"), QStringLiteral("gt"));
|
||||||
|
break;
|
||||||
|
case ALPM_DEP_MOD_LT:
|
||||||
|
depObj.insert(QStringLiteral("mod"), QStringLiteral("lt"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
jsonArray << depObj;
|
||||||
|
}
|
||||||
|
return jsonArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonArray qjarry(_alpm_pkgvalidation_t validation)
|
||||||
|
{
|
||||||
|
QJsonArray jsonArray;
|
||||||
|
if(validation & 0x1) {
|
||||||
|
jsonArray << QStringLiteral("none");
|
||||||
|
}
|
||||||
|
if(validation & 0x2) {
|
||||||
|
jsonArray << QStringLiteral("MD5");
|
||||||
|
}
|
||||||
|
if(validation & 0x4) {
|
||||||
|
jsonArray << QStringLiteral("SHA256");
|
||||||
|
}
|
||||||
|
if(validation & 0x8) {
|
||||||
|
jsonArray << QStringLiteral("signature");
|
||||||
|
}
|
||||||
|
if(jsonArray.empty()) {
|
||||||
|
jsonArray << QStringLiteral("unknown");
|
||||||
|
}
|
||||||
|
return jsonArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList qstrlist(StringList list)
|
||||||
|
{
|
||||||
|
QStringList strings;
|
||||||
|
for(const auto *str : list) {
|
||||||
|
strings << qstr(str);
|
||||||
|
}
|
||||||
|
return strings;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Alpm
|
} // namespace Alpm
|
||||||
|
|
|
@ -3,15 +3,12 @@
|
||||||
|
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
|
|
||||||
#include <QtGlobal>
|
#include <QString>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_FORWARD_DECLARE_CLASS(QJsonArray)
|
||||||
class QString;
|
|
||||||
class QJsonArray;
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
namespace PackageManagement {
|
namespace PackageManagement {
|
||||||
|
|
||||||
|
@ -22,6 +19,22 @@ std::list<std::string> getNames(DependencyList dependencyList);
|
||||||
QJsonArray sigLevelStrings(alpm_siglevel_t sigLevel);
|
QJsonArray sigLevelStrings(alpm_siglevel_t sigLevel);
|
||||||
QJsonArray usageStrings(alpm_db_usage_t usage);
|
QJsonArray usageStrings(alpm_db_usage_t usage);
|
||||||
QString sigStatusString(alpm_sigstatus_t sigStatus);
|
QString sigStatusString(alpm_sigstatus_t sigStatus);
|
||||||
|
QJsonArray validationMethodsStrings(alpm_pkgvalidation_t validationMethods);
|
||||||
|
|
||||||
|
QJsonArray qjarry(StringList list);
|
||||||
|
QJsonArray qjarry(DependencyList list);
|
||||||
|
QJsonArray qjarry(_alpm_pkgvalidation_t validation);
|
||||||
|
QStringList qstrlist(StringList list);
|
||||||
|
|
||||||
|
inline QString qstr(const char *str)
|
||||||
|
{
|
||||||
|
return QString::fromLocal8Bit(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QString qstr(const std::string &str)
|
||||||
|
{
|
||||||
|
return QString::fromLocal8Bit(str.data());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,6 @@ RCC_DIR = ./res
|
||||||
# compiler flags
|
# compiler flags
|
||||||
QMAKE_CXXFLAGS += -std=c++11
|
QMAKE_CXXFLAGS += -std=c++11
|
||||||
QMAKE_LFLAGS += -std=c++11
|
QMAKE_LFLAGS += -std=c++11
|
||||||
unix {
|
|
||||||
QMAKE_LFLAGS += "-Wl,--rpath=./"
|
|
||||||
}
|
|
||||||
# prefix
|
# prefix
|
||||||
targetprefix = $$(TARGET_PREFIX)
|
targetprefix = $$(TARGET_PREFIX)
|
||||||
message("Using target prefix \"$${targetprefix}\".")
|
message("Using target prefix \"$${targetprefix}\".")
|
||||||
|
|
8
main.cpp
8
main.cpp
|
@ -3,6 +3,7 @@
|
||||||
#include "alpm/config.h"
|
#include "alpm/config.h"
|
||||||
#include "alpm/resolvebuildorder.h"
|
#include "alpm/resolvebuildorder.h"
|
||||||
#include "alpm/mingwbundle.h"
|
#include "alpm/mingwbundle.h"
|
||||||
|
|
||||||
#include "network/server.h"
|
#include "network/server.h"
|
||||||
|
|
||||||
#include <c++utilities/application/argumentparser.h>
|
#include <c++utilities/application/argumentparser.h>
|
||||||
|
@ -39,6 +40,7 @@ int main(int argc, char *argv[])
|
||||||
if(find_if(parser.mainArguments().cbegin(), parser.mainArguments().cend(), [&configArgs] (const Argument *arg) {
|
if(find_if(parser.mainArguments().cbegin(), parser.mainArguments().cend(), [&configArgs] (const Argument *arg) {
|
||||||
return arg != &configArgs.helpArg && arg->isPresent();
|
return arg != &configArgs.helpArg && arg->isPresent();
|
||||||
}) != parser.mainArguments().cend()) {
|
}) != parser.mainArguments().cend()) {
|
||||||
|
cerr << "Loading databases ..." << endl;
|
||||||
// create app
|
// create app
|
||||||
QCoreApplication application(argc, argv);
|
QCoreApplication application(argc, argv);
|
||||||
// setup ALPM
|
// setup ALPM
|
||||||
|
@ -61,8 +63,10 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
cout << endl;
|
cout << endl;
|
||||||
} else if(configArgs.mingwBundleArg.isPresent()) {
|
} else if(configArgs.mingwBundleArg.isPresent()) {
|
||||||
MingwBundle bundle(manager, configArgs.mingwBundleArg.values());
|
MingwBundle bundle(manager, configArgs.mingwBundleArg.values(), configArgs.iconThemesArg.values());
|
||||||
bundle.createBundle(configArgs.outputFileArg.values().front());
|
bundle.createBundle(configArgs.targetDirArg.isPresent() ? configArgs.targetDirArg.values().front() : string("."),
|
||||||
|
configArgs.targetNameArg.values().front(),
|
||||||
|
configArgs.targetFormatArg.isPresent() ? configArgs.targetFormatArg.values().front() : string("zip"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cout << "No command line arguments specified. See --help for available commands." << endl;
|
cout << "No command line arguments specified. See --help for available commands." << endl;
|
||||||
|
|
|
@ -1,137 +0,0 @@
|
||||||
#include "aurquery.h"
|
|
||||||
|
|
||||||
#include "alpm/package.h"
|
|
||||||
|
|
||||||
#include <QUrlQuery>
|
|
||||||
#include <QNetworkRequest>
|
|
||||||
#include <QNetworkReply>
|
|
||||||
#include <QNetworkAccessManager>
|
|
||||||
#include <QJsonDocument>
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QJsonArray>
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace PackageManagement {
|
|
||||||
|
|
||||||
QUrl AurQuery::m_aurRpcUrl = QUrl(QStringLiteral("https://aur.archlinux.org/rpc.php"));
|
|
||||||
|
|
||||||
QUrl AurQuery::m_aurPkgbuildUrl = QUrl(QStringLiteral("https://aur.archlinux.org/cgit/aur.git/plain/PKGBUILD"));
|
|
||||||
|
|
||||||
const char *requestTypeProp = "type";
|
|
||||||
const QString rpcRequestTypeKey(QStringLiteral("type"));
|
|
||||||
const QString rpcRequestTypeSuggest(QStringLiteral("suggest"));
|
|
||||||
const QString rpcRequestTypeMultiInfo(QStringLiteral("multiinfo"));
|
|
||||||
const QString rpcArgKey(QStringLiteral("arg"));
|
|
||||||
const QString rpcArgArray(QStringLiteral("arg[]"));
|
|
||||||
const QString pkgbuildRequestType(QString("pkgbuild"));
|
|
||||||
|
|
||||||
AurQuery::AurQuery(QNetworkAccessManager &networkAccessManager, QObject *parent) :
|
|
||||||
QObject(parent),
|
|
||||||
m_networkAccessManager(networkAccessManager)
|
|
||||||
{}
|
|
||||||
|
|
||||||
QNetworkReply *AurQuery::requestSuggestions(const QString &phrase) const
|
|
||||||
{
|
|
||||||
auto url = m_aurRpcUrl;
|
|
||||||
QUrlQuery query;
|
|
||||||
query.addQueryItem(rpcRequestTypeKey, rpcRequestTypeSuggest);
|
|
||||||
query.addQueryItem(rpcArgKey, phrase);
|
|
||||||
url.setQuery(query);
|
|
||||||
auto *reply = m_networkAccessManager.get(QNetworkRequest(url));
|
|
||||||
reply->setProperty(requestTypeProp, rpcRequestTypeSuggest);
|
|
||||||
connect(reply, &QNetworkReply::finished, this, &AurQuery::dataReceived);
|
|
||||||
return reply;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Requests package information for the specified packages from the AUR.
|
|
||||||
* \returns Returns the QNetworkReply used for the request.
|
|
||||||
* \remarks
|
|
||||||
* If \a forceUpdate is true, package information which has already been retrieved
|
|
||||||
* and is still cached is requested again. Otherwise these packages will not be
|
|
||||||
* requested again. If it turns out, that all packages are already cached, nullptr
|
|
||||||
* is returned in this case.
|
|
||||||
*/
|
|
||||||
QNetworkReply *AurQuery::requestPackageInfo(const QStringList &packageNames, bool forceUpdate) const
|
|
||||||
{
|
|
||||||
QUrlQuery query;
|
|
||||||
for(const auto &packageName : packageNames) {
|
|
||||||
if(forceUpdate || !m_packages.count(packageName)) {
|
|
||||||
query.addQueryItem(rpcArgArray, packageName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(query.isEmpty()) {
|
|
||||||
return nullptr;
|
|
||||||
} else {
|
|
||||||
auto url = m_aurRpcUrl;
|
|
||||||
query.addQueryItem(rpcRequestTypeKey, rpcRequestTypeMultiInfo);
|
|
||||||
url.setQuery(query);
|
|
||||||
auto *reply = m_networkAccessManager.get(QNetworkRequest(url));
|
|
||||||
reply->setProperty(requestTypeProp, rpcRequestTypeMultiInfo);
|
|
||||||
connect(reply, &QNetworkReply::finished, this, &AurQuery::dataReceived);
|
|
||||||
return reply;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QNetworkReply *AurQuery::requestFullPackageInfo(const QString &package, bool forceUpdate) const
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
const auto &pkg = m_packages.at(package);
|
|
||||||
if(pkg.hasFullInfo() && !forceUpdate) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
} catch(const out_of_range &) {
|
|
||||||
}
|
|
||||||
auto url = m_aurPkgbuildUrl;
|
|
||||||
QUrlQuery query;
|
|
||||||
query.addQueryItem(QStringLiteral("h"), package);
|
|
||||||
url.setQuery(query);
|
|
||||||
auto *reply = m_networkAccessManager.get(QNetworkRequest(url));
|
|
||||||
reply->setProperty(requestTypeProp, pkgbuildRequestType);
|
|
||||||
connect(reply, &QNetworkReply::finished, this, &AurQuery::dataReceived);
|
|
||||||
return reply;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AurQuery::dataReceived()
|
|
||||||
{
|
|
||||||
if(auto *reply = qobject_cast<QNetworkReply *>(sender())) {
|
|
||||||
if(reply->error() == QNetworkReply::NoError) {
|
|
||||||
QJsonParseError error;
|
|
||||||
QByteArray data = reply->readAll();
|
|
||||||
cerr << "AUR reply: " << data.data() << endl;
|
|
||||||
const QJsonDocument doc = QJsonDocument::fromJson(data, &error);
|
|
||||||
//const QJsonDocument doc = QJsonDocument::fromJson(reply->readAll(), &error);
|
|
||||||
if(error.error == QJsonParseError::NoError) {
|
|
||||||
const QString requestType = reply->property(requestTypeProp).toString();
|
|
||||||
if(requestType == rpcRequestTypeSuggest) {
|
|
||||||
emit suggestionsAvailable(reply, doc.array());
|
|
||||||
} else if(requestType == rpcRequestTypeMultiInfo) {
|
|
||||||
processPackageInfo(reply, doc.object().value(QStringLiteral("results")).toArray());
|
|
||||||
} else {
|
|
||||||
cerr << "Error: Reply has invalid type. (should never happen)" << endl;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cerr << "Error: Unable to parse JSON received from AUR: " << error.errorString().toLocal8Bit().data() << " at character " << error.offset << endl;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cerr << "Error: Unable to request data from AUR: " << reply->errorString().toLocal8Bit().data() << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AurQuery::processPackageInfo(const QNetworkReply *reply, const QJsonArray &results)
|
|
||||||
{
|
|
||||||
for(const auto &result : results) {
|
|
||||||
AurPackage package(result);
|
|
||||||
if(!package.name().isEmpty()) {
|
|
||||||
m_packages[package.name()] = move(package);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
emit packageInfoAvailable(reply);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Alpm
|
|
||||||
|
|
|
@ -1,71 +0,0 @@
|
||||||
#ifndef ALPM_AURQUERY_H
|
|
||||||
#define ALPM_AURQUERY_H
|
|
||||||
|
|
||||||
#include "alpm/package.h"
|
|
||||||
|
|
||||||
#include <QUrl>
|
|
||||||
#include <QObject>
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
QT_FORWARD_DECLARE_CLASS(QNetworkAccessManager)
|
|
||||||
QT_FORWARD_DECLARE_CLASS(QNetworkReply)
|
|
||||||
|
|
||||||
namespace PackageManagement {
|
|
||||||
|
|
||||||
class AurQuery : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
AurQuery(QNetworkAccessManager &networkAccessManager, QObject *parent = nullptr);
|
|
||||||
|
|
||||||
static const QUrl aurRpcUrl();
|
|
||||||
static void setAurRpcUrl(const QUrl &aurRpcUrl);
|
|
||||||
|
|
||||||
QNetworkReply *requestSuggestions(const QString &phrase) const;
|
|
||||||
QNetworkReply *requestPackageInfo(const QStringList &packageNames, bool forceUpdate = false) const;
|
|
||||||
QNetworkReply *requestFullPackageInfo(const QString &package, bool forceUpdate = false) const;
|
|
||||||
const std::map<QString, AurPackage> &packages() const;
|
|
||||||
std::map<QString, AurPackage> &packages();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void suggestionsAvailable(const QNetworkReply *reply, const QJsonArray &suggestions);
|
|
||||||
void packageInfoAvailable(const QNetworkReply *reply);
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void dataReceived();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void processPackageInfo(const QNetworkReply *reply, const QJsonArray &results);
|
|
||||||
|
|
||||||
QNetworkAccessManager &m_networkAccessManager;
|
|
||||||
std::map<QString, AurPackage> m_packages;
|
|
||||||
|
|
||||||
static QUrl m_aurRpcUrl;
|
|
||||||
static QUrl m_aurPkgbuildUrl;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline const QUrl AurQuery::aurRpcUrl()
|
|
||||||
{
|
|
||||||
return m_aurRpcUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void AurQuery::setAurRpcUrl(const QUrl &aur4Url)
|
|
||||||
{
|
|
||||||
m_aurRpcUrl = aur4Url;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const std::map<QString, AurPackage> &AurQuery::packages() const
|
|
||||||
{
|
|
||||||
return m_packages;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline std::map<QString, AurPackage> &AurQuery::packages()
|
|
||||||
{
|
|
||||||
return m_packages;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Alpm
|
|
||||||
|
|
||||||
#endif // ALPM_AURQUERY_H
|
|
|
@ -1,19 +1,18 @@
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
|
|
||||||
#include "alpm/manager.h"
|
#include "alpm/manager.h"
|
||||||
|
#include "alpm/upgradelookup.h"
|
||||||
|
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QWebSocket>
|
#include <QWebSocket>
|
||||||
|
|
||||||
#include <functional>
|
using namespace PackageManagement;
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace Network {
|
namespace Network {
|
||||||
|
|
||||||
Connection::Connection(const PackageManagement::Manager &alpmManager, QWebSocket *socket, QObject *parent) :
|
Connection::Connection(const Manager &alpmManager, QWebSocket *socket, QObject *parent) :
|
||||||
QObject(parent),
|
QObject(parent),
|
||||||
m_socket(socket),
|
m_socket(socket),
|
||||||
m_alpmManager(alpmManager),
|
m_alpmManager(alpmManager),
|
||||||
|
@ -39,7 +38,7 @@ void Connection::sendError(const QString &msg)
|
||||||
sendJson(response);
|
sendJson(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::sendResult(const QString &what, const QJsonValue &id, const QJsonValue &value)
|
void Connection::sendResult(const QJsonValue &what, const QJsonValue &id, const QJsonValue &value)
|
||||||
{
|
{
|
||||||
QJsonObject response;
|
QJsonObject response;
|
||||||
response.insert(QStringLiteral("class"), QStringLiteral("results"));
|
response.insert(QStringLiteral("class"), QStringLiteral("results"));
|
||||||
|
@ -51,7 +50,7 @@ void Connection::sendResult(const QString &what, const QJsonValue &id, const QJs
|
||||||
sendJson(response);
|
sendJson(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::sendResults(const QString &what, const QJsonValue &id, const QJsonArray &values)
|
void Connection::sendResults(const QJsonValue &what, const QJsonValue &id, const QJsonArray &values)
|
||||||
{
|
{
|
||||||
QJsonObject response;
|
QJsonObject response;
|
||||||
response.insert(QStringLiteral("class"), QStringLiteral("results"));
|
response.insert(QStringLiteral("class"), QStringLiteral("results"));
|
||||||
|
@ -71,18 +70,14 @@ void Connection::handleQuery(const QJsonObject &obj)
|
||||||
m_repoInfoUpdatesRequested = obj.value(QStringLiteral("updates")).toBool(m_repoInfoUpdatesRequested);
|
m_repoInfoUpdatesRequested = obj.value(QStringLiteral("updates")).toBool(m_repoInfoUpdatesRequested);
|
||||||
sendResults(what, id, m_alpmManager.basicRepoInfo());
|
sendResults(what, id, m_alpmManager.basicRepoInfo());
|
||||||
} else if(what == QLatin1String("basicpkginfo")) {
|
} else if(what == QLatin1String("basicpkginfo")) {
|
||||||
sendResults(what, id, m_alpmManager.packageInfo(obj.value("sel").toArray(), false));
|
sendResults(what, id, m_alpmManager.packageInfo(obj.value("sel").toObject(), false));
|
||||||
} else if(what == QLatin1String("fullpkginfo")) {
|
} else if(what == QLatin1String("fullpkginfo")) {
|
||||||
sendResults(what, id, m_alpmManager.packageInfo(obj.value("sel").toArray(), true));
|
sendResults(what, id, m_alpmManager.packageInfo(obj.value("sel").toObject(), true));
|
||||||
} else if(what == QLatin1String("groupinfo")) {
|
} else if(what == QLatin1String("groupinfo")) {
|
||||||
m_groupInfoUpdatesRequested = obj.value(QStringLiteral("updates")).toBool(m_groupInfoUpdatesRequested);
|
m_groupInfoUpdatesRequested = obj.value(QStringLiteral("updates")).toBool(m_groupInfoUpdatesRequested);
|
||||||
sendResults(what, id, m_alpmManager.groupInfo());
|
sendResults(what, id, m_alpmManager.groupInfo());
|
||||||
} else if(what == QLatin1String("checkforupdates")) {
|
} else if(what == QLatin1String("checkforupdates")) {
|
||||||
//sendResult(what, id, m_alpmManager.invokeUpgradeLookup(obj));
|
connect(new UpgradeLookup(m_alpmManager, obj), &UpgradeLookup::resultsAvailable, this, &Connection::sendResult);
|
||||||
m_alpmManager.invokeUpgradeLookup(obj, bind(&Connection::sendResult, this, what, id, placeholders::_1));
|
|
||||||
//m_alpmManager.checkForUpgrades(obj, [this] (const QJsonObject &results) {
|
|
||||||
// sendResult(what, id, results);
|
|
||||||
//};
|
|
||||||
} else if(what == QLatin1String("ping")) {
|
} else if(what == QLatin1String("ping")) {
|
||||||
sendResult(what, id, QStringLiteral("pong"));
|
sendResult(what, id, QStringLiteral("pong"));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -24,12 +24,12 @@ private slots:
|
||||||
void processTextMessage(const QString &message);
|
void processTextMessage(const QString &message);
|
||||||
void processBinaryMessage(const QByteArray &message);
|
void processBinaryMessage(const QByteArray &message);
|
||||||
void socketDisconnected();
|
void socketDisconnected();
|
||||||
|
void sendResult(const QJsonValue &what, const QJsonValue &id, const QJsonValue &value);
|
||||||
|
void sendResults(const QJsonValue &what, const QJsonValue &id, const QJsonArray &values);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void sendJson(const QJsonObject &obj);
|
void sendJson(const QJsonObject &obj);
|
||||||
void sendError(const QString &msg);
|
void sendError(const QString &msg);
|
||||||
void sendResult(const QString &what, const QJsonValue &id, const QJsonValue &value);
|
|
||||||
void sendResults(const QString &what, const QJsonValue &id, const QJsonArray &values);
|
|
||||||
void handleQuery(const QJsonObject &obj);
|
void handleQuery(const QJsonObject &obj);
|
||||||
|
|
||||||
QWebSocket *m_socket;
|
QWebSocket *m_socket;
|
||||||
|
|
|
@ -0,0 +1,145 @@
|
||||||
|
#include "userrepository.h"
|
||||||
|
|
||||||
|
#include "alpm/aurpackage.h"
|
||||||
|
|
||||||
|
#include <c++utilities/misc/memory.h>
|
||||||
|
|
||||||
|
#include <QStringBuilder>
|
||||||
|
#include <QUrlQuery>
|
||||||
|
#include <QNetworkRequest>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonArray>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace PackageManagement {
|
||||||
|
|
||||||
|
const char *requestTypeProp = "type";
|
||||||
|
const QString rpcRequestTypeKey(QStringLiteral("type"));
|
||||||
|
const QString rpcRequestTypeSuggest(QStringLiteral("suggest"));
|
||||||
|
const QString rpcRequestTypeMultiInfo(QStringLiteral("multiinfo"));
|
||||||
|
const QString rpcArgKey(QStringLiteral("arg"));
|
||||||
|
const QString rpcArgArray(QStringLiteral("arg[]"));
|
||||||
|
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"));
|
||||||
|
|
||||||
|
AurPackageReply::AurPackageReply(QNetworkReply *networkReply, UserRepository *userRepo) :
|
||||||
|
PackageReply(networkReply, userRepo->packages()),
|
||||||
|
m_userRepo(userRepo)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void AurPackageReply::processData()
|
||||||
|
{
|
||||||
|
if(m_networkReply->error() == QNetworkReply::NoError) {
|
||||||
|
QJsonParseError error;
|
||||||
|
//QByteArray data = m_networkReply->readAll();
|
||||||
|
//cerr << "AUR reply: " << data.data() << endl;
|
||||||
|
//const QJsonDocument doc = QJsonDocument::fromJson(data, &error);
|
||||||
|
const QJsonDocument doc = QJsonDocument::fromJson(m_networkReply->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);
|
||||||
|
if(!package->name().isEmpty()) {
|
||||||
|
m_packages[package->name()] = move(package);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} 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();
|
||||||
|
}
|
||||||
|
emit resultsAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
|
AurSuggestionsReply::AurSuggestionsReply(QNetworkReply *networkReply) :
|
||||||
|
SuggestionsReply(networkReply)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void AurSuggestionsReply::processData()
|
||||||
|
{
|
||||||
|
if(m_networkReply->error() == QNetworkReply::NoError) {
|
||||||
|
QJsonParseError error;
|
||||||
|
//QByteArray data = m_networkReply->readAll();
|
||||||
|
//cerr << "AUR reply: " << data.data() << endl;
|
||||||
|
//const QJsonDocument doc = QJsonDocument::fromJson(data, &error);
|
||||||
|
const QJsonDocument doc = QJsonDocument::fromJson(m_networkReply->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();
|
||||||
|
}
|
||||||
|
emit resultsAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
|
UserRepository::UserRepository(QNetworkAccessManager &networkAccessManager, QObject *parent) :
|
||||||
|
Repository(QStringLiteral("AUR"), parent),
|
||||||
|
m_networkAccessManager(networkAccessManager)
|
||||||
|
{
|
||||||
|
m_description = QStringLiteral("Arch User Repository");
|
||||||
|
}
|
||||||
|
|
||||||
|
RepositoryType UserRepository::type() const
|
||||||
|
{
|
||||||
|
return RepositoryType::UserRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UserRepository::requestsRequired() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
AurSuggestionsReply *UserRepository::requestSuggestions(const QString &phrase) const
|
||||||
|
{
|
||||||
|
auto url = m_aurRpcUrl;
|
||||||
|
QUrlQuery query;
|
||||||
|
query.addQueryItem(rpcRequestTypeKey, rpcRequestTypeSuggest);
|
||||||
|
query.addQueryItem(rpcArgKey, phrase);
|
||||||
|
url.setQuery(query);
|
||||||
|
return new AurSuggestionsReply(m_networkAccessManager.get(QNetworkRequest(url)));
|
||||||
|
}
|
||||||
|
|
||||||
|
AurPackageReply *UserRepository::requestPackageInfo(const QStringList &packageNames, bool forceUpdate) const
|
||||||
|
{
|
||||||
|
QUrlQuery query;
|
||||||
|
for(const auto &packageName : packageNames) {
|
||||||
|
if(forceUpdate || !m_packages.count(packageName)) {
|
||||||
|
query.addQueryItem(rpcArgArray, packageName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(query.isEmpty()) {
|
||||||
|
return nullptr;
|
||||||
|
} else {
|
||||||
|
auto url = m_aurRpcUrl;
|
||||||
|
query.addQueryItem(rpcRequestTypeKey, rpcRequestTypeMultiInfo);
|
||||||
|
url.setQuery(query);
|
||||||
|
return new AurPackageReply(m_networkAccessManager.get(QNetworkRequest(url)), const_cast<UserRepository *>(this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AurPackageReply *UserRepository::requestFullPackageInfo(const QString &package, bool forceUpdate) const
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
const auto &pkg = m_packages.at(package);
|
||||||
|
if(pkg->hasGeneralInfo() && !forceUpdate) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
} 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));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Alpm
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
#ifndef ALPM_USER_REPOSITORY_H
|
||||||
|
#define ALPM_USER_REPOSITORY_H
|
||||||
|
|
||||||
|
#include "alpm/package.h"
|
||||||
|
#include "alpm/repository.h"
|
||||||
|
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
QT_FORWARD_DECLARE_CLASS(QNetworkAccessManager)
|
||||||
|
QT_FORWARD_DECLARE_CLASS(QNetworkReply)
|
||||||
|
|
||||||
|
namespace PackageManagement {
|
||||||
|
|
||||||
|
class UserRepository;
|
||||||
|
|
||||||
|
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 AurSuggestionsReply : public SuggestionsReply
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
AurSuggestionsReply(QNetworkReply *networkReply);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void processData();
|
||||||
|
};
|
||||||
|
|
||||||
|
class UserRepository : public Repository
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
UserRepository(QNetworkAccessManager &networkAccessManager, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
RepositoryType type() const;
|
||||||
|
|
||||||
|
static const QUrl aurRpcUrl();
|
||||||
|
static void setAurRpcUrl(const QUrl &aurRpcUrl);
|
||||||
|
|
||||||
|
bool requestsRequired() 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;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QNetworkAccessManager &m_networkAccessManager;
|
||||||
|
static QUrl m_aurRpcUrl;
|
||||||
|
static QUrl m_aurPkgbuildUrl;
|
||||||
|
static QUrl m_aurSrcInfoUrl;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline const QUrl UserRepository::aurRpcUrl()
|
||||||
|
{
|
||||||
|
return m_aurRpcUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void UserRepository::setAurRpcUrl(const QUrl &aur4Url)
|
||||||
|
{
|
||||||
|
m_aurRpcUrl = aur4Url;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Alpm
|
||||||
|
|
||||||
|
#endif // ALPM_USER_REPOSITORY_H
|
|
@ -1,4 +1,7 @@
|
||||||
projectname = repoindex
|
projectname = repoindex
|
||||||
|
appname = "Repository Index"
|
||||||
|
appauthor = Martchus
|
||||||
|
appurl = "https://github.com/$${appauthor}/$${projectname}"
|
||||||
VERSION = 1.0.0
|
VERSION = 1.0.0
|
||||||
|
|
||||||
# include ../../common.pri when building as part of a subdirs project; otherwise include general.pri
|
# include ../../common.pri when building as part of a subdirs project; otherwise include general.pri
|
||||||
|
@ -18,30 +21,36 @@ SOURCES += main.cpp \
|
||||||
alpm/manager.cpp \
|
alpm/manager.cpp \
|
||||||
alpm/package.cpp \
|
alpm/package.cpp \
|
||||||
alpm/utilities.cpp \
|
alpm/utilities.cpp \
|
||||||
alpm/database.cpp \
|
|
||||||
network/server.cpp \
|
network/server.cpp \
|
||||||
network/connection.cpp \
|
network/connection.cpp \
|
||||||
alpm/group.cpp \
|
alpm/group.cpp \
|
||||||
alpm/config.cpp \
|
alpm/config.cpp \
|
||||||
network/aurquery.cpp \
|
|
||||||
alpm/updatelookup.cpp \
|
|
||||||
alpm/resolvebuildorder.cpp \
|
alpm/resolvebuildorder.cpp \
|
||||||
alpm/mingwbundle.cpp
|
alpm/mingwbundle.cpp \
|
||||||
|
network/userrepository.cpp \
|
||||||
|
alpm/alpmpackage.cpp \
|
||||||
|
alpm/aurpackage.cpp \
|
||||||
|
alpm/alpmdatabase.cpp \
|
||||||
|
alpm/repository.cpp \
|
||||||
|
alpm/upgradelookup.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
alpm/manager.h \
|
alpm/manager.h \
|
||||||
alpm/package.h \
|
alpm/package.h \
|
||||||
alpm/list.h \
|
alpm/list.h \
|
||||||
alpm/utilities.h \
|
alpm/utilities.h \
|
||||||
alpm/database.h \
|
|
||||||
network/server.h \
|
network/server.h \
|
||||||
network/connection.h \
|
network/connection.h \
|
||||||
alpm/group.h \
|
alpm/group.h \
|
||||||
alpm/config.h \
|
alpm/config.h \
|
||||||
network/aurquery.h \
|
|
||||||
alpm/updatelookup.h \
|
|
||||||
alpm/resolvebuildorder.h \
|
alpm/resolvebuildorder.h \
|
||||||
alpm/mingwbundle.h
|
alpm/mingwbundle.h \
|
||||||
|
network/userrepository.h \
|
||||||
|
alpm/alpmpackage.h \
|
||||||
|
alpm/aurpackage.h \
|
||||||
|
alpm/alpmdatabase.h \
|
||||||
|
alpm/repository.h \
|
||||||
|
alpm/upgradelookup.h
|
||||||
|
|
||||||
DISTFILES += \
|
DISTFILES += \
|
||||||
README.md \
|
README.md \
|
||||||
|
@ -60,13 +69,18 @@ DISTFILES += \
|
||||||
web/css/dashboard.css \
|
web/css/dashboard.css \
|
||||||
repoindex.conf.js
|
repoindex.conf.js
|
||||||
|
|
||||||
|
# defines
|
||||||
|
CONFIG(release, debug|release) {
|
||||||
|
DEFINES += NDEBUG
|
||||||
|
}
|
||||||
|
|
||||||
# libs and includepath
|
# libs and includepath
|
||||||
CONFIG(debug, debug|release) {
|
CONFIG(debug, debug|release) {
|
||||||
LIBS += -L../../ -lc++utilitiesd -lalpm -lKF5Archive
|
LIBS += -lc++utilitiesd
|
||||||
} else {
|
} else {
|
||||||
LIBS += -L../../ -lc++utilities -lalpm -lKF5Archive
|
LIBS += -lc++utilities
|
||||||
}
|
}
|
||||||
INCLUDEPATH += ../
|
LIBS += -lalpm -lKF5Archive
|
||||||
|
|
||||||
# installs
|
# installs
|
||||||
target.path = $$(INSTALL_ROOT)/bin
|
target.path = $$(INSTALL_ROOT)/bin
|
||||||
|
|
|
@ -232,11 +232,9 @@
|
||||||
<tr><th>Package count</th><td id="repo_pkgcount"></td></tr>
|
<tr><th>Package count</th><td id="repo_pkgcount"></td></tr>
|
||||||
<tr><th>Usage</th><td id="repo_usage"></td></tr>
|
<tr><th>Usage</th><td id="repo_usage"></td></tr>
|
||||||
<tr><th>Signature level</th><td id="repo_siglevel"></td></tr>
|
<tr><th>Signature level</th><td id="repo_siglevel"></td></tr>
|
||||||
|
<tr><th>Source-only</th><td id="repo_source_only"></td></tr>
|
||||||
<tr><th>Upgrade sources</th><td id="repo_upgrade_sources"></td></tr>
|
<tr><th>Upgrade sources</th><td id="repo_upgrade_sources"></td></tr>
|
||||||
<tr>
|
<tr><th>Upgrades</th><td><span id="repo_checkforupdates"></span></td></tr>
|
||||||
<th>Upgrades</th>
|
|
||||||
<td><span id="repo_checkforupdates"></span></td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -248,10 +248,10 @@
|
||||||
repoMgr.removeEntries();
|
repoMgr.removeEntries();
|
||||||
pkgMgr.removeEntries();
|
pkgMgr.removeEntries();
|
||||||
for(var i1 = 0; i1 < values.length; ++i1) {
|
for(var i1 = 0; i1 < values.length; ++i1) {
|
||||||
repoMgr.addEntry(values[i1]);
|
var repoEntry = repoMgr.addEntry(values[i1]);
|
||||||
var packages = values[i1].packages;
|
var packages = repoEntry.info.packages;
|
||||||
for(var i2 = 0; i2 < packages.length; ++i2) {
|
for(var i2 = 0; i2 < packages.length; ++i2) {
|
||||||
pkgMgr.addEntry(values[i1].name, packages[i2]);
|
pkgMgr.addEntry(repoEntry, packages[i2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.hasBasicRepoInfo = true;
|
this.hasBasicRepoInfo = true;
|
||||||
|
|
|
@ -180,6 +180,24 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.entryByName = function(entryName) {
|
||||||
|
if(this.customSelection) {
|
||||||
|
for(var i = 0; i < this.customSelection.length; ++i) {
|
||||||
|
var entry = this.customSelection[i];
|
||||||
|
if(entry.info && entry.info.name === entryName) {
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for(var i = 0; i < this.entries.length; ++i) {
|
||||||
|
var entry = this.entries[i];
|
||||||
|
if(entry.info && entry.info.name === entryName) {
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// function called by the ALPM client when requested data is available
|
// function called by the ALPM client when requested data is available
|
||||||
this.useRequestedData = function() {
|
this.useRequestedData = function() {
|
||||||
this.invalidate();
|
this.invalidate();
|
||||||
|
|
|
@ -8,7 +8,8 @@
|
||||||
var PackageEntry = {};
|
var PackageEntry = {};
|
||||||
PackageEntry.prototype = new repoindex.Entry();
|
PackageEntry.prototype = new repoindex.Entry();
|
||||||
PackageEntry.prototype.constructor = PackageEntry;
|
PackageEntry.prototype.constructor = PackageEntry;
|
||||||
PackageEntry = function(packageInfo, color) {
|
PackageEntry = function(repoEntry, packageInfo, color) {
|
||||||
|
this.repoEntry = repoEntry; // might be undefined
|
||||||
repoindex.Entry.prototype.constructor.call(this, packageInfo);
|
repoindex.Entry.prototype.constructor.call(this, packageInfo);
|
||||||
|
|
||||||
// init row element
|
// init row element
|
||||||
|
@ -20,7 +21,8 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
this.initTableRow = function() {
|
this.initTableRow = function() {
|
||||||
var values = [this.info.arch, this.info.repo, this.info.name, this.info.ver, this.info.desc, this.info.bdate, ""];
|
var srcOnly = this.repoEntry && this.repoEntry.info.srcOnly;
|
||||||
|
var values = [srcOnly ? "n/a" : this.info.arch, this.info.repo, this.info.name, this.info.ver, this.info.desc, srcOnly ? "n/a" : this.info.bdate, this.info.flagdate];
|
||||||
for(var i = 0; i < 7; ++i) {
|
for(var i = 0; i < 7; ++i) {
|
||||||
this.rowElement.addCell(repoindex.makeStr(values[i]));
|
this.rowElement.addCell(repoindex.makeStr(values[i]));
|
||||||
}
|
}
|
||||||
|
@ -35,6 +37,7 @@
|
||||||
if(info.ver) this.info.ver = info.ver;
|
if(info.ver) this.info.ver = info.ver;
|
||||||
if(info.desc) this.info.desc = info.desc;
|
if(info.desc) this.info.desc = info.desc;
|
||||||
if(info.bdate) this.info.bdate = info.bdate;
|
if(info.bdate) this.info.bdate = info.bdate;
|
||||||
|
if(info.flagdate) this.info.flagdate = info.flagdate;
|
||||||
this.info.basic = true;
|
this.info.basic = true;
|
||||||
if(!noUpdate) {
|
if(!noUpdate) {
|
||||||
this.updateTableRow();
|
this.updateTableRow();
|
||||||
|
@ -80,22 +83,19 @@
|
||||||
this.getContainerQuantity = repoindex.entryManagerGetRepoQuantity;
|
this.getContainerQuantity = repoindex.entryManagerGetRepoQuantity;
|
||||||
|
|
||||||
this.createCustomEntry = function(color) {
|
this.createCustomEntry = function(color) {
|
||||||
return new PackageEntry({}, color);
|
return new PackageEntry(undefined, {}, color);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.addEntry = function(repoName, packageName) {
|
this.addEntry = function(repoEntry, packageName) {
|
||||||
var packageInfo = {
|
var packageInfo = {
|
||||||
index: this.entries.length,
|
index: this.entries.length,
|
||||||
arch: undefined,
|
repo: repoEntry.info.name,
|
||||||
repo: repoName,
|
|
||||||
name: packageName,
|
name: packageName,
|
||||||
version: undefined,
|
|
||||||
desc: undefined,
|
|
||||||
builddate: undefined,
|
|
||||||
flagdate: undefined,
|
|
||||||
received: false
|
received: false
|
||||||
};
|
};
|
||||||
this.entries.push(new PackageEntry(packageInfo));
|
var entry = new PackageEntry(repoEntry, packageInfo);
|
||||||
|
this.entries.push(entry);
|
||||||
|
return entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
// handle a page selection
|
// handle a page selection
|
||||||
|
@ -106,15 +106,22 @@
|
||||||
// if there is no page because there are no package entries, pageElement is null
|
// if there is no page because there are no package entries, pageElement is null
|
||||||
if(pageElement) {
|
if(pageElement) {
|
||||||
// show elements of selected page
|
// show elements of selected page
|
||||||
var packageSelection = []; // package selection for requesting package infos
|
var packageSelection = {}; // package selection for requesting package infos
|
||||||
|
var entriesRequired = false;
|
||||||
pageElement.forRange(function(i) {
|
pageElement.forRange(function(i) {
|
||||||
var entry = mgr.filteredEntries[i];
|
var entry = mgr.filteredEntries[i];
|
||||||
entry.add(mgr.entryContainer);
|
entry.add(mgr.entryContainer);
|
||||||
if(!entry.info.basic) {
|
if(!entry.info.basic) {
|
||||||
packageSelection.push({index: entry.info.index, repo: entry.info.repo, name: entry.info.name});
|
var repoArray = packageSelection[entry.info.repo];
|
||||||
|
if(!Array.isArray(repoArray)) {
|
||||||
|
packageSelection[entry.info.repo] = [{index: entry.info.index, name: entry.info.name}];
|
||||||
|
} else {
|
||||||
|
repoArray.push({index: entry.info.index, name: entry.info.name});
|
||||||
|
}
|
||||||
|
entriesRequired = true;
|
||||||
}
|
}
|
||||||
}, mgr.filteredEntries.length);
|
}, mgr.filteredEntries.length);
|
||||||
if(packageSelection.length > 0) {
|
if(entriesRequired) {
|
||||||
var pkgEntries = repoindex.pageManager.packageManager.relevantEntries();
|
var pkgEntries = repoindex.pageManager.packageManager.relevantEntries();
|
||||||
var useBasicPackageInfo = function(values) {
|
var useBasicPackageInfo = function(values) {
|
||||||
for(var i = 0; i < values.length; ++i) {
|
for(var i = 0; i < values.length; ++i) {
|
||||||
|
@ -228,7 +235,9 @@
|
||||||
};
|
};
|
||||||
if(!i.full) {
|
if(!i.full) {
|
||||||
// don't have the full package info yet -> request full package info
|
// don't have the full package info yet -> request full package info
|
||||||
repoindex.alpmClient.requestFullPackagesInfo([{index: entryIndex, repo: i.repo, name: i.name}], useFullPackageInfo);
|
var packageSelection = {};
|
||||||
|
packageSelection[i.repo] = [{index: entryIndex, name: i.name}];
|
||||||
|
repoindex.alpmClient.requestFullPackagesInfo(packageSelection, useFullPackageInfo);
|
||||||
}
|
}
|
||||||
// set currentInfo (the pageManager needs this value to update the hash)
|
// set currentInfo (the pageManager needs this value to update the hash)
|
||||||
this.currentInfo = i;
|
this.currentInfo = i;
|
||||||
|
@ -254,7 +263,10 @@
|
||||||
showEntry();
|
showEntry();
|
||||||
} else {
|
} else {
|
||||||
// no -> request full info, use callback to show entry when info becomes available
|
// no -> request full info, use callback to show entry when info becomes available
|
||||||
repoindex.alpmClient.requestFullPackagesInfo([{index: i.index, repo: i.repo, name: i.name}], showEntry());
|
//repoindex.alpmClient.requestFullPackagesInfo([{index: i.index, repo: i.repo, name: i.name}], showEntry());
|
||||||
|
var packageSelection = {};
|
||||||
|
packageSelection[i.repo] = [{index: entryIndex, name: i.name}];
|
||||||
|
repoindex.alpmClient.requestFullPackagesInfo(packageSelection, showEntry);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// no -> show error
|
// no -> show error
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
RepoEntry.prototype = new repoindex.Entry();
|
RepoEntry.prototype = new repoindex.Entry();
|
||||||
RepoEntry.prototype.constructor = RepoEntry;
|
RepoEntry.prototype.constructor = RepoEntry;
|
||||||
RepoEntry = function(repoInfo, enabled) {
|
RepoEntry = function(repoInfo, enabled) {
|
||||||
|
if(enabled === undefined) {
|
||||||
|
enabled = !repoInfo.requestRequired;
|
||||||
|
}
|
||||||
repoindex.Entry.prototype.constructor.call(this, repoInfo, enabled);
|
repoindex.Entry.prototype.constructor.call(this, repoInfo, enabled);
|
||||||
|
|
||||||
this.info.currentServer = 0;
|
this.info.currentServer = 0;
|
||||||
|
@ -40,12 +43,14 @@
|
||||||
this.link.setAttribute("data-placement", "bottom");
|
this.link.setAttribute("data-placement", "bottom");
|
||||||
$(this.link).tooltip();
|
$(this.link).tooltip();
|
||||||
|
|
||||||
// create badge with package count
|
if(!repoInfo.requestRequired) {
|
||||||
var span = document.createElement("span");
|
// create badge with package count
|
||||||
span.className = "badge";
|
var span = document.createElement("span");
|
||||||
span.appendChild(document.createTextNode(repoInfo.packages.length));
|
span.className = "badge";
|
||||||
this.link.appendChild(document.createTextNode(" "));
|
span.appendChild(document.createTextNode(repoInfo.packages.length));
|
||||||
this.link.appendChild(span);
|
this.link.appendChild(document.createTextNode(" "));
|
||||||
|
this.link.appendChild(span);
|
||||||
|
}
|
||||||
|
|
||||||
this.link.add = function() {
|
this.link.add = function() {
|
||||||
repoindex.pageManager.repoManager.buttonContainer.appendChild(this);
|
repoindex.pageManager.repoManager.buttonContainer.appendChild(this);
|
||||||
|
@ -103,12 +108,13 @@
|
||||||
|
|
||||||
// provide a function to add repo entries
|
// provide a function to add repo entries
|
||||||
this.addEntry = function(repoInfo) {
|
this.addEntry = function(repoInfo) {
|
||||||
var entry = new RepoEntry(repoInfo, true);
|
var entry = new RepoEntry(repoInfo);
|
||||||
entry.statusChanged = this.applyRepoStatusChange;
|
entry.statusChanged = this.applyRepoStatusChange;
|
||||||
entry.pageManager = this;
|
entry.pageManager = this;
|
||||||
entry.repoEntryManager = this;
|
entry.repoEntryManager = this;
|
||||||
entry.info.index = this.entries.length;
|
entry.info.index = this.entries.length;
|
||||||
this.entries.push(entry);
|
this.entries.push(entry);
|
||||||
|
return entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.baseRemoveEntries = this.removeEntries;
|
this.baseRemoveEntries = this.removeEntries;
|
||||||
|
@ -172,9 +178,10 @@
|
||||||
var i = entry.info;
|
var i = entry.info;
|
||||||
repoindex.setText("repo_name", i.name);
|
repoindex.setText("repo_name", i.name);
|
||||||
repoindex.setText("repo_desc", i.desc);
|
repoindex.setText("repo_desc", i.desc);
|
||||||
repoindex.setText("repo_pkgcount", i.packages.length);
|
repoindex.setText("repo_pkgcount", i.requestRequired ? "unknown" : i.packages.length);
|
||||||
repoindex.setText("repo_usage", repoindex.makeArray(i.usage, ", "));
|
repoindex.setText("repo_usage", repoindex.makeArray(i.usage, ", "));
|
||||||
repoindex.setText("repo_siglevel", repoindex.makeArray(i.sigLevel, ", "));
|
repoindex.setText("repo_siglevel", repoindex.makeArray(i.sigLevel, ", "));
|
||||||
|
repoindex.setText("repo_source_only", repoindex.makeBool(i.srcOnly));
|
||||||
repoindex.setText("repo_upgrade_sources", repoindex.makeArray(i.upgradeSources, ", "));
|
repoindex.setText("repo_upgrade_sources", repoindex.makeArray(i.upgradeSources, ", "));
|
||||||
var invokeUpdateLookupParams = {repo: i.name, invoke: "updatelookup"};
|
var invokeUpdateLookupParams = {repo: i.name, invoke: "updatelookup"};
|
||||||
repoindex.setDownloadButton("repo_checkforupdates", "check for updates", repoindex.makeHash(repoindex.Pages.Repositories, invokeUpdateLookupParams, true), function() {
|
repoindex.setDownloadButton("repo_checkforupdates", "check for updates", repoindex.makeHash(repoindex.Pages.Repositories, invokeUpdateLookupParams, true), function() {
|
||||||
|
@ -238,6 +245,7 @@
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
var pkgMgr = repoindex.pageManager.packageManager;
|
var pkgMgr = repoindex.pageManager.packageManager;
|
||||||
|
var repoMgr = repoindex.pageManager.repoManager;
|
||||||
for(var i1 = 0; i1 < updates.length; ++i1) {
|
for(var i1 = 0; i1 < updates.length; ++i1) {
|
||||||
for(var i2 = 0; i2 < updates[i1].entries.length; ++i2) {
|
for(var i2 = 0; i2 < updates[i1].entries.length; ++i2) {
|
||||||
var newEntry = pkgMgr.createCustomEntry(updates[i1].color);
|
var newEntry = pkgMgr.createCustomEntry(updates[i1].color);
|
||||||
|
@ -247,6 +255,10 @@
|
||||||
if(updates[i1].entries[i2].prevVersion) {
|
if(updates[i1].entries[i2].prevVersion) {
|
||||||
newEntry.info.ver = updates[i1].entries[i2].prevVersion + " → " + (newEntry.info.ver ? newEntry.info.ver : "?");
|
newEntry.info.ver = updates[i1].entries[i2].prevVersion + " → " + (newEntry.info.ver ? newEntry.info.ver : "?");
|
||||||
}
|
}
|
||||||
|
// find associated repo entry
|
||||||
|
if((newEntry.repoEntry = repoMgr.entryByName(newEntry.info.repo))) {
|
||||||
|
newEntry.repoEntry.updateEnabled(true); // ensure repo is enabled
|
||||||
|
}
|
||||||
newEntry.updateTableRow();
|
newEntry.updateTableRow();
|
||||||
} else {
|
} else {
|
||||||
newEntry.applyBasicInfo(updates[i1].entries[i2]);
|
newEntry.applyBasicInfo(updates[i1].entries[i2]);
|
||||||
|
@ -276,14 +288,6 @@
|
||||||
repoindex.pageManager.setPage(repoindex.Pages.Packages);
|
repoindex.pageManager.setPage(repoindex.Pages.Packages);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// determine sync databases (this is done by the server now)
|
|
||||||
//var syncDbNames = [];
|
|
||||||
//var repoEntries = repoindex.pageManager.repoManager.entries;
|
|
||||||
//for(var index = 0; index < repoEntries.length; ++index) {
|
|
||||||
// if(repoEntries[index].info.name !== repo) {
|
|
||||||
// syncDbNames.push(repoEntries[index].info.name);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
repoindex.alpmClient.checkForUpdates(repo, null, showUpdates);
|
repoindex.alpmClient.checkForUpdates(repo, null, showUpdates);
|
||||||
};
|
};
|
||||||
// basic repo info available?
|
// basic repo info available?
|
||||||
|
|
|
@ -18,13 +18,18 @@
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
if(true) {
|
var testobj = {};
|
||||||
var test = "asdf";
|
|
||||||
|
var testarray = testobj["attr"];
|
||||||
|
if(!Array.isArray(testarray)) {
|
||||||
|
testobj["attr"] = testarray = [];
|
||||||
|
}
|
||||||
|
testarray.push("123");
|
||||||
|
testarray.push("456");
|
||||||
|
|
||||||
|
for(var i = 0; i < testobj["attr"].length; ++i) {
|
||||||
|
window.alert(testobj["attr"][i]);
|
||||||
}
|
}
|
||||||
var func = function() {
|
|
||||||
window.alert(test);
|
|
||||||
};
|
|
||||||
func();
|
|
||||||
|
|
||||||
var debugTextArea = document.getElementById("debugTextArea");
|
var debugTextArea = document.getElementById("debugTextArea");
|
||||||
function debug(message) {
|
function debug(message) {
|
||||||
|
|
Loading…
Reference in New Issue