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