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"),
|
||||
aurArg("aur", "u", "enables/disables AUR queries"),
|
||||
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> pkgValueNames = {"package 1", "package 2", "package 3"};
|
||||
|
@ -83,10 +87,23 @@ ConfigArgs::ConfigArgs(ArgumentParser &parser) :
|
|||
outputFileArg.setCombinable(true);
|
||||
outputFileArg.setRequired(true);
|
||||
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});
|
||||
buildOrderArg.setSecondaryArguments({&aurArg, &verboseArg});
|
||||
mingwBundleArg.setSecondaryArguments({&outputFileArg});
|
||||
mingwBundleArg.setSecondaryArguments({&targetDirArg, &targetNameArg, &targetFormatArg, &iconThemesArg});
|
||||
parser.setMainArguments({&buildOrderArg, &serverArg, &mingwBundleArg, &repoindexConfArg, &repoindexConfArg, &helpArg});
|
||||
}
|
||||
|
||||
|
@ -271,7 +288,10 @@ void RepoEntry::load(const QJsonValue &jsonValue)
|
|||
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
|
||||
|
|
|
@ -7,9 +7,7 @@
|
|||
#include <QStringList>
|
||||
#include <QHostAddress>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QJsonValue;
|
||||
QT_END_NAMESPACE
|
||||
QT_FORWARD_DECLARE_CLASS(QJsonValue)
|
||||
|
||||
namespace PackageManagement {
|
||||
|
||||
|
@ -33,6 +31,10 @@ public:
|
|||
ApplicationUtilities::Argument aurArg;
|
||||
ApplicationUtilities::Argument verboseArg;
|
||||
ApplicationUtilities::Argument outputFileArg;
|
||||
ApplicationUtilities::Argument targetDirArg;
|
||||
ApplicationUtilities::Argument targetNameArg;
|
||||
ApplicationUtilities::Argument targetFormatArg;
|
||||
ApplicationUtilities::Argument iconThemesArg;
|
||||
};
|
||||
|
||||
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 {
|
||||
|
||||
/*!
|
||||
* \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;
|
||||
for(AlpmPackage pkg : packages()) {
|
||||
pkgNames << QString::fromLocal8Bit(pkg.name());
|
||||
name = QString::fromLocal8Bit(group.name());
|
||||
for(auto *pkg : PackageList(group.packages())) {
|
||||
packages << QString::fromLocal8Bit(alpm_pkg_get_name(pkg));
|
||||
}
|
||||
return pkgNames;
|
||||
}
|
||||
|
||||
} // namespace Alpm
|
||||
|
|
25
alpm/group.h
25
alpm/group.h
|
@ -2,14 +2,13 @@
|
|||
#define ALPM_GROUP_H
|
||||
|
||||
#include "list.h"
|
||||
#include "package.h"
|
||||
|
||||
#include <alpm.h>
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QStringList>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QJsonArray;
|
||||
QT_END_NAMESPACE
|
||||
QT_FORWARD_DECLARE_CLASS(QJsonArray)
|
||||
|
||||
namespace PackageManagement {
|
||||
|
||||
|
@ -21,11 +20,9 @@ public:
|
|||
// group properties
|
||||
const char *name() const;
|
||||
PackageList packages() const;
|
||||
QJsonArray packageNames() const;
|
||||
|
||||
private:
|
||||
const alpm_group_t *m_ptr;
|
||||
|
||||
};
|
||||
|
||||
/*!
|
||||
|
@ -51,6 +48,20 @@ inline PackageList AlpmGroup::packages() const
|
|||
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
|
||||
|
|
|
@ -111,6 +111,7 @@ typedef AlpmList<const char *> StringList;
|
|||
typedef AlpmList<alpm_depend_t *> DependencyList;
|
||||
typedef AlpmList<alpm_pkg_t *> PackageList;
|
||||
typedef AlpmList<alpm_group_t *> GroupList;
|
||||
typedef AlpmList<alpm_backup_t *> BackupList;
|
||||
|
||||
} // namespace Alpm
|
||||
|
||||
|
|
314
alpm/manager.cpp
314
alpm/manager.cpp
|
@ -1,11 +1,14 @@
|
|||
#include "manager.h"
|
||||
#include "database.h"
|
||||
#include "alpmdatabase.h"
|
||||
#include "utilities.h"
|
||||
#include "list.h"
|
||||
#include "config.h"
|
||||
|
||||
#include "network/userrepository.h"
|
||||
|
||||
#include <c++utilities/io/inifile.h>
|
||||
#include <c++utilities/conversion/stringconversion.h>
|
||||
#include <c++utilities/misc/memory.h>
|
||||
|
||||
#include <QList>
|
||||
#include <QSysInfo>
|
||||
|
@ -22,9 +25,23 @@ using namespace ConversionUtilities;
|
|||
|
||||
namespace PackageManagement {
|
||||
|
||||
/*!
|
||||
* \cond
|
||||
*/
|
||||
|
||||
constexpr int defaultSigLevel = ALPM_SIG_PACKAGE | ALPM_SIG_PACKAGE_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.
|
||||
*
|
||||
|
@ -40,12 +57,15 @@ constexpr int defaultSigLevel = ALPM_SIG_PACKAGE | ALPM_SIG_PACKAGE_OPTIONAL |
|
|||
Manager::Manager(const Config &config) :
|
||||
m_config(config),
|
||||
m_sigLevel(defaultSigLevel),
|
||||
m_localFileSigLevel(ALPM_SIG_USE_DEFAULT),
|
||||
m_aur(m_networkAccessManager)
|
||||
m_localFileSigLevel(ALPM_SIG_USE_DEFAULT)
|
||||
{
|
||||
alpm_errno_t 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.
|
||||
*/
|
||||
AlpmPackage Manager::packageFromSyncDataBase(const QString &dbName, const QString &pkgName) const
|
||||
AlpmPackage *Manager::packageFromDataBase(const QString &dbName, const QString &pkgName)
|
||||
{
|
||||
try {
|
||||
if(dbName == QLatin1String("local")) {
|
||||
return localDataBase().packages().at(pkgName);
|
||||
} else {
|
||||
return syncDataBases().at(dbName).packages().at(pkgName);
|
||||
}
|
||||
} catch(out_of_range &) {
|
||||
return AlpmPackage();
|
||||
if(auto *db = dataBaseByName(dbName)) {
|
||||
return static_cast<AlpmPackage *>(db->packageByName(pkgName));
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \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.
|
||||
*
|
||||
* 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;
|
||||
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)));
|
||||
} else {
|
||||
return AlpmOwnershipPackage(pkg);
|
||||
return make_unique<AlpmOwnershipPackage>(pkg);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \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)) {
|
||||
throw runtime_error(string("Unable to set install reason of the package ") + package.name() + ": " + alpm_strerror(alpm_errno(m_handle)));
|
||||
if(alpm_pkg_set_reason(package->ptr(), reason)) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
auto emplaced = m_syncDbs.emplace(dbName, make_unique<AlpmDataBase>(db, m_config.alpmDbPath()));
|
||||
// add sync db to internal map
|
||||
if(usage & ALPM_DB_USAGE_UPGRADE) {
|
||||
// -> db is used to upgrade local database
|
||||
localDataBase().upgradeSources() << dbName;
|
||||
localDataBase()->upgradeSources() << emplaced.first->second.get();
|
||||
}
|
||||
m_syncDbs.emplace(dbName, AlpmDataBase(db, QStringLiteral("%1/sync/%2").arg(m_config.alpmDbPath(), dbName)));
|
||||
} else {
|
||||
cerr << "Error: Unable to add sync database [" << scope.first << "]" << endl;
|
||||
}
|
||||
|
@ -324,18 +378,19 @@ void Manager::applyPacmanConfig()
|
|||
*/
|
||||
void Manager::applyRepoIndexConfig()
|
||||
{
|
||||
// check whether an entry already exists, if not create a new one
|
||||
for(const RepoEntry &repoEntry : m_config.repoEntries()) {
|
||||
AlpmDataBase *syncDb;
|
||||
AlpmDataBase *syncDb = nullptr;
|
||||
try {
|
||||
syncDb = &m_syncDbs.at(repoEntry.name());
|
||||
syncDb = m_syncDbs.at(repoEntry.name()).get();
|
||||
cerr << "Applying config for database [" << syncDb->name() << "]" << endl;
|
||||
if(!repoEntry.dataBasePath().isEmpty()) {
|
||||
cerr << "Warning: Can't use data base path specified in repo index config because the repo \""
|
||||
<< 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()) {
|
||||
cerr << "Warning: Can't use sig level path specified in repo index config because the repo \""
|
||||
<< repoEntry.name().toLocal8Bit().data() << "\" has already been added from the Pacman config." << endl;
|
||||
cerr << "Warning: Can't use sig level specified in repo index config because the repo \""
|
||||
<< repoEntry.name() << "\" has already been added from the Pacman config." << endl;
|
||||
}
|
||||
syncDb->setPackagesDirectory(repoEntry.packageDir());
|
||||
syncDb->setSourcesDirectory(repoEntry.sourceDir());
|
||||
|
@ -345,21 +400,39 @@ void Manager::applyRepoIndexConfig()
|
|||
} 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;
|
||||
} else {
|
||||
// TODO: database path
|
||||
auto *db = alpm_register_syncdb(m_handle, repoEntry.name().toLocal8Bit().data(), static_cast<alpm_siglevel_t>(repoEntry.sigLevel()));
|
||||
auto emplaced = m_syncDbs.emplace(repoEntry.name(), 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) {
|
||||
syncDb = &emplaced.first->second;
|
||||
syncDb = emplaced.first->second.get();
|
||||
syncDb->setSourcesDirectory(repoEntry.sourceDir());
|
||||
syncDb->setPackagesDirectory(repoEntry.packageDir());
|
||||
if(m_config.isVerbose() || m_config.runServer()) {
|
||||
cerr << "Added database [" << repoEntry.name().toLocal8Bit().data() << "]" << endl;
|
||||
cerr << "Added database [" << repoEntry.name() << "]" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(syncDb) {
|
||||
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.
|
||||
* \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
|
||||
}
|
||||
|
||||
/*!
|
||||
* \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.
|
||||
*
|
||||
|
@ -433,17 +465,22 @@ const QJsonArray &Manager::basicRepoInfo() const
|
|||
if(m_basicRepoInfo.isEmpty()) {
|
||||
QMutexLocker locker(&m_basicRepoInfoMutex);
|
||||
if(m_basicRepoInfo.isEmpty()) {
|
||||
m_basicRepoInfo << basicRepoInfo(localDataBase(), QStringLiteral("local"), QStringLiteral("The local database."));
|
||||
auto const &syncDbs = syncDataBases();
|
||||
for(const auto &syncDb : syncDbs) {
|
||||
// add local data base
|
||||
m_basicRepoInfo << localDataBase()->basicInfo();
|
||||
// add sync data bases
|
||||
for(const auto &syncDb : syncDataBases()) {
|
||||
// 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)) {
|
||||
m_basicRepoInfo << basicRepoInfo(syncDb.second, syncDb.first, QStringLiteral("The sync database »%1«.").arg(syncDb.first));
|
||||
m_basicRepoInfo << syncDb.second->basicInfo();
|
||||
} 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;
|
||||
|
@ -452,26 +489,38 @@ const QJsonArray &Manager::basicRepoInfo() const
|
|||
/*!
|
||||
* \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;
|
||||
for(const auto &pkgSelJsonVal : pkgSelection) {
|
||||
QJsonObject pkgSel = pkgSelJsonVal.toObject();
|
||||
if(!pkgSel.isEmpty()) {
|
||||
QString repoName = pkgSel.value(QStringLiteral("repo")).toString();
|
||||
QString pkgName = pkgSel.value(QStringLiteral("name")).toString();
|
||||
AlpmPackage pkg;
|
||||
QJsonObject pkgInfo;
|
||||
if(!repoName.isEmpty() && !pkgName.isEmpty() && (pkg = packageFromSyncDataBase(repoName, pkgName))) {
|
||||
pkgInfo = full ? pkg.fullInfo() : pkg.basicInfo();
|
||||
} else {
|
||||
pkgInfo.insert(QStringLiteral("error"), QStringLiteral("na"));
|
||||
for(auto i = pkgSelection.constBegin(), end = pkgSelection.constEnd(); i != end; ++i) {
|
||||
if(auto *repo = repositoryByName(i.key())) {
|
||||
for(const auto &entry : i.value().toArray()) {
|
||||
const auto entryObj = entry.toObject();
|
||||
const auto pkgName = entryObj.value(QStringLiteral("name")).toString();
|
||||
if(!pkgName.isEmpty()) {
|
||||
QJsonObject pkgInfo;
|
||||
if(auto *pkg = repo->packageByName(pkgName)) {
|
||||
pkgInfo = full ? pkg->fullInfo() : pkg->basicInfo();
|
||||
} else {
|
||||
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);
|
||||
pkgInfo.insert(QStringLiteral("repo"), repoName);
|
||||
pkgInfo.insert(QStringLiteral("index"), pkgSel.value(QStringLiteral("index")));
|
||||
pkgInfos << pkgInfo;
|
||||
} else {
|
||||
// specified repository can not be found
|
||||
QJsonObject errorObj;
|
||||
errorObj.insert(QStringLiteral("repo"), i.key());
|
||||
errorObj.insert(QStringLiteral("error"), QStringLiteral("na"));
|
||||
pkgInfos << errorObj;
|
||||
}
|
||||
|
||||
}
|
||||
return pkgInfos;
|
||||
}
|
||||
|
@ -484,9 +533,9 @@ const QJsonArray &Manager::groupInfo() const
|
|||
if(m_groupInfo.empty()) {
|
||||
QMutexLocker locker(&m_groupInfoMutex);
|
||||
if(m_groupInfo.empty()) {
|
||||
m_groupInfo << localDataBase().groupInfo();
|
||||
m_groupInfo << localDataBase()->groupInfo();
|
||||
for(const auto &db : m_syncDbs) {
|
||||
m_groupInfo << db.second.groupInfo();
|
||||
m_groupInfo << db.second->groupInfo();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -495,41 +544,70 @@ const QJsonArray &Manager::groupInfo() const
|
|||
|
||||
/*!
|
||||
* \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();
|
||||
} 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.
|
||||
* \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();
|
||||
} 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.
|
||||
*
|
||||
* 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.
|
||||
* \brief Returns the package source with the specified name.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
const UpdateLookupResults<AlpmPackage> Manager::checkForUpgrades(const AlpmDataBase &db) const
|
||||
const UpgradeLookupResults Manager::checkForUpgrades(AlpmDataBase *db) const
|
||||
{
|
||||
UpdateLookupResults<AlpmPackage> results;
|
||||
QList<const AlpmDataBase *> syncDbSel;
|
||||
for(const auto &syncDbName : db.upgradeSources()) {
|
||||
try {
|
||||
syncDbSel << &(syncDataBases().at(syncDbName));
|
||||
} catch(out_of_range &) {
|
||||
;
|
||||
}
|
||||
}
|
||||
db.checkForUpgrades(syncDbSel, results);
|
||||
UpgradeLookupResults results;
|
||||
db->checkForUpgrades(results);
|
||||
return results;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
#ifndef ALPM_MANAGER_H
|
||||
#define ALPM_MANAGER_H
|
||||
|
||||
#include "database.h"
|
||||
#include "updatelookup.h"
|
||||
|
||||
#include "network/aurquery.h"
|
||||
#include "upgradelookup.h"
|
||||
#include "alpmpackage.h"
|
||||
|
||||
#include <alpm.h>
|
||||
|
||||
|
@ -14,11 +12,13 @@
|
|||
#include <QMutex>
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
namespace PackageManagement {
|
||||
|
||||
class Config;
|
||||
template<class Package> class UpdateLookupResults;
|
||||
class UserRepository;
|
||||
class AlpmDataBase;
|
||||
|
||||
class Manager
|
||||
{
|
||||
|
@ -42,30 +42,33 @@ public:
|
|||
void applyRepoIndexConfig();
|
||||
|
||||
void unregisterSyncDataBases();
|
||||
const AurQuery &aurQuery() const;
|
||||
AurQuery &aurQuery();
|
||||
const UserRepository *userRepository() const;
|
||||
UserRepository *userRepository();
|
||||
|
||||
// package lookup
|
||||
AlpmPackage packageFromSyncDataBase(const QString &dbName, const QString &pkgName) const;
|
||||
AlpmPackage packageFromSyncDataBases(const char *name) const;
|
||||
AlpmOwnershipPackage packageFromFile(const char *fileName, bool verifyIntegrity = false);
|
||||
bool isPackageIgnored(AlpmPackage package) const;
|
||||
void setInstallReason(AlpmPackage package, alpm_pkgreason_t reason);
|
||||
AlpmPackage *packageFromDataBase(const QString &dbName, const QString &pkgName);
|
||||
const AlpmPackage *packageFromDataBase(const QString &dbName, const QString &pkgName) const;
|
||||
AlpmPackage *packageFromSyncDataBases(const QString &pkgName);
|
||||
const AlpmPackage *packageFromSyncDataBases(const QString &pkgName) const;
|
||||
std::unique_ptr<AlpmOwnershipPackage> packageFromFile(const char *fileName, bool verifyIntegrity = false);
|
||||
bool isPackageIgnored(const AlpmPackage *package) const;
|
||||
void setInstallReason(AlpmPackage *package, alpm_pkgreason_t reason);
|
||||
|
||||
// database lookup
|
||||
const AlpmDataBase &localDataBase() const;
|
||||
AlpmDataBase &localDataBase();
|
||||
const std::map<QString, AlpmDataBase> &syncDataBases() const;
|
||||
const AlpmDataBase &dataBaseByName(const QString &dbName) const;
|
||||
AlpmDataBase &dataBaseByName(const QString &dbName);
|
||||
const UpdateLookupResults<AlpmPackage> checkForUpgrades(const AlpmDataBase &db) const;
|
||||
// data base lookup
|
||||
const AlpmDataBase *localDataBase() const;
|
||||
AlpmDataBase *localDataBase();
|
||||
const std::map<QString, std::unique_ptr<AlpmDataBase> > &syncDataBases() const;
|
||||
const AlpmDataBase *dataBaseByName(const QString &dbName) const;
|
||||
AlpmDataBase *dataBaseByName(const QString &dbName);
|
||||
const Repository *repositoryByName(const QString &name) const;
|
||||
Repository *repositoryByName(const QString &name);
|
||||
const UpgradeLookupResults checkForUpgrades(AlpmDataBase *db) const;
|
||||
|
||||
// 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 packageInfo(const QJsonArray &pkgSelection, bool full = true) const;
|
||||
const QJsonArray packageInfo(const QJsonObject &pkgSelection, bool full = true) const;
|
||||
const QJsonArray &groupInfo() const;
|
||||
void invokeUpgradeLookup(const QJsonObject &request, UpdateLookupCallback callback) const;
|
||||
|
||||
private:
|
||||
void cleanup();
|
||||
|
@ -76,10 +79,9 @@ private:
|
|||
int m_localFileSigLevel;
|
||||
QString m_pacmanCacheDir;
|
||||
QNetworkAccessManager m_networkAccessManager;
|
||||
AurQuery m_aur;
|
||||
mutable AlpmDataBase m_localDb;
|
||||
mutable QMutex m_localDbMutex;
|
||||
mutable std::map<QString, AlpmDataBase> m_syncDbs;
|
||||
std::unique_ptr<UserRepository> m_userRepo;
|
||||
std::unique_ptr<AlpmDataBase> m_localDb;
|
||||
std::map<QString, std::unique_ptr<AlpmDataBase> > m_syncDbs;
|
||||
mutable QJsonArray m_basicRepoInfo;
|
||||
mutable QMutex m_basicRepoInfoMutex;
|
||||
mutable QJsonArray m_groupInfo;
|
||||
|
@ -135,20 +137,12 @@ inline void Manager::setLocalFileSigLevel(int 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.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
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 "utilities.h"
|
||||
#include "manager.h"
|
||||
|
||||
#include <c++utilities/conversion/stringconversion.h>
|
||||
#include <c++utilities/misc/memory.h>
|
||||
|
||||
#include <KTar>
|
||||
#include <K7Zip>
|
||||
#include <KZip>
|
||||
|
||||
#include <QFile>
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
#include <QStringBuilder>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonArray>
|
||||
#include <QFile>
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
@ -16,18 +22,25 @@ using namespace std;
|
|||
|
||||
namespace PackageManagement {
|
||||
|
||||
using namespace Utilities;
|
||||
|
||||
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)
|
||||
{
|
||||
cerr << "Resolving dependencies ..." << endl;
|
||||
string missing;
|
||||
// add mingw-w64 packages
|
||||
for(const auto &pkgName : packages) {
|
||||
bool found = false;
|
||||
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()) {
|
||||
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);
|
||||
found = true;
|
||||
|
@ -39,50 +52,125 @@ MingwBundle::MingwBundle(const Manager &manager, const ApplicationUtilities::Str
|
|||
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()) {
|
||||
throw runtime_error("The following packages can not be found:" + missing);
|
||||
} else {
|
||||
cerr << "Adding the following packages:";
|
||||
for(const auto &pkg : m_packages) {
|
||||
cerr << ' ' << pkg.second.name();
|
||||
cerr << ' ' << pkg.second->name().toLocal8Bit().data();
|
||||
}
|
||||
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
|
||||
{
|
||||
Binary,
|
||||
Translation
|
||||
Translation,
|
||||
QtTranslation,
|
||||
QtPlugin,
|
||||
Icon
|
||||
};
|
||||
|
||||
enum class RelevantFileArch
|
||||
{
|
||||
x86_64,
|
||||
i686
|
||||
i686,
|
||||
Any
|
||||
};
|
||||
|
||||
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),
|
||||
fileType(type),
|
||||
arch(arch)
|
||||
arch(arch),
|
||||
subDir(subDir)
|
||||
{}
|
||||
const KArchiveFile *file;
|
||||
RelevantFileType fileType;
|
||||
RelevantFileArch arch;
|
||||
QString subDir;
|
||||
};
|
||||
|
||||
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;
|
||||
unique_ptr<KTar> archive;
|
||||
list<RelevantFile> relevantFiles;
|
||||
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)
|
||||
{
|
||||
pkgFileInfo.archive = make_unique<KTar>(pkgFileInfo.path);
|
||||
|
@ -104,65 +192,190 @@ void getFiles(PkgFileInfo &pkgFileInfo)
|
|||
if(entry->isFile()) {
|
||||
const auto *binFile = static_cast<const KArchiveFile *>(entry);
|
||||
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 {
|
||||
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;
|
||||
for(const auto &entry : m_packages) {
|
||||
QString pkgFile;
|
||||
if(!entry.first.packagesDirectory().isEmpty()) {
|
||||
pkgFile = QStringLiteral("%1/%2").arg(entry.first.packagesDirectory(), QString::fromLocal8Bit(entry.second.fileName()));
|
||||
if(!entry.first->packagesDirectory().isEmpty()) {
|
||||
pkgFile = entry.first->packagesDirectory() % QChar('/') % entry.second->fileName();
|
||||
}
|
||||
if(pkgFile.isEmpty() || !QFile::exists(pkgFile)) {
|
||||
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)) {
|
||||
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
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
void MingwBundle::addDependencies(const AlpmPackage &pkg)
|
||||
{
|
||||
string missing;
|
||||
for(const auto &depInfo : pkg.dependencies()) {
|
||||
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);
|
||||
// check whether all packages could be opened
|
||||
string failed;
|
||||
for(const auto &pkgFile : pkgFiles) {
|
||||
if(pkgFile.failure) {
|
||||
failed.push_back(' ');
|
||||
failed.append(pkgFile.path.toLocal8Bit().data());
|
||||
}
|
||||
}
|
||||
if(!missing.empty()) {
|
||||
throw runtime_error("The following dependencies of the " + string(pkg.name()) + " package can not be resolved:" + missing);
|
||||
if(!failed.empty()) {
|
||||
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
|
||||
|
||||
#include "package.h"
|
||||
#include "database.h"
|
||||
#include "alpmdatabase.h"
|
||||
|
||||
#include <c++utilities/application/argumentparser.h>
|
||||
|
||||
|
@ -15,15 +15,15 @@ class Manager;
|
|||
class MingwBundle
|
||||
{
|
||||
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:
|
||||
void addDependencies(const AlpmPackage &pkg);
|
||||
void addDependencies(const Package *pkg);
|
||||
|
||||
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
|
||||
|
|
404
alpm/package.cpp
404
alpm/package.cpp
|
@ -1,5 +1,7 @@
|
|||
#include "package.h"
|
||||
#include "database.h"
|
||||
#include "alpmdatabase.h"
|
||||
#include "utilities.h"
|
||||
#include "repository.h"
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QJsonValue>
|
||||
|
@ -11,82 +13,191 @@ using namespace ChronoUtilities;
|
|||
|
||||
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
|
||||
*/
|
||||
|
||||
inline QString qstr(const char *str)
|
||||
{
|
||||
return QString::fromLocal8Bit(str);
|
||||
}
|
||||
namespace Utilities {
|
||||
|
||||
inline QJsonArray qjarry(StringList list)
|
||||
inline void put(QJsonObject &obj, const QString &key, const QJsonValue &value)
|
||||
{
|
||||
QJsonArray jsonArray;
|
||||
for(const char *str : list) {
|
||||
jsonArray << qstr(str);
|
||||
if(!value.isNull()) {
|
||||
obj.insert(key, value);
|
||||
}
|
||||
return jsonArray;
|
||||
}
|
||||
|
||||
inline QJsonArray qjarry(DependencyList list)
|
||||
inline void put(QJsonObject &obj, const QString &key, const DateTime dateTime)
|
||||
{
|
||||
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;
|
||||
if(!dateTime.isNull()) {
|
||||
put(obj, key, QString::fromLocal8Bit(dateTime.toString().data()));
|
||||
}
|
||||
}
|
||||
|
||||
inline void put(QJsonObject &obj, const QString &key, const QStringList &values)
|
||||
{
|
||||
if(!values.isEmpty()) {
|
||||
put(obj, key, QJsonArray::fromStringList(values));
|
||||
}
|
||||
}
|
||||
|
||||
void put(QJsonObject &obj, const QString &key, const QList<Dependency> &dependencies)
|
||||
{
|
||||
if(!dependencies.isEmpty()) {
|
||||
QJsonArray jsonArray;
|
||||
for(const auto &dep : dependencies) {
|
||||
QJsonObject depObj;
|
||||
depObj.insert(QStringLiteral("name"), dep.name);
|
||||
depObj.insert(QStringLiteral("ver"), dep.version);
|
||||
switch(dep.mode) {
|
||||
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;
|
||||
}
|
||||
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
|
||||
*/
|
||||
|
||||
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.
|
||||
*/
|
||||
|
@ -94,18 +205,11 @@ inline QJsonArray qjarry(_alpm_pkgvalidation_t validation)
|
|||
/*!
|
||||
* \brief Constructs a new PackageVersion instance from the specified \a 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)
|
||||
PackageVersion::PackageVersion(const QString &versionStr)
|
||||
{
|
||||
// determine start offsets of version and release
|
||||
const char *versionBeg = nullptr, *releaseBeg = nullptr;
|
||||
for(const char *i = versionStr; ; ++i) {
|
||||
const ushort *str = versionStr.utf16(), *versionBeg = nullptr, *releaseBeg = nullptr;
|
||||
for(const auto *i = str; ; ++i) {
|
||||
switch(*i) {
|
||||
case 0:
|
||||
goto terminationFound;
|
||||
|
@ -123,22 +227,22 @@ PackageVersion::PackageVersion(const char *versionStr)
|
|||
terminationFound:
|
||||
if(versionBeg) {
|
||||
// epoch present
|
||||
epoch = QString::fromLocal8Bit(versionStr, versionBeg - versionStr - 1);
|
||||
epoch = QString::fromUtf16(str, versionBeg - str - 1);
|
||||
if(releaseBeg) {
|
||||
// release present
|
||||
version = QString::fromLocal8Bit(versionBeg, releaseBeg - versionBeg - 1);
|
||||
release = QString::fromLocal8Bit(releaseBeg);
|
||||
version = QString::fromUtf16(versionBeg, releaseBeg - versionBeg - 1);
|
||||
release = QString::fromUtf16(releaseBeg);
|
||||
} else {
|
||||
version = QString::fromLocal8Bit(versionBeg);
|
||||
version = QString::fromUtf16(versionBeg);
|
||||
}
|
||||
} else {
|
||||
// epoch not present
|
||||
if(releaseBeg) {
|
||||
// release present
|
||||
version = QString::fromLocal8Bit(versionStr, releaseBeg - versionStr - 1);
|
||||
release = QString::fromLocal8Bit(releaseBeg);
|
||||
version = QString::fromUtf16(str, releaseBeg - str - 1);
|
||||
release = QString::fromUtf16(releaseBeg);
|
||||
} else {
|
||||
version = QString::fromLocal8Bit(versionStr);
|
||||
version = QString::fromUtf16(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -227,157 +331,5 @@ PackageVersionComparsion PackageVersion::compare(const PackageVersion &other) co
|
|||
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 <QHash>
|
||||
#include <QJsonArray>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QJsonObject;
|
||||
class QJsonValue;
|
||||
QT_END_NAMESPACE
|
||||
QT_FORWARD_DECLARE_CLASS(QJsonObject)
|
||||
QT_FORWARD_DECLARE_CLASS(QJsonValue)
|
||||
|
||||
namespace PackageManagement {
|
||||
|
||||
class Repository;
|
||||
|
||||
/*!
|
||||
* \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. */
|
||||
};
|
||||
|
||||
/*!
|
||||
* \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
|
||||
{
|
||||
public:
|
||||
PackageVersion(const QString &versionStr);
|
||||
PackageVersion(const char *versionStr);
|
||||
explicit PackageVersion(const QString &versionStr);
|
||||
|
||||
static PackageVersionPartComparsion compareParts(const QString &part1, const QString &part2);
|
||||
PackageVersionComparsion compare(const PackageVersion &other) const;
|
||||
|
@ -55,487 +74,525 @@ public:
|
|||
QString release;
|
||||
};
|
||||
|
||||
class AurPackage
|
||||
class Dependency
|
||||
{
|
||||
public:
|
||||
AurPackage();
|
||||
AurPackage(const QJsonValue &aurJsonValue);
|
||||
explicit Dependency(const QString &name, const QString &version, _alpm_depmod_t mode = ALPM_DEP_MOD_ANY);
|
||||
QString name;
|
||||
QString version;
|
||||
_alpm_depmod_t mode;
|
||||
};
|
||||
|
||||
bool isValid() const;
|
||||
bool hasFullInfo() const;
|
||||
int id() const;
|
||||
int categoryId() const;
|
||||
inline Dependency::Dependency(const QString &name, const QString &version, _alpm_depmod_t mode) :
|
||||
name(name),
|
||||
version(version),
|
||||
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 &version() const;
|
||||
template<class Package>
|
||||
PackageVersionComparsion compareVersion(const Package &syncPackage) const;
|
||||
const QString &description() 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;
|
||||
ChronoUtilities::DateTime outOfDate() const;
|
||||
const QString &maintainer() const;
|
||||
ChronoUtilities::DateTime firstSubmitted() const;
|
||||
ChronoUtilities::DateTime lastModified() const;
|
||||
const QString &license() const;
|
||||
const QString &tarUrl() const;
|
||||
|
||||
// JSON serialization
|
||||
QJsonObject basicInfo(bool includeRepoAndName) const;
|
||||
QJsonObject fullInfo(bool includeRepoAndName = false) const;
|
||||
|
||||
private:
|
||||
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;
|
||||
// version comparsion
|
||||
PackageVersionComparsion compareVersion(const Package *syncPackage) const;
|
||||
PackageVersionComparsion compareVersion(const Dependency &dependency) const;
|
||||
static bool matches(const QString &name, const QString &version, const Dependency &dependency);
|
||||
bool matches(const Dependency &dependency);
|
||||
|
||||
// JSON serialization
|
||||
QJsonObject basicInfo(bool includeRepoAndName = false) const;
|
||||
QJsonObject fullInfo(bool includeRepoAndName = false) const;
|
||||
|
||||
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) :
|
||||
m_ptr(package)
|
||||
{}
|
||||
|
||||
inline const alpm_pkg_t *AlpmPackage::ptr() const
|
||||
inline PackageOrigin Package::origin() const
|
||||
{
|
||||
return m_ptr;
|
||||
}
|
||||
|
||||
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);
|
||||
return m_origin;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \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 PackageVersionComparsion AlpmPackage::compareVersion(const Package &syncPackage) const
|
||||
inline bool Package::hasBuildRelatedMetaData() 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);
|
||||
}
|
||||
|
||||
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());
|
||||
return matches(name(), version(), dependency);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
if(const auto pkg = m_manager.packageFromSyncDataBases(task->name().toLocal8Bit().data())) {
|
||||
for(auto dep : pkg.dependencies()) {
|
||||
if(auto *depTask = addDep(tasks, dep->name)) {
|
||||
for(auto dep : pkg->dependencies()) {
|
||||
if(auto *depTask = addDep(tasks, dep.name)) {
|
||||
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)) {
|
||||
// we've already added a task for this dependency
|
||||
|
|
|
@ -20,7 +20,7 @@ public:
|
|||
|
||||
private:
|
||||
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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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 <QString>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QStringList>
|
||||
|
||||
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
|
||||
|
|
|
@ -3,15 +3,12 @@
|
|||
|
||||
#include "list.h"
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QString>
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QString;
|
||||
class QJsonArray;
|
||||
QT_END_NAMESPACE
|
||||
QT_FORWARD_DECLARE_CLASS(QJsonArray)
|
||||
|
||||
namespace PackageManagement {
|
||||
|
||||
|
@ -22,6 +19,22 @@ std::list<std::string> getNames(DependencyList dependencyList);
|
|||
QJsonArray sigLevelStrings(alpm_siglevel_t sigLevel);
|
||||
QJsonArray usageStrings(alpm_db_usage_t usage);
|
||||
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
|
||||
QMAKE_CXXFLAGS += -std=c++11
|
||||
QMAKE_LFLAGS += -std=c++11
|
||||
unix {
|
||||
QMAKE_LFLAGS += "-Wl,--rpath=./"
|
||||
}
|
||||
# prefix
|
||||
targetprefix = $$(TARGET_PREFIX)
|
||||
message("Using target prefix \"$${targetprefix}\".")
|
||||
|
|
8
main.cpp
8
main.cpp
|
@ -3,6 +3,7 @@
|
|||
#include "alpm/config.h"
|
||||
#include "alpm/resolvebuildorder.h"
|
||||
#include "alpm/mingwbundle.h"
|
||||
|
||||
#include "network/server.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) {
|
||||
return arg != &configArgs.helpArg && arg->isPresent();
|
||||
}) != parser.mainArguments().cend()) {
|
||||
cerr << "Loading databases ..." << endl;
|
||||
// create app
|
||||
QCoreApplication application(argc, argv);
|
||||
// setup ALPM
|
||||
|
@ -61,8 +63,10 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
cout << endl;
|
||||
} else if(configArgs.mingwBundleArg.isPresent()) {
|
||||
MingwBundle bundle(manager, configArgs.mingwBundleArg.values());
|
||||
bundle.createBundle(configArgs.outputFileArg.values().front());
|
||||
MingwBundle bundle(manager, configArgs.mingwBundleArg.values(), configArgs.iconThemesArg.values());
|
||||
bundle.createBundle(configArgs.targetDirArg.isPresent() ? configArgs.targetDirArg.values().front() : string("."),
|
||||
configArgs.targetNameArg.values().front(),
|
||||
configArgs.targetFormatArg.isPresent() ? configArgs.targetFormatArg.values().front() : string("zip"));
|
||||
}
|
||||
} else {
|
||||
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 "alpm/manager.h"
|
||||
#include "alpm/upgradelookup.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QWebSocket>
|
||||
|
||||
#include <functional>
|
||||
|
||||
using namespace std;
|
||||
using namespace PackageManagement;
|
||||
|
||||
namespace Network {
|
||||
|
||||
Connection::Connection(const PackageManagement::Manager &alpmManager, QWebSocket *socket, QObject *parent) :
|
||||
Connection::Connection(const Manager &alpmManager, QWebSocket *socket, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_socket(socket),
|
||||
m_alpmManager(alpmManager),
|
||||
|
@ -39,7 +38,7 @@ void Connection::sendError(const QString &msg)
|
|||
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;
|
||||
response.insert(QStringLiteral("class"), QStringLiteral("results"));
|
||||
|
@ -51,7 +50,7 @@ void Connection::sendResult(const QString &what, const QJsonValue &id, const QJs
|
|||
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;
|
||||
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);
|
||||
sendResults(what, id, m_alpmManager.basicRepoInfo());
|
||||
} 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")) {
|
||||
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")) {
|
||||
m_groupInfoUpdatesRequested = obj.value(QStringLiteral("updates")).toBool(m_groupInfoUpdatesRequested);
|
||||
sendResults(what, id, m_alpmManager.groupInfo());
|
||||
} else if(what == QLatin1String("checkforupdates")) {
|
||||
//sendResult(what, id, m_alpmManager.invokeUpgradeLookup(obj));
|
||||
m_alpmManager.invokeUpgradeLookup(obj, bind(&Connection::sendResult, this, what, id, placeholders::_1));
|
||||
//m_alpmManager.checkForUpgrades(obj, [this] (const QJsonObject &results) {
|
||||
// sendResult(what, id, results);
|
||||
//};
|
||||
connect(new UpgradeLookup(m_alpmManager, obj), &UpgradeLookup::resultsAvailable, this, &Connection::sendResult);
|
||||
} else if(what == QLatin1String("ping")) {
|
||||
sendResult(what, id, QStringLiteral("pong"));
|
||||
} else {
|
||||
|
|
|
@ -24,12 +24,12 @@ private slots:
|
|||
void processTextMessage(const QString &message);
|
||||
void processBinaryMessage(const QByteArray &message);
|
||||
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:
|
||||
void sendJson(const QJsonObject &obj);
|
||||
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);
|
||||
|
||||
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
|
||||
appname = "Repository Index"
|
||||
appauthor = Martchus
|
||||
appurl = "https://github.com/$${appauthor}/$${projectname}"
|
||||
VERSION = 1.0.0
|
||||
|
||||
# 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/package.cpp \
|
||||
alpm/utilities.cpp \
|
||||
alpm/database.cpp \
|
||||
network/server.cpp \
|
||||
network/connection.cpp \
|
||||
alpm/group.cpp \
|
||||
alpm/config.cpp \
|
||||
network/aurquery.cpp \
|
||||
alpm/updatelookup.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 += \
|
||||
alpm/manager.h \
|
||||
alpm/package.h \
|
||||
alpm/list.h \
|
||||
alpm/utilities.h \
|
||||
alpm/database.h \
|
||||
network/server.h \
|
||||
network/connection.h \
|
||||
alpm/group.h \
|
||||
alpm/config.h \
|
||||
network/aurquery.h \
|
||||
alpm/updatelookup.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 += \
|
||||
README.md \
|
||||
|
@ -60,13 +69,18 @@ DISTFILES += \
|
|||
web/css/dashboard.css \
|
||||
repoindex.conf.js
|
||||
|
||||
# defines
|
||||
CONFIG(release, debug|release) {
|
||||
DEFINES += NDEBUG
|
||||
}
|
||||
|
||||
# libs and includepath
|
||||
CONFIG(debug, debug|release) {
|
||||
LIBS += -L../../ -lc++utilitiesd -lalpm -lKF5Archive
|
||||
LIBS += -lc++utilitiesd
|
||||
} else {
|
||||
LIBS += -L../../ -lc++utilities -lalpm -lKF5Archive
|
||||
LIBS += -lc++utilities
|
||||
}
|
||||
INCLUDEPATH += ../
|
||||
LIBS += -lalpm -lKF5Archive
|
||||
|
||||
# installs
|
||||
target.path = $$(INSTALL_ROOT)/bin
|
||||
|
|
|
@ -232,11 +232,9 @@
|
|||
<tr><th>Package count</th><td id="repo_pkgcount"></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>Source-only</th><td id="repo_source_only"></td></tr>
|
||||
<tr><th>Upgrade sources</th><td id="repo_upgrade_sources"></td></tr>
|
||||
<tr>
|
||||
<th>Upgrades</th>
|
||||
<td><span id="repo_checkforupdates"></span></td>
|
||||
</tr>
|
||||
<tr><th>Upgrades</th><td><span id="repo_checkforupdates"></span></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
|
|
@ -248,10 +248,10 @@
|
|||
repoMgr.removeEntries();
|
||||
pkgMgr.removeEntries();
|
||||
for(var i1 = 0; i1 < values.length; ++i1) {
|
||||
repoMgr.addEntry(values[i1]);
|
||||
var packages = values[i1].packages;
|
||||
var repoEntry = repoMgr.addEntry(values[i1]);
|
||||
var packages = repoEntry.info.packages;
|
||||
for(var i2 = 0; i2 < packages.length; ++i2) {
|
||||
pkgMgr.addEntry(values[i1].name, packages[i2]);
|
||||
pkgMgr.addEntry(repoEntry, packages[i2]);
|
||||
}
|
||||
}
|
||||
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
|
||||
this.useRequestedData = function() {
|
||||
this.invalidate();
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
var PackageEntry = {};
|
||||
PackageEntry.prototype = new repoindex.Entry();
|
||||
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);
|
||||
|
||||
// init row element
|
||||
|
@ -20,7 +21,8 @@
|
|||
};
|
||||
|
||||
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) {
|
||||
this.rowElement.addCell(repoindex.makeStr(values[i]));
|
||||
}
|
||||
|
@ -35,6 +37,7 @@
|
|||
if(info.ver) this.info.ver = info.ver;
|
||||
if(info.desc) this.info.desc = info.desc;
|
||||
if(info.bdate) this.info.bdate = info.bdate;
|
||||
if(info.flagdate) this.info.flagdate = info.flagdate;
|
||||
this.info.basic = true;
|
||||
if(!noUpdate) {
|
||||
this.updateTableRow();
|
||||
|
@ -80,22 +83,19 @@
|
|||
this.getContainerQuantity = repoindex.entryManagerGetRepoQuantity;
|
||||
|
||||
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 = {
|
||||
index: this.entries.length,
|
||||
arch: undefined,
|
||||
repo: repoName,
|
||||
repo: repoEntry.info.name,
|
||||
name: packageName,
|
||||
version: undefined,
|
||||
desc: undefined,
|
||||
builddate: undefined,
|
||||
flagdate: undefined,
|
||||
received: false
|
||||
};
|
||||
this.entries.push(new PackageEntry(packageInfo));
|
||||
var entry = new PackageEntry(repoEntry, packageInfo);
|
||||
this.entries.push(entry);
|
||||
return entry;
|
||||
};
|
||||
|
||||
// handle a page selection
|
||||
|
@ -106,15 +106,22 @@
|
|||
// if there is no page because there are no package entries, pageElement is null
|
||||
if(pageElement) {
|
||||
// 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) {
|
||||
var entry = mgr.filteredEntries[i];
|
||||
entry.add(mgr.entryContainer);
|
||||
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);
|
||||
if(packageSelection.length > 0) {
|
||||
if(entriesRequired) {
|
||||
var pkgEntries = repoindex.pageManager.packageManager.relevantEntries();
|
||||
var useBasicPackageInfo = function(values) {
|
||||
for(var i = 0; i < values.length; ++i) {
|
||||
|
@ -228,7 +235,9 @@
|
|||
};
|
||||
if(!i.full) {
|
||||
// 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)
|
||||
this.currentInfo = i;
|
||||
|
@ -254,7 +263,10 @@
|
|||
showEntry();
|
||||
} else {
|
||||
// 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 {
|
||||
// no -> show error
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
RepoEntry.prototype = new repoindex.Entry();
|
||||
RepoEntry.prototype.constructor = RepoEntry;
|
||||
RepoEntry = function(repoInfo, enabled) {
|
||||
if(enabled === undefined) {
|
||||
enabled = !repoInfo.requestRequired;
|
||||
}
|
||||
repoindex.Entry.prototype.constructor.call(this, repoInfo, enabled);
|
||||
|
||||
this.info.currentServer = 0;
|
||||
|
@ -40,12 +43,14 @@
|
|||
this.link.setAttribute("data-placement", "bottom");
|
||||
$(this.link).tooltip();
|
||||
|
||||
// create badge with package count
|
||||
var span = document.createElement("span");
|
||||
span.className = "badge";
|
||||
span.appendChild(document.createTextNode(repoInfo.packages.length));
|
||||
this.link.appendChild(document.createTextNode(" "));
|
||||
this.link.appendChild(span);
|
||||
if(!repoInfo.requestRequired) {
|
||||
// create badge with package count
|
||||
var span = document.createElement("span");
|
||||
span.className = "badge";
|
||||
span.appendChild(document.createTextNode(repoInfo.packages.length));
|
||||
this.link.appendChild(document.createTextNode(" "));
|
||||
this.link.appendChild(span);
|
||||
}
|
||||
|
||||
this.link.add = function() {
|
||||
repoindex.pageManager.repoManager.buttonContainer.appendChild(this);
|
||||
|
@ -103,12 +108,13 @@
|
|||
|
||||
// provide a function to add repo entries
|
||||
this.addEntry = function(repoInfo) {
|
||||
var entry = new RepoEntry(repoInfo, true);
|
||||
var entry = new RepoEntry(repoInfo);
|
||||
entry.statusChanged = this.applyRepoStatusChange;
|
||||
entry.pageManager = this;
|
||||
entry.repoEntryManager = this;
|
||||
entry.info.index = this.entries.length;
|
||||
this.entries.push(entry);
|
||||
return entry;
|
||||
};
|
||||
|
||||
this.baseRemoveEntries = this.removeEntries;
|
||||
|
@ -172,9 +178,10 @@
|
|||
var i = entry.info;
|
||||
repoindex.setText("repo_name", i.name);
|
||||
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_siglevel", repoindex.makeArray(i.sigLevel, ", "));
|
||||
repoindex.setText("repo_source_only", repoindex.makeBool(i.srcOnly));
|
||||
repoindex.setText("repo_upgrade_sources", repoindex.makeArray(i.upgradeSources, ", "));
|
||||
var invokeUpdateLookupParams = {repo: i.name, invoke: "updatelookup"};
|
||||
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 repoMgr = repoindex.pageManager.repoManager;
|
||||
for(var i1 = 0; i1 < updates.length; ++i1) {
|
||||
for(var i2 = 0; i2 < updates[i1].entries.length; ++i2) {
|
||||
var newEntry = pkgMgr.createCustomEntry(updates[i1].color);
|
||||
|
@ -247,6 +255,10 @@
|
|||
if(updates[i1].entries[i2].prevVersion) {
|
||||
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();
|
||||
} else {
|
||||
newEntry.applyBasicInfo(updates[i1].entries[i2]);
|
||||
|
@ -276,14 +288,6 @@
|
|||
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);
|
||||
};
|
||||
// basic repo info available?
|
||||
|
|
|
@ -18,13 +18,18 @@
|
|||
</p>
|
||||
|
||||
<script type="text/javascript">
|
||||
if(true) {
|
||||
var test = "asdf";
|
||||
var testobj = {};
|
||||
|
||||
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");
|
||||
function debug(message) {
|
||||
|
|
Loading…
Reference in New Issue