14#include <zypp-core/zyppng/io/Process>
15#include <zypp-core/zyppng/pipelines/MTry>
16#include <zypp-core/zyppng/pipelines/Algorithm>
17#include <zypp-media/MediaException>
18#include <zypp-media/ng/Provide>
19#include <zypp-media/ng/ProvideSpec>
24#include <zypp/ng/Context>
33#undef ZYPP_BASE_LOGGER_LOGGROUP
34#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::repomanager"
42 template <
class Executor,
class OpType>
43 struct ProbeRepoLogic :
public LogicBase<Executor, OpType>
51 using MediaHandle =
typename ProvideType::MediaHandle;
58 ,
_path(std::move(path))
63 const auto &url =
_medium.baseUrl();
64 MIL <<
"going to probe the repo type at " << url <<
" (" <<
_path <<
")" << std::endl;
68 MIL <<
"Probed type NONE (not exists) at " << url <<
" (" <<
_path <<
")" << std::endl;
93 std::rethrow_exception (err);
98 DBG <<
"problem checking for repodata/repomd.xml file" << std::endl;
113 std::rethrow_exception (err);
118 DBG <<
"problem checking for content file" << std::endl;
130 const auto &url =
medium.baseUrl();
133 if ( ! ( url.schemeIsDownloading() || url.schemeIsPlugin() ) ) {
137 MIL <<
"Probed type RPMPLAINDIR at " << url <<
" (" <<
_path <<
")" << std::endl;
145 MIL <<
"Probed type NONE at " << url <<
" (" <<
_path <<
")" << std::endl;
161 return std::move(file)
179 template <
class RefreshContextRef>
185 return probeRepoType( ctx, std::forward<decltype(mediaHandle)>(mediaHandle), path );
212 template <
class ZyppContextRef>
218 DBG <<
"reading repo file " <<
repoFileUrl <<
", local path: " <<
local.file() << std::endl;
236 template<
typename Executor,
class OpType>
237 struct CheckIfToRefreshMetadataLogic :
public LogicBase<Executor, OpType> {
243 using ZyppContextRefType =
typename RefreshContextRefType::element_type::ContextRefType;
244 using ZyppContextType =
typename RefreshContextRefType::element_type::ContextType;
245 using ProvideType =
typename ZyppContextType::ProvideType;
247 using MediaHandle =
typename ProvideType::MediaHandle;
258 MIL <<
"Going to CheckIfToRefreshMetadata" << std::endl;
264 MIL <<
"Check if to refresh repo " <<
_refreshContext->repoInfo().alias() <<
" at " <<
_medium.baseUrl() <<
" (" << info.type() <<
")" << std::endl;
274 MIL <<
"No cached metadata, going to refresh" << std::endl;
278 if (
_medium.baseUrl().schemeIsVolatile() ) {
279 MIL <<
"Never refresh CD/DVD" << std::endl;
284 MIL <<
"Forced refresh!" << std::endl;
288 if (
_medium.baseUrl().schemeIsLocal() ) {
307 WAR <<
"Repository '" << info.alias() <<
"' was refreshed in the future!" << std::endl;
310 MIL <<
"Repository '" << info.alias()
311 <<
"' has been refreshed less than repo.refresh.delay ("
313 <<
") minutes ago. Advising to skip refresh" << std::endl;
319 MIL <<
"Metadata and solv cache don't match. Check data on server..." << std::endl;
338 MIL <<
"repo has not changed" << std::endl;
343 MIL <<
"repo has changed, going to refresh" << std::endl;
372 template<
typename Executor,
class OpType>
373 struct RefreshMetadataLogic :
public LogicBase<Executor, OpType>{
380 using ZyppContextRefType =
typename RefreshContextRefType::element_type::ContextRefType;
381 using ZyppContextType =
typename RefreshContextRefType::element_type::ContextType;
382 using ProvideType =
typename ZyppContextType::ProvideType;
383 using MediaHandle =
typename ProvideType::MediaHandle;
388 using DlContextRefType = std::shared_ptr<DlContextType>;
403 MIL <<
"RefreshCheckStatus returned: " << status << std::endl;
410 MIL <<
"Going to refresh metadata from " <<
_medium.baseUrl() << std::endl;
421 _refreshContext->setProbedType( repokind );
423 info.setProbedType( repokind );
442 |
and_then([
this]( DlContextRefType && ) {
475 template <
class RefreshContextRef>
488 "Valid metadata not found at specified URLs",
489 refCtx->repoInfo().baseUrlsSize() ) }
504 ERR <<
"Trying another url..." << std::endl;
510 helper->rexception.remember(
e );
513 helper->rexception.addHistory(
e.asUserString() );
522 return refCtx->repoInfo().baseUrls()
527 ERR <<
"No more urls..." << std::endl;
547 template <
typename ZyppCtxRef>
struct Repo2SolvOp;
555 MIL <<
"Starting repo2solv for repo " << repo.
alias () << std::endl;
556 auto me = std::make_shared<Repo2SolvOp<ContextRef>>();
557 me->_repo = std::move(repo);
562 std::vector<const char *>
argsIn;
563 argsIn.reserve ( args.size() );
564 std::for_each( args.begin (), args.end(), [&](
const std::string &
s ) { argsIn.push_back(s.data()); });
565 argsIn.push_back (
nullptr);
567 if (!
me->_proc->start(
argsIn.data() )) {
580 void procFinished(
int ret ) {
582 while (
_proc->canReadLine() )
623 template<
typename Executor,
class OpType>
624 struct BuildCacheLogic :
public LogicBase<Executor, OpType>{
627 using ZyppContextRefType =
typename RefreshContextRefType::element_type::ContextRefType;
628 using ZyppContextType =
typename RefreshContextRefType::element_type::ContextType;
629 using ProvideType =
typename ZyppContextType::ProvideType;
630 using MediaHandle =
typename ProvideType::MediaHandle;
652 const auto &options =
_refCtx->repoManagerOptions();
655 auto ex = ZYPP_EXCPT_PTR( zypp::Exception (zypp::str::form( _(
"Can't create %s"), options.repoCachePath.c_str()) ) );
656 return expected<RepoStatus>::error( std::move(ex) );
676 const auto &info =
_refCtx->repoInfo();
677 if (
_refCtx->repoManager()->isCached( info ) )
679 MIL << info.alias() <<
" is already cached." << std::endl;
686 MIL << info.alias() <<
" cache is up to date with metadata." << std::endl;
700 MIL << info.alias() <<
" cache rebuild is forced" << std::endl;
711 auto r =
_refCtx->repoManager()->cleanCache(info);
716 MIL << info.alias() <<
" building cache..." << info.type() << std::endl;
755 const auto &info =
_refCtx->repoInfo();
759 case zypp::repo::RepoType::RPMMD_e :
760 case zypp::repo::RepoType::YAST2_e :
761 case zypp::repo::RepoType::RPMPLAINDIR_e :
764 zypp::ManagedFile guard( solvfile, zypp::filesystem::unlink );
766 zypp::ExternalProgram::Arguments cmd;
767 cmd.push_back( zypp::PathInfo(
"/usr/bin/repo2solv" ).isFile() ?
"repo2solv" :
"repo2solv.sh" );
769 cmd.push_back(
"-o" );
770 cmd.push_back( solvfile.asString() );
771 cmd.push_back(
"-X" );
774 if ( repokind == zypp::repo::RepoType::RPMPLAINDIR )
777 cmd.push_back(
"-R" );
779 std::optional<zypp::Pathname> localPath = forPlainDirs.has_value() ? forPlainDirs->localPath() : zypp::Pathname();
781 return makeReadyResult( expected<void>::error( ZYPP_EXCPT_PTR( zypp::repo::RepoException( zypp::str::Format(_(
"Failed to cache repo %1%")) % _refCtx->repoInfo() ))) );
784 cmd.push_back( (*localPath / info.path().absolutename()).c_str() );
787 cmd.push_back( _productdatapath.asString() );
789 return Repo2SolvOp<ZyppContextRefType>::run( info, std::move(cmd) )
790 | and_then( [this, guard = std::move(guard), solvfile = std::move(solvfile) ]() mutable {
792 guard.resetDispose();
793 return mtry( zypp::sat::updateSolvFileIndex, solvfile );
808 MIL <<
"Commit cache.." << std::endl;
813 |
or_else ( [
this]( std::exception_ptr
e ) {
825 |
and_then( [
this]( MediaHandle handle ) {
854 template<
typename Executor,
class OpType>
855 struct AddRepoLogic :
public LogicBase<Executor, OpType>{
873 MIL <<
"Try adding repo " <<
_info << std::endl;
883 DBG <<
"unknown repository type, probing" << std::endl;
902 MIL <<
"done" << std::endl;
905 |
or_else( [
this]( std::exception_ptr
e) {
907 MIL <<
"done" << std::endl;
931 template<
typename Executor,
class OpType>
932 struct AddReposLogic :
public LogicBase<Executor, OpType>{
948 |
and_then([
this]( std::list<RepoInfo> repos ) {
950 for ( std::list<RepoInfo>::const_iterator
it = repos.begin();
957 if ( (*it).alias() == (*kit).alias() )
959 ERR <<
"To be added repo " << (*it).alias() <<
" conflicts with existing repo " << (*kit).alias() << std::endl;
979 MIL <<
"Saving " << repos.size() <<
" repo" << ( repos.size() ?
"s" :
"" ) <<
" in " <<
repofile << std::endl;
981 std::ofstream file(
repofile.c_str());
988 for ( std::list<RepoInfo>::iterator
it = repos.begin();
992 MIL <<
"Saving " << (*it).alias() << std::endl;
1000 it->dumpAsIniOn(file);
1002 it->setMetadataPath( *rawCachePath );
1009 MIL <<
"done" << std::endl;
1035 template<
typename Executor,
class OpType>
1036 struct RefreshGeoIpLogic :
public LogicBase<Executor, OpType>{
1042 using ZyppContextType =
typename ZyppContextRefType::element_type;
1043 using ProvideType =
typename ZyppContextType::ProvideType;
1044 using MediaHandle =
typename ProvideType::MediaHandle;
1045 using ProvideRes =
typename ProvideType::Res;
1057 if ( !
_zyppCtx->config().geoipEnabled() ) {
1058 MIL <<
"GeoIp disabled via ZConfig, not refreshing the GeoIP information." << std::endl;
1062 std::vector<std::string>
hosts;
1063 for (
const auto &baseUrl :
_urls ) {
1064 const auto &host = baseUrl.getHost();
1065 if (
zypp::any_of(
_zyppCtx->config().geoipHostnames(), [&host](
const auto &
elem ){ return ( zypp::str::compareCI( host, elem ) == 0 ); } ) ) {
1066 hosts.push_back( host );
1071 if (
hosts.empty() ) {
1072 MIL <<
"No configured geoip URL found, not updating geoip data" << std::endl;
1079 MIL <<
"Unable to create cache directory for GeoIP." << std::endl;
1084 MIL <<
"No access rights for the GeoIP cache directory." << std::endl;
1094 auto age = std::chrono::system_clock::now() - std::chrono::system_clock::from_time_t(
pi.mtime() );
1095 if (
age < std::chrono::hours(24) )
1098 MIL <<
"Removing GeoIP file for " <<
entry.name <<
" since it's older than 24hrs." << std::endl;
1103 auto firstOfCb = [
this]( std::string hostname ) {
1107 MIL <<
"Skipping GeoIP request for " << hostname <<
" since a valid cache entry exists." << std::endl;
1111 MIL <<
"Query GeoIP for " << hostname << std::endl;
1120 MIL <<
"Ignoring invalid GeoIP hostname: " << hostname << std::endl;
1127 |
inspect_err( [hostname](
const std::exception_ptr& ){
MIL <<
"Failed to query GeoIP from hostname: " << hostname << std::endl; } )
1134 out.open(
fName.asString(), std::ios_base::trunc );
1135 if ( out.is_open() ) {
1136 out << host << std::endl;
1138 MIL <<
"Failed to create/open GeoIP cache file " <<
fName << std::endl;
1145 if (
reader.seekToNode( 1,
"host" ) ) {
1146 const auto &
str =
reader.nodeText().asString();
1154 MIL <<
"Storing geoIP redirection: " << hostname <<
" -> " <<
str << std::endl;
1159 MIL <<
"No host entry or empty file returned for GeoIP, remembering for 24hrs" << std::endl;
1163 MIL <<
"Empty or invalid GeoIP file, not requesting again for 24hrs" << std::endl;
1172 return std::move(
hosts)
1177 MIL <<
"Successfully queried GeoIP data." << std::endl;
1181 MIL <<
"Failed to query GeoIP data." << std::endl;
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
reference value() const
Reference to the Tp object.
void resetDispose()
Set no dispose function.
std::string asString() const
static Date now()
Return the current time.
Base class for Exception.
void remember(const Exception &old_r)
Store an other Exception as history.
Execute a program and give access to its io An object of this class encapsulates the execution of an ...
std::vector< std::string > Arguments
Writing the zypp history file.
void addRepository(const RepoInfo &repo)
Log a newly added repository.
What is known about a repository.
Url url() const
Pars pro toto: The first repository url.
Pathname path() const
Repository path.
Track changing files or directories.
std::string asString() const
Returns a default string representation of the Url object.
std::string getPathName(EEncoding eflag=zypp::url::E_DECODED) const
Returns the path name from the URL.
void setHost(const std::string &host)
Set the hostname or IP in the URL authority.
void setScheme(const std::string &scheme)
Set the scheme name in the URL.
Wrapper class for stat/lstat.
bool isExist() const
Return whether valid stat info exists.
std::string basename() const
Return the last component of this path.
Repository already exists and some unique attribute can't be duplicated.
Exception for repository handling.
std::string alias() const
unique identifier for this source.
thrown when it was impossible to determine this repo type.
xmlTextReader based interface to iterate xml streams.
SignalProxy< void()> sigReadyRead()
SignalProxy< void(int)> sigFinished()
static ProgressObserverRef makeSubTask(ProgressObserverRef parentProgress, float weight=1.0, const std::string &label=std::string(), int steps=100)
static void setup(ProgressObserverRef progress, const std::string &label=std::string(), int steps=100)
static void finish(ProgressObserverRef progress, ProgressObserver::FinishResult result=ProgressObserver::Success)
A ProvideRes object is a reference counted ownership of a resource in the cache provided by a Provide...
The RepoManager class Provides knowledge and methods to maintain repo settings and metadata for a giv...
expected< RepoStatus > cacheStatus(const RepoInfo &info) const
static expected< void > touchIndexFile(const RepoInfo &info, const RepoManagerOptions &options)
static zypp::repo::RepoType probeCache(const zypp::Pathname &path_r)
Probe Metadata in a local cache directory.
static expected< RepoStatus > metadataStatus(const RepoInfo &info, const RepoManagerOptions &options)
static expected success(ConsParams &&...params)
static expected error(ConsParams &&...params)
#define ZYPP_ENABLE_LOGIC_BASE(Executor, OpType)
typename conditional< B, T, F >::type conditional_t
String related utilities and Regular expression matching.
RefreshCheckStatus
Possibly return state of RepoManager::checkIfToRefreshMetadata function.
@ REFRESH_NEEDED
refresh is needed
@ REPO_UP_TO_DATE
repository not changed
@ REPO_CHECK_DELAYED
refresh is delayed due to settings
@ RefreshIfNeededIgnoreDelay
bool provide(const Pathname &delta_r, const Pathname &new_r, const Progress &report_r)
Apply a binary delta to on-disk data to re-create a new rpm.
int unlink(const Pathname &path)
Like 'unlink'.
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
int dirForEachExt(const Pathname &dir_r, const function< bool(const Pathname &, const DirEntry &)> &fnc_r)
Simiar to.
void updateSolvFileIndex(const Pathname &solvfile_r)
Create solv file content digest for zypper bash completion.
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
std::list< RepoInfo > readRepoFile(const Url &repo_file)
Parses repo_file and returns a list of RepoInfo objects corresponding to repositories found within th...
bool any_of(const Container &c, Fnc &&cb)
AsyncOpRef< expected< repo::AsyncDownloadContextRef > > download(repo::AsyncDownloadContextRef dl, ProvideMediaHandle mediaHandle, ProgressObserverRef progressObserver=nullptr)
AsyncOpRef< expected< zypp::RepoStatus > > repoStatus(repo::AsyncDownloadContextRef dl, ProvideMediaHandle mediaHandle)
AsyncOpRef< expected< zypp::repo::RepoType > > probeRepoType(ContextRef ctx, AsyncLazyMediaHandle medium, zypp::Pathname path, std::optional< zypp::Pathname > targetPath)
AsyncOpRef< expected< RepoInfo > > addRepository(AsyncRepoManagerRef mgr, RepoInfo info, ProgressObserverRef myProgress)
AsyncOpRef< expected< repo::RefreshCheckStatus > > checkIfToRefreshMetadata(repo::AsyncRefreshContextRef refCtx, LazyMediaHandle< Provide > medium, ProgressObserverRef progressObserver)
AsyncOpRef< expected< std::list< RepoInfo > > > readRepoFile(ContextRef ctx, zypp::Url repoFileUrl)
AsyncOpRef< expected< void > > refreshGeoIPData(ContextRef ctx, RepoInfo::url_set urls)
AsyncOpRef< expected< void > > addRepositories(AsyncRepoManagerRef mgr, zypp::Url url, ProgressObserverRef myProgress)
AsyncOpRef< expected< repo::AsyncRefreshContextRef > > refreshMetadata(repo::AsyncRefreshContextRef refCtx, LazyMediaHandle< Provide > medium, ProgressObserverRef progressObserver)
AsyncOpRef< expected< repo::AsyncRefreshContextRef > > buildCache(repo::AsyncRefreshContextRef refCtx, zypp::RepoManagerFlags::CacheBuildPolicy policy, ProgressObserverRef progressObserver)
auto or_else(Fun &&function)
auto and_then(Fun &&function)
auto mtry(Fun &&function)
Exp mtry(F &&f, Args &&...args)
expected< void > assert_urls(const RepoInfo &info)
std::conditional_t< isAsync, AsyncOpRef< T >, T > makeReadyResult(T &&result)
typename remove_smart_ptr< T >::type remove_smart_ptr_t
static expected< std::decay_t< Type >, Err > make_expected_success(Type &&t)
expected< zypp::Pathname > rawcache_path_for_repoinfo(const RepoManagerOptions &opt, const RepoInfo &info)
Calculates the raw cache path for a repository, this is usually /var/cache/zypp/alias.
expected< void > assert_alias(const RepoInfo &info)
ResultType or_else(const expected< T, E > &exp, Function &&f)
ResultType and_then(const expected< T, E > &exp, Function &&f)
auto firstOf(Transformation &&transformFunc, DefaultType &&def, Predicate &&predicate=detail::ContinueUntilValidPredicate())
RepoManagerRef< SyncContextRef > SyncRepoManagerRef
expected< zypp::Pathname > solv_path_for_repoinfo(const RepoManagerOptions &opt, const RepoInfo &info)
Calculates the solv cache path for a repository.
expected< std::list< RepoInfo > > repositories_in_file(const zypp::Pathname &file)
Reads RepoInfo's from a repo file.
RepoManagerRef< ContextRef > AsyncRepoManagerRef
expected< zypp::Pathname > packagescache_path_for_repoinfo(const RepoManagerOptions &opt, const RepoInfo &info)
Calculates the packages cache path for a repository.
expected< zypp::Pathname > rawproductdata_path_for_repoinfo(const RepoManagerOptions &opt, const RepoInfo &info)
Calculates the raw product metadata path for a repository, this is inside the raw cache dir,...
expected< T, E > inspect(expected< T, E > exp, Function &&f)
expected< T, E > inspect_err(expected< T, E > exp, Function &&f)
RepoManagerPtrType _repoMgrRef
ZyppContextRefType _zyppContext
std::optional< zypp::Pathname > _targetPath
zypp::Pathname _productdatapath
RefreshContextRefType _refreshContext
zypp::Pathname _geoIPCache
zypp::repo::RepoException _error
zypp::RepoManagerFlags::CacheBuildPolicy _policy
ProgressObserverRef _progress
RefreshContextRefType _refCtx
ZyppContextRefType _zyppCtx
ProgressObserverRef _myProgress
zypp::Pathname _mediarootpath
ProgressObserverRef _progressObserver
Listentry returned by readdir.
Repository type enumeration.
static const RepoType YAST2
static const RepoType RPMMD
static const RepoType NONE
static const RepoType RPMPLAINDIR
Functor replacing repository variables.
Convenient building of std::string via std::ostringstream Basically a std::ostringstream autoconverti...
auto makeReadyResult(T &&res)
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
#define ZYPP_EXCPT_PTR(EXCPT)
Drops a logline and returns Exception as a std::exception_ptr.
#define ZYPP_FWD_CURRENT_EXCPT()
Drops a logline and returns the current Exception as a std::exception_ptr.
#define PL_(MSG1, MSG2, N)