libzypp  17.38.7
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 
17 #include <zypp-core/fs/PathInfo.h>
18 #include <zypp-core/ng/pipelines/Algorithm>
19 
20 #include <zypp/ng/media/provide.h>
21 #include <zypp-media/ng/ProvideSpec>
22 
23 namespace 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 
190  namespace DownloadWorkflow {
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:103
int assert_dir(const Pathname &path, unsigned mode)
Like &#39;mkdir -p&#39;.
Definition: PathInfo.cc:338
std::vector< zypp::Pathname > _cacheDirs
Definition: downloadwf.h:45
void addCacheDir(const zypp::Pathname &p)
Definition: downloadwf.cc:44
String related utilities and Regular expression matching.
Definition: ansi.h:854
static expected< std::decay_t< Type >, Err > make_expected_success(Type &&t)
Definition: expected.h:470
AutoDispose< const Pathname > ManagedFile
A Pathname plus associated cleanup code to be executed when path is no longer needed.
Definition: ManagedFile.h:27
auto firstOf(Transformation &&transformFunc, DefaultType &&def, Predicate &&predicate=detail::ContinueUntilValidPredicate())
Definition: algorithm.h:94
MaybeAwaitable< expected< zypp::ManagedFile > > provideToCacheDir(CacheProviderContextRef cacheContext, ProvideMediaHandle medium, zypp::Pathname file, ProvideFileSpec filespec)
Definition: downloadwf.cc:192
ContextRef _zyppContext
int unlink(const Pathname &path)
Like &#39;unlink&#39;.
Definition: PathInfo.cc:719
static expected success(ConsParams &&...params)
Definition: expected.h:178
Provide::Res ProvideRes
Definition: provide.h:154
MaybeAwaitable< expected< void > > verifyChecksum(ContextRef zyppCtx, zypp::CheckSum checksum, zypp::filesystem::Pathname file)
Definition: checksumwf.cc:111
#define ZYPP_PRIVATE_CONSTR_ARG
Definition: zyppglobal.h:153
Base class for Exception.
Definition: Exception.h:152
auto and_then(Fun &&function)
Definition: expected.h:708
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:225
MediaHandle _medium
Definition: downloadwf.cc:184
const zypp::Pathname & destDir() const
Definition: downloadwf.cc:38
const std::vector< zypp::Pathname > & cacheDirs() const
Definition: downloadwf.cc:50
ProvideFileSpec _filespec
Definition: downloadwf.cc:186
CacheProviderContextRef _ctx
Definition: downloadwf.cc:183
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:1
zypp::Pathname _file
Definition: downloadwf.cc:185
const ContextRef & zyppContext() const
Definition: downloadwf.cc:31