summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apt-pkg/edsp.cc73
-rwxr-xr-xtest/integration/test-external-installation-planer-protocol28
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"