00001
00002
00003
00004
00005
00006
00007
00008
00012 #include <iostream>
00013
00014 #include <boost/regex.hpp>
00015
00016 #include "zypp/base/Logger.h"
00017
00018 #include "zypp/source/susetags/PackagesParser.h"
00019 #include "zypp/parser/tagfile/TagFileParser.h"
00020 #include "zypp/Arch.h"
00021 #include "zypp/Package.h"
00022 #include "zypp/CapFactory.h"
00023 #include "zypp/CapSet.h"
00024
00025 #include "zypp/ZYppFactory.h"
00026
00027 using std::endl;
00028
00030 namespace zypp
00031 {
00032
00033 namespace source
00034 {
00035
00036 namespace susetags
00037 {
00038
00039 using namespace parser::tagfile;
00040
00041
00042 struct PackageDiskUsageParser : public parser::tagfile::TagFileParser
00043 {
00044 PkgDiskUsage result;
00045 NVRAD _current_nvrad;
00046 bool _pkg_pending;
00047 boost::regex sizeEntryRX;
00048
00049 virtual void beginParse()
00050 {
00051 _pkg_pending = false;
00052 sizeEntryRX = boost::regex("^(.*/)[[:space:]]([[:digit:]]+)[[:space:]]([[:digit:]]+)[[:space:]]([[:digit:]]+)[[:space:]]([[:digit:]]+)$");
00053 }
00054
00055
00056 virtual void consume( const SingleTag & stag_r )
00057 {
00058 if ( stag_r.name == "Pkg" )
00059 {
00060 std::vector<std::string> words;
00061 if ( str::split( stag_r.value, std::back_inserter(words) ) != 4 )
00062 ZYPP_THROW( ParseException( "packages.DU - Expected [name version release arch], got [" + stag_r.value +"]") );
00063
00064 _pkg_pending = true;
00065 _current_nvrad = NVRAD( words[0], Edition(words[1],words[2]), Arch(words[3]) );
00066 }
00067 else if ( stag_r.name == "Ver" )
00068 {
00069 if (stag_r.value != "2.0")
00070 WAR << "packages.DU " << stag_r.name << "=" << stag_r.value << ", should be 2.0" << endl;
00071 }
00072 else
00073 {
00074
00075 ERR << "packages.DU - ERROR! found unexpected tag " << stag_r.name << std::endl;
00076 }
00077 }
00078
00079
00080 virtual void consume( const MultiTag & mtag_r )
00081 {
00082 if ( ! _pkg_pending )
00083 return;
00084
00085 if ( mtag_r.name == "Dir" )
00086 {
00087 DiskUsage usage;
00088 for (std::list<std::string>::const_iterator it = mtag_r.values.begin(); it != mtag_r.values.end(); ++it )
00089 {
00090 boost::smatch what;
00091 if(boost::regex_match(*it, what, sizeEntryRX, boost::match_extra))
00092 {
00093
00094
00095 usage.add( what[1], str::strtonum<unsigned int>(what[2]) + str::strtonum<unsigned int>(what[3]), str::strtonum<unsigned int>(what[4]) + str::strtonum<unsigned int>(what[5]));
00096 }
00097 else
00098 {
00099 ZYPP_THROW( ParseException( std::string("Error parsing package size entry") + "[" + *it + "]" ) );
00100 }
00101 }
00102 result[_current_nvrad] = usage;
00103 _pkg_pending = false;
00104 }
00105 }
00106
00107 virtual void endParse()
00108 {
00109
00110 }
00111 };
00112
00113
00114 struct PackagesParser : public parser::tagfile::TagFileParser
00115 {
00116 PkgContent _result;
00117
00118 Source_Ref _source;
00119 SuseTagsImpl::Ptr _sourceImpl;
00120
00121 bool _isPendingPkg;
00122 PkgImplPtr _pkgImpl;
00123 SrcPkgImplPtr _srcPkgImpl;
00124 NVRAD _nvrad;
00125 bool _isShared;
00126
00127 Arch _system_arch;
00128
00129 PackagesParser(Source_Ref source, SuseTagsImpl::Ptr sourceimpl)
00130 : _source( source )
00131 , _sourceImpl( sourceimpl )
00132 , _isPendingPkg( false )
00133 , _isShared( false )
00134 {
00135 ZYpp::Ptr z = getZYpp();
00136 _system_arch = z->architecture();
00137 }
00138
00139 PkgContent result() const
00140 { return _result; }
00141
00142 void collectPkg()
00143 {
00144 if ( _isPendingPkg )
00145 {
00146 _pkgImpl->_sourceImpl = _sourceImpl;
00147
00148
00149 if ( !_isShared )
00150 {
00151 _pkgImpl->_data_index = _pkgImpl->_nvra;
00152 _sourceImpl->_is_shared[ _pkgImpl->_nvra] = false;
00153 }
00154 else
00155 {
00156 _sourceImpl->_is_shared[ _pkgImpl->_nvra] = true;
00157 }
00158
00159 if (_srcPkgImpl == NULL
00160 && _nvrad.arch.compatibleWith( _system_arch ) )
00161 {
00162 _result.insert( PkgContent::value_type( _nvrad, _pkgImpl ) );
00163 }
00164 _isPendingPkg = false;
00165 }
00166 }
00167
00168 void collectDeps( const std::list<std::string> & depstr_r, CapSet & capset )
00169 {
00170 for ( std::list<std::string>::const_iterator it = depstr_r.begin();
00171 it != depstr_r.end(); ++it )
00172 {
00173 try {
00174 capset.insert( CapFactory().parse( ResTraits<Package>::kind, *it ) );
00175 }
00176 catch (Exception & excpt_r) {
00177 ZYPP_THROW( ParseException("Bad source ["+ _source.alias() +"] at URL:[" + _source.url().asString() + "]. Can't parse capability: [" + *it + "]" ) );
00178 }
00179 }
00180 }
00181
00182
00183 virtual void consume( const SingleTag & stag_r )
00184 {
00185 if ( stag_r.name == "Pkg" )
00186 {
00187
00188
00189
00190 collectPkg();
00191
00192 _isShared = false;
00193 std::vector<std::string> words;
00194 str::split( stag_r.value, std::back_inserter(words) );
00195
00196 if ( str::split( stag_r.value, std::back_inserter(words) ) != 4 )
00197 ZYPP_THROW( ParseException("Bad source ["+ _source.alias() +"] at URL:[" + _source.url().asString() + "]. error, we expected NVRA here, got: " + stag_r.value ) );
00198
00199 std::string arch = words[3];
00200 #warning read comment in file
00201
00202
00203
00204
00205
00206 if (arch == "src"
00207 || arch == "nosrc")
00208 {
00209 arch = "noarch";
00210 _srcPkgImpl = SrcPkgImplPtr( new source::susetags::SuseTagsSrcPackageImpl( _source ) );
00211 }
00212 else
00213 _srcPkgImpl = NULL;
00214
00215 _pkgImpl = PkgImplPtr( new source::susetags::SuseTagsPackageImpl( _source ) );
00216 _nvrad = NVRAD( words[0], Edition( words[1], words[2] ), Arch( arch ) );
00217 _pkgImpl->_nvra = NVRA( words[0], Edition( words[1], words[2] ), Arch( arch ) );
00218
00219 _isPendingPkg = true;
00220
00221 }
00222 else if ( stag_r.name == "Cks" )
00223 {
00224 std::vector<std::string> words;
00225 if ( str::split( stag_r.value, std::back_inserter(words) ) != 2 )
00226 ZYPP_THROW( ParseException("Bad source ["+ _source.alias() +"] at URL:[" + _source.url().asString() + "]. Key: [" + stag_r.name + "] - Expected [type checksum], got [" + stag_r.value +"]"));
00227
00228 _pkgImpl->_checksum = CheckSum(words[0], words[1]);
00229 }
00230 else if ( stag_r.name == "Shr" )
00231 {
00232
00233 std::vector<std::string> words;
00234 str::split( stag_r.value, std::back_inserter(words) );
00235
00236 if ( str::split( stag_r.value, std::back_inserter(words) ) != 4 )
00237 ZYPP_THROW( ParseException("Bad source ["+ _source.alias() +"] at URL:[" + _source.url().asString() + "]. Shr tag is wrong, expected NVRA, got: " + stag_r.value ) );
00238
00239 std::string arch = words[3];
00240 NVRA shared_desc( words[0], Edition( words[1], words[2] ), Arch(arch));
00241 XXX << "package " << _nvrad << " shares data with " << shared_desc << std::endl;
00242 _isShared = true;
00243 _pkgImpl->_data_index = shared_desc;
00244
00245
00246
00247
00248 _sourceImpl->_provides_shared_data[ _pkgImpl->_data_index] = true;
00249 }
00250 if ( stag_r.name == "Grp" )
00251 {
00252 _pkgImpl->_group = stag_r.value;
00253 }
00254 if ( stag_r.name == "Lic" )
00255 {
00256 _pkgImpl->_license = stag_r.value;
00257 }
00258 if ( stag_r.name == "Tim" )
00259 {
00260 _pkgImpl->_buildtime = Date(str::strtonum<time_t>(stag_r.value));
00261 }
00262 if ( stag_r.name == "Siz" )
00263 {
00264 std::vector<std::string> words;
00265 if ( str::split( stag_r.value, std::back_inserter(words) ) != 2 )
00266 ZYPP_THROW( ParseException("Bad source ["+ _source.alias() +"] at URL:[" + _source.url().asString() + "]. Siz tag wrong. Got [" + stag_r.value + "]" ) );
00267
00268 _pkgImpl->_archivesize = str::strtonum<unsigned long>(words[0]);
00269 _pkgImpl->_size = str::strtonum<unsigned long>(words[1]);
00270 }
00271 if ( stag_r.name == "Loc" )
00272 {
00273 std::vector<std::string> words;
00274 unsigned int howmany = str::split( stag_r.value, std::back_inserter(words) );
00275 _pkgImpl->_media_number = 1;
00276 if ( howmany >= 2 )
00277 {
00278 _pkgImpl->_media_number = str::strtonum<unsigned int>(words[0]);
00279
00280 _pkgImpl->_location = _sourceImpl->sourceDir( (howmany > 2) ? words[2] : _nvrad.arch.asString() ) + words[1];
00281 }
00282 else
00283 {
00284 ZYPP_THROW( ParseException("Bad source ["+ _source.alias() +"] at URL:[" + _source.url().asString() + "]. Bad [Loc] tag. Got: [" + stag_r.value + "]"));
00285 }
00286
00287 }
00288 }
00289
00290
00291 virtual void consume( const MultiTag & mtag_r )
00292 {
00293 if ( ! _isPendingPkg )
00294 return;
00295
00296 if ( mtag_r.name == "Prv" )
00297 {
00298 collectDeps( mtag_r.values, _nvrad[Dep::PROVIDES] );
00299 }
00300 else if ( mtag_r.name == "Prq" )
00301 {
00302 collectDeps( mtag_r.values, _nvrad[Dep::PREREQUIRES] );
00303 }
00304 else if ( mtag_r.name == "Req" )
00305 {
00306 collectDeps( mtag_r.values, _nvrad[Dep::REQUIRES] );
00307 }
00308 else if ( mtag_r.name == "Con" )
00309 {
00310 collectDeps( mtag_r.values, _nvrad[Dep::CONFLICTS] );
00311 }
00312 else if ( mtag_r.name == "Obs" )
00313 {
00314 collectDeps( mtag_r.values, _nvrad[Dep::OBSOLETES] );
00315 }
00316 else if ( mtag_r.name == "Rec" )
00317 {
00318 collectDeps( mtag_r.values, _nvrad[Dep::RECOMMENDS] );
00319 }
00320 else if ( mtag_r.name == "Sup" )
00321 {
00322 collectDeps( mtag_r.values, _nvrad[Dep::SUPPLEMENTS] );
00323 }
00324 else if ( mtag_r.name == "Sug" )
00325 {
00326 collectDeps( mtag_r.values, _nvrad[Dep::SUGGESTS] );
00327 }
00328 else if ( mtag_r.name == "Fre" )
00329 {
00330 collectDeps( mtag_r.values, _nvrad[Dep::FRESHENS] );
00331 }
00332 else if ( mtag_r.name == "Enh" )
00333 {
00334 collectDeps( mtag_r.values, _nvrad[Dep::ENHANCES] );
00335 }
00336 else if ( mtag_r.name == "Key" )
00337 {
00338 _pkgImpl->_keywords = mtag_r.values;
00339 }
00340 else if ( mtag_r.name == "Aut" )
00341 {
00342
00343 _pkgImpl->_authors = mtag_r.values;
00344 }
00345 }
00346
00347 virtual void endParse()
00348 {
00349
00350 collectPkg();
00351 }
00352 };
00353
00355
00356 PkgContent parsePackages( Source_Ref source_r, SuseTagsImpl::Ptr sourceImpl_r, const Pathname & file_r )
00357 {
00358 MIL << "Starting to parse packages " << file_r << std::endl;
00359 PackagesParser p( source_r, sourceImpl_r );
00360 try
00361 {
00362 p.parse( file_r );
00363 }
00364 catch(zypp::parser::tagfile::ParseException &e)
00365 {
00366 ZYPP_CAUGHT(e);
00367 ERR << "Source [" << source_r.alias() << "] at URL:[" << source_r.url().asString() << "] has a broken packages file." << std::endl;
00368 ZYPP_RETHROW(e);
00369 }
00370 return p.result();
00371 }
00372
00373 PkgDiskUsage parsePackagesDiskUsage( const Pathname & file_r )
00374 {
00375 MIL << "Starting to parse packages disk usage " << file_r << std::endl;
00376 PackageDiskUsageParser duParser;
00377 try
00378 {
00379 duParser.parse(file_r);
00380 }
00381 catch(zypp::parser::tagfile::ParseException &e)
00382 {
00383 ZYPP_CAUGHT(e);
00384 ERR << "Broken disk usage file " << file_r << ". Ignoring." << std::endl;
00385 ZYPP_RETHROW(e);
00386 }
00387 return duParser.result;
00388 }
00389
00391 }
00394 }
00397 }