00001
00002
00003
00004
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 {
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:
00179 };
00181
00183
00184
00185
00186
00187 void RepoParser::Impl::parse( const Pathname & reporoot_r )
00188 {
00189 extract_packages_from_directory( reporoot_r, true );
00190
00191
00192
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
00206
00207
00208
00209
00210
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) {
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
00259
00261
00263
00264
00265
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
00276
00277
00278 RepoParser::~RepoParser()
00279 {}
00280
00282
00283
00284
00285
00286 void RepoParser::parse( const Pathname & reporoot_r )
00287 {
00288 _pimpl->parse( reporoot_r );
00289 }
00290
00292 }
00295 }
00298 }