- if ((Pkg->SelectedState == pkgCache::State::Hold) == MarkHold)
- {
- if (MarkHold == true)
- ioprintf(c1out,_("%s was already set on hold.\n"), Pkg.FullName(true).c_str());
- else
- ioprintf(c1out,_("%s was already not hold.\n"), Pkg.FullName(true).c_str());
- Pkg = pkgset.erase(Pkg, true);
- }
- else
- ++Pkg;
- }
-
- bool dpkgMultiArch = false;
- if (dpkgAssertMultiArch > 0)
- {
- int Status = 0;
- while (waitpid(dpkgAssertMultiArch, &Status, 0) != dpkgAssertMultiArch)
- {
- if (errno == EINTR)
- continue;
- _error->WarningE("dpkgGo", _("Waited for %s but it wasn't there"), "dpkg --assert-multi-arch");
- break;
- }
- if (WIFEXITED(Status) == true && WEXITSTATUS(Status) == 0)
- dpkgMultiArch = true;
- }
-
- if (pkgset.empty() == true)
- return true;
-
- if (_config->FindB("APT::Mark::Simulate", false) == true)
- {
- for (APT::PackageList::iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
- {
- if (MarkHold == false)
- ioprintf(c1out,_("%s set on hold.\n"), Pkg.FullName(true).c_str());
- else
- ioprintf(c1out,_("Canceled hold on %s.\n"), Pkg.FullName(true).c_str());
- }
- return true;
- }
-
- APT::PackageList keepoffset;
- for (APT::PackageList::iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
- {
- if (Pkg->CurrentVer != 0)
- continue;
- keepoffset.insert(*Pkg);
- }
-
- if (keepoffset.empty() == false)
- {
- Args.erase(Args.begin() + BaseArgs, Args.end());
- Args.push_back("--merge-avail");
- // FIXME: supported only since 1.17.7 in dpkg
- Args.push_back("-");
- Args.push_back(NULL);
-
- int external[2] = {-1, -1};
- if (pipe(external) != 0)
- return _error->WarningE("DoHold", "Can't create IPC pipe for dpkg --merge-avail");
-
- pid_t dpkgMergeAvail = ExecFork();
- if (dpkgMergeAvail == 0)
- {
- close(external[1]);
- std::string const chrootDir = _config->FindDir("DPkg::Chroot-Directory");
- if (chrootDir != "/" && chroot(chrootDir.c_str()) != 0 && chdir("/") != 0)
- _error->WarningE("getArchitecture", "Couldn't chroot into %s for dpkg --merge-avail", chrootDir.c_str());
- dup2(external[0], STDIN_FILENO);
- int const nullfd = open("/dev/null", O_RDONLY);
- dup2(nullfd, STDOUT_FILENO);
- execvp(Args[0], (char**) &Args[0]);
- _error->WarningE("dpkgGo", "Can't get dpkg --merge-avail running!");
- _exit(2);
- }
-
- FILE* dpkg = fdopen(external[1], "w");
- for (APT::PackageList::iterator Pkg = keepoffset.begin(); Pkg != keepoffset.end(); ++Pkg)
- {
- char const * Arch;
- if (Pkg->VersionList != 0)
- Arch = Pkg.VersionList().Arch();
- else
- Arch = Pkg.Arch();
- fprintf(dpkg, "Package: %s\nVersion: 0~\nArchitecture: %s\nMaintainer: Dummy Example <dummy@example.org>\n"
- "Description: dummy package record\n A record is needed to put a package on hold, so here it is.\n\n", Pkg.Name(), Arch);
- }
- fclose(dpkg);
- keepoffset.clear();
-
- if (dpkgMergeAvail > 0)
- {
- int Status = 0;
- while (waitpid(dpkgMergeAvail, &Status, 0) != dpkgMergeAvail)
- {
- if (errno == EINTR)
- continue;
- _error->WarningE("dpkgGo", _("Waited for %s but it wasn't there"), "dpkg --merge-avail");
- break;
- }
- if (WIFEXITED(Status) == false || WEXITSTATUS(Status) != 0)
- return _error->Error(_("Executing dpkg failed. Are you root?"));
- }
- }
-
- Args.erase(Args.begin() + BaseArgs, Args.end());
- Args.push_back("--set-selections");
- Args.push_back(NULL);
-
- int external[2] = {-1, -1};
- if (pipe(external) != 0)
- return _error->WarningE("DoHold", "Can't create IPC pipe for dpkg --set-selections");
+ auto const part = std::stable_partition(pkgset.begin(), pkgset.end(),
+ [](pkgCache::VerIterator const &V) { return V.ParentPkg()->SelectedState == pkgCache::State::Hold; });
+
+ bool const MarkHold = strcasecmp(CmdL.FileList[0],"hold") == 0;
+ auto const doneBegin = MarkHold ? pkgset.begin() : part;
+ auto const doneEnd = MarkHold ? part : pkgset.end();
+ std::for_each(doneBegin, doneEnd, [&MarkHold](pkgCache::VerIterator const &V) {
+ if (MarkHold == true)
+ ioprintf(c1out, _("%s was already set on hold.\n"), V.ParentPkg().FullName(true).c_str());
+ else
+ ioprintf(c1out, _("%s was already not hold.\n"), V.ParentPkg().FullName(true).c_str());
+ });
+
+ if (doneBegin == pkgset.begin() && doneEnd == pkgset.end())
+ return true;