summaryrefslogtreecommitdiff
path: root/apt-private
diff options
context:
space:
mode:
authorJulian Andres Klode <julian.klode@canonical.com>2019-05-09 22:23:17 +0200
committerJulian Andres Klode <julian.klode@canonical.com>2019-06-11 16:49:03 +0200
commit9244f712396c10b674740cc79fdab61c47173d04 (patch)
treeed9dcc194dba59faae6340e8bea55c5b57b2c867 /apt-private
parent35cb34d721e11a9e7dfa9ccd29d5bd58da8f7efc (diff)
Introduce apt satisfy and apt-get satisfy
Allow to satisfy dependency strings supplied on the command line, optionally prefixed with "Conflicts:" to satisfy them like Conflicts. Build profiles and architecture restriction lists, as used in build dependencies, are supported as well. Compared to build-dep, build-essential is not installed automatically, and installing of recommended packages follows the global default, which defaults to yes. Closes: #275379 See merge request apt-team/apt!63
Diffstat (limited to 'apt-private')
-rw-r--r--apt-private/private-cmndline.cc11
-rw-r--r--apt-private/private-source.cc77
2 files changed, 81 insertions, 7 deletions
diff --git a/apt-private/private-cmndline.cc b/apt-private/private-cmndline.cc
index 3a25c7131..3f43d6eb1 100644
--- a/apt-private/private-cmndline.cc
+++ b/apt-private/private-cmndline.cc
@@ -216,14 +216,17 @@ static bool addArgumentsAPTGet(std::vector<CommandLine::Args> &Args, char const
addArg(0, "tar-only", "APT::Get::Tar-Only", 0);
addArg(0, "dsc-only", "APT::Get::Dsc-Only", 0);
}
- else if (CmdMatches("build-dep"))
+ else if (CmdMatches("build-dep") || CmdMatches("satisfy"))
{
addArg('a', "host-architecture", "APT::Get::Host-Architecture", CommandLine::HasArg);
addArg('P', "build-profiles", "APT::Build-Profiles", CommandLine::HasArg);
addArg(0, "purge", "APT::Get::Purge", 0);
addArg(0, "solver", "APT::Solver", CommandLine::HasArg);
- addArg(0,"arch-only","APT::Get::Arch-Only",0);
- addArg(0,"indep-only","APT::Get::Indep-Only",0);
+ if (CmdMatches("build-dep"))
+ {
+ addArg(0,"arch-only","APT::Get::Arch-Only",0);
+ addArg(0,"indep-only","APT::Get::Indep-Only",0);
+ }
// this has no effect *but* sbuild is using it (see LP: #1255806)
// once sbuild is fixed, this option can be removed
addArg('f', "fix-broken", "APT::Get::Fix-Broken", 0);
@@ -241,7 +244,7 @@ static bool addArgumentsAPTGet(std::vector<CommandLine::Args> &Args, char const
if (CmdMatches("install", "reinstall", "remove", "purge", "upgrade", "dist-upgrade",
"dselect-upgrade", "autoremove", "auto-remove", "autopurge", "clean", "autoclean", "auto-clean", "check",
- "build-dep", "full-upgrade", "source"))
+ "build-dep", "satisfy", "full-upgrade", "source"))
{
addArg('s', "simulate", "APT::Get::Simulate", 0);
addArg('s', "just-print", "APT::Get::Simulate", 0);
diff --git a/apt-private/private-source.cc b/apt-private/private-source.cc
index 48c9d8094..bbb14b1d8 100644
--- a/apt-private/private-source.cc
+++ b/apt-private/private-source.cc
@@ -29,6 +29,7 @@
#include <apt-private/private-source.h>
#include <apt-pkg/debindexfile.h>
+#include <apt-pkg/deblistparser.h>
#include <stddef.h>
#include <stdio.h>
@@ -652,8 +653,10 @@ bool DoBuildDep(CommandLine &CmdL)
CacheFile Cache;
auto VolatileCmdL = GetPseudoPackages(Cache.GetSourceList(), CmdL, AddVolatileSourceFile, pseudoArch);
+ auto AreDoingSatisfy = strcasecmp(CmdL.FileList[0], "satisfy") == 0;
- _config->Set("APT::Install-Recommends", false);
+ if (not AreDoingSatisfy)
+ _config->Set("APT::Install-Recommends", false);
if (CmdL.FileSize() <= 1 && VolatileCmdL.empty())
return _error->Error(_("Must specify at least one package to check builddeps for"));
@@ -661,6 +664,7 @@ bool DoBuildDep(CommandLine &CmdL)
std::ostringstream buildDepsPkgFile;
std::vector<PseudoPkg> pseudoPkgs;
// deal with the build essentials first
+ if (not AreDoingSatisfy)
{
std::vector<pkgSrcRecords::Parser::BuildDepRec> BuildDeps;
for (auto && opt: _config->FindVector("APT::Build-Essential"))
@@ -678,11 +682,78 @@ bool DoBuildDep(CommandLine &CmdL)
pseudoPkgs.emplace_back(pseudo, nativeArch, "");
}
+ if (AreDoingSatisfy)
+ {
+ std::vector<pkgSrcRecords::Parser::BuildDepRec> BuildDeps;
+ for (unsigned i = 1; i < CmdL.FileSize(); i++)
+ {
+ const char *Start = CmdL.FileList[i];
+ const char *Stop = Start + strlen(Start);
+ auto Type = pkgSrcRecords::Parser::BuildDependIndep;
+
+ // Reject '>' and '<' as operators, as they have strange meanings.
+ bool insideVersionRestriction = false;
+ for (auto C = Start; C + 1 != Stop; C++)
+ {
+ if (*C == '(')
+ insideVersionRestriction = true;
+ else if (*C == ')')
+ insideVersionRestriction = false;
+ else if (insideVersionRestriction && (*C == '<' || *C == '>'))
+ {
+ if (C[1] != *C && C[1] != '=')
+ return _error->Error(_("Invalid operator '%c' at offset %d, did you mean '%c%c' or '%c='? - in: %s"), *C, (int)(C - Start), *C, *C, *C, Start);
+ C++;
+ }
+ }
+
+ if (APT::String::Startswith(Start, "Conflicts:"))
+ {
+ Type = pkgSrcRecords::Parser::BuildConflictIndep;
+ Start += strlen("Conflicts:");
+ }
+ while (1)
+ {
+ pkgSrcRecords::Parser::BuildDepRec rec;
+ Start = debListParser::ParseDepends(Start, Stop,
+ rec.Package, rec.Version, rec.Op, true, false, true, pseudoArch);
+
+ if (Start == 0)
+ return _error->Error("Problem parsing dependency: %s", CmdL.FileList[i]);
+ rec.Type = Type;
+
+ // We parsed a package that was ignored (wrong architecture restriction
+ // or something).
+ if (rec.Package.empty())
+ {
+ // If we are in an OR group, we need to set the "Or" flag of the
+ // previous entry to our value.
+ if (BuildDeps.empty() == false && (BuildDeps[BuildDeps.size() - 1].Op & pkgCache::Dep::Or) == pkgCache::Dep::Or)
+ {
+ BuildDeps[BuildDeps.size() - 1].Op &= ~pkgCache::Dep::Or;
+ BuildDeps[BuildDeps.size() - 1].Op |= (rec.Op & pkgCache::Dep::Or);
+ }
+ }
+ else
+ {
+ BuildDeps.emplace_back(std::move(rec));
+ }
+
+ if (Start == Stop)
+ break;
+ }
+ }
+ std::string const pseudo = "command line argument";
+ WriteBuildDependencyPackage(buildDepsPkgFile, pseudo, pseudoArch, BuildDeps);
+ pseudoPkgs.emplace_back(pseudo, pseudoArch, "");
+ }
+
// Read the source list
if (Cache.BuildSourceList() == false)
return false;
pkgSourceList *List = Cache.GetSourceList();
+ if (not AreDoingSatisfy)
{
auto const VolatileSources = List->GetVolatileFiles();
for (auto &&pkg : VolatileCmdL)
@@ -713,7 +784,7 @@ bool DoBuildDep(CommandLine &CmdL)
}
bool const WantLock = _config->FindB("APT::Get::Print-URIs", false) == false;
- if (CmdL.FileList[1] != 0)
+ if (CmdL.FileList[1] != 0 && not AreDoingSatisfy)
{
if (Cache.BuildCaches(WantLock) == false)
return false;
@@ -786,7 +857,7 @@ bool DoBuildDep(CommandLine &CmdL)
{
pkgDepCache::ActionGroup group(Cache);
- if (_config->FindB("APT::Get::Build-Dep-Automatic", false) == false)
+ if (_config->FindB(AreDoingSatisfy ? "APT::Get::Satisfy-Automatic" : "APT::Get::Build-Dep-Automatic", false) == false)
{
for (auto const &pkg: removeAgain)
{