1
/*---------------------------------------------------------------------\
3
| |__ / \ / / . \ . \ |
8
\---------------------------------------------------------------------*/
9
/** \file zypp/Fetcher.cc
17
#include "zypp/base/Easy.h"
18
#include "zypp/base/LogControl.h"
19
#include "zypp/base/LogTools.h"
20
#include "zypp/base/PtrTypes.h"
21
#include "zypp/base/DefaultIntegral.h"
22
#include "zypp/base/String.h"
23
#include "zypp/Fetcher.h"
24
#include "zypp/ZYppFactory.h"
25
#include "zypp/CheckSum.h"
26
#include "zypp/base/UserRequestException.h"
27
#include "zypp/parser/susetags/ContentFileReader.h"
28
#include "zypp/parser/susetags/RepoIndex.h"
32
#undef ZYPP_BASE_LOGGER_LOGGROUP
33
#define ZYPP_BASE_LOGGER_LOGGROUP "zypp:fetcher"
35
///////////////////////////////////////////////////////////////////
37
{ /////////////////////////////////////////////////////////////////
40
* class that represents indexes which add metadata
41
* to fetcher jobs and therefore need to be retrieved
46
FetcherIndex( const OnMediaLocation &loc )
49
/** Index localtion. */
50
OnMediaLocation location;
51
/** Whether we read this index. */
52
DefaultIntegral<bool,false> read;
55
typedef shared_ptr<FetcherIndex> FetcherIndex_Ptr;
57
/** std::set ordering (less semantic) */
58
struct SameFetcherIndex
60
bool operator()( const FetcherIndex_Ptr & lhs, const FetcherIndex_Ptr & rhs )
63
return false; // incl. NULL == NULL
65
return true; // NULL < nonNULL
67
return false; // nonNULL > NULL
68
// both nonNULL ==> compare medianr and path
69
if ( lhs->location.medianr() == rhs->location.medianr() )
70
return lhs->location.filename() < rhs->location.filename();
72
return lhs->location.medianr() < rhs->location.medianr();
77
* Class to encapsulate the \ref OnMediaLocation object
78
* and the \ref FileChecker together
87
RecursiveDirectory = Directory | Recursive,
88
// check checksums even if there is no such
89
// checksum (warns of no checksum)
90
AlwaysVerifyChecksum = 0x0004,
92
ZYPP_DECLARE_FLAGS(Flags, Flag);
95
FetcherJob( const OnMediaLocation &loc, const Pathname dfile = Pathname())
100
//MIL << location << endl;
105
//MIL << location << " | * " << checkers.size() << endl;
108
OnMediaLocation location;
110
//CompositeFileChecker checkers;
111
list<FileChecker> checkers;
115
ZYPP_DECLARE_OPERATORS_FOR_FLAGS(FetcherJob::Flags);
116
typedef shared_ptr<FetcherJob> FetcherJob_Ptr;
118
std::ostream & operator<<( std::ostream & str, const FetcherJob_Ptr & obj )
120
return str << obj->location;
123
///////////////////////////////////////////////////////////////////
125
// CLASS NAME : Fetcher::Impl
127
/** Fetcher implementation. */
130
friend std::ostream & operator<<( std::ostream & str, const Fetcher::Impl & obj );
137
void setOptions( Fetcher::Options options );
138
Fetcher::Options options() const;
140
void addIndex( const OnMediaLocation &resource );
142
void enqueueDir( const OnMediaLocation &resource, bool recursive, const FileChecker &checker = FileChecker() );
143
void enqueueDigestedDir( const OnMediaLocation &resource, bool recursive, const FileChecker &checker = FileChecker() );
145
void enqueue( const OnMediaLocation &resource, const FileChecker &checker = FileChecker() );
146
void enqueueDigested( const OnMediaLocation &resource, const FileChecker &checker = FileChecker(), const Pathname &deltafile = Pathname() );
147
void addCachePath( const Pathname &cache_dir );
149
void start( const Pathname &dest_dir,
150
MediaSetAccess &media,
151
const ProgressData::ReceiverFnc & progress_receiver );
153
/** Offer default Impl. */
154
static shared_ptr<Impl> nullimpl()
156
static shared_ptr<Impl> _nullimpl( new Impl );
161
* download the indexes and reads them
163
void downloadAndReadIndexList( MediaSetAccess &media, const Pathname &dest_dir);
166
* download the indexes and reads them
168
void downloadIndex( MediaSetAccess &media, const OnMediaLocation &resource, const Pathname &dest_dir);
171
* reads a downloaded index file and updates internal
174
* The index lists files relative to a directory, which is
175
* normally the same as the index file is located.
177
void readIndex( const Pathname &index, const Pathname &basedir );
179
/** specific version of \ref readIndex for CHECKSUMS file */
180
void readChecksumsIndex( const Pathname &index, const Pathname &basedir );
182
/** specific version of \ref readIndex for content file */
183
void readContentFileIndex( const Pathname &index, const Pathname &basedir );
185
/** reads the content of a directory but keeps a cache **/
186
void getDirectoryContent( MediaSetAccess &media, const OnMediaLocation &resource, filesystem::DirContent &content );
189
* tries to provide the file represented by job into dest_dir by
190
* looking at the cache. If success, returns true, and the desired
191
* file should be available on dest_dir
193
bool provideFromCache( const OnMediaLocation &resource, const Pathname &dest_dir );
195
* Validates the job against is checkers, by using the file instance
199
void validate( const OnMediaLocation &resource, const Pathname &dest_dir, const list<FileChecker> &checkers );
202
* scan the directory and adds the individual jobs
204
void addDirJobs( MediaSetAccess &media, const OnMediaLocation &resource,
205
const Pathname &dest_dir, FetcherJob::Flags flags );
208
* auto discovery and reading of indexes
210
void autoaddIndexes( const filesystem::DirContent &content,
211
MediaSetAccess &media,
212
const OnMediaLocation &resource,
213
const Pathname &dest_dir );
215
* Provide the resource to \ref dest_dir
217
void provideToDest( MediaSetAccess &media, const OnMediaLocation &resource, const Pathname &dest_dir , const Pathname &deltafile);
220
friend Impl * rwcowClone<Impl>( const Impl * rhs );
221
/** clone for RWCOW_pointer */
223
{ return new Impl( *this ); }
225
list<FetcherJob_Ptr> _resources;
226
std::set<FetcherIndex_Ptr,SameFetcherIndex> _indexes;
227
std::set<Pathname> _caches;
228
// checksums read from the indexes
229
map<string, CheckSum> _checksums;
230
// cache of dir contents
231
map<string, filesystem::DirContent> _dircontent;
233
Fetcher::Options _options;
235
///////////////////////////////////////////////////////////////////
237
void Fetcher::Impl::enqueueDigested( const OnMediaLocation &resource, const FileChecker &checker, const Pathname &deltafile )
240
job.reset(new FetcherJob(resource, deltafile));
241
job->flags |= FetcherJob:: AlwaysVerifyChecksum;
242
_resources.push_back(job);
245
Fetcher::Impl::Impl()
250
void Fetcher::Impl::setOptions( Fetcher::Options options )
251
{ _options = options; }
253
Fetcher::Options Fetcher::Impl::options() const
256
void Fetcher::Impl::enqueueDir( const OnMediaLocation &resource,
258
const FileChecker &checker )
261
job.reset(new FetcherJob(resource));
263
job->checkers.push_back(checker);
265
job->flags |= FetcherJob::Recursive;
266
job->flags |= FetcherJob::Directory;
268
_resources.push_back(job);
271
void Fetcher::Impl::enqueueDigestedDir( const OnMediaLocation &resource,
273
const FileChecker &checker )
276
job.reset(new FetcherJob(resource));
278
job->checkers.push_back(checker);
280
job->flags |= FetcherJob::Recursive;
281
job->flags |= FetcherJob::Directory;
282
job->flags |= FetcherJob::AlwaysVerifyChecksum;
284
_resources.push_back(job);
288
void Fetcher::Impl::enqueue( const OnMediaLocation &resource, const FileChecker &checker )
291
job.reset(new FetcherJob(resource));
293
job->checkers.push_back(checker);
294
_resources.push_back(job);
297
void Fetcher::Impl::addIndex( const OnMediaLocation &resource )
299
MIL << "adding index " << resource << endl;
300
_indexes.insert(FetcherIndex_Ptr(new FetcherIndex(resource)));
304
void Fetcher::Impl::reset()
312
void Fetcher::Impl::addCachePath( const Pathname &cache_dir )
314
PathInfo info(cache_dir);
315
if ( info.isExist() )
319
DBG << "Adding fetcher cache: '" << cache_dir << "'." << endl;
320
_caches.insert(cache_dir);
324
// don't add bad cache directory, just log the error
325
ERR << "Not adding cache: '" << cache_dir << "'. Not a directory." << endl;
330
ERR << "Not adding cache '" << cache_dir << "'. Path does not exists." << endl;
335
// tries to provide resource to dest_dir from any of the configured additional
336
// cache paths where the file may already be present. returns true if the
337
// file was provided from the cache.
338
bool Fetcher::Impl::provideFromCache( const OnMediaLocation &resource, const Pathname &dest_dir )
340
Pathname dest_full_path = dest_dir + resource.filename();
342
// first check in the destination directory
343
if ( PathInfo(dest_full_path).isExist() )
345
if ( is_checksum( dest_full_path, resource.checksum() )
346
&& (! resource.checksum().empty() ) )
350
MIL << "start fetcher with " << _caches.size() << " cache directories." << endl;
351
for_ ( it_cache, _caches.begin(), _caches.end() )
353
// does the current file exists in the current cache?
354
Pathname cached_file = *it_cache + resource.filename();
355
if ( PathInfo( cached_file ).isExist() )
357
DBG << "File '" << cached_file << "' exist, testing checksum " << resource.checksum() << endl;
358
// check the checksum
359
if ( is_checksum( cached_file, resource.checksum() ) && (! resource.checksum().empty() ) )
362
MIL << "file " << resource.filename() << " found in previous cache. Using cached copy." << endl;
363
// checksum is already checked.
364
// we could later implement double failover and try to download if file copy fails.
365
// replicate the complete path in the target directory
366
if( dest_full_path != cached_file )
368
if ( assert_dir( dest_full_path.dirname() ) != 0 )
369
ZYPP_THROW( Exception("Can't create " + dest_full_path.dirname().asString()));
371
if ( filesystem::hardlinkCopy(cached_file, dest_full_path ) != 0 )
373
ERR << "Can't hardlink/copy " << cached_file + " to " + dest_dir << endl;
381
} // iterate over caches
385
void Fetcher::Impl::validate( const OnMediaLocation &resource, const Pathname &dest_dir, const list<FileChecker> &checkers )
387
// no matter where did we got the file, try to validate it:
388
Pathname localfile = dest_dir + resource.filename();
389
// call the checker function
392
MIL << "Checking job [" << localfile << "] (" << checkers.size() << " checkers )" << endl;
394
for ( list<FileChecker>::const_iterator it = checkers.begin();
395
it != checkers.end();
404
ERR << "Invalid checker for '" << localfile << "'" << endl;
409
catch ( const FileCheckException &e )
413
catch ( const Exception &e )
419
ZYPP_THROW(Exception("Unknown error while validating " + resource.filename().asString()));
423
void Fetcher::Impl::autoaddIndexes( const filesystem::DirContent &content,
424
MediaSetAccess &media,
425
const OnMediaLocation &resource,
426
const Pathname &dest_dir )
428
auto fnc_addIfInContent( [&]( const std::string & index_r ) -> bool
430
if ( find( content.begin(), content.end(), filesystem::DirEntry(index_r,filesystem::FT_FILE) ) == content.end() )
432
// add the index of this directory
433
OnMediaLocation indexloc( resource );
434
indexloc.changeFilename( resource.filename() + index_r );
435
addIndex( indexloc );
436
// we need to read it now
437
downloadAndReadIndexList( media, dest_dir );
441
if ( _options & AutoAddChecksumsIndexes )
443
fnc_addIfInContent( "CHECKSUMS" ) || fnc_addIfInContent( "SHA1SUMS" );
445
if ( _options & AutoAddContentFileIndexes )
447
fnc_addIfInContent( "content" );
451
void Fetcher::Impl::getDirectoryContent( MediaSetAccess &media,
452
const OnMediaLocation &resource,
453
filesystem::DirContent &content )
455
if ( _dircontent.find(resource.filename().asString())
456
!= _dircontent.end() )
458
filesystem::DirContent filled(_dircontent[resource.filename().asString()]);
460
std::copy(filled.begin(), filled.end(), std::back_inserter(content));
464
filesystem::DirContent tofill;
465
media.dirInfo( tofill,
469
std::copy(tofill.begin(), tofill.end(), std::back_inserter(content));
470
_dircontent[resource.filename().asString()] = tofill;
474
void Fetcher::Impl::addDirJobs( MediaSetAccess &media,
475
const OnMediaLocation &resource,
476
const Pathname &dest_dir, FetcherJob::Flags flags )
478
// first get the content of the directory so we can add
479
// individual transfer jobs
480
MIL << "Adding directory " << resource.filename() << endl;
481
filesystem::DirContent content;
483
getDirectoryContent(media, resource, content);
485
catch ( media::MediaFileNotFoundException & exception )
487
ZYPP_CAUGHT( exception );
488
WAR << "Skiping subtree hidden at " << resource.filename() << endl;
492
// this method test for the option flags so indexes are added
493
// only if the options are enabled
494
autoaddIndexes(content, media, resource, dest_dir);
496
for ( filesystem::DirContent::const_iterator it = content.begin();
500
// skip CHECKSUMS* as they were already retrieved
501
if ( str::hasPrefix(it->name, "CHECKSUMS") || str::hasPrefix(it->name, "SHA1SUMS") )
504
Pathname filename = resource.filename() + it->name;
508
case filesystem::FT_NOT_AVAIL: // old directory.yast contains no typeinfo at all
509
case filesystem::FT_FILE:
511
CheckSum chksm(resource.checksum());
512
if ( _checksums.find(filename.asString()) != _checksums.end() )
514
// the checksum can be replaced with the one in the index.
515
chksm = _checksums[filename.asString()];
516
//MIL << "resource " << filename << " has checksum in the index file." << endl;
519
WAR << "Resource " << filename << " has no checksum in the index either." << endl;
521
if ( flags & FetcherJob::AlwaysVerifyChecksum )
522
enqueueDigested(OnMediaLocation(filename, resource.medianr()).setChecksum(chksm));
524
enqueue(OnMediaLocation(filename, resource.medianr()).setChecksum(chksm));
527
case filesystem::FT_DIR: // newer directory.yast contain at least directory info
528
if ( flags & FetcherJob::Recursive )
529
addDirJobs(media, filename, dest_dir, flags);
532
// don't provide devices, sockets, etc.
538
void Fetcher::Impl::provideToDest( MediaSetAccess &media, const OnMediaLocation &resource, const Pathname &dest_dir, const Pathname &deltafile )
540
bool got_from_cache = false;
542
// start look in cache
543
got_from_cache = provideFromCache(resource, dest_dir);
545
if ( ! got_from_cache )
547
MIL << "Not found in cache, downloading" << endl;
549
// try to get the file from the net
552
Pathname tmp_file = media.provideFile(resource, resource.optional() ? MediaSetAccess::PROVIDE_NON_INTERACTIVE : MediaSetAccess::PROVIDE_DEFAULT, deltafile );
554
Pathname dest_full_path = dest_dir + resource.filename();
556
if ( assert_dir( dest_full_path.dirname() ) != 0 )
557
ZYPP_THROW( Exception("Can't create " + dest_full_path.dirname().asString()));
558
if ( filesystem::hardlinkCopy( tmp_file, dest_full_path ) != 0 )
560
if ( ! PathInfo(tmp_file).isExist() )
561
ERR << tmp_file << " does not exist" << endl;
562
if ( ! PathInfo(dest_full_path.dirname()).isExist() )
563
ERR << dest_full_path.dirname() << " does not exist" << endl;
565
media.releaseFile(resource); //not needed anymore, only eat space
566
ZYPP_THROW( Exception("Can't hardlink/copy " + tmp_file.asString() + " to " + dest_dir.asString()));
569
media.releaseFile(resource); //not needed anymore, only eat space
571
catch (Exception & excpt_r)
573
if ( resource.optional() )
575
ZYPP_CAUGHT(excpt_r);
576
WAR << "optional resource " << resource << " could not be transfered" << endl;
581
excpt_r.remember("Can't provide " + resource.filename().asString() );
582
ZYPP_RETHROW(excpt_r);
588
// We got the file from cache
589
// continue with next file
594
// helper class to consume a content file
595
struct ContentReaderHelper : public parser::susetags::ContentFileReader
597
ContentReaderHelper()
599
setRepoIndexConsumer( bind( &ContentReaderHelper::consumeIndex, this, _1 ) );
602
void consumeIndex( const parser::susetags::RepoIndex_Ptr & data_r )
603
{ _repoindex = data_r; }
605
parser::susetags::RepoIndex_Ptr _repoindex;
608
// generic function for reading indexes
609
void Fetcher::Impl::readIndex( const Pathname &index, const Pathname &basedir )
611
if ( index.basename() == "CHECKSUMS" || index.basename() == "SHA1SUMS" )
612
readChecksumsIndex(index, basedir);
613
else if ( index.basename() == "content" )
614
readContentFileIndex(index, basedir);
616
WAR << index << ": index file format not known" << endl;
619
// reads a content file index
620
void Fetcher::Impl::readContentFileIndex( const Pathname &index, const Pathname &basedir )
622
ContentReaderHelper reader;
624
MIL << index << " contains " << reader._repoindex->mediaFileChecksums.size() << " checksums." << endl;
625
for_( it, reader._repoindex->mediaFileChecksums.begin(), reader._repoindex->mediaFileChecksums.end() )
627
// content file entries don't start with /
628
_checksums[(basedir + it->first).asString()] = it->second;
632
// reads a CHECKSUMS (old SHA1SUMS) file index
633
void Fetcher::Impl::readChecksumsIndex( const Pathname &index, const Pathname &basedir )
635
std::ifstream in( index.c_str() );
639
while ( getline( in, buffer ) )
642
if ( buffer[0] == '#' )
643
continue; // simple comment
645
CheckSum checksum( str::stripFirstWord( buffer, /*ltrim before strip*/true ) );
646
if ( checksum.empty() )
647
continue; // empty line | unknown cheksum format
649
if ( buffer.empty() )
651
WAR << "Missing filename in CHECKSUMS file: " << index.asString() << " (" << checksum << ")" << endl;
655
_checksums[(basedir/buffer).asString()] = checksum;
659
ZYPP_THROW(Exception("Can't open CHECKSUMS file: " + index.asString()));
662
void Fetcher::Impl::downloadIndex( MediaSetAccess &media, const OnMediaLocation &resource, const Pathname &dest_dir)
664
MIL << "downloading index " << resource << endl;
665
// create a new fetcher with a different state to transfer the
666
// file containing checksums and its signature
668
// signature checker for index. We havent got the signature from
670
SignatureFileChecker sigchecker;
672
// build the name of the index and the signature
673
OnMediaLocation idxloc(resource);
674
OnMediaLocation sigloc(resource);
675
OnMediaLocation keyloc(resource);
677
// we should not fail the download if those don't exists
678
// the checking will warn later
679
sigloc.setOptional(true);
680
keyloc.setOptional(true);
682
// calculate signature and key name
683
sigloc.changeFilename( sigloc.filename().extend(".asc") );
684
keyloc.changeFilename( keyloc.filename().extend(".key") );
686
//assert_dir(dest_dir + idxloc.filename().dirname());
688
// transfer the signature
689
fetcher.enqueue(sigloc);
690
fetcher.start( dest_dir, media );
691
// if we get the signature, update the checker
692
if ( PathInfo(dest_dir + sigloc.filename()).isExist() )
693
sigchecker = SignatureFileChecker(dest_dir + sigloc.filename());
698
fetcher.enqueue(keyloc);
699
fetcher.start( dest_dir, media );
702
// try to import the key
703
if ( PathInfo(dest_dir + keyloc.filename()).isExist() )
704
getZYpp()->keyRing()->importKey(PublicKey(dest_dir + keyloc.filename()), false);
706
WAR << "No public key specified by user for index '" << keyloc.filename() << "'"<< endl;
708
// now the index itself
709
fetcher.enqueue( idxloc, FileChecker(sigchecker) );
710
fetcher.start( dest_dir, media );
714
// this method takes all the user pointed indexes, gets them and also tries to
715
// download their signature, and verify them. After that, its parses each one
716
// to fill the checksum cache.
717
void Fetcher::Impl::downloadAndReadIndexList( MediaSetAccess &media, const Pathname &dest_dir)
719
// if there is no indexes, then just return to avoid
720
// the directory listing
721
if ( _indexes.empty() )
723
MIL << "No indexes to read." << endl;
727
for_( it_idx, _indexes.begin(), _indexes.end() )
729
if ( (*it_idx)->read )
731
DBG << "Already read index " << PathInfo(dest_dir + (*it_idx)->location.filename()) << endl;
735
// base::LogControl::TmpLineWriter shutUp;
736
downloadIndex( media, (*it_idx)->location, dest_dir );
737
// now we have the indexes in dest_dir
738
readIndex( dest_dir + (*it_idx)->location.filename(), (*it_idx)->location.filename().dirname() );
739
// Take care we don't process it again
740
MIL << "Remember read index " << PathInfo(dest_dir + (*it_idx)->location.filename()) << endl;
741
(*it_idx)->read = true;
744
MIL << "done reading indexes" << endl;
747
// start processing all fetcher jobs.
748
// it processes any user pointed index first
749
void Fetcher::Impl::start( const Pathname &dest_dir,
750
MediaSetAccess &media,
751
const ProgressData::ReceiverFnc & progress_receiver )
753
ProgressData progress(_resources.size());
754
progress.sendTo(progress_receiver);
756
downloadAndReadIndexList(media, dest_dir);
758
for ( list<FetcherJob_Ptr>::const_iterator it_res = _resources.begin(); it_res != _resources.end(); ++it_res )
761
if ( (*it_res)->flags & FetcherJob::Directory )
763
const OnMediaLocation location((*it_res)->location);
764
addDirJobs(media, location, dest_dir, (*it_res)->flags);
768
// may be this code can be factored out
769
// together with the autodiscovery of indexes
771
if ( ( _options & AutoAddChecksumsIndexes ) ||
772
( _options & AutoAddContentFileIndexes ) )
774
// if auto indexing is enabled, then we need to read the
775
// index for each file. We look only in the directory
776
// where the file is. this is expensive of course.
777
filesystem::DirContent content;
778
getDirectoryContent(media, (*it_res)->location.filename().dirname(), content);
779
// this method test for the option flags so indexes are added
780
// only if the options are enabled
781
MIL << "Autodiscovering signed indexes on '"
782
<< (*it_res)->location.filename().dirname() << "' for '"
783
<< (*it_res)->location.filename() << "'" << endl;
785
autoaddIndexes(content, media, (*it_res)->location.filename().dirname(), dest_dir);
787
// also look in the root of the media
789
getDirectoryContent(media, Pathname("/"), content);
790
// this method test for the option flags so indexes are added
791
// only if the options are enabled
792
MIL << "Autodiscovering signed indexes on '"
794
<< (*it_res)->location.filename() << "'" << endl;
796
autoaddIndexes(content, media, Pathname("/"), dest_dir);
799
provideToDest(media, (*it_res)->location, dest_dir, (*it_res)->deltafile);
801
// if the file was not transfered, and no exception, just
802
// return, as it was an optional file
803
if ( ! PathInfo(dest_dir + (*it_res)->location.filename()).isExist() )
806
// if the checksum is empty, but the checksum is in one of the
807
// indexes checksum, then add a checker
808
if ( (*it_res)->location.checksum().empty() )
810
if ( _checksums.find((*it_res)->location.filename().asString())
811
!= _checksums.end() )
813
CheckSum chksm = _checksums[(*it_res)->location.filename().asString()];
814
ChecksumFileChecker digest_check(chksm);
815
(*it_res)->checkers.push_back(digest_check);
819
// if the index checksum is empty too, we only add the checker
820
// if the AlwaysVerifyChecksum option is set on
821
if ( (*it_res)->flags & FetcherJob::AlwaysVerifyChecksum )
823
// add the checker with the empty checksum
824
ChecksumFileChecker digest_check((*it_res)->location.checksum());
825
(*it_res)->checkers.push_back(digest_check);
831
// checksum is not empty, so add a checksum checker
832
ChecksumFileChecker digest_check((*it_res)->location.checksum());
833
(*it_res)->checkers.push_back(digest_check);
836
// validate job, this throws if not valid
837
validate((*it_res)->location, dest_dir, (*it_res)->checkers);
839
if ( ! progress.incr() )
840
ZYPP_THROW(AbortRequestException());
844
/** \relates Fetcher::Impl Stream output */
845
inline std::ostream & operator<<( std::ostream & str, const Fetcher::Impl & obj )
847
for ( list<FetcherJob_Ptr>::const_iterator it_res = obj._resources.begin(); it_res != obj._resources.end(); ++it_res )
855
: _pimpl( new Impl() )
861
void Fetcher::setOptions( Fetcher::Options options )
863
_pimpl->setOptions(options);
866
Fetcher::Options Fetcher::options() const
868
return _pimpl->options();
871
void Fetcher::enqueueDigested( const OnMediaLocation &resource, const FileChecker &checker, const Pathname &deltafile )
873
_pimpl->enqueueDigested(resource, checker, deltafile);
876
void Fetcher::enqueueDir( const OnMediaLocation &resource,
878
const FileChecker &checker )
880
_pimpl->enqueueDir(resource, recursive, checker);
883
void Fetcher::enqueueDigestedDir( const OnMediaLocation &resource,
885
const FileChecker &checker )
887
_pimpl->enqueueDigestedDir(resource, recursive, checker);
891
void Fetcher::addIndex( const OnMediaLocation &resource )
893
_pimpl->addIndex(resource);
897
void Fetcher::enqueue( const OnMediaLocation &resource, const FileChecker &checker )
899
_pimpl->enqueue(resource, checker);
902
void Fetcher::addCachePath( const Pathname &cache_dir )
904
_pimpl->addCachePath(cache_dir);
907
void Fetcher::reset()
912
void Fetcher::start( const Pathname &dest_dir,
913
MediaSetAccess &media,
914
const ProgressData::ReceiverFnc & progress_receiver )
916
_pimpl->start(dest_dir, media, progress_receiver);
919
std::ostream & operator<<( std::ostream & str, const Fetcher & obj )
921
return str << *obj._pimpl;
924
/////////////////////////////////////////////////////////////////
926
///////////////////////////////////////////////////////////////////