]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/pkgcache.cc
merge with debian-sid
[apt.git] / apt-pkg / pkgcache.cc
index aa3e8565eb40285fa123ba2ed3d4e7c27b3e4ed4..038bd7ec4a7986706e1ae24b11fcdece6e26c8d7 100644 (file)
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description                                                         /*{{{*/
-// $Id: pkgcache.cc,v 1.32 2001/02/20 07:03:17 jgg Exp $
+// $Id: pkgcache.cc,v 1.37 2003/02/10 01:40:58 doogie Exp $
 /* ######################################################################
    
    Package Cache - Accessor code for the cache
    ##################################################################### */
                                                                        /*}}}*/
 // Include Files                                                       /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/pkgcache.h"
-#pragma implementation "apt-pkg/cacheiterators.h"
-#endif 
-
 #include <apt-pkg/pkgcache.h>
+#include <apt-pkg/policy.h>
 #include <apt-pkg/version.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/configuration.h>
+#include <apt-pkg/aptconfiguration.h>
+#include <apt-pkg/macros.h>
 
 #include <apti18n.h>
     
 #include <sys/stat.h>
 #include <unistd.h>
 
-#include <system.h>
-
+#include <ctype.h>
                                                                        /*}}}*/
 
+using std::string;
+
+
 // Cache::Header::Header - Constructor                                 /*{{{*/
 // ---------------------------------------------------------------------
 /* Simply initialize the header */
@@ -50,25 +50,30 @@ pkgCache::Header::Header()
    
    /* Whenever the structures change the major version should be bumped,
       whenever the generator changes the minor version should be bumped. */
-   MajorVersion = 3;
-   MinorVersion = 5;
+   MajorVersion = 8;
+   MinorVersion = 0;
    Dirty = false;
    
    HeaderSz = sizeof(pkgCache::Header);
    PackageSz = sizeof(pkgCache::Package);
    PackageFileSz = sizeof(pkgCache::PackageFile);
    VersionSz = sizeof(pkgCache::Version);
+   DescriptionSz = sizeof(pkgCache::Description);
    DependencySz = sizeof(pkgCache::Dependency);
    ProvidesSz = sizeof(pkgCache::Provides);
    VerFileSz = sizeof(pkgCache::VerFile);
+   DescFileSz = sizeof(pkgCache::DescFile);
    
    PackageCount = 0;
    VersionCount = 0;
+   DescriptionCount = 0;
    DependsCount = 0;
    PackageFileCount = 0;
    VerFileCount = 0;
+   DescFileCount = 0;
    ProvidesCount = 0;
    MaxVerFileSize = 0;
+   MaxDescFileSize = 0;
    
    FileList = 0;
    StringList = 0;
@@ -87,8 +92,10 @@ bool pkgCache::Header::CheckSizes(Header &Against) const
        PackageSz == Against.PackageSz &&
        PackageFileSz == Against.PackageFileSz &&
        VersionSz == Against.VersionSz &&
+       DescriptionSz == Against.DescriptionSz &&
        DependencySz == Against.DependencySz &&
        VerFileSz == Against.VerFileSz &&
+       DescFileSz == Against.DescFileSz &&
        ProvidesSz == Against.ProvidesSz)
       return true;
    return false;
@@ -113,8 +120,10 @@ bool pkgCache::ReMap()
    HeaderP = (Header *)Map.Data();
    PkgP = (Package *)Map.Data();
    VerFileP = (VerFile *)Map.Data();
+   DescFileP = (DescFile *)Map.Data();
    PkgFileP = (PackageFile *)Map.Data();
    VerP = (Version *)Map.Data();
+   DescP = (Description *)Map.Data();
    ProvideP = (Provides *)Map.Data();
    DepP = (Dependency *)Map.Data();
    StringItemP = (StringItem *)Map.Data();
@@ -137,12 +146,12 @@ bool pkgCache::ReMap()
    // Locate our VS..
    if (HeaderP->VerSysName == 0 ||
        (VS = pkgVersioningSystem::GetVS(StrP + HeaderP->VerSysName)) == 0)
-      return _error->Error(_("This APT does not support the Versioning System '%s'"),StrP + HeaderP->VerSysName);
+      return _error->Error(_("This APT does not support the versioning system '%s'"),StrP + HeaderP->VerSysName);
 
    // Chcek the arhcitecture
    if (HeaderP->Architecture == 0 ||
        _config->Find("APT::Architecture") != StrP + HeaderP->Architecture)
-      return _error->Error(_("The package cache was build for a different architecture"));
+      return _error->Error(_("The package cache was built for a different architecture"));
    return true;
 }
                                                                        /*}}}*/
@@ -151,11 +160,11 @@ bool pkgCache::ReMap()
 /* This is used to generate the hash entries for the HashTable. With my
    package list from bo this function gets 94% table usage on a 512 item
    table (480 used items) */
-unsigned long pkgCache::sHash(string Str) const
+unsigned long pkgCache::sHash(const string &Str) const
 {
    unsigned long Hash = 0;
-   for (const char *I = Str.begin(); I != Str.end(); I++)
-      Hash = 5*Hash + tolower(*I);
+   for (string::const_iterator I = Str.begin(); I != Str.end(); I++)
+      Hash = 5*Hash + tolower_ascii(*I);
    return Hash % _count(HeaderP->HashTable);
 }
 
@@ -163,7 +172,7 @@ unsigned long pkgCache::sHash(const char *Str) const
 {
    unsigned long Hash = 0;
    for (const char *I = Str; *I != 0; I++)
-      Hash = 5*Hash + tolower(*I);
+      Hash = 5*Hash + tolower_ascii(*I);
    return Hash % _count(HeaderP->HashTable);
 }
 
@@ -171,14 +180,14 @@ unsigned long pkgCache::sHash(const char *Str) const
 // Cache::FindPkg - Locate a package by name                           /*{{{*/
 // ---------------------------------------------------------------------
 /* Returns 0 on error, pointer to the package otherwise */
-pkgCache::PkgIterator pkgCache::FindPkg(string Name)
+pkgCache::PkgIterator pkgCache::FindPkg(const string &Name)
 {
    // Look at the hash bucket
    Package *Pkg = PkgP + HeaderP->HashTable[Hash(Name)];
    for (; Pkg != PkgP; Pkg = PkgP + Pkg->NextPackage)
    {
       if (Pkg->Name != 0 && StrP[Pkg->Name] == Name[0] &&
-         stringcasecmp(Name.begin(),Name.end(),StrP + Pkg->Name) == 0)
+         stringcasecmp(Name,StrP + Pkg->Name) == 0)
         return PkgIterator(*this,Pkg);
    }
    return PkgIterator(*this,0);
@@ -215,8 +224,8 @@ const char *pkgCache::DepType(unsigned char Type)
 {
    const char *Types[] = {"",_("Depends"),_("PreDepends"),_("Suggests"),
                           _("Recommends"),_("Conflicts"),_("Replaces"),
-                          _("Obsoletes")};
-   if (Type < 8)
+                          _("Obsoletes"),_("Breaks"), _("Enhances")};
+   if (Type < sizeof(Types)/sizeof(*Types))
       return Types[Type];
    return "";
 }
@@ -233,11 +242,11 @@ const char *pkgCache::Priority(unsigned char Prio)
    return 0;
 }
                                                                        /*}}}*/
-
 // Bases for iterator classes                                          /*{{{*/
 void pkgCache::VerIterator::_dummy() {}
 void pkgCache::DepIterator::_dummy() {}
 void pkgCache::PrvIterator::_dummy() {}
+void pkgCache::DescIterator::_dummy() {}
                                                                        /*}}}*/
 // PkgIterator::operator ++ - Postfix incr                             /*{{{*/
 // ---------------------------------------------------------------------
@@ -267,6 +276,12 @@ pkgCache::PkgIterator::OkState pkgCache::PkgIterator::State() const
    
    if (Pkg->CurrentState == pkgCache::State::UnPacked ||
        Pkg->CurrentState == pkgCache::State::HalfConfigured)
+      // we leave triggers alone complettely. dpkg deals with
+      // them in a hard-to-predict manner and if they get 
+      // resolved by dpkg before apt run dpkg --configure on 
+      // the TriggersPending package dpkg returns a error
+      //Pkg->CurrentState == pkgCache::State::TriggersAwaited
+      //Pkg->CurrentState == pkgCache::State::TriggersPending)
       return NeedsConfigure;
    
    if (Pkg->CurrentState == pkgCache::State::HalfInstalled ||
@@ -276,13 +291,64 @@ pkgCache::PkgIterator::OkState pkgCache::PkgIterator::State() const
    return NeedsNothing;
 }
                                                                        /*}}}*/
+// PkgIterator::CandVersion - Returns the candidate version string     /*{{{*/
+// ---------------------------------------------------------------------
+/* Return string representing of the candidate version. */
+const char *
+pkgCache::PkgIterator::CandVersion() const 
+{
+  //TargetVer is empty, so don't use it.
+  VerIterator version = pkgPolicy(Owner).GetCandidateVer(*this);
+  if (version.IsGood())
+    return version.VerStr();
+  return 0;
+};
+                                                                       /*}}}*/
+// PkgIterator::CurVersion - Returns the current version string                /*{{{*/
+// ---------------------------------------------------------------------
+/* Return string representing of the current version. */
+const char *
+pkgCache::PkgIterator::CurVersion() const 
+{
+  VerIterator version = CurrentVer();
+  if (version.IsGood())
+    return CurrentVer().VerStr();
+  return 0;
+};
+                                                                       /*}}}*/
+// ostream operator to handle string representation of a package       /*{{{*/
+// ---------------------------------------------------------------------
+/* Output name < cur.rent.version -> candid.ate.version | new.est.version > (section)
+   Note that the characters <|>() are all literal above. Versions will be ommited
+   if they provide no new information (e.g. there is no newer version than candidate)
+   If no version and/or section can be found "none" is used. */
+std::ostream& 
+operator<<(ostream& out, pkgCache::PkgIterator Pkg) 
+{
+   if (Pkg.end() == true)
+      return out << "invalid package";
+
+   string current = string(Pkg.CurVersion() == 0 ? "none" : Pkg.CurVersion());
+   string candidate = string(Pkg.CandVersion() == 0 ? "none" : Pkg.CandVersion());
+   string newest = string(Pkg.VersionList().end() ? "none" : Pkg.VersionList().VerStr());
+
+   out << Pkg.Name() << " < " << current;
+   if (current != candidate)
+      out << " -> " << candidate;
+   if ( newest != "none" && candidate != newest)
+      out << " | " << newest;
+   out << " > ( " << string(Pkg.Section()==0?"none":Pkg.Section()) << " )";
+   return out;
+}
+                                                                       /*}}}*/
 // DepIterator::IsCritical - Returns true if the dep is important      /*{{{*/
 // ---------------------------------------------------------------------
 /* Currently critical deps are defined as depends, predepends and
-   conflicts. */
+   conflicts (including dpkg's Breaks fields). */
 bool pkgCache::DepIterator::IsCritical()
 {
    if (Dep->Type == pkgCache::Dep::Conflicts ||
+       Dep->Type == pkgCache::Dep::DpkgBreaks ||
        Dep->Type == pkgCache::Dep::Obsoletes ||
        Dep->Type == pkgCache::Dep::Depends ||
        Dep->Type == pkgCache::Dep::PreDepends)
@@ -368,6 +434,7 @@ pkgCache::Version **pkgCache::DepIterator::AllTargets()
            continue;
 
         if ((Dep->Type == pkgCache::Dep::Conflicts ||
+             Dep->Type == pkgCache::Dep::DpkgBreaks ||
              Dep->Type == pkgCache::Dep::Obsoletes) &&
             ParentPkg() == I.ParentPkg())
            continue;
@@ -384,6 +451,7 @@ pkgCache::Version **pkgCache::DepIterator::AllTargets()
            continue;
         
         if ((Dep->Type == pkgCache::Dep::Conflicts ||
+             Dep->Type == pkgCache::Dep::DpkgBreaks ||
              Dep->Type == pkgCache::Dep::Obsoletes) &&
             ParentPkg() == I.OwnerPkg())
            continue;
@@ -525,7 +593,7 @@ string pkgCache::VerIterator::RelStr()
            Seen = true;
            break;
         }
-        if (File2->Version == 0)
+        if (File2->Version == 0 || File->Version == 0)
            break;
         if (strcmp(File.Version(),File2.Version()) == 0)
            Seen = true;
@@ -578,3 +646,50 @@ bool pkgCache::PkgFileIterator::IsOk()
    return true;
 }
                                                                        /*}}}*/
+// PkgFileIterator::RelStr - Return the release string                 /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+string pkgCache::PkgFileIterator::RelStr()
+{
+   string Res;
+   if (Version() != 0)
+      Res = Res + (Res.empty() == true?"v=":",v=") + Version();
+   if (Origin() != 0)
+      Res = Res + (Res.empty() == true?"o=":",o=")  + Origin();
+   if (Archive() != 0)
+      Res = Res + (Res.empty() == true?"a=":",a=")  + Archive();
+   if (Codename() != 0)
+      Res = Res + (Res.empty() == true?"n=":",n=")  + Codename();
+   if (Label() != 0)
+      Res = Res + (Res.empty() == true?"l=":",l=")  + Label();
+   if (Component() != 0)
+      Res = Res + (Res.empty() == true?"c=":",c=")  + Component();
+   return Res;
+}
+                                                                       /*}}}*/
+// VerIterator::TranslatedDescription - Return the a DescIter for locale/*{{{*/
+// ---------------------------------------------------------------------
+/* return a DescIter for the current locale or the default if none is 
+ * found
+ */
+pkgCache::DescIterator pkgCache::VerIterator::TranslatedDescription() const
+{
+   std::vector<string> const lang = APT::Configuration::getLanguages();
+   for (std::vector<string>::const_iterator l = lang.begin();
+       l != lang.end(); l++)
+   {
+      pkgCache::DescIterator DescDefault = DescriptionList();
+      pkgCache::DescIterator Desc = DescDefault;
+
+      for (; Desc.end() == false; Desc++)
+        if (*l == Desc.LanguageCode())
+           break;
+      if (Desc.end() == true) 
+        Desc = DescDefault;
+      return Desc;
+   }
+
+   return DescriptionList();
+};
+
+                                                                       /*}}}*/