summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Kalnischkies <david@kalnischkies.de>2018-01-26 23:33:25 +0100
committerDavid Kalnischkies <david@kalnischkies.de>2018-05-11 17:58:46 +0200
commitce9223cc4e4ffcc43d17ae97ff8c57fb759a2c49 (patch)
tree97e3a97c145abd660ebe8f09ac2fcc97f558075d
parent9169cd5049bd7f0d5dcc56c40d567a766cf5b851 (diff)
Support release selector for volatile files as well
The syntax is a bit awkward, but it is the same as for a package name and introducing another syntax wouldn't really help usability, so with apt install ./foo.deb/experimental you will get the dependencies of foo satisfied by your default release, but if this wouldn't satisfy the version requirements the candidate for this dependency is switched to the version from the experimental release. The same applies for apt build-dep ./foo.dsc/stable-backports which was the initial request.
-rw-r--r--apt-private/private-install.cc80
-rw-r--r--apt-private/private-install.h17
-rw-r--r--apt-private/private-source.cc70
-rw-r--r--apt-private/private-upgrade.cc3
-rwxr-xr-xtest/integration/test-apt-install-file-reltag94
5 files changed, 214 insertions, 50 deletions
diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc
index c9e45cc00..4bb756b4f 100644
--- a/apt-private/private-install.cc
+++ b/apt-private/private-install.cc
@@ -564,16 +564,16 @@ static const unsigned short MOD_INSTALL = 2;
bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache, int UpgradeMode)
{
- std::vector<std::string> VolatileCmdL;
+ std::vector<PseudoPkg> VolatileCmdL;
return DoCacheManipulationFromCommandLine(CmdL, VolatileCmdL, Cache, UpgradeMode);
}
-bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector<std::string> &VolatileCmdL, CacheFile &Cache, int UpgradeMode)
+bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector<PseudoPkg> &VolatileCmdL, CacheFile &Cache, int UpgradeMode)
{
std::map<unsigned short, APT::VersionSet> verset;
std::set<std::string> UnknownPackages;
return DoCacheManipulationFromCommandLine(CmdL, VolatileCmdL, Cache, verset, UpgradeMode, UnknownPackages);
}
-bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector<std::string> &VolatileCmdL, CacheFile &Cache,
+bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector<PseudoPkg> &VolatileCmdL, CacheFile &Cache,
std::map<unsigned short, APT::VersionSet> &verset, int UpgradeMode, std::set<std::string> &UnknownPackages)
{
// Enter the special broken fixing mode if the user specified arguments
@@ -611,13 +611,18 @@ bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector<std::stri
for (auto const &I: VolatileCmdL)
{
- pkgCache::PkgIterator const P = Cache->FindPkg(I);
+ pkgCache::PkgIterator const P = Cache->FindPkg(I.name);
if (P.end())
continue;
// Set any version providing the .deb as the candidate.
for (auto Prv = P.ProvidesList(); Prv.end() == false; Prv++)
- Cache.GetDepCache()->SetCandidateVersion(Prv.OwnerVer());
+ {
+ if (I.release.empty())
+ Cache.GetDepCache()->SetCandidateVersion(Prv.OwnerVer());
+ else
+ Cache.GetDepCache()->SetCandidateRelease(Prv.OwnerVer(), I.release);
+ }
// via cacheset to have our usual virtual handling
APT::VersionContainerInterface::FromPackage(&(verset[MOD_INSTALL]), Cache, P, APT::CacheSetHelper::CANDIDATE, helper);
@@ -703,6 +708,68 @@ bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector<std::stri
return true;
}
/*}}}*/
+bool AddVolatileSourceFile(pkgSourceList *const SL, PseudoPkg &&pkg, std::vector<PseudoPkg> &VolatileCmdL)/*{{{*/
+{
+ auto const ext = flExtension(pkg.name);
+ if (ext != "dsc" && FileExists(pkg.name + "/debian/control") == false)
+ return false;
+ std::vector<std::string> files;
+ SL->AddVolatileFile(pkg.name, &files);
+ for (auto &&f: files)
+ VolatileCmdL.emplace_back(std::move(f), pkg.arch, pkg.release, pkg.index);
+ return true;
+
+}
+ /*}}}*/
+bool AddVolatileBinaryFile(pkgSourceList *const SL, PseudoPkg &&pkg, std::vector<PseudoPkg> &VolatileCmdL)/*{{{*/
+{
+ auto const ext = flExtension(pkg.name);
+ if (ext != "deb" && ext != "ddeb" && ext != "changes")
+ return false;
+ std::vector<std::string> files;
+ SL->AddVolatileFile(pkg.name, &files);
+ for (auto &&f: files)
+ VolatileCmdL.emplace_back(std::move(f), pkg.arch, pkg.release, pkg.index);
+ return true;
+}
+ /*}}}*/
+std::vector<PseudoPkg> GetPseudoPackages(pkgSourceList *const SL, CommandLine &CmdL, bool (*Add)(pkgSourceList *const, PseudoPkg &&, std::vector<PseudoPkg> &), std::string const &pseudoArch)/*{{{*/
+{
+ std::vector<PseudoPkg> VolatileCmdL;
+ std::remove_if(CmdL.FileList + 1, CmdL.FileList + 1 + CmdL.FileSize(), [&](char const *const I) {
+ if (I != nullptr && (I[0] == '/' || (I[0] == '.' && (I[1] == '\0' || (I[1] == '.' && (I[2] == '\0' || I[2] == '/')) || I[1] == '/'))))
+ {
+ PseudoPkg pkg(I, pseudoArch, "", SL->GetVolatileFiles().size());
+ if (FileExists(I)) // this accepts directories and symlinks, too
+ {
+ if (Add(SL, std::move(pkg), VolatileCmdL))
+ ;
+ else
+ _error->Error(_("Unsupported file %s given on commandline"), I);
+ return true;
+ }
+ else
+ {
+ auto const found = pkg.name.rfind("/");
+ if (found == pkg.name.find("/"))
+ _error->Error(_("Unsupported file %s given on commandline"), I);
+ else
+ {
+ pkg.release = pkg.name.substr(found + 1);
+ pkg.name.erase(found);
+ if (Add(SL, std::move(pkg), VolatileCmdL))
+ ;
+ else
+ _error->Error(_("Unsupported file %s given on commandline"), I);
+ }
+ return true;
+ }
+ }
+ return false;
+ });
+ return VolatileCmdL;
+}
+ /*}}}*/
// DoInstall - Install packages from the command line /*{{{*/
// ---------------------------------------------------------------------
/* Install named packages */
@@ -721,8 +788,7 @@ struct PkgIsExtraInstalled {
bool DoInstall(CommandLine &CmdL)
{
CacheFile Cache;
- std::vector<std::string> VolatileCmdL;
- Cache.GetSourceList()->AddVolatileFiles(CmdL, &VolatileCmdL);
+ auto VolatileCmdL = GetPseudoPackages(Cache.GetSourceList(), CmdL, AddVolatileBinaryFile, "");
// then open the cache
if (Cache.OpenForInstall() == false ||
diff --git a/apt-private/private-install.h b/apt-private/private-install.h
index 2d27756c9..07aa582be 100644
--- a/apt-private/private-install.h
+++ b/apt-private/private-install.h
@@ -17,9 +17,22 @@ class pkgProblemResolver;
APT_PUBLIC bool DoInstall(CommandLine &Cmd);
-bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector<std::string> &VolatileCmdL, CacheFile &Cache,
+struct PseudoPkg
+{
+ std::string name;
+ std::string arch;
+ std::string release;
+ ssize_t index;
+ PseudoPkg(std::string const &n, std::string const &a, std::string const &r) : name(n), arch(a), release(r), index(-1) {}
+ PseudoPkg(std::string const &n, std::string const &a, std::string const &r, ssize_t i) : name(n), arch(a), release(r), index(i) {}
+};
+std::vector<PseudoPkg> GetPseudoPackages(pkgSourceList *const SL, CommandLine &CmdL, bool (*Add)(pkgSourceList *const, PseudoPkg &&, std::vector<PseudoPkg> &), std::string const &pseudoArch);
+bool AddVolatileBinaryFile(pkgSourceList *const SL, PseudoPkg &&pkg, std::vector<PseudoPkg> &VolatileCmdL);
+bool AddVolatileSourceFile(pkgSourceList *const SL, PseudoPkg &&pkg, std::vector<PseudoPkg> &VolatileCmdL);
+
+bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector<PseudoPkg> &VolatileCmdL, CacheFile &Cache,
std::map<unsigned short, APT::VersionSet> &verset, int UpgradeMode, std::set<std::string> &UnknownPackages);
-bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector<std::string> &VolatileCmdL, CacheFile &Cache, int UpgradeMode);
+bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, std::vector<PseudoPkg> &VolatileCmdL, CacheFile &Cache, int UpgradeMode);
bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache, int UpgradeMode);
APT_PUBLIC bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
diff --git a/apt-private/private-source.cc b/apt-private/private-source.cc
index a24493421..c8a48a74a 100644
--- a/apt-private/private-source.cc
+++ b/apt-private/private-source.cc
@@ -636,15 +636,6 @@ static void WriteBuildDependencyPackage(std::ostringstream &buildDepsPkgFile,
}
bool DoBuildDep(CommandLine &CmdL)
{
- CacheFile Cache;
- std::vector<std::string> VolatileCmdL;
- Cache.GetSourceList()->AddVolatileFiles(CmdL, &VolatileCmdL);
-
- _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"));
-
bool StripMultiArch;
std::string hostArch = _config->Find("APT::Get::Host-Architecture");
if (hostArch.empty() == false)
@@ -656,16 +647,18 @@ bool DoBuildDep(CommandLine &CmdL)
}
else
StripMultiArch = true;
+ auto const nativeArch = _config->Find("APT::Architecture");
+ std::string const pseudoArch = hostArch.empty() ? nativeArch : hostArch;
+
+ CacheFile Cache;
+ auto VolatileCmdL = GetPseudoPackages(Cache.GetSourceList(), CmdL, AddVolatileSourceFile, pseudoArch);
+
+ _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"));
std::ostringstream buildDepsPkgFile;
- struct PseudoPkg
- {
- std::string name;
- std::string arch;
- std::string release;
- PseudoPkg(std::string const &n, std::string const &a, std::string const &r) :
- name(n), arch(a), release(r) {}
- };
std::vector<PseudoPkg> pseudoPkgs;
// deal with the build essentials first
{
@@ -681,7 +674,6 @@ bool DoBuildDep(CommandLine &CmdL)
BuildDeps.push_back(rec);
}
std::string const pseudo = "builddeps:essentials";
- std::string const nativeArch = _config->Find("APT::Architecture");
WriteBuildDependencyPackage(buildDepsPkgFile, pseudo, nativeArch, BuildDeps);
pseudoPkgs.emplace_back(pseudo, nativeArch, "");
}
@@ -690,34 +682,34 @@ bool DoBuildDep(CommandLine &CmdL)
if (Cache.BuildSourceList() == false)
return false;
pkgSourceList *List = Cache.GetSourceList();
- std::string const pseudoArch = hostArch.empty() ? _config->Find("APT::Architecture") : hostArch;
- // FIXME: Avoid volatile sources == cmdline assumption
{
auto const VolatileSources = List->GetVolatileFiles();
- if (VolatileSources.size() == VolatileCmdL.size())
+ for (auto &&pkg : VolatileCmdL)
{
- for (size_t i = 0; i < VolatileSources.size(); ++i)
+ if (unlikely(pkg.index == -1))
{
- auto const Src = VolatileCmdL[i];
- if (DirectoryExists(Src))
- ioprintf(c1out, _("Note, using directory '%s' to get the build dependencies\n"), Src.c_str());
- else
- ioprintf(c1out, _("Note, using file '%s' to get the build dependencies\n"), Src.c_str());
- std::unique_ptr<pkgSrcRecords::Parser> Last(VolatileSources[i]->CreateSrcParser());
- if (Last == nullptr)
- return _error->Error(_("Unable to find a source package for %s"), Src.c_str());
-
- std::string const pseudo = std::string("builddeps:") + Src;
- WriteBuildDependencyPackage(buildDepsPkgFile, pseudo, pseudoArch,
- GetBuildDeps(Last.get(), Src.c_str(), StripMultiArch, hostArch));
- pseudoPkgs.emplace_back(pseudo, pseudoArch, "");
+ _error->Error(_("Unable to find a source package for %s"), pkg.name.c_str());
+ continue;
+ }
+ if (DirectoryExists(pkg.name))
+ ioprintf(c1out, _("Note, using directory '%s' to get the build dependencies\n"), pkg.name.c_str());
+ else
+ ioprintf(c1out, _("Note, using file '%s' to get the build dependencies\n"), pkg.name.c_str());
+ std::unique_ptr<pkgSrcRecords::Parser> Last(VolatileSources[pkg.index]->CreateSrcParser());
+ if (Last == nullptr)
+ {
+ _error->Error(_("Unable to find a source package for %s"), pkg.name.c_str());
+ continue;
}
+
+ auto pseudo = std::string("builddeps:") + pkg.name;
+ WriteBuildDependencyPackage(buildDepsPkgFile, pseudo, pseudoArch,
+ GetBuildDeps(Last.get(), pkg.name.c_str(), StripMultiArch, hostArch));
+ pkg.name = std::move(pseudo);
+ pseudoPkgs.push_back(std::move(pkg));
}
- else
- return _error->Error("Implementation error: Volatile sources (%lu) and"
- "commandline elements (%lu) do not match!", VolatileSources.size(),
- VolatileCmdL.size());
+ VolatileCmdL.clear();
}
bool const WantLock = _config->FindB("APT::Get::Print-URIs", false) == false;
diff --git a/apt-private/private-upgrade.cc b/apt-private/private-upgrade.cc
index 989f6b0c1..aeaf5066b 100644
--- a/apt-private/private-upgrade.cc
+++ b/apt-private/private-upgrade.cc
@@ -19,8 +19,7 @@
static bool UpgradeHelper(CommandLine &CmdL, int UpgradeFlags)
{
CacheFile Cache;
- std::vector<std::string> VolatileCmdL;
- Cache.GetSourceList()->AddVolatileFiles(CmdL, &VolatileCmdL);
+ auto VolatileCmdL = GetPseudoPackages(Cache.GetSourceList(), CmdL, AddVolatileBinaryFile, "");
if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false)
return false;
diff --git a/test/integration/test-apt-install-file-reltag b/test/integration/test-apt-install-file-reltag
new file mode 100755
index 000000000..afbf9bef9
--- /dev/null
+++ b/test/integration/test-apt-install-file-reltag
@@ -0,0 +1,94 @@
+#!/bin/sh
+set -e
+
+TESTDIR="$(readlink -f "$(dirname "$0")")"
+. "$TESTDIR/framework"
+
+setupenvironment
+configarchitecture 'i386'
+
+insertpackage 'unstable' 'foo' 'all' '2' 'Depends: foo-common (= 2)'
+insertpackage 'unstable' 'foo-common' 'all' '2'
+insertpackage 'unstable' 'baz' 'all' '1'
+insertpackage 'experimental' 'foo' 'all' '5' 'Depends: foo-common (= 5)'
+insertpackage 'experimental' 'foo-common' 'all' '5' 'Source: foo (5)'
+insertpackage 'experimental' 'baz' 'all' '2'
+setupaptarchive
+
+insertinstalledpackage 'build-essential' 'all' '1'
+
+cat > foobar.dsc <<EOF
+Format: 3.0 (native)
+Source: foobar
+Binary: foobar
+Architecture: all
+Version: 1
+Maintainer: Joe Sixpack <joe@example.org>
+Build-Depends: foo (= 5), baz
+Standards-Version: 4.1.3
+EOF
+buildsimplenativepackage 'foobar2' 'all' '1' 'unstable' 'Depends: foo (= 5), baz'
+
+ln -s "$(readlink -f ./incoming/foobar2_1_all.deb)" foobar.deb
+mkdir -p foobar
+testfailuremsg 'E: Unable to correct problems, you have held broken packages.' apt build-dep "$(readlink -f ./foobar.dsc)" -s
+testfailuremsg 'E: Unable to correct problems, you have held broken packages.' apt install "$(readlink -f ./foobar.deb)" -s
+testfailuremsg 'E: Unable to correct problems, you have held broken packages.' apt build-dep ./foobar.dsc -s
+testfailuremsg 'E: Unable to correct problems, you have held broken packages.' apt install ./foobar.deb -s
+cd foobar
+testfailuremsg 'E: Unable to correct problems, you have held broken packages.' apt build-dep ../foobar.dsc -s
+testfailuremsg 'E: Unable to correct problems, you have held broken packages.' apt install ../foobar.deb -s
+cd ..
+
+SUCCESSDSC='The following NEW packages will be installed:
+ baz foo foo-common
+0 upgraded, 3 newly installed, 0 to remove and 0 not upgraded.
+Inst baz (1 unstable [all])
+Inst foo-common (5 experimental [all])
+Inst foo (5 experimental [all])
+Conf baz (1 unstable [all])
+Conf foo-common (5 experimental [all])
+Conf foo (5 experimental [all])'
+SUCCESSDEB='The following additional packages will be installed:
+ baz foo foo-common
+The following NEW packages will be installed:
+ baz foo foo-common foobar2
+0 upgraded, 4 newly installed, 0 to remove and 0 not upgraded.
+Inst baz (1 unstable [all])
+Inst foo-common (5 experimental [all])
+Inst foo (5 experimental [all])
+Inst foobar2 (1 local-deb [all])
+Conf baz (1 unstable [all])
+Conf foo-common (5 experimental [all])
+Conf foo (5 experimental [all])
+Conf foobar2 (1 local-deb [all])'
+testsuccessequal "Note, using file '$(readlink -f ./foobar.dsc)' to get the build dependencies
+$SUCCESSDSC" apt build-dep "$(readlink -f ./foobar.dsc)/experimental" -s -q=2
+testsuccessequal "Reading package lists...
+Building dependency tree...
+Note, selecting 'foobar2' instead of '$(readlink -f ./foobar.deb)'
+$SUCCESSDEB" apt install "$(readlink -f ./foobar.deb)/experimental" -s
+testsuccessequal "Note, using file './foobar.dsc' to get the build dependencies
+$SUCCESSDSC" apt build-dep ./foobar.dsc/experimental -sq=2
+testsuccessequal "Reading package lists...
+Building dependency tree...
+Note, selecting 'foobar2' instead of './foobar.deb'
+$SUCCESSDEB" apt install "./foobar.deb/experimental" -s
+cd foobar
+testsuccessequal "Note, using file '../foobar.dsc' to get the build dependencies
+$SUCCESSDSC" apt build-dep ../foobar.dsc/experimental -sqq
+testsuccessequal "Reading package lists...
+Building dependency tree...
+Note, selecting 'foobar2' instead of '../foobar.deb'
+$SUCCESSDEB" apt install "../foobar.deb/experimental" -s
+cd ..
+
+msgmsg 'fail with' 'incorrect release'
+testfailuremsg 'E: Unable to correct problems, you have held broken packages.' apt build-dep "$(readlink -f ./foobar.dsc)/stable" -s
+testfailuremsg 'E: Unable to correct problems, you have held broken packages.' apt install "$(readlink -f ./foobar.deb)/stable" -s
+testfailuremsg 'E: Unable to correct problems, you have held broken packages.' apt build-dep ./foobar.dsc/stable -s
+testfailuremsg 'E: Unable to correct problems, you have held broken packages.' apt install ./foobar.deb/stable -s
+cd foobar
+testfailuremsg 'E: Unable to correct problems, you have held broken packages.' apt build-dep ../foobar.dsc/stable -s
+testfailuremsg 'E: Unable to correct problems, you have held broken packages.' apt install ../foobar.deb/stable -s
+cd ..