]> git.saurik.com Git - apt.git/blobdiff - cmdline/apt-get.cc
* add "purge" commandline argument, closes: #133421)
[apt.git] / cmdline / apt-get.cc
index a723174ab47998339634ad408611350b851e4400..1dcbbfc5badad255a3ed3b193b67c6974fc8f17b 100644 (file)
@@ -629,6 +629,8 @@ void CacheFile::Sort()
    and verifies that the system is OK. */
 bool CacheFile::CheckDeps(bool AllowBroken)
 {
+   bool FixBroken = _config->FindB("APT::Get::Fix-Broken",false);
+
    if (_error->PendingError() == true)
       return false;
 
@@ -640,12 +642,24 @@ bool CacheFile::CheckDeps(bool AllowBroken)
    if (pkgApplyStatus(*DCache) == false)
       return false;
    
+   if (_config->FindB("APT::Get::Fix-Policy-Broken",false) == true)
+   {
+      FixBroken = true;
+      if ((DCache->PolicyBrokenCount() > 0))
+      {
+        // upgrade all policy-broken packages with ForceImportantDeps=True
+        for (pkgCache::PkgIterator I = Cache->PkgBegin(); !I.end(); I++)
+           if ((*DCache)[I].NowPolicyBroken() == true) 
+              DCache->MarkInstall(I,true,0, false, true);
+      }
+   }
+
    // Nothing is broken
    if (DCache->BrokenCount() == 0 || AllowBroken == true)
       return true;
 
    // Attempt to fix broken things
-   if (_config->FindB("APT::Get::Fix-Broken",false) == true)
+   if (FixBroken == true)
    {
       c1out << _("Correcting dependencies...") << flush;
       if (pkgFixBroken(*DCache) == false || DCache->BrokenCount() != 0)
@@ -1146,9 +1160,11 @@ bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
    else
       ExpectedInst++;
    
-   // Install it with autoinstalling enabled.
-   if (State.InstBroken() == true && BrokenFix == false)
+   // Install it with autoinstalling enabled (if we not respect the minial
+   // required deps or the policy)
+   if ((State.InstBroken() == true || State.InstPolicyBroken() == true) && BrokenFix == false)
       Cache.MarkInstall(Pkg,true);
+
    return true;
 }
                                                                        /*}}}*/
@@ -1403,31 +1419,52 @@ bool DoUpdate(CommandLine &CmdL)
 /* Remove unused automatic packages */
 bool DoAutomaticRemove(CacheFile &Cache)
 {
-   if(_config->FindI("Debug::pkgAutoRemove",false))
-      std::cout << "DoAutomaticRemove()" << std::endl;
+   bool Debug = _config->FindI("Debug::pkgAutoRemove",false);
+   bool doAutoRemove = _config->FindB("APT::Get::AutomaticRemove", false);
+   bool hideAutoRemove = _config->FindB("APT::Get::HideAutoRemove");
+   pkgDepCache::ActionGroup group(*Cache);
 
-   if (_config->FindB("APT::Get::Remove",true) == false)
-      return _error->Error(_("We are not supposed to delete stuff, can't "
-                            "start AutoRemover"));
+   if(Debug)
+      std::cout << "DoAutomaticRemove()" << std::endl;
 
+   if (_config->FindB("APT::Get::Remove",true) == false &&
+       doAutoRemove == true)
    {
-     pkgDepCache::ActionGroup group(*Cache);
-
-     // look over the cache to see what can be removed
-     for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); ! Pkg.end(); ++Pkg)
-       {
-        if (Cache[Pkg].Garbage)
-          {
-            if(Pkg.CurrentVer() != 0 || Cache[Pkg].Install())
-              fprintf(stdout,"We could delete %s\n", Pkg.Name());
+      c1out << _("We are not supposed to delete stuff, can't start "
+                "AutoRemover") << std::endl;
+      doAutoRemove = false;
+   }
 
-            if(Pkg.CurrentVer() != 0 && Pkg->CurrentState != pkgCache::State::ConfigFiles)
+   string autoremovelist, autoremoveversions;
+   // look over the cache to see what can be removed
+   for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); ! Pkg.end(); ++Pkg)
+   {
+      if (Cache[Pkg].Garbage)
+      {
+        if(Pkg.CurrentVer() != 0 || Cache[Pkg].Install())
+           if(Debug)
+              std::cout << "We could delete %s" <<  Pkg.Name() << std::endl;
+         
+        // only show stuff in the list that is not yet marked for removal
+        if(Cache[Pkg].Delete() == false) 
+        {
+           autoremovelist += string(Pkg.Name()) + " ";
+           autoremoveversions += string(Cache[Pkg].CandVersion) + "\n";
+        }
+        if (doAutoRemove)
+        {
+           if(Pkg.CurrentVer() != 0 && 
+              Pkg->CurrentState != pkgCache::State::ConfigFiles)
               Cache->MarkDelete(Pkg, _config->FindB("APT::Get::Purge", false));
-            else
+           else
               Cache->MarkKeep(Pkg, false, false);
-          }
-       }
+        }
+      }
    }
+   if (!hideAutoRemove) 
+      ShowList(c1out, _("The following packages were automatically installed and are no longer required:"), autoremovelist, autoremoveversions);
+   if (!doAutoRemove && !hideAutoRemove && autoremovelist.size() > 0)
+      c1out << _("Use 'apt-get autoremove' to remove them.") << std::endl;
 
    // Now see if we destroyed anything
    if (Cache->BrokenCount() != 0)
@@ -1464,6 +1501,51 @@ bool DoUpgrade(CommandLine &CmdL)
    return InstallPackages(Cache,true);
 }
                                                                        /*}}}*/
+// DoInstallTask - Install task from the command line                  /*{{{*/
+// ---------------------------------------------------------------------
+/* Install named task */
+bool TryInstallTask(pkgDepCache &Cache, pkgProblemResolver &Fix, 
+                   bool BrokenFix,
+                   unsigned int& ExpectedInst, 
+                   const char *taskname)
+{
+   const char *start, *end;
+   pkgCache::PkgIterator Pkg;
+   char buf[64*1024];
+   regex_t Pattern;
+
+   // get the records
+   pkgRecords Recs(Cache);
+
+   // build regexp for the task
+   char S[300];
+   snprintf(S, sizeof(S), "^Task:.*[^a-z]%s[^a-z].*\n", taskname);
+   regcomp(&Pattern,S, REG_EXTENDED | REG_NOSUB | REG_NEWLINE);
+   
+   bool found = false;
+   bool res = true;
+   for (Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
+   {
+      pkgCache::VerIterator ver = Cache[Pkg].CandidateVerIter(Cache);
+      if(ver.end())
+        continue;
+      pkgRecords::Parser &parser = Recs.Lookup(ver.FileList());
+      parser.GetRec(start,end);
+      strncpy(buf, start, end-start);
+      buf[end-start] = 0x0;
+      if (regexec(&Pattern,buf,0,0,0) != 0)
+        continue;
+      res &= TryToInstall(Pkg,Cache,Fix,false,BrokenFix,ExpectedInst);
+      found = true;
+   }
+   
+   if(!found)
+      _error->Error(_("Couldn't find task %s"),taskname);
+
+   regfree(&Pattern);
+   return res;
+}
+
 // DoInstall - Install packages from the command line                  /*{{{*/
 // ---------------------------------------------------------------------
 /* Install named packages */
@@ -1479,6 +1561,7 @@ bool DoInstall(CommandLine &CmdL)
    if (Cache->BrokenCount() != 0)
       BrokenFix = true;
    
+   unsigned int AutoMarkChanged = 0;
    unsigned int ExpectedInst = 0;
    unsigned int Packages = 0;
    pkgProblemResolver Fix(Cache);
@@ -1486,12 +1569,16 @@ bool DoInstall(CommandLine &CmdL)
    bool DefRemove = false;
    if (strcasecmp(CmdL.FileList[0],"remove") == 0)
       DefRemove = true;
+   else if (strcasecmp(CmdL.FileList[0], "purge") == 0)
+   {
+      _config->Set("APT::Get::Purge", true);
+      DefRemove = true;
+   }
    else if (strcasecmp(CmdL.FileList[0], "autoremove") == 0)
    {
       _config->Set("APT::Get::AutomaticRemove", "true");
       DefRemove = true;
    }
-
    // new scope for the ActionGroup
    {
       pkgDepCache::ActionGroup group(Cache);
@@ -1601,6 +1688,19 @@ bool DoInstall(CommandLine &CmdL)
                  return false;
            if (TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,ExpectedInst) == false)
               return false;
+
+           // see if we need to fix the auto-mark flag 
+           // e.g. apt-get install foo 
+           // where foo is marked automatic
+           if(!Remove && 
+              Cache[Pkg].Install() == false && 
+              (Cache[Pkg].Flags & pkgCache::Flag::Auto))
+           {
+              ioprintf(c1out,_("%s set to manual installed.\n"),
+                       Pkg.Name());
+              Cache->MarkAuto(Pkg,false);
+              AutoMarkChanged++;
+           }
         }      
       }
 
@@ -1680,73 +1780,99 @@ bool DoInstall(CommandLine &CmdL)
       string SuggestsVersions, RecommendsVersions;
       for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
       {
-        pkgCache::PkgIterator I(Cache,Cache.List[J]);
+        pkgCache::PkgIterator Pkg(Cache,Cache.List[J]);
 
         /* Just look at the ones we want to install */
-        if ((*Cache)[I].Install() == false)
+        if ((*Cache)[Pkg].Install() == false)
           continue;
 
-        for (pkgCache::VerIterator V = I.VersionList(); V.end() == false; V++)
-         {
-            for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; )
-             {
-                pkgCache::DepIterator Start;
-                pkgCache::DepIterator 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
-                 */
-                
-                bool providedBySomething = 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;
-            
-                 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;
-
-                     /* Skip if we already saw it */
-                     if (int(SuggestsList.find(target)) != -1 || int(RecommendsList.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) {
-                      RecommendsList += target;
-                      RecommendsVersions += string(Cache[Start.TargetPkg()].CandVersion) + "\n";
-                    }
-
-                     if (Start >= End)
-                        break;
-                     Start++;
-                 }
-             }
-         }
+        // get the recommends/suggests for the candidate ver
+        pkgCache::VerIterator CV = (*Cache)[Pkg].CandidateVerIter(*Cache);
+        for (pkgCache::DepIterator D = CV.DependsList(); D.end() == false; )
+        {
+           pkgCache::DepIterator Start;
+           pkgCache::DepIterator End;
+           D.GlobOr(Start,End); // advances D
+
+           // FIXME: we really should display a or-group as a or-group to the user
+           //        the problem is that ShowList is incapable of doing this
+           string RecommendsOrList,RecommendsOrVersions;
+           string SuggestsOrList,SuggestsOrVersions;
+           bool foundInstalledInOrGroup = false;
+           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())
+              {
+                 foundInstalledInOrGroup=true;
+                 break;
+              }
+
+              /* Skip if we already saw it */
+              if (int(SuggestsList.find(target)) != -1 || int(RecommendsList.find(target)) != -1)
+              {
+                 foundInstalledInOrGroup=true;
+                 break; 
+              }
+
+              // this is a dep on a virtual pkg, check if any package that provides it
+              // should be installed
+              if(Start.TargetPkg().ProvidesList() != 0)
+              {
+                 pkgCache::PrvIterator I = Start.TargetPkg().ProvidesList();
+                 for (; I.end() == false; I++)
+                 {
+                    pkgCache::PkgIterator Pkg = I.OwnerPkg();
+                    if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer() && 
+                        Pkg.CurrentVer() != 0)
+                       foundInstalledInOrGroup=true;
+                 }
+              }
+
+              if (Start->Type == pkgCache::Dep::Suggests) 
+              {
+                 SuggestsOrList += target;
+                 SuggestsOrVersions += string(Cache[Start.TargetPkg()].CandVersion) + "\n";
+              }
+              
+              if (Start->Type == pkgCache::Dep::Recommends) 
+              {
+                 RecommendsOrList += target;
+                 RecommendsOrVersions += string(Cache[Start.TargetPkg()].CandVersion) + "\n";
+              }
+
+              if (Start >= End)
+                 break;
+              Start++;
+           }
+           
+           if(foundInstalledInOrGroup == false)
+           {
+              RecommendsList += RecommendsOrList;
+              RecommendsVersions += RecommendsOrVersions;
+              SuggestsList += SuggestsOrList;
+              SuggestsVersions += SuggestsOrVersions;
+           }
+              
+        }
       }
+
       ShowList(c1out,_("Suggested packages:"),SuggestsList,SuggestsVersions);
       ShowList(c1out,_("Recommended packages:"),RecommendsList,RecommendsVersions);
 
    }
 
+   // if nothing changed in the cache, but only the automark information
+   // we write the StateFile here, otherwise it will be written in 
+   // cache.commit()
+   if (AutoMarkChanged > 0 &&
+       Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
+       Cache->BadCount() == 0)
+      Cache->writeStateFile(NULL);
+
    // See if we need to prompt
    if (Cache->InstCount() == ExpectedInst && Cache->DelCount() == 0)
       return InstallPackages(Cache,false,false);
@@ -2005,6 +2131,11 @@ bool DoSource(CommandLine &CmdL)
             I->Type != "tar")
            continue;
 
+        // Dsc only mode only fetches .dsc files
+        if (_config->FindB("APT::Get::Dsc-Only",false) == true &&
+            I->Type != "dsc")
+           continue;
+
         // don't download the same uri twice (should this be moved to
         // the fetcher interface itself?)
         if(queued.find(Last->Index().ArchiveURI(I->Path)) != queued.end())
@@ -2498,6 +2629,7 @@ bool ShowHelp(CommandLine &CmdL)
       "   upgrade - Perform an upgrade\n"
       "   install - Install new packages (pkg is libc6 not libc6.deb)\n"
       "   remove - Remove packages\n"
+      "   purge - Remove and purge packages\n"
       "   source - Download source archives\n"
       "   build-dep - Configure build-dependencies for source packages\n"
       "   dist-upgrade - Distribution upgrade, see apt-get(8)\n"
@@ -2587,7 +2719,8 @@ int main(int argc,const char *argv[])
       {0,"force-yes","APT::Get::force-yes",0},
       {0,"print-uris","APT::Get::Print-URIs",0},
       {0,"diff-only","APT::Get::Diff-Only",0},
-      {0,"tar-only","APT::Get::tar-Only",0},
+      {0,"tar-only","APT::Get::Tar-Only",0},
+      {0,"dsc-only","APT::Get::Dsc-Only",0},
       {0,"purge","APT::Get::Purge",0},
       {0,"list-cleanup","APT::Get::List-Cleanup",0},
       {0,"reinstall","APT::Get::ReInstall",0},
@@ -2597,6 +2730,8 @@ int main(int argc,const char *argv[])
       {0,"arch-only","APT::Get::Arch-Only",0},
       {0,"auto-remove","APT::Get::AutomaticRemove",0},
       {0,"allow-unauthenticated","APT::Get::AllowUnauthenticated",0},
+      {0,"install-recommends","APT::Install-Recommends",CommandLine::Boolean},
+      {0,"fix-policy","APT::Get::Fix-Policy-Broken",0},
       {'c',"config-file",0,CommandLine::ConfigFile},
       {'o',"option",0,CommandLine::ArbItem},
       {0,0,0,0}};