Browse Source

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
tags/debian/1.7.0_alpha1
David Kalnischkies 3 years ago
parent
commit
6085ab7488
4 changed files with 127 additions and 32 deletions
  1. +39
    -24
      apt-private/private-install.cc
  2. +1
    -0
      apt-private/private-install.h
  3. +61
    -3
      apt-private/private-show.cc
  4. +26
    -5
      test/integration/test-apt-get-install-deb

+ 39
- 24
apt-private/private-install.cc View File

@@ -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;
}


+ 1
- 0
apt-private/private-install.h View File

@@ -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);


+ 61
- 3
apt-private/private-show.cc View File

@@ -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);


+ 26
- 5
test/integration/test-apt-get-install-deb View File

@@ -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'


Loading…
Cancel
Save