- support 'patterns.pat' and 'patterns.pat.gz' to read all
[platform/upstream/libzypp.git] / zypp / repo / susetags / Downloader.cc
1
2 #include <iostream>
3 #include <fstream>
4
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
18 using namespace std;
19 using namespace zypp::parser;
20 using namespace zypp::parser::susetags;
21
22 namespace zypp
23 {
24 namespace repo
25 {
26 namespace susetags
27 {
28
29 Downloader::Downloader(const Pathname &path )
30     : _path(path)
31 {
32
33 }
34
35 RepoStatus Downloader::status( MediaSetAccess &media )
36 {
37   Pathname content = media.provideFile( _path + "/content");
38   Pathname mediafile = media.provideFile( _path + "/media.1/media" );
39
40   return RepoStatus(content) && RepoStatus(mediafile);
41 }
42
43 void Downloader::download( MediaSetAccess &media,
44                            const Pathname &dest_dir,
45                            const ProgressData::ReceiverFnc & progress )
46 {
47   downloadMediaInfo( dest_dir, media );
48
49   SignatureFileChecker sigchecker;
50
51   Pathname sig = _path + "/content.asc";
52   if ( media.doesFileExist(sig) )
53   {
54     this->enqueue( OnMediaLocation( sig, 1 ) );
55     this->start( dest_dir, media );
56     this->reset();
57
58     sigchecker = SignatureFileChecker( dest_dir + sig );
59   }
60
61   Pathname key = _path + "/content.key";
62   if ( media.doesFileExist(key) )
63   {
64     this->enqueue( OnMediaLocation( key, 1 ) );
65     this->start( dest_dir, media );
66     this->reset();
67     sigchecker.addPublicKey(dest_dir + key);
68   }
69
70
71   this->enqueue( OnMediaLocation( _path + "/content", 1 ), sigchecker );
72   this->start( dest_dir, media );
73   this->reset();
74
75   Pathname descr_dir;
76
77   // Content file first to get the repoindex
78   {
79     Pathname inputfile( dest_dir +  _path + "/content" );
80     ContentFileReader content;
81     content.setRepoIndexConsumer( bind( &Downloader::consumeIndex, this, _1 ) );
82     content.parse( inputfile );
83   }
84   if ( ! _repoindex )
85   {
86     ZYPP_THROW( ParseException( (dest_dir+_path).asString() + ": " + "No repository index in content file." ) );
87   }
88   
89   // Prepare parsing
90   descr_dir = _repoindex->descrdir; // path below reporoot
91   //_datadir  = _repoIndex->datadir;  // path below reporoot
92   
93   for ( RepoIndex::FileChecksumMap::const_iterator it = _repoindex->metaFileChecksums.begin();
94         it != _repoindex->metaFileChecksums.end();
95         ++it )
96   {
97     // omit unwanted translations
98     if ( str::hasPrefix( it->first, "packages" ) )
99     {
100       std::string rest( str::stripPrefix( it->first, "packages" ) );
101       if ( ! (   rest.empty()
102               || rest == ".DU"
103               || rest == ".en"
104               || rest == ".gz"
105               || rest == ".DU.gz"
106               || rest == ".en.gz" ) )
107       {
108         // Not 100% correct as we take each fallback of textLocale
109         Locale toParse( ZConfig::instance().textLocale() );
110         while ( toParse != Locale::noCode )
111         {
112           if ( rest == ("."+toParse.code()) || (rest == ("."+toParse.code()+".gz")) )
113             break;
114           toParse = toParse.fallback();
115         }
116         if ( toParse == Locale::noCode )
117         {
118           // discard
119           continue;
120         }
121       }
122     }
123     else if ( it->first == "patterns.pat"
124               || it->first == "patterns.pat.gz" )
125     {
126       // take all patterns in one go
127     }
128     else if ( str::endsWith( it->first, ".pat" ) 
129               || str::endsWith( it->first, ".pat.gz" ) )
130     {
131
132       // *** see also zypp/parser/susetags/RepoParser.cc ***
133
134       // omit unwanted patterns, see https://bugzilla.novell.com/show_bug.cgi?id=298716
135       // expect "<name>.<arch>.pat[.gz]", <name> might contain additional dots
136       // split at dots, take .pat or .pat.gz into account
137
138       std::vector<std::string> patparts;
139       unsigned archpos = 2;
140       // expect "<name>.<arch>.pat[.gz]", <name> might contain additional dots
141       unsigned count = str::split( it->first, std::back_inserter(patparts), "." );
142       if ( patparts[count-1] == "gz" )
143           archpos++;
144
145       if ( count > archpos )
146       {
147         try                             // might by an invalid architecture
148         {
149           Arch patarch( patparts[count-archpos] );
150           if ( !patarch.compatibleWith( ZConfig::instance().systemArchitecture() ) )
151           {
152             // discard, if not compatible
153             MIL << "Discarding pattern " << it->first << endl;
154             continue;
155           }
156         }
157         catch ( const Exception & excpt )
158         {
159           WAR << "Pattern file name does not contain recognizable architecture: " << it->first << endl;
160           // keep .pat file if it doesn't contain an recognizable arch
161         }
162       }
163     }
164     MIL << "adding job " << it->first << endl;
165     OnMediaLocation location( _path + descr_dir + it->first, 1 );
166     location.setChecksum( it->second );
167     this->enqueueDigested(location);
168   }
169   
170   for ( RepoIndex::FileChecksumMap::const_iterator it = _repoindex->signingKeys.begin();
171         it != _repoindex->signingKeys.end();
172         ++it )
173   {
174     OnMediaLocation location( _path + it->first, 1 );
175     location.setChecksum( it->second );
176     this->enqueueDigested(location);
177   }
178   
179   this->start( dest_dir, media );
180 }
181
182 void Downloader::consumeIndex( const RepoIndex_Ptr & data_r )
183 {
184   MIL << "Consuming repo index" << endl;
185   _repoindex = data_r;
186 }
187
188 }// ns susetags
189 }// ns source
190 } // ns zypp