libzypp  16.22.5
Downloader.cc
Go to the documentation of this file.
1 
2 #include <iostream>
3 #include <fstream>
4 
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"
19 
20 using namespace std;
21 using namespace zypp::parser;
22 using namespace zypp::parser::susetags;
23 
24 namespace zypp
25 {
26 namespace repo
27 {
28 namespace susetags
29 {
30 
31 Downloader::Downloader( const RepoInfo &repoinfo, const Pathname &delta_dir )
32  : repo::Downloader(repoinfo), _delta_dir(delta_dir)
33 {
34 }
35 
37 {
38  RepoStatus ret( media.provideOptionalFile( repoInfo().path() + "/content") );
39  if ( !ret.empty() ) // else: mandatory master index is missing
40  ret = ret && RepoStatus( media.provideOptionalFile( "/media.1/media" ) );
41  // else: mandatory master index is missing -> stay empty
42  return ret;
43 }
44 
45 // search old repository file file to run the delta algorithm on
46 static Pathname search_deltafile( const Pathname &dir, const Pathname &file )
47 {
48  Pathname deltafile(dir + file.basename());
49  if (PathInfo(deltafile).isExist())
50  return deltafile;
51  return Pathname();
52 }
53 
54 
57  const Pathname &dest_dir,
58  const ProgressData::ReceiverFnc & progress )
59 {
60  downloadMediaInfo( dest_dir, media );
61 
62  Pathname masterIndex( repoInfo().path() / "/content" );
63  defaultDownloadMasterIndex( media, dest_dir, masterIndex );
64 
65  // Content file first to get the repoindex
66  {
67  Pathname inputfile( dest_dir / masterIndex );
68  ContentFileReader content;
69  content.setRepoIndexConsumer( bind( &Downloader::consumeIndex, this, _1 ) );
70  content.parse( inputfile );
71  }
72  if ( ! _repoindex )
73  {
74  ZYPP_THROW( ParseException( (dest_dir+repoInfo().path()).asString() + ": " + "No repository index in content file." ) );
75  }
76  MIL << "RepoIndex: " << _repoindex << endl;
77  if ( _repoindex->metaFileChecksums.empty() )
78  {
79  ZYPP_THROW( ParseException( (dest_dir+repoInfo().path()).asString() + ": " + "No metadata checksums in content file." ) );
80  }
81  if ( _repoindex->signingKeys.empty() )
82  {
83  WAR << "No signing keys defined." << endl;
84  }
85 
86  // Prepare parsing
87  Pathname descr_dir = _repoindex->descrdir; // path below reporoot
88  //_datadir = _repoIndex->datadir; // path below reporoot
89 
90  std::map<std::string,RepoIndex::FileChecksumMap::const_iterator> availablePackageTranslations;
91 
92  for_( it, _repoindex->metaFileChecksums.begin(), _repoindex->metaFileChecksums.end() )
93  {
94  // omit unwanted translations
95  if ( str::hasPrefix( it->first, "packages" ) )
96  {
97  static const str::regex rx_packages( "^packages((.gz)?|(.([^.]*))(.gz)?)$" );
98  str::smatch what;
99  if ( str::regex_match( it->first, what, rx_packages ) )
100  {
101  if ( what[4].empty() // packages(.gz)?
102  || what[4] == "DU"
103  || what[4] == "en" )
104  { ; /* always downloaded */ }
105  else if ( what[4] == "FL" )
106  { continue; /* never downloaded */ }
107  else
108  {
109  // remember and decide later
110  availablePackageTranslations[what[4]] = it;
111  continue;
112  }
113  }
114  else
115  continue; // discard
116  }
117  else if ( it->first == "patterns.pat"
118  || it->first == "patterns.pat.gz" )
119  {
120  // take all patterns in one go
121  }
122  else if ( str::endsWith( it->first, ".pat" )
123  || str::endsWith( it->first, ".pat.gz" ) )
124  {
125 
126  // *** see also zypp/parser/susetags/RepoParser.cc ***
127 
128  // omit unwanted patterns, see https://bugzilla.novell.com/show_bug.cgi?id=298716
129  // expect "<name>.<arch>.pat[.gz]", <name> might contain additional dots
130  // split at dots, take .pat or .pat.gz into account
131 
132  std::vector<std::string> patparts;
133  unsigned archpos = 2;
134  // expect "<name>.<arch>.pat[.gz]", <name> might contain additional dots
135  unsigned count = str::split( it->first, std::back_inserter(patparts), "." );
136  if ( patparts[count-1] == "gz" )
137  archpos++;
138 
139  if ( count > archpos )
140  {
141  try // might by an invalid architecture
142  {
143  Arch patarch( patparts[count-archpos] );
145  {
146  // discard, if not compatible
147  MIL << "Discarding pattern " << it->first << endl;
148  continue;
149  }
150  }
151  catch ( const Exception & excpt )
152  {
153  WAR << "Pattern file name does not contain recognizable architecture: " << it->first << endl;
154  // keep .pat file if it doesn't contain an recognizable arch
155  }
156  }
157  }
158  MIL << "adding job " << it->first << endl;
159  OnMediaLocation location( repoInfo().path() + descr_dir + it->first, 1 );
160  location.setChecksum( it->second );
161  enqueueDigested(location, FileChecker(), search_deltafile(_delta_dir + descr_dir, it->first));
162  }
163 
164  // check whether to download more package translations:
165  {
166  auto fnc_checkTransaltions( [&]( const Locale & locale_r ) {
167  for ( Locale toGet( locale_r ); toGet; toGet = toGet.fallback() )
168  {
169  auto it( availablePackageTranslations.find( toGet.code() ) );
170  if ( it != availablePackageTranslations.end() )
171  {
172  auto mit( it->second );
173  MIL << "adding job " << mit->first << endl;
174  OnMediaLocation location( repoInfo().path() + descr_dir + mit->first, 1 );
175  location.setChecksum( mit->second );
176  enqueueDigested(location, FileChecker(), search_deltafile(_delta_dir + descr_dir, mit->first));
177  break;
178  }
179  }
180  });
181  for ( const Locale & it : ZConfig::instance().repoRefreshLocales() )
182  {
183  fnc_checkTransaltions( it );
184  }
185  fnc_checkTransaltions( ZConfig::instance().textLocale() );
186  }
187 
188  for_( it, _repoindex->mediaFileChecksums.begin(), _repoindex->mediaFileChecksums.end() )
189  {
190  // Repo adopts license files listed in HASH
191  if ( it->first != "license.tar.gz" )
192  continue;
193 
194  MIL << "adding job " << it->first << endl;
195  OnMediaLocation location( repoInfo().path() + it->first, 1 );
196  location.setChecksum( it->second );
197  enqueueDigested(location, FileChecker(), search_deltafile(_delta_dir, it->first));
198  }
199 
200  for_( it, _repoindex->signingKeys.begin(),_repoindex->signingKeys.end() )
201  {
202  MIL << "adding job " << it->first << endl;
203  OnMediaLocation location( repoInfo().path() + it->first, 1 );
204  location.setChecksum( it->second );
205  enqueueDigested(location);
206  }
207 
208  start( dest_dir, media );
209 }
210 
211 void Downloader::consumeIndex( const RepoIndex_Ptr & data_r )
212 {
213  MIL << "Consuming repo index" << endl;
214  _repoindex = data_r;
215 }
216 
217 }// ns susetags
218 }// ns source
219 } // ns zypp
Interface to gettext.
#define MIL
Definition: Logger.h:64
void defaultDownloadMasterIndex(MediaSetAccess &media_r, const Pathname &destdir_r, const Pathname &masterIndex_r)
Common workflow downloading a (signed) master index file.
Definition: Downloader.cc:49
bool compatibleWith(const Arch &targetArch_r) const
Compatibility relation.
Definition: Arch.cc:497
std::string asString(const DefaultIntegral< Tp, TInitial > &obj)
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:350
Describes a path on a certain media amongs as the information required to download it...
Regular expression.
Definition: Regex.h:86
static ZConfig & instance()
Singleton ctor.
Definition: Resolver.cc:122
Pathname provideOptionalFile(const Pathname &file, unsigned media_nr=1)
Provides an optional file from media media_nr.
Architecture.
Definition: Arch.h:36
void downloadMediaInfo(const Pathname &dest_dir, MediaSetAccess &media, const ProgressData::ReceiverFnc &progressrcv)
Downloads the media info (/media.1) to a local directory.
What is known about a repository.
Definition: RepoInfo.h:71
parser::susetags::RepoIndex_Ptr _repoindex
Definition: Downloader.h:68
void consumeIndex(const parser::susetags::RepoIndex_Ptr &data_r)
Content file parser consumer.
Definition: Downloader.cc:211
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition: Easy.h:27
const RepoInfo & repoInfo() const
Definition: Downloader.h:58
function< bool(const ProgressData &)> ReceiverFnc
Most simple version of progress reporting The percentage in most cases.
Definition: ProgressData.h:139
void enqueueDigested(const OnMediaLocation &resource, const FileChecker &checker=FileChecker(), const Pathname &deltafile=Pathname())
Enqueue a object for transferal, they will not be transferred until start() is called.
Definition: Fetcher.cc:831
Downloader for SUSETags (YaST2) repositories Encapsulates all the knowledge of which files have to be...
Definition: Downloader.h:34
Locale fallback() const
Return the fallback locale for this locale, if no fallback exists the empty Locale::noCode.
Definition: Locale.cc:208
unsigned split(const C_Str &line_r, TOutputIterator result_r, const C_Str &sepchars_r=" \t")
Split line_r into words.
Definition: String.h:519
LocaleSet repoRefreshLocales() const
List of locales for which translated package descriptions should be downloaded.
Definition: ZConfig.cc:974
#define WAR
Definition: Logger.h:65
Parse repoindex part from a content file.
OnMediaLocation & setChecksum(const CheckSum &val_r)
Set the files checksum.
void start(const Pathname &dest_dir, MediaSetAccess &media, const ProgressData::ReceiverFnc &progress=ProgressData::ReceiverFnc())
start the transfer to a destination directory dest_dir You have to provde a media set access media to...
Definition: Fetcher.cc:872
void setRepoIndexConsumer(const RepoIndexConsumer &fnc_r)
Consumer to call when repo index was parsed.
void download(MediaSetAccess &media, const Pathname &dest_dir, const ProgressData::ReceiverFnc &progress=ProgressData::ReceiverFnc())
Download metadata to a local directory.
Definition: Downloader.cc:56
static Pathname search_deltafile(const Pathname &dir, const Pathname &file)
Definition: Downloader.cc:46
bool endsWith(const C_Str &str_r, const C_Str &prefix_r)
alias for hasSuffix
Definition: String.h:1102
'Language[_Country]' codes.
Definition: Locale.h:49
Regular expression match result.
Definition: Regex.h:145
RepoStatus status(MediaSetAccess &media)
Status of the remote repository.
Definition: Downloader.cc:36
Base class for Exception.
Definition: Exception.h:143
bool regex_match(const std::string &s, smatch &matches, const regex &regex)
regex ZYPP_STR_REGEX regex ZYPP_STR_REGEX
Definition: Regex.h:70
Track changing files or directories.
Definition: RepoStatus.h:38
Arch systemArchitecture() const
The system architecture zypp uses.
Definition: ZConfig.cc:839
function< void(const Pathname &file)> FileChecker
Functor signature used to check files.
Definition: FileChecker.h:28
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
Definition: String.h:1037
virtual void parse(const InputStream &imput_r, const ProgressData::ReceiverFnc &fnc_r=ProgressData::ReceiverFnc())
Parse the stream.
Media access layer responsible for handling files distributed on a set of media with media change and...