11#include <zypp-core/ManagedFile.h>
13#include <zypp-core/zyppng/pipelines/MTry>
14#include <zypp-media/MediaException>
15#include <zypp-media/ng/Provide>
16#include <zypp-media/ng/ProvideSpec>
18#include <zypp/ng/Context>
25 using namespace zyppng::operators;
29 template <
class Executor,
class OpType>
30 struct ProbeRepoLogic :
public LogicBase<Executor, OpType>
37 using ProvideType =
typename remove_smart_ptr_t<ZyppContextRefType>::ProvideType;
38 using MediaHandle =
typename ProvideType::MediaHandle;
39 using ProvideRes =
typename ProvideType::Res;
41 ProbeRepoLogic(ZyppContextRefType zyppCtx, MediaHandle &&medium,
zypp::Pathname &&path, std::optional<zypp::Pathname> &&targetPath )
48 MaybeAsyncRef<expected<zypp::repo::RepoType>> execute( ) {
49 const auto &url =
_medium.baseUrl();
50 MIL <<
"going to probe the repo type at " << url <<
" (" <<
_path <<
")" << std::endl;
54 MIL <<
"Probed type NONE (not exists) at " << url <<
" (" <<
_path <<
")" << std::endl;
64 std::shared_ptr<ProvideType> providerRef =
_zyppContext->provider();
70 return providerRef->provide( _medium, _path/
"repodata/repomd.xml", ProvideFileSpec().setCheckExistsOnly( !
_targetPath.has_value() ) )
71 | and_then( maybeCopyResultToDest(
"repodata/repomd.xml") )
74 | or_else( [
this, providerRef]( std::exception_ptr err ) {
76 std::rethrow_exception (err);
81 DBG <<
"problem checking for repodata/repomd.xml file" << std::endl;
86 return makeReadyResult( expected<zypp::repo::RepoType>::error( std::current_exception() ) );
88 return providerRef->provide( _medium, _path/
"content", ProvideFileSpec().setCheckExistsOnly( !
_targetPath.has_value() ) )
89 | and_then( maybeCopyResultToDest(
"content") )
93 | or_else( [
this]( std::exception_ptr err ) {
96 std::rethrow_exception (err);
101 DBG <<
"problem checking for content file" << std::endl;
107 return expected<zypp::repo::RepoType>::error(
ZYPP_EXCPT_PTR(e) );
110 return expected<zypp::repo::RepoType>::error( std::current_exception() );
113 const auto &url =
_medium.baseUrl();
116 if ( ! ( url.schemeIsDownloading() || url.schemeIsPlugin() ) ) {
120 MIL <<
"Probed type RPMPLAINDIR at " << url <<
" (" <<
_path <<
")" << std::endl;
126 return expected<zypp::repo::RepoType>::error(
ZYPP_EXCPT_PTR( _error ));
128 MIL <<
"Probed type NONE at " << url <<
" (" <<
_path <<
")" << std::endl;
139 auto maybeCopyResultToDest ( std::string &&subPath ) {
140 return [
this, subPath = std::move(subPath)]( ProvideRes file ) -> MaybeAsyncRef<expected<void>> {
142 MIL <<
"Target path is set, copying " << file.file() <<
" to " << *
_targetPath/subPath << std::endl;
143 return std::move(file)
144 | ProvideType::copyResultToDest(
_zyppContext->provider(), *_targetPath/subPath)
147 return makeReadyResult( expected<void>::success() );
177 template<
typename Executor,
class OpType>
178 struct CheckIfToRefreshMetadataLogic :
public LogicBase<Executor, OpType> {
184 using ZyppContextRefType =
typename RefreshContextRefType::element_type::ContextRefType;
185 using ZyppContextType =
typename RefreshContextRefType::element_type::ContextType;
186 using ProvideType =
typename ZyppContextType::ProvideType;
187 using MediaHandle =
typename ProvideType::MediaHandle;
190 CheckIfToRefreshMetadataLogic( RefreshContextRefType refCtx, MediaHandle &&medium, ProgressObserverRef progressObserver )
196 MaybeAsyncRef<expected<repo::RefreshCheckStatus>> execute( ) {
198 MIL <<
"Going to CheckIfToRefreshMetadata" << std::endl;
202 | and_then( [
this](){
206 MIL <<
"Check if to refresh repo " <<
_refreshContext->repoInfo().alias() <<
" at " <<
_medium.baseUrl() <<
" (" << info.type() <<
")" << std::endl;
214 if ( oldstatus.
empty() ) {
215 MIL <<
"No cached metadata, going to refresh" << std::endl;
219 if (
_medium.baseUrl().schemeIsVolatile() ) {
220 MIL <<
"Never refresh CD/DVD" << std::endl;
225 MIL <<
"Forced refresh!" << std::endl;
229 if (
_medium.baseUrl().schemeIsLocal() ) {
241 if ( oldstatus == cachestatus ) {
244 const auto refDelay =
_refreshContext->zyppContext()->config().repo_refresh_delay();
245 if ( diff < refDelay ) {
247 WAR <<
"Repository '" << info.alias() <<
"' was refreshed in the future!" << std::endl;
250 MIL <<
"Repository '" << info.alias()
251 <<
"' has been refreshed less than repo.refresh.delay ("
253 <<
") minutes ago. Advising to skip refresh" << std::endl;
259 MIL <<
"Metadata and solv cache don't match. Check data on server..." << std::endl;
267 return makeReadyResult( expected<zypp::repo::RepoType>::success(repokind) );
277 if ( oldstatus == newstatus ) {
278 MIL <<
"repo has not changed" << std::endl;
283 MIL <<
"repo has changed, going to refresh" << std::endl;
284 MIL <<
"Old status: " << oldstatus <<
" New Status: " << newstatus << std::endl;
313 template<
typename Executor,
class OpType>
314 struct RefreshMetadataLogic :
public LogicBase<Executor, OpType>{
321 using ZyppContextRefType =
typename RefreshContextRefType::element_type::ContextRefType;
322 using ZyppContextType =
typename RefreshContextRefType::element_type::ContextType;
323 using ProvideType =
typename ZyppContextType::ProvideType;
324 using MediaHandle =
typename ProvideType::MediaHandle;
328 using DlContextRefType = std::shared_ptr<DlContextType>;
330 RefreshMetadataLogic( RefreshContextRefType refCtx, MediaHandle &&medium, ProgressObserverRef progressObserver )
335 MIL <<
"Constructor called" << std::endl;
338 MaybeAsyncRef<expected<RefreshContextRefType>> execute() {
348 MIL <<
"RefreshCheckStatus returned: " << status << std::endl;
353 return makeReadyResult ( expected<RefreshContextRefType>::success( std::move(_refreshContext) ) );
355 MIL <<
"Going to refresh metadata from " <<
_medium.baseUrl() << std::endl;
365 if ( info.type() != repokind ) {
366 _refreshContext->setProbedType( repokind );
368 info.setProbedType( repokind );
378 return makeReadyResult( expected<DlContextRefType>::error( std::move(exception) ));
382 dlContext->setPluginRepoverification(
_refreshContext->pluginRepoverification() );
387 | and_then([
this]( DlContextRefType && ) {
396 return expected<RefreshContextRefType>::success( std::move(_refreshContext) );
410 refreshGeoIPData( info.baseUrls() );
413 RepoException rexception( info,
PL_(
"Valid metadata not found at specified URL",
414 "Valid metadata not found at specified URLs",
415 info.baseUrlsSize() ) );
418 media::ScopedDisableMediaChangeReport guard( info.baseUrlsSize() > 1 );
420 for ( RepoInfo::urls_const_iterator it = info.baseUrlsBegin(); it != info.baseUrlsEnd(); ++it )
431 MIL <<
"Going to refresh metadata from " << url << endl;
434 repo::RepoType repokind = info.type();
436 repo::RepoType probed = probe( *it, info.path() );
443 if ( ( repokind.toEnum() == RepoType::RPMMD_e ) ||
444 ( repokind.toEnum() == RepoType::YAST2_e ) )
446 MediaSetAccess media(url);
449 MIL <<
"Creating downloader for [ " << info.alias() <<
" ]" << endl;
451 if ( repokind.toEnum() == RepoType::RPMMD_e ) {
452 downloader_ptr.reset(
new yum::Downloader(info, mediarootpath ));
453 if ( _pluginRepoverification.checkIfNeeded() )
454 downloader_ptr->setPluginRepoverification( _pluginRepoverification );
457 downloader_ptr.reset(
new susetags::Downloader(info, mediarootpath) );
465 for_( it, repoBegin(), repoEnd() )
468 if ( PathInfo(cachepath).isExist() )
469 downloader_ptr->addCachePath(cachepath);
473 downloader_ptr->download( media, tmpdir.path() );
475 else if ( repokind.toEnum() == RepoType::RPMPLAINDIR_e )
478 MediaMounter media( url );
479 RepoStatus newstatus = RepoStatus( media.getPathName( info.path() ) );
481 Pathname productpath( tmpdir.path() / info.path() );
482 filesystem::assert_dir( productpath );
483 newstatus.saveToCookieFile( productpath/
"cookie" );
492 filesystem::exchange( tmpdir.path(), mediarootpath );
499 catch (
const Exception &e )
502 ERR <<
"Trying another url..." << endl;
507 if (it == info.baseUrlsBegin())
508 rexception.remember(e);
510 rexception.addHistory( e.asUserString() );
514 ERR <<
"No more urls..." << endl;
530 namespace RepoManagerWorkflow {
void resetDispose()
Set no dispose function.
static Date now()
Return the current time.
Base class for Exception.
void remember(const Exception &old_r)
Store an other Exception as history.
What is known about a repository.
Track changing files or directories.
Date timestamp() const
The time the data were changed the last time.
bool empty() const
Whether the status is empty (empty checksum)
Wrapper class for stat/lstat.
const char * c_str() const
String representation.
Exception for repository handling.
thrown when it was impossible to determine this repo type.
A ProvideRes object is a reference counted ownership of a resource in the cache provided by a Provide...
#define ZYPP_ENABLE_LOGIC_BASE(Executor, OpType)
typename conditional< B, T, F >::type conditional_t
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
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.
bool isTmpRepo(const RepoInfo &info_r)
Whether repo is not under RM control and provides its own methadata paths.
void assert_alias(const RepoInfo &info)
void assert_urls(const RepoInfo &info)
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, ProvideMediaHandle medium, zypp::Pathname path, std::optional< zypp::Pathname > targetPath={})
AsyncOpRef< expected< repo::AsyncRefreshContextRef > > refreshMetadata(repo::AsyncRefreshContextRef refCtx, ProvideMediaHandle medium, ProgressObserverRef progressObserver)
AsyncOpRef< expected< repo::RefreshCheckStatus > > checkIfToRefreshMetadata(repo::AsyncRefreshContextRef refCtx, ProvideMediaHandle medium, ProgressObserverRef progressObserver=nullptr)
RefreshCheckStatus
Possibly return state of checkIfRefreshMEtadata function.
@ REFRESH_NEEDED
refresh is needed
@ REPO_CHECK_DELAYED
refresh is delayed due to settings
@ REPO_UP_TO_DATE
repository not changed
@ RefreshIfNeededIgnoreDelay
ZyppContextRefType _zyppContext
std::optional< zypp::Pathname > _targetPath
RefreshContextRefType _refreshContext
zypp::repo::RepoException _error
ProgressObserverRef _progress
zypp::Pathname _mediarootpath
static void touchIndexFile(const RepoInfo &info, const RepoManagerOptions &options)
RepoStatus cacheStatus(const RepoInfo &info) const
static RepoStatus metadataStatus(const RepoInfo &info, const RepoManagerOptions &options)
Repository type enumeration.
static const RepoType YAST2
static const RepoType RPMMD
static const RepoType NONE
static const RepoType RPMPLAINDIR
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
#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_THROW(EXCPT)
Drops a logline and throws the Exception.
#define PL_(MSG1, MSG2, N)