Imported Upstream version 15.0.0
[platform/upstream/libzypp.git] / zypp / parser / RepoFileReader.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/repo/RepoFileReader.cc
10  *
11 */
12 #include <iostream>
13 #include "zypp/base/LogTools.h"
14 #include "zypp/base/String.h"
15 #include "zypp/base/Regex.h"
16 #include "zypp/base/InputStream.h"
17 #include "zypp/base/UserRequestException.h"
18
19 #include "zypp/parser/IniDict.h"
20 #include "zypp/parser/RepoFileReader.h"
21
22 using std::endl;
23
24 ///////////////////////////////////////////////////////////////////
25 namespace zypp
26 {
27   ///////////////////////////////////////////////////////////////////
28   namespace parser
29   {
30     ///////////////////////////////////////////////////////////////////
31     namespace {
32
33       ///////////////////////////////////////////////////////////////////
34       /// \class RepoFileParser
35       /// \brief Modified \ref IniDict to allow parsing multiple 'baseurl=' entries
36       ///////////////////////////////////////////////////////////////////
37       class RepoFileParser : public IniDict
38       {
39       public:
40         RepoFileParser( const InputStream & is_r )
41         { read( is_r ); }
42
43         using IniDict::consume; // don't hide overloads we don't redefine here
44
45         virtual void consume( const std::string & section_r, const std::string & key_r, const std::string & value_r )
46         {
47           if ( key_r == "baseurl" )
48           {
49             setInBaseurls( true );
50             _baseurls[section_r].push_back( Url(value_r) );
51           }
52           else
53           {
54             setInBaseurls( false );
55             IniDict::consume( section_r, key_r, value_r );
56           }
57         }
58
59         virtual void garbageLine( const std::string & section_r, const std::string & line_r )
60         {
61           if ( _inBaseurls )
62             _baseurls[section_r].push_back( Url(line_r) );
63           else
64             IniDict::garbageLine( section_r, line_r );  // throw
65         }
66
67         std::list<Url> & baseurls( const std::string & section_r )
68         { return _baseurls[section_r]; }
69
70       private:
71         void setInBaseurls( bool yesno_r )
72         { if ( _inBaseurls != yesno_r ) _inBaseurls = yesno_r; }
73
74         DefaultIntegral<bool,false> _inBaseurls;
75         std::map<std::string,std::list<Url>> _baseurls;
76       };
77
78     } //namespace
79     ///////////////////////////////////////////////////////////////////
80
81     /**
82    * \short List of RepoInfo's from a file.
83    * \param file pathname of the file to read.
84    */
85     static void repositories_in_stream( const InputStream &is,
86                                         const RepoFileReader::ProcessRepo &callback,
87                                         const ProgressData::ReceiverFnc &progress )
88     {
89       RepoFileParser dict(is);
90       for_( its, dict.sectionsBegin(), dict.sectionsEnd() )
91       {
92         RepoInfo info;
93         info.setAlias(*its);
94         std::string proxy;
95         std::string proxyport;
96
97         for_( it, dict.entriesBegin(*its), dict.entriesEnd(*its) )
98         {
99           //MIL << (*it).first << endl;
100           if (it->first == "name" )
101             info.setName(it-> second);
102           else if ( it->first == "enabled" )
103             info.setEnabled( str::strToTrue( it->second ) );
104           else if ( it->first == "priority" )
105             info.setPriority( str::strtonum<unsigned>( it->second ) );
106           else if ( it->first == "path" )
107             info.setPath( Pathname(it->second) );
108           else if ( it->first == "type" )
109             info.setType(repo::RepoType(it->second));
110           else if ( it->first == "autorefresh" )
111             info.setAutorefresh( str::strToTrue( it->second ) );
112           else if ( it->first == "mirrorlist" && !it->second.empty())
113             info.setMirrorListUrl(Url(it->second));
114           else if ( it->first == "gpgkey" && !it->second.empty())
115           {
116             std::vector<std::string> keys;
117             str::split( it->second, std::back_inserter(keys) );
118             if ( ! keys.empty() )
119               info.setGpgKeyUrl( Url(*keys.begin()) );
120           }
121           else if ( it->first == "gpgcheck" )
122             info.setGpgCheck( str::strToTrue( it->second ) );
123           else if ( it->first == "keeppackages" )
124             info.setKeepPackages( str::strToTrue( it->second ) );
125           else if ( it->first == "service" )
126             info.setService( it->second );
127           else if ( it->first == "proxy" )
128           {
129             // Translate it into baseurl queryparams
130             // NOTE: The hack here does not add proxy to mirrorlist urls but the
131             //       original code worked without complains, so keep it for now.
132             static const str::regex ex( ":[0-9]+$" );   // portspec
133             str::smatch what;
134             if ( str::regex_match( it->second, what, ex ) )
135             {
136               proxy = it->second.substr( 0, it->second.size() - what[0].size() );
137               proxyport = what[0].substr( 1 );
138             }
139             else
140             {
141               proxy = it->second;
142             }
143           }
144           else
145             ERR << "Unknown attribute in [" << *its << "]: " << it->first << "=" << it->second << " ignored" << endl;
146         }
147
148         for ( auto & url : dict.baseurls( *its ) )
149         {
150           if ( ! proxy.empty() && url.getQueryParam( "proxy" ).empty() )
151           {
152             url.setQueryParam( "proxy", proxy );
153             url.setQueryParam( "proxyport", proxyport );
154           }
155           info.addBaseUrl( url );
156         }
157
158         info.setFilepath(is.path());
159         MIL << info << endl;
160         // add it to the list.
161         callback(info);
162         //if (!progress.tick())
163         //  ZYPP_THROW(AbortRequestException());
164       }
165     }
166
167     ///////////////////////////////////////////////////////////////////
168     //
169     //  CLASS NAME : RepoFileReader
170     //
171     ///////////////////////////////////////////////////////////////////
172
173     RepoFileReader::RepoFileReader( const Pathname & repo_file,
174                                     const ProcessRepo & callback,
175                                     const ProgressData::ReceiverFnc &progress )
176       : _callback(callback)
177     {
178       repositories_in_stream(InputStream(repo_file), _callback, progress);
179     }
180
181     RepoFileReader::RepoFileReader( const InputStream &is,
182                                     const ProcessRepo & callback,
183                                     const ProgressData::ReceiverFnc &progress )
184       : _callback(callback)
185     {
186       repositories_in_stream(is, _callback, progress);
187     }
188
189     RepoFileReader::~RepoFileReader()
190     {}
191
192
193     std::ostream & operator<<( std::ostream & str, const RepoFileReader & obj )
194     {
195       return str;
196     }
197
198   } // namespace parser
199   ///////////////////////////////////////////////////////////////////
200 } // namespace zypp
201 ///////////////////////////////////////////////////////////////////