* apt-pkg/deb/dpkgpm.cc:
authorDavid Kalnischkies <kalnischkies@gmail.com>
Tue, 20 Sep 2011 12:30:31 +0000 (14:30 +0200)
committerDavid Kalnischkies <kalnischkies@gmail.com>
Tue, 20 Sep 2011 12:30:31 +0000 (14:30 +0200)
  - use std::vector instead of fixed size arrays to store args and
    multiarch-packagename strings
  - load the dpkg base arguments only one time and reuse them later
* cmdline/apt-get.cc:
  - follow Provides in the evaluation of saving candidates, too, for
    statisfying garbage package dependencies (Closes: #640590)
* apt-pkg/algorithms.cc:
  - if a package is garbage, don't try to save it with FixByInstall

apt-pkg/algorithms.cc
apt-pkg/deb/dpkgpm.cc
cmdline/apt-get.cc
debian/changelog

index 5fbcb47..6ac6903 100644 (file)
@@ -1002,7 +1002,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
                     if (BrokenFix == false || DoUpgrade(I) == false)
                     {
                        // Consider other options
-                       if (InOr == false)
+                       if (InOr == false || Cache[I].Garbage == true)
                        {
                           if (Debug == true)
                              clog << "  Removing " << I.FullName(false) << " rather than change " << Start.TargetPkg().FullName(false) << endl;
index 46f4877..b6c92fc 100644 (file)
@@ -887,6 +887,28 @@ bool pkgDPkgPM::Go(int OutStatusFd)
    // create log
    OpenLog();
 
+   // Generate the base argument list for dpkg
+   std::vector<const char *> Args;
+   unsigned long StartSize = 0;
+   string const Tmp = _config->Find("Dir::Bin::dpkg","dpkg");
+   Args.push_back(Tmp.c_str());
+   StartSize += Tmp.length();
+
+   // Stick in any custom dpkg options
+   Configuration::Item const *Opts = _config->Tree("DPkg::Options");
+   if (Opts != 0)
+   {
+      Opts = Opts->Child;
+      for (; Opts != 0; Opts = Opts->Next)
+      {
+        if (Opts->Value.empty() == true)
+           continue;
+        Args.push_back(Opts->Value.c_str());
+        StartSize += Opts->Value.length();
+      }
+   }
+   size_t const BaseArgs = Args.size();
+
    // this loop is runs once per operation
    for (vector<Item>::const_iterator I = List.begin(); I != List.end();)
    {
@@ -908,11 +930,12 @@ bool pkgDPkgPM::Go(int OutStatusFd)
         for (; J != List.end() && J->Op == I->Op; ++J)
            /* nothing */;
 
-      // Generate the argument list
-      const char *Args[MaxArgs + 50];
       // keep track of allocated strings for multiarch package names
-      char *Packages[MaxArgs + 50];
-      unsigned int pkgcount = 0;
+      std::vector<char *> Packages;
+
+      // start with the baseset of arguments
+      unsigned long Size = StartSize;
+      Args.erase(Args.begin() + BaseArgs, Args.end());
 
       // Now check if we are within the MaxArgs limit
       //
@@ -922,91 +945,67 @@ bool pkgDPkgPM::Go(int OutStatusFd)
       // - with the split they may now be configured in different
       //   runs 
       if (J - I > (signed)MaxArgs)
+      {
         J = I + MaxArgs;
-      
-      unsigned int n = 0;
-      unsigned long Size = 0;
-      string const Tmp = _config->Find("Dir::Bin::dpkg","dpkg");
-      Args[n++] = Tmp.c_str();
-      Size += strlen(Args[n-1]);
-      
-      // Stick in any custom dpkg options
-      Configuration::Item const *Opts = _config->Tree("DPkg::Options");
-      if (Opts != 0)
+        Args.reserve(MaxArgs + 10);
+      }
+      else
       {
-        Opts = Opts->Child;
-        for (; Opts != 0; Opts = Opts->Next)
-        {
-           if (Opts->Value.empty() == true)
-              continue;
-           Args[n++] = Opts->Value.c_str();
-           Size += Opts->Value.length();
-        }       
+        Args.reserve((J - I) + 10);
       }
+
       
-      char status_fd_buf[20];
       int fd[2];
       pipe(fd);
-      
-      Args[n++] = "--status-fd";
-      Size += strlen(Args[n-1]);
+
+#define ADDARG(X) Args.push_back(X); Size += strlen(X)
+#define ADDARGC(X) Args.push_back(X); Size += sizeof(X) - 1
+
+      ADDARGC("--status-fd");
+      char status_fd_buf[20];
       snprintf(status_fd_buf,sizeof(status_fd_buf),"%i", fd[1]);
-      Args[n++] = status_fd_buf;
-      Size += strlen(Args[n-1]);
+      ADDARG(status_fd_buf);
 
       switch (I->Op)
       {
         case Item::Remove:
-        Args[n++] = "--force-depends";
-        Size += strlen(Args[n-1]);
-        Args[n++] = "--force-remove-essential";
-        Size += strlen(Args[n-1]);
-        Args[n++] = "--remove";
-        Size += strlen(Args[n-1]);
+        ADDARGC("--force-depends");
+        ADDARGC("--force-remove-essential");
+        ADDARGC("--remove");
         break;
         
         case Item::Purge:
-        Args[n++] = "--force-depends";
-        Size += strlen(Args[n-1]);
-        Args[n++] = "--force-remove-essential";
-        Size += strlen(Args[n-1]);
-        Args[n++] = "--purge";
-        Size += strlen(Args[n-1]);
+        ADDARGC("--force-depends");
+        ADDARGC("--force-remove-essential");
+        ADDARGC("--purge");
         break;
         
         case Item::Configure:
-        Args[n++] = "--configure";
-        Size += strlen(Args[n-1]);
+        ADDARGC("--configure");
         break;
 
         case Item::ConfigurePending:
-        Args[n++] = "--configure";
-        Size += strlen(Args[n-1]);
-        Args[n++] = "--pending";
-        Size += strlen(Args[n-1]);
+        ADDARGC("--configure");
+        ADDARGC("--pending");
         break;
 
         case Item::TriggersPending:
-        Args[n++] = "--triggers-only";
-        Size += strlen(Args[n-1]);
-        Args[n++] = "--pending";
-        Size += strlen(Args[n-1]);
+        ADDARGC("--triggers-only");
+        ADDARGC("--pending");
         break;
 
         case Item::Install:
-        Args[n++] = "--unpack";
-        Size += strlen(Args[n-1]);
-        Args[n++] = "--auto-deconfigure";
-        Size += strlen(Args[n-1]);
+        ADDARGC("--unpack");
+        ADDARGC("--auto-deconfigure");
         break;
       }
 
       if (NoTriggers == true && I->Op != Item::TriggersPending &&
          I->Op != Item::ConfigurePending)
       {
-        Args[n++] = "--no-triggers";
-        Size += strlen(Args[n-1]);
+        ADDARGC("--no-triggers");
       }
+#undef ADDARGC
 
       // Write in the file or package names
       if (I->Op == Item::Install)
@@ -1015,10 +1014,10 @@ bool pkgDPkgPM::Go(int OutStatusFd)
         {
            if (I->File[0] != '/')
               return _error->Error("Internal Error, Pathname to install is not absolute '%s'",I->File.c_str());
-           Args[n++] = I->File.c_str();
-           Size += strlen(Args[n-1]);
+           Args.push_back(I->File.c_str());
+           Size += I->File.length();
         }
-      }      
+      }
       else
       {
         string const nativeArch = _config->Find("APT::Architecture");
@@ -1030,29 +1029,35 @@ bool pkgDPkgPM::Go(int OutStatusFd)
            if (I->Op == Item::Configure && disappearedPkgs.find(I->Pkg.Name()) != disappearedPkgs.end())
               continue;
            if (I->Pkg.Arch() == nativeArch || !strcmp(I->Pkg.Arch(), "all"))
-              Args[n++] = I->Pkg.Name();
+           {
+              char const * const name = I->Pkg.Name();
+              ADDARG(name);
+           }
            else
            {
-              Packages[pkgcount] = strdup(I->Pkg.FullName(false).c_str());
-              Args[n++] = Packages[pkgcount++];
+              char * const fullname = strdup(I->Pkg.FullName(false).c_str());
+              Packages.push_back(fullname);
+              ADDARG(fullname);
            }
-           Size += strlen(Args[n-1]);
         }
         // skip configure action if all sheduled packages disappeared
         if (oldSize == Size)
            continue;
       }
-      Args[n] = 0;
+#undef ADDARG
+
       J = I;
       
       if (_config->FindB("Debug::pkgDPkgPM",false) == true)
       {
-        for (unsigned int k = 0; k != n; k++)
-           clog << Args[k] << ' ';
+        for (std::vector<const char *>::const_iterator a = Args.begin();
+             a != Args.end(); ++a)
+           clog << *a << ' ';
         clog << endl;
         continue;
       }
-      
+      Args.push_back(NULL);
+
       cout << flush;
       clog << flush;
       cerr << flush;
@@ -1162,7 +1167,7 @@ bool pkgDPkgPM::Go(int OutStatusFd)
         /* No Job Control Stop Env is a magic dpkg var that prevents it
            from using sigstop */
         putenv((char *)"DPKG_NO_TSTP=yes");
-        execvp(Args[0],(char **)Args);
+        execvp(Args[0], (char**) &Args[0]);
         cerr << "Could not exec dpkg!" << endl;
         _exit(100);
       }      
@@ -1188,10 +1193,11 @@ bool pkgDPkgPM::Go(int OutStatusFd)
       sigemptyset(&sigmask);
       sigprocmask(SIG_BLOCK,&sigmask,&original_sigmask);
 
-      /* clean up the temporary allocation for multiarch package names in
-         the parent, so we don't leak memory when we return. */
-      for (unsigned int i = 0; i < pkgcount; i++)
-        free(Packages[i]);
+      /* free vectors (and therefore memory) as we don't need the included data anymore */
+      for (std::vector<char *>::const_iterator p = Packages.begin();
+          p != Packages.end(); ++p)
+        free(*p);
+      Packages.clear();
 
       // the result of the waitpid call
       int res;
index 9096f26..49ac8f2 100644 (file)
@@ -1684,8 +1684,9 @@ bool DoAutomaticRemove(CacheFile &Cache)
            // install it in the first place, so nuke it instead of show it
            if (Cache[Pkg].Install() == true && Pkg.CurrentVer() == 0)
            {
+              if (Pkg.CandVersion() != 0)
+                 tooMuch.insert(Pkg);
               Cache->MarkDelete(Pkg, false);
-              tooMuch.insert(Pkg);
            }
            // only show stuff in the list that is not yet marked for removal
            else if(hideAutoRemove == false && Cache[Pkg].Delete() == false) 
@@ -1709,33 +1710,41 @@ bool DoAutomaticRemove(CacheFile &Cache)
       bool Changed;
       do {
         Changed = false;
-        for (APT::PackageSet::const_iterator P = tooMuch.begin();
-             P != tooMuch.end() && Changed == false; ++P)
+        for (APT::PackageSet::const_iterator Pkg = tooMuch.begin();
+             Pkg != tooMuch.end() && Changed == false; ++Pkg)
         {
-           for (pkgCache::DepIterator R = P.RevDependsList();
-                R.end() == false; ++R)
-           {
-              if (R.IsNegative() == true ||
-                  Cache->IsImportantDep(R) == false)
-                 continue;
-              pkgCache::PkgIterator N = R.ParentPkg();
-              if (N.end() == true || (N->CurrentVer == 0 && (*Cache)[N].Install() == false))
-                 continue;
-              if (Debug == true)
-                 std::clog << "Save " << P << " as another installed garbage package depends on it" << std::endl;
-              Cache->MarkInstall(P, false);
-              if(hideAutoRemove == false)
+           APT::PackageSet too;
+           too.insert(Pkg);
+           for (pkgCache::PrvIterator Prv = Cache[Pkg].CandidateVerIter(Cache).ProvidesList();
+                Prv.end() == false; ++Prv)
+              too.insert(Prv.ParentPkg());
+           for (APT::PackageSet::const_iterator P = too.begin();
+                P != too.end() && Changed == false; ++P) {
+              for (pkgCache::DepIterator R = P.RevDependsList();
+                   R.end() == false; ++R)
               {
-                 ++autoRemoveCount;
-                 if (smallList == false)
-                 {
-                    autoremovelist += P.FullName(true) + " ";
-                    autoremoveversions += string(Cache[P].CandVersion) + "\n";
-                 }
+                 if (R.IsNegative() == true ||
+                     Cache->IsImportantDep(R) == false)
+                    continue;
+                pkgCache::PkgIterator N = R.ParentPkg();
+                if (N.end() == true || (N->CurrentVer == 0 && (*Cache)[N].Install() == false))
+                   continue;
+                if (Debug == true)
+                   std::clog << "Save " << Pkg << " as another installed garbage package depends on it" << std::endl;
+                Cache->MarkInstall(Pkg, false);
+                if (hideAutoRemove == false)
+                {
+                   ++autoRemoveCount;
+                   if (smallList == false)
+                   {
+                      autoremovelist += Pkg.FullName(true) + " ";
+                      autoremoveversions += string(Cache[Pkg].CandVersion) + "\n";
+                   }
+                }
+                tooMuch.erase(Pkg);
+                Changed = true;
+                break;
               }
-              tooMuch.erase(P);
-              Changed = true;
-              break;
            }
         }
       } while (Changed == true);
index 12b7d4b..147a7ec 100644 (file)
@@ -1,9 +1,18 @@
-apt (0.8.15.9) unstable; urgency=low
+apt (0.8.15.9) UNRELEASED; urgency=low
 
   [ David Kalnischkies ]
   * doc/apt-get.8.xml:
     - change wording of autoremove description as suggested
       by Robert Simmons, thanks! (Closes: #641490)
+  * apt-pkg/deb/dpkgpm.cc:
+    - use std::vector instead of fixed size arrays to store args and
+      multiarch-packagename strings
+    - load the dpkg base arguments only one time and reuse them later
+  * cmdline/apt-get.cc:
+    - follow Provides in the evaluation of saving candidates, too, for
+      statisfying garbage package dependencies (Closes: #640590)
+  * apt-pkg/algorithms.cc:
+    - if a package is garbage, don't try to save it with FixByInstall
 
  -- David Kalnischkies <kalnischkies@gmail.com>  Wed, 14 Sep 2011 21:01:56 +0200