5 #include "zypp/base/LogTools.h"
6 #include "zypp/base/Gettext.h"
7 #include "zypp/base/String.h"
8 #include "zypp/base/Regex.h"
9 #include "zypp/OnMediaLocation.h"
10 #include "zypp/MediaSetAccess.h"
11 #include "zypp/Fetcher.h"
12 #include "zypp/Locale.h"
13 #include "zypp/ZConfig.h"
14 #include "zypp/repo/MediaInfoDownloader.h"
15 #include "zypp/repo/susetags/Downloader.h"
16 #include "zypp/parser/ParseException.h"
17 #include "zypp/parser/susetags/RepoIndex.h"
18 #include "zypp/base/UserRequestException.h"
21 using namespace zypp::parser;
22 using namespace zypp::parser::susetags;
31 Downloader::Downloader( const RepoInfo &repoinfo, const Pathname &delta_dir )
32 : repo::Downloader(repoinfo), _delta_dir(delta_dir)
36 RepoStatus Downloader::status( MediaSetAccess &media )
38 Pathname content = media.provideFile( repoInfo().path() + "/content");
39 // the media.1 is always in the root of the media, not like the content
40 // file which is in the path() location
41 Pathname mediafile = media.provideFile( "/media.1/media" );
43 return RepoStatus(content) && RepoStatus(mediafile);
46 // search old repository file file to run the delta algorithm on
47 static Pathname search_deltafile( const Pathname &dir, const Pathname &file )
49 Pathname deltafile(dir + file.basename());
50 if (PathInfo(deltafile).isExist())
56 /** \todo: Downloading/sigcheck of master index shoudl be common in base class */
57 void Downloader::download( MediaSetAccess &media,
58 const Pathname &dest_dir,
59 const ProgressData::ReceiverFnc & progress )
61 downloadMediaInfo( dest_dir, media );
63 Pathname masterIndex( repoInfo().path() / "/content" );
64 defaultDownloadMasterIndex( media, dest_dir, masterIndex );
66 // Content file first to get the repoindex
68 Pathname inputfile( dest_dir / masterIndex );
69 ContentFileReader content;
70 content.setRepoIndexConsumer( bind( &Downloader::consumeIndex, this, _1 ) );
71 content.parse( inputfile );
75 ZYPP_THROW( ParseException( (dest_dir+repoInfo().path()).asString() + ": " + "No repository index in content file." ) );
77 MIL << "RepoIndex: " << _repoindex << endl;
78 if ( _repoindex->metaFileChecksums.empty() )
80 ZYPP_THROW( ParseException( (dest_dir+repoInfo().path()).asString() + ": " + "No metadata checksums in content file." ) );
82 if ( _repoindex->signingKeys.empty() )
84 WAR << "No signing keys defined." << endl;
88 Pathname descr_dir = _repoindex->descrdir; // path below reporoot
89 //_datadir = _repoIndex->datadir; // path below reporoot
91 std::map<std::string,RepoIndex::FileChecksumMap::const_iterator> availablePackageTranslations;
93 for_( it, _repoindex->metaFileChecksums.begin(), _repoindex->metaFileChecksums.end() )
95 // omit unwanted translations
96 if ( str::hasPrefix( it->first, "packages" ) )
98 static const str::regex rx_packages( "^packages((.gz)?|(.([^.]*))(.gz)?)$" );
100 if ( str::regex_match( it->first, what, rx_packages ) )
102 if ( what[4].empty() // packages(.gz)?
105 { ; /* always downloaded */ }
106 else if ( what[4] == "FL" )
107 { continue; /* never downloaded */ }
110 // remember and decide later
111 availablePackageTranslations[what[4]] = it;
118 else if ( it->first == "patterns.pat"
119 || it->first == "patterns.pat.gz" )
121 // take all patterns in one go
123 else if ( str::endsWith( it->first, ".pat" )
124 || str::endsWith( it->first, ".pat.gz" ) )
127 // *** see also zypp/parser/susetags/RepoParser.cc ***
129 // omit unwanted patterns, see https://bugzilla.novell.com/show_bug.cgi?id=298716
130 // expect "<name>.<arch>.pat[.gz]", <name> might contain additional dots
131 // split at dots, take .pat or .pat.gz into account
133 std::vector<std::string> patparts;
134 unsigned archpos = 2;
135 // expect "<name>.<arch>.pat[.gz]", <name> might contain additional dots
136 unsigned count = str::split( it->first, std::back_inserter(patparts), "." );
137 if ( patparts[count-1] == "gz" )
140 if ( count > archpos )
142 try // might by an invalid architecture
144 Arch patarch( patparts[count-archpos] );
145 if ( !patarch.compatibleWith( ZConfig::instance().systemArchitecture() ) )
147 // discard, if not compatible
148 MIL << "Discarding pattern " << it->first << endl;
152 catch ( const Exception & excpt )
154 WAR << "Pattern file name does not contain recognizable architecture: " << it->first << endl;
155 // keep .pat file if it doesn't contain an recognizable arch
159 MIL << "adding job " << it->first << endl;
160 OnMediaLocation location( repoInfo().path() + descr_dir + it->first, 1 );
161 location.setChecksum( it->second );
162 enqueueDigested(location, FileChecker(), search_deltafile(_delta_dir + descr_dir, it->first));
165 // check whether to download more package translations:
167 auto fnc_checkTransaltions( [&]( const Locale & locale_r ) {
168 for ( Locale toGet( locale_r ); toGet != Locale::noCode; toGet = toGet.fallback() )
170 auto it( availablePackageTranslations.find( toGet.code() ) );
171 if ( it != availablePackageTranslations.end() )
173 auto mit( it->second );
174 MIL << "adding job " << mit->first << endl;
175 OnMediaLocation location( repoInfo().path() + descr_dir + mit->first, 1 );
176 location.setChecksum( mit->second );
177 enqueueDigested(location, FileChecker(), search_deltafile(_delta_dir + descr_dir, mit->first));
182 for ( const Locale & it : ZConfig::instance().repoRefreshLocales() )
184 fnc_checkTransaltions( it );
186 fnc_checkTransaltions( ZConfig::instance().textLocale() );
189 for_( it, _repoindex->mediaFileChecksums.begin(), _repoindex->mediaFileChecksums.end() )
191 // Repo adopts license files listed in HASH
192 if ( it->first != "license.tar.gz" )
195 MIL << "adding job " << it->first << endl;
196 OnMediaLocation location( repoInfo().path() + it->first, 1 );
197 location.setChecksum( it->second );
198 enqueueDigested(location, FileChecker(), search_deltafile(_delta_dir, it->first));
201 for_( it, _repoindex->signingKeys.begin(),_repoindex->signingKeys.end() )
203 MIL << "adding job " << it->first << endl;
204 OnMediaLocation location( repoInfo().path() + it->first, 1 );
205 location.setChecksum( it->second );
206 enqueueDigested(location);
209 start( dest_dir, media );
212 void Downloader::consumeIndex( const RepoIndex_Ptr & data_r )
214 MIL << "Consuming repo index" << endl;