RepoParser.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00009 
00010 #include <iostream>
00011 #include "zypp/base/Logger.h"
00012 #include "zypp/base/Iterator.h"
00013 #include "zypp/base/String.h"
00014 #include "zypp/base/Regex.h"
00015 
00016 #include <zypp/target/rpm/RpmHeader.h>
00017 #include <zypp/target/rpm/RpmDb.h>
00018 
00019 #include "zypp/parser/plaindir/RepoParser.h"
00020 #include "zypp/parser/ParseException.h"
00021 #include "zypp/capability/CapabilityImpl.h"
00022 #include "zypp/PathInfo.h"
00023 #include "zypp/ResStore.h"
00024 #include "zypp/ZConfig.h"
00025 
00026 using namespace std;
00027 using namespace zypp::target::rpm;
00028 
00030 namespace zypp
00031 { 
00032 
00033 namespace parser
00034 { 
00035 
00036 namespace plaindir
00037 { 
00038 
00039 static time_t recursive_timestamp( const Pathname &dir )
00040 {
00041   time_t max = PathInfo(dir).mtime();
00042   std::list<std::string> dircontent;
00043   if (filesystem::readdir( dircontent, dir, false) != 0)
00044   {           // dont look for dot files
00045     ERR << "readdir " << dir << " failed" << endl;
00046     return 0;
00047   }
00048 
00049   for (std::list<std::string>::const_iterator it = dircontent.begin();
00050        it != dircontent.end();
00051        ++it)
00052   {
00053     Pathname dir_path = dir + *it;
00054     if ( PathInfo(dir_path).isDir())
00055     {
00056       time_t val = recursive_timestamp(dir_path);
00057       if ( val > max )
00058         max = val;
00059     }
00060   }
00061   return max;
00062 }
00063 
00064 RepoStatus dirStatus( const Pathname &dir )
00065 {
00066   RepoStatus status;
00067   time_t t = recursive_timestamp(dir);
00068   status.setTimestamp(Date(t));
00069   status.setChecksum(str::numstring(t));
00070   return status;
00071 }
00072 
00073 data::Package_Ptr makePackageDataFromHeader( const RpmHeader::constPtr header,
00074                                              set<string> * filerequires,
00075                                              const Pathname & location, data::RecordId &repoid )
00076 {
00077   if ( ! header )
00078     return 0;
00079 
00080   if ( header->isSrc() ) {
00081     WAR << "Can't make Package from SourcePackage header" << endl;
00082     return 0;
00083   }
00084 
00085   data::Package_Ptr pkg = new data::Package;
00086 
00087   pkg->name = header->tag_name();
00088 
00089   try  {
00090     pkg->edition = Edition( header->tag_version(),
00091                             header->tag_release(),
00092                             header->tag_epoch());
00093   }
00094   catch (Exception & excpt_r) {
00095     ZYPP_CAUGHT( excpt_r );
00096     WAR << "Package " << pkg->name << " has bad edition '"
00097     << (header->tag_epoch().empty()?"":(header->tag_epoch()+":"))
00098     << header->tag_version()
00099     << (header->tag_release().empty()?"":(string("-") + header->tag_release())) << "'";
00100     return 0;
00101   }
00102 
00103   Arch arch;
00104   try {
00105     pkg->arch = Arch( header->tag_arch() );
00106   }
00107   catch (Exception & excpt_r) {
00108     ZYPP_CAUGHT( excpt_r );
00109     WAR << "Package " << pkg->name << " has bad architecture '" << header->tag_arch() << "'";
00110     return 0;
00111   }
00112 
00113   pkg->deps[Dep::REQUIRES]    = header->tag_requires( filerequires );
00114   pkg->deps[Dep::PREREQUIRES] = header->tag_prerequires( filerequires );
00115   pkg->deps[Dep::CONFLICTS]   = header->tag_conflicts( filerequires );
00116   pkg->deps[Dep::OBSOLETES]   = header->tag_obsoletes( filerequires );
00117   pkg->deps[Dep::ENHANCES]    = header->tag_enhances( filerequires );
00118   pkg->deps[Dep::SUPPLEMENTS] = header->tag_supplements( filerequires );
00119   pkg->vendor                 = header->tag_vendor();
00120   pkg->installedSize          = header->tag_size();
00121   pkg->buildTime              = header->tag_buildtime();
00122   pkg->summary                = (TranslatedText)header->tag_summary();
00123   pkg->description            = (TranslatedText)header->tag_description();
00124 
00125   pkg->repositoryLocation     = location;
00126 
00127   header->tag_du( pkg->diskusage );
00128 
00129   list<string> filenames = header->tag_filenames();
00130   pkg->deps[Dep::PROVIDES] = header->tag_provides ( filerequires );
00131 
00132   for (list<string>::const_iterator filename = filenames.begin();
00133        filename != filenames.end();
00134        ++filename)
00135   {
00136     if ( capability::isInterestingFileSpec( *filename ) )
00137     {
00138       try {
00139         pkg->deps[Dep::PROVIDES].insert(capability::buildFile( ResTraits<Package>::kind, *filename ));
00140       }
00141       catch (Exception & excpt_r)
00142       {
00143         ZYPP_CAUGHT( excpt_r );
00144         WAR << "Ignoring invalid capability: " << *filename << endl;
00145       }
00146     }
00147   }
00148 
00149   return pkg;
00150 }
00151 
00152 
00156 class RepoParser::Impl
00157 {
00158   public:
00159     Impl( const data::RecordId & repositoryId_r,
00160           data::ResolvableDataConsumer & consumer_r,
00161           const ProgressData::ReceiverFnc & fnc_r )
00162     : _repositoryId( repositoryId_r )
00163     , _consumer( consumer_r )
00164     {
00165       _ticks.sendTo( fnc_r );
00166     }
00167     int extract_packages_from_directory( const Pathname & path,
00168                                          bool recursive);
00170     void parse( const Pathname & reporoot_r );
00171   public:
00172 
00173   private:
00174     data::RecordId                 _repositoryId;
00175     data::ResolvableDataConsumer & _consumer;
00176     ProgressData                   _ticks;
00177 
00178   private: // these (and _ticks) are actually scoped per parse() run.
00179 };
00181 
00183 //
00184 //      METHOD NAME : RepoParser::Impl::parse
00185 //      METHOD TYPE : void
00186 //
00187 void RepoParser::Impl::parse( const Pathname & reporoot_r )
00188 {
00189   extract_packages_from_directory( reporoot_r, true );
00190 /*if ( ! _ticks.incr() )
00191       ZYPP_THROW( AbortRequestException() );*/
00192   // Done
00193   if ( ! _ticks.toMax() )
00194     ZYPP_THROW( AbortRequestException() );
00195 }
00196 
00197 int RepoParser::Impl::extract_packages_from_directory( const Pathname & path,
00198                                                        bool recursive)
00199 {
00200   using target::rpm::RpmHeader;
00201   Pathname filename;
00202   PathInfo magic;
00203   bool distro_magic, pkginfo_magic;
00204 
00205 //   DBG << "extract_packages_from_directory(.., " << path << ", " << repo.info().alias() << ", " << recursive << ")" << endl;
00206 
00207     /*
00208       Check for magic files that indicate how to treat the
00209       directory.  The files aren't read -- it is sufficient that
00210       they exist.
00211     */
00212 
00213   magic = PathInfo( path + "/RC_SKIP" );
00214   if (magic.isExist()) {
00215     return 0;
00216   }
00217 
00218   magic = PathInfo( path + "/RC_RECURSIVE" );
00219   if (magic.isExist())
00220     recursive = true;
00221 
00222   magic = PathInfo( path + "/RC_BY_DISTRO" );
00223   distro_magic = magic.isExist();
00224 
00225   pkginfo_magic = true;
00226   magic = PathInfo( path + "/RC_IGNORE_PKGINFO" );
00227   if (magic.isExist())
00228     pkginfo_magic = false;
00229 
00230 
00231   std::list<std::string> dircontent;
00232   if (filesystem::readdir( dircontent, path, false) != 0) {           // dont look for dot files
00233     ERR << "readdir " << path << " failed" << endl;
00234     return -1;
00235   }
00236 
00237   for (std::list<std::string>::const_iterator it = dircontent.begin(); it != dircontent.end(); ++it) {
00238     Pathname file_path = path + *it;
00239     PathInfo file_info( file_path );
00240     if (recursive && file_info.isDir()) {
00241 
00242       extract_packages_from_directory( file_path, recursive );
00243 
00244     } else if (file_info.isFile() && file_path.extension() == ".rpm" ) {
00245       RpmHeader::constPtr header = RpmHeader::readPackage( file_path, RpmHeader::NOSIGNATURE );
00246 #warning FIX creation of Package from src.rpm header
00247       data::Package_Ptr package = makePackageDataFromHeader( header, NULL, *it, _repositoryId );
00248       if (package != NULL) {
00249         DBG << "Adding package " << *package << endl;
00250         _consumer.consumePackage( _repositoryId, package );
00251       }
00252     }
00253   }
00254   return 0;
00255 }
00257 //
00258 //      CLASS NAME : RepoParser
00259 //
00261 
00263 //
00264 //      METHOD NAME : RepoParser::RepoParser
00265 //      METHOD TYPE : Ctor
00266 //
00267 RepoParser::RepoParser( const data::RecordId & repositoryId_r,
00268                         data::ResolvableDataConsumer & consumer_r,
00269                         const ProgressData::ReceiverFnc & fnc_r )
00270 : _pimpl( new Impl( repositoryId_r, consumer_r, fnc_r ) )
00271 {}
00272 
00274 //
00275 //      METHOD NAME : RepoParser::~RepoParser
00276 //      METHOD TYPE : Dtor
00277 //
00278 RepoParser::~RepoParser()
00279 {}
00280 
00282 //
00283 //      METHOD NAME : RepoParser::parse
00284 //      METHOD TYPE : void
00285 //
00286 void RepoParser::parse( const Pathname & reporoot_r )
00287 {
00288   _pimpl->parse( reporoot_r );
00289 }
00290 
00292 } // namespace plaindir
00295 } // namespace parser
00298 } // namespace zypp

Generated on Tue Sep 25 19:23:02 2007 for libzypp by  doxygen 1.5.3