libzypp  17.14.0
Downloader.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
9 
10 #include <fstream>
11 #include "zypp/base/String.h"
12 #include "zypp/base/LogTools.h"
13 #include "zypp/base/Function.h"
14 #include "zypp/ZConfig.h"
15 
18 #include "Downloader.h"
21 #include "zypp/parser/xml/Reader.h"
22 
23 using namespace std;
24 using namespace zypp::xml;
25 using namespace zypp::parser::yum;
26 
27 namespace zypp
28 {
29 namespace repo
30 {
31 namespace yum
32 {
33 
34 Downloader::Downloader( const RepoInfo &repoinfo , const Pathname &delta_dir)
35  : repo::Downloader(repoinfo), _delta_dir(delta_dir), _media_ptr(0L)
36 {}
37 
39 {
40  RepoStatus ret( media.provideOptionalFile( repoInfo().path() / "/repodata/repomd.xml" ) );
41  if ( !ret.empty() ) // else: mandatory master index is missing
42  ret = ret && RepoStatus( media.provideOptionalFile( "/media.1/media" ) );
43  // else: mandatory master index is missing -> stay empty
44  return ret;
45 }
46 
47 static OnMediaLocation loc_with_path_prefix( const OnMediaLocation & loc, const Pathname & prefix )
48 {
49  if (prefix.empty() || prefix == "/")
50  return loc;
51 
52  OnMediaLocation loc_with_path(loc);
53  loc_with_path.changeFilename(prefix / loc.filename());
54  return loc_with_path;
55 }
56 
57 // search old repository file file to run the delta algorithm on
58 static Pathname search_deltafile( const Pathname & dir, const Pathname & file )
59 {
60  Pathname deltafile;
61  if (!PathInfo(dir).isDir())
62  return deltafile;
63  string base = file.basename();
64  size_t hypoff = base.find("-");
65  if (hypoff != string::npos)
66  base.replace(0, hypoff + 1, "");
67  size_t basesize = base.size();
68  std::list<Pathname> retlist;
69  if (!filesystem::readdir(retlist, dir, false))
70  {
71  for_( it, retlist.begin(), retlist.end() )
72  {
73  string fn = it->asString();
74  if (fn.size() >= basesize && fn.substr(fn.size() - basesize, basesize) == base)
75  deltafile = *it;
76  }
77  }
78  return deltafile;
79 }
80 
81 bool Downloader::patches_Callback( const OnMediaLocation & loc_r, const string & id_r )
82 {
83  OnMediaLocation loc_with_path(loc_with_path_prefix(loc_r, repoInfo().path()));
84  MIL << id_r << " : " << loc_with_path << endl;
85  this->enqueueDigested(loc_with_path, FileChecker(), search_deltafile(_delta_dir + "repodata", loc_r.filename()));
86  return true;
87 }
88 
89 
90 //bool repomd_Callback2( const OnMediaLocation &loc, const ResourceType &dtype, const std::string &typestr, UserData & userData_r );
91 
93 namespace
94 {
106  struct RepomdFileReaderCallback2
107  {
108  RepomdFileReaderCallback2( const RepomdFileReader::ProcessResource & origCallback_r )
109  : _origCallback( origCallback_r )
110  {
111  addWantedLocale( ZConfig::instance().textLocale() );
112  for ( const Locale & it : ZConfig::instance().repoRefreshLocales() )
113  addWantedLocale( it );
114  }
115 
117  bool repomd_Callback2( const OnMediaLocation & loc_r, const ResourceType & dtype_r, const std::string & typestr_r )
118  {
119  // filter well known resource types
120  if ( dtype_r == ResourceType::OTHER || dtype_r == ResourceType::FILELISTS )
121  return true; // skip it
122 
123  // filter custom resource types (by string)
124  if ( dtype_r == ResourceType::NONE )
125  {
126  // susedata.LANG
127  if ( str::hasPrefix( typestr_r, "susedata." ) && ! wantLocale( Locale(typestr_r.c_str()+9) ) )
128  return true; // skip it
129  }
130 
131  // take it
132  return( _origCallback ? _origCallback( loc_r, dtype_r ) : true );
133  }
134 
135  private:
136  bool wantLocale( const Locale & locale_r ) const
137  { return _wantedLocales.count( locale_r ); }
138 
139  void addWantedLocale( Locale locale_r )
140  {
141  while ( locale_r )
142  {
143  _wantedLocales.insert( locale_r );
144  locale_r = locale_r.fallback();
145  }
146  }
147 
148  private:
151 
152  };
153 } // namespace
155 
156 bool Downloader::repomd_Callback( const OnMediaLocation & loc_r, const ResourceType & dtype_r )
157 {
158  // NOTE: Filtering of unwanted files is done in RepomdFileReaderCallback2!
159 
160  // schedule file for download
161  const OnMediaLocation & loc_with_path(loc_with_path_prefix(loc_r, repoInfo().path()));
162  this->enqueueDigested(loc_with_path, FileChecker(), search_deltafile(_delta_dir + "repodata", loc_r.filename()));
163 
164  // We got a patches file we need to read, to add patches listed
165  // there, so we transfer what we have in the queue, and
166  // queue the patches in the patches callback
167  if ( dtype_r == ResourceType::PATCHES )
168  {
169  this->start( _dest_dir, *_media_ptr );
170  // now the patches.xml file must exists
171  PatchesFileReader( _dest_dir + repoInfo().path() + loc_r.filename(),
172  bind( &Downloader::patches_Callback, this, _1, _2));
173  }
174  return true;
175 }
176 
177 void Downloader::download( MediaSetAccess & media, const Pathname & dest_dir, const ProgressData::ReceiverFnc & progressrcv )
178 {
179  downloadMediaInfo( dest_dir, media );
180 
181  Pathname masterIndex( repoInfo().path() / "/repodata/repomd.xml" );
182  defaultDownloadMasterIndex( media, dest_dir, masterIndex );
183 
184  // init the data stored in Downloader itself
185  _media_ptr = (&media);
186  _dest_dir = dest_dir;
187 
188  // init the extended data
189  RepomdFileReaderCallback2 pimpl( bind(&Downloader::repomd_Callback, this, _1, _2) );
190 
191  // setup parser
192  RepomdFileReader( dest_dir / masterIndex,
193  RepomdFileReader::ProcessResource2( bind(&RepomdFileReaderCallback2::repomd_Callback2, &pimpl, _1, _2, _3) ) );
194 
195  // ready, go!
196  start( dest_dir, media );
197 }
198 
199 } // namespace yum
200 } // namespace repo
201 } // namespace zypp
202 
203 
204