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#ifdef ZYPP_REPO2SOLV_PATH
768 cmd.push_back( ZYPP_REPO2SOLV_PATH );
770 cmd.push_back( zypp::PathInfo(
"/usr/bin/repo2solv" ).isFile() ?
"repo2solv" :
"repo2solv.sh" );
773 cmd.push_back(
"-o" );
774 cmd.push_back( solvfile.asString() );
775 cmd.push_back(
"-X" );
778 if ( repokind == zypp::repo::RepoType::RPMPLAINDIR )
781 cmd.push_back(
"-R" );
783 std::optional<zypp::Pathname> localPath = forPlainDirs.has_value() ? forPlainDirs->localPath() : zypp::Pathname();
785 return makeReadyResult( expected<void>::error( ZYPP_EXCPT_PTR( zypp::repo::RepoException( zypp::str::Format(_(
"Failed to cache repo %1%")) % _refCtx->repoInfo() ))) );
788 cmd.push_back( (*localPath / info.path().absolutename()).c_str() );
791 cmd.push_back( _productdatapath.asString() );
793 return Repo2SolvOp<ZyppContextRefType>::run( info, std::move(cmd) )
794 | and_then( [this, guard = std::move(guard), solvfile = std::move(solvfile) ]() mutable {
796 guard.resetDispose();
797 return mtry( zypp::sat::updateSolvFileIndex, solvfile );
812 MIL <<
"Commit cache.." << std::endl;
817 |
or_else ( [
this]( std::exception_ptr
e ) {
829 |
and_then( [
this]( MediaHandle handle ) {
858 template<
typename Executor,
class OpType>
859 struct AddRepoLogic :
public LogicBase<Executor, OpType>{
877 MIL <<
"Try adding repo " <<
_info << std::endl;
887 DBG <<
"unknown repository type, probing" << std::endl;
906 MIL <<
"done" << std::endl;
909 |
or_else( [
this]( std::exception_ptr
e) {
911 MIL <<
"done" << std::endl;
935 template<
typename Executor,
class OpType>
936 struct AddReposLogic :
public LogicBase<Executor, OpType>{
952 |
and_then([
this]( std::list<RepoInfo> repos ) {
954 for ( std::list<RepoInfo>::const_iterator
it = repos.begin();
961 if ( (*it).alias() == (*kit).alias() )
963 ERR <<
"To be added repo " << (*it).alias() <<
" conflicts with existing repo " << (*kit).alias() << std::endl;
983 MIL <<
"Saving " << repos.size() <<
" repo" << ( repos.size() ?
"s" :
"" ) <<
" in " <<
repofile << std::endl;
985 std::ofstream file(
repofile.c_str());
992 for ( std::list<RepoInfo>::iterator
it = repos.begin();
996 MIL <<
"Saving " << (*it).alias() << std::endl;
1004 it->dumpAsIniOn(file);
1006 it->setMetadataPath( *rawCachePath );
1013 MIL <<
"done" << std::endl;
1039 template<
typename Executor,
class OpType>
1040 struct RefreshGeoIpLogic :
public LogicBase<Executor, OpType>{
1046 using ZyppContextType =
typename ZyppContextRefType::element_type;
1047 using ProvideType =
typename ZyppContextType::ProvideType;
1048 using MediaHandle =
typename ProvideType::MediaHandle;
1049 using ProvideRes =
typename ProvideType::Res;
1061 if ( !
_zyppCtx->config().geoipEnabled() ) {
1062 MIL <<
"GeoIp disabled via ZConfig, not refreshing the GeoIP information." << std::endl;
1066 std::vector<std::string>
hosts;
1067 for (
const auto &baseUrl :
_urls ) {
1068 const auto &host = baseUrl.getHost();
1069 if (
zypp::any_of(
_zyppCtx->config().geoipHostnames(), [&host](
const auto &
elem ){ return ( zypp::str::compareCI( host, elem ) == 0 ); } ) ) {
1070 hosts.push_back( host );
1075 if (
hosts.empty() ) {
1076 MIL <<
"No configured geoip URL found, not updating geoip data" << std::endl;
1083 MIL <<
"Unable to create cache directory for GeoIP." << std::endl;
1088 MIL <<
"No access rights for the GeoIP cache directory." << std::endl;
1098 auto age = std::chrono::system_clock::now() - std::chrono::system_clock::from_time_t(
pi.mtime() );
1099 if (
age < std::chrono::hours(24) )
1102 MIL <<
"Removing GeoIP file for " <<
entry.name <<
" since it's older than 24hrs." << std::endl;
1107 auto firstOfCb = [
this]( std::string hostname ) {
1111 MIL <<
"Skipping GeoIP request for " << hostname <<
" since a valid cache entry exists." << std::endl;
1115 MIL <<
"Query GeoIP for " << hostname << std::endl;
1124 MIL <<
"Ignoring invalid GeoIP hostname: " << hostname << std::endl;
1131 |
inspect_err( [hostname](
const std::exception_ptr& ){
MIL <<
"Failed to query GeoIP from hostname: " << hostname << std::endl; } )
1138 out.open(
fName.asString(), std::ios_base::trunc );
1139 if ( out.is_open() ) {
1140 out << host << std::endl;
1142 MIL <<
"Failed to create/open GeoIP cache file " <<
fName << std::endl;
1149 if (
reader.seekToNode( 1,
"host" ) ) {
1150 const auto &
str =
reader.nodeText().asString();
1158 MIL <<
"Storing geoIP redirection: " << hostname <<
" -> " <<
str << std::endl;
1163 MIL <<
"No host entry or empty file returned for GeoIP, remembering for 24hrs" << std::endl;
1167 MIL <<
"Empty or invalid GeoIP file, not requesting again for 24hrs" << std::endl;
1176 return std::move(
hosts)
1181 MIL <<
"Successfully queried GeoIP data." << std::endl;
1185 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)