]> git.saurik.com Git - apt.git/blobdiff - cmdline/apt-get.cc
* use mark-and-sweep from aptitude now as GC algorithm
[apt.git] / cmdline / apt-get.cc
index 0cf723466d34a65e69810cb36e39a657f8058d44..9d97f8756eb9abf5f91e6ef9100bcba426891267 100644 (file)
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description                                                         /*{{{*/
-// $Id: apt-get.cc,v 1.143 2003/09/24 04:00:25 mdz Exp $
+// $Id: apt-get.cc,v 1.156 2004/08/28 01:05:16 mdz Exp $
 /* ######################################################################
    
    apt-get - Cover for dpkg
@@ -58,6 +58,7 @@
 #include <errno.h>
 #include <regex.h>
 #include <sys/wait.h>
+#include <sstream>
                                                                        /*}}}*/
 
 using namespace std;
@@ -111,7 +112,7 @@ class CacheFile : public pkgCacheFile
 // YnPrompt - Yes No Prompt.                                           /*{{{*/
 // ---------------------------------------------------------------------
 /* Returns true on a Yes.*/
-bool YnPrompt()
+bool YnPrompt(bool Default=true)
 {
    if (_config->FindB("APT::Get::Assume-Yes",false) == true)
    {
@@ -126,7 +127,7 @@ bool YnPrompt()
       return false;
 
    if (strlen(response) == 0)
-      return true;
+      return Default;
 
    regex_t Pattern;
    int Res;
@@ -270,7 +271,7 @@ void ShowBroken(ostream &out,CacheFile &Cache,bool Now)
         // Compute a single dependency element (glob or)
         pkgCache::DepIterator Start;
         pkgCache::DepIterator End;
-        D.GlobOr(Start,End);
+        D.GlobOr(Start,End); // advances D
 
         if (Cache->IsImportantDep(End) == false)
            continue;
@@ -418,7 +419,7 @@ void ShowKept(ostream &out,CacheFile &Cache)
       List += string(I.Name()) + " ";
       VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
    }
-   ShowList(out,_("The following packages have been kept back"),List,VersionsList);
+   ShowList(out,_("The following packages have been kept back:"),List,VersionsList);
 }
                                                                        /*}}}*/
 // ShowUpgraded - Show upgraded packages                               /*{{{*/
@@ -439,7 +440,7 @@ void ShowUpgraded(ostream &out,CacheFile &Cache)
       List += string(I.Name()) + " ";
       VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
    }
-   ShowList(out,_("The following packages will be upgraded"),List,VersionsList);
+   ShowList(out,_("The following packages will be upgraded:"),List,VersionsList);
 }
                                                                        /*}}}*/
 // ShowDowngraded - Show downgraded packages                           /*{{{*/
@@ -460,7 +461,7 @@ bool ShowDowngraded(ostream &out,CacheFile &Cache)
       List += string(I.Name()) + " ";
       VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
    }
-   return ShowList(out,_("The following packages will be DOWNGRADED"),List,VersionsList);
+   return ShowList(out,_("The following packages will be DOWNGRADED:"),List,VersionsList);
 }
                                                                        /*}}}*/
 // ShowHold - Show held but changed packages                           /*{{{*/
@@ -541,9 +542,10 @@ bool ShowEssential(ostream &out,CacheFile &Cache)
    }
    
    delete [] Added;
-   return ShowList(out,_("WARNING: The following essential packages will be removed\n"
+   return ShowList(out,_("WARNING: The following essential packages will be removed.\n"
                         "This should NOT be done unless you know exactly what you are doing!"),List,VersionsList);
 }
+
                                                                        /*}}}*/
 // Stats - Show some statistics                                                /*{{{*/
 // ---------------------------------------------------------------------
@@ -630,7 +632,7 @@ bool CacheFile::CheckDeps(bool AllowBroken)
 
    // Check that the system is OK
    if (DCache->DelCount() != 0 || DCache->InstCount() != 0)
-      return _error->Error("Internal Error, non-zero counts");
+      return _error->Error("Internal error, non-zero counts");
    
    // Apply corrections for half-installed packages
    if (pkgApplyStatus(*DCache) == false)
@@ -666,6 +668,49 @@ bool CacheFile::CheckDeps(bool AllowBroken)
       
    return true;
 }
+
+static bool CheckAuth(pkgAcquire& Fetcher)
+{
+   string UntrustedList;
+   for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd(); ++I)
+   {
+      if (!(*I)->IsTrusted())
+      {
+         UntrustedList += string((*I)->ShortDesc()) + " ";
+      }
+   }
+
+   if (UntrustedList == "")
+   {
+      return true;
+   }
+        
+   ShowList(c2out,_("WARNING: The following packages cannot be authenticated!"),UntrustedList,"");
+
+   if (_config->FindB("APT::Get::AllowUnauthenticated",false) == true)
+   {
+      c2out << "Authentication warning overridden.\n";
+      return true;
+   }
+
+   if (_config->FindI("quiet",0) < 2
+       && _config->FindB("APT::Get::Assume-Yes",false) == false)
+   {
+      c2out << _("Install these packages without verification [y/N]? ") << flush;
+      if (!YnPrompt(false))
+         return _error->Error(_("Some packages could not be authenticated"));
+
+      return true;
+   }
+   else if (_config->FindB("APT::Get::Force-Yes",false) == true)
+   {
+      return true;
+   }
+
+   return _error->Error(_("There are problems and -y was used without --force-yes"));
+}
+
+
                                                                        /*}}}*/
 
 // InstallPackages - Actually download and install the packages                /*{{{*/
@@ -673,7 +718,7 @@ bool CacheFile::CheckDeps(bool AllowBroken)
 /* This displays the informative messages describing what is going to 
    happen and then calls the download routines */
 bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
-                    bool Saftey = true)
+                    bool Safety = true)
 {
    if (_config->FindB("APT::Get::Purge",false) == true)
    {
@@ -701,12 +746,12 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
         Essential = !ShowEssential(c1out,Cache);
    Fail |= Essential;
    Stats(c1out,Cache);
-   
+
    // Sanity check
    if (Cache->BrokenCount() != 0)
    {
       ShowBroken(c1out,Cache,false);
-      return _error->Error("Internal Error, InstallPackages was called with broken packages!");
+      return _error->Error("Internal error, InstallPackages was called with broken packages!");
    }
 
    if (Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
@@ -715,7 +760,7 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
 
    // No remove flag
    if (Cache->DelCount() != 0 && _config->FindB("APT::Get::Remove",true) == false)
-      return _error->Error(_("Packages need to be removed but Remove is disabled."));
+      return _error->Error(_("Packages need to be removed but remove is disabled."));
        
    // Run the simulator ..
    if (_config->FindB("APT::Get::Simulate") == true)
@@ -725,7 +770,7 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
       if (Res == pkgPackageManager::Failed)
         return false;
       if (Res != pkgPackageManager::Completed)
-        return _error->Error("Internal Error, Ordering didn't finish");
+        return _error->Error("Internal error, Ordering didn't finish");
       return true;
    }
    
@@ -811,14 +856,14 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
         return _error->Error(_("There are problems and -y was used without --force-yes"));
    }         
 
-   if (Essential == true && Saftey == true)
+   if (Essential == true && Safety == true)
    {
       if (_config->FindB("APT::Get::Trivial-Only",false) == true)
         return _error->Error(_("Trivial Only specified but this is not a trivial operation."));
       
       const char *Prompt = _("Yes, do as I say!");
       ioprintf(c2out,
-              _("You are about to do something potentially harmful\n"
+              _("You are about to do something potentially harmful.\n"
                 "To continue type in the phrase '%s'\n"
                 " ?] "),Prompt);
       c2out << flush;
@@ -839,7 +884,7 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
         if (_config->FindI("quiet",0) < 2 &&
             _config->FindB("APT::Get::Assume-Yes",false) == false)
         {
-           c2out << _("Do you want to continue? [Y/n] ") << flush;
+           c2out << _("Do you want to continue [Y/n]? ") << flush;
         
            if (YnPrompt() == false)
            {
@@ -860,6 +905,9 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
       return true;
    }
 
+   if (!CheckAuth(Fetcher))
+      return false;
+
    /* Unlock the dpkg lock if we are not going to be doing an install
       after. */
    if (_config->FindB("APT::Get::Download-Only",false) == true)
@@ -943,9 +991,9 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
       if (Failed == true && PM->FixMissing() == false)
       {
         cerr << _("Unable to correct missing packages.") << endl;
-        return _error->Error(_("Aborting Install."));
+        return _error->Error(_("Aborting install."));
       }
-                
+
       _system->UnLock();
       pkgPackageManager::OrderResult Res = PM->DoInstall();
       if (Res == pkgPackageManager::Failed || _error->PendingError() == true)
@@ -1037,10 +1085,9 @@ bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
       else
       {
         ioprintf(c1out,
-        _("Package %s has no available version, but exists in the database.\n"
-          "This typically means that the package was mentioned in a dependency and\n"
-          "never uploaded, has been obsoleted or is not available with the contents\n"
-          "of sources.list\n"),Pkg.Name());
+        _("Package %s is not available, but is referred to by another package.\n"
+          "This may mean that the package is missing, has been obsoleted, or\n"
+           "is only available from another source\n"),Pkg.Name());
         
         string List;
         string VersionsList;
@@ -1253,19 +1300,25 @@ bool DoUpdate(CommandLine &CmdL)
    AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
    pkgAcquire Fetcher(&Stat);
 
-   // Populate it with the source selection
-   if (List.GetIndexes(&Fetcher) == false)
-        return false;
    
    // Just print out the uris an exit if the --print-uris flag was used
    if (_config->FindB("APT::Get::Print-URIs") == true)
    {
+      // Populate it with the source selection and get all Indexes 
+      // (GetAll=true)
+      if (List.GetIndexes(&Fetcher,true) == false)
+        return false;
+
       pkgAcquire::UriIterator I = Fetcher.UriBegin();
       for (; I != Fetcher.UriEnd(); I++)
         cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << 
               I->Owner->FileSize << ' ' << I->Owner->MD5Sum() << endl;
       return true;
    }
+
+   // Populate it with the source selection
+   if (List.GetIndexes(&Fetcher) == false)
+        return false;
    
    // Run it
    if (Fetcher.Run() == pkgAcquire::Failed)
@@ -1303,6 +1356,47 @@ bool DoUpdate(CommandLine &CmdL)
    return true;
 }
                                                                        /*}}}*/
+// DoAutomaticRemove - Remove all automatic unused packages            /*{{{*/
+// ---------------------------------------------------------------------
+/* Remove unused automatic packages */
+bool DoAutomaticRemove(CacheFile &Cache)
+{
+   if(_config->FindI("Debug::pkgAutoRemove",false))
+      std::cout << "DoAutomaticRemove()" << std::endl;
+
+   if (_config->FindB("APT::Get::Remove",true) == false)
+      return _error->Error(_("We are not supposed to delete stuff, can't "
+                            "start AutoRemover"));
+
+   // do the actual work
+   pkgMarkUsed(Cache);
+
+   // look over the cache to see what can be removed
+   for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); ! Pkg.end(); ++Pkg)
+   {
+      if (Cache[Pkg].Garbage &&
+          (Pkg->CurrentVer != 0 && Cache[Pkg].Install() == false && 
+          Cache[Pkg].Delete() == false))
+      {
+         fprintf(stdout,"We could delete %s\n", Pkg.Name());
+         Cache->MarkDelete(Pkg,_config->FindB("APT::Get::Purge",false));
+      }
+   }
+
+   // Now see if we destroyed anything
+   if (Cache->BrokenCount() != 0)
+   {
+      c1out << _("Hmm, seems like the AutoRemover destroyed something which really\n"
+                "shouldn't happen. Please file a bug report against apt.") << endl;
+      c1out << endl;
+      c1out << _("The following information may help to resolve the situation:") << endl;
+      c1out << endl;
+      ShowBroken(c1out,Cache,false);
+
+      return _error->Error(_("Internal Error, AutoRemover broke stuff"));
+   }
+   return true;
+}
 // DoUpgrade - Upgrade all packages                                    /*{{{*/
 // ---------------------------------------------------------------------
 /* Upgrade all packages without installing new packages or erasing old
@@ -1317,7 +1411,7 @@ bool DoUpgrade(CommandLine &CmdL)
    if (pkgAllUpgrade(Cache) == false)
    {
       ShowBroken(c1out,Cache,false);
-      return _error->Error(_("Internal Error, AllUpgrade broke stuff"));
+      return _error->Error(_("Internal error, AllUpgrade broke stuff"));
    }
    
    return InstallPackages(Cache,true);
@@ -1328,6 +1422,15 @@ bool DoUpgrade(CommandLine &CmdL)
 /* Install named packages */
 bool DoInstall(CommandLine &CmdL)
 {
+   // Lock the list directory
+   FileFd Lock;
+   if (_config->FindB("Debug::NoLocking",false) == false)
+   {
+      Lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock"));
+      if (_error->PendingError() == true)
+        return _error->Error(_("Unable to lock the list directory"));
+   }
+   
    CacheFile Cache;
    if (Cache.OpenForInstall() == false || 
        Cache.CheckDeps(CmdL.FileSize() != 1) == false)
@@ -1494,6 +1597,11 @@ bool DoInstall(CommandLine &CmdL)
       return _error->Error(_("Broken packages"));
    }   
    
+   if (_config->FindB("APT::Get::AutomaticRemove")) {
+      if (!DoAutomaticRemove(Cache)) 
+        return false;
+   }
+
    /* Print out a list of packages that are going to be installed extra
       to what the user asked */
    if (Cache->InstCount() != ExpectedInst)
@@ -1513,8 +1621,8 @@ bool DoInstall(CommandLine &CmdL)
         
         if (*J == 0) {
            List += string(I.Name()) + " ";
-        VersionsList += string(Cache[I].CandVersion) + "\n";
-     }
+           VersionsList += string(Cache[I].CandVersion) + "\n";
+        }
       }
       
       ShowList(c1out,_("The following extra packages will be installed:"),List,VersionsList);
@@ -1533,69 +1641,60 @@ bool DoInstall(CommandLine &CmdL)
           continue;
 
         for (pkgCache::VerIterator V = I.VersionList(); V.end() == false; V++)
-          {
-            for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; D++)
-              {
+         {
+            for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; )
+             {
                 pkgCache::DepIterator Start;
                 pkgCache::DepIterator End;
-                D.GlobOr(Start,End);
+                D.GlobOr(Start,End); // advances D
 
                 /* 
                  * If this is a virtual package, we need to check the list of
                  * packages that provide it and see if any of those are
                  * installed
                  */
-                pkgCache::PrvIterator Prv = Start.TargetPkg().ProvidesList();
+                
                 bool providedBySomething = false;
-                for (; Prv.end() != true; Prv++)
-                   if ((*Cache)[Prv.OwnerPkg()].InstVerIter(*Cache).end() == false) {
+                for (pkgCache::PrvIterator Prv = Start.TargetPkg().ProvidesList();
+                      Prv.end() != true;
+                      Prv++)
+                   if ((*Cache)[Prv.OwnerPkg()].InstVerIter(*Cache).end() == false)
+                    {
                       providedBySomething = true;
                       break;
                    }
 
                 if (providedBySomething) continue;
             
-                do
-                  {
-                    if (Start->Type == pkgCache::Dep::Suggests) {
+                 for(;;)
+                 {
+                     /* Skip if package is  installed already, or is about to be */
+                     string target = string(Start.TargetPkg().Name()) + " ";
+
+                     if ((*Start.TargetPkg()).SelectedState == pkgCache::State::Install
+                         || Cache[Start.TargetPkg()].Install())
+                       break;
 
-                      /* A suggests relations, let's see if we have it 
-                         installed already */
+                     /* Skip if we already saw it */
+                     if (int(SuggestsList.find(target)) != -1 || int(RecommendsList.find(target)) != -1)
+                       break; 
 
-                      string target = string(Start.TargetPkg().Name()) + " ";
-                      if ((*Start.TargetPkg()).SelectedState == pkgCache::State::Install || Cache[Start.TargetPkg()].Install())
-                        break;
-                      /* Does another package suggest it as well?  If so,
-                         don't print it twice */
-                      if (int(SuggestsList.find(target)) > -1)
-                        break; 
+                    if (Start->Type == pkgCache::Dep::Suggests) {
                       SuggestsList += target;
                       SuggestsVersions += string(Cache[Start.TargetPkg()].CandVersion) + "\n";
                     }
                     
                     if (Start->Type == pkgCache::Dep::Recommends) {
-
-                      /* A recommends relation, let's see if we have it
-                         installed already */
-
-                      string target = string(Start.TargetPkg().Name()) + " ";
-                      if ((*Start.TargetPkg()).SelectedState == pkgCache::State::Install || Cache[Start.TargetPkg()].Install())
-                        break;
-                      
-                      /* Does another package recommend it as well?  If so,
-                         don't print it twice */
-
-                      if (int(RecommendsList.find(target)) > -1)
-                        break;
                       RecommendsList += target;
-                      SuggestsVersions += string(Cache[Start.TargetPkg()].CandVersion) + "\n";
+                      RecommendsVersions += string(Cache[Start.TargetPkg()].CandVersion) + "\n";
                     }
-             if (Start == End)
-               break;
-             Start++;
-           } while (1);
-              }
-          }
+
+                     if (Start >= End)
+                        break;
+                     Start++;
+                 }
+             }
+         }
       }
       ShowList(c1out,_("Suggested packages:"),SuggestsList,SuggestsVersions);
       ShowList(c1out,_("Recommended packages:"),RecommendsList,RecommendsVersions);
@@ -1618,7 +1717,7 @@ bool DoDistUpgrade(CommandLine &CmdL)
    if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false)
       return false;
 
-   c0out << _("Calculating Upgrade... ") << flush;
+   c0out << _("Calculating upgrade... ") << flush;
    if (pkgDistUpgrade(*Cache) == false)
    {
       c0out << _("Failed") << endl;
@@ -1691,7 +1790,7 @@ bool DoDSelectUpgrade(CommandLine &CmdL)
       if (Fix.Resolve() == false)
       {
         ShowBroken(c1out,Cache,false);
-        return _error->Error("Internal Error, problem resolver broke stuff");
+        return _error->Error("Internal error, problem resolver broke stuff");
       }
    }
 
@@ -1699,7 +1798,7 @@ bool DoDSelectUpgrade(CommandLine &CmdL)
    if (pkgAllUpgrade(Cache) == false)
    {
       ShowBroken(c1out,Cache,false);
-      return _error->Error("Internal Error, problem resolver broke stuff");
+      return _error->Error("Internal error, problem resolver broke stuff");
    }
    
    return InstallPackages(Cache,false);
@@ -1887,7 +1986,7 @@ bool DoSource(CommandLine &CmdL)
    if (_config->FindB("APT::Get::Simulate",false) == true)
    {
       for (unsigned I = 0; I != J; I++)
-        ioprintf(cout,_("Fetch Source %s\n"),Dsc[I].Package.c_str());
+        ioprintf(cout,_("Fetch source %s\n"),Dsc[I].Package.c_str());
       return true;
    }
    
@@ -2156,11 +2255,18 @@ bool DoBuildDep(CommandLine &CmdL)
                            break;
                  }
                  if (CV.end() == true)
+                  if (hasAlternatives)
+                  {
+                     continue;
+                  }
+                  else
+                  {
                       return _error->Error(_("%s dependency for %s cannot be satisfied "
                                              "because no available versions of package %s "
                                              "can satisfy version requirements"),
                                            Last->BuildDepType((*D).Type),Src.c_str(),
                                            (*D).Package.c_str());
+                  }
             }
             else
             {
@@ -2229,8 +2335,7 @@ bool DoBuildDep(CommandLine &CmdL)
       
       // Now we check the state of the packages,
       if (Cache->BrokenCount() != 0)
-        return _error->Error(_("Some broken packages were found while trying to process build-dependencies for %s.\n"
-                               "You might want to run `apt-get -f install' to correct these."),*I);
+         return _error->Error(_("Build-dependencies for %s could not be satisfied."),*I);
    }
   
    if (InstallPackages(Cache, false, true) == false)
@@ -2266,7 +2371,7 @@ bool ShowHelp(CommandLine &CmdL)
            
    if (_config->FindB("version") == true)
    {
-      cout << _("Supported Modules:") << endl;
+      cout << _("Supported modules:") << endl;
       
       for (unsigned I = 0; I != pkgVersioningSystem::GlobalListLen; I++)
       {
@@ -2341,7 +2446,7 @@ bool ShowHelp(CommandLine &CmdL)
       "  -b  Build the source package after fetching it\n"
       "  -V  Show verbose version numbers\n"
       "  -c=? Read this configuration file\n"
-      "  -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n"
+      "  -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
       "See the apt-get(8), sources.list(5) and apt.conf(5) manual\n"
       "pages for more information and options.\n"
       "                       This APT has Super Cow Powers.\n");
@@ -2360,7 +2465,8 @@ void GetInitialize()
    _config->Set("APT::Get::Assume-Yes",false);
    _config->Set("APT::Get::Fix-Broken",false);
    _config->Set("APT::Get::Force-Yes",false);
-   _config->Set("APT::Get::APT::Get::No-List-Cleanup",true);
+   _config->Set("APT::Get::List-Cleanup",true);
+   _config->Set("APT::Get::AutomaticRemove",false);
 }
                                                                        /*}}}*/
 // SigWinch - Window size change signal handler                                /*{{{*/
@@ -2416,6 +2522,8 @@ int main(int argc,const char *argv[])
       {0,"remove","APT::Get::Remove",0},
       {0,"only-source","APT::Get::Only-Source",0},
       {0,"arch-only","APT::Get::Arch-Only",0},
+      {0,"automatic-remove","APT::Get::AutomaticRemove",0},
+      {0,"allow-unauthenticated","APT::Get::AllowUnauthenticated",0},
       {'c',"config-file",0,CommandLine::ConfigFile},
       {'o',"option",0,CommandLine::ArbItem},
       {0,0,0,0}};
@@ -2461,7 +2569,7 @@ int main(int argc,const char *argv[])
    }
    
    // Deal with stdout not being a tty
-   if (ttyname(STDOUT_FILENO) == 0 && _config->FindI("quiet",0) < 1)
+   if (!isatty(STDOUT_FILENO) && _config->FindI("quiet",0) < 1)
       _config->Set("quiet","1");
 
    // Setup the output streams