]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/algorithms.cc
Another error message for failed updates
[apt.git] / apt-pkg / algorithms.cc
index a65062a9bc7ff8d25a97bacf11b91754601c8c21..d84ce2e216a1b958984c1ad10c5fc64369c4b348 100644 (file)
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description                                                         /*{{{*/
-// $Id: algorithms.cc,v 1.9 1998/11/13 07:08:57 jgg Exp $
+// $Id: algorithms.cc,v 1.23 1999/07/30 02:54:25 jgg Exp $
 /* ######################################################################
 
    Algorithms - A set of misc algorithms
@@ -29,10 +29,15 @@ pkgProblemResolver *pkgProblemResolver::This = 0;
 // ---------------------------------------------------------------------
 /* */
 pkgSimulate::pkgSimulate(pkgDepCache &Cache) : pkgPackageManager(Cache), 
-                            Sim(Cache)
+                            Sim(Cache.GetMap())
 {
    Flags = new unsigned char[Cache.HeaderP->PackageCount];
    memset(Flags,0,sizeof(*Flags)*Cache.HeaderP->PackageCount);
+
+   // Fake a filename so as not to activate the media swapping
+   string Jnk = "SIMULATE";
+   for (unsigned int I = 0; I != Cache.Head().PackageCount; I++)
+      FileNames[I] = Jnk;
 }
                                                                        /*}}}*/
 // Simulate::Install - Simulate unpacking of a package                 /*{{{*/
@@ -44,7 +49,7 @@ bool pkgSimulate::Install(PkgIterator iPkg,string /*File*/)
    PkgIterator Pkg = Sim.FindPkg(iPkg.Name());
    Flags[Pkg->ID] = 1;
    
-   clog << "Inst " << Pkg.Name();
+   cout << "Inst " << Pkg.Name();
    Sim.MarkInstall(Pkg,false);
    
    // Look for broken conflicts+predepends.
@@ -58,7 +63,7 @@ bool pkgSimulate::Install(PkgIterator iPkg,string /*File*/)
          {
            if ((Sim[D] & pkgDepCache::DepInstall) == 0)
            {
-              clog << " [" << I.Name() << " on " << D.TargetPkg().Name() << ']';
+              cout << " [" << I.Name() << " on " << D.TargetPkg().Name() << ']';
               if (D->Type == pkgCache::Dep::Conflicts)
                  _error->Error("Fatal, conflicts violated %s",I.Name());
            }       
@@ -68,7 +73,7 @@ bool pkgSimulate::Install(PkgIterator iPkg,string /*File*/)
    if (Sim.BrokenCount() != 0)
       ShortBreaks();
    else
-      clog << endl;
+      cout << endl;
    return true;
 }
                                                                        /*}}}*/
@@ -86,7 +91,7 @@ bool pkgSimulate::Configure(PkgIterator iPkg)
 //   Sim.MarkInstall(Pkg,false);
    if (Sim[Pkg].InstBroken() == true)
    {
-      clog << "Conf " << Pkg.Name() << " broken" << endl;
+      cout << "Conf " << Pkg.Name() << " broken" << endl;
 
       Sim.Update();
       
@@ -98,21 +103,21 @@ bool pkgSimulate::Configure(PkgIterator iPkg)
            continue;
         
         if (D->Type == pkgCache::Dep::Conflicts)
-           clog << " Conflicts:" << D.TargetPkg().Name();
+           cout << " Conflicts:" << D.TargetPkg().Name();
         else
-           clog << " Depends:" << D.TargetPkg().Name();
+           cout << " Depends:" << D.TargetPkg().Name();
       }            
-      clog << endl;
+      cout << endl;
 
       _error->Error("Conf Broken %s",Pkg.Name());
    }   
    else
-      clog << "Conf " <<  Pkg.Name();
+      cout << "Conf " <<  Pkg.Name();
 
    if (Sim.BrokenCount() != 0)
       ShortBreaks();
    else
-      clog << endl;
+      cout << endl;
    
    return true;
 }
@@ -120,19 +125,22 @@ bool pkgSimulate::Configure(PkgIterator iPkg)
 // Simulate::Remove - Simulate the removal of a package                        /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-bool pkgSimulate::Remove(PkgIterator iPkg)
+bool pkgSimulate::Remove(PkgIterator iPkg,bool Purge)
 {
    // Adapt the iterator
    PkgIterator Pkg = Sim.FindPkg(iPkg.Name());
 
    Flags[Pkg->ID] = 3;
    Sim.MarkDelete(Pkg);
-   clog << "Remv " << Pkg.Name();
+   if (Purge == true)
+      cout << "Purg " << Pkg.Name();
+   else
+      cout << "Remv " << Pkg.Name();
 
    if (Sim.BrokenCount() != 0)
       ShortBreaks();
    else
-      clog << endl;
+      cout << endl;
 
    return true;
 }
@@ -142,18 +150,18 @@ bool pkgSimulate::Remove(PkgIterator iPkg)
 /* */
 void pkgSimulate::ShortBreaks()
 {
-   clog << " [";
+   cout << " [";
    for (PkgIterator I = Sim.PkgBegin(); I.end() == false; I++)
    {
       if (Sim[I].InstBroken() == true)
       {
         if (Flags[I->ID] == 0)
-           clog << I.Name() << ' ';
+           cout << I.Name() << ' ';
 /*      else
-           clog << I.Name() << "! ";*/
+           cout << I.Name() << "! ";*/
       }      
    }
-   clog << ']' << endl;
+   cout << ']' << endl;
 }
                                                                        /*}}}*/
 // ApplyStatus - Adjust for non-ok packages                            /*{{{*/
@@ -165,12 +173,41 @@ bool pkgApplyStatus(pkgDepCache &Cache)
 {
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
    {
+      // Only choice for a ReInstReq package is to reinstall
+      if (I->InstState == pkgCache::State::ReInstReq ||
+         I->InstState == pkgCache::State::HoldReInstReq)
+      {
+        if (I.CurrentVer().Downloadable() == true)
+           Cache.MarkKeep(I);
+        else
+        {
+           // Is this right? Will dpkg choke on an upgrade?
+           if (Cache[I].CandidateVerIter(Cache).Downloadable() == true)
+              Cache.MarkInstall(I);
+           else
+              return _error->Error("The package %s needs to be reinstalled, "
+                                   "but I can't find an archive for it.",I.Name());
+        }
+        
+        continue;
+      }
+      
       switch (I->CurrentState)
       {
-        // This means installation failed somehow
+        /* This means installation failed somehow - it does not need to be
+           re-unpacked (probably) */
         case pkgCache::State::UnPacked:
         case pkgCache::State::HalfConfigured:
-        Cache.MarkKeep(I);
+        if (I.CurrentVer().Downloadable() == true || 
+            I.State() != pkgCache::PkgIterator::NeedsUnpack)
+           Cache.MarkKeep(I);
+        else
+        {
+           if (Cache[I].CandidateVerIter(Cache).Downloadable() == true)
+              Cache.MarkInstall(I);
+           else
+              Cache.MarkDelete(I);
+        }
         break;
 
         // This means removal failed
@@ -303,6 +340,7 @@ bool pkgMinimizeUpgrade(pkgDepCache &Cache)
    
    // We loop indefinately to get the minimal set size.
    bool Change = false;
+   unsigned int Count = 0;
    do
    {
       Change = false;
@@ -311,16 +349,21 @@ bool pkgMinimizeUpgrade(pkgDepCache &Cache)
         // Not interesting
         if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true)
            continue;
-        
+
         // Keep it and see if that is OK
         Cache.MarkKeep(I);
         if (Cache.BrokenCount() != 0)
            Cache.MarkInstall(I,false);
         else
-           Change = true;
+        {
+           // If keep didnt actually do anything then there was no change..
+           if (Cache[I].Upgrade() == false)
+              Change = true;
+        }       
       }      
+      Count++;
    }
-   while (Change == true);
+   while (Change == true && Count < 10);
 
    if (Cache.BrokenCount() != 0)
       return _error->Error("Internal Error in pkgMinimizeUpgrade");
@@ -445,8 +488,12 @@ void pkgProblemResolver::MakeScores()
    /* Protected things are pushed really high up. This number should put them
       ahead of everything */
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+   {
       if ((Flags[I->ID] & Protected) != 0)
         Scores[I->ID] += 10000;
+      if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
+        Scores[I->ID] += 5000;
+   }
    
    delete [] OldScores;
 }
@@ -671,16 +718,9 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
         for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false;)
         {
            // Compute a single dependency element (glob or)
-           pkgCache::DepIterator Start = D;
-           pkgCache::DepIterator End = D;
-           unsigned char State = 0;
-           for (bool LastOR = true; D.end() == false && LastOR == true; D++)
-           {
-              State |= Cache[D];
-              LastOR = (D->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or;
-              if (LastOR == true)
-                 End = D;
-           }
+           pkgCache::DepIterator Start;
+           pkgCache::DepIterator End;
+           D.GlobOr(Start,End);
            
            // We only worry about critical deps.
            if (End.IsCritical() != true)
@@ -693,17 +733,29 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
            // Hm, the group is broken.. I have no idea how to handle this
            if (Start != End)
            {
-              clog << "Note, a broken or group was found in " << I.Name() << "." << endl;
-              Cache.MarkDelete(I);
+              if (Debug == true)
+                 clog << "Note, a broken or group was found in " << I.Name() << "." << endl;
+              if ((Flags[I->ID] & Protected) != Protected)
+                 Cache.MarkDelete(I);
               break;
            }
                    
            if (Debug == true)
               clog << "Package " << I.Name() << " has broken dep on " << End.TargetPkg().Name() << endl;
-           
-           /* Conflicts is simple, decide if we should remove this package
-              or the conflicted one */
+
+           /* Look across the version list. If there are no possible
+              targets then we keep the package and bail. This is necessary
+              if a package has a dep on another package that cant be found */
            pkgCache::Version **VList = End.AllTargets();
+           if (*VList == 0 && (Flags[I->ID] & Protected) != Protected &&
+               End->Type != pkgCache::Dep::Conflicts && 
+               Cache[I].NowBroken() == false)
+           {
+              Change = true;
+              Cache.MarkKeep(I);
+              break;
+           }
+           
            bool Done = false;
            for (pkgCache::Version **V = VList; *V != 0; V++)
            {
@@ -717,10 +769,16 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
                   ((Cache[End] & pkgDepCache::DepGNow) == 0 &&
                    End->Type != pkgCache::Dep::Conflicts))
               {
+                 // Try a little harder to fix protected packages..
                  if ((Flags[I->ID] & Protected) == Protected)
+                 {
+                    if (DoUpgrade(Pkg) == true)
+                       Scores[Pkg->ID] = Scores[I->ID];
                     continue;
-
-                 // See if a keep will do
+                 }
+                 
+                 /* See if a keep will do, unless the package is protected,
+                    then installing it will be necessary */    
                  Cache.MarkKeep(I);
                  if (Cache[I].InstBroken() == false)
                  {
@@ -738,7 +796,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
                           Scores[I->ID] = Scores[Pkg->ID];
                     }
                  }
-
+                                 
                  Change = true;
                  Done = true;
                  break;
@@ -818,8 +876,19 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
    delete [] PList;
    
    if (Cache.BrokenCount() != 0)
-      return _error->Error("Internal error, pkgProblemResolver::Resolve generated breaks.");
-
+   {
+      // See if this is the result of a hold
+      pkgCache::PkgIterator I = Cache.PkgBegin();
+      for (;I.end() != true; I++)
+      {
+        if (Cache[I].InstBroken() == false)
+           continue;
+        if ((Flags[I->ID] & Protected) != Protected)
+           return _error->Error("Error, pkgProblemResolver::Resolve generated breaks, this may be caused by held packages.");
+      }
+      return _error->Error("Unable to correct problems, you have held broken packages.");
+   }
+   
    return true;
 }
                                                                        /*}}}*/