2015-08-10 22:46:01 +02:00
# include "manager.h"
2015-09-04 14:37:01 +02:00
# include "alpmdatabase.h"
2015-08-10 22:46:01 +02:00
# include "utilities.h"
# include "list.h"
# include "config.h"
2015-09-06 15:34:39 +02:00
# include "repoindex/network/userrepository.h"
2015-09-04 14:37:01 +02:00
2015-08-10 22:46:01 +02:00
# include <c++utilities/io/inifile.h>
# include <c++utilities/conversion/stringconversion.h>
2015-09-04 14:37:01 +02:00
# include <c++utilities/misc/memory.h>
2015-08-10 22:46:01 +02:00
# include <QList>
# include <QSysInfo>
2015-08-19 02:13:28 +02:00
# include <QMutexLocker>
2015-09-05 17:25:05 +02:00
2015-08-10 22:46:01 +02:00
# include <fstream>
# include <iostream>
# include <unordered_map>
# include <algorithm>
using namespace std ;
using namespace IoUtilities ;
using namespace ConversionUtilities ;
2015-09-05 17:25:05 +02:00
namespace RepoIndex {
2015-08-10 22:46:01 +02:00
2015-09-04 14:37:01 +02:00
/*!
* \ cond
*/
2015-08-10 22:46:01 +02:00
constexpr int defaultSigLevel = ALPM_SIG_PACKAGE | ALPM_SIG_PACKAGE_OPTIONAL |
ALPM_SIG_DATABASE | ALPM_SIG_DATABASE_OPTIONAL ;
2015-09-04 14:37:01 +02:00
inline ostream & operator < < ( ostream & stream , const QString & str )
{
stream < < str . toLocal8Bit ( ) . data ( ) ;
return stream ;
}
/*!
* \ endcond
*/
2015-08-10 22:46:01 +02:00
/*!
* \ brief The Manager class helps accessing ALPM .
*
* - It queries the ALPM for database and package information .
* - It serializes the information as JSON objects used by the network classes and the web interface .
*/
/*!
* \ brief Creates a new manager class ; initializes a new ALPM handle .
* \ param rootdir Specifies the root directory .
* \ param dbpath Specifies the database directory .
*/
2015-08-19 02:13:28 +02:00
Manager : : Manager ( const Config & config ) :
2015-08-10 22:46:01 +02:00
m_config ( config ) ,
m_sigLevel ( defaultSigLevel ) ,
2015-09-04 14:37:01 +02:00
m_localFileSigLevel ( ALPM_SIG_USE_DEFAULT )
2015-08-10 22:46:01 +02:00
{
alpm_errno_t err ;
if ( ! ( m_handle = alpm_initialize ( config . alpmRootDir ( ) . toLocal8Bit ( ) . data ( ) , config . alpmDbPath ( ) . toLocal8Bit ( ) . data ( ) , & err ) ) ) {
2015-09-04 14:37:01 +02:00
throw runtime_error ( string ( " Cannot initialize ALPM: " ) + alpm_strerror ( err ) ) ;
}
2015-09-05 17:25:05 +02:00
m_localDb = make_unique < AlpmDatabase > ( alpm_get_localdb ( m_handle ) , config . alpmDbPath ( ) ) ;
2015-09-04 14:37:01 +02:00
if ( config . isAurEnabled ( ) ) {
m_userRepo = make_unique < UserRepository > ( m_networkAccessManager ) ;
2015-08-10 22:46:01 +02:00
}
}
/*!
* \ brief Releases the associated ALPM handle .
*/
Manager : : ~ Manager ( )
{
alpm_release ( m_handle ) ;
}
/*!
2015-09-05 17:25:05 +02:00
* \ brief Returns the first package with the specified name from the specified database .
2015-08-10 22:46:01 +02:00
*/
2015-09-05 17:25:05 +02:00
AlpmPackage * Manager : : packageFromDatabase ( const QString & dbName , const QString & pkgName )
2015-08-10 22:46:01 +02:00
{
2015-09-05 17:25:05 +02:00
if ( auto * db = databaseByName ( dbName ) ) {
2015-09-04 14:37:01 +02:00
return static_cast < AlpmPackage * > ( db - > packageByName ( pkgName ) ) ;
} else {
return nullptr ;
}
}
/*!
2015-09-05 17:25:05 +02:00
* \ brief Returns the first package with the specified name from the specified database .
2015-09-04 14:37:01 +02:00
*/
2015-09-05 17:25:05 +02:00
const AlpmPackage * Manager : : packageFromDatabase ( const QString & dbName , const QString & pkgName ) const
2015-09-04 14:37:01 +02:00
{
2015-09-05 17:25:05 +02:00
if ( const auto * db = databaseByName ( dbName ) ) {
2015-09-04 14:37:01 +02:00
return static_cast < const AlpmPackage * > ( db - > packageByName ( pkgName ) ) ;
} else {
return nullptr ;
}
}
/*!
2015-09-05 17:25:05 +02:00
* \ brief Returns the first package with the specified \ a name from one of the sync databases .
2015-09-04 14:37:01 +02:00
*/
2015-09-05 17:25:05 +02:00
AlpmPackage * Manager : : packageFromSyncDatabases ( const QString & pkgName )
2015-09-04 14:37:01 +02:00
{
2015-09-05 17:25:05 +02:00
for ( const auto & dbEntry : syncDatabases ( ) ) {
2015-09-04 14:37:01 +02:00
if ( auto * pkg = dbEntry . second - > packageByName ( pkgName ) ) {
return static_cast < AlpmPackage * > ( pkg ) ;
}
}
return nullptr ;
}
/*!
2015-09-05 17:25:05 +02:00
* \ brief Returns the first package with the specified \ a name from one of the sync databases .
2015-09-04 14:37:01 +02:00
*/
2015-09-05 17:25:05 +02:00
const AlpmPackage * Manager : : packageFromSyncDatabases ( const QString & pkgName ) const
2015-09-04 14:37:01 +02:00
{
2015-09-05 17:25:05 +02:00
for ( const auto & dbEntry : syncDatabases ( ) ) {
2015-09-04 14:37:01 +02:00
if ( const auto * pkg = dbEntry . second - > packageByName ( pkgName ) ) {
return static_cast < const AlpmPackage * > ( pkg ) ;
2015-08-10 22:46:01 +02:00
}
}
2015-09-04 14:37:01 +02:00
return nullptr ;
2015-08-10 22:46:01 +02:00
}
/*!
* \ brief Creates a new package instance for the specified package file .
*
* Verifies the integrity of the file if the option is set .
*/
2015-09-04 14:37:01 +02:00
unique_ptr < AlpmOwnershipPackage > Manager : : packageFromFile ( const char * fileName , bool verifyIntegrity )
2015-08-10 22:46:01 +02:00
{
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 {
2015-09-04 14:37:01 +02:00
return make_unique < AlpmOwnershipPackage > ( pkg ) ;
2015-08-10 22:46:01 +02:00
}
}
2015-09-05 17:25:05 +02:00
/*!
* \ brief Returns the first package satisfiing the specified dependency from one of the available package sources ( excluding the local database ) .
*/
Package * Manager : : packageProviding ( const Dependency & dependency )
{
for ( auto & dbEntry : syncDatabases ( ) ) {
if ( auto * pkg = dbEntry . second - > packageProviding ( dependency ) ) {
return pkg ;
}
}
if ( config ( ) . isAurEnabled ( ) ) {
// TODO: check AUR
}
return nullptr ;
}
/*!
* \ brief Returns the first package satisfiing the specified dependency from one of the available package sources ( excluding the local database
* and sources requirering requests such as the AUR ) .
*/
const Package * Manager : : packageProviding ( const Dependency & dependency ) const
{
for ( const auto & dbEntry : syncDatabases ( ) ) {
if ( const auto * pkg = dbEntry . second - > packageProviding ( dependency ) ) {
return pkg ;
}
}
return nullptr ;
}
2015-08-10 22:46:01 +02:00
/*!
* \ brief Sets the install reason for the specified \ a package .
*/
2015-09-04 14:37:01 +02:00
void Manager : : setInstallReason ( AlpmPackage * package , alpm_pkgreason_t reason )
2015-08-10 22:46:01 +02:00
{
2015-09-04 14:37:01 +02:00
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 ) ) ) ;
2015-08-10 22:46:01 +02:00
}
}
/*!
* \ brief Returns the last value with the specified \ a key in the specified multimap .
*/
const string & lastValue ( const multimap < string , string > & mm , const string & key )
{
static const string defaultValue ;
const auto i = find_if ( mm . crbegin ( ) , mm . crend ( ) , [ & key ] ( const pair < string , string > & i ) {
return i . first = = key ;
} ) ;
return i ! = mm . crend ( ) ? i - > second : defaultValue ;
}
/*!
* \ brief Parses a " SigLevel " denotation from pacman config file .
*/
2015-08-19 02:13:28 +02:00
int Manager : : parseSigLevel ( const string & sigLevelStr )
2015-08-10 22:46:01 +02:00
{
int sigLevel = defaultSigLevel ;
// split sig level denotation into parts
const auto parts = splitString < list < string > > ( sigLevelStr , " " ) ;
for ( const auto & part : parts ) {
// determine whether part affect packages, databases or both
bool package = true , db = true ;
const char * partStart = part . data ( ) ;
if ( ! strncmp ( partStart , " Package " , 7 ) ) {
db = false ; // package only part
partStart + = 7 ;
} else if ( ! strncmp ( partStart , " Database " , 8 ) ) {
package = false ; // db only part
partStart + = 8 ;
}
// set sig level according part
if ( ! strcmp ( partStart , " Never " ) ) {
if ( package ) {
sigLevel & = ~ ALPM_SIG_PACKAGE ;
}
if ( db ) {
sigLevel & = ~ ALPM_SIG_DATABASE ;
}
} else if ( ! strcmp ( partStart , " Optional " ) ) {
if ( package ) {
sigLevel | = ALPM_SIG_PACKAGE | ALPM_SIG_PACKAGE_OPTIONAL ;
}
if ( db ) {
sigLevel | = ALPM_SIG_DATABASE | ALPM_SIG_DATABASE_OPTIONAL ;
}
} else if ( ! strcmp ( partStart , " Required " ) ) {
if ( package ) {
sigLevel | = ALPM_SIG_PACKAGE ;
sigLevel & = ~ ALPM_SIG_PACKAGE_OPTIONAL ;
}
if ( db ) {
sigLevel | = ALPM_SIG_DATABASE ;
sigLevel & = ~ ALPM_SIG_DATABASE_OPTIONAL ;
}
} else if ( ! strcmp ( partStart , " TrustedOnly " ) ) {
if ( package ) {
sigLevel & = ~ ( ALPM_SIG_PACKAGE_MARGINAL_OK | ALPM_SIG_PACKAGE_UNKNOWN_OK ) ;
}
if ( db ) {
sigLevel & = ~ ( ALPM_SIG_DATABASE_MARGINAL_OK | ALPM_SIG_DATABASE_UNKNOWN_OK ) ;
}
} else if ( ! strcmp ( partStart , " TrustAll " ) ) {
if ( package ) {
sigLevel | = ALPM_SIG_PACKAGE_MARGINAL_OK | ALPM_SIG_PACKAGE_UNKNOWN_OK ;
}
if ( db ) {
sigLevel | = ALPM_SIG_DATABASE_MARGINAL_OK | ALPM_SIG_DATABASE_UNKNOWN_OK ;
}
} else {
2015-09-05 17:25:05 +02:00
cerr < < shchar < < " Warning: Invalid value \" " < < part < < " \" for \" SigLevel \" in pacman config file will be ignored. " < < endl ;
2015-08-10 22:46:01 +02:00
}
}
return sigLevel ;
}
/*!
* \ brief Parses a " Usage " denotation from pacman config file .
*/
2015-08-19 02:13:28 +02:00
int Manager : : parseUsage ( const string & usageStr )
2015-08-10 22:46:01 +02:00
{
int usage = 0 ;
const auto parts = splitString < list < string > > ( usageStr , " " ) ;
for ( const auto & part : parts ) {
if ( part = = " Sync " ) {
usage | = ALPM_DB_USAGE_SYNC ;
} else if ( part = = " Search " ) {
usage | = ALPM_DB_USAGE_SEARCH ;
} else if ( part = = " Install " ) {
usage | = ALPM_DB_USAGE_INSTALL ;
} else if ( part = = " Upgrade " ) {
usage | = ALPM_DB_USAGE_UPGRADE ;
} else {
2015-09-05 17:25:05 +02:00
cerr < < shchar < < " Warning: Invalid value \" " < < part < < " \" for \" Usage \" in pacman config file will be ignored. " < < endl ;
2015-08-10 22:46:01 +02:00
}
}
return usage ? usage : ALPM_DB_USAGE_ALL ;
}
/*!
2015-08-19 02:13:28 +02:00
* \ brief Parses and applies the Pacman configuration . Registers the listed sync databases .
2015-08-10 22:46:01 +02:00
*/
2015-08-19 02:13:28 +02:00
void Manager : : applyPacmanConfig ( )
2015-08-10 22:46:01 +02:00
{
// open config file and parse as ini
try {
IniFile configIni ;
{
fstream configFile ;
configFile . exceptions ( ios_base : : failbit | ios_base : : badbit ) ;
configFile . open ( m_config . pacmanConfFile ( ) . toLocal8Bit ( ) . data ( ) , ios_base : : in ) ;
configIni . parse ( configFile ) ;
}
// determine current cpu archtitecture (required for server URLs)
static const string sysArch ( QSysInfo : : currentCpuArchitecture ( ) . toStdString ( ) ) ;
string arch = sysArch ;
const auto & config = configIni . data ( ) ;
// read relevant options
static const string sigLevelKey ( " SigLevel " ) ;
static const string usageKey ( " Usage " ) ;
int globalSigLevel ;
try {
const auto & options = config . at ( " options " ) ;
const auto & specifiedArch = lastValue ( options , " Architecture " ) ;
if ( ! specifiedArch . empty ( ) & & specifiedArch ! = " auto " ) {
arch = specifiedArch ;
}
const auto & specifiedDir = lastValue ( options , " CacheDir " ) ;
if ( ! specifiedDir . empty ( ) ) {
2015-08-19 02:13:28 +02:00
m_pacmanCacheDir = QString : : fromStdString ( specifiedDir ) ;
2015-08-10 22:46:01 +02:00
}
globalSigLevel = parseSigLevel ( lastValue ( options , sigLevelKey ) ) ;
} catch ( const out_of_range & ) {
// no options specified
globalSigLevel = defaultSigLevel ;
}
// register sync databases
unordered_map < string , IniFile > includedInis ;
for ( const auto & scope : config ) {
if ( scope . first ! = " options " ) {
// read and validate database name
QString dbName = QString : : fromLocal8Bit ( scope . first . c_str ( ) ) ;
2015-08-19 02:13:28 +02:00
if ( dbName . compare ( QLatin1String ( " local " ) , Qt : : CaseInsensitive ) = = 0 ) {
2015-09-05 17:25:05 +02:00
cerr < < shchar < < " Error: Unable to add database from pacman config: The database name mustn't be \" local \" because this name is reserved for the local database. " < < endl ;
2015-08-19 02:13:28 +02:00
} else if ( dbName . startsWith ( QLatin1String ( " aur " ) , Qt : : CaseInsensitive ) ) {
2015-09-05 17:25:05 +02:00
cerr < < shchar < < " Error: Unable to add database from pacman config: The database name mustn't start with \" aur \" because this name is reserved for the Arch Linux User Repository. " < < endl ;
2015-08-10 22:46:01 +02:00
} else if ( m_syncDbs . count ( dbName ) ) {
2015-09-05 17:25:05 +02:00
cerr < < shchar < < " Error: Unable to add database from pacman config: Database names must be unique. Ignoring second occurance of database \" " < < scope . first < < " \" . " < < endl ;
2015-08-10 22:46:01 +02:00
} else {
// read sig level and usage
const auto & sigLevelStr = lastValue ( scope . second , sigLevelKey ) ;
int sigLevel = sigLevelStr . empty ( ) ? globalSigLevel : parseSigLevel ( sigLevelStr ) ;
int usage = parseUsage ( lastValue ( scope . second , usageKey ) ) ;
// try to register database in the ALPM system
if ( alpm_db_t * db = alpm_register_syncdb ( m_handle , scope . first . c_str ( ) , static_cast < alpm_siglevel_t > ( sigLevel ) ) ) {
// set usage
if ( alpm_db_set_usage ( db , static_cast < alpm_db_usage_t > ( usage ) ) = = 0 ) {
2015-08-19 02:13:28 +02:00
if ( m_config . isVerbose ( ) | | m_config . runServer ( ) ) {
2015-09-05 17:25:05 +02:00
cerr < < shchar < < " Added database [ " < < scope . first < < " ] " < < endl ;
2015-08-19 02:13:28 +02:00
}
2015-08-10 22:46:01 +02:00
} else {
2015-08-19 02:13:28 +02:00
if ( m_config . isVerbose ( ) | | m_config . runServer ( ) ) {
2015-09-05 17:25:05 +02:00
cerr < < shchar < < " Warning: Added database [ " < < scope . first < < " ] but failed to set usage " < < endl ;
2015-08-19 02:13:28 +02:00
}
2015-08-10 22:46:01 +02:00
}
// add servers
for ( auto range = scope . second . equal_range ( " Server " ) ; range . first ! = range . second ; + + range . first ) {
string url = range . first - > second ;
findAndReplace < string > ( url , " $repo " , scope . first ) ;
findAndReplace < string > ( url , " $arch " , arch ) ;
alpm_db_add_server ( db , url . c_str ( ) ) ;
2015-08-19 02:13:28 +02:00
if ( m_config . isVerbose ( ) | | m_config . runServer ( ) ) {
2015-09-05 17:25:05 +02:00
cerr < < shchar < < " Added server: " < < url < < endl ;
2015-08-19 02:13:28 +02:00
}
2015-08-10 22:46:01 +02:00
}
// add included servers
for ( auto range = scope . second . equal_range ( " Include " ) ; range . first ! = range . second ; + + range . first ) {
const auto & path = range . first - > second ;
auto & includedIni = includedInis [ path ] ;
if ( includedIni . data ( ) . empty ( ) ) {
try {
fstream includedFile ;
includedFile . exceptions ( ios_base : : failbit | ios_base : : badbit ) ;
includedFile . open ( path , ios_base : : in ) ;
includedIni . parse ( includedFile ) ;
} catch ( const ios_base : : failure & ) {
2015-09-05 17:25:05 +02:00
cerr < < shchar < < " Error: An IO exception occured when parsing the included file \" " < < path < < " \" . " < < endl ;
2015-08-10 22:46:01 +02:00
}
}
try {
const auto & includedScope = includedIni . data ( ) . at ( string ( ) ) ;
for ( auto range = includedScope . equal_range ( " Server " ) ; range . first ! = range . second ; + + range . first ) {
string url = range . first - > second ;
findAndReplace < string > ( url , " $repo " , scope . first ) ;
findAndReplace < string > ( url , " $arch " , arch ) ;
alpm_db_add_server ( db , url . c_str ( ) ) ;
2015-08-19 02:13:28 +02:00
if ( m_config . isVerbose ( ) | | m_config . runServer ( ) ) {
2015-09-05 17:25:05 +02:00
cerr < < shchar < < " Added server: " < < url < < endl ;
2015-08-19 02:13:28 +02:00
}
2015-08-10 22:46:01 +02:00
}
} catch ( const out_of_range & ) {
2015-09-05 17:25:05 +02:00
cerr < < shchar < < " Warning: Included file \" " < < path < < " \" has no values. " < < endl ;
2015-08-10 22:46:01 +02:00
}
}
2015-09-05 17:25:05 +02:00
auto emplaced = m_syncDbs . emplace ( dbName , make_unique < AlpmDatabase > ( db , m_config . alpmDbPath ( ) ) ) ;
2015-08-10 22:46:01 +02:00
// add sync db to internal map
if ( usage & ALPM_DB_USAGE_UPGRADE ) {
// -> db is used to upgrade local database
2015-09-05 17:25:05 +02:00
localDatabase ( ) - > upgradeSources ( ) < < emplaced . first - > second . get ( ) ;
2015-08-10 22:46:01 +02:00
}
} else {
2015-09-05 17:25:05 +02:00
cerr < < shchar < < " Error: Unable to add sync database [ " < < scope . first < < " ] " < < endl ;
2015-08-10 22:46:01 +02:00
}
}
}
}
} catch ( const ios_base : : failure & ) {
2015-08-19 02:13:28 +02:00
throw ios_base : : failure ( " Error: An IO exception occured when parsing the config file. " ) ;
}
}
/*!
* \ brief Applies the repository index configuration .
*/
void Manager : : applyRepoIndexConfig ( )
{
2015-09-04 14:37:01 +02:00
// check whether an entry already exists, if not create a new one
2015-08-19 02:13:28 +02:00
for ( const RepoEntry & repoEntry : m_config . repoEntries ( ) ) {
2015-09-05 17:25:05 +02:00
AlpmDatabase * syncDb = nullptr ;
2015-08-19 02:13:28 +02:00
try {
2015-09-04 14:37:01 +02:00
syncDb = m_syncDbs . at ( repoEntry . name ( ) ) . get ( ) ;
2015-09-05 17:25:05 +02:00
cerr < < shchar < < " Applying config for database [ " < < syncDb - > name ( ) < < " ] " < < endl ;
2015-08-19 02:13:28 +02:00
if ( ! repoEntry . dataBasePath ( ) . isEmpty ( ) ) {
2015-09-05 17:25:05 +02:00
cerr < < shchar < < " Warning: Can't use data base path specified in repo index config because the repo \" "
2015-09-04 14:37:01 +02:00
< < repoEntry . name ( ) < < " \" has already been added from the Pacman config. " < < endl ;
2015-08-19 02:13:28 +02:00
}
if ( repoEntry . sigLevel ( ) ) {
2015-09-05 17:25:05 +02:00
cerr < < shchar < < " Warning: Can't use sig level specified in repo index config because the repo \" "
2015-09-04 14:37:01 +02:00
< < repoEntry . name ( ) < < " \" has already been added from the Pacman config. " < < endl ;
2015-08-19 02:13:28 +02:00
}
syncDb - > setPackagesDirectory ( repoEntry . packageDir ( ) ) ;
syncDb - > setSourcesDirectory ( repoEntry . sourceDir ( ) ) ;
} catch ( const out_of_range & ) {
if ( repoEntry . name ( ) . compare ( QLatin1String ( " local " ) , Qt : : CaseInsensitive ) = = 0 ) {
2015-09-05 17:25:05 +02:00
cerr < < shchar < < " Error: Unable to add database from repo index config: The database name mustn't be \" local \" because this name is reserved for the local database. " < < endl ;
2015-08-19 02:13:28 +02:00
} else if ( repoEntry . name ( ) . startsWith ( QLatin1String ( " aur " ) , Qt : : CaseInsensitive ) ) {
2015-09-05 17:25:05 +02:00
cerr < < shchar < < " 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 ;
2015-08-19 02:13:28 +02:00
} else {
2015-09-04 14:37:01 +02:00
// TODO: database path
2015-08-19 02:13:28 +02:00
auto * db = alpm_register_syncdb ( m_handle , repoEntry . name ( ) . toLocal8Bit ( ) . data ( ) , static_cast < alpm_siglevel_t > ( repoEntry . sigLevel ( ) ) ) ;
2015-09-05 17:25:05 +02:00
auto emplaced = m_syncDbs . emplace ( repoEntry . name ( ) , make_unique < AlpmDatabase > ( db , m_config . alpmDbPath ( ) ) ) ;
2015-08-19 02:13:28 +02:00
if ( emplaced . second ) {
2015-09-04 14:37:01 +02:00
syncDb = emplaced . first - > second . get ( ) ;
syncDb - > setSourcesDirectory ( repoEntry . sourceDir ( ) ) ;
syncDb - > setPackagesDirectory ( repoEntry . packageDir ( ) ) ;
2015-08-19 02:13:28 +02:00
if ( m_config . isVerbose ( ) | | m_config . runServer ( ) ) {
2015-09-05 17:25:05 +02:00
cerr < < shchar < < " Added database [ " < < repoEntry . name ( ) < < " ] " < < endl ;
2015-08-19 02:13:28 +02:00
}
}
}
}
if ( syncDb ) {
syncDb - > addServerUrls ( repoEntry . servers ( ) ) ;
}
2015-08-10 22:46:01 +02:00
}
2015-09-04 14:37:01 +02:00
// 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 {
2015-09-05 17:25:05 +02:00
cerr < < shchar < < " Warning: The specified upgrade source \" " < < upgradeSourceName < < " \" can not be found and will be ignored. " < < endl ;
2015-09-04 14:37:01 +02:00
}
}
} catch ( const out_of_range & ) {
// entry should have been added before
}
}
2015-08-10 22:46:01 +02:00
}
2015-09-05 17:25:05 +02:00
/*!
* \ brief Initiates all ALPM data bases .
* \ remarks Must be called , after all relevant sync data bases have been registered ( eg . via applyPacmanConfig ( ) ) .
*/
void Manager : : initAlpmDataBases ( )
{
QList < PackageLoader * > loaders ;
loaders . reserve ( m_syncDbs . size ( ) + 1 ) ;
loaders < < localDatabase ( ) - > init ( ) ;
for ( auto & syncDbEntry : m_syncDbs ) {
loaders < < syncDbEntry . second - > init ( ) ;
}
for ( auto * loader : loaders ) {
loader - > future ( ) . waitForFinished ( ) ;
delete loader ;
}
}
2015-08-10 22:46:01 +02:00
/*!
* \ brief Unregisters all registred sync databases .
*/
void Manager : : unregisterSyncDataBases ( )
{
if ( alpm_unregister_all_syncdbs ( m_handle ) ) {
throw runtime_error ( string ( " Cannot unregister sync databases: " ) + alpm_strerror ( alpm_errno ( m_handle ) ) ) ;
}
}
/*!
* \ brief Returns a list of all sync databases .
* \ remarks Sync databases must be registered with parsePacmanConfig ( ) before .
*/
2015-09-05 17:25:05 +02:00
const map < QString , unique_ptr < AlpmDatabase > > & Manager : : syncDatabases ( ) const
2015-08-10 22:46:01 +02:00
{
return m_syncDbs ; // m_syncDbs has been filled when the databases were registered
}
/*!
* \ brief Returns basic information about all repositories known to the manager .
*
* The results include the local database ( " local " ) and the names of
* the registered sync databases .
*/
const QJsonArray & Manager : : basicRepoInfo ( ) const
{
if ( m_basicRepoInfo . isEmpty ( ) ) {
2015-08-19 02:13:28 +02:00
QMutexLocker locker ( & m_basicRepoInfoMutex ) ;
if ( m_basicRepoInfo . isEmpty ( ) ) {
2015-09-04 14:37:01 +02:00
// add local data base
2015-09-05 17:25:05 +02:00
m_basicRepoInfo < < localDatabase ( ) - > basicInfo ( ) ;
2015-09-04 14:37:01 +02:00
// add sync data bases
2015-09-05 17:25:05 +02:00
for ( const auto & syncDb : syncDatabases ( ) ) {
2015-08-19 02:13:28 +02:00
// check if the "sync" database is actually used for syncing
2015-09-04 14:37:01 +02:00
auto usage = syncDb . second - > usage ( ) ;
2015-08-19 02:13:28 +02:00
if ( ( usage & ALPM_DB_USAGE_SYNC ) | | ( usage & ALPM_DB_USAGE_INSTALL ) | | ( usage & ALPM_DB_USAGE_UPGRADE ) ) {
2015-09-04 14:37:01 +02:00
m_basicRepoInfo < < syncDb . second - > basicInfo ( ) ;
2015-08-19 02:13:28 +02:00
} else {
2015-09-04 14:37:01 +02:00
m_basicRepoInfo < < syncDb . second - > basicInfo ( ) ;
2015-08-19 02:13:28 +02:00
}
2015-08-10 22:46:01 +02:00
}
2015-09-04 14:37:01 +02:00
// add AUR
if ( config ( ) . isAurEnabled ( ) ) {
m_basicRepoInfo < < userRepository ( ) - > basicInfo ( ) ;
}
2015-08-10 22:46:01 +02:00
}
}
return m_basicRepoInfo ;
}
/*!
* \ brief Returns package information for the specified selection of packages .
*/
2015-09-04 14:37:01 +02:00
const QJsonArray Manager : : packageInfo ( const QJsonObject & pkgSelection , bool full ) const
2015-08-10 22:46:01 +02:00
{
QJsonArray pkgInfos ;
2015-09-04 14:37:01 +02:00
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 ;
}
2015-08-10 22:46:01 +02:00
}
2015-09-04 14:37:01 +02:00
} else {
// specified repository can not be found
QJsonObject errorObj ;
errorObj . insert ( QStringLiteral ( " repo " ) , i . key ( ) ) ;
errorObj . insert ( QStringLiteral ( " error " ) , QStringLiteral ( " na " ) ) ;
pkgInfos < < errorObj ;
2015-08-10 22:46:01 +02:00
}
2015-09-04 14:37:01 +02:00
2015-08-10 22:46:01 +02:00
}
return pkgInfos ;
}
/*!
* \ brief Returns group information for the local database and all registred sync databases .
*/
const QJsonArray & Manager : : groupInfo ( ) const
{
if ( m_groupInfo . empty ( ) ) {
2015-08-19 02:13:28 +02:00
QMutexLocker locker ( & m_groupInfoMutex ) ;
if ( m_groupInfo . empty ( ) ) {
2015-09-05 17:25:05 +02:00
m_groupInfo < < localDatabase ( ) - > groupInfo ( ) ;
2015-08-19 02:13:28 +02:00
for ( const auto & db : m_syncDbs ) {
2015-09-04 14:37:01 +02:00
m_groupInfo < < db . second - > groupInfo ( ) ;
2015-08-19 02:13:28 +02:00
}
2015-08-10 22:46:01 +02:00
}
}
return m_groupInfo ;
}
/*!
* \ brief Returns the ALPM database with the specified name .
*/
2015-09-05 17:25:05 +02:00
const AlpmDatabase * Manager : : databaseByName ( const QString & dbName ) const
2015-08-10 22:46:01 +02:00
{
2015-09-04 14:37:01 +02:00
if ( dbName . compare ( QLatin1String ( " local " ) , Qt : : CaseInsensitive ) = = 0 ) {
2015-09-05 17:25:05 +02:00
return localDatabase ( ) ;
2015-08-10 22:46:01 +02:00
} else {
2015-09-04 14:37:01 +02:00
try {
return m_syncDbs . at ( dbName ) . get ( ) ;
} catch ( const out_of_range & ) {
return nullptr ;
}
2015-08-10 22:46:01 +02:00
}
}
/*!
* \ brief Returns the ALPM database with the specified name .
*/
2015-09-05 17:25:05 +02:00
AlpmDatabase * Manager : : databaseByName ( const QString & dbName )
2015-08-10 22:46:01 +02:00
{
2015-09-04 14:37:01 +02:00
if ( dbName . compare ( QLatin1String ( " local " ) , Qt : : CaseInsensitive ) = = 0 ) {
2015-09-05 17:25:05 +02:00
return localDatabase ( ) ;
2015-08-10 22:46:01 +02:00
} else {
2015-09-04 14:37:01 +02:00
try {
return m_syncDbs . at ( dbName ) . get ( ) ;
} catch ( const out_of_range & ) {
return nullptr ;
}
2015-08-10 22:46:01 +02:00
}
}
/*!
2015-09-04 14:37:01 +02:00
* \ brief Returns the package source with the specified name .
2015-08-10 22:46:01 +02:00
*/
2015-09-04 14:37:01 +02:00
const Repository * Manager : : repositoryByName ( const QString & name ) const
2015-08-10 22:46:01 +02:00
{
2015-09-04 14:37:01 +02:00
if ( name . compare ( QLatin1String ( " local " ) , Qt : : CaseInsensitive ) = = 0 ) {
2015-09-05 17:25:05 +02:00
return localDatabase ( ) ;
2015-09-04 14:37:01 +02:00
} 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 ;
}
}
2015-08-10 22:46:01 +02:00
}
/*!
2015-09-04 14:37:01 +02:00
* \ brief Returns the package source with the specified name .
2015-08-10 22:46:01 +02:00
*/
2015-09-04 14:37:01 +02:00
Repository * Manager : : repositoryByName ( const QString & name )
2015-08-10 22:46:01 +02:00
{
2015-09-04 14:37:01 +02:00
if ( name . compare ( QLatin1String ( " local " ) , Qt : : CaseInsensitive ) = = 0 ) {
2015-09-05 17:25:05 +02:00
return localDatabase ( ) ;
2015-09-04 14:37:01 +02:00
} else if ( config ( ) . isAurEnabled ( ) & & ( name . compare ( QLatin1String ( " aur " ) , Qt : : CaseInsensitive ) = = 0 ) ) {
return userRepository ( ) ;
} else {
2015-08-10 22:46:01 +02:00
try {
2015-09-04 14:37:01 +02:00
return m_syncDbs . at ( name ) . get ( ) ;
} catch ( const out_of_range & ) {
return nullptr ;
2015-08-10 22:46:01 +02:00
}
}
2015-09-04 14:37:01 +02:00
}
2015-09-05 17:25:05 +02:00
/*!
* \ brief Returns a list of all repositories excluding the local database .
*/
QList < const Repository * > Manager : : repositories ( ) const
{
QList < const Repository * > repos ;
repos . reserve ( m_syncDbs . size ( ) + 1 ) ;
for ( const auto & dbEntry : m_syncDbs ) {
repos < < dbEntry . second . get ( ) ;
}
repos < < m_userRepo . get ( ) ;
return repos ;
}
/*!
* \ brief Returns a list of all repositories excluding the local database .
*/
QList < Repository * > Manager : : repositories ( )
{
QList < Repository * > repos ;
repos . reserve ( m_syncDbs . size ( ) + 1 ) ;
for ( auto & dbEntry : m_syncDbs ) {
repos < < dbEntry . second . get ( ) ;
}
repos < < m_userRepo . get ( ) ;
return repos ;
}
2015-09-04 14:37:01 +02:00
/*!
* \ brief Checks the specified database for upgrades .
*
* Appropriate upgrade sources will be determined automatically ; does not check the AUR .
*/
2015-09-05 17:25:05 +02:00
const UpgradeLookupResults Manager : : checkForUpgrades ( AlpmDatabase * db ) const
2015-09-04 14:37:01 +02:00
{
UpgradeLookupResults results ;
db - > checkForUpgrades ( results ) ;
2015-08-10 22:46:01 +02:00
return results ;
}
}