diff options
author | David Kalnischkies <david@kalnischkies.de> | 2018-04-12 09:59:47 +0200 |
---|---|---|
committer | David Kalnischkies <david@kalnischkies.de> | 2018-05-11 17:58:46 +0200 |
commit | 6085ab7488326cfed8f82e07eefcbc2dc40d4bea (patch) | |
tree | d7e0241441f329b0ea00b25eded6f1fce6e8903f | |
parent | bf53f39c9a0221b670ffff74053ed36fc502d5a0 (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.cc | 63 | ||||
-rw-r--r-- | apt-private/private-install.h | 1 | ||||
-rw-r--r-- | apt-private/private-show.cc | 64 | ||||
-rwxr-xr-x | test/integration/test-apt-get-install-deb | 31 |
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' |