releasing version 0.8.16~exp13
[ntk/apt.git] / apt-pkg / packagemanager.cc
index dd08a48..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)
@@ -322,22 +320,22 @@ bool pkgPackageManager::ConfigureAll()
    only shown when debuging*/
 bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
 {
-   // If this is true, only check and correct and dependancies without the Loop flag
+   // If this is true, only check and correct and dependencies without the Loop flag
    bool PkgLoop = List->IsFlag(Pkg,pkgOrderList::Loop);
 
    if (Debug) {
       VerIterator InstallVer = VerIterator(Cache,Cache[Pkg].InstallVer);
       clog << OutputInDepth(Depth) << "SmartConfigure " << Pkg.Name() << " (" << InstallVer.VerStr() << ")";
       if (PkgLoop)
-        clog << " (Only Correct Dependancies)";
+        clog << " (Only Correct Dependencies)";
       clog << endl;
    }
 
    VerIterator const instVer = Cache[Pkg].InstVerIter(Cache);
       
-   /* Because of the ordered list, most dependancies should be unpacked, 
+   /* Because of the ordered list, most dependencies should be unpacked, 
       however if there is a loop (A depends on B, B depends on A) this will not 
-      be the case, so check for dependancies before configuring. */
+      be the case, so check for dependencies before configuring. */
    bool Bad = false;
    for (DepIterator D = instVer.DependsList();
        D.end() == false; )
@@ -424,7 +422,7 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
         
         if (Start==End) {
            if (Bad && Debug && List->IsFlag(DepPkg,pkgOrderList::Loop) == false)
-                 std::clog << OutputInDepth(Depth) << "Could not satisfy dependancies for " << Pkg.Name() << std::endl;
+                 std::clog << OutputInDepth(Depth) << "Could not satisfy dependencies for " << Pkg.Name() << std::endl;
            break;
         } else {
             Start++;
@@ -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;
    }
 
@@ -529,7 +529,6 @@ bool pkgPackageManager::SmartRemove(PkgIterator Pkg)
    List->Flag(Pkg,pkgOrderList::Configured,pkgOrderList::States);
 
    return Remove(Pkg,(Cache[Pkg].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge);
-   return true;
 }
                                                                        /*}}}*/
 // PM::SmartUnPack - Install helper                                    /*{{{*/
@@ -612,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 */
@@ -681,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)
@@ -690,35 +697,64 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c
            }
 
            // Check if it needs to be unpacked
-           if (List->IsFlag(BrokenPkg,pkgOrderList::InList) && Cache[BrokenPkg].Delete() == false && 
+           if (List->IsFlag(BrokenPkg,pkgOrderList::InList) && Cache[BrokenPkg].Delete() == false &&
                List->IsNow(BrokenPkg)) {
-             if (List->IsFlag(BrokenPkg,pkgOrderList::Loop) && PkgLoop) {
-               // This dependancy has already been dealt with by another SmartUnPack on Pkg
-               break;
-             } else if (List->IsFlag(Pkg,pkgOrderList::Loop)) {
-               /* Found a break, so unpack the package, but dont remove loop as already set.
-                  This means that there is another SmartUnPack call for this 
-                  package and it will remove the loop flag. */
-               if (Debug) 
-                 cout << OutputInDepth(Depth) << "  Unpacking " << BrokenPkg.Name() << " to avoid break" << endl;
-                   
-               SmartUnPack(BrokenPkg, false, Depth + 1);
-             } else {
-                List->Flag(Pkg,pkgOrderList::Loop);
-               // Found a break, so unpack the package
-               if (Debug) 
-                 cout << OutputInDepth(Depth) << "  Unpacking " << BrokenPkg.Name() << " to avoid break" << endl;
-                
-               SmartUnPack(BrokenPkg, false, Depth + 1);
-               List->RmFlag(Pkg,pkgOrderList::Loop);
-             }
-           }
-           
-           // Check if a package needs to be removed
-           if (Cache[BrokenPkg].Delete() == true && !List->IsFlag(BrokenPkg,pkgOrderList::Configured)) {
-             if (Debug) 
-                cout << OutputInDepth(Depth) << "  Removing " << BrokenPkg.Name() << " to avoid break" << endl;
-             SmartRemove(BrokenPkg);
+              if (List->IsFlag(BrokenPkg,pkgOrderList::Loop) && PkgLoop) {
+                 // This dependancy has already been dealt with by another SmartUnPack on Pkg
+                 break;
+              } else {
+                 // 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
+                 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
+              if (Cache[BrokenPkg].Delete() == true && !List->IsFlag(BrokenPkg,pkgOrderList::Configured))
+              {
+                 if (Debug)
+                    cout << OutputInDepth(Depth) << "  Removing " << BrokenPkg.Name() << " to avoid " << End << endl;
+                 SmartRemove(BrokenPkg);
+              }
            }
         }
       }