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( "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 << "warning 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 ERR << "Error parsing package size entry" << "[" << *it << "]" << std::endl;
00100 ZYPP_THROW( ParseException( "Dir" ) );
00101 }
00102 }
00103 result[_current_nvrad] = usage;
00104 _pkg_pending = false;
00105 }
00106 }
00107
00108 virtual void endParse()
00109 {
00110
00111 }
00112 };
00113
00114
00115 struct PackagesParser : public parser::tagfile::TagFileParser
00116 {
00117 PkgContent _result;
00118
00119 Source_Ref _source;
00120 SuseTagsImpl::Ptr _sourceImpl;
00121
00122 bool _isPendingPkg;
00123 PkgImplPtr _pkgImpl;
00124 SrcPkgImplPtr _srcPkgImpl;
00125 NVRAD _nvrad;
00126 bool _isShared;
00127
00128 Arch _system_arch;
00129
00130 PackagesParser(Source_Ref source, SuseTagsImpl::Ptr sourceimpl)
00131 : _source( source )
00132 , _sourceImpl( sourceimpl )
00133 , _isPendingPkg( false )
00134 , _isShared( false )
00135 {
00136 ZYpp::Ptr z = getZYpp();
00137 _system_arch = z->architecture();
00138 }
00139
00140 PkgContent result() const
00141 { return _result; }
00142
00143 void collectPkg()
00144 {
00145 if ( _isPendingPkg )
00146 {
00147 _pkgImpl->_sourceImpl = _sourceImpl;
00148
00149
00150 if ( !_isShared )
00151 {
00152 _pkgImpl->_data_index = _pkgImpl->_nvra;
00153 _sourceImpl->_is_shared[ _pkgImpl->_nvra] = false;
00154 }
00155 else
00156 {
00157 _sourceImpl->_is_shared[ _pkgImpl->_nvra] = true;
00158 }
00159
00160 if (_srcPkgImpl == NULL
00161 && _nvrad.arch.compatibleWith( _system_arch ) )
00162 {
00163 _result.insert( PkgContent::value_type( _nvrad, _pkgImpl ) );
00164 }
00165 _isPendingPkg = false;
00166 }
00167 }
00168
00169 void collectDeps( const std::list<std::string> & depstr_r, CapSet & capset )
00170 {
00171 for ( std::list<std::string>::const_iterator it = depstr_r.begin();
00172 it != depstr_r.end(); ++it )
00173 {
00174 try {
00175 capset.insert( CapFactory().parse( ResTraits<Package>::kind, *it ) );
00176 }
00177 catch (Exception & excpt_r) {
00178 ZYPP_CAUGHT(excpt_r);
00179 }
00180 }
00181 }
00182
00183
00184 virtual void consume( const SingleTag & stag_r )
00185 {
00186 if ( stag_r.name == "Pkg" )
00187 {
00188
00189
00190
00191 collectPkg();
00192
00193 _isShared = false;
00194 std::vector<std::string> words;
00195 str::split( stag_r.value, std::back_inserter(words) );
00196
00197 if ( str::split( stag_r.value, std::back_inserter(words) ) != 4 )
00198 ZYPP_THROW( ParseException( "Pkg error, we expected NVRA here, got: " + stag_r.value ) );
00199
00200 std::string arch = words[3];
00201 #warning read comment in file
00202
00203
00204
00205
00206
00207 if (arch == "src"
00208 || arch == "nosrc")
00209 {
00210 arch = "noarch";
00211 _srcPkgImpl = SrcPkgImplPtr( new source::susetags::SuseTagsSrcPackageImpl( _source ) );
00212 }
00213 else
00214 _srcPkgImpl = NULL;
00215
00216 _pkgImpl = PkgImplPtr( new source::susetags::SuseTagsPackageImpl( _source ) );
00217 _nvrad = NVRAD( words[0], Edition( words[1], words[2] ), Arch( arch ) );
00218 _pkgImpl->_nvra = NVRA( words[0], Edition( words[1], words[2] ), Arch( arch ) );
00219
00220 _isPendingPkg = true;
00221
00222 }
00223 else if ( stag_r.name == "Cks" )
00224 {
00225 std::vector<std::string> words;
00226 if ( str::split( stag_r.value, std::back_inserter(words) ) != 2 )
00227 ZYPP_THROW( ParseException( stag_r.name + " - Expected [type checksum], got [" + stag_r.value +"]") );
00228
00229 _pkgImpl->_checksum = CheckSum(words[0], words[1]);
00230 }
00231 else if ( stag_r.name == "Shr" )
00232 {
00233
00234 std::vector<std::string> words;
00235 str::split( stag_r.value, std::back_inserter(words) );
00236
00237 if ( str::split( stag_r.value, std::back_inserter(words) ) != 4 )
00238 ZYPP_THROW( ParseException( "Shr tag is wrong, expected NVRA, got: " + stag_r.value ) );
00239
00240 std::string arch = words[3];
00241 NVRA shared_desc( words[0], Edition( words[1], words[2] ), Arch(arch));
00242 XXX << "package " << _nvrad << " shares data with " << shared_desc << std::endl;
00243 _isShared = true;
00244 _pkgImpl->_data_index = shared_desc;
00245 }
00246 if ( stag_r.name == "Grp" )
00247 {
00248 _pkgImpl->_group = stag_r.value;
00249 }
00250 if ( stag_r.name == "Lic" )
00251 {
00252 _pkgImpl->_license = stag_r.value;
00253 }
00254 if ( stag_r.name == "Tim" )
00255 {
00256 _pkgImpl->_buildtime = Date(str::strtonum<time_t>(stag_r.value));
00257 }
00258 if ( stag_r.name == "Siz" )
00259 {
00260 std::vector<std::string> words;
00261 if ( str::split( stag_r.value, std::back_inserter(words) ) != 2 )
00262 ZYPP_THROW( ParseException( "Siz" ) );
00263
00264 _pkgImpl->_archivesize = str::strtonum<unsigned long>(words[0]);
00265 _pkgImpl->_size = str::strtonum<unsigned long>(words[1]);
00266 }
00267 if ( stag_r.name == "Loc" )
00268 {
00269 std::vector<std::string> words;
00270 unsigned int howmany = str::split( stag_r.value, std::back_inserter(words) );
00271 _pkgImpl->_media_number = 1;
00272 if ( howmany >= 2 )
00273 {
00274 _pkgImpl->_media_number = str::strtonum<unsigned int>(words[0]);
00275
00276 _pkgImpl->_location = _sourceImpl->sourceDir( (howmany > 2) ? words[2] : _nvrad.arch.asString() ) + words[1];
00277 }
00278 else
00279 {
00280 ZYPP_THROW( ParseException( "Loc" ) );
00281 }
00282
00283 }
00284 }
00285
00286
00287 virtual void consume( const MultiTag & mtag_r )
00288 {
00289 if ( ! _isPendingPkg )
00290 return;
00291
00292 if ( mtag_r.name == "Prv" )
00293 {
00294 collectDeps( mtag_r.values, _nvrad[Dep::PROVIDES] );
00295 }
00296 else if ( mtag_r.name == "Prq" )
00297 {
00298 collectDeps( mtag_r.values, _nvrad[Dep::PREREQUIRES] );
00299 }
00300 else if ( mtag_r.name == "Req" )
00301 {
00302 collectDeps( mtag_r.values, _nvrad[Dep::REQUIRES] );
00303 }
00304 else if ( mtag_r.name == "Con" )
00305 {
00306 collectDeps( mtag_r.values, _nvrad[Dep::CONFLICTS] );
00307 }
00308 else if ( mtag_r.name == "Obs" )
00309 {
00310 collectDeps( mtag_r.values, _nvrad[Dep::OBSOLETES] );
00311 }
00312 else if ( mtag_r.name == "Rec" )
00313 {
00314 collectDeps( mtag_r.values, _nvrad[Dep::RECOMMENDS] );
00315 }
00316 else if ( mtag_r.name == "Sup" )
00317 {
00318 collectDeps( mtag_r.values, _nvrad[Dep::SUPPLEMENTS] );
00319 }
00320 else if ( mtag_r.name == "Sug" )
00321 {
00322 collectDeps( mtag_r.values, _nvrad[Dep::SUGGESTS] );
00323 }
00324 else if ( mtag_r.name == "Fre" )
00325 {
00326 collectDeps( mtag_r.values, _nvrad[Dep::FRESHENS] );
00327 }
00328 else if ( mtag_r.name == "Enh" )
00329 {
00330 collectDeps( mtag_r.values, _nvrad[Dep::ENHANCES] );
00331 }
00332 else if ( mtag_r.name == "Key" )
00333 {
00334 _pkgImpl->_keywords = mtag_r.values;
00335 }
00336 else if ( mtag_r.name == "Aut" )
00337 {
00338
00339 _pkgImpl->_authors = mtag_r.values;
00340 }
00341 }
00342
00343 virtual void endParse()
00344 {
00345
00346 collectPkg();
00347 }
00348 };
00349
00351
00352 PkgContent parsePackages( Source_Ref source_r, SuseTagsImpl::Ptr sourceImpl_r, const Pathname & file_r )
00353 {
00354 MIL << "Starting to parse packages " << file_r << std::endl;
00355 PackagesParser p( source_r, sourceImpl_r );
00356 try
00357 {
00358 p.parse( file_r );
00359 }
00360 catch(zypp::parser::tagfile::ParseException &e)
00361 {
00362 ZYPP_CAUGHT(e);
00363 ERR << "Package file " << file_r << " is broken." << std::endl;
00364 return PkgContent();
00365 }
00366 return p.result();
00367 }
00368
00369 PkgDiskUsage parsePackagesDiskUsage( const Pathname & file_r )
00370 {
00371 MIL << "Starting to parse packages disk usage " << file_r << std::endl;
00372 PackageDiskUsageParser duParser;
00373 try
00374 {
00375 duParser.parse(file_r);
00376 }
00377 catch(zypp::parser::tagfile::ParseException &e)
00378 {
00379 ZYPP_CAUGHT(e);
00380 ERR << "Disk usage " << file_r << " is broken." << std::endl;
00381 return PkgDiskUsage();
00382 }
00383 return duParser.result;
00384 }
00385
00387 }
00390 }
00393 }