a27dd2f768ddb992ca8bbf0ac7e5238ca048ae7e
[platform/upstream/libzypp.git] / zypp / repo / yum / Downloader.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9
10 #include <fstream>
11 #include "zypp/base/String.h"
12 #include "zypp/base/Logger.h"
13 #include "zypp/base/Function.h"
14
15 #include "zypp/parser/yum/RepomdFileReader.h"
16 #include "zypp/parser/yum/PatchesFileReader.h"
17 #include "Downloader.h"
18 #include "zypp/repo/MediaInfoDownloader.h"
19 #include "zypp/base/UserRequestException.h"
20 #include "zypp/parser/xml/Reader.h"
21
22 using namespace std;
23 using namespace zypp::xml;
24 using namespace zypp::parser::yum;
25
26 namespace zypp
27 {
28 namespace repo
29 {
30 namespace yum
31 {
32
33 Downloader::Downloader( const RepoInfo &repoinfo , const Pathname &delta_dir)
34   : repo::Downloader(repoinfo), _delta_dir(delta_dir), _media_ptr(0L)
35 {
36 }
37
38
39 RepoStatus Downloader::status( MediaSetAccess &media )
40 {
41   Pathname repomd = media.provideFile( repoInfo().path() + "/repodata/repomd.xml");
42   return RepoStatus(repomd);
43 }
44
45 static OnMediaLocation
46 loc_with_path_prefix(const OnMediaLocation & loc,
47                      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,
82                                    const string &id )
83 {
84   OnMediaLocation loc_with_path(loc_with_path_prefix(loc, repoInfo().path()));
85   MIL << id << " : " << loc_with_path << endl;
86   this->enqueueDigested(loc_with_path,  FileChecker(), search_deltafile(_delta_dir + "repodata", loc.filename()));
87   return true;
88 }
89
90 bool Downloader::repomd_Callback( const OnMediaLocation &loc,
91                                   const ResourceType &dtype )
92 {
93   OnMediaLocation loc_with_path(loc_with_path_prefix(loc, repoInfo().path()));
94   MIL << dtype << " : " << loc_with_path << endl;
95
96   //! \todo do this through a ZConfig call so that it is always in sync with parser
97   // skip other
98   if ( dtype == ResourceType::OTHER )
99   {
100     MIL << "Skipping other.xml" << endl;
101     return true;
102   }
103   // skip filelists
104   if ( dtype == ResourceType::FILELISTS )
105   {
106     MIL << "Skipping filelists.xml.gz" << endl;
107     return true;
108   }
109
110   this->enqueueDigested(loc_with_path, FileChecker(), search_deltafile(_delta_dir + "repodata", loc.filename()));
111
112   // We got a patches file we need to read, to add patches listed
113   // there, so we transfer what we have in the queue, and
114   // queue the patches in the patches callback
115   if ( dtype == ResourceType::PATCHES )
116   {
117     this->start( _dest_dir, *_media_ptr );
118     // now the patches.xml file must exists
119     PatchesFileReader( _dest_dir + repoInfo().path() + loc.filename(),
120                        bind( &Downloader::patches_Callback, this, _1, _2));
121   }
122
123   return true;
124 }
125
126 /** \todo: Downloading/sigcheck of master index shoudl be common in base class */
127 void Downloader::download( MediaSetAccess &media,
128                            const Pathname &dest_dir,
129                            const ProgressData::ReceiverFnc & progressrcv )
130 {
131   Pathname masterIndex( repoInfo().path() / "/repodata/repomd.xml" );
132   defaultDownloadMasterIndex( media, dest_dir, masterIndex );
133
134   _media_ptr = (&media);
135   _dest_dir = dest_dir;
136   RepomdFileReader( dest_dir / masterIndex, bind( &Downloader::repomd_Callback, this, _1, _2));
137
138   // ready, go!
139   start( dest_dir, media );
140 }
141
142 }// ns yum
143 }// ns source
144 } // ns zypp
145
146
147