summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Vogt <mvo@debian.org>2014-06-18 11:21:35 +0200
committerMichael Vogt <mvo@debian.org>2014-06-18 11:24:16 +0200
commit8d20b69d2fd7a8fec82bb559f0e39059bbaecf1b (patch)
tree000fce642c5c12f3cc8b5472bcd03994c78b5050
parent17091f2f33de16c2dae501e7868f7aec4fc3452f (diff)
parent82ced5c894cd013721f432ae8da66114155e04c7 (diff)
Merge remote-tracking branch 'donkult/debian/sid' into debian/experimental
Conflicts: apt-private/private-install.cc
-rw-r--r--apt-pkg/contrib/strutl.cc21
-rw-r--r--apt-pkg/edsp.cc7
-rw-r--r--apt-pkg/upgrade.cc6
-rw-r--r--apt-private/private-install.cc23
-rw-r--r--apt-private/private-install.h4
-rw-r--r--apt-private/private-output.cc204
-rw-r--r--apt-private/private-output.h3
-rw-r--r--apt-private/private-update.cc7
-rw-r--r--apt-private/private-upgrade.cc12
-rw-r--r--cmdline/apt-internal-solver.cc24
-rw-r--r--cmdline/makefile20
-rw-r--r--doc/apt-secure.8.xml2
-rw-r--r--doc/external-dependency-solver-protocol.txt28
-rw-r--r--doc/po/apt-doc.pot2
-rw-r--r--doc/po/de.po8
-rw-r--r--doc/po/es.po4
-rw-r--r--doc/po/fr.po4
-rw-r--r--doc/po/it.po4
-rw-r--r--doc/po/ja.po4
-rw-r--r--doc/po/pl.po4
-rw-r--r--doc/po/pt.po4
-rw-r--r--doc/po/pt_BR.po2
-rwxr-xr-xtest/integration/test-external-dependency-solver-protocol6
-rw-r--r--test/libapt/strutil_test.cc35
24 files changed, 265 insertions, 173 deletions
diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc
index 2100ee47b..ce69c7a02 100644
--- a/apt-pkg/contrib/strutl.cc
+++ b/apt-pkg/contrib/strutl.cc
@@ -434,23 +434,30 @@ string TimeToStr(unsigned long Sec)
/* This replaces all occurrences of Subst with Contents in Str. */
string SubstVar(const string &Str,const string &Subst,const string &Contents)
{
+ if (Subst.empty() == true)
+ return Str;
+
string::size_type Pos = 0;
string::size_type OldPos = 0;
string Temp;
-
- while (OldPos < Str.length() &&
+
+ while (OldPos < Str.length() &&
(Pos = Str.find(Subst,OldPos)) != string::npos)
{
- Temp += string(Str,OldPos,Pos) + Contents;
- OldPos = Pos + Subst.length();
+ if (OldPos != Pos)
+ Temp.append(Str, OldPos, Pos - OldPos);
+ if (Contents.empty() == false)
+ Temp.append(Contents);
+ OldPos = Pos + Subst.length();
}
-
+
if (OldPos == 0)
return Str;
-
+
+ if (OldPos >= Str.length())
+ return Temp;
return Temp + string(Str,OldPos);
}
-
string SubstVar(string Str,const struct SubstVar *Vars)
{
for (; Vars->Subst != 0; Vars++)
diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc
index 6d1b68c23..0d0418e06 100644
--- a/apt-pkg/edsp.cc
+++ b/apt-pkg/edsp.cc
@@ -26,6 +26,7 @@
#include <time.h>
#include <unistd.h>
#include <stdio.h>
+#include <algorithm>
#include <iostream>
#include <vector>
#include <limits>
@@ -50,7 +51,12 @@ bool EDSP::WriteScenario(pkgDepCache &Cache, FILE* output, OpProgress *Progress)
if (Progress != NULL)
Progress->SubProgress(Cache.Head().VersionCount, _("Send scenario to solver"));
unsigned long p = 0;
+ std::vector<std::string> archs = APT::Configuration::getArchitectures();
for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++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; ++Ver, ++p)
{
WriteScenarioVersion(Cache, output, Pkg, Ver);
@@ -59,6 +65,7 @@ bool EDSP::WriteScenario(pkgDepCache &Cache, FILE* output, OpProgress *Progress)
if (Progress != NULL && p % 100 == 0)
Progress->Progress(p);
}
+ }
return true;
}
/*}}}*/
diff --git a/apt-pkg/upgrade.cc b/apt-pkg/upgrade.cc
index 7926845c2..29b11937b 100644
--- a/apt-pkg/upgrade.cc
+++ b/apt-pkg/upgrade.cc
@@ -143,6 +143,12 @@ static bool pkgAllUpgradeNoNewPackages(pkgDepCache &Cache)
*/
static bool pkgAllUpgradeWithNewPackages(pkgDepCache &Cache)
{
+ std::string const solver = _config->Find("APT::Solver", "internal");
+ if (solver != "internal") {
+ OpTextProgress Prog(*_config);
+ return EDSP::ResolveExternal(solver.c_str(), Cache, true, false, false, &Prog);
+ }
+
pkgDepCache::ActionGroup group(Cache);
pkgProblemResolver Fix(&Cache);
diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc
index 3b94237b4..55893bda0 100644
--- a/apt-private/private-install.cc
+++ b/apt-private/private-install.cc
@@ -19,7 +19,7 @@
#include <apt-pkg/macros.h>
#include <apt-pkg/packagemanager.h>
#include <apt-pkg/pkgcache.h>
-#include <apt-pkg/sourcelist.h>
+#include <apt-pkg/upgrade.h>
#include <apt-pkg/install-progress.h>
#include <errno.h>
@@ -527,15 +527,14 @@ static bool DoAutomaticRemove(CacheFile &Cache)
static const unsigned short MOD_REMOVE = 1;
static const unsigned short MOD_INSTALL = 2;
-bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache)
+bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache, int UpgradeMode)
{
std::map<unsigned short, APT::VersionSet> verset;
- return DoCacheManipulationFromCommandLine(CmdL, Cache, verset);
+ return DoCacheManipulationFromCommandLine(CmdL, Cache, verset, UpgradeMode);
}
bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache,
- std::map<unsigned short, APT::VersionSet> &verset)
+ std::map<unsigned short, APT::VersionSet> &verset, int UpgradeMode)
{
-
// Enter the special broken fixing mode if the user specified arguments
bool BrokenFix = false;
if (Cache->BrokenCount() != 0)
@@ -620,7 +619,17 @@ bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache,
if (Fix != NULL)
{
// Call the scored problem resolver
- if (Fix->Resolve(true) == false && Cache->BrokenCount() == 0)
+ bool resolver_fail = false;
+ if (UpgradeMode == 0)
+ {
+ if (strcmp(CmdL.FileList[0], "dist-upgrade") == 0 || strcmp(CmdL.FileList[0], "full-upgrade") == 0)
+ resolver_fail = APT::Upgrade::Upgrade(Cache, 0);
+ else
+ resolver_fail = Fix->Resolve(true);
+ } else
+ resolver_fail = APT::Upgrade::Upgrade(Cache, UpgradeMode);
+
+ if (resolver_fail == false && Cache->BrokenCount() == 0)
return false;
}
@@ -703,7 +712,7 @@ bool DoInstall(CommandLine &CmdL)
std::map<unsigned short, APT::VersionSet> verset;
- if(!DoCacheManipulationFromCommandLine(CmdL, Cache, verset))
+ if(!DoCacheManipulationFromCommandLine(CmdL, Cache, verset, 0))
return false;
/* Print out a list of packages that are going to be installed extra
diff --git a/apt-private/private-install.h b/apt-private/private-install.h
index 828163e40..8daa4a776 100644
--- a/apt-private/private-install.h
+++ b/apt-private/private-install.h
@@ -21,8 +21,8 @@ class pkgProblemResolver;
APT_PUBLIC bool DoInstall(CommandLine &Cmd);
bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache,
- std::map<unsigned short, APT::VersionSet> &verset);
-bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache);
+ std::map<unsigned short, APT::VersionSet> &verset, int UpgradeMode);
+bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache, int UpgradeMode);
APT_PUBLIC bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
bool Safety = true);
diff --git a/apt-private/private-output.cc b/apt-private/private-output.cc
index 8f190a551..158bd5c71 100644
--- a/apt-private/private-output.cc
+++ b/apt-private/private-output.cc
@@ -344,129 +344,141 @@ bool ShowList(ostream &out,string Title,string List,string VersionsList)
Depends: libldap2 (>= 2.0.2-2) but it is not going to be installed
Depends: libsasl7 but it is not going to be installed
*/
-void ShowBroken(ostream &out,CacheFile &Cache,bool Now)
+static void ShowBrokenPackage(ostream &out, pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg, bool const Now)
{
- if (Cache->BrokenCount() == 0)
+ if (Now == true)
+ {
+ if ((*Cache)[Pkg].NowBroken() == false)
+ return;
+ }
+ else
+ {
+ if ((*Cache)[Pkg].InstBroken() == false)
+ return;
+ }
+
+ // Print out each package and the failed dependencies
+ out << " " << Pkg.FullName(true) << " :";
+ unsigned const Indent = Pkg.FullName(true).size() + 3;
+ bool First = true;
+ pkgCache::VerIterator Ver;
+
+ if (Now == true)
+ Ver = Pkg.CurrentVer();
+ else
+ Ver = (*Cache)[Pkg].InstVerIter(*Cache);
+
+ if (Ver.end() == true)
+ {
+ out << endl;
return;
+ }
- out << _("The following packages have unmet dependencies:") << endl;
- for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
+ for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false;)
{
- pkgCache::PkgIterator I(Cache,Cache.List[J]);
-
+ // Compute a single dependency element (glob or)
+ pkgCache::DepIterator Start;
+ pkgCache::DepIterator End;
+ D.GlobOr(Start,End); // advances D
+
+ if ((*Cache)->IsImportantDep(End) == false)
+ continue;
+
if (Now == true)
{
- if (Cache[I].NowBroken() == false)
+ if (((*Cache)[End] & pkgDepCache::DepGNow) == pkgDepCache::DepGNow)
continue;
}
else
{
- if (Cache[I].InstBroken() == false)
+ if (((*Cache)[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
continue;
}
-
- // Print out each package and the failed dependencies
- out << " " << I.FullName(true) << " :";
- unsigned const Indent = I.FullName(true).size() + 3;
- bool First = true;
- pkgCache::VerIterator Ver;
-
- if (Now == true)
- Ver = I.CurrentVer();
- else
- Ver = Cache[I].InstVerIter(Cache);
-
- if (Ver.end() == true)
- {
- out << endl;
- continue;
- }
-
- for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false;)
+
+ bool FirstOr = true;
+ while (1)
{
- // Compute a single dependency element (glob or)
- pkgCache::DepIterator Start;
- pkgCache::DepIterator End;
- D.GlobOr(Start,End); // advances D
+ if (First == false)
+ for (unsigned J = 0; J != Indent; J++)
+ out << ' ';
+ First = false;
- if (Cache->IsImportantDep(End) == false)
- continue;
-
- if (Now == true)
+ if (FirstOr == false)
{
- if ((Cache[End] & pkgDepCache::DepGNow) == pkgDepCache::DepGNow)
- continue;
+ for (unsigned J = 0; J != strlen(End.DepType()) + 3; J++)
+ out << ' ';
}
else
+ out << ' ' << End.DepType() << ": ";
+ FirstOr = false;
+
+ out << Start.TargetPkg().FullName(true);
+
+ // Show a quick summary of the version requirements
+ if (Start.TargetVer() != 0)
+ out << " (" << Start.CompType() << " " << Start.TargetVer() << ")";
+
+ /* Show a summary of the target package if possible. In the case
+ of virtual packages we show nothing */
+ pkgCache::PkgIterator Targ = Start.TargetPkg();
+ if (Targ->ProvidesList == 0)
{
- if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
- continue;
- }
-
- bool FirstOr = true;
- while (1)
- {
- if (First == false)
- for (unsigned J = 0; J != Indent; J++)
- out << ' ';
- First = false;
+ out << ' ';
+ pkgCache::VerIterator Ver = (*Cache)[Targ].InstVerIter(*Cache);
+ if (Now == true)
+ Ver = Targ.CurrentVer();
- if (FirstOr == false)
+ if (Ver.end() == false)
{
- for (unsigned J = 0; J != strlen(End.DepType()) + 3; J++)
- out << ' ';
+ if (Now == true)
+ ioprintf(out,_("but %s is installed"),Ver.VerStr());
+ else
+ ioprintf(out,_("but %s is to be installed"),Ver.VerStr());
}
else
- out << ' ' << End.DepType() << ": ";
- FirstOr = false;
-
- out << Start.TargetPkg().FullName(true);
-
- // Show a quick summary of the version requirements
- if (Start.TargetVer() != 0)
- out << " (" << Start.CompType() << " " << Start.TargetVer() << ")";
-
- /* Show a summary of the target package if possible. In the case
- of virtual packages we show nothing */
- pkgCache::PkgIterator Targ = Start.TargetPkg();
- if (Targ->ProvidesList == 0)
{
- out << ' ';
- pkgCache::VerIterator Ver = Cache[Targ].InstVerIter(Cache);
- if (Now == true)
- Ver = Targ.CurrentVer();
-
- if (Ver.end() == false)
+ if ((*Cache)[Targ].CandidateVerIter(*Cache).end() == true)
{
- if (Now == true)
- ioprintf(out,_("but %s is installed"),Ver.VerStr());
+ if (Targ->ProvidesList == 0)
+ out << _("but it is not installable");
else
- ioprintf(out,_("but %s is to be installed"),Ver.VerStr());
- }
+ out << _("but it is a virtual package");
+ }
else
- {
- if (Cache[Targ].CandidateVerIter(Cache).end() == true)
- {
- if (Targ->ProvidesList == 0)
- out << _("but it is not installable");
- else
- out << _("but it is a virtual package");
- }
- else
- out << (Now?_("but it is not installed"):_("but it is not going to be installed"));
- }
+ out << (Now?_("but it is not installed"):_("but it is not going to be installed"));
}
-
- if (Start != End)
- out << _(" or");
- out << endl;
-
- if (Start == End)
- break;
- ++Start;
- }
- }
- }
+ }
+
+ if (Start != End)
+ out << _(" or");
+ out << endl;
+
+ if (Start == End)
+ break;
+ ++Start;
+ }
+ }
+}
+void ShowBroken(ostream &out, CacheFile &Cache, bool const Now)
+{
+ if (Cache->BrokenCount() == 0)
+ return;
+
+ out << _("The following packages have unmet dependencies:") << endl;
+ for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
+ {
+ pkgCache::PkgIterator const I(Cache,Cache.List[J]);
+ ShowBrokenPackage(out, &Cache, I, Now);
+ }
+}
+void ShowBroken(ostream &out, pkgCacheFile &Cache, bool const Now)
+{
+ if (Cache->BrokenCount() == 0)
+ return;
+
+ out << _("The following packages have unmet dependencies:") << endl;
+ for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg)
+ ShowBrokenPackage(out, &Cache, Pkg, Now);
}
/*}}}*/
// ShowNew - Show packages to newly install /*{{{*/
diff --git a/apt-private/private-output.h b/apt-private/private-output.h
index 9633d0c37..6f3a964d7 100644
--- a/apt-private/private-output.h
+++ b/apt-private/private-output.h
@@ -28,7 +28,8 @@ void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records,
// helper to describe global state
-APT_PUBLIC void ShowBroken(std::ostream &out,CacheFile &Cache,bool Now);
+APT_PUBLIC void ShowBroken(std::ostream &out, CacheFile &Cache, bool const Now);
+APT_PUBLIC void ShowBroken(std::ostream &out, pkgCacheFile &Cache, bool const Now);
APT_PUBLIC bool ShowList(std::ostream &out, std::string Title, std::string List,
std::string VersionsList);
diff --git a/apt-private/private-update.cc b/apt-private/private-update.cc
index fa827dea4..0f2f7a8da 100644
--- a/apt-private/private-update.cc
+++ b/apt-private/private-update.cc
@@ -86,11 +86,14 @@ bool DoUpdate(CommandLine &CmdL)
if (I->CurrentVer != 0 && state.Upgradable())
upgradable++;
}
- const char *msg = ngettext(
+ const char *msg = P_(
"%i package can be upgraded. Run 'apt list --upgradable' to see it.\n",
"%i packages can be upgraded. Run 'apt list --upgradable' to see them.\n",
upgradable);
- ioprintf(c1out, msg, upgradable);
+ if (upgradable == 0)
+ c1out << _("All packages are up to date.") << std::endl;
+ else
+ ioprintf(c1out, msg, upgradable);
}
return true;
diff --git a/apt-private/private-upgrade.cc b/apt-private/private-upgrade.cc
index 68b2c5e00..31f067576 100644
--- a/apt-private/private-upgrade.cc
+++ b/apt-private/private-upgrade.cc
@@ -23,18 +23,10 @@ static bool UpgradeHelper(CommandLine &CmdL, int UpgradeFlags)
return false;
c0out << _("Calculating upgrade... ") << std::flush;
- if (APT::Upgrade::Upgrade(Cache, UpgradeFlags) == false)
- {
- c0out << _("Failed") << std::endl;
- ShowBroken(c1out,Cache,false);
- return _error->Error(_("Internal error, Upgrade broke stuff"));
- }
+ if(!DoCacheManipulationFromCommandLine(CmdL, Cache, UpgradeFlags))
+ return false;
c0out << _("Done") << std::endl;
- // parse additional cmdline pkg manipulation switches
- if(!DoCacheManipulationFromCommandLine(CmdL, Cache))
- return false;
-
return InstallPackages(Cache,true);
}
diff --git a/cmdline/apt-internal-solver.cc b/cmdline/apt-internal-solver.cc
index 0cac12da2..c24a96cdf 100644
--- a/cmdline/apt-internal-solver.cc
+++ b/cmdline/apt-internal-solver.cc
@@ -24,9 +24,11 @@
#include <apt-pkg/depcache.h>
#include <apt-pkg/pkgcache.h>
#include <apt-pkg/cacheiterators.h>
+#include <apt-private/private-output.h>
#include <string.h>
#include <iostream>
+#include <sstream>
#include <list>
#include <string>
#include <unistd.h>
@@ -171,18 +173,20 @@ int main(int argc,const char *argv[]) /*{{{*/
EDSP::WriteProgress(60, "Call problemresolver on current scenario…", output);
+ std::string failure;
if (upgrade == true) {
- if (pkgAllUpgrade(CacheFile) == false) {
- EDSP::WriteError("ERR_UNSOLVABLE_UPGRADE", "An upgrade error occurred", output);
- return 0;
- }
+ if (pkgAllUpgrade(CacheFile) == false)
+ failure = "ERR_UNSOLVABLE_UPGRADE";
} else if (distUpgrade == true) {
- if (pkgDistUpgrade(CacheFile) == false) {
- EDSP::WriteError("ERR_UNSOLVABLE_DIST_UPGRADE", "An dist-upgrade error occurred", output);
- return 0;
- }
- } else if (Fix.Resolve() == false) {
- EDSP::WriteError("ERR_UNSOLVABLE", "An error occurred", output);
+ if (pkgDistUpgrade(CacheFile) == false)
+ failure = "ERR_UNSOLVABLE_DIST_UPGRADE";
+ } else if (Fix.Resolve() == false)
+ failure = "ERR_UNSOLVABLE";
+
+ if (failure.empty() == false) {
+ std::ostringstream broken;
+ ShowBroken(broken, CacheFile, false);
+ EDSP::WriteError(failure.c_str(), broken.str(), output);
return 0;
}
diff --git a/cmdline/makefile b/cmdline/makefile
index c4a249cd6..b7c35ddd1 100644
--- a/cmdline/makefile
+++ b/cmdline/makefile
@@ -8,49 +8,49 @@ include ../buildlib/defaults.mak
# The apt program
PROGRAM=apt
SLIBS = -lapt-pkg -lapt-private $(INTLLIBS)
-LIB_MAKES = apt-pkg/makefile
+LIB_MAKES = apt-pkg/makefile apt-private/makefile
SOURCE = apt.cc
include $(PROGRAM_H)
# The apt-cache program
PROGRAM=apt-cache
SLIBS = -lapt-pkg -lapt-private $(INTLLIBS)
-LIB_MAKES = apt-pkg/makefile
+LIB_MAKES = apt-pkg/makefile apt-private/makefile
SOURCE = apt-cache.cc
include $(PROGRAM_H)
# The apt-get program
PROGRAM=apt-get
SLIBS = -lapt-pkg -lapt-private $(INTLLIBS)
-LIB_MAKES = apt-pkg/makefile
+LIB_MAKES = apt-pkg/makefile apt-private/makefile
SOURCE = apt-get.cc
include $(PROGRAM_H)
# The apt-config program
PROGRAM=apt-config
SLIBS = -lapt-pkg -lapt-private $(INTLLIBS)
-LIB_MAKES = apt-pkg/makefile
+LIB_MAKES = apt-pkg/makefile apt-private/makefile
SOURCE = apt-config.cc
include $(PROGRAM_H)
# The apt-cdrom program
PROGRAM=apt-cdrom
SLIBS = -lapt-pkg -lapt-private $(INTLLIBS)
-LIB_MAKES = apt-pkg/makefile
+LIB_MAKES = apt-pkg/makefile apt-private/makefile
SOURCE = apt-cdrom.cc
include $(PROGRAM_H)
# The apt-mark program
PROGRAM=apt-mark
SLIBS = -lapt-pkg -lapt-private $(INTLLIBS)
-LIB_MAKES = apt-pkg/makefile
+LIB_MAKES = apt-pkg/makefile apt-private/makefile
SOURCE = apt-mark.cc
include $(PROGRAM_H)
# The apt-helper
PROGRAM=apt-helper
SLIBS = -lapt-pkg -lapt-private $(INTLLIBS)
-LIB_MAKES = apt-pkg/makefile
+LIB_MAKES = apt-pkg/makefile apt-private/makefile
SOURCE = apt-helper.cc
include $(PROGRAM_H)
@@ -75,14 +75,14 @@ include $(PROGRAM_H)
# The apt-extracttemplates program
PROGRAM=apt-extracttemplates
SLIBS = -lapt-pkg -lapt-inst $(INTLLIBS)
-LIB_MAKES = apt-pkg/makefile
+LIB_MAKES = apt-pkg/makefile apt-inst/makefile
SOURCE = apt-extracttemplates.cc
include $(PROGRAM_H)
# The internal solver acting as an external
PROGRAM=apt-internal-solver
-SLIBS = -lapt-pkg $(INTLLIBS)
-LIB_MAKES = apt-pkg/makefile
+SLIBS = -lapt-pkg -lapt-private $(INTLLIBS)
+LIB_MAKES = apt-pkg/makefile apt-private/makefile
SOURCE = apt-internal-solver.cc
include $(PROGRAM_H)
diff --git a/doc/apt-secure.8.xml b/doc/apt-secure.8.xml
index 981351615..15a73476d 100644
--- a/doc/apt-secure.8.xml
+++ b/doc/apt-secure.8.xml
@@ -193,7 +193,7 @@
<refsect1><title>See Also</title>
<para>
&apt-conf;, &apt-get;, &sources-list;, &apt-key;, &apt-ftparchive;,
-&debsign; &debsig-verify;, &gpg;
+&debsign;, &debsig-verify;, &gpg;
</para>
<para>For more background information you might want to review the
diff --git a/doc/external-dependency-solver-protocol.txt b/doc/external-dependency-solver-protocol.txt
index 790f2f1ee..14e9528c8 100644
--- a/doc/external-dependency-solver-protocol.txt
+++ b/doc/external-dependency-solver-protocol.txt
@@ -5,6 +5,14 @@ external dependency solvers. The protocol is called APT EDSP, for "APT
External Dependency Solver Protocol".
+## Terminology
+
+In the following we use the term **architecture qualified package name**
+(or *arch-qualified package names* for short) to refer to package
+identifiers of the form "package:arch" where "package" is a package name
+and "arch" a dpkg architecture.
+
+
## Components
- **APT**: we know this one.
@@ -62,6 +70,7 @@ configuration documentation for more, and more up to date, information.
- **Dir::Bin::Solvers**: absolute path of the directory where to look for
external solvers. Defaults to `/usr/lib/apt/solvers`.
+
## Protocol
When configured to use an external solver, APT will resort to it to
@@ -132,9 +141,9 @@ The following **configuration fields** are supported in request stanzas:
The following **action fields** are supported in request stanzas:
- **Install:** (optional, defaults to the empty string) A space
- separated list of package names, with *no version attached*, to
- install. This field denotes a list of packages that the user wants to
- install, usually via an APT `install` request.
+ separated list of arch-qualified package names, with *no version
+ attached*, to install. This field denotes a list of packages that the
+ user wants to install, usually via an APT `install` request.
- **Remove:** (optional, defaults to the empty string) Same syntax of
Install. This field denotes a list of packages that the user wants to
@@ -201,7 +210,7 @@ field. The following fields are supported in package stanzas:
- **APT-Candidate:** (optional, defaults to `no`). Allowed values:
`yes`, `no`. When set to `yes`, the corresponding package is the APT
candidate for installation among all available packages with the same
- name.
+ name and architecture.
- **APT-Automatic:** (optional, defaults to `no`). Allowed values:
`yes`, `no`. When set to `yes`, the corresponding package is marked by
@@ -218,6 +227,7 @@ field. The following fields are supported in package stanzas:
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
@@ -226,11 +236,11 @@ An answer from the external solver to APT is either a *solution* or an
The following invariant on **exit codes** must hold true. When the
external solver is *able to find a solution*, it will write the solution
to standard output and then exit with an exit code of 0. When the
-external solver is *unable to find a solution* (and s aware of that), it
-will write an error to standard output and then exit with an exit code
-of 0. An exit code other than 0 will be interpreted as a solver crash
-with no meaningful error about dependency resolution to convey to the
-user.
+external solver is *unable to find a solution* (and is aware of that),
+it will write an error to standard output and then exit with an exit
+code of 0. An exit code other than 0 will be interpreted as a solver
+crash with no meaningful error about dependency resolution to convey to
+the user.
#### Solution
diff --git a/doc/po/apt-doc.pot b/doc/po/apt-doc.pot
index a058e6506..94ad1238d 100644
--- a/doc/po/apt-doc.pot
+++ b/doc/po/apt-doc.pot
@@ -2153,7 +2153,7 @@ msgstr ""
#: apt-secure.8.xml:195
msgid ""
"&apt-conf;, &apt-get;, &sources-list;, &apt-key;, &apt-ftparchive;, "
-"&debsign; &debsig-verify;, &gpg;"
+"&debsign;, &debsig-verify;, &gpg;"
msgstr ""
#. type: Content of: <refentry><refsect1><para>
diff --git a/doc/po/de.po b/doc/po/de.po
index b048d9661..98bfcb6e4 100644
--- a/doc/po/de.po
+++ b/doc/po/de.po
@@ -726,7 +726,7 @@ msgid ""
"installed instead of removed."
msgstr ""
"<literal>remove</literal> ist identisch mit <literal>install</literal>, mit "
-"der Ausnahme, dass Pakte entfernt anstatt installiert werden. Beachten Sie, "
+"der Ausnahme, dass Pakete entfernt anstatt installiert werden. Beachten Sie, "
"dass das Entfernen von Paketen deren Konfigurationsdateien im System "
"belässt. Wenn ein Pluszeichen an den Paketnamen angehängt wird (ohne "
"Leerzeichen dazwischen) wird das erkannte Paket installiert anstatt entfernt."
@@ -1051,7 +1051,7 @@ msgid ""
"you wish to upgrade, and if a newer version is available, it (and its "
"dependencies, as described above) will be downloaded and installed."
msgstr ""
-"Dies ist außerdem die bevorzugt zu benutzende Art, wenn Sie Sie ein Upgrade "
+"Dies ist außerdem die bevorzugt zu benutzende Art, wenn Sie ein Upgrade "
"eines oder mehrerer bereits installierter Pakete durchführen möchten, ohne "
"ein Upgrade aller Pakete, die Sie auf Ihrem System haben, durchzuführen. "
"Anders als das Ziel von »upgrade«, das die neusten Versionen aller aktuell "
@@ -3010,10 +3010,10 @@ msgstr ""
#: apt-secure.8.xml:195
msgid ""
"&apt-conf;, &apt-get;, &sources-list;, &apt-key;, &apt-ftparchive;, "
-"&debsign; &debsig-verify;, &gpg;"
+"&debsign;, &debsig-verify;, &gpg;"
msgstr ""
"&apt-conf;, &apt-get;, &sources-list;, &apt-key;, &apt-ftparchive;, "
-"&debsign; &debsig-verify;, &gpg;"
+"&debsign;, &debsig-verify;, &gpg;"
#. type: Content of: <refentry><refsect1><para>
#: apt-secure.8.xml:199
diff --git a/doc/po/es.po b/doc/po/es.po
index 2cf3a070a..0b594afe9 100644
--- a/doc/po/es.po
+++ b/doc/po/es.po
@@ -3098,10 +3098,10 @@ msgstr ""
#: apt-secure.8.xml:195
msgid ""
"&apt-conf;, &apt-get;, &sources-list;, &apt-key;, &apt-ftparchive;, "
-"&debsign; &debsig-verify;, &gpg;"
+"&debsign;, &debsig-verify;, &gpg;"
msgstr ""
"&apt-conf;, &apt-get;, &sources-list;, &apt-key;, &apt-ftparchive;, "
-"&debsign; &debsig-verify;, &gpg;"
+"&debsign;, &debsig-verify;, &gpg;"
#. type: Content of: <refentry><refsect1><para>
#: apt-secure.8.xml:199
diff --git a/doc/po/fr.po b/doc/po/fr.po
index 530de5046..0c69a1482 100644
--- a/doc/po/fr.po
+++ b/doc/po/fr.po
@@ -3022,10 +3022,10 @@ msgstr ""
#: apt-secure.8.xml:195
msgid ""
"&apt-conf;, &apt-get;, &sources-list;, &apt-key;, &apt-ftparchive;, "
-"&debsign; &debsig-verify;, &gpg;"
+"&debsign;, &debsig-verify;, &gpg;"
msgstr ""
"&apt-conf;, &apt-get;, &sources-list;, &apt-key;, &apt-ftparchive;, "
-"&debsign; &debsig-verify;, &gpg;"
+"&debsign;, &debsig-verify;, &gpg;"
#. type: Content of: <refentry><refsect1><para>
#: apt-secure.8.xml:199
diff --git a/doc/po/it.po b/doc/po/it.po
index c5ef090ff..fc098a6ab 100644
--- a/doc/po/it.po
+++ b/doc/po/it.po
@@ -3033,10 +3033,10 @@ msgstr ""
#: apt-secure.8.xml:195
msgid ""
"&apt-conf;, &apt-get;, &sources-list;, &apt-key;, &apt-ftparchive;, "
-"&debsign; &debsig-verify;, &gpg;"
+"&debsign;, &debsig-verify;, &gpg;"
msgstr ""
"&apt-conf;, &apt-get;, &sources-list;, &apt-key;, &apt-ftparchive;, "
-"&debsign; &debsig-verify;, &gpg;"
+"&debsign;, &debsig-verify;, &gpg;"
#. type: Content of: <refentry><refsect1><para>
#: apt-secure.8.xml:199
diff --git a/doc/po/ja.po b/doc/po/ja.po
index 2475b810d..5f127426a 100644
--- a/doc/po/ja.po
+++ b/doc/po/ja.po
@@ -2963,10 +2963,10 @@ msgstr ""
#: apt-secure.8.xml:195
msgid ""
"&apt-conf;, &apt-get;, &sources-list;, &apt-key;, &apt-ftparchive;, "
-"&debsign; &debsig-verify;, &gpg;"
+"&debsign;, &debsig-verify;, &gpg;"
msgstr ""
"&apt-conf;, &apt-get;, &sources-list;, &apt-key;, &apt-ftparchive;, "
-"&debsign; &debsig-verify;, &gpg;"
+"&debsign;, &debsig-verify;, &gpg;"
#. type: Content of: <refentry><refsect1><para>
#: apt-secure.8.xml:199
diff --git a/doc/po/pl.po b/doc/po/pl.po
index 5f92c521c..66b494ff9 100644
--- a/doc/po/pl.po
+++ b/doc/po/pl.po
@@ -3131,10 +3131,10 @@ msgstr ""
#: apt-secure.8.xml:195
msgid ""
"&apt-conf;, &apt-get;, &sources-list;, &apt-key;, &apt-ftparchive;, "
-"&debsign; &debsig-verify;, &gpg;"
+"&debsign;, &debsig-verify;, &gpg;"
msgstr ""
"&apt-conf;, &apt-get;, &sources-list;, &apt-key;, &apt-ftparchive;, "
-"&debsign; &debsig-verify;, &gpg;"
+"&debsign;, &debsig-verify;, &gpg;"
#. type: Content of: <refentry><refsect1><para>
#: apt-secure.8.xml:199
diff --git a/doc/po/pt.po b/doc/po/pt.po
index 6ebf93bc7..b67dc8b03 100644
--- a/doc/po/pt.po
+++ b/doc/po/pt.po
@@ -3042,10 +3042,10 @@ msgstr ""
#: apt-secure.8.xml:195
msgid ""
"&apt-conf;, &apt-get;, &sources-list;, &apt-key;, &apt-ftparchive;, "
-"&debsign; &debsig-verify;, &gpg;"
+"&debsign;, &debsig-verify;, &gpg;"
msgstr ""
"&apt-conf;, &apt-get;, &sources-list;, &apt-key;, &apt-ftparchive;, "
-"&debsign; &debsig-verify;, &gpg;"
+"&debsign;, &debsig-verify;, &gpg;"
#. type: Content of: <refentry><refsect1><para>
#: apt-secure.8.xml:199
diff --git a/doc/po/pt_BR.po b/doc/po/pt_BR.po
index e9e785f08..b1df8a068 100644
--- a/doc/po/pt_BR.po
+++ b/doc/po/pt_BR.po
@@ -2159,7 +2159,7 @@ msgstr ""
#: apt-secure.8.xml:195
msgid ""
"&apt-conf;, &apt-get;, &sources-list;, &apt-key;, &apt-ftparchive;, "
-"&debsign; &debsig-verify;, &gpg;"
+"&debsign;, &debsig-verify;, &gpg;"
msgstr ""
#. type: Content of: <refentry><refsect1><para>
diff --git a/test/integration/test-external-dependency-solver-protocol b/test/integration/test-external-dependency-solver-protocol
index 09230d383..07d2441b6 100755
--- a/test/integration/test-external-dependency-solver-protocol
+++ b/test/integration/test-external-dependency-solver-protocol
@@ -51,6 +51,12 @@ rm -f /tmp/dump.edsp
testfailure aptget install --solver dump awesomecoolstuff:i386 -s
testsuccess test -s /tmp/dump.edsp
+testsuccess aptget dist-upgrade -s
+testsuccess aptget dist-upgrade -s --solver apt
+
+testsuccess aptget upgrade -s
+testsuccess aptget upgrade -s --solver apt
+
configarchitecture 'armel'
msgtest 'Test direct calling is okay for' 'apt-internal-solver'
cat /tmp/dump.edsp | aptinternalsolver > solver.result 2>&1 || true
diff --git a/test/libapt/strutil_test.cc b/test/libapt/strutil_test.cc
index bc004fd66..e9b778c6b 100644
--- a/test/libapt/strutil_test.cc
+++ b/test/libapt/strutil_test.cc
@@ -70,3 +70,38 @@ TEST(StrUtilTest,EndsWith)
EXPECT_FALSE(Endswith("abcd", "x"));
EXPECT_FALSE(Endswith("abcd", "abcndefg"));
}
+TEST(StrUtilTest,SubstVar)
+{
+ EXPECT_EQ("", SubstVar("", "fails", "passes"));
+ EXPECT_EQ("test ", SubstVar("test fails", "fails", ""));
+ EXPECT_EQ("test passes", SubstVar("test passes", "", "fails"));
+
+ EXPECT_EQ("test passes", SubstVar("test passes", "fails", "passes"));
+ EXPECT_EQ("test passes", SubstVar("test fails", "fails", "passes"));
+
+ EXPECT_EQ("starts with", SubstVar("beginnt with", "beginnt", "starts"));
+ EXPECT_EQ("beginnt with", SubstVar("starts with", "starts", "beginnt"));
+ EXPECT_EQ("is in middle", SubstVar("is in der middle", "in der", "in"));
+ EXPECT_EQ("is in der middle", SubstVar("is in middle", "in", "in der"));
+ EXPECT_EQ("does end", SubstVar("does enden", "enden", "end"));
+ EXPECT_EQ("does enden", SubstVar("does end", "end", "enden"));
+
+ EXPECT_EQ("abc", SubstVar("abc", "d", "a"));
+ EXPECT_EQ("abc", SubstVar("abd", "d", "c"));
+ EXPECT_EQ("abc", SubstVar("adc", "d", "b"));
+ EXPECT_EQ("abc", SubstVar("dbc", "d", "a"));
+
+ EXPECT_EQ("b", SubstVar("b", "aa", "a"));
+ EXPECT_EQ("bb", SubstVar("bb", "aa", "a"));
+ EXPECT_EQ("bbb", SubstVar("bbb", "aa", "a"));
+
+ EXPECT_EQ("aa", SubstVar("aaaa", "aa", "a"));
+ EXPECT_EQ("aaaa", SubstVar("aa", "a", "aa"));
+ EXPECT_EQ("aaaa", SubstVar("aaaa", "a", "a"));
+ EXPECT_EQ("a a a a ", SubstVar("aaaa", "a", "a "));
+
+ EXPECT_EQ(" bb bb bb bb ", SubstVar(" a a a a ", "a", "bb"));
+ EXPECT_EQ(" bb bb bb bb ", SubstVar(" aaa aaa aaa aaa ", "aaa", "bb"));
+ EXPECT_EQ(" bb a bb a bb a bb ", SubstVar(" aaa a aaa a aaa a aaa ", "aaa", "bb"));
+
+}