PackagesParser.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
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         /* Consume SingleTag data. */
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             //ZYPP_THROW( ParseException( "Loc" ) );
00075             ERR << "warning found unexpected tag " << stag_r.name << std::endl;
00076           }
00077         }
00078 
00079         /* Consume MulitTag data. */
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                 //zypp::parser::tagfile::dumpRegexpResults(what);
00094                 // build the disk usage info
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             // if the package does not depend on other package for its data
00149             // then use its own nvrad as an index
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                                     // only if its not a src/nosrc
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         /* Consume SingleTag data. */
00184         virtual void consume( const SingleTag & stag_r )
00185         {
00186           if ( stag_r.name == "Pkg" )
00187           {
00188             // reset
00189             // this means this is either the first package, or we just finished parsing a package and a new one is starting
00190             // collect previous pending package if needed
00191             collectPkg();
00192             // reset
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             // warning: according to autobuild, this is the wrong check
00203             //  a 'src/norsrc' packages is determined by _not_ having a "=Src:" tag in packages
00204             // However, the 'arch' string we're checking here must be remembered since
00205             // it determines the directory below the <DATADIR> where the real package
00206             // can be found.
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             // shared description tags
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               // if a 3rd value is given, use it as the directory specifier, else default to the architecture
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             // ignore path
00283           }
00284         }
00285 
00286         /* Consume MulitTag data. */
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               // MultiTag is a Set but author is a list
00339               _pkgImpl->_authors = mtag_r.values;
00340             }
00341         }
00342 
00343         virtual void endParse()
00344         {
00345           // collect last package if there is one
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     } // namespace susetags
00390   } // namespace source
00393 } // namespace zypp

Generated on Thu May 4 16:03:26 2006 for zypp by  doxygen 1.4.6