42 template <
class Executor,
class OpType>
43 struct ProbeRepoLogic :
public LogicBase<Executor, OpType>
51 using MediaHandle =
typename ProvideType::MediaHandle;
58 ,
_path(std::move(path))
62 MaybeAsyncRef<expected<zypp::repo::RepoType>> execute( ) {
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;
78 std::shared_ptr<ProvideType> providerRef =
_zyppContext->provider();
83 return providerRef->attachMediaIfNeeded(
_medium )
84 |
and_then([
this, providerRef]( MediaHandle medium )
88 |
and_then( maybeCopyResultToDest(
"repodata/repomd.xml") )
91 |
or_else( [
this, providerRef, medium]( std::exception_ptr err ) {
93 std::rethrow_exception (err);
98 DBG <<
"problem checking for repodata/repomd.xml file" << std::endl;
106 |
and_then( maybeCopyResultToDest(
"content") )
110 |
or_else( [
this, medium]( std::exception_ptr err ) {
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;
157 auto maybeCopyResultToDest ( std::string &&subPath ) {
160 MIL <<
"Target path is set, copying " << file.file() <<
" to " << *
_targetPath/subPath << std::endl;
161 return std::move(file)
179 template <
class RefreshContextRef>
180 auto probeRepoLogic( RefreshContextRef ctx,
RepoInfo repo, std::optional<zypp::Pathname> targetPath)
184 |
and_then( [ctx, path = repo.
path() ](
auto &&mediaHandle ) {
185 return probeRepoType( ctx, std::forward<decltype(mediaHandle)>(mediaHandle), path );
202 return probeRepoLogic( std::move(ctx), std::move(repo), std::move(targetPath) );
207 return probeRepoLogic( std::move(ctx), std::move(repo), std::move(targetPath) );
212 template <
class ZyppContextRef>
213 auto readRepoFileLogic( ZyppContextRef ctx,
zypp::Url repoFileUrl )
217 |
and_then([repoFileUrl](
auto local ){
218 DBG <<
"reading repo file " << repoFileUrl <<
", local path: " << local.file() << std::endl;
226 return readRepoFileLogic( std::move(ctx), std::move(repoFileUrl) );
231 return readRepoFileLogic( std::move(ctx), std::move(repoFileUrl) );
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;
250 CheckIfToRefreshMetadataLogic( RefreshContextRefType refCtx,
LazyMediaHandle &&medium, ProgressObserverRef progressObserver )
256 MaybeAsyncRef<expected<repo::RefreshCheckStatus>> execute( ) {
258 MIL <<
"Going to CheckIfToRefreshMetadata" << std::endl;
264 MIL <<
"Check if to refresh repo " <<
_refreshContext->repoInfo().alias() <<
" at " <<
_medium.baseUrl() <<
" (" << info.type() <<
")" << std::endl;
273 if ( oldstatus.
empty() ) {
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() ) {
301 if ( oldstatus == *cachestatus ) {
304 const auto refDelay =
_refreshContext->zyppContext()->config().repo_refresh_delay();
305 if ( diff < refDelay ) {
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;
337 if ( oldstatus == newstatus ) {
338 MIL <<
"repo has not changed" << std::endl;
343 MIL <<
"repo has changed, going to refresh" << std::endl;
344 MIL <<
"Old status: " << oldstatus <<
" New Status: " << newstatus << 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>;
390 RefreshMetadataLogic( RefreshContextRefType refCtx,
LazyMediaHandle &&medium, ProgressObserverRef progressObserver )
396 MaybeAsyncRef<expected<RefreshContextRefType>> execute() {
403 MIL <<
"RefreshCheckStatus returned: " << status << std::endl;
410 MIL <<
"Going to refresh metadata from " <<
_medium.baseUrl() << std::endl;
420 if ( info.type() != repokind ) {
421 _refreshContext->setProbedType( repokind );
423 info.setProbedType( repokind );
437 dlContext->setPluginRepoverification(
_refreshContext->pluginRepoverification() );
442 |
and_then([
this]( DlContextRefType && ) {
475 template <
class RefreshContextRef>
476 auto refreshMetadataLogic( RefreshContextRef refCtx, ProgressObserverRef progressObserver)
485 auto helper = std::make_shared<ExHelper>( ExHelper{
488 "Valid metadata not found at specified URLs",
489 refCtx->repoInfo().baseUrlsSize() ) }
493 auto refreshPipeline = [ refCtx, progressObserver ](
zypp::Url url ){
495 |
and_then( [ refCtx , progressObserver](
auto mediaHandle )
mutable {
return refreshMetadata ( std::move(refCtx), std::move(mediaHandle), progressObserver ); } );
504 ERR <<
"Trying another url..." << std::endl;
509 if ( helper->isFirst ) {
510 helper->rexception.remember( e );
511 helper->isFirst =
false;
522 return refCtx->repoInfo().baseUrls()
527 ERR <<
"No more urls..." << std::endl;
537 return refreshMetadataLogic ( std::move(refCtx), std::move(progressObserver) );
541 return refreshMetadataLogic ( std::move(refCtx), std::move(progressObserver) );
547 template <
typename ZyppCtxRef>
struct Repo2SolvOp;
550 struct Repo2SolvOp<ContextRef> :
public AsyncOp<expected<void>>
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() )) {
575 const std::string &line = data.
asString();
580 void procFinished(
int ret ) {
582 while (
_proc->canReadLine() )
601 struct Repo2SolvOp<SyncContextRef>
605 std::string errdetail;
608 WAR <<
" " << output;
612 int ret = prog.
close();
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;
641 MaybeAsyncRef<expected<RefreshContextRefType>> execute() {
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) );
663 if ( raw_metadata_status.
empty() )
675 bool needs_cleaning =
false;
676 const auto &info =
_refCtx->repoInfo();
677 if (
_refCtx->repoManager()->isCached( info ) )
679 MIL << info.alias() <<
" is already cached." << std::endl;
684 if ( *cache_status == raw_metadata_status )
686 MIL << info.alias() <<
" cache is up to date with metadata." << std::endl;
700 MIL << info.alias() <<
" cache rebuild is forced" << std::endl;
704 needs_cleaning =
true;
711 auto r =
_refCtx->repoManager()->cleanCache(info);
716 MIL << info.alias() <<
" building cache..." << info.type() << std::endl;
740 switch ( repokind.
toEnum() )
750 MIL <<
"repo type is " << repokind << std::endl;
752 return mountIfRequired( repokind, info )
753 |
and_then([
this, repokind, solvfile = std::move(solvfile) ]( std::optional<MediaHandle> forPlainDirs )
mutable {
755 const auto &info =
_refCtx->repoInfo();
757 switch ( repokind.
toEnum() )
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 );
802 |
and_then([
this, raw_metadata_status](){
804 return _refCtx->repoManager()->setCacheStatus(
_refCtx->repoInfo(), raw_metadata_status );
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>{
861 AddRepoLogic( RepoManagerPtrType &&repoMgrRef,
RepoInfo &&info, ProgressObserverRef &&myProgress )
867 MaybeAsyncRef<expected<RepoInfo> > execute() {
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>{
937 AddReposLogic( RepoManagerPtrType &&repoMgrRef,
zypp::Url &&url, ProgressObserverRef &&myProgress )
943 MaybeAsyncRef<expected<void>> execute() {
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);
1001 it->setFilepath(repofile);
1002 it->setMetadataPath( *rawCachePath );
1003 it->setPackagesPath( *pckCachePath );
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;
1053 MaybeAsyncRef<expected<void>> execute() {
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; } )
1132 constexpr auto writeHostToFile = [](
const zypp::Pathname &fName,
const std::string &host ){
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;
1142 std::string geoipMirror;
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;
1166 writeHostToFile(
_geoIPCache / hostname, geoipMirror );
1172 return std::move(hosts)
1174 | [](
bool foundGeoIP ){
1177 MIL <<
"Successfully queried GeoIP data." << std::endl;
1181 MIL <<
"Failed to query GeoIP data." << std::endl;