2016-01-28 14:52:40 +01:00
|
|
|
/** @file
|
|
|
|
|
*
|
|
|
|
|
* @par History
|
|
|
|
|
*/
|
2015-01-19 18:18:21 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "pkg.h"
|
2018-01-29 21:55:48 +01:00
|
|
|
|
2015-11-06 16:09:15 +01:00
|
|
|
#include "pol_global_config.h"
|
2019-10-12 15:09:43 +02:00
|
|
|
#include <algorithm>
|
2021-12-30 07:21:20 +01:00
|
|
|
#include <filesystem>
|
2018-12-23 13:55:47 +01:00
|
|
|
#include <stdlib.h>
|
2021-12-30 07:21:20 +01:00
|
|
|
#include <system_error>
|
2015-01-19 18:18:21 +01:00
|
|
|
|
|
|
|
|
#include "../clib/cfgelem.h"
|
|
|
|
|
#include "../clib/cfgfile.h"
|
2018-01-29 21:55:48 +01:00
|
|
|
#include "../clib/clib.h"
|
2015-01-19 18:18:21 +01:00
|
|
|
#include "../clib/fileutil.h"
|
|
|
|
|
#include "../clib/logfacility.h"
|
|
|
|
|
#include "../clib/passert.h"
|
|
|
|
|
#include "../clib/stlutil.h"
|
|
|
|
|
#include "../clib/strutil.h"
|
2018-12-21 20:27:05 +01:00
|
|
|
#include "systemstate.h"
|
2015-01-19 18:18:21 +01:00
|
|
|
|
2021-12-30 07:21:20 +01:00
|
|
|
namespace fs = std::filesystem;
|
2016-02-19 19:26:35 +01:00
|
|
|
namespace Pol
|
|
|
|
|
{
|
|
|
|
|
namespace Plib
|
|
|
|
|
{
|
|
|
|
|
bool Package::provides_system_home_page() const
|
|
|
|
|
{
|
|
|
|
|
return provides_system_home_page_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Package* find_package( const std::string& pkgname )
|
|
|
|
|
{
|
|
|
|
|
auto itr = systemstate.packages_byname.find( pkgname );
|
|
|
|
|
if ( itr != systemstate.packages_byname.end() )
|
|
|
|
|
{
|
|
|
|
|
return ( *itr ).second;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-10-09 16:36:35 +02:00
|
|
|
return nullptr;
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void remove_package( Package* pkg )
|
|
|
|
|
{
|
2019-10-12 15:09:43 +02:00
|
|
|
auto last = std::remove( systemstate.packages.begin(), systemstate.packages.end(), pkg );
|
2016-02-19 19:26:35 +01:00
|
|
|
systemstate.packages.erase( last, systemstate.packages.end() );
|
|
|
|
|
|
|
|
|
|
auto itr = systemstate.packages_byname.begin();
|
|
|
|
|
while ( itr != systemstate.packages_byname.end() )
|
|
|
|
|
{
|
2019-10-12 15:09:43 +02:00
|
|
|
if ( itr->second == pkg )
|
|
|
|
|
{
|
|
|
|
|
systemstate.packages_byname.erase( itr );
|
|
|
|
|
break;
|
|
|
|
|
}
|
2016-02-19 19:26:35 +01:00
|
|
|
++itr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void compare_versions( const std::string& verleft, const std::string& verright, bool& isgreater,
|
|
|
|
|
bool& isequal )
|
|
|
|
|
{
|
|
|
|
|
isgreater = isequal = false;
|
|
|
|
|
|
|
|
|
|
const char* vneed = verright.c_str();
|
|
|
|
|
const char* vhave = verleft.c_str();
|
|
|
|
|
|
2018-10-09 16:36:35 +02:00
|
|
|
while ( ( vneed != nullptr && vneed[0] != '\0' ) || ( vhave != nullptr && vhave[0] != '\0' ) )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
2018-10-09 16:36:35 +02:00
|
|
|
char* new_vneed = nullptr;
|
|
|
|
|
char* new_vhave = nullptr;
|
2016-02-19 19:26:35 +01:00
|
|
|
unsigned int vneedpart, vhavepart;
|
2018-10-09 16:36:35 +02:00
|
|
|
vneedpart = ( vneed != nullptr ) ? strtoul( vneed, &new_vneed, 0 ) : 0;
|
|
|
|
|
vhavepart = ( vhave != nullptr ) ? strtoul( vhave, &new_vhave, 0 ) : 0;
|
2016-02-19 19:26:35 +01:00
|
|
|
|
|
|
|
|
if ( vhavepart > vneedpart )
|
|
|
|
|
{
|
|
|
|
|
isgreater = true;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else if ( vhavepart < vneedpart )
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else // same, so check the next one
|
|
|
|
|
{
|
|
|
|
|
vneed = new_vneed;
|
|
|
|
|
if ( vneed && *vneed )
|
|
|
|
|
++vneed;
|
|
|
|
|
vhave = new_vhave;
|
|
|
|
|
if ( vhave && *vhave )
|
|
|
|
|
++vhave;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
isequal = true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-18 03:35:17 -07:00
|
|
|
bool version_greater_or_equal( const std::string& version_have, const std::string& version_need )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
|
|
|
|
bool isgreater;
|
|
|
|
|
bool isequal;
|
|
|
|
|
compare_versions( version_have, version_need, isgreater, isequal );
|
|
|
|
|
return ( isequal || isgreater );
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-18 03:35:17 -07:00
|
|
|
bool version_equal( const std::string& version_have, const std::string& version_need )
|
|
|
|
|
{
|
|
|
|
|
bool isgreater;
|
|
|
|
|
bool isequal;
|
|
|
|
|
compare_versions( version_have, version_need, isgreater, isequal );
|
|
|
|
|
return isequal;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
void test_check_version()
|
|
|
|
|
{ // have // need
|
2020-10-18 03:35:17 -07:00
|
|
|
passert( version_greater_or_equal( "0", "0" ) == true );
|
|
|
|
|
passert( version_greater_or_equal( "1", "0" ) == true );
|
|
|
|
|
passert( version_greater_or_equal( "0", "1" ) == false );
|
|
|
|
|
passert( version_greater_or_equal( "0.5", "1" ) == false );
|
|
|
|
|
passert( version_greater_or_equal( "0.5", "0" ) == true );
|
|
|
|
|
passert( version_greater_or_equal( "1.2", "1.12" ) == false );
|
|
|
|
|
passert( version_greater_or_equal( "1.12", "1.2" ) == true );
|
|
|
|
|
passert( version_greater_or_equal( "1.2.3", "1" ) == true );
|
|
|
|
|
passert( version_greater_or_equal( "1.1", "1.2.3" ) == false );
|
|
|
|
|
passert( version_greater_or_equal( "1.3", "1.2.3" ) == true );
|
|
|
|
|
|
|
|
|
|
passert( version_equal( "93", "93.0.0" ) == true );
|
|
|
|
|
passert( version_equal( "93.0.0", "93" ) == true );
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PackageList::PackageList( Clib::ConfigElem& elem, const char* tag )
|
|
|
|
|
{
|
|
|
|
|
std::string tmp;
|
|
|
|
|
while ( elem.remove_prop( tag, &tmp ) )
|
|
|
|
|
{
|
2019-01-12 11:46:30 +01:00
|
|
|
Clib::mklowerASCII( tmp );
|
2016-02-19 19:26:35 +01:00
|
|
|
ISTRINGSTREAM is( tmp );
|
|
|
|
|
Elem _elem;
|
|
|
|
|
if ( is >> _elem.pkgname )
|
|
|
|
|
{
|
|
|
|
|
if ( !( is >> _elem.version ) )
|
|
|
|
|
_elem.version = "0";
|
|
|
|
|
|
|
|
|
|
elems.push_back( _elem );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
size_t PackageList::sizeEstimate() const
|
|
|
|
|
{
|
|
|
|
|
size_t size = sizeof( PackageList );
|
|
|
|
|
for ( const auto& elem : elems )
|
|
|
|
|
size += elem.pkgname.capacity() + elem.version.capacity();
|
|
|
|
|
return size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Package::Package( const std::string& pkg_dir, Clib::ConfigElem& elem )
|
2024-01-28 15:49:55 +07:00
|
|
|
: dir_( Clib::normalized_dir_form( pkg_dir ) ),
|
2016-02-19 19:26:35 +01:00
|
|
|
name_( elem.remove_string( "Name" ) ),
|
|
|
|
|
version_( elem.remove_string( "Version", "0" ) ),
|
2020-10-18 03:35:17 -07:00
|
|
|
core_required_( "" ),
|
2016-02-19 19:26:35 +01:00
|
|
|
requires_( elem, "Requires" ),
|
|
|
|
|
conflicts_( elem, "Conflicts" ),
|
|
|
|
|
replaces_( elem, "Replaces" ),
|
|
|
|
|
provides_system_home_page_( elem.remove_bool( "ProvidesSystemHomePage", false ) )
|
|
|
|
|
{
|
2019-01-12 11:46:30 +01:00
|
|
|
Clib::mklowerASCII( name_ );
|
2016-02-19 19:26:35 +01:00
|
|
|
std::string tmp = elem.read_string( "CoreRequired", "0" );
|
|
|
|
|
if ( isdigit( tmp[0] ) )
|
|
|
|
|
{
|
2020-10-18 03:35:17 -07:00
|
|
|
core_required_ = elem.remove_string( "CoreRequired", "" );
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2020-10-18 03:35:17 -07:00
|
|
|
// Forms like CoreRequired POL095-2003-01-28 are no longer allowed.
|
2024-01-12 06:51:44 +01:00
|
|
|
ERROR_PRINTLN(
|
|
|
|
|
"Error in package {}({}):\n"
|
|
|
|
|
" Core version must be a semantic version (n.n.n), but got "
|
|
|
|
|
"\"{}\".",
|
|
|
|
|
name_, dir_, core_required_ );
|
2020-10-18 03:35:17 -07:00
|
|
|
throw std::runtime_error( "Malformed CoreRequired package field" );
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string Package::desc() const
|
|
|
|
|
{
|
|
|
|
|
return name() + " (" + dir() + ")";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Package::check_replacements() const
|
|
|
|
|
{
|
|
|
|
|
bool any = false;
|
|
|
|
|
for ( const auto& elem : replaces_.elems )
|
|
|
|
|
{
|
|
|
|
|
Package* found = find_package( elem.pkgname );
|
2018-10-09 16:36:35 +02:00
|
|
|
if ( found != nullptr )
|
2015-01-19 18:18:21 +01:00
|
|
|
{
|
2016-02-19 19:26:35 +01:00
|
|
|
any = true;
|
2024-01-10 18:29:10 +01:00
|
|
|
INFO_PRINTLN( "Package {} replaces package {}", desc(), found->desc() );
|
2016-02-19 19:26:35 +01:00
|
|
|
remove_package( found );
|
|
|
|
|
delete found;
|
2018-10-09 16:36:35 +02:00
|
|
|
found = nullptr;
|
2015-01-19 18:18:21 +01:00
|
|
|
}
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
|
|
|
|
return any;
|
|
|
|
|
}
|
2015-01-19 18:18:21 +01:00
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
void Package::check_dependencies() const
|
|
|
|
|
{
|
2020-10-18 03:35:17 -07:00
|
|
|
if ( !core_required_.empty() )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
2021-12-30 07:21:20 +01:00
|
|
|
if ( !( version_greater_or_equal( POL_VERSION_STR, core_required_ ) ) )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
2024-01-12 06:51:44 +01:00
|
|
|
ERROR_PRINTLN(
|
|
|
|
|
"Error in package {}:\n"
|
|
|
|
|
" Core version {} is required, but version {} is running.",
|
|
|
|
|
desc(), core_required_, POL_VERSION_STR );
|
2016-02-19 19:26:35 +01:00
|
|
|
throw std::runtime_error( "Package requires a newer core version" );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for ( const auto& elem : requires_.elems )
|
|
|
|
|
{
|
|
|
|
|
Package* found = find_package( elem.pkgname );
|
2018-10-09 16:36:35 +02:00
|
|
|
if ( found == nullptr )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
2024-01-12 06:51:44 +01:00
|
|
|
ERROR_PRINTLN(
|
|
|
|
|
"Error in package '{}' ({}):\n"
|
|
|
|
|
" Package '{}' is required, but is not installed.",
|
|
|
|
|
name_, dir_, elem.pkgname );
|
2016-02-19 19:26:35 +01:00
|
|
|
throw std::runtime_error( "Package dependency error" );
|
|
|
|
|
}
|
|
|
|
|
else
|
2015-01-19 18:18:21 +01:00
|
|
|
{
|
2020-10-18 03:35:17 -07:00
|
|
|
if ( !version_greater_or_equal( found->version_, elem.version ) )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
2024-01-12 06:51:44 +01:00
|
|
|
ERROR_PRINTLN(
|
|
|
|
|
"Error in package '{}' ({}):\n"
|
|
|
|
|
" Package '{}' version {} is required, but version {} "
|
|
|
|
|
"was found",
|
|
|
|
|
name_, dir_, elem.pkgname, elem.version, found->version_ );
|
2016-02-19 19:26:35 +01:00
|
|
|
throw std::runtime_error( "Package dependency error" );
|
|
|
|
|
}
|
2015-01-19 18:18:21 +01:00
|
|
|
}
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
|
|
|
|
}
|
2015-01-19 18:18:21 +01:00
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
void Package::check_conflicts() const
|
|
|
|
|
{
|
|
|
|
|
for ( const auto& elem : conflicts_.elems )
|
|
|
|
|
{
|
|
|
|
|
Package* found = find_package( elem.pkgname );
|
2018-10-09 16:36:35 +02:00
|
|
|
if ( found != nullptr )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
2024-01-12 06:51:44 +01:00
|
|
|
ERROR_PRINTLN(
|
|
|
|
|
"Error in package {}:\n"
|
|
|
|
|
" Package conflicts with package {}",
|
|
|
|
|
desc(), found->desc() );
|
2016-02-19 19:26:35 +01:00
|
|
|
throw std::runtime_error( "Package dependency error" );
|
|
|
|
|
}
|
2015-01-19 18:18:21 +01:00
|
|
|
}
|
2015-11-06 16:50:31 +01:00
|
|
|
}
|
2016-02-19 19:26:35 +01:00
|
|
|
|
|
|
|
|
size_t Package::estimateSize() const
|
|
|
|
|
{
|
|
|
|
|
size_t size = dir_.capacity() + name_.capacity() + version_.capacity() +
|
2021-12-30 07:21:20 +01:00
|
|
|
+core_required_.capacity() + requires_.sizeEstimate() + conflicts_.sizeEstimate() +
|
|
|
|
|
replaces_.sizeEstimate() + sizeof( bool ) /*provides_system_home_page_*/
|
2016-02-19 19:26:35 +01:00
|
|
|
;
|
|
|
|
|
return size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void load_package( const std::string& pkg_dir, Clib::ConfigElem& elem, bool quiet )
|
|
|
|
|
{
|
|
|
|
|
std::unique_ptr<Package> pkg( new Package( pkg_dir, elem ) );
|
|
|
|
|
Package* existing_pkg = find_package( pkg->name() );
|
|
|
|
|
|
2018-10-09 16:36:35 +02:00
|
|
|
if ( existing_pkg != nullptr )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
|
|
|
|
bool isgreater, isequal;
|
|
|
|
|
compare_versions( pkg->version(), existing_pkg->version(), isgreater, isequal );
|
|
|
|
|
if ( isgreater )
|
|
|
|
|
{
|
|
|
|
|
// replace existing package with newer version
|
|
|
|
|
if ( !quiet )
|
2024-01-10 18:29:10 +01:00
|
|
|
INFO_PRINTLN( "Replacing package {} version {} with version {} found in {}",
|
2024-01-12 06:51:44 +01:00
|
|
|
existing_pkg->desc(), existing_pkg->version(), pkg->version(), pkg->dir() );
|
2016-02-19 19:26:35 +01:00
|
|
|
remove_package( existing_pkg );
|
|
|
|
|
delete existing_pkg;
|
2018-10-09 16:36:35 +02:00
|
|
|
existing_pkg = nullptr;
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
|
|
|
|
else if ( isequal )
|
|
|
|
|
{
|
2024-01-12 06:51:44 +01:00
|
|
|
ERROR_PRINTLN(
|
|
|
|
|
"Error in package {}:\n"
|
|
|
|
|
" Package by same name already found in {}",
|
|
|
|
|
pkg->desc(), existing_pkg->desc() );
|
2016-02-19 19:26:35 +01:00
|
|
|
throw std::runtime_error( "Duplicate package found" );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// skip this package, its version is older
|
|
|
|
|
if ( !quiet )
|
2024-01-10 18:29:10 +01:00
|
|
|
INFO_PRINTLN( "Skipping package {} version {} because version {} was already found in ",
|
2024-01-12 06:51:44 +01:00
|
|
|
pkg->desc(), pkg->version(), existing_pkg->version(), existing_pkg->dir() );
|
2016-02-19 19:26:35 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
systemstate.packages.push_back( pkg.get() );
|
|
|
|
|
Package* ppkg = pkg.release();
|
|
|
|
|
systemstate.packages_byname.insert( PackagesByName::value_type( ppkg->name(), ppkg ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void load_packages( const std::string& basedir, bool quiet )
|
|
|
|
|
{
|
2021-12-30 07:21:20 +01:00
|
|
|
std::error_code ec;
|
|
|
|
|
for ( const auto& dir_entry : fs::directory_iterator( basedir, ec ) )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
2021-12-30 07:21:20 +01:00
|
|
|
if ( !dir_entry.is_directory() )
|
2016-02-19 19:26:35 +01:00
|
|
|
continue;
|
2021-12-30 07:21:20 +01:00
|
|
|
if ( auto fn = dir_entry.path().filename().u8string();
|
|
|
|
|
!fn.empty() && ( *fn.begin() == '.' || fn == "template" ) )
|
2016-02-19 19:26:35 +01:00
|
|
|
continue;
|
2021-12-30 07:21:20 +01:00
|
|
|
const auto pkg_dir = dir_entry.path();
|
|
|
|
|
const auto pkg_cfg = pkg_dir / "pkg.cfg";
|
|
|
|
|
if ( fs::exists( pkg_cfg ) )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
2021-12-30 07:21:20 +01:00
|
|
|
Clib::ConfigFile cf( pkg_cfg.u8string().c_str() );
|
2016-02-19 19:26:35 +01:00
|
|
|
Clib::ConfigElem elem;
|
|
|
|
|
|
|
|
|
|
cf.readraw( elem );
|
|
|
|
|
|
2021-12-30 07:21:20 +01:00
|
|
|
if ( ( elem.remove_bool( "Enabled" ) == true || fs::exists( pkg_dir / "enabled.pkg" ) ) &&
|
|
|
|
|
!fs::exists( pkg_dir / "disabled.pkg" ) )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
|
|
|
|
if ( !quiet )
|
2024-01-10 18:29:10 +01:00
|
|
|
INFO_PRINTLN( "Loading package in {}", pkg_dir.u8string() );
|
2021-12-30 07:21:20 +01:00
|
|
|
load_package( pkg_dir.u8string() + "/", elem, quiet );
|
2016-02-19 19:26:35 +01:00
|
|
|
|
2021-12-30 07:21:20 +01:00
|
|
|
load_packages( pkg_dir.u8string(), quiet );
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2021-12-30 07:21:20 +01:00
|
|
|
load_packages( pkg_dir.u8string(), quiet );
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void check_deps_for_package( const Package* pkg )
|
|
|
|
|
{
|
|
|
|
|
pkg->check_dependencies();
|
|
|
|
|
pkg->check_conflicts();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void replace_packages()
|
|
|
|
|
{
|
|
|
|
|
bool done;
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
done = true;
|
|
|
|
|
|
|
|
|
|
for ( const auto& pkg : systemstate.packages )
|
|
|
|
|
{
|
|
|
|
|
bool change = pkg->check_replacements();
|
|
|
|
|
if ( change )
|
|
|
|
|
{
|
|
|
|
|
done = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} while ( !done );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void check_package_deps()
|
|
|
|
|
{
|
|
|
|
|
for ( const auto& pkg : systemstate.packages )
|
|
|
|
|
check_deps_for_package( pkg );
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-05 13:58:51 +01:00
|
|
|
void load_packages( bool quiet )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
|
|
|
|
test_check_version();
|
|
|
|
|
|
2018-01-05 13:58:51 +01:00
|
|
|
load_packages( "pkg/", quiet );
|
2016-02-19 19:26:35 +01:00
|
|
|
|
|
|
|
|
if ( Clib::FileExists( "config/pkgroots.cfg" ) )
|
|
|
|
|
{
|
|
|
|
|
Clib::ConfigFile cf( "config/pkgroots.cfg", "PackageRoot" );
|
|
|
|
|
Clib::ConfigElem elem;
|
|
|
|
|
while ( cf.read( elem ) )
|
|
|
|
|
{
|
|
|
|
|
std::string dir;
|
|
|
|
|
while ( elem.remove_prop( "dir", &dir ) )
|
|
|
|
|
{
|
|
|
|
|
dir = Clib::normalized_dir_form( dir );
|
2018-12-23 13:55:47 +01:00
|
|
|
if ( !quiet )
|
2024-01-10 18:29:10 +01:00
|
|
|
INFO_PRINTLN( "Searching for packages under {}", dir );
|
2018-01-05 13:58:51 +01:00
|
|
|
load_packages( dir.c_str(), quiet );
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
replace_packages();
|
|
|
|
|
|
|
|
|
|
check_package_deps();
|
2019-10-12 15:09:43 +02:00
|
|
|
// sort pkg vector by name, so e.g. startup order is in a defined and maybe also expected order.
|
2021-12-30 07:21:20 +01:00
|
|
|
std::sort( systemstate.packages.begin(), systemstate.packages.end(),
|
|
|
|
|
[]( const Package* pkg1, const Package* pkg2 )
|
|
|
|
|
{ return pkg1->name() < pkg2->name(); } );
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool pkgdef_split( const std::string& spec, const Package* inpkg, const Package** outpkg,
|
|
|
|
|
std::string* path )
|
|
|
|
|
{
|
|
|
|
|
if ( spec[0] == ':' )
|
|
|
|
|
{
|
|
|
|
|
if ( spec[1] == ':' ) // '::corefile' -- a core file
|
|
|
|
|
{
|
2018-10-09 16:36:35 +02:00
|
|
|
*outpkg = nullptr;
|
2016-02-19 19:26:35 +01:00
|
|
|
*path = spec.substr( 2, std::string::npos );
|
|
|
|
|
}
|
|
|
|
|
else // ':pkgname:pkgfile' -- a packaged file
|
|
|
|
|
{
|
|
|
|
|
std::string::size_type second_colon = spec.find( ':', 2 );
|
|
|
|
|
if ( second_colon != std::string::npos )
|
|
|
|
|
{
|
|
|
|
|
std::string pkgname = spec.substr( 1, second_colon - 1 );
|
|
|
|
|
std::string pkgfile = spec.substr( second_colon + 1, std::string::npos );
|
|
|
|
|
Package* dstpkg = find_package( pkgname );
|
2018-10-09 16:36:35 +02:00
|
|
|
if ( dstpkg != nullptr )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
|
|
|
|
*outpkg = dstpkg;
|
|
|
|
|
*path = pkgfile;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2024-01-12 06:51:44 +01:00
|
|
|
ERROR_PRINTLN( "Unable to find package '{}'", pkgname );
|
2016-02-19 19:26:35 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2024-01-12 06:51:44 +01:00
|
|
|
ERROR_PRINTLN( "Poorly formed packagefile descriptor: '{}'", spec );
|
2016-02-19 19:26:35 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
*outpkg = inpkg;
|
|
|
|
|
*path = spec;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void load_packaged_cfgs( const char* cfgname, const char* taglist,
|
|
|
|
|
void ( *loadentry )( const Package*, Clib::ConfigElem& ) )
|
|
|
|
|
{
|
|
|
|
|
for ( const auto& pkg : systemstate.packages )
|
|
|
|
|
{
|
|
|
|
|
std::string filename = GetPackageCfgPath( pkg, cfgname );
|
|
|
|
|
if ( Clib::FileExists( filename.c_str() ) )
|
|
|
|
|
{
|
|
|
|
|
Clib::ConfigFile cf( filename.c_str(), taglist );
|
|
|
|
|
Clib::ConfigElem elem;
|
|
|
|
|
|
|
|
|
|
while ( cf.read( elem ) )
|
|
|
|
|
{
|
|
|
|
|
loadentry( pkg, elem );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void load_all_cfgs( const char* cfgname, const char* taglist,
|
|
|
|
|
void ( *loadentry )( const Package*, Clib::ConfigElem& ) )
|
|
|
|
|
{
|
|
|
|
|
std::string filename = std::string( "config/" ) + cfgname;
|
|
|
|
|
if ( Clib::FileExists( filename ) )
|
|
|
|
|
{
|
|
|
|
|
Clib::ConfigFile cf( filename.c_str(), taglist );
|
|
|
|
|
Clib::ConfigElem elem;
|
|
|
|
|
|
|
|
|
|
while ( cf.read( elem ) )
|
|
|
|
|
{
|
2018-10-09 16:36:35 +02:00
|
|
|
loadentry( nullptr, elem );
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
load_packaged_cfgs( cfgname, taglist, loadentry );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2016-12-15 16:59:58 +01:00
|
|
|
std::string GetPackageCfgPath( const Package* pkg, const std::string& filename )
|
2016-02-19 19:26:35 +01:00
|
|
|
{
|
|
|
|
|
std::string filepath;
|
2018-10-09 16:36:35 +02:00
|
|
|
if ( pkg == nullptr )
|
2016-02-19 19:26:35 +01:00
|
|
|
{ // If no package is sent, assume pol/config/file.xxx
|
|
|
|
|
filepath = "config/" + filename;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{ // ** Going to save this feature for 097 **
|
|
|
|
|
// With packages, first try for /pkg/config/file.xxx
|
|
|
|
|
filepath = pkg->dir() + "config/" + filename;
|
|
|
|
|
if ( !Clib::FileExists( filepath ) )
|
|
|
|
|
{
|
|
|
|
|
// Lastly, assume /pkg/file.xxx
|
|
|
|
|
filepath = pkg->dir() + filename;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return filepath;
|
|
|
|
|
}
|
2018-12-23 13:55:47 +01:00
|
|
|
} // namespace Plib
|
|
|
|
|
} // namespace Pol
|