added desc parser, minor adjustments

This commit is contained in:
Martchus 2016-02-12 01:05:08 +01:00
parent 82d4ae2eb7
commit 69b0d7e258
13 changed files with 434 additions and 47 deletions

View File

@ -125,5 +125,10 @@ bool AlpmDatabase::addServerUrls(const QStringList &urls)
return res;
}
std::unique_ptr<Package> AlpmDatabase::emptyPackage()
{
return make_unique<AlpmPackage>(this);
}
} // namespace Alpm

View File

@ -49,6 +49,9 @@ public:
signals:
void initiated();
protected:
std::unique_ptr<Package> emptyPackage();
private:
alpm_db_t *m_ptr;
QString m_dbFile;

View File

@ -37,6 +37,14 @@ using namespace Utilities;
* \brief The AlpmPackage class wraps an ALPM package struct and holds additional meta information.
*/
/*!
* \brief Constructs an empty ALPM package.
*/
AlpmPackage::AlpmPackage(AlpmDatabase *repository) :
Package(QString(), repository),
m_ptr(nullptr)
{}
/*!
* \brief Constructs a new instance for the specified ALPM \a package.
*/
@ -64,7 +72,7 @@ AlpmPackage::AlpmPackage(alpm_pkg_t *package, AlpmDatabase *alpmDatabase) :
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_packager = 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));

View File

@ -10,6 +10,7 @@ class AlpmDatabase;
class AlpmPackage : public Package
{
public:
AlpmPackage(AlpmDatabase *repository);
AlpmPackage(alpm_pkg_t *package, AlpmDatabase *alpmDatabase);
AlpmPackage(alpm_pkg_t *package);

View File

@ -53,6 +53,7 @@ ConfigArgs::ConfigArgs(ArgumentParser &parser) :
defaultIconThemeArg("default-icon-theme", string(), "specifies the name of the default icon theme (should be included in --icon-packages)"),
extraPackagesArg("extra-packages", string(), "specifies extra packages to be included"),
cacheDirArg("cache-dir", string(), "specifies the cache directory (default is /var/cache/repoindex)"),
storageDirArg("storage-dir", string(), "specifies the storage directory (default is /var/lib/repoindex)"),
shSyntaxArg("sh-syntax", string(), "prints the output using shell syntax: export REPOINDEX_RESULTS=('res1' 'res2' 'res3') or export REPOINDEX_ERROR='some error message'"),
repoArg("repo", string(), "specifies the repository")
{
@ -130,6 +131,9 @@ ConfigArgs::ConfigArgs(ArgumentParser &parser) :
cacheDirArg.setCombinable(true);
cacheDirArg.setRequiredValueCount(1);
cacheDirArg.setValueNames(pathValueName);
storageDirArg.setCombinable(true);
storageDirArg.setRequiredValueCount(1);
storageDirArg.setValueNames(pathValueName);
parser.setMainArguments({&buildOrderArg, &upgradeLookupArg, &serverArg, &mingwBundleArg, &repoindexConfArg, &repoindexConfArg, &cacheDirArg, &helpArg});
}
@ -146,6 +150,7 @@ Config::Config() :
m_alpmDbPath(QStringLiteral("/var/lib/pacman")),
m_pacmanConfFile(QStringLiteral("/etc/pacman.conf")),
m_cacheDir(QStringLiteral("/var/cache/repoindex")),
m_storageDir(QStringLiteral("/var/lib/repoindex")),
m_websocketServerListeningAddr(QHostAddress::LocalHost),
m_websocketServerListeningPort(1234),
m_serverInsecure(false),
@ -234,6 +239,7 @@ void Config::loadFromConfigFile(const QString &configFilePath)
m_alpmDbPath = alpmObj.value(QStringLiteral("dbPath")).toString(m_alpmDbPath);
m_pacmanConfFile = alpmObj.value(QStringLiteral("pacmanConfigFile")).toString(m_pacmanConfFile);
m_cacheDir = mainObj.value(QStringLiteral("cacheDir")).toString(m_cacheDir);
m_storageDir = mainObj.value(QStringLiteral("storageDir")).toString(m_storageDir);
auto aurObj = mainObj.value(QStringLiteral("aur")).toObject();
m_aurEnabled = aurObj.value(QStringLiteral("enabled")).toBool(m_aurEnabled);
auto serverObj = mainObj.value(QStringLiteral("server")).toObject();

View File

@ -44,6 +44,7 @@ public:
ApplicationUtilities::Argument defaultIconThemeArg;
ApplicationUtilities::Argument extraPackagesArg;
ApplicationUtilities::Argument cacheDirArg;
ApplicationUtilities::Argument storageDirArg;
ApplicationUtilities::Argument shSyntaxArg;
ApplicationUtilities::Argument repoArg;
};
@ -143,6 +144,7 @@ private:
QString m_alpmDbPath;
QString m_pacmanConfFile;
QString m_cacheDir;
QString m_storageDir;
QHostAddress m_websocketServerListeningAddr;
quint16 m_websocketServerListeningPort;

View File

@ -328,7 +328,7 @@ QJsonObject Package::detailedInfo() const
put(info, QStringLiteral("optf"), optionalFor());
put(info, QStringLiteral("conf"), conflicts());
put(info, QStringLiteral("repl"), replaces());
put(info, QStringLiteral("pack"), packer());
put(info, QStringLiteral("pack"), packager());
put(info, QStringLiteral("expl"), QJsonValue(installReason() == ALPM_PKG_REASON_EXPLICIT));
put(info, QStringLiteral("scri"), QJsonValue(hasInstallScript()));
put(info, QStringLiteral("sig"), Utilities::validationMethodsStrings(validationMethods()));
@ -348,7 +348,7 @@ QJsonObject Package::simpleInfo() const
put(info, QStringLiteral("bdate"), buildDate());
put(info, QStringLiteral("url"), upstreamUrl());
put(info, QStringLiteral("lic"), licenses());
put(info, QStringLiteral("packer"), packer());
put(info, QStringLiteral("packer"), packager());
return info;
}
@ -363,7 +363,7 @@ void Package::writeToCacheStream(QDataStream &out)
<< m_groups << m_dependencies << m_optionalDependencies << m_conflicts << m_provides
<< m_replaces << m_requiredByComputed << m_requiredBy << m_optionalFor << m_hasInstallScript;
// build related meta data
out << m_hasBuildRelatedMetaData << m_fileName << m_files << m_buildDate << m_packer
out << m_hasBuildRelatedMetaData << m_fileName << m_files << m_buildDate << m_packager
<< m_md5 << m_sha256 << m_buildArchitecture << m_packageSize << m_makeDependencies;
// installation related meta data
out << m_hasInstallRelatedMetaData << m_installDate << m_installedSize << m_backupFiles
@ -396,7 +396,7 @@ void Package::restoreFromCacheStream(QDataStream &in)
>> m_groups >> m_dependencies >> m_optionalDependencies >> m_conflicts >> m_provides
>> m_replaces >> m_requiredByComputed >> m_requiredBy >> m_optionalFor >> m_hasInstallScript;
// build related meta data
in >> m_hasBuildRelatedMetaData >> m_fileName >> m_files >> m_buildDate >> m_packer
in >> m_hasBuildRelatedMetaData >> m_fileName >> m_files >> m_buildDate >> m_packager
>> m_md5 >> m_sha256 >> m_buildArchitecture >> m_packageSize >> m_makeDependencies;
// installation related meta data
in >> m_hasInstallRelatedMetaData >> m_installDate >> m_installedSize >> m_backupFiles;
@ -423,32 +423,101 @@ void Package::restoreFromCacheStream(QDataStream &in)
}
/*!
* \brief Puts the specified src/pkg info key value pairs; clears current dependencies, provides, ... before inserting new values.
* \remarks This method should only be called by the associated repository because it must handle a possible name change.
* \brief Puts the specified .SRCINFO/.PKGINFO key value pairs; clears current values before inserting new values.
* \remarks
* - This method should only be called by the associated repository because the associated repository might
* has to handle a possible name change.
* - Actual parsing of .SRCINFO/.PKGINFO is done in Repository::addPackagesFromSrcInfo() because one info file
* applies to multiple packages in case of split packages.
*/
void Package::putInfo(const QList<QPair<QString, QString> > &baseInfo, const QList<QPair<QString, QString> > &pkgInfo, bool includesSourceRelatedMetaData)
void Package::putInfo(const QList<QPair<QString, QString> > &baseInfo, const QList<QPair<QString, QString> > &pkgInfo, bool includesSourceRelatedMetaData, bool includesBuildRelatedMetaData)
{
// clear current values
m_baseName.clear();
m_description.clear();
m_upstreamUrl.clear();
m_packager.clear();
m_licenses.clear();
m_dependencies.clear();
m_makeDependencies.clear();
m_checkDependencies.clear();
m_optionalDependencies.clear();
m_conflicts.clear();
m_provides.clear();
m_replaces.clear();
// read specified key value pairs
if(includesBuildRelatedMetaData) {
m_buildArchitecture.clear();
}
if(includesSourceRelatedMetaData) {
m_architectures.clear();
m_makeDependencies.clear();
m_checkDependencies.clear();
m_installedSize = 0;
m_buildDate = DateTime();
m_packager.clear();
}
// prevent overwriting these crucial fields with empty values
QString name;
PackageVersion version;
QStringList archs;
// read specified key value pairs
const auto infos = {baseInfo, pkgInfo};
for(const auto &info : infos) {
for(const auto &pair : info) {
const auto &field = pair.first;
if(field == QLatin1String("pkgbase")) {
m_baseName.clear();
} else if(field == QLatin1String("pkgname")) {
name.clear();
} else if(field == QLatin1String("epoch")) {
version.epoch.clear();
} else if(field == QLatin1String("pkgver")) {
version.version.clear();
} else if(field == QLatin1String("pkgrel")) {
version.release.clear();
} else if(field == QLatin1String("pkgdesc")) {
m_description.clear();
} else if(field == QLatin1String("url")) {
m_upstreamUrl.clear();
} else if(field == QLatin1String("arch")) {
if(includesSourceRelatedMetaData) {
m_architectures.clear();
}
if(includesBuildRelatedMetaData) {
m_buildArchitecture.clear();
}
} else if(field == QLatin1String("license")) {
m_licenses.clear();
} else if(field == QLatin1String("depends")) {
m_dependencies.clear();
} else if(field == QLatin1String("makedepends")) {
m_makeDependencies.clear();
} else if(field == QLatin1String("checkdepends")) {
m_checkDependencies.clear();
} else if(field == QLatin1String("optdepends")) {
m_optionalDependencies.clear();
} else if(field == QLatin1String("conflicts")) {
m_conflicts.clear();
} else if(field == QLatin1String("provides")) {
m_provides.clear();
} else if(field == QLatin1String("replaces")) {
m_replaces.clear();
} else if(field == QLatin1String("source")) {
// currently not used
} else if(field == QLatin1String("size")) {
m_installedSize = 0;
} else if(field == QLatin1String("builddate")) {
m_buildDate = DateTime();
} else if(field == QLatin1String("packager")) {
m_packager.clear();
}
}
for(const auto &pair : info) {
const auto &field = pair.first;
const auto &value = pair.second;
if(field == QLatin1String("pkgbase")) {
m_baseName = value;
} else if(field == QLatin1String("pkgname")) {
m_name = value;
name = value;
} else if(field == QLatin1String("epoch")) {
version.epoch = value;
} else if(field == QLatin1String("pkgver")) {
@ -460,7 +529,12 @@ void Package::putInfo(const QList<QPair<QString, QString> > &baseInfo, const QLi
} else if(field == QLatin1String("url")) {
m_upstreamUrl = value;
} else if(field == QLatin1String("arch")) {
archs << value;
if(includesSourceRelatedMetaData) {
m_architectures << value;
}
if(includesBuildRelatedMetaData) {
m_buildArchitecture = value;
}
} else if(field == QLatin1String("license")) {
m_licenses << value;
} else if(field == QLatin1String("depends")) {
@ -479,26 +553,196 @@ void Package::putInfo(const QList<QPair<QString, QString> > &baseInfo, const QLi
m_replaces << Dependency(value);
} else if(field == QLatin1String("source")) {
// currently not used
} else if(field == QLatin1String("size")) {
m_installedSize = value.toUInt();
} else if(field == QLatin1String("builddate")) {
m_buildDate = DateTime::fromTimeStampGmt(value.toUInt());
} else if(field == QLatin1String("packager")) {
m_packager = value;
}
}
}
// ensure crucial information is still present (use old values rather than no values)
if(!name.isEmpty()) {
m_name = name;
}
if(!version.version.isEmpty()) {
m_version = version.toString();
}
if(!archs.isEmpty()) {
m_architectures.swap(archs);
// use the name as base name if the base name hasn't been specified explicitely
if(includesSourceRelatedMetaData && m_baseName.isEmpty()) {
m_baseName = m_name;
}
// consider general information as complete
m_hasGeneralInfo = m_hasAllGeneralInfo = true;
m_hasSourceRelatedMetaData = includesSourceRelatedMetaData;
m_hasBuildRelatedMetaData = includesBuildRelatedMetaData;
}
inline void put(QString &lhs, const QStringList &rhs)
{
if(!rhs.isEmpty()) {
lhs = rhs.back();
}
}
inline void put(QList<Dependency> &lhs, const QStringList &rhs)
{
lhs.reserve(rhs.size());
for(const QString &dep : rhs) {
lhs << Dependency(dep);
}
}
inline void put(QJsonArray &lhs, const QStringList &rhs)
{
for(const QString &value : rhs) {
lhs << value;
}
}
/*!
* \brief Puts the specified desc/depends/files key value(s) pairs; clears current values before inserting new values.
* \remarks
* - This method should only be called by the associated repository because the associated repository might
* has to handle a possible name change.
* - Actual parsing of desc/depends/files is done in Repository::addPackagesFromSrcInfo() because one info file
* applies to multiple packages in case of split packages.
*/
void Package::putDescription(QString name, const QList<QPair<QString, QStringList> > &description)
{
// clear current meta data
m_hasInstallRelatedMetaData = false;
m_fileName.clear();
m_description.clear();
m_upstreamUrl.clear();
m_buildArchitecture.clear();
m_licenses.clear();
m_dependencies.clear();
m_makeDependencies.clear();
m_checkDependencies.clear();
m_optionalDependencies.clear();
m_conflicts.clear();
m_provides.clear();
m_replaces.clear();
m_buildDate = m_installDate = DateTime();
m_packageSize = m_installedSize = 0;
m_files = QJsonArray();
m_md5.clear();
m_sha256.clear();
m_installReason = ALPM_PKG_REASON_EXPLICIT;
m_validationMethods = ALPM_PKG_VALIDATION_UNKNOWN;
// prevent overwriting these crucial fields with empty values
PackageVersion version;
for(const auto &pair : description) {
const auto &field = pair.first;
const auto &values = pair.second;
if(field == QLatin1String("FILENAME")) {
put(m_fileName, values);
} else if(field == QLatin1String("NAME")) {
put(name, values);
} else if(field == QLatin1String("VERSION")) {
if(!values.isEmpty()) {
version = PackageVersion(values.back());
}
} else if(field == QLatin1String("DESC")) {
put(m_description, values);
} else if(field == QLatin1String("URL")) {
put(m_upstreamUrl, values);
} else if(field == QLatin1String("ARCH")) {
put(m_buildArchitecture, values);
} else if(field == QLatin1String("LICENSE")) {
m_licenses = values;
} else if(field == QLatin1String("DEPENDS")) {
put(m_dependencies, values);
} else if(field == QLatin1String("MAKEDEPENDS")) {
put(m_makeDependencies, values);
} else if(field == QLatin1String("CHECKDEPENDS")) {
put(m_checkDependencies, values);
} else if(field == QLatin1String("OPTDEPENDS")) {
put(m_optionalDependencies, values);
} else if(field == QLatin1String("CONFLICTS")) {
put(m_conflicts, values);
} else if(field == QLatin1String("PROVIDES")) {
put(m_provides, values);
} else if(field == QLatin1String("REPLACES")) {
put(m_replaces, values);
} else if(field == QLatin1String("BUILDDATE")) {
if(!values.isEmpty()) {
m_buildDate = DateTime::fromTimeStampGmt(values.back().toUInt());
}
} else if(field == QLatin1String("INSTALLDATE")) {
if(!values.isEmpty()) {
m_installDate = DateTime::fromTimeStampGmt(values.back().toUInt());
m_hasInstallRelatedMetaData = true;
}
} else if(field == QLatin1String("ISIZE") || field == QLatin1String("SIZE")) {
if(!values.empty()) {
m_installedSize = values.back().toUInt();
m_hasInstallRelatedMetaData = true;
}
} else if(field == QLatin1String("CSIZE")) {
if(!values.empty()) {
m_packageSize = values.back().toUInt();
}
} else if(field == QLatin1String("PACKAGER")) {
put(m_packager, values);
} else if(field == QLatin1String("MD5SUM")) {
put(m_md5, values);
} else if(field == QLatin1String("SHA256SUM")) {
put(m_sha256, values);
} else if(field == QLatin1String("FILES")) {
put(m_files, values);
} else if(field == QLatin1String("REASON")) {
if(!values.isEmpty()) {
m_installReason = values.back().toUInt() == 1 ? ALPM_PKG_REASON_DEPEND : ALPM_PKG_REASON_EXPLICIT;
}
} else if(field == QLatin1String("VALIDATION")) {
if(values.isEmpty()) {
m_validationMethods = ALPM_PKG_VALIDATION_NONE;
} else {
for(const QString &value : values) {
if(value == QLatin1String("md5")) {
m_validationMethods = static_cast<alpm_pkgvalidation_t>(m_validationMethods | ALPM_PKG_VALIDATION_MD5SUM);
} else if(value == QLatin1String("sha256")) {
m_validationMethods = static_cast<alpm_pkgvalidation_t>(m_validationMethods | ALPM_PKG_VALIDATION_SHA256SUM);
} else if(value == QLatin1String("pgp")) {
m_validationMethods = static_cast<alpm_pkgvalidation_t>(m_validationMethods | ALPM_PKG_VALIDATION_SIGNATURE);
} else {
// TODO: error handling (imporant?)
}
}
}
m_hasInstallRelatedMetaData = true;
}
}
// ensure crucial information is still present (use old values rather than no values)
if(!name.isEmpty()) {
m_name = name;
}
if(!version.version.isEmpty()) {
m_version = version.toString();
}
// description provides source related meta data, too (except pkgbase, TODO: special flag required?)
m_hasBuildRelatedMetaData = m_hasSourceRelatedMetaData = true;
}
/*!
* \brief Adds a source file with the specified \a path and \a data.
*/
void Package::putSourceFile(const QString &path, const QByteArray &data)
{
m_sourceFiles.insert(make_pair(path, data));
}
/*!
* \class PackageVersion
* \brief The PackageVersion class helps parsing package versions.
*/

View File

@ -144,7 +144,7 @@ public:
const QString &fileName() const;
const QJsonArray &files() const;
ChronoUtilities::DateTime buildDate() const;
const QString &packer() const;
const QString &packager() const;
const QString &md5() const;
const QString &sha256() const;
const QString &buildArchitecture() const;
@ -191,8 +191,9 @@ public:
void restoreFromCacheStream(QDataStream &in);
void reinitEntries();
// parsing src/pkg info
void putInfo(const QList<QPair<QString, QString> > &baseInfo, const QList<QPair<QString, QString> > &pkgInfo, bool includesSourceRelatedMetaData = false);
// parsing .SRCINFO/.PKGINFO/desc/depends/files info
void putInfo(const QList<QPair<QString, QString> > &baseInfo, const QList<QPair<QString, QString> > &pkgInfo, bool includesSourceRelatedMetaData = false, bool includesBuildRelatedMetaData = false);
void putDescription(QString name, const QList<QPair<QString, QStringList> > &description);
void putSourceFile(const QString &path, const QByteArray &data);
protected:
@ -228,7 +229,7 @@ protected:
QString m_fileName;
QJsonArray m_files;
ChronoUtilities::DateTime m_buildDate;
QString m_packer;
QString m_packager;
QString m_md5;
QString m_sha256;
QString m_buildArchitecture;
@ -457,11 +458,11 @@ inline ChronoUtilities::DateTime Package::buildDate() const
}
/*!
* \brief Returns the packer of the package file.
* \brief Returns the packager of the package file.
*/
inline const QString &Package::packer() const
inline const QString &Package::packager() const
{
return m_packer;
return m_packager;
}
/*!
@ -660,7 +661,9 @@ inline const QString &Package::tarUrl() const
}
/*!
* \brief Returns the source files of the package.
* \brief Returns the available source files.
*
* Contains usually the PKGBUILD/.SRCINFO file and patches.
*/
inline const std::map<QString, QByteArray> &Package::sourceFiles() const
{

View File

@ -551,25 +551,37 @@ void Repository::cleanOutdatedPackages()
}
/*!
* \brief Adds packages parsed from the specified \a srcInfo.
* \returns Returns the added packages.
* \brief Adds packages parsed from the specified .SRCINFO/.PKGINFO file.
* \remarks Updates existing packages.
* \returns Returns the added/updated packages. In the case of a split package more then
* one package is returned.
*/
QList<Package *> Repository::addPackagesFromSrcInfo(const QByteArray &srcInfo)
{
// define states
enum {
FieldName,
EquationSign,
Pad,
FieldValue,
Comment
FieldName, // reading field name (initial state)
EquationSign, // expecting equation sign
Pad, // expecting padding
FieldValue, // reading field value
Comment // reading comment
} state = FieldName;
// define variables to store parsing results
QString currentFieldName;
currentFieldName.reserve(16);
QString currentFieldValue;
currentFieldValue.reserve(32);
QString packageBase;
packageBase.reserve(32);
QList<QPair<QString, QString> > baseInfo;
baseInfo.reserve(16);
QList<QPair<QString, QString> > packageInfo;
packageInfo.reserve(16);
QList<Package *> packages;
Package *currentPackage = nullptr;
// state machine: consumes each char of .SRCINFO
for(const char c : srcInfo) {
switch(state) {
case FieldName:
@ -628,23 +640,28 @@ QList<Package *> Repository::addPackagesFromSrcInfo(const QByteArray &srcInfo)
} else if(currentFieldName == QLatin1String("pkgname")) {
// next package
if(packageBase.isEmpty()) {
// TODO: handle error - pkgbase must be present
} else {
if(currentPackage) {
currentPackage->putInfo(baseInfo, packageInfo, true);
packages << currentPackage;
}
auto &pkg = m_packages[currentFieldValue];
if(!pkg) {
pkg = emptyPackage();
}
currentPackage = pkg.get();
packageInfo.clear();
// no pkgbase specified -> use the first pkgname as pkgbase
packageBase = currentFieldName;
}
// put current info to current package
if(currentPackage) {
currentPackage->putInfo(baseInfo, packageInfo, true);
packages << currentPackage;
}
// find next package
auto &pkg = m_packages[currentFieldValue];
if(!pkg) {
pkg = emptyPackage();
}
currentPackage = pkg.get();
packageInfo.clear();
}
// add field to ...
if(currentPackage) {
// ... concrete package info if there's already a concrete package
packageInfo << QPair<QString, QString>(currentFieldName, currentFieldValue);
} else {
// ... base info if still parsing general info
baseInfo << QPair<QString, QString>(currentFieldName, currentFieldValue);
}
currentFieldName.clear();
@ -672,4 +689,97 @@ QList<Package *> Repository::addPackagesFromSrcInfo(const QByteArray &srcInfo)
return packages;
}
/*!
* \brief Adds packages parsed from the specified desc/depends/files file.
* \remarks Updates the package if it already exists.
* \returns Returns the added/updated package.
*/
Package *Repository::addPackageFromDescription(QString name, const QList<QByteArray> &descriptions)
{
// define variables to store parsing results
QString currentFieldName;
currentFieldName.reserve(16);
QStringList currentFieldValues;
QList<QPair<QString, QStringList> > fields;
for(const QByteArray &description : descriptions) {
// define states
enum {
FieldName, // reading field name
NewLine, // expecting new line (after field name)
Next, // start reading next field value / next field name (initial state)
FieldValue, // reading field value
} state = Next;
// state machine: consumes each char of desc
for(const char c : description) {
switch(state) {
case FieldName:
switch(c) {
case '%':
state = NewLine;
break;
default:
currentFieldName.append(c);
}
break;
case NewLine:
switch(c) {
case '\n': case '\r':
state = Next;
break;
default:
; // ignore unexpected characters
}
break;
case Next:
switch(c) {
case '\n': case '\r': case '\t': case ' ':
break;
case '%':
state = FieldName;
// next field -> put current field
if(!currentFieldName.isEmpty()) {
if(!currentFieldValues.isEmpty() && currentFieldName == QLatin1String("NAME")) {
name = currentFieldValues.back();
}
fields << QPair<QString, QStringList>(currentFieldName, currentFieldValues);
currentFieldName.clear();
currentFieldValues.clear();
}
break;
default:
state = FieldValue;
currentFieldValues << QString(QChar(c));
}
break;
case FieldValue:
switch(c) {
case '\n': case '\r':
state = Next;
break;
default:
currentFieldValues.back().append(c);
}
}
}
// put last field
if(!currentFieldName.isEmpty()) {
if(!currentFieldValues.isEmpty() && currentFieldName == QLatin1String("NAME")) {
name = currentFieldValues.back();
}
fields << QPair<QString, QStringList>(currentFieldName, currentFieldValues);
}
}
// find/create package for description
auto &pkg = m_packages[name];
if(!pkg) {
pkg = emptyPackage();
}
pkg->putDescription(name, fields);
return pkg.get();
}
} // namespace PackageManagement

View File

@ -242,6 +242,7 @@ public:
// parsing src/pkg info
QList<Package *> addPackagesFromSrcInfo(const QByteArray &srcInfo);
Package *addPackageFromDescription(QString name, const QList<QByteArray> &descriptions);
// thread synchronization
QReadWriteLock *lock() const;

View File

@ -1,6 +1,7 @@
#include "userrepository.h"
#include "../alpm/aurpackage.h"
#include "../alpm/config.h"
#include <c++utilities/misc/memory.h>
@ -20,6 +21,8 @@
#include <QTemporaryFile>
#include <QStringBuilder>
#include <iostream>
using namespace std;
using namespace ChronoUtilities;
@ -118,10 +121,9 @@ void AurFullPackageReply::processData(QNetworkReply *reply)
const auto data = static_cast<const KArchiveFile *>(entry)->data();
for(Package *package : packages) {
package->putSourceFile(entry->name(), data);
// TODO: add source files
}
} else {
// don't think it is required to read sub directories recursively
// don't think it is required to read sub directories recursively (TODO?)
}
}
}
@ -135,7 +137,7 @@ void AurFullPackageReply::processData(QNetworkReply *reply)
m_error = QStringLiteral("Unable to request tarball from AUR: ") + reply->errorString();
}
if(!m_error.isEmpty()) {
qDebug() << m_error;
cerr << shchar << m_error.toLocal8Bit().data();
}
}

View File

@ -9,7 +9,8 @@
"enabled": true
},
"cacheDir": "/var/cache/repoindex"
"cacheDir": "/var/cache/repoindex",
"storageDir": "/var/lib/repoindex",
"server": {
"websocketListeningAddr": "any-IPv4",

View File

@ -54,6 +54,7 @@ span.glyphicon {
border: none!important;
font-size: 90%;
padding: 5px;
vertical-align: top!important;
}
/*