diff options
-rw-r--r-- | apt-pkg/edsp.cc | 73 | ||||
-rwxr-xr-x | test/integration/test-external-installation-planer-protocol | 28 |
2 files changed, 81 insertions, 20 deletions
diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index 58982ade2..e37ab04b4 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -1143,7 +1143,7 @@ bool EIPP::WriteRequest(pkgDepCache &Cache, FileFd &output, /*{{{*/ return WriteOkay(Okay, output, "\n"); } /*}}}*/ -static bool WriteScenarioEIPPVersion(pkgDepCache &Cache, FileFd &output, pkgCache::PkgIterator const &Pkg,/*{{{*/ +static bool WriteScenarioEIPPVersion(pkgDepCache &, FileFd &output, pkgCache::PkgIterator const &Pkg,/*{{{*/ pkgCache::VerIterator const &Ver) { bool Okay = true; @@ -1159,37 +1159,70 @@ static bool WriteScenarioEIPPVersion(pkgDepCache &Cache, FileFd &output, pkgCach case pkgCache::State::TriggersPending: WriteOkay(Okay, output, "\nStatus: triggers-pending"); break; case pkgCache::State::Installed: WriteOkay(Okay, output, "\nStatus: installed"); break; } - if (Pkg->SelectedState == pkgCache::State::Hold) - WriteOkay(Okay, output, "\nHold: yes"); - // FIXME: Ideally, an EIPP request contains at most two versions (installed and to install) - if (Cache.GetCandidateVersion(Pkg) == Ver) - WriteOkay(Okay, output, "\nAPT-Candidate: yes"); return Okay; } /*}}}*/ // EIPP::WriteScenario - to the given file descriptor /*{{{*/ +template<typename forVersion> void forAllInterestingVersions(pkgDepCache &Cache, pkgCache::PkgIterator const &Pkg, forVersion const &func) +{ + if (Pkg->CurrentState == pkgCache::State::NotInstalled) + { + auto P = Cache[Pkg]; + if (P.Install() == false) + return; + func(Pkg, P.InstVerIter(Cache)); + } + else + { + if (Pkg->CurrentVer != 0) + func(Pkg, Pkg.CurrentVer()); + auto P = Cache[Pkg]; + auto const V = P.InstVerIter(Cache); + if (P.Delete() == false && Pkg.CurrentVer() != V) + func(Pkg, V); + } +} + bool EIPP::WriteScenario(pkgDepCache &Cache, FileFd &output, OpProgress * const Progress) { if (Progress != NULL) - Progress->SubProgress(Cache.Head().VersionCount, _("Send scenario to planer")); + Progress->SubProgress(Cache.Head().PackageCount, _("Send scenario to planer")); unsigned long p = 0; bool Okay = output.Failed() == false; std::vector<std::string> archs = APT::Configuration::getArchitectures(); - std::vector<bool> pkgset(Cache.Head().VersionCount, true); - for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false && likely(Okay); ++Pkg) - { - std::string const arch = Pkg.Arch(); - if (std::find(archs.begin(), archs.end(), arch) == archs.end()) - continue; - for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false && likely(Okay); ++Ver, ++p) + std::vector<bool> pkgset(Cache.Head().PackageCount, false); + auto const MarkVersion = [&](pkgCache::PkgIterator const &Pkg, pkgCache::VerIterator const &Ver) { + pkgset[Pkg->ID] = true; + for (auto D = Ver.DependsList(); D.end() == false; ++D) { - Okay &= WriteScenarioVersion(output, Pkg, Ver); - Okay &= WriteScenarioEIPPVersion(Cache, output, Pkg, Ver); - Okay &= WriteScenarioLimitedDependency(output, Ver, pkgset, true); - WriteOkay(Okay, output, "\n"); - if (Progress != NULL && p % 100 == 0) - Progress->Progress(p); + if (D.IsCritical() == false) + continue; + auto const P = D.TargetPkg(); + for (auto Prv = P.ProvidesList(); Prv.end() == false; ++Prv) + { + auto const V = Prv.OwnerVer(); + auto const PV = V.ParentPkg(); + if (V == PV.CurrentVer() || V == Cache[PV].InstVerIter(Cache)) + pkgset[PV->ID] = true; + } + pkgset[P->ID] = true; } + }; + for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg) + forAllInterestingVersions(Cache, Pkg, MarkVersion); + auto const WriteVersion = [&](pkgCache::PkgIterator const &Pkg, pkgCache::VerIterator const &Ver) { + Okay &= WriteScenarioVersion(output, Pkg, Ver); + Okay &= WriteScenarioEIPPVersion(Cache, output, Pkg, Ver); + Okay &= WriteScenarioLimitedDependency(output, Ver, pkgset, true); + WriteOkay(Okay, output, "\n"); + if (Progress != NULL && p % 100 == 0) + Progress->Progress(p); + }; + for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false && likely(Okay); ++Pkg, ++p) + { + if (pkgset[Pkg->ID] == false || Pkg->VersionList == 0) + continue; + forAllInterestingVersions(Cache, Pkg, WriteVersion); } return true; } diff --git a/test/integration/test-external-installation-planer-protocol b/test/integration/test-external-installation-planer-protocol new file mode 100755 index 000000000..db43675e1 --- /dev/null +++ b/test/integration/test-external-installation-planer-protocol @@ -0,0 +1,28 @@ +#!/bin/sh +set -e + +TESTDIR="$(readlink -f "$(dirname "$0")")" +. "$TESTDIR/framework" +setupenvironment +configarchitecture 'amd64' + +buildsimplenativepackage 'libfoo' 'amd64' '3' 'experimental' 'Multi-Arch: same' +buildsimplenativepackage 'foo' 'all' '3' 'experimental' 'Depends: newstuff' +buildsimplenativepackage 'foo' 'all' '2' 'unstable' 'Depends: libfoo:amd64, stuff +Conflicts: bar, libfoo:i386 +Recommends: unrelated' +buildsimplenativepackage 'libfoo' 'amd64' '2' 'unstable' 'Multi-Arch: same' +buildsimplenativepackage 'unrelated-2' 'amd64' '2' 'unstable' +insertinstalledpackage 'foo' 'all' '1' +insertinstalledpackage 'bar' 'all' '1' +insertinstalledpackage 'stuff' 'all' '1' +insertinstalledpackage 'unrelated-1' 'all' '1' + +setupaptarchive --no-update + +testsuccess apt update +export APT_EDSP_DUMP_FILENAME="${TMPWORKINGDIRECTORY}/eipp.dump" +testfailure aptget install foo --planer dump -y +testfailure grep 'unrelated-2' "$APT_EDSP_DUMP_FILENAME" +testsuccessequal '2' grep -c '^Package: foo$' "$APT_EDSP_DUMP_FILENAME" +testsuccessequal '1' grep -c '^Package: libfoo$' "$APT_EDSP_DUMP_FILENAME" |