- xmlTextReaderRead() can fail with non-zero values as well
[apt.git] / apt-pkg / rpm / rpmindexfile.cc
index a166ffa..9aaa72e 100644 (file)
@@ -17,6 +17,8 @@
 
 #ifdef HAVE_RPM
 
+#include <cassert>
+
 #include <apt-pkg/rpmindexfile.h>
 #include <apt-pkg/rpmsrcrecords.h>
 #include <apt-pkg/rpmlistparser.h>
@@ -536,14 +538,9 @@ string rpmSingleSrcIndex::ArchiveURI(string File) const
 
 string rpmRepomdIndex::ArchiveURI(string File) const
 {
-   RPMPackageData *rpmdata = RPMPackageData::Singleton();
    string Res;
 
-   //cout << Dist << File << endl;
-
    Res += URI + '/' + Dist + '/' + File;
-   //cout << "repomd archiveuri " << " " << Res << endl;
-
    return Res;
 }
 
@@ -586,18 +583,19 @@ pkgCache::PkgFileIterator rpmRepomdIndex::FindInCache(pkgCache &Cache) const
 }
 string rpmRepomdIndex::ReleaseURI(string Type) const
 {
-   RPMPackageData *rpmdata = RPMPackageData::Singleton();
-   string Res;
-   Res = URI + Dist + "/repodata/" + "repomd.xml";
-
-   //cout << "XXXXX repomd releaseuri " << Res << endl;
-   
+   string Res = URI + Dist;
+   assert( Res.size() > 0 );
+   if ( Res[Res.size() - 1] != '/' )
+     Res += '/';
+   Res += "repodata/";
+   Res += "repomd.xml";
    return Res;
 }
 
 string rpmRepomdIndex::ReleaseInfo(string Type) const
 {
    string Info = ::URI::SiteOnly(URI) + ' ';
+   assert( Dist.size() > 0 );
    if (Dist[Dist.size() - 1] == '/')
    {
       if (Dist != "/")
@@ -607,13 +605,13 @@ string rpmRepomdIndex::ReleaseInfo(string Type) const
       Info += Dist;   
    Info += " ";
    Info += Type;
-   //cout << "repomd releaseinfo " << Info << endl;
    return Info;
 };
 
 string rpmRepomdIndex::Info(string Type) const 
 {
    string Info = ::URI::SiteOnly(URI) + ' ';
+   assert( Dist.size() > 0 );
    if (Dist[Dist.size() - 1] == '/')
    {
       if (Dist != "/")
@@ -623,18 +621,22 @@ string rpmRepomdIndex::Info(string Type) const
       Info += Dist + '/' ;   
    Info += " ";
    Info += Type;
-   //cout << "repomd info " << Info << endl;
    return Info;
 }
 
 string rpmRepomdIndex::IndexURI(string Type) const
 {
-   RPMPackageData *rpmdata = RPMPackageData::Singleton();
    string Res = URI + Dist;
+   assert( Dist.size() > 0 );
    if (Dist[Dist.size() - 1] != '/') {
         Res += "/";
    }
-   Res += "repodata/primary.xml";
+   // When called with the main type it's primary.xml we want, at other
+   // times it could be eg filelists.xml
+   if (Type == "repomd" || Type == "repomd-src")
+      Res += "repodata/primary.xml";
+   else
+      Res += "repodata/" + Type;
    return Res;
 }
                                                                        /*}}}*/
@@ -654,10 +656,9 @@ bool rpmRepomdIndex::GetIndexes(pkgAcquire *Owner) const
 {
    new pkgAcqIndex(Owner,Repository,IndexURI("primary.xml"),
                   Info("primary.xml"), "primary.xml");
-// wont be needing these for a while...
-#if 0
    new pkgAcqIndex(Owner,Repository,IndexURI("filelists.xml"),
                   Info("filelists.xml"), "filelists.xml");
+#if 0
    new pkgAcqIndex(Owner,Repository,IndexURI("other.xml"),
                   Info("other.xml"), "other.xml");
 #endif
@@ -677,7 +678,6 @@ string rpmRepomdIndex::Describe(bool Short) const
 
 string rpmRepomdIndex::IndexFile(string Type) const
 {
-   //cout << "XXX indexfile " << _config->FindDir("Dir::State::lists")+URItoFileName(IndexURI(Type)) << endl;
    return _config->FindDir("Dir::State::lists")+URItoFileName(IndexURI(Type));
 };
 
@@ -692,10 +692,31 @@ string rpmRepomdIndex::ReleasePath() const
    return _config->FindDir("Dir::State::lists")+URItoFileName(ReleaseURI("release.xml"));
 }
 
+// This gets called several times per each index during cache generation,
+// only for progress percentage reporting. A rough estimate would do just
+// fine but using xmlReader appears to be cheap enough. OTOH creating a new 
+// handler like is done for rpmPkgDirIndex is hideously expensive.
+unsigned long rpmRepomdIndex::Size() const
+{
+   xmlTextReaderPtr Index;
+   unsigned long Res;
+   Index = xmlReaderForFile(IndexPath().c_str(), NULL,
+                         XML_PARSE_NONET|XML_PARSE_NOBLANKS);
+   if (Index == NULL) return 0;
+
+   if (xmlTextReaderRead(Index) == 1) {
+      xmlChar *pkgs = xmlTextReaderGetAttribute(Index, (xmlChar*)"packages");
+      Res = atoi((char*)pkgs);
+      xmlFree(pkgs);
+   } else {
+      Res = 0;
+   }
+   xmlFreeTextReader(Index);
+   return Res;
+}
 
 bool rpmRepomdIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const
 {
-   //cout << "repomd MERGE" << endl;
    string PackageFile = IndexPath();
    RPMHandler *Handler = CreateHandler();
 
@@ -709,7 +730,6 @@ bool rpmRepomdIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const
 
    // Store the IMS information
    pkgCache::PkgFileIterator File = Gen.GetCurFile();
-   //cout << "merge pkgfile " << PackageFile << endl;
    struct stat St;
    if (stat(PackageFile.c_str(),&St) != 0) 
    {
@@ -744,6 +764,25 @@ bool rpmRepomdIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const
    return true;
 }
 
+bool rpmRepomdIndex::MergeFileProvides(pkgCacheGenerator &Gen,
+                                       OpProgress &Prog) const
+{
+   string PackageFile = IndexPath();
+   RPMHandler *Handler = CreateHandler();
+   rpmListParser Parser(Handler);
+   if (_error->PendingError() == true) {
+      delete Handler;
+      return _error->Error(_("Problem opening %s"),PackageFile.c_str());
+   }
+   // We call SubProgress with Size(), since we won't call SelectFile() here.
+   Prog.SubProgress(Size(),Info("pkglist"));
+   if (Gen.MergeFileProvides(Parser) == false)
+      return _error->Error(_("Problem with MergeFileProvides %s"),
+                          PackageFile.c_str());
+   delete Handler;
+   return true;
+}
+
 pkgSrcRecords::Parser *rpmRepomdSrcIndex::CreateSrcParser() const
 {
    return new rpmSrcRecordParser(IndexPath(), this);
@@ -906,7 +945,6 @@ class rpmSLTypeGen : public pkgSourceList::Type
       else
         BaseURI = URI + Dist + '/';
 
-      //cout << "XXXX GetRepo " << URI << " " << Dist << " " << BaseURI << endl;
       Rep = new pkgRepository(URI,Dist,Vendor,BaseURI);
       RepList.push_back(Rep);
       return Rep;