Pārlūkot izejas kodu

* 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 15 gadi atpakaļ
vecāks
revīzija
778559db79
4 mainītis faili ar 123 papildinājumiem un 99 dzēšanām
  1. 1 1
      apt-pkg/algorithms.cc
  2. 78 72
      apt-pkg/deb/dpkgpm.cc
  3. 34 25
      cmdline/apt-get.cc
  4. 10 1
      debian/changelog

+ 1 - 1
apt-pkg/algorithms.cc

@@ -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;

+ 78 - 72
apt-pkg/deb/dpkgpm.cc

@@ -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;

+ 34 - 25
cmdline/apt-get.cc

@@ -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);

+ 10 - 1
debian/changelog

@@ -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