#include "./alpmdatabase.h" #include "./upgradelookup.h" #include "./alpmpackage.h" #include "./utilities.h" #include #include #include #include #include #include #include using namespace std; namespace RepoIndex { using namespace Utilities; /*! * \class AlpmDatabase * \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. */ class LoadPackage { public: LoadPackage(AlpmDatabase *database, PackageOrigin origin) : m_db(database), m_origin(origin) {} void operator()(const QPair > &description) { m_db->addPackageFromDescription(description.first, description.second, m_origin); } private: AlpmDatabase *const m_db; const PackageOrigin m_origin; }; void AlpmDatabase::loadDescriptions(QList > > &descriptions) { QFileInfo pathInfo(databasePath()); if(pathInfo.isDir()) { static const QStringList relevantFiles = QStringList() << QStringLiteral("desc") << QStringLiteral("files"); QDir dbDir(databasePath()); QStringList pkgDirNames = dbDir.entryList(QDir::Dirs | QDir::Readable | QDir::Executable | QDir::NoDotAndDotDot); descriptions.reserve(pkgDirNames.size()); for(QString &pkgDirName : pkgDirNames) { if(dbDir.cd(pkgDirName)) { Utilities::stripVersion(pkgDirName); const QStringList descFileNames = dbDir.entryList(relevantFiles, QDir::Files | QDir::Readable | QDir::NoDotAndDotDot); QList descData; descData.reserve(descFileNames.size()); for(const QString &descFileName : descFileNames) { QFile descFile(dbDir.absoluteFilePath(descFileName)); if(descFile.open(QFile::ReadOnly)) { descData << descFile.readAll(); } else { // TODO: error handling (can't open pkg file) } } if(!descData.isEmpty()) { descriptions << qMakePair(pkgDirName, descData); } dbDir.cdUp(); } else { // TODO: error handling (can't enter pkg dir) } } } else if(pathInfo.isFile()) { KTar tar(databasePath()); const KArchiveDirectory *dbDir; if(tar.open(QIODevice::ReadOnly) && (dbDir = tar.directory())) { QStringList pkgDirNames = dbDir->entries(); descriptions.reserve(pkgDirNames.size()); for(QString &pkgDirName : pkgDirNames) { if(const auto *pkgEntry = dbDir->entry(pkgDirName)) { if(pkgEntry->isDirectory()) { Utilities::stripVersion(pkgDirName); const auto *pkgDir = static_cast(pkgEntry); const QStringList descFileNames = pkgDir->entries(); QList descData; descData.reserve(descFileNames.size()); for(const QString &descFileName : descFileNames) { if(const auto *descEntry = pkgDir->entry(descFileName)) { if(descEntry->isFile()) { descData << static_cast(descEntry)->data(); } else { // there shouldn't be any subdirs } } } if(!descData.isEmpty()) { descriptions << qMakePair(pkgDirName, descData); } } else { // there shouldn't be any files } } } } else { // TODO: error handling (can't open sync db file) } } else { // TODO: error handling } } AlpmPackageLoader::AlpmPackageLoader(AlpmDatabase *repository, PackageOrigin origin) { repository->loadDescriptions(m_descriptions); m_future = QtConcurrent::map(m_descriptions, LoadPackage(repository, origin)); } /*! * \brief Creates a new instance wrapping the specified database struct. */ AlpmDatabase::AlpmDatabase(const QString &name, const QString &dbPath, RepositoryUsage usage, SignatureLevel sigLevel, uint32 index, QObject *parent) : Repository(name, index, parent), m_dbPath(dbPath) { m_usage = usage; m_sigLevel = sigLevel; } AlpmPackageLoader *AlpmDatabase::init() { // set description, determine origin PackageOrigin origin; if(m_name.compare(QLatin1String("local"), Qt::CaseInsensitive) == 0) { m_description = QStringLiteral("The local database"); origin = PackageOrigin::LocalDb; } else { if((m_usage & RepositoryUsage::Sync) || (m_usage & RepositoryUsage::Install) || (m_usage & RepositoryUsage::Upgrade)) { m_description = QStringLiteral("Sync database »%1«").arg(m_name); } else { m_description = QStringLiteral("Database »%1«").arg(m_name); } origin = PackageOrigin::SyncDb; } // initialization of packages is done concurrently via AlpmPackageLoader: ~ 4 sec return new AlpmPackageLoader(this, origin); // without concurrency: ~ 12 sec //QList > > descriptions; //loadDescriptions(descriptions); //for(const auto &description : descriptions) { // addPackageFromDescription(description.first, description.second, origin); //} //return nullptr; } RepositoryType AlpmDatabase::type() const { return RepositoryType::AlpmDatabase; } PackageDetailAvailability AlpmDatabase::requestsRequired(PackageDetail packageDetail) const { switch(packageDetail) { case PackageDetail::Basics: case PackageDetail::Dependencies: case PackageDetail::PackageInfo: case PackageDetail::AllAvailable: return PackageDetailAvailability::Immediately; default: return PackageDetailAvailability::Never; } } std::unique_ptr AlpmDatabase::emptyPackage() { return make_unique(this); } } // namespace Alpm