2016-02-15 18:26:05 +01:00
# include " ./manager.h "
2015-09-07 19:36:45 +02:00
# include "./utilities.h"
# include "./config.h"
2015-09-21 22:16:19 +02:00
# include "./alpmdatabase.h"
2015-08-10 22:46:01 +02:00
2015-09-07 19:36:45 +02:00
# include "../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-11 21:59:47 +02:00
# include <QStringBuilder>
# include <QFile>
# include <QDataStream>
2016-01-18 20:34:29 +01:00
# include <QTimer>
2016-02-14 23:48:43 +01:00
# include <QFileInfo>
# include <QtConcurrent>
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>
2016-02-25 22:53:33 +01:00
# include <functional>
2015-08-10 22:46:01 +02:00
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
*/
2016-02-14 23:48:43 +01:00
constexpr auto defaultSigLevel = SignatureLevel : : Package | SignatureLevel : : PackageOptional
| SignatureLevel : : Database | SignatureLevel : : DatabaseOptional ;
2015-08-10 22:46:01 +02:00
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 .
*/
2016-02-25 22:53:33 +01:00
Manager : : Manager ( const Config & config , QObject * parent ) :
QObject ( parent ) ,
2015-08-10 22:46:01 +02:00
m_config ( config ) ,
2015-09-11 21:59:47 +02:00
m_writeCacheBeforeGone ( true ) ,
2015-08-10 22:46:01 +02:00
m_sigLevel ( defaultSigLevel ) ,
2016-02-14 23:48:43 +01:00
m_localFileSigLevel ( SignatureLevel : : UseDefault )
2015-08-10 22:46:01 +02:00
{
2016-02-25 22:53:33 +01:00
if ( config . isLocalDatabaseEnabled ( ) ) {
addLocalDatabase ( ) ;
}
2015-09-04 14:37:01 +02:00
if ( config . isAurEnabled ( ) ) {
2016-02-20 03:00:34 +01:00
m_userRepo = make_unique < UserRepository > ( ) ;
2015-08-10 22:46:01 +02:00
}
}
/*!
* \ brief Releases the associated ALPM handle .
*/
Manager : : ~ Manager ( )
{
2015-09-11 21:59:47 +02:00
if ( m_writeCacheBeforeGone ) {
writeCache ( ) ;
}
2016-02-14 23:48:43 +01:00
removeAllDatabases ( ) ;
2015-08-10 22:46:01 +02:00
}
/*!
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-12-08 18:59:17 +01:00
for ( const auto & dbEntry : m_syncDbs ) {
if ( auto * pkg = dbEntry - > packageByName ( pkgName ) ) {
2015-09-04 14:37:01 +02:00
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-12-08 18:59:17 +01:00
for ( const auto & dbEntry : m_syncDbs ) {
if ( const auto * pkg = dbEntry - > packageByName ( pkgName ) ) {
2015-09-04 14:37:01 +02:00
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
}
2015-09-05 17:25:05 +02:00
/*!
2015-12-08 00:24:45 +01:00
* \ 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 ) .
2015-09-05 17:25:05 +02:00
*/
Package * Manager : : packageProviding ( const Dependency & dependency )
{
2015-12-08 18:59:17 +01:00
for ( auto & dbEntry : m_syncDbs ) {
QReadLocker locker ( dbEntry - > lock ( ) ) ;
if ( auto * pkg = dbEntry - > packageProviding ( dependency ) ) {
2015-09-05 17:25:05 +02:00
return pkg ;
}
}
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
{
2015-12-08 18:59:17 +01:00
for ( const auto & dbEntry : m_syncDbs ) {
QReadLocker locker ( dbEntry - > lock ( ) ) ;
if ( const auto * pkg = dbEntry - > packageProviding ( dependency ) ) {
2015-09-05 17:25:05 +02:00
return pkg ;
}
}
return nullptr ;
}
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 .
*/
2016-02-14 23:48:43 +01:00
SignatureLevel Manager : : parseSigLevel ( const string & sigLevelStr )
2015-08-10 22:46:01 +02:00
{
2016-02-14 23:48:43 +01:00
SignatureLevel sigLevel = defaultSigLevel ;
2015-08-10 22:46:01 +02:00
// 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 ) {
2016-02-14 23:48:43 +01:00
sigLevel & = ~ SignatureLevel : : Package ;
2015-08-10 22:46:01 +02:00
}
if ( db ) {
2016-02-14 23:48:43 +01:00
sigLevel & = ~ SignatureLevel : : Database ;
2015-08-10 22:46:01 +02:00
}
} else if ( ! strcmp ( partStart , " Optional " ) ) {
if ( package ) {
2016-02-14 23:48:43 +01:00
sigLevel | = SignatureLevel : : Package | SignatureLevel : : PackageOptional ;
2015-08-10 22:46:01 +02:00
}
if ( db ) {
2016-02-14 23:48:43 +01:00
sigLevel | = SignatureLevel : : Database | SignatureLevel : : DatabaseOptional ;
2015-08-10 22:46:01 +02:00
}
} else if ( ! strcmp ( partStart , " Required " ) ) {
if ( package ) {
2016-02-14 23:48:43 +01:00
sigLevel | = SignatureLevel : : Package ;
sigLevel & = ~ SignatureLevel : : PackageOptional ;
2015-08-10 22:46:01 +02:00
}
if ( db ) {
2016-02-14 23:48:43 +01:00
sigLevel | = SignatureLevel : : Database ;
sigLevel & = ~ SignatureLevel : : DatabaseOptional ;
2015-08-10 22:46:01 +02:00
}
} else if ( ! strcmp ( partStart , " TrustedOnly " ) ) {
if ( package ) {
2016-02-14 23:48:43 +01:00
sigLevel & = ~ ( SignatureLevel : : PackageMarginalOk | SignatureLevel : : PackageUnknownOk ) ;
2015-08-10 22:46:01 +02:00
}
if ( db ) {
2016-02-14 23:48:43 +01:00
sigLevel & = ~ ( SignatureLevel : : DatabaseMarginalOk | SignatureLevel : : DatabaseUnknownOk ) ;
2015-08-10 22:46:01 +02:00
}
} else if ( ! strcmp ( partStart , " TrustAll " ) ) {
if ( package ) {
2016-02-14 23:48:43 +01:00
sigLevel | = SignatureLevel : : PackageMarginalOk | SignatureLevel : : PackageUnknownOk ;
2015-08-10 22:46:01 +02:00
}
if ( db ) {
2016-02-14 23:48:43 +01:00
sigLevel | = SignatureLevel : : DatabaseMarginalOk | SignatureLevel : : DatabaseUnknownOk ;
2015-08-10 22:46:01 +02:00
}
} 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 .
*/
2016-02-14 23:48:43 +01:00
RepositoryUsage Manager : : parseUsage ( const string & usageStr )
2015-08-10 22:46:01 +02:00
{
2016-02-14 23:48:43 +01:00
RepositoryUsage usage = RepositoryUsage : : None ;
const auto parts = splitString < list < string > > ( usageStr , " " , EmptyPartsTreat : : Omit ) ;
2015-08-10 22:46:01 +02:00
for ( const auto & part : parts ) {
if ( part = = " Sync " ) {
2016-02-14 23:48:43 +01:00
usage | = RepositoryUsage : : Sync ;
2015-08-10 22:46:01 +02:00
} else if ( part = = " Search " ) {
2016-02-14 23:48:43 +01:00
usage | = RepositoryUsage : : Search ;
2015-08-10 22:46:01 +02:00
} else if ( part = = " Install " ) {
2016-02-14 23:48:43 +01:00
usage | = RepositoryUsage : : Install ;
2015-08-10 22:46:01 +02:00
} else if ( part = = " Upgrade " ) {
2016-02-14 23:48:43 +01:00
usage | = RepositoryUsage : : Upgrade ;
2015-08-10 22:46:01 +02:00
} 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
}
}
2016-02-14 23:48:43 +01:00
return usage ! = RepositoryUsage : : None ? usage : RepositoryUsage : : All ;
2015-08-10 22:46:01 +02:00
}
/*!
2016-02-14 23:48:43 +01:00
* \ brief Adds sync databases listed in the Pacman config file . Also reads the cache dir .
2015-08-10 22:46:01 +02:00
*/
2016-02-14 23:48:43 +01:00
void Manager : : addDataBasesFromPacmanConfig ( )
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 ( ) ) ;
2016-02-14 23:48:43 +01:00
string arch ( sysArch ) ;
2015-08-10 22:46:01 +02:00
const auto & config = configIni . data ( ) ;
// read relevant options
static const string sigLevelKey ( " SigLevel " ) ;
static const string usageKey ( " Usage " ) ;
2016-02-14 23:48:43 +01:00
SignatureLevel globalSigLevel = defaultSigLevel ;
2015-09-21 22:16:19 +02:00
for ( auto & scope : config ) {
if ( scope . first = = " options " ) {
// iterate through all "config" scopes (just to cover the case that there are multiple "options" scopes)
const auto & options = scope . second ;
const auto & specifiedArch = lastValue ( options , " Architecture " ) ;
if ( ! specifiedArch . empty ( ) & & specifiedArch ! = " auto " ) {
arch = specifiedArch ;
}
const auto & specifiedDir = lastValue ( options , " CacheDir " ) ;
if ( ! specifiedDir . empty ( ) ) {
m_pacmanCacheDir = QString : : fromStdString ( specifiedDir ) ;
}
globalSigLevel = parseSigLevel ( lastValue ( options , sigLevelKey ) ) ;
2015-08-10 22:46:01 +02:00
}
}
// 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-12-08 18:59:17 +01:00
} else if ( m_syncDbMap . count ( dbName ) ) {
2016-02-25 22:53:33 +01: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 ) ;
2016-02-14 23:48:43 +01:00
SignatureLevel sigLevel = sigLevelStr . empty ( ) ? globalSigLevel : parseSigLevel ( sigLevelStr ) ;
RepositoryUsage usage = parseUsage ( lastValue ( scope . second , usageKey ) ) ;
// add sync db to internal map (use as index size + 1 because the local database has index 0)
2016-02-15 18:26:05 +01:00
m_syncDbs . emplace_back ( make_unique < AlpmDatabase > ( dbName , findDatabasePath ( dbName , false , false ) , usage , sigLevel , m_syncDbs . size ( ) + 1 ) ) ;
2016-02-14 23:48:43 +01:00
AlpmDatabase * emplacedDb = m_syncDbs . back ( ) . get ( ) ;
m_syncDbMap . emplace ( dbName , emplacedDb ) ;
2016-02-25 22:53:33 +01:00
connectRepository ( emplacedDb ) ;
2016-02-15 18:26:05 +01:00
cerr < < shchar < < " Added [ " < < dbName < < " ] " < < endl ;
2016-02-25 22:53:33 +01:00
if ( localDatabase ( ) & & usage & RepositoryUsage : : Upgrade ) {
2016-02-14 23:48:43 +01:00
// -> db is used to upgrade local database
2016-02-25 22:53:33 +01:00
localDatabase ( ) - > upgradeSources ( ) < < emplacedDb ;
2016-02-14 23:48:43 +01: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 ) ;
emplacedDb - > serverUrls ( ) < < Utilities : : qstr ( url ) ;
if ( m_config . isVerbose ( ) | | m_config . runServer ( ) ) {
2016-02-15 18:26:05 +01:00
cerr < < shchar < < " Added server: " < < url < < endl ;
2015-08-10 22:46:01 +02:00
}
2016-02-14 23:48:43 +01:00
}
// add included servers / parse mirror list
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 & ) {
cerr < < shchar < < " Error: An IO exception occured when parsing the included file \" " < < path < < " \" . " < < endl ;
2015-08-19 02:13:28 +02:00
}
2015-08-10 22:46:01 +02:00
}
2016-02-14 23:48:43 +01:00
try {
2016-02-25 22:53:33 +01:00
for ( auto & nestedScope : includedIni . data ( ) ) {
if ( nestedScope . first . empty ( ) ) {
for ( auto range = nestedScope . second . equal_range ( " Server " ) ; range . first ! = range . second ; + + range . first ) {
2016-02-14 23:48:43 +01:00
string url = range . first - > second ;
findAndReplace < string > ( url , " $repo " , scope . first ) ;
findAndReplace < string > ( url , " $arch " , arch ) ;
emplacedDb - > serverUrls ( ) < < Utilities : : qstr ( url ) ;
if ( m_config . isVerbose ( ) | | m_config . runServer ( ) ) {
2016-02-15 18:26:05 +01:00
cerr < < shchar < < " Added server: " < < url < < endl ;
2015-09-21 22:16:19 +02:00
}
2015-08-19 02:13:28 +02:00
}
2015-08-10 22:46:01 +02:00
}
}
2016-02-14 23:48:43 +01:00
} catch ( const out_of_range & ) {
cerr < < shchar < < " Warning: Included file \" " < < path < < " \" has no values. " < < 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. " ) ;
}
}
/*!
2016-02-14 23:48:43 +01:00
* \ brief Adds sync databases listed in the repository index configuration .
2015-08-19 02:13:28 +02:00
*/
2016-02-14 23:48:43 +01:00
void Manager : : addDatabasesFromRepoIndexConfig ( )
2015-08-19 02:13:28 +02:00
{
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 ( ) ) {
2016-02-25 22:53:33 +01:00
AlpmDatabase * syncDb ;
if ( m_localDb & & repoEntry . name ( ) = = QLatin1String ( " local " ) ) {
syncDb = m_localDb . get ( ) ;
} else {
try {
syncDb = m_syncDbMap . at ( repoEntry . name ( ) ) ;
} catch ( const out_of_range & ) {
syncDb = nullptr ;
}
}
if ( syncDb ) {
2015-09-21 22:16:19 +02:00
cerr < < shchar < < " Applying config for database [ " < < syncDb - > name ( ) < < ' ] ' < < endl ;
2016-02-14 23:48:43 +01:00
if ( ! repoEntry . databasePath ( ) . isEmpty ( ) ) {
syncDb - > setDatabasePath ( repoEntry . databasePath ( ) ) ;
2015-08-19 02:13:28 +02:00
}
2016-02-14 23:48:43 +01:00
if ( repoEntry . sigLevel ( ) ! = SignatureLevel : : UseDefault ) {
syncDb - > setSigLevel ( repoEntry . sigLevel ( ) ) ;
2015-08-19 02:13:28 +02:00
}
syncDb - > setPackagesDirectory ( repoEntry . packageDir ( ) ) ;
syncDb - > setSourcesDirectory ( repoEntry . sourceDir ( ) ) ;
2016-02-25 22:53:33 +01:00
if ( ! repoEntry . maxDatabaseAge ( ) . isNull ( ) ) {
syncDb - > setMaxPackageAge ( repoEntry . maxDatabaseAge ( ) ) ;
}
} else {
2015-08-19 02:13:28 +02:00
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 {
2016-02-25 22:53:33 +01:00
// repo name mustn't be empty
if ( repoEntry . name ( ) . isEmpty ( ) ) {
cerr < < shchar < < " Warning: Ignoring empty repository entry in configuration file. " < < endl ;
continue ;
}
2016-02-14 23:48:43 +01:00
// determine path of db file
// -> currently just use the file from pacman dir, TODO: download syncdata base
QString dbPath ;
if ( repoEntry . databasePath ( ) . isEmpty ( ) ) {
2016-02-15 18:26:05 +01:00
// no path specified -> use defaults
dbPath = findDatabasePath ( repoEntry . name ( ) , ! repoEntry . maxDatabaseAge ( ) . isNull ( ) , true ) ;
2016-02-14 23:48:43 +01:00
} else {
dbPath = repoEntry . databasePath ( ) ;
}
// add sync db to internal map (use as index size + 1 because the local database has index 0)
m_syncDbs . emplace_back ( make_unique < AlpmDatabase > ( repoEntry . name ( ) , dbPath , RepositoryUsage : : None , repoEntry . sigLevel ( ) , m_syncDbs . size ( ) + 1 ) ) ;
2016-02-25 22:53:33 +01:00
connectRepository ( syncDb = m_syncDbs . back ( ) . get ( ) ) ;
2016-02-14 23:48:43 +01:00
m_syncDbMap . emplace ( repoEntry . name ( ) , syncDb ) ;
syncDb - > setSourcesDirectory ( repoEntry . sourceDir ( ) ) ;
syncDb - > setPackagesDirectory ( repoEntry . packageDir ( ) ) ;
2016-02-15 18:26:05 +01:00
if ( ! repoEntry . maxDatabaseAge ( ) . isNull ( ) ) {
syncDb - > setMaxPackageAge ( repoEntry . maxDatabaseAge ( ) ) ;
}
2016-02-14 23:48:43 +01:00
if ( m_config . isVerbose ( ) | | m_config . runServer ( ) ) {
cerr < < shchar < < " Added database [ " < < repoEntry . name ( ) < < ' ] ' < < endl ;
2015-08-19 02:13:28 +02:00
}
}
}
if ( syncDb ) {
2016-02-14 23:48:43 +01:00
syncDb - > serverUrls ( ) < < repoEntry . servers ( ) ;
2015-08-19 02:13:28 +02:00
}
2015-08-10 22:46:01 +02:00
}
2016-02-14 23:48:43 +01:00
2015-09-04 14:37:01 +02:00
// add upgrade sources
for ( const RepoEntry & repoEntry : m_config . repoEntries ( ) ) {
try {
2015-12-08 18:59:17 +01:00
auto & upgradeSources = m_syncDbMap . at ( repoEntry . name ( ) ) - > upgradeSources ( ) ;
2015-09-04 14:37:01 +02:00
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 .
2016-02-14 23:48:43 +01:00
* \ remarks Must be called , after all relevant sync databases have been added ( eg . via applyPacmanConfig ( ) ) .
2015-09-05 17:25:05 +02:00
*/
2016-02-25 22:53:33 +01:00
void Manager : : initAlpmDataBases ( )
2016-02-14 23:48:43 +01:00
{
2016-02-25 22:53:33 +01:00
// connect computeRequiredBy()
if ( m_config . runServer ( ) ) {
if ( localDatabase ( ) ) {
QObject : : connect ( localDatabase ( ) , & AlpmDatabase : : initialized , bind ( & Manager : : computeRequiredBy , this , localDatabase ( ) ) ) ;
}
2015-12-08 18:59:17 +01:00
for ( auto & syncDbEntry : m_syncDbMap ) {
2016-02-25 22:53:33 +01:00
QObject : : connect ( syncDbEntry . second , & AlpmDatabase : : initialized , bind ( & Manager : : computeRequiredBy , this , syncDbEntry . second ) ) ;
2015-09-11 21:59:47 +02:00
}
2016-02-25 22:53:33 +01:00
}
// call the init method
if ( m_config . isVerbose ( ) | | m_config . runServer ( ) ) {
cerr < < " Initializing ALPM databases ... " ;
cerr . flush ( ) ;
}
QList < AlpmPackageLoader * > loaders ;
loaders . reserve ( m_syncDbMap . size ( ) + ( localDatabase ( ) ? 1 : 0 ) ) ;
if ( localDatabase ( ) ) {
loaders < < static_cast < AlpmPackageLoader * > ( localDatabase ( ) - > init ( ) ) ;
}
for ( auto & syncDbEntry : m_syncDbMap ) {
loaders < < static_cast < AlpmPackageLoader * > ( syncDbEntry . second - > init ( ) ) ;
}
for ( auto * loader : loaders ) {
if ( loader ) {
loader - > future ( ) . waitForFinished ( ) ;
switch ( loader - > error ( ) ) {
case DatabaseError : : NoError :
break ;
case DatabaseError : : NotFound :
if ( loader - > database ( ) - > serverUrls ( ) . isEmpty ( ) ) {
// there are no server URLs associated -> print error
cerr < < endl < < shchar < < " Unable to locate database file for ALPM database [ " < < loader - > database ( ) - > name ( ) . toLocal8Bit ( ) . data ( ) < < " ] " < < endl ;
} else {
// try to download the database from server
loader - > database ( ) - > downloadDatabase ( m_config . storageDir ( ) + QStringLiteral ( " /sync " ) ) ;
}
break ;
default :
cerr < < endl < < shchar < < " Unable to initialize ALPM database [ " < < loader - > database ( ) - > name ( ) . toLocal8Bit ( ) . data ( ) < < " ] " < < endl ;
// TODO: print the cause of the problem
2016-02-14 23:48:43 +01:00
}
2016-02-25 22:53:33 +01:00
delete loader ;
2016-02-14 23:48:43 +01:00
}
}
2016-02-25 22:53:33 +01:00
for ( auto & syncDbEntry : m_syncDbMap ) {
syncDbEntry . second - > updateGroups ( ) ;
}
2016-02-14 23:48:43 +01:00
if ( m_config . isVerbose ( ) | | m_config . runServer ( ) ) {
cerr < < " DONE " < < endl ;
2015-09-11 21:59:47 +02:00
}
2016-02-25 22:53:33 +01:00
}
2016-02-14 23:48:43 +01:00
2016-02-25 22:53:33 +01:00
/*!
* \ brief Computes required - by and optional - for fields for the packages of the specified \ a repo .
* \ remarks
* - The computing is performed asynchronously so this method will return immidiately .
* - Do not call this method if the specified \ a repo is busy .
*/
void Manager : : computeRequiredBy ( Repository * repo )
{
// find relevant databases
QList < Repository * > relevantDbs ;
if ( repo = = localDatabase ( ) ) {
relevantDbs . reserve ( 1 ) ;
relevantDbs < < repo ;
} else {
relevantDbs . reserve ( m_syncDbs . size ( ) ) ;
for ( auto & syncDb : m_syncDbs ) {
relevantDbs < < syncDb . get ( ) ;
2016-02-14 23:48:43 +01:00
}
2015-09-11 21:59:47 +02:00
}
2016-02-25 22:53:33 +01:00
repo - > computeRequiredBy ( relevantDbs ) ;
2015-09-11 21:59:47 +02:00
}
2016-01-18 20:34:29 +01:00
/*!
* \ brief Returns whether automatic cache maintenance is enabled .
* \ remarks If enabled , the cache will be cleaned and saved frequently .
*/
bool Manager : : isAutoCacheMaintenanceEnabled ( ) const
{
return m_cacheTimer & & m_cacheTimer - > isActive ( ) ;
}
/*!
* \ brief Sets whether automatic cache maintenacne is enabled .
* \ sa isAutoCacheMaintenanceEnabled ( )
*/
void Manager : : setAutoCacheMaintenanceEnabled ( bool enabled )
{
if ( isAutoCacheMaintenanceEnabled ( ) ! = enabled ) {
if ( enabled ) {
if ( ! m_cacheTimer ) {
m_cacheTimer = make_unique < QTimer > ( ) ;
m_cacheTimer - > setInterval ( 5 * 60 * 1000 ) ;
QObject : : connect ( m_cacheTimer . get ( ) , & QTimer : : timeout , bind ( & Manager : : maintainCache , this ) ) ;
}
m_cacheTimer - > start ( ) ;
} else {
m_cacheTimer - > stop ( ) ;
}
}
}
2015-09-11 21:59:47 +02:00
/*!
* \ brief Writes the cache for all repositories where caching makes sense .
*/
void Manager : : writeCache ( )
2015-09-05 17:25:05 +02:00
{
2015-09-11 21:59:47 +02:00
// could iterate through all repos and check isCachingUseful() but
// currently its just the AUR which is needed to be cached
if ( userRepository ( ) ) {
QFile file ( config ( ) . cacheDir ( ) % QChar ( ' / ' ) % userRepository ( ) - > name ( ) % QStringLiteral ( " .cache " ) ) ;
if ( file . open ( QFileDevice : : WriteOnly ) ) {
QDataStream stream ( & file ) ;
userRepository ( ) - > writeToCacheStream ( stream ) ;
// if warnings/errors occur, these will be printed directly by writeToCacheStream()
} else {
cerr < < shchar < < " Warning: Unable to write cache file for the AUR. " < < endl ;
}
2015-09-05 17:25:05 +02:00
}
2015-09-11 21:59:47 +02:00
}
2016-02-25 22:53:33 +01:00
/*!
* \ brief Restores the cache for all repositories where caching makes sense .
*/
2015-09-11 21:59:47 +02:00
void Manager : : restoreCache ( )
{
// could iterate through all repos and check isCachingUseful() but
// currently its just the AUR which is needed to be cached
if ( userRepository ( ) ) {
QFile file ( config ( ) . cacheDir ( ) % QChar ( ' / ' ) % userRepository ( ) - > name ( ) % QStringLiteral ( " .cache " ) ) ;
if ( file . exists ( ) ) {
if ( file . open ( QFileDevice : : ReadOnly ) ) {
QDataStream stream ( & file ) ;
userRepository ( ) - > restoreFromCacheStream ( stream ) ;
// if warnings/errors occur, these will be printed directly by restoreFromCacheStream()
} else {
cerr < < shchar < < " Warning: Unable to open cache file for the AUR. " < < endl ;
}
}
2015-09-05 17:25:05 +02:00
}
}
2016-02-25 22:53:33 +01:00
/*!
* \ brief Removes outdated packages from the cache .
* \ remarks Currently only the AUR cache is affected .
*/
2016-01-18 20:34:29 +01:00
void Manager : : cleanCache ( )
{
if ( userRepository ( ) ) {
userRepository ( ) - > cleanOutdatedPackages ( ) ;
}
}
2016-02-25 22:53:33 +01:00
/*!
* \ brief Removes all cached packages .
* \ remarks Currently only the AUR cache is affected .
*/
2016-01-18 20:34:29 +01:00
void Manager : : wipeCache ( )
{
if ( userRepository ( ) ) {
userRepository ( ) - > wipePackages ( ) ;
}
}
2016-02-25 22:53:33 +01:00
/*!
* \ brief Cleans and writes the cache .
* \ remarks Automatically called if automatic cache maintenance is enabled .
*/
2016-01-18 20:34:29 +01:00
void Manager : : maintainCache ( )
{
cleanCache ( ) ;
// TODO: write cache only when modified
writeCache ( ) ;
}
2016-02-25 22:53:33 +01:00
/*!
* \ brief Returns whether automatic updates are enabled .
* \ remarks If enabled , the ALPM databases will be updated frequently .
*/
bool Manager : : isAutoUpdateEnabled ( ) const
{
return m_updateTimer & & m_updateTimer - > isActive ( ) ;
}
/*!
* \ brief Sets whether automatic updates are enabled .
* \ sa isAutoUpdateEnabled ( )
*/
void Manager : : setAutoUpdateEnabled ( bool enabled )
{
2016-02-26 16:59:15 +01:00
if ( isAutoUpdateEnabled ( ) ! = enabled ) {
2016-02-25 22:53:33 +01:00
if ( enabled ) {
if ( ! m_updateTimer ) {
m_updateTimer = make_unique < QTimer > ( ) ;
m_updateTimer - > setInterval ( 5 * 60 * 1000 ) ;
QObject : : connect ( m_updateTimer . get ( ) , & QTimer : : timeout , bind ( & Manager : : updateAlpmDatabases , this ) ) ;
}
m_updateTimer - > start ( ) ;
} else {
m_updateTimer - > stop ( ) ;
}
}
}
/*!
* \ brief Triggers updating ALPM databases with outdated packages .
*/
void Manager : : updateAlpmDatabases ( )
{
if ( localDatabase ( ) ) {
if ( localDatabase ( ) - > hasOutdatedPackages ( ) ) {
localDatabase ( ) - > init ( ) ;
}
}
for ( auto & syncDbEntry : m_syncDbMap ) {
if ( syncDbEntry . second - > hasOutdatedPackages ( ) ) {
syncDbEntry . second - > refresh ( m_config . storageDir ( ) + QStringLiteral ( " /sync " ) ) ;
}
}
}
/*!
* \ brief Triggers updating all ALPM databases ( regardless whether packages are outdated or not ) .
*/
void Manager : : forceUpdateAlpmDatabases ( )
{
if ( localDatabase ( ) ) {
localDatabase ( ) - > init ( ) ;
}
for ( auto & syncDbEntry : m_syncDbMap ) {
syncDbEntry . second - > refresh ( m_config . storageDir ( ) + QStringLiteral ( " /sync " ) ) ;
}
}
2015-08-10 22:46:01 +02:00
/*!
* \ brief Returns a list of all sync databases .
* \ remarks Sync databases must be registered with parsePacmanConfig ( ) before .
*/
2015-12-08 18:59:17 +01:00
const std : : map < QString , AlpmDatabase * > & Manager : : syncDatabases ( ) const
2015-08-10 22:46:01 +02:00
{
2015-12-08 18:59:17 +01:00
return m_syncDbMap ; // m_syncDbs has been filled when the databases were registered
2015-08-10 22:46:01 +02:00
}
2016-02-25 22:53:33 +01:00
QJsonObject emptyJsonObject ;
2015-08-10 22:46:01 +02:00
/*!
* \ brief Returns basic information about all repositories known to the manager .
*/
2015-09-21 22:16:19 +02:00
const QJsonObject & Manager : : basicRepoInfo ( ) const
2015-08-10 22:46:01 +02:00
{
2016-02-25 22:53:33 +01:00
QMutexLocker locker ( & m_basicRepoInfoMutex ) ;
2015-08-10 22:46:01 +02:00
if ( m_basicRepoInfo . isEmpty ( ) ) {
2015-08-19 02:13:28 +02:00
if ( m_basicRepoInfo . isEmpty ( ) ) {
2015-09-04 14:37:01 +02:00
// add local data base
2016-02-25 22:53:33 +01:00
if ( localDatabase ( ) ) {
if ( localDatabase ( ) - > isBusy ( ) ) {
m_basicRepoInfo . insert ( QStringLiteral ( " local " ) , QStringLiteral ( " incomplete " ) ) ;
} else {
QReadLocker locker ( localDatabase ( ) - > lock ( ) ) ;
m_basicRepoInfo . insert ( localDatabase ( ) - > name ( ) , localDatabase ( ) - > basicInfo ( ) ) ;
}
2015-11-03 18:19:24 +01:00
}
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 ( ) ) {
2016-02-25 22:53:33 +01:00
if ( syncDb . second - > isBusy ( ) ) {
m_basicRepoInfo . insert ( syncDb . first , QStringLiteral ( " incomplete " ) ) ;
2015-08-19 02:13:28 +02:00
} else {
2016-02-25 22:53:33 +01:00
// check if the "sync" database is actually used for syncing
QReadLocker locker ( syncDb . second - > lock ( ) ) ;
auto usage = syncDb . second - > usage ( ) ;
if ( ( usage & RepositoryUsage : : Sync ) | | ( usage & RepositoryUsage : : Install ) | | ( usage & RepositoryUsage : : Upgrade ) ) {
m_basicRepoInfo . insert ( syncDb . first , syncDb . second - > basicInfo ( ) ) ;
} else {
m_basicRepoInfo . insert ( syncDb . first , 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
2015-09-21 22:16:19 +02:00
if ( userRepository ( ) ) {
2016-02-25 22:53:33 +01:00
if ( userRepository ( ) - > isBusy ( ) ) {
m_basicRepoInfo . insert ( QStringLiteral ( " aur " ) , QStringLiteral ( " incomplete " ) ) ;
} else {
QReadLocker locker ( userRepository ( ) - > lock ( ) ) ;
m_basicRepoInfo . insert ( userRepository ( ) - > name ( ) , userRepository ( ) - > basicInfo ( ) ) ;
}
2015-09-04 14:37:01 +02:00
}
2015-08-10 22:46:01 +02:00
}
}
return m_basicRepoInfo ;
}
/*!
* \ brief Returns package information for the specified selection of packages .
2015-09-27 19:29:45 +02:00
* \ remarks Does not request any information and hence will only return information
* which does not need to be requested or has been requested yet .
2015-08-10 22:46:01 +02:00
*/
2016-02-25 22:53:33 +01:00
QJsonArray Manager : : packageInfo ( const QJsonObject & pkgSelection , PackageInfoPart part ) const
2015-08-10 22:46:01 +02:00
{
2015-09-21 22:16:19 +02:00
QJsonArray results ;
2015-09-04 14:37:01 +02:00
for ( auto i = pkgSelection . constBegin ( ) , end = pkgSelection . constEnd ( ) ; i ! = end ; + + i ) {
2016-02-25 22:53:33 +01:00
QJsonObject res ;
res . insert ( QStringLiteral ( " repo " ) , i . key ( ) ) ;
2015-09-04 14:37:01 +02:00
if ( auto * repo = repositoryByName ( i . key ( ) ) ) {
2016-02-25 22:53:33 +01:00
if ( repo - > isBusy ( ) ) {
// specified repository is busy
res . insert ( QStringLiteral ( " error " ) , QStringLiteral ( " busy " ) ) ;
results < < res ;
} else {
QReadLocker locker ( repo - > lock ( ) ) ;
for ( const auto & entry : i . value ( ) . toArray ( ) ) {
const auto entryObj = entry . toObject ( ) ;
const auto pkgName = entryObj . value ( QStringLiteral ( " name " ) ) . toString ( ) ;
2015-09-29 21:52:30 +02:00
const auto index = entryObj . value ( QStringLiteral ( " index " ) ) ;
if ( ! index . isNull ( ) & & ! index . isUndefined ( ) ) {
res . insert ( QStringLiteral ( " index " ) , index ) ;
}
2016-02-25 22:53:33 +01:00
if ( ! pkgName . isEmpty ( ) ) {
res . insert ( QStringLiteral ( " name " ) , pkgName ) ;
if ( auto * pkg = repo - > packageByName ( pkgName ) ) {
if ( part & Basics ) {
res . insert ( QStringLiteral ( " basics " ) , pkg - > basicInfo ( ) ) ;
}
if ( part & Details ) {
res . insert ( QStringLiteral ( " details " ) , pkg - > detailedInfo ( ) ) ;
}
} else {
res . insert ( QStringLiteral ( " error " ) , QStringLiteral ( " na " ) ) ;
2015-09-21 22:16:19 +02:00
}
2016-02-25 22:53:33 +01:00
results < < res ;
2015-09-04 14:37:01 +02:00
}
}
2015-08-10 22:46:01 +02:00
}
2015-09-04 14:37:01 +02:00
} else {
// specified repository can not be found
2016-02-25 22:53:33 +01:00
res . insert ( QStringLiteral ( " error " ) , QStringLiteral ( " na " ) ) ;
results < < res ;
2015-08-10 22:46:01 +02:00
}
2015-09-04 14:37:01 +02:00
2015-08-10 22:46:01 +02:00
}
2015-09-21 22:16:19 +02:00
return results ;
2015-08-10 22:46:01 +02:00
}
2016-02-25 22:53:33 +01:00
QJsonObject incompleteGroupInfo ( const QString & repo )
{
QJsonObject busyObject ;
busyObject . insert ( QStringLiteral ( " repo " ) , QStringLiteral ( " local " ) ) ;
busyObject . insert ( QStringLiteral ( " incomplete " ) , true ) ;
return busyObject ;
}
2015-08-10 22:46:01 +02:00
/*!
* \ brief Returns group information for the local database and all registred sync databases .
*/
const QJsonArray & Manager : : groupInfo ( ) const
{
2016-02-25 22:53:33 +01:00
QMutexLocker locker ( & m_groupInfoMutex ) ;
2015-08-10 22:46:01 +02:00
if ( m_groupInfo . empty ( ) ) {
2015-08-19 02:13:28 +02:00
if ( m_groupInfo . empty ( ) ) {
2016-02-25 22:53:33 +01:00
if ( localDatabase ( ) ) {
if ( localDatabase ( ) - > isBusy ( ) ) {
m_groupInfo < < incompleteGroupInfo ( QStringLiteral ( " local " ) ) ;
} else {
QReadLocker locker ( localDatabase ( ) - > lock ( ) ) ;
m_groupInfo < < localDatabase ( ) - > groupInfo ( ) ;
}
}
2015-12-08 18:59:17 +01:00
for ( const auto & db : m_syncDbMap ) {
2016-02-25 22:53:33 +01:00
if ( db . second - > isBusy ( ) ) {
m_groupInfo < < incompleteGroupInfo ( db . first ) ;
} else {
QReadLocker locker ( db . second - > lock ( ) ) ;
m_groupInfo < < db . second - > groupInfo ( ) ;
}
2015-08-19 02:13:28 +02:00
}
2015-08-10 22:46:01 +02:00
}
}
return m_groupInfo ;
}
2016-02-25 22:53:33 +01:00
/*!
* \ brief Internally called to invalidate cached JSON serialization .
*
* This method is called after a repository has been initialized or the
* required - by computition has finished .
*/
void Manager : : invalidateCachedJsonSerialization ( )
{
m_basicRepoInfo = QJsonObject ( ) ;
m_groupInfo = QJsonArray ( ) ;
}
/*!
* \ brief Internally called to emit the updatesAvailable ( ) signal .
*
* Emits the signal only if no repository is busy .
*/
void Manager : : emitUpdatesAvailable ( )
{
if ( localDatabase ( ) & & localDatabase ( ) - > isBusy ( ) ) {
return ;
}
if ( userRepository ( ) & & userRepository ( ) - > isBusy ( ) ) {
return ;
}
for ( const auto & syncDb : m_syncDbs ) {
if ( syncDb - > isBusy ( ) ) {
return ;
}
}
emit updatesAvailable ( ) ;
}
/*!
* \ brief Internally called after a repository has been added to connect
* the available ( ) signal .
*/
void Manager : : connectRepository ( Repository * repo )
{
connect ( repo , & Repository : : available , this , & Manager : : invalidateCachedJsonSerialization ) ;
connect ( repo , & Repository : : requiredByComputed , this , & Manager : : emitUpdatesAvailable ) ;
}
2015-09-21 22:16:19 +02:00
/*!
2016-02-15 18:26:05 +01:00
* \ brief Add the local database .
2015-09-21 22:16:19 +02:00
*/
2016-02-14 23:48:43 +01:00
void Manager : : addLocalDatabase ( )
2015-09-21 22:16:19 +02:00
{
2016-02-14 23:48:43 +01:00
m_localDb = make_unique < AlpmDatabase > ( QStringLiteral ( " local " ) , config ( ) . alpmDbPath ( ) % QStringLiteral ( " /local " ) , RepositoryUsage : : None , SignatureLevel : : UseDefault , 0 ) ;
2016-02-25 22:53:33 +01:00
connectRepository ( m_localDb . get ( ) ) ;
2015-09-21 22:16:19 +02:00
}
/*!
2016-02-14 23:48:43 +01:00
* \ brief Removes all ALPM databases .
2015-09-21 22:16:19 +02:00
*/
2016-02-14 23:48:43 +01:00
void Manager : : removeAllDatabases ( )
2015-09-21 22:16:19 +02:00
{
2016-02-14 23:48:43 +01:00
m_localDb . reset ( ) ;
m_syncDbs . clear ( ) ;
m_syncDbMap . clear ( ) ;
2015-09-21 22:16:19 +02:00
}
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
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 ) {
2016-02-25 22:53:33 +01:00
return localDatabase ( ) ;
2015-08-10 22:46:01 +02:00
} else {
2015-09-04 14:37:01 +02:00
try {
2015-12-08 18:59:17 +01:00
return m_syncDbMap . at ( dbName ) ;
2015-09-04 14:37:01 +02:00
} 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 ) {
2016-02-25 22:53:33 +01:00
return localDatabase ( ) ;
2015-08-10 22:46:01 +02:00
} else {
2015-09-04 14:37:01 +02:00
try {
2015-12-08 18:59:17 +01:00
return m_syncDbMap . at ( dbName ) ;
2015-09-04 14:37:01 +02:00
} 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 ) {
2016-02-25 22:53:33 +01:00
return localDatabase ( ) ;
} else if ( name . compare ( QLatin1String ( " aur " ) , Qt : : CaseInsensitive ) = = 0 ) {
2015-09-04 14:37:01 +02:00
return userRepository ( ) ;
} else {
try {
2015-12-08 18:59:17 +01:00
return m_syncDbMap . at ( name ) ;
2015-09-04 14:37:01 +02:00
} 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 ) {
2016-02-25 22:53:33 +01:00
return localDatabase ( ) ;
} else if ( name . compare ( QLatin1String ( " aur " ) , Qt : : CaseInsensitive ) = = 0 ) {
2015-09-04 14:37:01 +02:00
return userRepository ( ) ;
} else {
2015-08-10 22:46:01 +02:00
try {
2015-12-08 18:59:17 +01:00
return m_syncDbMap . at ( name ) ;
2015-09-04 14:37:01 +02:00
} catch ( const out_of_range & ) {
return nullptr ;
2015-08-10 22:46:01 +02:00
}
}
2015-09-04 14:37:01 +02:00
}
/*!
2016-02-15 18:26:05 +01:00
* \ 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 .
2015-09-04 14:37:01 +02:00
*/
2016-02-15 18:26:05 +01:00
QString Manager : : findDatabasePath ( const QString & name , bool updatesRequired , bool printError ) const
{
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 ( ) ) ) {
2016-02-18 17:11:37 +01:00
return dbPathWithFiles . absoluteFilePath ( ) ;
2016-02-15 18:26:05 +01:00
} else if ( dbPathRegular . isFile ( ) ) {
2016-02-18 17:11:37 +01:00
return dbPathRegular . absoluteFilePath ( ) ;
2016-02-15 18:26:05 +01:00
} 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 ( ) ) ) {
2016-02-18 17:11:37 +01:00
return pacmanDbPathWithFiles . absoluteFilePath ( ) ;
2016-02-15 18:26:05 +01:00
} else if ( pacmanDbPathRegular . isFile ( ) ) {
2016-02-18 17:11:37 +01:00
return pacmanDbPathRegular . absoluteFilePath ( ) ;
2016-02-15 18:26:05 +01:00
}
}
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
2015-09-04 14:37:01 +02:00
{
2016-02-15 18:26:05 +01:00
return m_config . storageDir ( ) % QStringLiteral ( " /sync/ " ) % name % ( files ? QStringLiteral ( " .files " ) : QStringLiteral ( " .db " ) ) ;
2015-08-10 22:46:01 +02:00
}
}