- Opts = Opts->Child;
- for (; Opts != 0; Opts = Opts->Next)
- {
- if (Opts->Value.empty() == true)
- continue;
- Args.push_back(Opts->Value.c_str());
- }
- }
-
- APT::PackageList keepoffset;
- std::copy_if(changeBegin, changeEnd, std::back_inserter(keepoffset),
- [](pkgCache::PkgIterator const &P) { return P->CurrentVer == 0; });
-
- if (keepoffset.empty() == false)
- {
- size_t const BaseArgs = Args.size();
- 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;