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 & rootpath,
00168 const Pathname & subdir,
00169 bool recursive);
00171 void parse( const Pathname & reporoot_r );
00172 public:
00173
00174 private:
00175 data::RecordId _repositoryId;
00176 data::ResolvableDataConsumer & _consumer;
00177 ProgressData _ticks;
00178
00179 private:
00180 };
00182
00184
00185
00186
00187
00188 void RepoParser::Impl::parse( const Pathname & reporoot_r )
00189 {
00190 extract_packages_from_directory( reporoot_r, Pathname(), true );
00191
00192
00193
00194 if ( ! _ticks.toMax() )
00195 ZYPP_THROW( AbortRequestException() );
00196 }
00197
00198 int RepoParser::Impl::extract_packages_from_directory( const Pathname & rootpath,
00199 const Pathname & subdir,
00200 bool recursive)
00201 {
00202 using target::rpm::RpmHeader;
00203 Pathname path = rootpath / subdir;
00204 Pathname filename;
00205 PathInfo magic;
00206 bool distro_magic, pkginfo_magic;
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 magic = PathInfo( path + "/RC_SKIP" );
00217 if (magic.isExist()) {
00218 return 0;
00219 }
00220
00221 magic = PathInfo( path + "/RC_RECURSIVE" );
00222 if (magic.isExist())
00223 recursive = true;
00224
00225 magic = PathInfo( path + "/RC_BY_DISTRO" );
00226 distro_magic = magic.isExist();
00227
00228 pkginfo_magic = true;
00229 magic = PathInfo( path + "/RC_IGNORE_PKGINFO" );
00230 if (magic.isExist())
00231 pkginfo_magic = false;
00232
00233
00234 std::list<std::string> dircontent;
00235 if (filesystem::readdir( dircontent, path, false) != 0) {
00236 ERR << "readdir " << path << " failed" << endl;
00237 return -1;
00238 }
00239
00240 for (std::list<std::string>::const_iterator it = dircontent.begin(); it != dircontent.end(); ++it) {
00241 Pathname file_path = path + *it;
00242 PathInfo file_info( file_path );
00243 if (recursive && file_info.isDir())
00244 {
00245 extract_packages_from_directory( rootpath, subdir / *it, recursive );
00246 }
00247 else if (file_info.isFile() && file_path.extension() == ".rpm" )
00248 {
00249 RpmHeader::constPtr header = RpmHeader::readPackage( file_path, RpmHeader::NOSIGNATURE );
00250 #warning FIX creation of Package from src.rpm header
00251
00252 data::Package_Ptr package = makePackageDataFromHeader( header, NULL, subdir / *it, _repositoryId );
00253 if (package != NULL) {
00254 DBG << "Adding package " << *package << endl;
00255 _consumer.consumePackage( _repositoryId, package );
00256 }
00257 }
00258 }
00259 return 0;
00260 }
00262
00263
00264
00266
00268
00269
00270
00271
00272 RepoParser::RepoParser( const data::RecordId & repositoryId_r,
00273 data::ResolvableDataConsumer & consumer_r,
00274 const ProgressData::ReceiverFnc & fnc_r )
00275 : _pimpl( new Impl( repositoryId_r, consumer_r, fnc_r ) )
00276 {}
00277
00279
00280
00281
00282
00283 RepoParser::~RepoParser()
00284 {}
00285
00287
00288
00289
00290
00291 void RepoParser::parse( const Pathname & reporoot_r )
00292 {
00293 _pimpl->parse( reporoot_r );
00294 }
00295
00297 }
00300 }
00303 }