diff --git a/alpm/config.cpp b/alpm/config.cpp index 7ce70b4..5ad5b18 100644 --- a/alpm/config.cpp +++ b/alpm/config.cpp @@ -13,6 +13,7 @@ using namespace std; using namespace ApplicationUtilities; using namespace ConversionUtilities; +using namespace ChronoUtilities; namespace RepoIndex { @@ -314,6 +315,9 @@ void Config::loadFromArgs(const ConfigArgs &args) if(args.cacheDirArg.isPresent()) { m_cacheDir = QString::fromLocal8Bit(args.cacheDirArg.values().front().data()); } + if(args.storageDirArg.isPresent()) { + m_storageDir = QString::fromLocal8Bit(args.storageDirArg.values().front().data()); + } } RepoEntry::RepoEntry() : @@ -346,6 +350,7 @@ void RepoEntry::load(const QJsonValue &jsonValue) if(sigLevelValue.isString()) { m_sigLevel = Manager::parseSigLevel(sigLevelValue.toString().toLocal8Bit().data()); } + m_maxDatabaseAge = TimeSpan::fromSeconds(obj.value(QStringLiteral("maxAge")).toDouble()); } } // namespace Alpm diff --git a/alpm/config.h b/alpm/config.h index 5dcea44..21708de 100644 --- a/alpm/config.h +++ b/alpm/config.h @@ -2,6 +2,7 @@ #define ALPM_CONFIG_H #include +#include #include #include @@ -65,6 +66,7 @@ public: const QStringList &servers() const; const QStringList &upgradeSources() const; SignatureLevel sigLevel() const; + ChronoUtilities::TimeSpan maxDatabaseAge() const; void load(const QJsonValue &jsonValue); private: @@ -75,6 +77,7 @@ private: QStringList m_servers; QStringList m_upgradeSources; SignatureLevel m_sigLevel; + ChronoUtilities::TimeSpan m_maxDatabaseAge; }; inline const QString &RepoEntry::name() const @@ -112,6 +115,11 @@ inline SignatureLevel RepoEntry::sigLevel() const return m_sigLevel; } +inline ChronoUtilities::TimeSpan RepoEntry::maxDatabaseAge() const +{ + return m_maxDatabaseAge; +} + class Config { public: @@ -121,6 +129,7 @@ public: const QString &alpmDbPath() const; const QString &pacmanConfFile() const; const QString &cacheDir() const; + const QString &storageDir() const; const QHostAddress &websocketServerListeningAddr() const; quint16 websocketServerListeningPort() const; const QString &serverCertFile() const; @@ -177,6 +186,11 @@ inline const QString &Config::cacheDir() const return m_cacheDir; } +inline const QString &Config::storageDir() const +{ + return m_storageDir; +} + inline const QHostAddress &Config::websocketServerListeningAddr() const { return m_websocketServerListeningAddr; diff --git a/alpm/manager.cpp b/alpm/manager.cpp index bf4c2b0..7268fc3 100644 --- a/alpm/manager.cpp +++ b/alpm/manager.cpp @@ -1,4 +1,4 @@ -#include "./manager.h" +#include "./manager.h" #include "./utilities.h" #include "./config.h" #include "./alpmdatabase.h" @@ -316,23 +316,11 @@ void Manager::addDataBasesFromPacmanConfig() SignatureLevel sigLevel = sigLevelStr.empty() ? globalSigLevel : parseSigLevel(sigLevelStr); RepositoryUsage usage = parseUsage(lastValue(scope.second, usageKey)); - // determine path of db file - // -> currently just use the file from pacman dir, TODO: download syncdata base - QFileInfo dbPathRegular(m_config.alpmDbPath() % QStringLiteral("/sync/") % dbName % QStringLiteral(".db")); - QFileInfo dbPathWithFiles(m_config.alpmDbPath() % QStringLiteral("/sync/") % dbName % QStringLiteral(".files")); - QString dbPath; - if(dbPathWithFiles.isFile() && (!dbPathRegular.isFile() || dbPathWithFiles.lastModified() > dbPathRegular.lastModified())) { - dbPath = dbPathWithFiles.absoluteFilePath(); - } else if(dbPathRegular.isFile()) { - dbPath = dbPathRegular.absoluteFilePath(); - } else { - cerr << shchar << "Error: Unable to locate database file for [" << scope.first << "]" << endl; - } - // add sync db to internal map (use as index size + 1 because the local database has index 0) - m_syncDbs.emplace_back(make_unique(dbName, dbPath, usage, sigLevel, m_syncDbs.size() + 1)); + m_syncDbs.emplace_back(make_unique(dbName, findDatabasePath(dbName, false, false), usage, sigLevel, m_syncDbs.size() + 1)); AlpmDatabase *emplacedDb = m_syncDbs.back().get(); m_syncDbMap.emplace(dbName, emplacedDb); + cerr << shchar << "Added [" << dbName << "]" << endl; if(usage & RepositoryUsage::Upgrade) { // -> db is used to upgrade local database localDataBase()->upgradeSources() << emplacedDb; @@ -345,7 +333,7 @@ void Manager::addDataBasesFromPacmanConfig() findAndReplace(url, "$arch", arch); emplacedDb->serverUrls() << Utilities::qstr(url); if(m_config.isVerbose() || m_config.runServer()) { - cerr << shchar << "Added server: " << url << endl; + cerr << shchar << " Added server: " << url << endl; } } @@ -372,7 +360,7 @@ void Manager::addDataBasesFromPacmanConfig() findAndReplace(url, "$arch", arch); emplacedDb->serverUrls() << Utilities::qstr(url); if(m_config.isVerbose() || m_config.runServer()) { - cerr << shchar << "Added server: " << url << endl; + cerr << shchar << " Added server: " << url << endl; } } } @@ -418,15 +406,8 @@ void Manager::addDatabasesFromRepoIndexConfig() // -> currently just use the file from pacman dir, TODO: download syncdata base QString dbPath; if(repoEntry.databasePath().isEmpty()) { - QFileInfo dbPathRegular(m_config.alpmDbPath() % QStringLiteral("/sync/") % repoEntry.name() % QStringLiteral(".db")); - QFileInfo dbPathWithFiles(m_config.alpmDbPath() % QStringLiteral("/sync/") % repoEntry.name() % QStringLiteral(".files")); - if(dbPathWithFiles.isFile() && (!dbPathRegular.isFile() || dbPathWithFiles.lastModified() > dbPathRegular.lastModified())) { - dbPath = dbPathWithFiles.absolutePath(); - } else if(dbPathRegular.isFile()) { - dbPath = dbPathRegular.absolutePath(); - } else { - cerr << shchar << "Error: Unable to locate database file for [" << repoEntry.name().toLocal8Bit().data() << "]" << endl; - } + // no path specified -> use defaults + dbPath = findDatabasePath(repoEntry.name(), !repoEntry.maxDatabaseAge().isNull(), true); } else { dbPath = repoEntry.databasePath(); } @@ -438,6 +419,9 @@ void Manager::addDatabasesFromRepoIndexConfig() syncDb->setSourcesDirectory(repoEntry.sourceDir()); syncDb->setPackagesDirectory(repoEntry.packageDir()); + if(!repoEntry.maxDatabaseAge().isNull()) { + syncDb->setMaxPackageAge(repoEntry.maxDatabaseAge()); + } if(m_config.isVerbose() || m_config.runServer()) { cerr << shchar << "Added database [" << repoEntry.name() << ']' << endl; } @@ -719,7 +703,7 @@ const QJsonArray &Manager::groupInfo() const } /*! - * \brief Add local database. + * \brief Add the local database. */ void Manager::addLocalDatabase() { @@ -805,15 +789,43 @@ Repository *Manager::repositoryByName(const QString &name) } /*! - * \brief Checks the specified database for upgrades. - * - * Appropriate upgrade sources will be determined automatically; does not check the AUR. + * \brief Finds the default path for the database with the specified \a name. + * \remarks + * - If the database couldn't be located and \a printError is true + * an error message is printed to cerr. + * - If \a updatesRequired is false using the pacman sync dbs is not considered. + * - This is used if the database path hasn't been specified explicitely. */ -const UpgradeLookupResults Manager::checkForUpgrades(AlpmDatabase *db) const +QString Manager::findDatabasePath(const QString &name, bool updatesRequired, bool printError) const { - UpgradeLookupResults results; - db->checkForUpgrades(results); - return results; + QFileInfo dbPathRegular(m_config.storageDir() % QStringLiteral("/sync/") % name % QStringLiteral(".db")); + QFileInfo dbPathWithFiles(m_config.storageDir() % QStringLiteral("/sync/") % name % QStringLiteral(".files")); + if(dbPathWithFiles.isFile() && (!dbPathRegular.isFile() || dbPathWithFiles.lastModified() > dbPathRegular.lastModified())) { + return dbPathWithFiles.absolutePath(); + } else if(dbPathRegular.isFile()) { + return dbPathRegular.absolutePath(); + } else if(!updatesRequired) { + // can't find database file in storage directory and database should not be updated automatically + // -> it might be possible to use the databases from pacman + QFileInfo pacmanDbPathRegular(m_config.alpmDbPath() % QStringLiteral("/sync/") % name % QStringLiteral(".db")); + QFileInfo pacmanDbPathWithFiles(m_config.alpmDbPath() % QStringLiteral("/sync/") % name % QStringLiteral(".files")); + if(pacmanDbPathWithFiles.isFile() && (!pacmanDbPathRegular.isFile() || pacmanDbPathWithFiles.lastModified() > pacmanDbPathRegular.lastModified())) { + return pacmanDbPathWithFiles.absolutePath(); + } else if(pacmanDbPathRegular.isFile()) { + return pacmanDbPathRegular.absolutePath(); + } + } + if(printError) { + cerr << shchar << "Error: Unable to locate database file for [" << name.toLocal8Bit().data() << "]" << endl; + } +} + +/*! + * \brief Returns a database path for the database with the specified \a name. + */ +QString Manager::proposedDatabasePath(const QString &name, bool files) const +{ + return m_config.storageDir() % QStringLiteral("/sync/") % name % (files ? QStringLiteral(".files") : QStringLiteral(".db")); } } diff --git a/alpm/manager.h b/alpm/manager.h index 40bc376..8ffc90d 100644 --- a/alpm/manager.h +++ b/alpm/manager.h @@ -81,7 +81,8 @@ public: Repository *repositoryByName(const QString &name); const UserRepository *userRepository() const; UserRepository *userRepository(); - const UpgradeLookupResults checkForUpgrades(AlpmDatabase *db) const; + QString findDatabasePath(const QString &name, bool updatesRequired, bool printError) const; + QString proposedDatabasePath(const QString &name, bool files) const; // JSON serialization, handling JSON requests const QJsonObject basicRepoInfo(const Repository *packageSource) const; diff --git a/alpm/package.cpp b/alpm/package.cpp index 7969a23..930d39e 100644 --- a/alpm/package.cpp +++ b/alpm/package.cpp @@ -316,10 +316,12 @@ QJsonObject Package::basicInfo(bool includeRepoAndName) const QJsonObject Package::detailedInfo() const { QJsonObject info; + put(info, QStringLiteral("installAvail"), hasInstallRelatedMetaData()); put(info, QStringLiteral("buildAvail"), hasBuildRelatedMetaData()); put(info, QStringLiteral("srcAvail"), hasSourceRelatedMetaData()); put(info, QStringLiteral("idate"), installDate()); put(info, QStringLiteral("isize"), QJsonValue(static_cast(installedSize()))); + put(info, QStringLiteral("csize"), QJsonValue(static_cast(packageSize()))); put(info, QStringLiteral("url"), upstreamUrl()); put(info, QStringLiteral("lic"), licenses()); put(info, QStringLiteral("grp"), groups()); diff --git a/alpm/repository.cpp b/alpm/repository.cpp index 9165e49..1d8c808 100644 --- a/alpm/repository.cpp +++ b/alpm/repository.cpp @@ -560,6 +560,28 @@ void Repository::cleanOutdatedPackages() } } +/*! + * \brief Returns whether the repository has outdated packages. + * \sa cleanOutdatedPackages() + */ +bool Repository::hasOutdatedPackages() +{ + if(maxPackageAge().isInfinity()) { + return false; + } + auto now = DateTime::now(); + for(auto i = m_packages.begin(); i != m_packages.end(); ) { + const Package &pkg = *i->second; + if((now - pkg.timeStamp()) > maxPackageAge()) { + return true; + } + } + return false; +} + +/*! + * \brief Parses the specified .PKGINFO file. + */ void Repository::parsePkgInfo(const QByteArray &pkgInfo, QString &name, QList > packageInfo) { // define states @@ -912,19 +934,13 @@ Package *Repository::addPackageFromDescription(QString name, const QListputDescription(name, fields, origin); { QWriteLocker locker(&m_lock); - auto &pkgPtrRef = m_packages[name]; - if(!pkgPtrRef) { - pkgPtrRef = emptyPackage(); - } - pkgRawPtr = pkgPtrRef.get(); + m_packages[name] = move(pkg); } - - // add groups - pkgRawPtr->putDescription(name, fields, origin); - return pkgRawPtr; } diff --git a/alpm/repository.h b/alpm/repository.h index 1e0ff40..83c4417 100644 --- a/alpm/repository.h +++ b/alpm/repository.h @@ -263,6 +263,7 @@ public: ChronoUtilities::TimeSpan maxPackageAge() const; void setMaxPackageAge(ChronoUtilities::TimeSpan maxPackageAge); void cleanOutdatedPackages(); + bool hasOutdatedPackages(); void wipePackages(); // parsing src/pkg info @@ -447,11 +448,18 @@ inline void Repository::setSigLevel(SignatureLevel sigLevel) m_sigLevel = sigLevel; } +/*! + * \brief Returns the upgrade sources for the repository. + */ inline const QList &Repository::upgradeSources() const { return m_upgradeSources; } +/*! + * \brief Returns the upgrade sources for the repository. + * \remarks This non-const version is used by the manager to add upgrade sources. + */ inline QList &Repository::upgradeSources() { return m_upgradeSources; @@ -508,21 +516,35 @@ inline bool Repository::isCachingUseful() const } } +/*! + * \brief Returns the max package age. + * \sa setMaxPackageAge() + */ inline ChronoUtilities::TimeSpan Repository::maxPackageAge() const { return m_maxPackageAge; } +/*! + * \brief Sets the max package age which is used by the cleanOutdatedPackages() and + * the hasOutdatedPackages() method. + */ inline void Repository::setMaxPackageAge(ChronoUtilities::TimeSpan maxPackageAge) { m_maxPackageAge = maxPackageAge; } +/*! + * \brief Wipes all packages. + */ inline void Repository::wipePackages() { m_packages.clear(); } +/*! + * \brief Returns the read-write lock used for thread-synchronization. + */ inline QReadWriteLock *Repository::lock() const { return const_cast(&m_lock); diff --git a/main.cpp b/main.cpp index 2e9e02e..83e42de 100644 --- a/main.cpp +++ b/main.cpp @@ -56,8 +56,9 @@ int main(int argc, char *argv[]) manager.addDataBasesFromPacmanConfig(); manager.addDatabasesFromRepoIndexConfig(); manager.initAlpmDataBases(configArgs.serverArg.isPresent()); - cerr << shchar << "Restoring cache ..." << endl; + cerr << shchar << "Restoring cache ... "; manager.restoreCache(); + cerr << shchar << "DONE" << endl; if(configArgs.serverArg.isPresent()) { // setup the server diff --git a/network/server.cpp b/network/server.cpp index 960d98b..e823cb5 100644 --- a/network/server.cpp +++ b/network/server.cpp @@ -16,7 +16,7 @@ namespace RepoIndex { Server::Server(RepoIndex::Manager &alpmManager, const RepoIndex::Config &config, QObject *parent) : QObject(parent), - m_server(new QWebSocketServer(QStringLiteral("Repository index server"), + m_server(new QWebSocketServer(QStringLiteral("Repository index Web Socket server"), config.serverInsecure() ? QWebSocketServer::NonSecureMode : QWebSocketServer::SecureMode, this)), m_alpmManager(alpmManager) diff --git a/web/js/packagemanagement.js b/web/js/packagemanagement.js index 08499db..c144839 100644 --- a/web/js/packagemanagement.js +++ b/web/js/packagemanagement.js @@ -170,6 +170,9 @@ repoindex.addPackageNames(tb, "Conflicts with", repoindex.pkgNamesFromDeps(details.conf)); repoindex.addPackageNames(tb, "Replaces", repoindex.pkgNamesFromDeps(details.repl)); if(details.buildAvail) { + if(entry.info.repo !== "local") { // local repo does no provide package size + repoindex.addField(tb, "Package size", repoindex.makeDataSize(details.csize)); + } repoindex.addField(tb, "Install size", repoindex.makeDataSize(details.isize)); repoindex.addField(tb, "Packager", details.pack); repoindex.addField(tb, "Build date", repoindex.makeStr(basics.bdate));