5 #include "zypp/base/Logger.h"
6 #include "zypp/base/String.h"
7 #include "zypp/OnMediaLocation.h"
8 #include "zypp/MediaSetAccess.h"
9 #include "zypp/Fetcher.h"
10 #include "zypp/Locale.h"
11 #include "zypp/ZConfig.h"
12 #include "zypp/repo/MediaInfoDownloader.h"
13 #include "zypp/repo/susetags/Downloader.h"
14 #include "zypp/parser/ParseException.h"
15 #include "zypp/parser/susetags/RepoIndex.h"
16 #include "zypp/base/UserRequestException.h"
17 #include "zypp/KeyContext.h" // for SignatureFileChecker
20 using namespace zypp::parser;
21 using namespace zypp::parser::susetags;
30 Downloader::Downloader( const RepoInfo &repoinfo )
31 : repo::Downloader(repoinfo)
35 RepoStatus Downloader::status( MediaSetAccess &media )
37 Pathname content = media.provideFile( repoInfo().path() + "/content");
38 // the media.1 is always in the root of the media, not like the content
39 // file which is in the path() location
40 Pathname mediafile = media.provideFile( "/media.1/media" );
42 return RepoStatus(content) && RepoStatus(mediafile);
45 void Downloader::download( MediaSetAccess &media,
46 const Pathname &dest_dir,
47 const ProgressData::ReceiverFnc & progress )
49 downloadMediaInfo( dest_dir, media );
51 SignatureFileChecker sigchecker/*(repoInfo().name())*/;
53 Pathname sig = repoInfo().path() + "/content.asc";
54 if ( media.doesFileExist(sig) )
56 this->enqueue( OnMediaLocation( sig, 1 ) );
57 this->start( dest_dir, media );
60 sigchecker = SignatureFileChecker( dest_dir + sig/*, repoInfo().name() */);
63 Pathname key = repoInfo().path() + "/content.key";
64 if ( media.doesFileExist(key) )
67 context.setRepoInfo(repoInfo());
68 this->enqueue( OnMediaLocation( key, 1 ) );
69 this->start( dest_dir, media );
71 sigchecker.addPublicKey(dest_dir + key, context);
74 if ( ! repoInfo().gpgCheck() )
76 WAR << "Signature checking disabled in config of repository " << repoInfo().alias() << endl;
78 this->enqueue( OnMediaLocation( repoInfo().path() + "/content", 1 ),
79 repoInfo().gpgCheck() ? FileChecker(sigchecker) : FileChecker(NullFileChecker()) );
80 this->start( dest_dir, media );
85 // Content file first to get the repoindex
87 Pathname inputfile( dest_dir + repoInfo().path() + "/content" );
88 ContentFileReader content;
89 content.setRepoIndexConsumer( bind( &Downloader::consumeIndex, this, _1 ) );
90 content.parse( inputfile );
94 ZYPP_THROW( ParseException( (dest_dir+repoInfo().path()).asString() + ": " + "No repository index in content file." ) );
96 MIL << "RepoIndex: " << _repoindex << endl;
97 if ( _repoindex->metaFileChecksums.empty() )
99 ZYPP_THROW( ParseException( (dest_dir+repoInfo().path()).asString() + ": " + "No metadata checksums in content file." ) );
101 if ( _repoindex->signingKeys.empty() )
103 WAR << "No signing keys defined." << endl;
107 descr_dir = _repoindex->descrdir; // path below reporoot
108 //_datadir = _repoIndex->datadir; // path below reporoot
111 for_( it, _repoindex->metaFileChecksums.begin(), _repoindex->metaFileChecksums.end() )
113 // omit unwanted translations
114 if ( str::hasPrefix( it->first, "packages" ) )
116 std::string rest( str::stripPrefix( it->first, "packages" ) );
117 if ( ! ( rest.empty()
122 || rest == ".en.gz" ) )
124 // Not 100% correct as we take each fallback of textLocale
125 Locale toParse( ZConfig::instance().textLocale() );
126 while ( toParse != Locale::noCode )
128 if ( rest == ("."+toParse.code()) || (rest == ("."+toParse.code()+".gz")) )
130 toParse = toParse.fallback();
132 if ( toParse == Locale::noCode )
139 else if ( it->first == "patterns.pat"
140 || it->first == "patterns.pat.gz" )
142 // take all patterns in one go
144 else if ( str::endsWith( it->first, ".pat" )
145 || str::endsWith( it->first, ".pat.gz" ) )
148 // *** see also zypp/parser/susetags/RepoParser.cc ***
150 // omit unwanted patterns, see https://bugzilla.novell.com/show_bug.cgi?id=298716
151 // expect "<name>.<arch>.pat[.gz]", <name> might contain additional dots
152 // split at dots, take .pat or .pat.gz into account
154 std::vector<std::string> patparts;
155 unsigned archpos = 2;
156 // expect "<name>.<arch>.pat[.gz]", <name> might contain additional dots
157 unsigned count = str::split( it->first, std::back_inserter(patparts), "." );
158 if ( patparts[count-1] == "gz" )
161 if ( count > archpos )
163 try // might by an invalid architecture
165 Arch patarch( patparts[count-archpos] );
166 if ( !patarch.compatibleWith( ZConfig::instance().systemArchitecture() ) )
168 // discard, if not compatible
169 MIL << "Discarding pattern " << it->first << endl;
173 catch ( const Exception & excpt )
175 WAR << "Pattern file name does not contain recognizable architecture: " << it->first << endl;
176 // keep .pat file if it doesn't contain an recognizable arch
180 MIL << "adding job " << it->first << endl;
181 OnMediaLocation location( repoInfo().path() + descr_dir + it->first, 1 );
182 location.setChecksum( it->second );
183 this->enqueueDigested(location);
186 for_( it, _repoindex->mediaFileChecksums.begin(), _repoindex->mediaFileChecksums.end() )
188 // Repo adopts license files listed in HASH
189 if ( it->first != "license.tar.gz" )
192 MIL << "adding job " << it->first << endl;
193 OnMediaLocation location( repoInfo().path() + it->first, 1 );
194 location.setChecksum( it->second );
195 this->enqueueDigested(location);
198 for_( it, _repoindex->signingKeys.begin(),_repoindex->signingKeys.end() )
200 MIL << "adding job " << it->first << endl;
201 OnMediaLocation location( repoInfo().path() + it->first, 1 );
202 location.setChecksum( it->second );
203 this->enqueueDigested(location);
206 this->start( dest_dir, media );
209 void Downloader::consumeIndex( const RepoIndex_Ptr & data_r )
211 MIL << "Consuming repo index" << endl;