libzypp 17.38.3
downloadwf.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
9
10#include "downloadwf.h"
11
12#include <utility>
13#include <zypp/ng/context.h>
15
16
18#include <zypp-core/ng/pipelines/Algorithm>
19
21#include <zypp-media/ng/ProvideSpec>
22
23namespace zyppng {
24
25 CacheProviderContext::CacheProviderContext( ZYPP_PRIVATE_CONSTR_ARG, ContextRef zyppContext, zypp::Pathname destDir )
26 : _zyppContext( std::move(zyppContext) )
27 , _destDir( std::move(destDir) )
28 { }
29
30
31 const ContextRef &CacheProviderContext::zyppContext() const
32 {
33 return _zyppContext;
34 }
35
36
37
39 {
40 return _destDir;
41 }
42
43
45 {
46 _cacheDirs.push_back ( p );
47 }
48
49
50 const std::vector<zypp::Pathname> &CacheProviderContext::cacheDirs() const
51 {
52 return _cacheDirs;
53 }
54
55 namespace {
56
57 using namespace zyppng::operators;
58
59 class CacheMissException : public zypp::Exception
60 {
61 public:
62 CacheMissException( const zypp::Pathname &filename )
63 : zypp::Exception( zypp::str::Str() << filename << " not found in target cache" ) { }
64 };
65
66 struct ProvideFromCacheOrMediumLogic {
67 protected:
68
69 using ContextType = Context;
70 using ProvideType = typename ContextType::ProvideType;
71 using MediaHandle = typename ProvideType::MediaHandle;
72 using ProvideRes = typename ProvideType::Res;
73
74 public:
75 ProvideFromCacheOrMediumLogic( CacheProviderContextRef cacheContext, MediaHandle &&medium, zypp::Pathname &&file, ProvideFileSpec &&filespec )
76 : _ctx( std::move(cacheContext) )
77 , _medium( std::move(medium) )
78 , _file(std::move( file ))
79 , _filespec( std::move(filespec) ) {}
80
81 MaybeAwaitable<expected<zypp::ManagedFile>> execute() {
82
83 return findFileInCache( )
84 | [this]( expected<zypp::ManagedFile> cached ) -> MaybeAwaitable<expected<zypp::ManagedFile>> {
85 if ( !cached ) {
86 MIL << "Didn't find " << _file << " in the caches, providing from medium" << std::endl;
87
88 // we didn't find it in the caches or the lookup failed, lets provide and check it
89 std::shared_ptr<ProvideType> provider = _ctx->zyppContext()->provider();
90 return provider->provide( _medium, _file, _filespec )
91 | and_then( [this]( ProvideRes res ) {
92 return verifyFile( res.file() )
93 | and_then( [res = res]() {
94 return expected<ProvideRes>::success( std::move(res) );
95 });
96 })
97 | and_then( ProvideType::copyResultToDest( _ctx->zyppContext()->provider(), _ctx->destDir() / _file ) )
98 | and_then( []( zypp::ManagedFile &&file ){
99 file.resetDispose ();
100 return make_expected_success (std::move(file));
101 }) ;
102
103 } else {
104
105 return verifyFile ( cached.get() )
106 | and_then([ this, cachedFile = cached.get() ]() mutable {
107 if ( cachedFile == _ctx->destDir() / _file ) {
108 cachedFile.resetDispose(); // make sure dispose is reset
109 return makeReadyTask( expected<zypp::ManagedFile>::success(std::move(cachedFile) ));
110 }
111
112 const auto &targetPath = _ctx->destDir() / _file;
113 zypp::filesystem::assert_dir( targetPath.dirname () );
114
115 return _ctx->zyppContext()->provider()->copyFile( cachedFile, _ctx->destDir() / _file )
116 | and_then( [cachedFile]( zypp::ManagedFile &&f) { f.resetDispose(); return make_expected_success (std::move(f)); });
117 });
118 }};
119 }
120
121 protected:
126 MaybeAwaitable<expected<zypp::ManagedFile>> findFileInCache( ) {
127
128 // No checksum - no match
129 if ( _filespec.checksum().empty() )
130 return makeReadyTask( expected<zypp::ManagedFile>::error(std::make_exception_ptr( CacheMissException(_file) )) );
131
132 const auto &confDirs = _ctx->cacheDirs();
133 const auto targetFile = _ctx->destDir() / _file ;
134 std::vector<zypp::Pathname> caches;
135 caches.push_back( _ctx->destDir() );
136 caches.insert( caches.end(), confDirs.begin(), confDirs.end() );
137
138 auto makeSearchPipeline = [this, targetFile]( zypp::Pathname cachePath ) -> expected<zypp::ManagedFile> {
139 zypp::Pathname cacheFilePath( cachePath / _file );
140 zypp::PathInfo cacheFileInfo( cacheFilePath );
141 if ( !cacheFileInfo.isExist () ) {
142 return makeReadyTask(expected<zypp::ManagedFile>::error( std::make_exception_ptr (CacheMissException(_file)) ));
143 } else {
144 auto provider = _ctx->zyppContext()->provider();
145
146 // calc checksum, but do not use the workflow. Here we don't want to ask the user if a wrong checksum should
147 // be accepted
148 return provider->checksumForFile( cacheFilePath, _filespec.checksum().type() )
149 | and_then([this, cacheFilePath, targetFile]( zypp::CheckSum sum ) {
150
151 auto mgdFile = zypp::ManagedFile( cacheFilePath );
152
153 // if the file is in the target dir, make sure to release it if its not used
154 if ( cacheFilePath == targetFile )
155 mgdFile.setDispose ( zypp::filesystem::unlink );
156
157 if ( sum == _filespec.checksum () ) {
158 // we found the file!
159 return expected<zypp::ManagedFile>::success( std::move(mgdFile) );
160 }
161
162 return expected<zypp::ManagedFile>::error( std::make_exception_ptr (CacheMissException(_file)) );
163 });
164 }
165 };
166
167 auto defVal = expected<zypp::ManagedFile>::error( std::make_exception_ptr (CacheMissException(_file) ) );
168 return std::move(caches) | firstOf( std::move(makeSearchPipeline), std::move(defVal), detail::ContinueUntilValidPredicate() );
169 }
170
171 MaybeAwaitable<expected<void>> verifyFile ( const zypp::Pathname &dlFilePath ) {
172
173 return zypp::Pathname( dlFilePath )
174 | [this]( zypp::Pathname &&dlFilePath ) {
175 if ( !_filespec.checksum().empty () ) {
176 return CheckSumWorkflow::verifyChecksum( _ctx->zyppContext(), _filespec.checksum (), std::move(dlFilePath) );
177 }
178 return makeReadyTask(expected<void>::success());
179 };
180 // add other verifier here via and_then(), like a signature based one
181 }
182
183 CacheProviderContextRef _ctx;
184 MediaHandle _medium;
186 ProvideFileSpec _filespec;
187 };
188 }
189
191
192 MaybeAwaitable<expected<zypp::ManagedFile> > provideToCacheDir( CacheProviderContextRef cacheContext, ProvideMediaHandle medium, zypp::Pathname file, ProvideFileSpec filespec )
193 {
194 ProvideFromCacheOrMediumLogic impl(std::move(cacheContext), std::move(medium), std::move(file), std::move(filespec));
195 zypp_co_return zypp_co_await( impl.execute() );
196 }
197
198 }
199
200}
#define MIL
Definition Logger.h:100
Base class for Exception.
Definition Exception.h:153
Wrapper class for stat/lstat.
Definition PathInfo.h:226
const zypp::Pathname & destDir() const
Definition downloadwf.cc:38
const ContextRef & zyppContext() const
Definition downloadwf.cc:31
void addCacheDir(const zypp::Pathname &p)
Definition downloadwf.cc:44
std::vector< zypp::Pathname > _cacheDirs
Definition downloadwf.h:45
const std::vector< zypp::Pathname > & cacheDirs() const
Definition downloadwf.cc:50
Provide ProvideType
Definition context.h:34
const zypp::Pathname file() const
Definition provide.cc:152
static expected success(ConsParams &&...params)
Definition expected.h:178
static expected error(ConsParams &&...params)
Definition expected.h:189
String related utilities and Regular expression matching.
int unlink(const Pathname &path)
Like 'unlink'.
Definition PathInfo.cc:719
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
Definition PathInfo.cc:338
Easy-to use interface to the ZYPP dependency resolver.
AutoDispose< const Pathname > ManagedFile
A Pathname plus associated cleanup code to be executed when path is no longer needed.
Definition ManagedFile.h:27
Pathname _file
MaybeAwaitable< expected< void > > verifyChecksum(ContextRef zyppCtx, zypp::CheckSum checksum, zypp::filesystem::Pathname file)
MaybeAwaitable< expected< zypp::ManagedFile > > provideToCacheDir(CacheProviderContextRef cacheContext, ProvideMediaHandle medium, zypp::Pathname file, ProvideFileSpec filespec)
auto and_then(Fun &&function)
Definition expected.h:708
ResultType and_then(const expected< T, E > &exp, Function &&f)
Definition expected.h:520
auto firstOf(Transformation &&transformFunc, DefaultType &&def, Predicate &&predicate=detail::ContinueUntilValidPredicate())
Definition algorithm.h:94
#define ZYPP_PRIVATE_CONSTR_ARG
Definition zyppglobal.h:160