From 778559db797ce61611e2b761b24dcb49c49f2652 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 20 Sep 2011 14:30:31 +0200 Subject: * 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 --- apt-pkg/algorithms.cc | 2 +- apt-pkg/deb/dpkgpm.cc | 150 ++++++++++++++++++++++++++------------------------ cmdline/apt-get.cc | 59 +++++++++++--------- debian/changelog | 11 +++- 4 files changed, 123 insertions(+), 99 deletions(-) diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index 5fbcb47be..6ac69032b 100644 --- a/apt-pkg/algorithms.cc +++ b/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; diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 46f48777c..b6c92fc23 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/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 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::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 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_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::const_iterator p = Packages.begin(); + p != Packages.end(); ++p) + free(*p); + Packages.clear(); // the result of the waitpid call int res; diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 9096f263f..49ac8f2cf 100644 --- a/cmdline/apt-get.cc +++ b/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); diff --git a/debian/changelog b/debian/changelog index 12b7d4b23..147a7ec78 100644 --- a/debian/changelog +++ b/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 Wed, 14 Sep 2011 21:01:56 +0200 -- cgit v1.2.3