releasing version 0.8.16~exp13
[ntk/apt.git] / apt-pkg / packagemanager.cc
index 4247334..382ee43 100644 (file)
@@ -36,11 +36,13 @@ bool pkgPackageManager::SigINTStop = false;
 // PM::PackageManager - Constructor                                    /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-pkgPackageManager::pkgPackageManager(pkgDepCache *pCache) : Cache(*pCache)
+pkgPackageManager::pkgPackageManager(pkgDepCache *pCache) : Cache(*pCache),
+                                                           List(NULL), Res(Incomplete)
 {
    FileNames = new string[Cache.Head().PackageCount];
-   List = 0;
    Debug = _config->FindB("Debug::pkgPackageManager",false);
+   NoImmConfigure = !_config->FindB("APT::Immediate-Configure",true);
+   ImmConfigureAll = _config->FindB("APT::Immediate-Configure-All",false);
 }
                                                                        /*}}}*/
 // PM::PackageManager - Destructor                                     /*{{{*/
@@ -169,10 +171,7 @@ bool pkgPackageManager::CreateOrderList()
    
    delete List;
    List = new pkgOrderList(&Cache);
-   
-   NoImmConfigure = !_config->FindB("APT::Immediate-Configure",true);
-   ImmConfigureAll = _config->FindB("APT::Immediate-Configure-All",false);
-   
+
    if (Debug && ImmConfigureAll) 
       clog << "CreateOrderList(): Adding Immediate flag for all packages because of APT::Immediate-Configure-All" << endl;
    
@@ -184,8 +183,7 @@ bool pkgPackageManager::CreateOrderList()
         continue;
       
       // Mark the package and its dependends for immediate configuration
-      if ((((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential ||
-          (I->Flags & pkgCache::Flag::Important) == pkgCache::Flag::Important) &&
+      if ((((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential) &&
          NoImmConfigure == false) || ImmConfigureAll)
       {
         if(Debug && !ImmConfigureAll)
@@ -487,7 +485,8 @@ bool pkgPackageManager::EarlyRemove(PkgIterator Pkg)
 
    // Essential packages get special treatment
    bool IsEssential = false;
-   if ((Pkg->Flags & pkgCache::Flag::Essential) != 0)
+   if ((Pkg->Flags & pkgCache::Flag::Essential) != 0 ||
+       (Pkg->Flags & pkgCache::Flag::Important) != 0)
       IsEssential = true;
 
    /* Check for packages that are the dependents of essential packages and 
@@ -497,7 +496,8 @@ bool pkgPackageManager::EarlyRemove(PkgIterator Pkg)
       for (DepIterator D = Pkg.RevDependsList(); D.end() == false &&
           IsEssential == false; ++D)
         if (D->Type == pkgCache::Dep::Depends || D->Type == pkgCache::Dep::PreDepends)
-           if ((D.ParentPkg()->Flags & pkgCache::Flag::Essential) != 0)
+           if ((D.ParentPkg()->Flags & pkgCache::Flag::Essential) != 0 ||
+               (D.ParentPkg()->Flags & pkgCache::Flag::Important) != 0)
               IsEssential = true;
    }
 
@@ -611,10 +611,19 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c
               continue;
            }
 
-           if (Debug)
-              clog << OutputInDepth(Depth) << "Trying to SmartConfigure " << Pkg.Name() << endl;
-           Bad = !SmartConfigure(Pkg, Depth + 1);
-        }
+            // check if it needs unpack or if if configure is enough
+            if (!List->IsFlag(Pkg,pkgOrderList::UnPacked))
+            {
+               if (Debug)
+                  clog << OutputInDepth(Depth) << "Trying to SmartUnpack " << Pkg.Name() << endl;
+               // SmartUnpack with the ImmediateFlag to ensure its really ready
+               Bad = !SmartUnPack(Pkg, true, Depth + 1);
+            } else {
+               if (Debug)
+                  clog << OutputInDepth(Depth) << "Trying to SmartConfigure " << Pkg.Name() << endl;
+               Bad = !SmartConfigure(Pkg, Depth + 1);
+            }
+         }
 
         /* If this or element did not match then continue on to the
            next or element until a matching element is found */
@@ -680,7 +689,6 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c
         {
            VerIterator Ver(Cache,*I);
            PkgIterator BrokenPkg = Ver.ParentPkg();
-           VerIterator InstallVer(Cache,Cache[BrokenPkg].InstallVer);
            if (BrokenPkg.CurrentVer() != Ver)
            {
               if (Debug)
@@ -695,15 +703,49 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c
                  // This dependancy has already been dealt with by another SmartUnPack on Pkg
                  break;
               } else {
-                 // Found a break, so unpack the package,
+                 // Found a break, so see if we can unpack the package to avoid it
                  // but do not set loop if another SmartUnPack already deals with it
-                 if (Debug)
-                    cout << OutputInDepth(Depth) << "  Unpacking " << BrokenPkg.Name() << " to avoid " << End << endl;
-                 if (PkgLoop == false)
-                    List->Flag(Pkg,pkgOrderList::Loop);
-                 SmartUnPack(BrokenPkg, false, Depth + 1);
-                 if (PkgLoop == false)
-                    List->RmFlag(Pkg,pkgOrderList::Loop);
+                 VerIterator InstallVer(Cache,Cache[BrokenPkg].InstallVer);
+                 bool circle = false;
+                 for (pkgCache::DepIterator D = InstallVer.DependsList(); D.end() == false; ++D)
+                 {
+                    if (D->Type != pkgCache::Dep::PreDepends)
+                       continue;
+                    SPtrArray<Version *> VL = D.AllTargets();
+                    for (Version **I = VL; *I != 0; ++I)
+                    {
+                       VerIterator V(Cache,*I);
+                       PkgIterator P = V.ParentPkg();
+                       // we are checking for installation as an easy 'protection' against or-groups and (unchosen) providers
+                       if (P->CurrentVer == 0 || P != Pkg || (P.CurrentVer() != V && Cache[P].InstallVer != V))
+                          continue;
+                       circle = true;
+                       break;
+                    }
+                    if (circle == true)
+                       break;
+                 }
+                 if (circle == true)
+                 {
+                    if (Debug)
+                       cout << OutputInDepth(Depth) << "  Avoiding " << End << " avoided as " << BrokenPkg.FullName() << " has a pre-depends on " << Pkg.FullName() << std::endl;
+                    continue;
+                 }
+                 else
+                 {
+                    if (Debug)
+                    {
+                       cout << OutputInDepth(Depth) << "  Unpacking " << BrokenPkg.FullName() << " to avoid " << End;
+                       if (PkgLoop == true)
+                          cout << " (Looping)";
+                       cout << std::endl;
+                    }
+                    if (PkgLoop == false)
+                       List->Flag(Pkg,pkgOrderList::Loop);
+                    SmartUnPack(BrokenPkg, false, Depth + 1);
+                    if (PkgLoop == false)
+                       List->RmFlag(Pkg,pkgOrderList::Loop);
+                 }
               }
            } else {
               // Check if a package needs to be removed