From 25252738d5ad6042b356f2d6bec2ca52ef08a1e2 Mon Sep 17 00:00:00 2001 From: Stefano Zacchiroli Date: Wed, 4 Sep 2013 17:06:11 +0200 Subject: EDSP: bump protocol version to 0.5 --- apt-pkg/edsp.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apt-pkg/edsp.cc') diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index ee42267bc..a44d4a4a9 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -231,7 +231,7 @@ bool EDSP::WriteRequest(pkgDepCache &Cache, FILE* output, bool const Upgrade, continue; req->append(" ").append(Pkg.FullName()); } - fprintf(output, "Request: EDSP 0.4\n"); + fprintf(output, "Request: EDSP 0.5\n"); if (del.empty() == false) fprintf(output, "Remove: %s\n", del.c_str()+1); if (inst.empty() == false) -- cgit v1.2.3-70-g09d2 From caa3279367401965cbdd5e3a41c47945f3e263bd Mon Sep 17 00:00:00 2001 From: Stefano Zacchiroli Date: Wed, 4 Sep 2013 17:13:49 +0200 Subject: EDSP: add Architecture(s) multi-arch fields to the Request stanza --- apt-pkg/edsp.cc | 9 +++++++++ doc/external-dependency-solver-protocol.txt | 13 ++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) (limited to 'apt-pkg/edsp.cc') diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index a44d4a4a9..33478dfa6 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -232,6 +232,15 @@ bool EDSP::WriteRequest(pkgDepCache &Cache, FILE* output, bool const Upgrade, req->append(" ").append(Pkg.FullName()); } fprintf(output, "Request: EDSP 0.5\n"); + + const char *arch = _config->Find("APT::Architecture").c_str(); + std::vector archs = APT::Configuration::getArchitectures(); + fprintf(output, "Architecture: %s\n", arch); + fprintf(output, "Architectures:"); + for (std::vector::const_iterator a = archs.begin(); a != archs.end(); ++a) + fprintf(output, " %s", a->c_str()); + fprintf(output, "\n"); + if (del.empty() == false) fprintf(output, "Remove: %s\n", del.c_str()+1); if (inst.empty() == false) diff --git a/doc/external-dependency-solver-protocol.txt b/doc/external-dependency-solver-protocol.txt index 7d41571de..477bc23ed 100644 --- a/doc/external-dependency-solver-protocol.txt +++ b/doc/external-dependency-solver-protocol.txt @@ -110,7 +110,8 @@ Within a dependency solving scenario, a request represents the action on installed packages requested by the user. A request is a single Deb 822 stanza opened by a mandatory Request field -and followed by a mixture of action and preference fields. +and followed by a mixture of action, preference, and global +configuration fields. The value of the **Request:** field is a string describing the EDSP protocol which will be used to communicate. At present, the string must @@ -118,6 +119,16 @@ be `EDSP 0.5`. Request fields are mainly used to identify the beginning of a request stanza; their actual values are otherwise not used by the EDSP protocol. +The following **configuration fields** are supported in request stanzas: + +- **Architecture:** (mandatory) The name of the *native* architecture on + the user machine (see also: `dpkg --print-architecture`) + +- **Architectures:** (optional, defaults to the native architecture) A + space separated list of *all* architectures known to APT (this is + roughly equivalent to the union of `dpkg --print-architecture` and + `dpkg --print-foreign-architectures`) + The following **action fields** are supported in request stanzas: - **Install:** (optional, defaults to the empty string) A space -- cgit v1.2.3-70-g09d2 From f63c067e686b59ce9fa7c52bb39b7440e0770671 Mon Sep 17 00:00:00 2001 From: Stefano Zacchiroli Date: Thu, 5 Sep 2013 16:36:44 +0200 Subject: EDSP: add Source field to Package stanzas --- apt-pkg/edsp.cc | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'apt-pkg/edsp.cc') diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index 33478dfa6..178791dae 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -87,7 +88,12 @@ bool EDSP::WriteLimitedScenario(pkgDepCache &Cache, FILE* output, void EDSP::WriteScenarioVersion(pkgDepCache &Cache, FILE* output, pkgCache::PkgIterator const &Pkg, pkgCache::VerIterator const &Ver) { + pkgRecords Recs(Cache); + pkgRecords::Parser &rec = Recs.Lookup(Ver.FileList()); + string srcpkg = rec.SourcePkg().empty() ? Pkg.Name() : rec.SourcePkg(); + fprintf(output, "Package: %s\n", Pkg.Name()); + fprintf(output, "Source: %s\n", srcpkg.c_str()); fprintf(output, "Architecture: %s\n", Ver.Arch()); fprintf(output, "Version: %s\n", Ver.VerStr()); if (Pkg.CurrentVer() == Ver) -- cgit v1.2.3-70-g09d2 From b5ea5d4a5b8f82afb7bbe4c3eee07ae36f2fba9c Mon Sep 17 00:00:00 2001 From: Stefano Zacchiroli Date: Thu, 5 Sep 2013 10:54:12 +0200 Subject: EDSP: add APT-Release field to Package stanzas --- apt-pkg/edsp.cc | 16 ++++++++++++++-- doc/external-dependency-solver-protocol.txt | 9 +++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) (limited to 'apt-pkg/edsp.cc') diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index 178791dae..88ad27681 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -113,10 +113,22 @@ void EDSP::WriteScenarioVersion(pkgDepCache &Cache, FILE* output, pkgCache::PkgI else if ((Ver->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same) fprintf(output, "Multi-Arch: same\n"); signed short Pin = std::numeric_limits::min(); - for (pkgCache::VerFileIterator File = Ver.FileList(); File.end() == false; ++File) { - signed short const p = Cache.GetPolicy().GetPriority(File.File()); + std::set Releases; + for (pkgCache::VerFileIterator I = Ver.FileList(); I.end() == false; ++I) { + pkgCache::PkgFileIterator File = I.File(); + signed short const p = Cache.GetPolicy().GetPriority(File); if (Pin < p) Pin = p; + if ((File->Flags & pkgCache::Flag::NotSource) != pkgCache::Flag::NotSource) { + string Release = File.RelStr(); + if (!Release.empty()) + Releases.insert(Release); + } + } + if (!Releases.empty()) { + fprintf(output, "APT-Release:\n"); + for (std::set::iterator R = Releases.begin(); R != Releases.end(); ++R) + fprintf(output, " %s\n", R->c_str()); } fprintf(output, "APT-Pin: %d\n", Pin); if (Cache.GetCandidateVer(Pkg) == Ver) diff --git a/doc/external-dependency-solver-protocol.txt b/doc/external-dependency-solver-protocol.txt index 477bc23ed..790f2f1ee 100644 --- a/doc/external-dependency-solver-protocol.txt +++ b/doc/external-dependency-solver-protocol.txt @@ -209,6 +209,15 @@ field. The following fields are supported in package stanzas: should be removed by the solver only when the Autoremove action is requested (see Request section). +- **APT-Release:** (optional) The releases the package belongs to, according to + APT. The format of this field is multiline with one value per line and the + first line (the one containing the field name) empty. Each subsequent line + corresponds to one of the releases the package belongs to and looks like + this: `o=Debian,a=unstable,n=sid,l=Debian,c=main`. That is, each release line + is a comma-separated list of "key=value" pairs, each of which denotes a + Release file entry (Origin, Label, Codename, etc.) in the format of + APT_PREFERENCES(5). + ### Answer An answer from the external solver to APT is either a *solution* or an -- cgit v1.2.3-70-g09d2 From 5681b3fc2a8e35a12cd7c8e94013611211188459 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 30 May 2014 15:58:30 +0200 Subject: check exit status of external solvers Solvers are supposed to exit successfully even if they haven't found a solution, but a solver which fails drastically (like e.g. segfaults) should be detected and dealt with accordingly instead of ignored. --- apt-pkg/edsp.cc | 29 ++++++++++++++++++++++------- apt-pkg/edsp.h | 6 +++--- 2 files changed, 25 insertions(+), 10 deletions(-) (limited to 'apt-pkg/edsp.cc') diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index 88ad27681..52556c1ed 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -535,7 +535,7 @@ bool EDSP::WriteError(char const * const uuid, std::string const &message, FILE* } /*}}}*/ // EDSP::ExecuteSolver - fork requested solver and setup ipc pipes {{{*/ -bool EDSP::ExecuteSolver(const char* const solver, int *solver_in, int *solver_out) { +pid_t EDSP::ExecuteSolver(const char* const solver, int * const solver_in, int * const solver_out, bool) { std::vector const solverDirs = _config->FindVector("Dir::Bin::Solvers"); std::string file; for (std::vector::const_iterator dir = solverDirs.begin(); @@ -547,10 +547,16 @@ bool EDSP::ExecuteSolver(const char* const solver, int *solver_in, int *solver_o } if (file.empty() == true) - return _error->Error("Can't call external solver '%s' as it is not in a configured directory!", solver); + { + _error->Error("Can't call external solver '%s' as it is not in a configured directory!", solver); + return 0; + } int external[4] = {-1, -1, -1, -1}; if (pipe(external) != 0 || pipe(external + 2) != 0) - return _error->Errno("Resolve", "Can't create needed IPC pipes for EDSP"); + { + _error->Errno("Resolve", "Can't create needed IPC pipes for EDSP"); + return 0; + } for (int i = 0; i < 4; ++i) SetCloseExec(external[i], true); @@ -567,11 +573,19 @@ bool EDSP::ExecuteSolver(const char* const solver, int *solver_in, int *solver_o close(external[3]); if (WaitFd(external[1], true, 5) == false) - return _error->Errno("Resolve", "Timed out while Waiting on availability of solver stdin"); + { + _error->Errno("Resolve", "Timed out while Waiting on availability of solver stdin"); + return 0; + } *solver_in = external[1]; *solver_out = external[2]; - return true; + return Solver; +} +bool EDSP::ExecuteSolver(const char* const solver, int *solver_in, int *solver_out) { + if (ExecuteSolver(solver, solver_in, solver_out, true) == 0) + return false; + return true; } /*}}}*/ // EDSP::ResolveExternal - resolve problems by asking external for help {{{*/ @@ -579,7 +593,8 @@ bool EDSP::ResolveExternal(const char* const solver, pkgDepCache &Cache, bool const upgrade, bool const distUpgrade, bool const autoRemove, OpProgress *Progress) { int solver_in, solver_out; - if (EDSP::ExecuteSolver(solver, &solver_in, &solver_out) == false) + pid_t const solver_pid = EDSP::ExecuteSolver(solver, &solver_in, &solver_out, true); + if (solver_pid == 0) return false; FILE* output = fdopen(solver_in, "w"); @@ -599,6 +614,6 @@ bool EDSP::ResolveExternal(const char* const solver, pkgDepCache &Cache, if (EDSP::ReadResponse(solver_out, Cache, Progress) == false) return false; - return true; + return ExecWait(solver_pid, solver); } /*}}}*/ diff --git a/apt-pkg/edsp.h b/apt-pkg/edsp.h index f3092d3c6..9e833556a 100644 --- a/apt-pkg/edsp.h +++ b/apt-pkg/edsp.h @@ -205,10 +205,10 @@ public: * \param[out] solver_in will be the stdin of the solver * \param[out] solver_out will be the stdout of the solver * - * \return true if the solver could be started and the pipes - * are set up correctly, otherwise false and the pipes are invalid + * \return PID of the started solver or 0 if failure occurred */ - bool static ExecuteSolver(const char* const solver, int *solver_in, int *solver_out); + pid_t static ExecuteSolver(const char* const solver, int * const solver_in, int * const solver_out, bool /*overload*/); + APT_DEPRECATED bool static ExecuteSolver(const char* const solver, int *solver_in, int *solver_out); /** \brief call an external resolver to handle the request * -- cgit v1.2.3-70-g09d2 From 1f6cf9e79742ea8e328ef2225b2f5217a9440216 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 30 May 2014 18:01:47 +0200 Subject: support parsing EDSP requests Architecture{,s} stanza Adds also a small testcase for EDSP Git-Dch: Ignore --- apt-pkg/edsp.cc | 7 +++ test/integration/framework | 6 ++ .../test-external-dependency-solver-protocol | 65 ++++++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100755 test/integration/test-external-dependency-solver-protocol (limited to 'apt-pkg/edsp.cc') diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index 52556c1ed..6d1b68c23 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -438,6 +438,13 @@ bool EDSP::ReadRequest(int const input, std::list &install, distUpgrade = EDSP::StringToBool(line.c_str() + 14, false); else if (line.compare(0, 11, "Autoremove:") == 0) autoRemove = EDSP::StringToBool(line.c_str() + 12, false); + else if (line.compare(0, 13, "Architecture:") == 0) + _config->Set("APT::Architecture", line.c_str() + 14); + else if (line.compare(0, 14, "Architectures:") == 0) + { + std::string const archs = line.c_str() + 15; + _config->Set("APT::Architectures", SubstVar(archs, " ", ",")); + } else _error->Warning("Unknown line in EDSP Request stanza: %s", line.c_str()); diff --git a/test/integration/framework b/test/integration/framework index 4f0a69994..7959699fd 100644 --- a/test/integration/framework +++ b/test/integration/framework @@ -194,6 +194,12 @@ setupenvironment() { touch var/lib/dpkg/available mkdir -p usr/lib/apt ln -s ${METHODSDIR} usr/lib/apt/methods + if [ "$BUILDDIRECTORY" = "$LIBRARYPATH" ]; then + mkdir -p usr/lib/apt/solvers + ln -s "${BUILDDIRECTORY}/apt-dump-solver" usr/lib/apt/solvers/dump + ln -s "${BUILDDIRECTORY}/apt-internal-solver" usr/lib/apt/solvers/apt + echo "Dir::Bin::Solvers \"${TMPWORKINGDIRECTORY}/rootdir/usr/lib/apt/solvers\";" > etc/apt/apt.conf.d/externalsolver.conf + fi # use the autoremove from the BUILDDIRECTORY if its there, otherwise # system if [ -e ${BUILDDIRECTORY}/../../debian/apt.conf.autoremove ]; then diff --git a/test/integration/test-external-dependency-solver-protocol b/test/integration/test-external-dependency-solver-protocol new file mode 100755 index 000000000..129565993 --- /dev/null +++ b/test/integration/test-external-dependency-solver-protocol @@ -0,0 +1,65 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework +setupenvironment +configarchitecture 'amd64' 'i386' + +insertinstalledpackage 'cool' 'all' '1' +insertinstalledpackage 'stuff' 'all' '1' + +insertpackage 'unstable' 'cool' 'all' '2' 'Multi-Arch: foreign' +insertpackage 'unstable' 'stuff' 'all' '2' 'Multi-Arch: foreign' +insertpackage 'unstable' 'coolstuff' 'i386,amd64' '2' 'Depends: cool, stuff' +insertpackage 'unstable' 'awesome' 'all' '2' 'Multi-Arch: foreign' +insertpackage 'unstable' 'awesomecoolstuff' 'i386' '2' 'Depends: coolstuff, awesome' + +insertpackage 'experimental' 'cool' 'all' '3' 'Multi-Arch: foreign' +insertpackage 'experimental' 'stuff' 'all' '3' 'Multi-Arch: foreign' +insertpackage 'experimental' 'coolstuff' 'i386,amd64' '3' 'Depends: cool, stuff' + +setupaptarchive + +rm -f /tmp/dump.edsp +testequal 'Reading package lists... +Building dependency tree... +Execute external solver... +The solver encountered an error of type: ERR_JUST_DUMPING +The following information might help you to understand what is wrong: +I am too dumb, i can just dump! +Please use one of my friends instead! + +E: External solver failed with: I am too dumb, i can just dump!' aptget install --solver dump coolstuff -s +testsuccess test -s /tmp/dump.edsp +rm -f /tmp/dump.edsp + +#FIXME: this should be unstable, but we don't support pinning yet +testequal 'Reading package lists... +Building dependency tree... +Execute external solver... +The following NEW packages will be installed: + coolstuff +0 upgraded, 1 newly installed, 0 to remove and 2 not upgraded. +Inst coolstuff (3 experimental [amd64]) +Conf coolstuff (3 experimental [amd64])' aptget install --solver apt coolstuff -s + +testsuccess aptget install awesomecoolstuff:i386 -s +testsuccess aptget install --solver apt awesomecoolstuff:i386 -s + +rm -f /tmp/dump.edsp +testfailure aptget install --solver dump awesomecoolstuff:i386 -s +testsuccess test -s /tmp/dump.edsp + +configarchitecture 'armel' +msgtest 'Test direct calling is okay for' 'apt-internal-solver' +cat /tmp/dump.edsp | runapt apt-internal-solver > solver.result 2>&1 || true +if [ "$(tail -n2 solver.result | head -n1 )" = "Message: Done" ]; then + msgpass +else + cat solver.result + msgfail +fi +rm -f /tmp/dump.edsp + +testfailure aptget install --solver apt awesomecoolstuff:i386 -s -- cgit v1.2.3-70-g09d2