libzypp  17.38.7
repomanagerwf.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
9 #include "repomanagerwf.h"
10 
11 #include "zypp/parser/xml/Reader.h"
12 
13 #include <zypp-core/ManagedFile.h>
15 #include <zypp-core/ng/io/Process>
16 #include <zypp-core/ng/pipelines/MTry>
17 #include <zypp-core/ng/pipelines/Algorithm>
18 #include <zypp-media/MediaException>
19 #include <zypp/ng/media/Provide>
20 #include <zypp-media/ng/ProvideSpec>
21 
23 #include <zypp/HistoryLog.h>
24 #include <zypp/base/Algorithm.h>
25 #include <zypp/ng/Context>
26 
28 #include <zypp/ng/repomanager.h>
29 #include <zypp/ZConfig.h>
30 
31 #include <utility>
32 #include <fstream>
33 
34 #undef ZYPP_BASE_LOGGER_LOGGROUP
35 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::repomanager"
36 
38 
39  using namespace zyppng::operators;
40 
41  namespace {
42 
43  struct ProbeRepoLogic
44  {
45  public:
46  using MediaHandle = typename Provide::MediaHandle;
48  using ProvideRes = typename Provide::Res;
49 
50 
51  private:
56  auto maybeCopyResultToDest ( std::string &&subPath ) {
57  return [this, subPath = std::move(subPath)]( ProvideRes file ) -> MaybeAwaitable<expected<void>> {
58  if ( _targetPath ) {
59  MIL << "Target path is set, copying " << file.file() << " to " << *_targetPath/subPath << std::endl;
60  return std::move(file)
61  | Provide::copyResultToDest( _zyppContext->provider(), *_targetPath/subPath)
62  | and_then([]( zypp::ManagedFile file ){ file.resetDispose(); return expected<void>::success(); } );
63  }
64  return makeReadyTask( expected<void>::success() );
65  };
66  }
67 
68  public:
69 
70  ProbeRepoLogic(ContextRef zyppCtx, LazyMediaHandle &&medium, zypp::Pathname &&path, std::optional<zypp::Pathname> &&targetPath )
71  : _zyppContext(std::move(zyppCtx))
72  , _medium(std::move(medium))
73  , _path(std::move(path))
74  , _targetPath(std::move(targetPath))
75  {}
76 
77  MaybeAwaitable<expected<zypp::repo::RepoType>> execute( ) {
78  const auto &url = _medium.baseUrl();
79  MIL << "going to probe the repo type at " << url << " (" << _path << ")" << std::endl;
80 
81  if ( url.getScheme() == "dir" && ! zypp::PathInfo( url.getPathName()/_path ).isDir() ) {
82  // Handle non existing local directory in advance
83  MIL << "Probed type NONE (not exists) at " << url << " (" << _path << ")" << std::endl;
85  }
86 
87  // prepare exception to be thrown if the type could not be determined
88  // due to a media exception. We can't throw right away, because of some
89  // problems with proxy servers returning an incorrect error
90  // on ftp file-not-found(bnc #335906). Instead we'll check another types
91  // before throwing.
92 
93  std::shared_ptr<Provide> providerRef = _zyppContext->provider();
94 
95  // TranslatorExplanation '%s' is an URL
96  _error = zypp::repo::RepoException (zypp::str::form( _("Error trying to read from '%s'"), url.asString().c_str() ));
97 
98  return providerRef->attachMediaIfNeeded( _medium )
99  | and_then([this, providerRef]( MediaHandle medium )
100  {
101  // first try rpmmd
102  return providerRef->provide( medium, _path/"repodata/repomd.xml", ProvideFileSpec().setCheckExistsOnly( !_targetPath.has_value() ).setMirrorsAllowed(false) )
103  | and_then( maybeCopyResultToDest("repodata/repomd.xml") )
105  // try susetags if rpmmd fails and remember the error
106  | or_else( [this, providerRef, medium]( std::exception_ptr err ) {
107  try {
108  std::rethrow_exception (err);
109  } catch ( const zypp::media::MediaFileNotFoundException &e ) {
110  // do nothing
111  ;
112  } catch( const zypp::media::MediaException &e ) {
113  DBG << "problem checking for repodata/repomd.xml file" << std::endl;
114  _error.remember ( err );
115  _gotMediaError = true;
116  } catch( ... ) {
117  // any other error, we give up
119  }
120  return providerRef->provide( medium, _path/"content", ProvideFileSpec().setCheckExistsOnly( !_targetPath.has_value() ).setMirrorsAllowed(false) )
121  | and_then( maybeCopyResultToDest("content") )
123  })
124  // no rpmmd and no susetags!
125  | or_else( [this, medium]( std::exception_ptr err ) {
126 
127  try {
128  std::rethrow_exception (err);
129  } catch ( const zypp::media::MediaFileNotFoundException &e ) {
130  // do nothing
131  ;
132  } catch( const zypp::media::MediaException &e ) {
133  DBG << "problem checking for content file" << std::endl;
134  _error.remember ( err );
135  _gotMediaError = true;
136  } catch( zypp::Exception &e ) {
137  _error.remember(e);
138  // any other error, we give up
140  } catch(...) {
141  // any other error, we give up
143  }
144 
145  const auto &url = medium.baseUrl();
146 
147  // if it is a non-downloading URL denoting a directory (bsc#1191286: and no plugin)
148  if ( ! ( url.schemeIsDownloading() || url.schemeIsPlugin() ) ) {
149 
150  if ( medium.localPath() && zypp::PathInfo(medium.localPath().value()/_path).isDir() ) {
151  // allow empty dirs for now
152  MIL << "Probed type RPMPLAINDIR at " << url << " (" << _path << ")" << std::endl;
154  }
155  }
156 
157  if( _gotMediaError )
159 
160  MIL << "Probed type NONE at " << url << " (" << _path << ")" << std::endl;
162  })
163  ;
164  });
165  }
166 
167  private:
168  ContextRef _zyppContext;
169  LazyMediaHandle _medium;
171  std::optional<zypp::Pathname> _targetPath;
172 
174  bool _gotMediaError = false;
175  };
176 
177  auto probeRepoLogic( ContextRef ctx, RepoInfo repo, std::optional<zypp::Pathname> targetPath)
178  {
179  using namespace zyppng::operators;
180  return ctx->provider()->prepareMedia( repo.url(), zyppng::ProvideMediaSpec() )
181  | and_then( [ctx, path = repo.path() ]( auto &&mediaHandle ) {
182  return probeRepoType( ctx, std::forward<decltype(mediaHandle)>(mediaHandle), path );
183  });
184  }
185 
186  }
187 
188  MaybeAwaitable<expected<zypp::repo::RepoType> > probeRepoType( ContextRef ctx, Provide::LazyMediaHandle medium, zypp::Pathname path, std::optional<zypp::Pathname> targetPath)
189  {
190  ProbeRepoLogic impl( std::move(ctx), std::move(medium), std::move(path), std::move(targetPath) );
191  zypp_co_return zypp_co_await(impl.execute());
192  }
193 
194  MaybeAwaitable<expected<zypp::repo::RepoType> > probeRepoType( ContextRef ctx, RepoInfo repo, std::optional<zypp::Pathname> targetPath )
195  {
196  if constexpr ( ZYPP_IS_ASYNC )
197  return probeRepoLogic( std::move(ctx), std::move(repo), std::move(targetPath) );
198  else
199  return probeRepoLogic( std::move(ctx), std::move(repo), std::move(targetPath) );
200  }
201 
202 
203  namespace {
204  auto readRepoFileLogic( ContextRef ctx, zypp::Url repoFileUrl )
205  {
206  using namespace zyppng::operators;
207  return ctx->provider()->provide( repoFileUrl, ProvideFileSpec() )
208  | and_then([repoFileUrl]( auto local ){
209  DBG << "reading repo file " << repoFileUrl << ", local path: " << local.file() << std::endl;
210  return repositories_in_file( local.file() );
211  });
212  }
213  }
214 
215  MaybeAwaitable<expected<std::list<RepoInfo> > > readRepoFile(ContextRef ctx, zypp::Url repoFileUrl)
216  {
217  return readRepoFileLogic( std::move(ctx), std::move(repoFileUrl) );
218  }
219 
220  namespace {
221 
222  struct CheckIfToRefreshMetadataLogic {
223  public:
224  using LazyMediaHandle = typename Provide::LazyMediaHandle;
225  using MediaHandle = typename Provide::MediaHandle;
226  using ProvideRes = typename Provide::Res;
227 
228  CheckIfToRefreshMetadataLogic( repo::RefreshContextRef refCtx, LazyMediaHandle &&medium, ProgressObserverRef progressObserver )
229  : _refreshContext(std::move(refCtx))
230  , _progress(std::move( progressObserver ))
231  , _medium(std::move( medium ))
232  {}
233 
234  MaybeAwaitable<expected<repo::RefreshCheckStatus>> execute( ) {
235 
236  MIL << "Going to CheckIfToRefreshMetadata" << std::endl;
237 
238  return assert_alias( _refreshContext->repoInfo() )
239  | and_then( [this] {
240 
241  const auto &info = _refreshContext->repoInfo();
242  MIL << "Check if to refresh repo " << _refreshContext->repoInfo().alias() << " at " << _medium.baseUrl() << " (" << info.type() << ")" << std::endl;
243 
244  // first check old (cached) metadata
245  return zyppng::RepoManager::metadataStatus( info, _refreshContext->repoManagerOptions() );
246  })
247  | and_then( [this](zypp::RepoStatus oldstatus) {
248 
249  const auto &info = _refreshContext->repoInfo();
250 
251  if ( oldstatus.empty() ) {
252  MIL << "No cached metadata, going to refresh" << std::endl;
254  }
255 
256  if ( _medium.baseUrl().schemeIsVolatile() ) {
257  MIL << "Never refresh CD/DVD" << std::endl;
259  }
260 
262  MIL << "Forced refresh!" << std::endl;
264  }
265 
266  if ( _medium.baseUrl().schemeIsLocal() ) {
268  }
269 
270  // Check whether repo.refresh.delay applies...
272  {
273  // bsc#1174016: Prerequisite to skipping the refresh is that metadata
274  // and solv cache status match. They will not, if the repos URL was
275  // changed e.g. due to changed repovars.
276  expected<zypp::RepoStatus> cachestatus = zyppng::RepoManager::cacheStatus( info, _refreshContext->repoManagerOptions() );
277  if ( !cachestatus ) return makeReadyTask( expected<repo::RefreshCheckStatus>::error(cachestatus.error()) );
278 
279  if ( oldstatus == *cachestatus ) {
280  // difference in seconds
281  double diff = ::difftime( (zypp::Date::ValueType)zypp::Date::now(), (zypp::Date::ValueType)oldstatus.timestamp() ) / 60;
282  const auto refDelay = _refreshContext->zyppContext()->config().repo_refresh_delay();
283  if ( diff < refDelay ) {
284  if ( diff < 0 ) {
285  WAR << "Repository '" << info.alias() << "' was refreshed in the future!" << std::endl;
286  }
287  else {
288  MIL << "Repository '" << info.alias()
289  << "' has been refreshed less than repo.refresh.delay ("
290  << refDelay
291  << ") minutes ago. Advising to skip refresh" << std::endl;
293  }
294  }
295  }
296  else {
297  MIL << "Metadata and solv cache don't match. Check data on server..." << std::endl;
298  }
299  }
300 
301  return info.type() | [this]( zypp::repo::RepoType repokind ) {
302  // if unknown: probe it
303  if ( repokind == zypp::repo::RepoType::NONE )
304  return probeRepoType( _refreshContext->zyppContext(), _medium, _refreshContext->repoInfo().path()/*, _refreshContext->targetDir()*/ );
305  return makeReadyTask( expected<zypp::repo::RepoType>::success(repokind) );
306  } | and_then([this, oldstatus]( zypp::repo::RepoType repokind ) {
307 
308  // make sure to remember the repo type
309  _refreshContext->repoInfo().setProbedType( repokind );
310 
311  auto dlContext = std::make_shared<repo::DownloadContext>( _refreshContext->zyppContext(), _refreshContext->repoInfo(), _refreshContext->targetDir() );
312  return RepoDownloaderWorkflow::repoStatus ( dlContext, _medium )
313  | and_then( [this, dlContext, oldstatus]( zypp::RepoStatus newstatus ){
314  // check status
315  if ( oldstatus == newstatus ) {
316  MIL << "repo has not changed" << std::endl;
317  return zyppng::RepoManager::touchIndexFile( _refreshContext->repoInfo(), _refreshContext->repoManagerOptions() )
319  }
320  else { // includes newstatus.empty() if e.g. repo format changed
321  MIL << "repo has changed, going to refresh" << std::endl;
322  MIL << "Old status: " << oldstatus << " New Status: " << newstatus << std::endl;
324  }
325  });
326  });
327  });
328  }
329 
330  protected:
331  repo::RefreshContextRef _refreshContext;
332  ProgressObserverRef _progress;
333  LazyMediaHandle _medium;
334  };
335  }
336 
337  MaybeAwaitable<expected<repo::RefreshCheckStatus> > checkIfToRefreshMetadata(repo::RefreshContextRef refCtx, LazyMediaHandle<Provide> medium, ProgressObserverRef progressObserver)
338  {
339  CheckIfToRefreshMetadataLogic impl( std::move(refCtx), std::move(medium), std::move(progressObserver) );
340  zypp_co_return zypp_co_await(impl.execute());
341  }
342 
343 
344  namespace {
345 
346  struct RefreshMetadataLogic {
347 
348  public:
349  using MediaHandle = typename Provide::MediaHandle;
350  using LazyMediaHandle = typename Provide::LazyMediaHandle;
351  using ProvideRes = typename Provide::Res;
352 
353  using DlContextType = repo::DownloadContext;
354  using DlContextRefType = std::shared_ptr<DlContextType>;
355 
356  RefreshMetadataLogic( repo::RefreshContextRef refCtx, LazyMediaHandle &&medium, ProgressObserverRef progressObserver )
357  : _refreshContext(std::move(refCtx))
358  , _progress ( std::move( progressObserver ) )
359  , _medium ( std::move( medium ) )
360  { }
361 
362  MaybeAwaitable<expected<repo::RefreshContextRef>> execute() {
363 
364  return assert_alias( _refreshContext->repoInfo() )
365  | and_then( [this](){ return assert_urls( _refreshContext->repoInfo() ); })
367  | and_then( [this]( repo::RefreshCheckStatus status ){
368 
369  MIL << "RefreshCheckStatus returned: " << status << std::endl;
370 
371  // check whether to refresh metadata
372  // if the check fails for this url, it throws, so another url will be checked
374  return makeReadyTask ( expected<repo::RefreshContextRef>::success( std::move(_refreshContext) ) );
375 
376  // if REFRESH_NEEDED but we don't have the permission to write the cache, stop here.
377  if ( zypp::IamNotRoot() && not zypp::PathInfo(_refreshContext->rawCachePath().dirname()).userMayWX() ) {
378  WAR << "No permision to write cache " << zypp::PathInfo(_refreshContext->rawCachePath().dirname()) << std::endl;
379  auto exception = ZYPP_EXCPT_PTR( zypp::repo::RepoNoPermissionException( _refreshContext->repoInfo() ) );
380  return makeReadyTask( expected<repo::RefreshContextRef>::error( std::move(exception) ) );
381  }
382 
383  MIL << "Going to refresh metadata from " << _medium.baseUrl() << std::endl;
384 
385  // bsc#1048315: Always re-probe in case of repo format change.
386  // TODO: Would be sufficient to verify the type and re-probe
387  // if verification failed (or type is RepoType::NONE)
388  return probeRepoType ( _refreshContext->zyppContext(), _medium, _refreshContext->repoInfo().path() /*, _refreshContext->targetDir()*/ )
389  | and_then([this]( zypp::repo::RepoType repokind ) {
390 
391  auto &info = _refreshContext->repoInfo();
392 
393  if ( info.type() != repokind ) {
394  _refreshContext->setProbedType( repokind );
395  // Adjust the probed type in RepoInfo
396  info.setProbedType( repokind ); // lazy init!
397  }
398 
399  // no need to continue with an unknown type
400  if ( repokind.toEnum() == zypp::repo::RepoType::NONE_e )
402 
403  const zypp::Pathname &mediarootpath = _refreshContext->rawCachePath();
404  if( zypp::filesystem::assert_dir(mediarootpath) ) {
405  auto exception = ZYPP_EXCPT_PTR (zypp::Exception(zypp::str::form( _("Can't create %s"), mediarootpath.c_str() )));
406  return makeReadyTask( expected<DlContextRefType>::error( std::move(exception) ));
407  }
408 
409  auto dlContext = std::make_shared<DlContextType>( _refreshContext->zyppContext(), _refreshContext->repoInfo(), _refreshContext->targetDir() );
410  dlContext->setPluginRepoverification( _refreshContext->pluginRepoverification() );
411 
412  return RepoDownloaderWorkflow::download ( dlContext, _medium, _progress );
413 
414  })
415  | and_then([this]( DlContextRefType && ) {
416 
417  // ok we have the metadata, now exchange
418  // the contents
419  _refreshContext->saveToRawCache();
420  // if ( ! isTmpRepo( info ) )
421  // reposManip(); // remember to trigger appdata refresh
422 
423  // we are done.
425  });
426  });
427  }
428 
429  repo::RefreshContextRef _refreshContext;
430  ProgressObserverRef _progress;
431  LazyMediaHandle _medium;
433 
434  };
435  }
436 
437  MaybeAwaitable<expected<repo::RefreshContextRef> > refreshMetadata( repo::RefreshContextRef refCtx, LazyMediaHandle<Provide> medium, ProgressObserverRef progressObserver )
438  {
439  RefreshMetadataLogic impl( std::move(refCtx), std::move(medium), std::move(progressObserver));
440  zypp_co_return zypp_co_await(impl.execute());
441  }
442 
443  namespace {
444  auto refreshMetadataLogic( repo::RefreshContextRef refCtx, ProgressObserverRef progressObserver)
445  {
446  // small shared helper struct to pass around the exception and to remember that we tried the first URL
447  struct ExHelper
448  {
449  // We will throw this later if no URL checks out fine.
450  // The first exception will be remembered, further exceptions just added to the history.
451  ExHelper( const RepoInfo & info_r )
452  : rexception { info_r, _("Failed to retrieve new repository metadata.") }
453  {}
454  void remember( const zypp::Exception & old_r )
455  {
456  if ( rexception.historyEmpty() ) {
457  rexception.remember( old_r );
458  } else {
459  rexception.addHistory( old_r.asUserString() );
460  }
461  }
462  zypp::repo::RepoException rexception;
463  };
464 
465  auto helper = std::make_shared<ExHelper>( ExHelper{ refCtx->repoInfo() } );
466 
467  // the actual logic pipeline, attaches the medium and tries to refresh from it
468  auto refreshPipeline = [ refCtx, progressObserver ]( zypp::MirroredOrigin origin ){
469  return refCtx->zyppContext()->provider()->prepareMedia( origin, zyppng::ProvideMediaSpec() )
470  | and_then( [ refCtx , progressObserver]( auto mediaHandle ) mutable { return refreshMetadata ( std::move(refCtx), std::move(mediaHandle), progressObserver ); } );
471  };
472 
473  // predicate that accepts only valid results, and in addition collects all errors in rexception
474  auto predicate = [ info = refCtx->repoInfo(), helper ]( const expected<repo::RefreshContextRef> &res ) -> bool{
475  if ( !res ) {
476  try {
477  ZYPP_RETHROW( res.error() );
478  } catch ( const zypp::repo::RepoNoPermissionException &e ) {
479  // We deliver the Exception caught here (no permission to write chache) and give up.
480  ERR << "Giving up..." << std::endl;
481  helper->remember( e );
482  return true; // stop processing
483  } catch ( const zypp::Exception &e ) {
484  ERR << "Trying another url..." << std::endl;
485  helper->remember( e );
486  }
487  return false;
488  }
489  return true;
490  };
491 
492 
493  // now go over the url groups until we find one that works
494  return refCtx->repoInfo().repoOrigins()
495  | firstOf( std::move(refreshPipeline), expected<repo::RefreshContextRef>::error( std::make_exception_ptr(NotFoundException()) ), std::move(predicate) )
496  | [helper]( expected<repo::RefreshContextRef> result ) {
497  if ( !result ) {
498  // none of the URLs worked
499  ERR << "No more urls..." << std::endl;
500  return expected<repo::RefreshContextRef>::error( ZYPP_EXCPT_PTR(helper->rexception) );
501  }
502  // we are done.
503  return result;
504  };
505  }
506  }
507 
508  MaybeAwaitable<expected<repo::RefreshContextRef> > refreshMetadata( repo::RefreshContextRef refCtx, ProgressObserverRef progressObserver) {
509  return refreshMetadataLogic ( std::move(refCtx), std::move(progressObserver) );
510  }
511 
512 
513  namespace {
514 
515 #ifdef ZYPP_ENABLE_ASYNC
516 
517  Task<expected<void>> repo2Solv( zypp::RepoInfo repo, zypp::ExternalProgram::Arguments args )
518  {
519  struct Repo2SolvOp
520  {
521  Repo2SolvOp( zypp::RepoInfo repo, zypp::ExternalProgram::Arguments args )
522  : _repo( std::move(repo) )
523  , _args( std::move(args)) { }
524 
525  bool await_ready() const noexcept { return false; }
526 
527  expected<void> await_resume() {
528  // Return the value stored by the callback
529  return *_result;
530  }
531 
532  void await_suspend( std::coroutine_handle<> cont )
533  {
534  MIL << "Starting repo2solv for repo " << _repo.alias () << std::endl;
535  _cont = std::move(cont);
536  _proc = Process::create();
537  _proc->connect( &Process::sigFinished, *me, &Repo2SolvOp::procFinished );
538  _proc->connect( &Process::sigReadyRead, *me, &Repo2SolvOp::readyRead );
539 
540  std::vector<const char *> argsIn;
541  argsIn.reserve ( args.size() );
542  std::for_each( args.begin (), args.end(), [&]( const std::string &s ) { argsIn.push_back(s.data()); });
543  argsIn.push_back (nullptr);
544  me->_proc->setOutputChannelMode ( Process::Merged );
545  if (!me->_proc->start( argsIn.data() )) {
546  setReady( expected<void>::error(ZYPP_EXCPT_PTR(zypp::repo::RepoException ( me->_repo, _("Failed to cache repo ( unable to start repo2solv ).") ))) );
547  }
548  }
549 
550  void readyRead (){
551  const ByteArray &data = _proc->readLine();
552  const std::string &line = data.asString();
553  WAR << " " << line;
554  _errdetail += line;
555  }
556 
557  void procFinished( int ret ) {
558 
559  while ( _proc->canReadLine() )
560  readyRead();
561 
562  if ( ret != 0 ) {
563  zypp::repo::RepoException ex( _repo, zypp::str::form( _("Failed to cache repo (%d)."), ret ));
564  ex.addHistory( zypp::str::Str() << _proc->executedCommand() << std::endl << _errdetail << _proc->execError() ); // errdetail lines are NL-terminaled!
565  setReady( expected<void>::error(ZYPP_EXCPT_PTR(ex)) );
566  return;
567  }
568  setReady( expected<void>::success() );
569  }
570 
571  void setReady( expected<void> &&val ) {
572  _result = std::move(val);
573  _cont.resume();
574  }
575 
576  private:
577  ProcessRef _proc;
578  zypp::RepoInfo _repo;
580  std::string _errdetail;
581  std::coroutine_handle<> _cont;
582  std::optional<expected<void>> _result;
583  };
584 
585 
586  MIL << "Starting repo2solv for repo " << repo.alias () << std::endl;
587  co_return co_await Repo2SolvOp{ std::move(repo), std::move(args) };
588  }
589 #else
590  static expected<void> repo2Solv( zypp::RepoInfo repo, zypp::ExternalProgram::Arguments args ) {
592  std::string errdetail;
593 
594  for ( std::string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) {
595  WAR << " " << output;
596  errdetail += output;
597  }
598 
599  int ret = prog.close();
600  if ( ret != 0 )
601  {
602  zypp::repo::RepoException ex(repo, zypp::str::form( _("Failed to cache repo (%d)."), ret ));
603  ex.addHistory( zypp::str::Str() << prog.command() << std::endl << errdetail << prog.execError() ); // errdetail lines are NL-terminaled!
605  }
606  return expected<void>::success();
607  }
608 #endif
609 
610  struct BuildCacheLogic {
611 
612  BuildCacheLogic( repo::RefreshContextRef &&refCtx, zypp::RepoManagerFlags::CacheBuildPolicy policy, ProgressObserverRef &&progressObserver )
613  : _refCtx( std::move(refCtx) )
614  , _policy( policy )
615  , _progressObserver( std::move(progressObserver) )
616  {}
617 
618  MaybeAwaitable<expected<repo::RefreshContextRef>> execute() {
619 
620  ProgressObserver::setup ( _progressObserver, zypp::str::form(_("Building repository '%s' cache"), _refCtx->repoInfo().label().c_str()), 100 );
621 
622  return assert_alias(_refCtx->repoInfo() )
623  | and_then( mtry( [this] {
624  _mediarootpath = rawcache_path_for_repoinfo( _refCtx->repoManagerOptions(), _refCtx->repoInfo() ).unwrap();
625  _productdatapath = rawproductdata_path_for_repoinfo( _refCtx->repoManagerOptions(), _refCtx->repoInfo() ).unwrap();
626  }))
627  | and_then( [this] {
628 
629  const auto &options = _refCtx->repoManagerOptions();
630 
631  if( zypp::filesystem::assert_dir( options.repoCachePath ) ) {
632  auto ex = ZYPP_EXCPT_PTR( zypp::Exception (zypp::str::form( _("Can't create %s"), options.repoCachePath.c_str()) ) );
633  return expected<RepoStatus>::error( std::move(ex) );
634  }
635 
636  return RepoManager::metadataStatus( _refCtx->repoInfo(), options );
637 
638  }) | and_then( [this](RepoStatus raw_metadata_status ) {
639 
640  if ( raw_metadata_status.empty() )
641  {
642  // If there is no raw cache at this point, we refresh the raw metadata.
643  // This may happen if no autorefresh is configured and no explicit
644  // refresh was called.
645  //
646  zypp::Pathname mediarootParent { _mediarootpath.dirname() };
647 
648  if ( zypp::filesystem::assert_dir( mediarootParent ) == 0
649  && ( zypp::IamRoot() || zypp::PathInfo(mediarootParent).userMayWX() ) ) {
650 
652  | and_then([this]( auto /*refCtx*/) { return RepoManager::metadataStatus( _refCtx->repoInfo(), _refCtx->repoManagerOptions() ); } );
653 
654  } else {
655  // Non-root user is not allowed to write the raw cache.
656  WAR << "No permission to write raw cache " << mediarootParent << std::endl;
657  auto exception = ZYPP_EXCPT_PTR( zypp::repo::RepoNoPermissionException( _refCtx->repoInfo() ) );
658  return makeReadyTask( expected<zypp::RepoStatus>::error( std::move(exception) ) );
659  }
660  }
661  return makeReadyTask( make_expected_success (raw_metadata_status) );
662 
663  }) | and_then( [this]( RepoStatus raw_metadata_status ) {
664 
665  bool needs_cleaning = false;
666  const auto &info = _refCtx->repoInfo();
667  if ( _refCtx->repoManager()->isCached( info ) )
668  {
669  MIL << info.alias() << " is already cached." << std::endl;
670  expected<RepoStatus> cache_status = RepoManager::cacheStatus( info, _refCtx->repoManagerOptions() );
671  if ( !cache_status )
672  return makeReadyTask( expected<void>::error(cache_status.error()) );
673 
674  if ( *cache_status == raw_metadata_status )
675  {
676  MIL << info.alias() << " cache is up to date with metadata." << std::endl;
678  {
679  // On the fly add missing solv.idx files for bash completion.
680  return makeReadyTask(
681  solv_path_for_repoinfo( _refCtx->repoManagerOptions(), info)
682  | and_then([]( zypp::Pathname base ){
683  if ( ! zypp::PathInfo(base/"solv.idx").isExist() )
684  return mtry( zypp::sat::updateSolvFileIndex, base/"solv" );
685  return expected<void>::success ();
686  })
687  );
688  }
689  else {
690  MIL << info.alias() << " cache rebuild is forced" << std::endl;
691  }
692  }
693 
694  needs_cleaning = true;
695  }
696 
698 
699  if (needs_cleaning)
700  {
701  auto r = _refCtx->repoManager()->cleanCache(info);
702  if ( !r )
703  return makeReadyTask( expected<void>::error(r.error()) );
704  }
705 
706  MIL << info.alias() << " building cache..." << info.type() << std::endl;
707 
708  expected<zypp::Pathname> base = solv_path_for_repoinfo( _refCtx->repoManagerOptions(), info);
709  if ( !base )
710  return makeReadyTask( expected<void>::error(base.error()) );
711 
712  if( zypp::filesystem::assert_dir(*base) )
713  {
714  zypp::Exception ex(zypp::str::form( _("Can't create %s"), base->c_str()) );
715  return makeReadyTask( expected<void>::error(ZYPP_EXCPT_PTR(ex)) );
716  }
717 
718  if( zypp::IamNotRoot() && not zypp::PathInfo(*base).userMayW() )
719  {
720  zypp::Exception ex(zypp::str::form( _("Can't create cache at %s - no writing permissions."), base->c_str()) );
721  return makeReadyTask( expected<void>::error(ZYPP_EXCPT_PTR(ex)) );
722  }
723 
724  zypp::Pathname solvfile = *base / "solv";
725 
726  // do we have type?
727  zypp::repo::RepoType repokind = info.type();
728 
729  // if the type is unknown, try probing.
730  switch ( repokind.toEnum() )
731  {
733  // unknown, probe the local metadata
735  break;
736  default:
737  break;
738  }
739 
740  MIL << "repo type is " << repokind << std::endl;
741 
742  return mountIfRequired( repokind, info )
743  | and_then([this, repokind, solvfile = std::move(solvfile) ]( std::optional<ProvideMediaHandle> forPlainDirs ) mutable {
744 
745  const auto &info = _refCtx->repoInfo();
746 
747  switch ( repokind.toEnum() )
748  {
752  {
753  // Take care we unlink the solvfile on error
754  zypp::ManagedFile guard( solvfile, zypp::filesystem::unlink );
755 
757 #ifdef ZYPP_REPO2SOLV_PATH
758  cmd.push_back( ZYPP_REPO2SOLV_PATH );
759 #else
760  cmd.push_back( zypp::PathInfo( "/usr/bin/repo2solv" ).isFile() ? "repo2solv" : "repo2solv.sh" );
761 #endif
762  // repo2solv expects -o as 1st arg!
763  cmd.push_back( "-o" );
764  cmd.push_back( solvfile.asString() );
765  cmd.push_back( "-X" ); // autogenerate pattern from pattern-package
766  // bsc#1104415: no more application support // cmd.push_back( "-A" ); // autogenerate application pseudo packages
767 
768  if ( repokind == zypp::repo::RepoType::RPMPLAINDIR )
769  {
770  // recusive for plaindir as 2nd arg!
771  cmd.push_back( "-R" );
772 
773  std::optional<zypp::Pathname> localPath = forPlainDirs.has_value() ? forPlainDirs->localPath() : zypp::Pathname();
774  if ( !localPath )
775  return makeReadyTask( expected<void>::error( ZYPP_EXCPT_PTR( zypp::repo::RepoException( zypp::str::Format(_("Failed to cache repo %1%")) % _refCtx->repoInfo() ))) );
776 
777  // FIXME this does only work for dir: URLs
778  cmd.push_back( (*localPath / info.path().absolutename()).c_str() );
779  }
780  else
781  cmd.push_back( _productdatapath.asString() );
782 
783  return repo2Solv( info, std::move(cmd) )
784  | and_then( [guard = std::move(guard), solvfile = std::move(solvfile) ]() mutable {
785  // We keep it.
786  guard.resetDispose();
787  return mtry( zypp::sat::updateSolvFileIndex, solvfile ); // content digest for zypper bash completion
788  });
789  }
790  break;
791  default:
792  return makeReadyTask( expected<void>::error( ZYPP_EXCPT_PTR(zypp::repo::RepoUnknownTypeException( info, _("Unhandled repository type") )) ) );
793  break;
794  }
795  })
796  | and_then([this, raw_metadata_status](){
797  // update timestamp and checksum
798  return _refCtx->repoManager()->setCacheStatus( _refCtx->repoInfo(), raw_metadata_status );
799  });
800  })
801  | and_then( [this](){
802  MIL << "Commit cache.." << std::endl;
804  return make_expected_success ( _refCtx );
805 
806  })
807  | or_else ( [this]( std::exception_ptr e ) {
810  });
811  }
812 
813  private:
814  MaybeAwaitable<expected<std::optional<ProvideMediaHandle>>> mountIfRequired ( zypp::repo::RepoType repokind, zypp::RepoInfo info ) {
815  if ( repokind != zypp::repo::RepoType::RPMPLAINDIR )
816  return makeReadyTask( make_expected_success( std::optional<ProvideMediaHandle>() ));
817 
818  return _refCtx->zyppContext()->provider()->attachMedia( info.url(), ProvideMediaSpec() )
819  | and_then( []( ProvideMediaHandle handle ) {
820  return makeReadyTask( make_expected_success( std::optional<ProvideMediaHandle>( std::move(handle)) ));
821  });
822  }
823 
824  private:
825  repo::RefreshContextRef _refCtx;
827  ProgressObserverRef _progressObserver;
828 
831  };
832  }
833 
834  MaybeAwaitable<expected<repo::RefreshContextRef> > buildCache(repo::RefreshContextRef refCtx, zypp::RepoManagerFlags::CacheBuildPolicy policy, ProgressObserverRef progressObserver)
835  {
836  BuildCacheLogic impl( std::move(refCtx), policy, std::move(progressObserver));
837  zypp_co_return zypp_co_await ( impl.execute () );
838  }
839 
840 
841  // Add repository logic
842  namespace {
843 
844  struct AddRepoLogic {
845 
846  AddRepoLogic( RepoManagerRef &&repoMgrRef, RepoInfo &&info, ProgressObserverRef &&myProgress, const zypp::TriBool & forcedProbe )
847  : _repoMgrRef( std::move(repoMgrRef) )
848  , _doProbeUrl( zypp::indeterminate(forcedProbe) ? _repoMgrRef->options().probe : bool(forcedProbe) )
849  , _info( std::move(info) )
850  , _myProgress ( std::move(myProgress) )
851  {}
852 
853  MaybeAwaitable<expected<RepoInfo> > execute() {
854  using namespace zyppng::operators;
855 
856  return assert_alias(_info)
857  | and_then([this]( ) {
858 
859  MIL << "Try adding repo " << _info << std::endl;
860  ProgressObserver::setup( _myProgress, zypp::str::form(_("Adding repository '%s'"), _info.label().c_str()) );
862 
863  if ( _repoMgrRef->repos().find(_info) != _repoMgrRef->repos().end() )
865 
866  // check the first url for now
867  if ( _doProbeUrl )
868  {
869  DBG << "unknown repository type, probing" << std::endl;
870  return assert_urls(_info)
871  | and_then([this]{ return probeRepoType( _repoMgrRef->zyppContext(), _info ); })
872  | and_then([this]( zypp::repo::RepoType probedtype ) {
873 
874  if ( probedtype == zypp::repo::RepoType::NONE )
876 
877  RepoInfo tosave = _info;
878  tosave.setType(probedtype);
879  return make_expected_success(tosave);
880  });
881  }
882  return makeReadyTask( make_expected_success(_info) );
883  })
885  | and_then( [this]( RepoInfo tosave ){ return _repoMgrRef->addProbedRepository( tosave, tosave.type() ); })
886  | and_then( [this]( RepoInfo updated ) {
888  MIL << "done" << std::endl;
889  return expected<RepoInfo>::success( updated );
890  })
891  | or_else( [this]( std::exception_ptr e) {
893  MIL << "done" << std::endl;
894  return expected<RepoInfo>::error(e);
895  })
896  ;
897  }
898 
899  RepoManagerRef _repoMgrRef;
900  bool _doProbeUrl;
902  ProgressObserverRef _myProgress;
903  };
904  };
905 
906  MaybeAwaitable<expected<RepoInfo> > addRepository( RepoManagerRef mgr, RepoInfo info, ProgressObserverRef myProgress, const zypp::TriBool & forcedProbe )
907  {
908  AddRepoLogic impl( std::move(mgr), std::move(info), std::move(myProgress), forcedProbe );
909  zypp_co_return zypp_co_await ( impl.execute () );
910  }
911 
912  namespace {
913 
914  struct AddReposLogic {
915  AddReposLogic( RepoManagerRef &&repoMgrRef, zypp::Url &&url, ProgressObserverRef &&myProgress )
916  : _repoMgrRef( std::move(repoMgrRef) )
917  , _url( std::move(url) )
918  , _myProgress ( std::move(myProgress) )
919  {}
920 
921  MaybeAwaitable<expected<void>> execute() {
922  using namespace zyppng::operators;
923 
925  | and_then([this]( zypp::Url repoFileUrl ) { return readRepoFile( _repoMgrRef->zyppContext(), std::move(repoFileUrl) ); } )
926  | and_then([this]( std::list<RepoInfo> repos ) {
927 
928  for ( std::list<RepoInfo>::const_iterator it = repos.begin();
929  it != repos.end();
930  ++it )
931  {
932  // look if the alias is in the known repos.
933  for_ ( kit, _repoMgrRef->repoBegin(), _repoMgrRef->repoEnd() )
934  {
935  if ( (*it).alias() == (*kit).alias() )
936  {
937  ERR << "To be added repo " << (*it).alias() << " conflicts with existing repo " << (*kit).alias() << std::endl;
939  }
940  }
941  }
942 
943  std::string filename = zypp::Pathname(_url.getPathName()).basename();
944  if ( filename == zypp::Pathname() )
945  {
946  // TranslatorExplanation '%s' is an URL
947  return expected<void>::error(ZYPP_EXCPT_PTR(zypp::repo::RepoException(zypp::str::form( _("Invalid repo file name at '%s'"), _url.asString().c_str() ))));
948  }
949 
950  const auto &options = _repoMgrRef->options();
951 
952  // assert the directory exists
953  zypp::filesystem::assert_dir( options.knownReposPath );
954 
955  zypp::Pathname repofile = _repoMgrRef->generateNonExistingName( options.knownReposPath, filename );
956  // now we have a filename that does not exists
957  MIL << "Saving " << repos.size() << " repo" << ( repos.size() ? "s" : "" ) << " in " << repofile << std::endl;
958 
959  std::ofstream file(repofile.c_str());
960  if (!file)
961  {
962  // TranslatorExplanation '%s' is a filename
963  return expected<void>::error(ZYPP_EXCPT_PTR( zypp::Exception(zypp::str::form( _("Can't open file '%s' for writing."), repofile.c_str() ))));
964  }
965 
966  for ( std::list<RepoInfo>::iterator it = repos.begin();
967  it != repos.end();
968  ++it )
969  {
970  MIL << "Saving " << (*it).alias() << std::endl;
971 
972  const auto &rawCachePath = rawcache_path_for_repoinfo( options, *it );
973  if ( !rawCachePath ) return expected<void>::error(rawCachePath.error());
974 
975  const auto &pckCachePath = packagescache_path_for_repoinfo( options, *it ) ;
976  if ( !pckCachePath ) return expected<void>::error(pckCachePath.error());
977 
978  it->dumpAsIniOn(file);
979  it->setFilepath(repofile);
980  it->setMetadataPath( *rawCachePath );
981  it->setPackagesPath( *pckCachePath );
982  _repoMgrRef->reposManip().insert(*it);
983 
984  zypp::HistoryLog( _repoMgrRef->options().rootDir).addRepository(*it);
985  }
986 
987  MIL << "done" << std::endl;
988  return expected<void>::success();
989  });
990  }
991 
992  private:
993  RepoManagerRef _repoMgrRef;
995  ProgressObserverRef _myProgress;
996  };
997 
998  }
999 
1000  MaybeAwaitable<expected<void>> addRepositories( RepoManagerRef mgr, zypp::Url url, ProgressObserverRef myProgress )
1001  {
1002  AddReposLogic impl( std::move(mgr), std::move(url), std::move(myProgress) );
1003  zypp_co_return zypp_co_await ( impl.execute () );
1004  }
1005 
1006 
1007  namespace {
1008 
1009  struct RefreshGeoIpLogic {
1010 
1011  using MediaHandle = typename Provide::MediaHandle;
1012  using ProvideRes = typename Provide::Res;
1013 
1014 
1015  RefreshGeoIpLogic( ContextRef &&zyppCtx, zypp::MirroredOriginSet &&origins )
1016  : _zyppCtx( std::move(zyppCtx) )
1017  , _origins( std::move(origins) )
1018  { }
1019 
1020  MaybeAwaitable<expected<void>> execute() {
1021 
1022  using namespace zyppng::operators;
1023 
1024  if ( !_zyppCtx->config().geoipEnabled() ) {
1025  MIL << "GeoIp disabled via ZConfig, not refreshing the GeoIP information." << std::endl;
1026  return makeReadyTask(expected<void>::success());
1027  }
1028 
1029  std::vector<std::string> hosts;
1030  for ( const zypp::MirroredOrigin &origin : _origins ){
1031  if ( !origin.schemeIsDownloading () )
1032  continue;
1033 
1034  for ( const auto &originEndpoint : origin ) {
1035  const auto &host = originEndpoint.url().getHost();
1036  if ( zypp::any_of( _zyppCtx->config().geoipHostnames(), [&host]( const auto &elem ){ return ( zypp::str::compareCI( host, elem ) == 0 ); } ) ) {
1037  hosts.push_back( host );
1038  break;
1039  }
1040  }
1041  }
1042 
1043  if ( hosts.empty() ) {
1044  MIL << "No configured geoip URL found, not updating geoip data" << std::endl;
1045  return makeReadyTask(expected<void>::success());
1046  }
1047 
1048  _geoIPCache = _zyppCtx->config().geoipCachePath();
1049 
1050  if ( zypp::filesystem::assert_dir( _geoIPCache ) != 0 ) {
1051  MIL << "Unable to create cache directory for GeoIP." << std::endl;
1052  return makeReadyTask(expected<void>::success());
1053  }
1054 
1055  if ( zypp::IamNotRoot() && not zypp::PathInfo(_geoIPCache).userMayRWX() ) {
1056  MIL << "No access rights for the GeoIP cache directory." << std::endl;
1057  return makeReadyTask(expected<void>::success());
1058  }
1059 
1060  // remove all older cache entries
1062  if ( entry.type != zypp::filesystem::FT_FILE )
1063  return true;
1064 
1065  zypp::PathInfo pi( dir/entry.name );
1066  auto age = std::chrono::system_clock::now() - std::chrono::system_clock::from_time_t( pi.mtime() );
1067  if ( age < std::chrono::hours(24) )
1068  return true;
1069 
1070  MIL << "Removing GeoIP file for " << entry.name << " since it's older than 24hrs." << std::endl;
1071  zypp::filesystem::unlink( dir/entry.name );
1072  return true;
1073  });
1074 
1075  auto firstOfCb = [this]( std::string hostname ) {
1076 
1077  // do not query files that are still there
1078  if ( zypp::PathInfo( _geoIPCache / hostname ).isExist() ) {
1079  MIL << "Skipping GeoIP request for " << hostname << " since a valid cache entry exists." << std::endl;
1080  return makeReadyTask(false);
1081  }
1082 
1083  MIL << "Query GeoIP for " << hostname << std::endl;
1084 
1085  zypp::Url url;
1086  try {
1087  url.setHost(hostname);
1088  url.setScheme("https");
1089 
1090  } catch(const zypp::Exception &e ) {
1091  ZYPP_CAUGHT(e);
1092  MIL << "Ignoring invalid GeoIP hostname: " << hostname << std::endl;
1093  return makeReadyTask(false);
1094  }
1095 
1096  // always https ,but attaching makes things easier
1097  return _zyppCtx->provider()->attachMedia( url, ProvideMediaSpec() )
1098  | and_then( [this]( MediaHandle provideHdl ) { return _zyppCtx->provider()->provide( provideHdl, "/geoip", ProvideFileSpec() ); })
1099  | inspect_err( [hostname]( const std::exception_ptr& ){ MIL << "Failed to query GeoIP from hostname: " << hostname << std::endl; } )
1100  | and_then( [hostname, this]( ProvideRes provideRes ) {
1101 
1102  // here we got something from the server, we will stop after this hostname and mark the process as success()
1103 
1104  constexpr auto writeHostToFile = []( const zypp::Pathname &fName, const std::string &host ){
1105  std::ofstream out;
1106  out.open( fName.asString(), std::ios_base::trunc );
1107  if ( out.is_open() ) {
1108  out << host << std::endl;
1109  } else {
1110  MIL << "Failed to create/open GeoIP cache file " << fName << std::endl;
1111  }
1112  };
1113 
1114  std::string geoipMirror;
1115  try {
1116  zypp::xml::Reader reader( provideRes.file() );
1117  if ( reader.seekToNode( 1, "host" ) ) {
1118  const auto &str = reader.nodeText().asString();
1119 
1120  // make a dummy URL to ensure the hostname is valid
1121  zypp::Url testUrl;
1122  testUrl.setHost(str);
1123  testUrl.setScheme("https");
1124 
1125  if ( testUrl.isValid() ) {
1126  MIL << "Storing geoIP redirection: " << hostname << " -> " << str << std::endl;
1127  geoipMirror = str;
1128  }
1129 
1130  } else {
1131  MIL << "No host entry or empty file returned for GeoIP, remembering for 24hrs" << std::endl;
1132  }
1133  } catch ( const zypp::Exception &e ) {
1134  ZYPP_CAUGHT(e);
1135  MIL << "Empty or invalid GeoIP file, not requesting again for 24hrs" << std::endl;
1136  }
1137 
1138  writeHostToFile( _geoIPCache / hostname, geoipMirror );
1139  return expected<void>::success(); // need to return a expected<> due to and_then requirements
1140  })
1141  | []( expected<void> res ) { return res.is_valid(); };
1142  };
1143 
1144  return std::move(hosts)
1145  | firstOf( std::move(firstOfCb), false, zyppng::detail::ContinueUntilValidPredicate() )
1146  | []( bool foundGeoIP ) {
1147 
1148  if ( foundGeoIP ) {
1149  MIL << "Successfully queried GeoIP data." << std::endl;
1150  return expected<void>::success ();
1151  }
1152 
1153  MIL << "Failed to query GeoIP data." << std::endl;
1154  return expected<void>::error( std::make_exception_ptr( zypp::Exception("No valid geoIP url found" )) );
1155 
1156  };
1157  }
1158 
1159  private:
1160  ContextRef _zyppCtx;
1163 
1164  };
1165  }
1166 
1167  MaybeAwaitable<expected<void> > refreshGeoIPData( ContextRef ctx, RepoInfo::url_set urls )
1168  {
1169  RefreshGeoIpLogic impl( std::move(ctx), zypp::MirroredOriginSet(urls) );
1170  zypp_co_return zypp_co_await ( impl.execute () );
1171  }
1172 
1173  MaybeAwaitable<expected<void> > refreshGeoIPData(ContextRef ctx, zypp::MirroredOriginSet origins)
1174  {
1175  RefreshGeoIpLogic impl( std::move(ctx), std::move(origins) );
1176  zypp_co_return zypp_co_await ( impl.execute () );
1177  }
1178 
1179 }
RepoInfo _info
ProgressObserverRef _progressObserver
#define MIL
Definition: Logger.h:103
zypp::RepoStatus RepoStatus
Definition: repomanager.h:39
MaybeAwaitable< expected< repo::RefreshContextRef > > refreshMetadata(repo::RefreshContextRef refCtx, LazyMediaHandle< Provide > medium, ProgressObserverRef progressObserver)
LazyMediaHandle _medium
bool empty() const
Whether the status is empty (empty checksum)
Definition: RepoStatus.cc:234
thrown when it was impossible to determine this repo type.
int assert_dir(const Pathname &path, unsigned mode)
Like &#39;mkdir -p&#39;.
Definition: PathInfo.cc:338
Listentry returned by readdir.
Definition: PathInfo.h:517
Type toEnum() const
Definition: RepoType.h:49
zypp::RepoInfo RepoInfo
Definition: repomanager.h:38
bool IamNotRoot()
Definition: PathInfo.h:42
expected< T, E > inspect(expected< T, E > exp, Function &&f)
Definition: expected.h:616
SignalProxy< void(int)> sigFinished()
Definition: process.cpp:294
ProgressObserverRef _myProgress
MaybeAwaitable< expected< repo::RefreshContextRef > > buildCache(repo::RefreshContextRef refCtx, zypp::RepoManagerFlags::CacheBuildPolicy policy, ProgressObserverRef progressObserver)
expected< std::list< RepoInfo > > repositories_in_file(const zypp::Pathname &file)
Reads RepoInfo&#39;s from a repo file.
Definition: repomanager.cc:167
std::string asString() const
Definition: ByteArray.h:24
zypp::Pathname _mediarootpath
bool _doProbeUrl
RepoManagerOptions::probe opt. overwritten in by ctor arg forcedProbe.
const char * c_str() const
String representation.
Definition: Pathname.h:113
String related utilities and Regular expression matching.
MaybeAwaitable< expected< RepoInfo > > addRepository(RepoManagerRef mgr, RepoInfo info, ProgressObserverRef myProgress, const zypp::TriBool &forcedProbe)
zypp::Pathname _geoIPCache
Definition: ansi.h:854
What is known about a repository.
Definition: RepoInfo.h:71
static expected< std::decay_t< Type >, Err > make_expected_success(Type &&t)
Definition: expected.h:470
std::optional< zypp::Pathname > _targetPath
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition: Easy.h:27
void setHost(const std::string &host)
Set the hostname or IP in the URL authority.
Definition: Url.cc:775
Convenient building of std::string with boost::format.
Definition: String.h:253
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Definition: String.cc:39
ProgressObserverRef _progress
#define ZYPP_EXCPT_PTR(EXCPT)
Drops a logline and returns Exception as a std::exception_ptr.
Definition: Exception.h:463
ContextRef _zyppCtx
zypp::Pathname _path
#define ERR
Definition: Logger.h:105
expected< zypp::Pathname > packagescache_path_for_repoinfo(const RepoManagerOptions &opt, const RepoInfo &info)
Calculates the packages cache path for a repository.
Definition: repomanager.h:189
zypp::Url _url
boost::logic::tribool TriBool
3-state boolean logic (true, false and indeterminate).
Definition: String.h:31
void remember(const Exception &old_r)
Store an other Exception as history.
Definition: Exception.cc:154
time_t ValueType
Definition: Date.h:38
ResultType or_else(const expected< T, E > &exp, Function &&f)
Definition: expected.h:554
zypp::MirroredOriginSet _origins
Url url() const
Pars pro toto: The first repository url, this is either baseUrls().front() or if no baseUrl is define...
Definition: RepoInfo.cc:854
zypp::repo::RepoException _error
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
Definition: Exception.h:479
std::string asString() const
Returns a default string representation of the Url object.
Definition: Url.cc:524
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...
Definition: repomanager.h:180
auto firstOf(Transformation &&transformFunc, DefaultType &&def, Predicate &&predicate=detail::ContinueUntilValidPredicate())
Definition: algorithm.h:94
static Ptr create()
Definition: process.cpp:49
Convenient building of std::string via std::ostringstream Basically a std::ostringstream autoconverti...
Definition: String.h:212
Execute a program and give access to its io An object of this class encapsulates the execution of an ...
void setScheme(const std::string &scheme)
Set the scheme name in the URL.
Definition: Url.cc:695
Manages a data source characterized by an authoritative URL and a list of mirror URLs.
const std::string & asString() const
String representation.
Definition: Pathname.h:94
std::string alias() const
unique identifier for this source.
bool isExist() const
Return whether valid stat info exists.
Definition: PathInfo.h:286
expected< T, E > inspect_err(expected< T, E > exp, Function &&f)
Definition: expected.h:629
Just inherits Exception to separate media exceptions.
std::string asUserString() const
Translated error message as string suitable for the user.
Definition: Exception.cc:131
RepoManagerRef _repoMgrRef
expected< void > assert_alias(const RepoInfo &info)
Definition: repomanager.h:52
Pathname dirname() const
Return all but the last component od this path.
Definition: Pathname.h:133
#define WAR
Definition: Logger.h:104
zypp::Pathname _productdatapath
MaybeAwaitable< expected< repo::RefreshCheckStatus > > checkIfToRefreshMetadata(repo::RefreshContextRef refCtx, LazyMediaHandle< Provide > medium, ProgressObserverRef progressObserver)
ProvideMediaHandle MediaHandle
Definition: provide.h:109
static void setup(ProgressObserverRef progress, const std::string &label=std::string(), int steps=100)
ContextRef _zyppContext
MaybeAwaitable< expected< void > > refreshGeoIPData(ContextRef ctx, RepoInfo::url_set urls)
void updateSolvFileIndex(const Pathname &solvfile_r)
Create solv file content digest for zypper bash completion.
Definition: Pool.cc:286
Writing the zypp history fileReference counted signleton for writhing the zypp history file...
Definition: HistoryLog.h:56
#define _(MSG)
Definition: Gettext.h:39
bool isValid() const
Verifies the Url.
Definition: Url.cc:516
std::list< Url > url_set
Definition: RepoInfo.h:108
MaybeAwaitable< expected< zypp::repo::RepoType > > probeRepoType(ContextRef ctx, Provide::LazyMediaHandle medium, zypp::Pathname path, std::optional< zypp::Pathname > targetPath)
std::vector< std::string > Arguments
int unlink(const Pathname &path)
Like &#39;unlink&#39;.
Definition: PathInfo.cc:719
static const RepoType NONE
Definition: RepoType.h:33
static expected success(ConsParams &&...params)
Definition: expected.h:178
Provide::Res ProvideRes
Definition: provide.h:154
void resetDispose()
Set no dispose function.
Definition: AutoDispose.h:171
int compareCI(const C_Str &lhs, const C_Str &rhs)
Definition: String.h:1055
thrown if the user has no permission to update(write) the caches.
MaybeAwaitable< expected< repo::DownloadContextRef > > download(repo::DownloadContextRef dl, ProvideMediaHandle mediaHandle, ProgressObserverRef progressObserver=nullptr)
static const RepoType RPMMD
Definition: RepoType.h:30
expected< RepoStatus > cacheStatus(const RepoInfo &info) const
Definition: repomanager.h:347
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition: Exception.h:475
zypp::RepoManagerFlags::CacheBuildPolicy _policy
zypp::RepoManagerFlags::RefreshCheckStatus RefreshCheckStatus
Definition: refresh.h:34
static const RepoType YAST2
Definition: RepoType.h:31
bool _gotMediaError
expected< void > assert_urls(const RepoInfo &info)
Definition: repomanager.cc:227
static ProgressObserverRef makeSubTask(ProgressObserverRef parentProgress, float weight=1.0, const std::string &label=std::string(), int steps=100)
Base class for Exception.
Definition: Exception.h:152
Date timestamp() const
The time the data were changed the last time.
Definition: RepoStatus.cc:237
auto setProgress(ProgressObserverRef progressObserver, double progrValue, std::optional< std::string > newStr={})
Exception for repository handling.
Definition: RepoException.h:37
SignalProxy< void()> sigReadyRead()
Definition: iodevice.cc:368
refresh is delayed due to settings
static expected< void > touchIndexFile(const RepoInfo &info, const RepoManagerOptions &options)
bool any_of(const Container &c, Fnc &&cb)
Definition: Algorithm.h:76
static Date now()
Return the current time.
Definition: Date.h:78
MaybeAwaitable< expected< void > > addRepositories(RepoManagerRef mgr, zypp::Url url, ProgressObserverRef myProgress)
repo::RefreshContextRef _refCtx
Predicate predicate
Definition: PoolQuery.cc:314
std::string getPathName(EEncoding eflag=zypp::url::E_DECODED) const
Returns the path name from the URL.
Definition: Url.cc:631
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:225
static void finish(ProgressObserverRef progress, ProgressObserver::FinishResult result=ProgressObserver::Success)
ResultType and_then(const expected< T, E > &exp, Function &&f)
Definition: expected.h:520
auto mtry(F &&f, Args &&...args)
Definition: mtry.h:50
static const RepoType RPMPLAINDIR
Definition: RepoType.h:32
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.
Definition: repomanager.h:166
MaybeAwaitable< expected< zypp::RepoStatus > > repoStatus(repo::DownloadContextRef dl, ProvideMediaHandle mediaHandle)
Track changing files or directories.
Definition: RepoStatus.h:40
Repository already exists and some unique attribute can&#39;t be duplicated.
static zypp::repo::RepoType probeCache(const zypp::Pathname &path_r)
Probe Metadata in a local cache directory.
Definition: repomanager.cc:423
#define ZYPP_FWD_CURRENT_EXCPT()
Drops a logline and returns the current Exception as a std::exception_ptr.
Definition: Exception.h:471
Functor replacing repository variables.
ProvideRes Res
Definition: provide.h:111
int dirForEachExt(const Pathname &dir_r, const function< bool(const Pathname &, const DirEntry &)> &fnc_r)
Simiar to.
Definition: PathInfo.cc:612
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:1
MaybeAwaitable< expected< std::list< RepoInfo > > > readRepoFile(ContextRef ctx, zypp::Url repoFileUrl)
static auto copyResultToDest(ProvideRef provider, const zypp::Pathname &targetPath)
Definition: provide.h:139
Url manipulation class.
Definition: Url.h:92
A smart container that manages a collection of MirroredOrigin objects, automatically grouping endpoin...
expected< zypp::Pathname > solv_path_for_repoinfo(const RepoManagerOptions &opt, const RepoInfo &info)
Calculates the solv cache path for a repository.
Definition: repomanager.h:199
#define DBG
Definition: Logger.h:102
::zyppng::LazyMediaHandle< Provide > LazyMediaHandle
Definition: provide.h:110
static expected< RepoStatus > metadataStatus(const RepoInfo &info, const RepoManagerOptions &options)
Definition: repomanager.cc:307
ZYppCommitResult & _result
Definition: TargetImpl.cc:1726
Repository type enumeration.
Definition: RepoType.h:28
bool IamRoot()
Definition: PathInfo.h:41
xmlTextReader based interface to iterate xml streams.
Definition: Reader.h:95
zypp::ByteArray ByteArray
Definition: bytearray.h:21
repo::RefreshContextRef _refreshContext