summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Kalnischkies <david@kalnischkies.de>2018-04-12 09:59:47 +0200
committerDavid Kalnischkies <david@kalnischkies.de>2018-05-11 17:58:46 +0200
commit6085ab7488326cfed8f82e07eefcbc2dc40d4bea (patch)
treed7e0241441f329b0ea00b25eded6f1fce6e8903f
parentbf53f39c9a0221b670ffff74053ed36fc502d5a0 (diff)
Support local files as arguments in show command
Now that --with-source is supported in show we can go a little further and add the "syntactic sugar" of supporting deb-files on the commandline directly to give users an alternative to remembering dpkg -I for deb files & as a bonus apt also works on changes files. Most of the code churn is actually to deal with cases probably not too common in reality like mixing packages and deb-files on the commandline and getting the right order for these multiple records. Closes: 883206
-rw-r--r--apt-private/private-install.cc63
-rw-r--r--apt-private/private-install.h1
-rw-r--r--apt-private/private-show.cc64
-rwxr-xr-xtest/integration/test-apt-get-install-deb31
4 files changed, 127 insertions, 32 deletions
diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc
index 4bb756b4f..f90e7097f 100644
--- a/apt-private/private-install.cc
+++ b/apt-private/private-install.cc
@@ -733,39 +733,54 @@ bool AddVolatileBinaryFile(pkgSourceList *const SL, PseudoPkg &&pkg, std::vector
return true;
}
/*}}}*/
-std::vector<PseudoPkg> GetPseudoPackages(pkgSourceList *const SL, CommandLine &CmdL, bool (*Add)(pkgSourceList *const, PseudoPkg &&, std::vector<PseudoPkg> &), std::string const &pseudoArch)/*{{{*/
+static bool AddIfVolatile(pkgSourceList *const SL, std::vector<PseudoPkg> &VolatileCmdL, bool (*Add)(pkgSourceList *const, PseudoPkg &&, std::vector<PseudoPkg> &), char const * const I, 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] == '/'))))
+ 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
{
- PseudoPkg pkg(I, pseudoArch, "", SL->GetVolatileFiles().size());
- if (FileExists(I)) // this accepts directories and symlinks, too
+ 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;
- }
- 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 true;
}
- return false;
+ }
+ return false;
+}
+ /*}}}*/
+std::vector<PseudoPkg> GetAllPackagesAsPseudo(pkgSourceList *const SL, CommandLine &CmdL, bool (*Add)(pkgSourceList *const, PseudoPkg &&, std::vector<PseudoPkg> &), std::string const &pseudoArch)/*{{{*/
+{
+ std::vector<PseudoPkg> PkgCmdL;
+ std::for_each(CmdL.FileList + 1, CmdL.FileList + CmdL.FileSize(), [&](char const *const I) {
+ if (AddIfVolatile(SL, PkgCmdL, Add, I, pseudoArch) == false)
+ PkgCmdL.emplace_back(I, pseudoArch, "", -1);
+ });
+ return PkgCmdL;
+}
+ /*}}}*/
+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) {
+ return AddIfVolatile(SL, VolatileCmdL, Add, I, pseudoArch);
});
return VolatileCmdL;
}
diff --git a/apt-private/private-install.h b/apt-private/private-install.h
index 07aa582be..39a040e7d 100644
--- a/apt-private/private-install.h
+++ b/apt-private/private-install.h
@@ -26,6 +26,7 @@ struct PseudoPkg
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> GetAllPackagesAsPseudo(pkgSourceList *const SL, CommandLine &CmdL, bool (*Add)(pkgSourceList *const, PseudoPkg &&, std::vector<PseudoPkg> &), std::string const &pseudoArch);
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);
diff --git a/apt-private/private-show.cc b/apt-private/private-show.cc
index 64251bed4..15c05d420 100644
--- a/apt-private/private-show.cc
+++ b/apt-private/private-show.cc
@@ -20,6 +20,7 @@
#include <apt-private/private-cacheset.h>
#include <apt-private/private-output.h>
+#include <apt-private/private-install.h>
#include <apt-private/private-show.h>
#include <ostream>
@@ -251,6 +252,8 @@ static bool DisplayRecordV2(pkgCacheFile &CacheFile, pkgRecords &Recs, /*{{{*/
bool ShowPackage(CommandLine &CmdL) /*{{{*/
{
pkgCacheFile CacheFile;
+ auto VolatileCmdL = GetAllPackagesAsPseudo(CacheFile.GetSourceList(), CmdL, AddVolatileBinaryFile, "");
+
if (unlikely(CacheFile.GetPkgCache() == nullptr))
return false;
CacheSetHelperVirtuals helper(true, GlobalError::NOTICE);
@@ -258,7 +261,38 @@ bool ShowPackage(CommandLine &CmdL) /*{{{*/
APT::CacheSetHelper::ALL : APT::CacheSetHelper::CANDIDATE;
if (select == APT::CacheSetHelper::CANDIDATE && CacheFile.GetDepCache() == nullptr)
return false;
- APT::VersionList const verset = APT::VersionList::FromCommandLine(CacheFile, CmdL.FileList + 1, select, helper);
+
+ APT::VersionList verset;
+ size_t normalPackages = 0;
+ for (auto const &I: VolatileCmdL)
+ {
+ if (I.index == -1)
+ {
+ APT::VersionContainerInterface::FromString(&verset, CacheFile, I.name, select, helper);
+ ++normalPackages;
+ }
+ else
+ {
+ if (select != APT::CacheSetHelper::CANDIDATE && unlikely(CacheFile.GetDepCache() == nullptr))
+ return false;
+ pkgCache::PkgIterator const P = CacheFile->FindPkg(I.name);
+ if (unlikely(P.end()))
+ continue;
+
+ // Set any version providing the .deb as the candidate.
+ for (auto Prv = P.ProvidesList(); Prv.end() == false; ++Prv)
+ {
+ if (I.release.empty())
+ CacheFile->SetCandidateVersion(Prv.OwnerVer());
+ else
+ CacheFile->SetCandidateRelease(Prv.OwnerVer(), I.release);
+
+ // via cacheset to have our usual handling
+ APT::VersionContainerInterface::FromPackage(&verset, CacheFile, Prv.OwnerPkg(), APT::CacheSetHelper::CANDIDATE, helper);
+ }
+ }
+ }
+
int const ShowVersion = _config->FindI("APT::Cache::Show::Version", 1);
pkgRecords Recs(CacheFile);
for (APT::VersionList::const_iterator Ver = verset.begin(); Ver != verset.end(); ++Ver)
@@ -278,9 +312,33 @@ bool ShowPackage(CommandLine &CmdL) /*{{{*/
return false;
}
- if (select == APT::CacheSetHelper::CANDIDATE)
+ if (select == APT::CacheSetHelper::CANDIDATE && normalPackages != 0)
{
- APT::VersionList const verset_all = APT::VersionList::FromCommandLine(CacheFile, CmdL.FileList + 1, APT::CacheSetHelper::ALL, helper);
+ APT::VersionList verset_all;
+ for (auto const &I: VolatileCmdL)
+ {
+ if (I.index == -1)
+ APT::VersionContainerInterface::FromString(&verset_all, CacheFile, I.name, APT::CacheSetHelper::ALL, helper);
+ else
+ {
+ pkgCache::PkgIterator const P = CacheFile->FindPkg(I.name);
+ if (unlikely(P.end()))
+ continue;
+
+ // Set any version providing the .deb as the candidate.
+ for (auto Prv = P.ProvidesList(); Prv.end() == false; ++Prv)
+ {
+ if (I.release.empty())
+ CacheFile->SetCandidateVersion(Prv.OwnerVer());
+ else
+ CacheFile->SetCandidateRelease(Prv.OwnerVer(), I.release);
+
+ // via cacheset to have our usual virtual handling
+ APT::VersionContainerInterface::FromPackage(&verset_all, CacheFile, Prv.OwnerPkg(), APT::CacheSetHelper::CANDIDATE, helper);
+ }
+ }
+ }
+
int const records = verset_all.size() - verset.size();
if (records > 0)
_error->Notice(P_("There is %i additional record. Please use the '-a' switch to see it", "There are %i additional records. Please use the '-a' switch to see them.", records), records);
diff --git a/test/integration/test-apt-get-install-deb b/test/integration/test-apt-get-install-deb
index ff103a514..844f1d7c5 100755
--- a/test/integration/test-apt-get-install-deb
+++ b/test/integration/test-apt-get-install-deb
@@ -48,16 +48,37 @@ E: Unable to correct problems, you have held broken packages." aptget install ./
testsuccess apt show foo --with-source ./incoming/foo_1.0_amd64.deb
testequal 'Package: foo
-Version: 1.0' head -n 2 rootdir/tmp/testsuccess.output
+Version: 1.0' grep -e '^Package:' -e '^Version:' -e '^Architecture:' rootdir/tmp/testsuccess.output
+testsuccess apt show ./incoming/foo_1.0_amd64.deb
+testequal 'Package: foo
+Version: 1.0' grep -e '^Package:' -e '^Version:' -e '^Architecture:' rootdir/tmp/testsuccess.output
+testsuccess apt show foo:i386 ./incoming/foo_1.0_amd64.deb --with-source ./incoming/foo_1.0_i386.deb
+testequal 'Package: foo:i386
+Version: 1.0
+Package: foo
+Version: 1.0' grep -e '^Package:' -e '^Version:' -e '^Architecture:' rootdir/tmp/testsuccess.output
+
+testsuccess aptcache show foo --with-source ./incoming/foo_1.0_amd64.deb
+testequal 'Package: foo
+Version: 1.0
+Architecture: amd64' grep -e '^Package:' -e '^Version:' -e '^Architecture:' rootdir/tmp/testsuccess.output
+testsuccess aptcache show ./incoming/foo_1.0_amd64.deb
+testequal 'Package: foo
+Version: 1.0
+Architecture: amd64' grep -e '^Package:' -e '^Version:' -e '^Architecture:' rootdir/tmp/testsuccess.output
+testsuccess aptcache show foo:i386 ./incoming/foo_1.0_amd64.deb --with-source ./incoming/foo_1.0_i386.deb
+testequal 'Package: foo
+Version: 1.0
+Architecture: i386
+Package: foo
+Version: 1.0
+Architecture: amd64' grep -e '^Package:' -e '^Version:' -e '^Architecture:' rootdir/tmp/testsuccess.output
+
testsuccessequal 'Sorting...
Full Text Search...
foo/local-deb 1.0 amd64
an autogenerated dummy foo=1.0/unstable
' apt search foo --with-source ./incoming/foo_1.0_amd64.deb
-
-testsuccess aptcache show foo --with-source ./incoming/foo_1.0_amd64.deb
-testequal 'Package: foo
-Version: 1.0' head -n 2 rootdir/tmp/testsuccess.output
testsuccessequal 'foo - an autogenerated dummy foo=1.0/unstable' aptcache search foo --with-source ./incoming/foo_1.0_amd64.deb
testdpkgnotinstalled 'foo' 'foo:i386'