]> git.saurik.com Git - apt.git/blobdiff - cmdline/apt-get.cc
add a ConstructedBy member to the PackageSet which can be used by the
[apt.git] / cmdline / apt-get.cc
index c081ca130e178d98ff018fb7bbec451b486045db..d3ddcbfe8e1a1346da53166e02f889a7c71c9edb 100644 (file)
@@ -1079,43 +1079,8 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
    name matching it was split out.. */
 bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
                  pkgProblemResolver &Fix,bool Remove,bool BrokenFix,
-                 unsigned int &ExpectedInst,bool AllowFail = true)
+                 bool AllowFail = true)
 {
-   /* This is a pure virtual package and there is a single available
-      candidate providing it. */
-   if (Cache[Pkg].CandidateVer == 0 && Pkg->ProvidesList != 0)
-   {
-      pkgCache::PkgIterator Prov;
-      bool found_one = false;
-
-      for (pkgCache::PrvIterator P = Pkg.ProvidesList(); P; P++)
-      {
-        pkgCache::VerIterator const PVer = P.OwnerVer();
-        pkgCache::PkgIterator const PPkg = PVer.ParentPkg();
-
-        /* Ignore versions that are not a candidate. */
-        if (Cache[PPkg].CandidateVer != PVer)
-            continue;
-
-        if (found_one == false)
-        {
-           Prov = PPkg;
-           found_one = true;
-        }
-        else if (PPkg != Prov)
-        {
-           found_one = false; // we found at least two
-           break;
-        }
-      }
-
-      if (found_one == true)
-      {
-        ioprintf(c1out,_("Note, selecting %s instead of %s\n"),
-                 Prov.FullName(true).c_str(),Pkg.FullName(true).c_str());
-        Pkg = Prov;
-      }
-   }
 
    // Handle the no-upgrade case
    if (_config->FindB("APT::Get::upgrade",true) == false &&
@@ -1244,9 +1209,7 @@ bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
                     Pkg.FullName(true).c_str());
       }      
    }   
-   else
-      ExpectedInst++;
-   
+
    // 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)
@@ -1589,6 +1552,88 @@ bool DoUpgrade(CommandLine &CmdL)
    return InstallPackages(Cache,true);
 }
                                                                        /*}}}*/
+// CacheSetHelperAPTGet - responsible for message telling from the CacheSets/*{{{*/
+class CacheSetHelperAPTGet : public APT::CacheSetHelper {
+       /** \brief stream message should be printed to */
+       std::ostream &out;
+       /** \brief were things like Task or RegEx used to select packages? */
+       bool explicitlyNamed;
+
+public:
+       CacheSetHelperAPTGet(std::ostream &out) : APT::CacheSetHelper(true), out(out) {
+               explicitlyNamed = true;
+       }
+
+       virtual void showTaskSelection(APT::PackageSet const &pkgset, string const &pattern) {
+               for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
+                       ioprintf(out, _("Note, selecting '%s' for task '%s'\n"),
+                                Pkg.FullName(true).c_str(), pattern.c_str());
+               explicitlyNamed = false;
+       }
+       virtual void showRegExSelection(APT::PackageSet const &pkgset, string const &pattern) {
+               for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
+                       ioprintf(out, _("Note, selecting '%s' for regex '%s'\n"),
+                                Pkg.FullName(true).c_str(), pattern.c_str());
+               explicitlyNamed = false;
+       }
+       virtual void showSelectedVersion(pkgCache::PkgIterator const &Pkg, pkgCache::VerIterator const Ver,
+                                string const &ver, bool const &verIsRel) {
+               if (ver != Ver.VerStr())
+                       ioprintf(out, _("Selected version '%s' (%s) for '%s'\n"),
+                                Ver.VerStr(), Ver.RelStr().c_str(), Pkg.FullName(true).c_str());
+       }
+
+       virtual APT::VersionSet canNotFindCandInstVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
+               return tryVirtualPackage(Cache, Pkg, APT::VersionSet::CANDINST);
+       }
+
+       virtual APT::VersionSet canNotFindInstCandVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
+               return tryVirtualPackage(Cache, Pkg, APT::VersionSet::INSTCAND);
+       }
+
+       APT::VersionSet tryVirtualPackage(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg,
+                                               APT::VersionSet::Version const &select) {
+               /* This is a pure virtual package and there is a single available
+                  candidate providing it. */
+               if (unlikely(Cache[Pkg].CandidateVer != 0) || Pkg->ProvidesList == 0) {
+                       if (select == APT::VersionSet::CANDINST)
+                               return APT::CacheSetHelper::canNotFindCandInstVer(Cache, Pkg);
+                       return APT::CacheSetHelper::canNotFindInstCandVer(Cache, Pkg);
+               }
+
+               pkgCache::PkgIterator Prov;
+               bool found_one = false;
+               for (pkgCache::PrvIterator P = Pkg.ProvidesList(); P; ++P) {
+                       pkgCache::VerIterator const PVer = P.OwnerVer();
+                       pkgCache::PkgIterator const PPkg = PVer.ParentPkg();
+
+                       /* Ignore versions that are not a candidate. */
+                       if (Cache[PPkg].CandidateVer != PVer)
+                               continue;
+
+                       if (found_one == false) {
+                               Prov = PPkg;
+                               found_one = true;
+                       } else if (PPkg != Prov) {
+                               found_one = false; // we found at least two
+                               break;
+                       }
+               }
+
+               if (found_one == true) {
+                       ioprintf(out, _("Note, selecting '%s' instead of '%s'\n"),
+                                Prov.FullName(true).c_str(), Pkg.FullName(true).c_str());
+                       return APT::VersionSet::FromPackage(Cache, Prov, select, *this);
+               }
+               if (select == APT::VersionSet::CANDINST)
+                       return APT::CacheSetHelper::canNotFindCandInstVer(Cache, Pkg);
+               return APT::CacheSetHelper::canNotFindInstCandVer(Cache, Pkg);
+       }
+
+       inline bool allPkgNamedExplicitly() const { return explicitlyNamed; }
+
+};
+                                                                       /*}}}*/
 // DoInstall - Install packages from the command line                  /*{{{*/
 // ---------------------------------------------------------------------
 /* Install named packages */
@@ -1605,69 +1650,85 @@ bool DoInstall(CommandLine &CmdL)
       BrokenFix = true;
    
    unsigned int AutoMarkChanged = 0;
-   unsigned int ExpectedInst = 0;
    pkgProblemResolver Fix(Cache);
 
-   unsigned short fallback = 0;
+   static const unsigned short MOD_REMOVE = 1;
+   static const unsigned short MOD_INSTALL = 2;
+
+   unsigned short fallback = MOD_INSTALL;
    if (strcasecmp(CmdL.FileList[0],"remove") == 0)
-      fallback = 1;
+      fallback = MOD_REMOVE;
    else if (strcasecmp(CmdL.FileList[0], "purge") == 0)
    {
       _config->Set("APT::Get::Purge", true);
-      fallback = 1;
+      fallback = MOD_REMOVE;
    }
    else if (strcasecmp(CmdL.FileList[0], "autoremove") == 0)
    {
       _config->Set("APT::Get::AutomaticRemove", "true");
-      fallback = 1;
+      fallback = MOD_REMOVE;
    }
-   // new scope for the ActionGroup
-   {
-      // TODO: Howto get an ExpectedInst count ?
-      pkgDepCache::ActionGroup group(Cache);
-      std::list<APT::VersionSet::Modifier> mods;
-      mods.push_back(APT::VersionSet::Modifier(0, "+",
+
+   std::list<APT::VersionSet::Modifier> mods;
+   mods.push_back(APT::VersionSet::Modifier(MOD_INSTALL, "+",
                APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::CANDINST));
-      mods.push_back(APT::VersionSet::Modifier(1, "-",
+   mods.push_back(APT::VersionSet::Modifier(MOD_REMOVE, "-",
                APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::INSTCAND));
-      std::map<unsigned short, APT::VersionSet> verset = APT::VersionSet::GroupedFromCommandLine(Cache,
-               CmdL.FileList + 1, mods, fallback, c0out);
+   CacheSetHelperAPTGet helper(c0out);
+   std::map<unsigned short, APT::VersionSet> verset = APT::VersionSet::GroupedFromCommandLine(Cache,
+               CmdL.FileList + 1, mods, fallback, helper);
 
-      if (_error->PendingError() == true)
-        return false;
+   if (_error->PendingError() == true)
+      return false;
 
-      for (APT::VersionSet::const_iterator Ver = verset[0].begin();
-          Ver != verset[0].end(); ++Ver)
-      {
-        pkgCache::PkgIterator Pkg = Ver.ParentPkg();
-        Cache->SetCandidateVersion(Ver);
-
-        if (TryToInstall(Pkg, Cache, Fix, false, 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 (Cache[Pkg].Install() == false &&
-            (Cache[Pkg].Flags & pkgCache::Flag::Auto) &&
-            _config->FindB("APT::Get::ReInstall",false) == false &&
-            _config->FindB("APT::Get::Only-Upgrade",false) == false &&
-            _config->FindB("APT::Get::Download-Only",false) == false)
-        {
-           ioprintf(c1out,_("%s set to manually installed.\n"),
-                       Pkg.FullName(true).c_str());
-           Cache->MarkAuto(Pkg,false);
-           AutoMarkChanged++;
-        }
-      }
+   unsigned short order[] = { 0, 0, 0 };
+   if (fallback == MOD_INSTALL) {
+      order[0] = MOD_INSTALL;
+      order[1] = MOD_REMOVE;
+   } else {
+      order[0] = MOD_REMOVE;
+      order[1] = MOD_INSTALL;
+   }
 
-      for (APT::VersionSet::const_iterator Ver = verset[1].begin();
-          Ver != verset[1].end(); ++Ver)
+   // new scope for the ActionGroup
+   {
+      pkgDepCache::ActionGroup group(Cache);
+      for (unsigned short i = 0; order[i] != 0; ++i)
       {
-        pkgCache::PkgIterator Pkg = Ver.ParentPkg();
+        if (order[i] == MOD_INSTALL)
+           for (APT::VersionSet::const_iterator Ver = verset[MOD_INSTALL].begin();
+                Ver != verset[MOD_INSTALL].end(); ++Ver)
+           {
+              pkgCache::PkgIterator Pkg = Ver.ParentPkg();
+              Cache->SetCandidateVersion(Ver);
+
+              if (TryToInstall(Pkg, Cache, Fix, false, BrokenFix) == 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 (Cache[Pkg].Install() == false &&
+                  (Cache[Pkg].Flags & pkgCache::Flag::Auto) &&
+                  _config->FindB("APT::Get::ReInstall",false) == false &&
+                  _config->FindB("APT::Get::Only-Upgrade",false) == false &&
+                  _config->FindB("APT::Get::Download-Only",false) == false)
+              {
+                 ioprintf(c1out,_("%s set to manually installed.\n"),
+                               Pkg.FullName(true).c_str());
+                 Cache->MarkAuto(Pkg,false);
+                 AutoMarkChanged++;
+              }
+           }
+        else if (order[i] == MOD_REMOVE)
+           for (APT::VersionSet::const_iterator Ver = verset[MOD_REMOVE].begin();
+                Ver != verset[MOD_REMOVE].end(); ++Ver)
+           {
+              pkgCache::PkgIterator Pkg = Ver.ParentPkg();
 
-        if (TryToInstall(Pkg, Cache, Fix, true, BrokenFix, ExpectedInst) == false)
-           return false;
+              if (TryToInstall(Pkg, Cache, Fix, true, BrokenFix) == false)
+                 return false;
+           }
       }
 
       if (_error->PendingError() == true)
@@ -1719,7 +1780,7 @@ bool DoInstall(CommandLine &CmdL)
 
    /* Print out a list of packages that are going to be installed extra
       to what the user asked */
-   if (Cache->InstCount() != ExpectedInst)
+   if (Cache->InstCount() != verset[MOD_INSTALL].size())
    {
       string List;
       string VersionsList;
@@ -1845,7 +1906,8 @@ bool DoInstall(CommandLine &CmdL)
       Cache->writeStateFile(NULL);
 
    // See if we need to prompt
-   if (Cache->InstCount() == ExpectedInst && Cache->DelCount() == 0)
+   // FIXME: check if really the packages in the set are going to be installed
+   if (Cache->InstCount() == verset[MOD_INSTALL].size() && Cache->DelCount() == 0)
       return InstallPackages(Cache,false,false);
 
    return InstallPackages(Cache,false);   
@@ -2429,7 +2491,6 @@ bool DoBuildDep(CommandLine &CmdL)
       }
       
       // Install the requested packages
-      unsigned int ExpectedInst = 0;
       vector <pkgSrcRecords::Parser::BuildDepRec>::iterator D;
       pkgProblemResolver Fix(Cache);
       bool skipAlternatives = false; // skip remaining alternatives in an or group
@@ -2460,7 +2521,7 @@ bool DoBuildDep(CommandLine &CmdL)
              */
             if (IV.end() == false && 
                 Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
-               TryToInstall(Pkg,Cache,Fix,true,false,ExpectedInst);
+               TryToInstall(Pkg,Cache,Fix,true,false);
          }
         else // BuildDep || BuildDepIndep
          {
@@ -2576,7 +2637,7 @@ bool DoBuildDep(CommandLine &CmdL)
             if (_config->FindB("Debug::BuildDeps",false) == true)
                cout << "  Trying to install " << (*D).Package << endl;
 
-            if (TryToInstall(Pkg,Cache,Fix,false,false,ExpectedInst) == true)
+            if (TryToInstall(Pkg,Cache,Fix,false,false) == true)
             {
                // We successfully installed something; skip remaining alternatives
                skipAlternatives = hasAlternatives;
@@ -2866,7 +2927,7 @@ int main(int argc,const char *argv[])                                     /*{{{*/
    }
 
    // Deal with stdout not being a tty
-   if (!isatty(STDOUT_FILENO) && _config->FindI("quiet",0) < 1)
+   if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1)
       _config->Set("quiet","1");
 
    // Setup the output streams
@@ -2887,13 +2948,11 @@ int main(int argc,const char *argv[])                                   /*{{{*/
    CmdL.DispatchArg(Cmds);
 
    // Print any errors or warnings found during parsing
-   if (_error->empty() == false)
-   {
-      bool Errors = _error->PendingError();
+   bool const Errors = _error->PendingError();
+   if (_config->FindI("quiet",0) > 0)
       _error->DumpErrors();
-      return Errors == true?100:0;
-   }
-   
-   return 0;   
+   else
+      _error->DumpErrors(GlobalError::DEBUG);
+   return Errors == true ? 100 : 0;
 }
                                                                        /*}}}*/