Browse Source

Support --with-source in show & search commands

tags/debian/1.7.0_alpha1
David Kalnischkies 3 years ago
parent
commit
bf53f39c9a
5 changed files with 141 additions and 104 deletions
  1. +8
    -1
      apt-private/private-search.cc
  2. +96
    -90
      apt-private/private-show.cc
  3. +6
    -1
      apt-private/private-show.h
  4. +1
    -6
      cmdline/apt-cache.cc
  5. +30
    -6
      test/integration/test-apt-get-install-deb

+ 8
- 1
apt-private/private-search.cc View File

@@ -316,7 +316,14 @@ static bool Search(CommandLine &CmdL)
if (matchedAll == true)
{
if (ShowFull == true)
DisplayRecordV1(CacheFile, J->V, std::cout);
{
pkgCache::VerFileIterator Vf;
auto &Parser = LookupParser(Recs, J->V, Vf);
char const *Start, *Stop;
Parser.GetRec(Start, Stop);
size_t const Length = Stop - Start;
DisplayRecordV1(CacheFile, Recs, J->V, Vf, Start, Length, std::cout);
}
else
printf("%s - %s\n",P.Name().c_str(),P.ShortDesc().c_str());
}


+ 96
- 90
apt-private/private-show.cc View File

@@ -30,35 +30,23 @@
#include <apti18n.h>
/*}}}*/

static bool OpenPackagesFile(pkgCacheFile &CacheFile, pkgCache::VerIterator const &V,/*{{{*/
FileFd &PkgF, pkgCache::VerFileIterator &Vf)
pkgRecords::Parser &LookupParser(pkgRecords &Recs, pkgCache::VerIterator const &V, pkgCache::VerFileIterator &Vf) /*{{{*/
{
pkgCache const * const Cache = CacheFile.GetPkgCache();
if (unlikely(Cache == NULL))
return false;

// Find an appropriate file
Vf = V.FileList();
for (; Vf.end() == false; ++Vf)
if ((Vf.File()->Flags & pkgCache::Flag::NotSource) == 0)
break;
if (Vf.end() == true)
Vf = V.FileList();
// Check and load the package list file
pkgCache::PkgFileIterator I = Vf.File();
if (I.IsOk() == false)
return _error->Error(_("Package file %s is out of sync."),I.FileName());

// Read the record
return PkgF.Open(I.FileName(), FileFd::ReadOnly, FileFd::Extension);
return Recs.Lookup(Vf);
}
/*}}}*/
static APT_PURE unsigned char const* skipDescriptionFields(unsigned char const * DescP)/*{{{*/
static APT_PURE char const *skipDescriptionFields(char const *DescP, size_t const Length) /*{{{*/
{
auto const backup = DescP;
char const * const TagName = "\nDescription";
size_t const TagLen = strlen(TagName);
while ((DescP = (unsigned char*)strchr((char*)DescP, '\n')) != NULL)
while ((DescP = static_cast<char const *>(memchr(DescP, '\n', Length - (DescP - backup)))) != nullptr)
{
if (DescP[1] == ' ')
DescP += 2;
@@ -72,114 +60,126 @@ static APT_PURE unsigned char const* skipDescriptionFields(unsigned char const *
return DescP;
}
/*}}}*/
bool DisplayRecordV1(pkgCacheFile &CacheFile, pkgCache::VerIterator const &V,/*{{{*/
std::ostream &out)
static APT_PURE char const *findDescriptionField(char const *DescP, size_t const Length) /*{{{*/
{
FileFd PkgF;
pkgCache::VerFileIterator Vf;
if (OpenPackagesFile(CacheFile, V, PkgF, Vf) == false)
return false;
auto const backup = DescP;
char const * const TagName = "\nDescription";
size_t const TagLen = strlen(TagName);
while ((DescP = static_cast<char const *>(memchr(DescP, '\n', Length - (DescP - backup)))) != nullptr)
{
if (strncmp(DescP, TagName, TagLen) == 0)
break;
else
++DescP;
}
if (DescP != nullptr)
++DescP;
return DescP;
}
/*}}}*/

pkgCache * const Cache = CacheFile.GetPkgCache();
if (unlikely(Cache == NULL))
bool DisplayRecordV1(pkgCacheFile &, pkgRecords &Recs, /*{{{*/
pkgCache::VerIterator const &V, pkgCache::VerFileIterator const &,
char const *Buffer, size_t Length, std::ostream &out)
{
if (unlikely(Length == 0))
return false;

// Read the record (and ensure that it ends with a newline and NUL)
unsigned char *Buffer = new unsigned char[Cache->HeaderP->MaxVerFileSize+2];
Buffer[Vf->Size] = '\n';
Buffer[Vf->Size+1] = '\0';
if (PkgF.Seek(Vf->Offset) == false ||
PkgF.Read(Buffer,Vf->Size) == false)
auto const Desc = V.TranslatedDescription();
if (Desc.end())
{
delete [] Buffer;
return false;
// we have no translation output whatever we have got
return FileFd::Write(STDOUT_FILENO, Buffer, Length);
}

// Get a pointer to start of Description field
const unsigned char *DescP = (unsigned char*)strstr((char*)Buffer, "\nDescription");
if (DescP != NULL)
++DescP;
else
DescP = Buffer + Vf->Size;
char const *DescP = findDescriptionField(Buffer, Length);
if (DescP == nullptr)
DescP = Buffer + Length;

// Write all but Description
size_t const length = DescP - Buffer;
if (length != 0 && FileFd::Write(STDOUT_FILENO, Buffer, length) == false)
{
delete [] Buffer;
size_t const untilDesc = DescP - Buffer;
if (untilDesc != 0 && FileFd::Write(STDOUT_FILENO, Buffer, untilDesc) == false)
return false;
}

// Show the right description
pkgRecords Recs(*Cache);
pkgCache::DescIterator Desc = V.TranslatedDescription();
if (Desc.end() == false)
{
pkgRecords::Parser &P = Recs.Lookup(Desc.FileList());
out << "Description" << ( (strcmp(Desc.LanguageCode(),"") != 0) ? "-" : "" ) << Desc.LanguageCode() << ": " << P.LongDesc();
out << std::endl << "Description-md5: " << Desc.md5() << std::endl;
char desctag[50];
auto const langcode = Desc.LanguageCode();
if (strcmp(langcode, "") == 0)
strcpy(desctag, "\nDescription");
else
snprintf(desctag, sizeof(desctag), "\nDescription-%s", langcode);

// Find the first field after the description (if there is any)
DescP = skipDescriptionFields(DescP);
out << desctag + 1 << ": ";
auto const Df = Desc.FileList();
if (Df.end() == false)
{
pkgRecords::Parser &P = Recs.Lookup(Df);
out << P.LongDesc();
}
// else we have no translation, so we found a lonely Description-md5 -> don't skip it

out << std::endl << "Description-md5: " << Desc.md5() << std::endl;

// Find the first field after the description (if there is any)
DescP = skipDescriptionFields(DescP, Length - (DescP - Buffer));

// write the rest of the buffer, but skip mixed in Descriptions* fields
while (DescP != NULL)
while (DescP != nullptr)
{
const unsigned char * const Start = DescP;
const unsigned char *End = (unsigned char*)strstr((char*)DescP, "\nDescription");
if (End == NULL)
char const *const Start = DescP;
char const *End = findDescriptionField(DescP, Length - (DescP - Buffer));
if (End == nullptr)
{
End = &Buffer[Vf->Size];
DescP = NULL;
DescP = nullptr;
End = Buffer + Length - 1;
size_t endings = 0;
while (*End == '\n')
{
--End;
if (*End == '\r')
--End;
++endings;
}
if (endings >= 1)
{
++End;
if (*End == '\r')
++End;
}
++End;
}
else
{
++End; // get the newline into the output
DescP = skipDescriptionFields(End + strlen("Description"));
}
DescP = skipDescriptionFields(End + strlen("Description"), Length - (End - Buffer));

size_t const length = End - Start;
if (length != 0 && FileFd::Write(STDOUT_FILENO, Start, length) == false)
{
delete [] Buffer;
return false;
}
}
// write a final newline after the last field
out << std::endl;

delete [] Buffer;
return true;
}
/*}}}*/
static bool DisplayRecordV2(pkgCacheFile &CacheFile, pkgCache::VerIterator const &V,/*{{{*/
std::ostream &out)
static bool DisplayRecordV2(pkgCacheFile &CacheFile, pkgRecords &Recs, /*{{{*/
pkgCache::VerIterator const &V, pkgCache::VerFileIterator const &Vf,
char const *Buffer, size_t const Length, std::ostream &out)
{
FileFd PkgF;
pkgCache::VerFileIterator Vf;
if (OpenPackagesFile(CacheFile, V, PkgF, Vf) == false)
return false;

// Check and load the package list file
pkgCache::PkgFileIterator I = Vf.File();
if (I.IsOk() == false)
return _error->Error(_("Package file %s is out of sync."),I.FileName());

// find matching sources.list metaindex
pkgSourceList *SrcList = CacheFile.GetSourceList();
pkgIndexFile *Index;
if (SrcList->FindIndex(I, Index) == false &&
_system->FindIndex(I, Index) == false)
return _error->Error("Can not find indexfile for Package %s (%s)",
V.ParentPkg().Name(), V.VerStr());
return _error->Error("Can not find indexfile for Package %s (%s)",
V.ParentPkg().Name(), V.VerStr());
std::string source_index_file = Index->Describe(true);

// Read the record
pkgTagSection Tags;
pkgTagFile TagF(&PkgF);

if (TagF.Jump(Tags, V.FileList()->Offset) == false)
if (Tags.Scan(Buffer, Length, true) == false)
return _error->Error("Internal Error, Unable to parse a package record");

// make size nice
@@ -234,10 +234,6 @@ static bool DisplayRecordV2(pkgCacheFile &CacheFile, pkgCache::VerIterator const
return _error->Error("Internal Error, Unable to parse a package record");

// write the description
pkgCache * const Cache = CacheFile.GetPkgCache();
if (unlikely(Cache == NULL))
return false;
pkgRecords Recs(*Cache);
// FIXME: show (optionally) all available translations(?)
pkgCache::DescIterator Desc = V.TranslatedDescription();
if (Desc.end() == false)
@@ -245,7 +241,7 @@ static bool DisplayRecordV2(pkgCacheFile &CacheFile, pkgCache::VerIterator const
pkgRecords::Parser &P = Recs.Lookup(Desc.FileList());
out << "Description: " << P.LongDesc();
}
// write a final newline (after the description)
out << std::endl << std::endl;

@@ -255,6 +251,8 @@ static bool DisplayRecordV2(pkgCacheFile &CacheFile, pkgCache::VerIterator const
bool ShowPackage(CommandLine &CmdL) /*{{{*/
{
pkgCacheFile CacheFile;
if (unlikely(CacheFile.GetPkgCache() == nullptr))
return false;
CacheSetHelperVirtuals helper(true, GlobalError::NOTICE);
APT::CacheSetHelper::VerSelector const select = _config->FindB("APT::Cache::AllVersions", true) ?
APT::CacheSetHelper::ALL : APT::CacheSetHelper::CANDIDATE;
@@ -262,15 +260,23 @@ bool ShowPackage(CommandLine &CmdL) /*{{{*/
return false;
APT::VersionList const verset = APT::VersionList::FromCommandLine(CacheFile, CmdL.FileList + 1, select, 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)
{
pkgCache::VerFileIterator Vf;
auto &Parser = LookupParser(Recs, Ver, Vf);
char const *Start, *Stop;
Parser.GetRec(Start, Stop);
size_t const Length = Stop - Start;

if (ShowVersion <= 1)
{
if (DisplayRecordV1(CacheFile, Ver, std::cout) == false)
if (DisplayRecordV1(CacheFile, Recs, Ver, Vf, Start, Length, std::cout) == false)
return false;
}
else
if (DisplayRecordV2(CacheFile, Ver, c1out) == false)
return false;
else if (DisplayRecordV2(CacheFile, Recs, Ver, Vf, Start, Length + 1, c1out) == false)
return false;
}

if (select == APT::CacheSetHelper::CANDIDATE)
{


+ 6
- 1
apt-private/private-show.h View File

@@ -3,6 +3,7 @@

#include <apt-pkg/macros.h>
#include <apt-pkg/pkgcache.h>
#include <apt-pkg/pkgrecords.h>

#include <iostream>

@@ -10,8 +11,12 @@ class CommandLine;
class pkgCacheFile;

APT_PUBLIC bool ShowPackage(CommandLine &CmdL);
APT_PUBLIC bool DisplayRecordV1(pkgCacheFile &CacheFile, pkgCache::VerIterator const &V, std::ostream &out);
APT_PUBLIC bool ShowSrcPackage(CommandLine &CmdL);
APT_PUBLIC bool Policy(CommandLine &CmdL);

pkgRecords::Parser &LookupParser(pkgRecords &Recs, pkgCache::VerIterator const &V, pkgCache::VerFileIterator &Vf);
bool DisplayRecordV1(pkgCacheFile &CacheFile, pkgRecords &Recs,
pkgCache::VerIterator const &V, pkgCache::VerFileIterator const &Vf,
char const *Buffer, size_t const Length, std::ostream &out);

#endif

+ 1
- 6
cmdline/apt-cache.cc View File

@@ -470,12 +470,7 @@ static bool DumpAvail(CommandLine &)
for (pkgCache::VerFile **J = VFList; *J != 0;)
{
pkgCache::PkgFileIterator File(*Cache,(*J)->File + Cache->PkgFileP);
if (File.IsOk() == false)
{
_error->Error(_("Package file %s is out of sync."),File.FileName());
break;
}

// FIXME: Add support for volatile/with-source files
FileFd PkgF(File.FileName(),FileFd::ReadOnly, FileFd::Extension);
if (_error->PendingError() == true)
break;


+ 30
- 6
test/integration/test-apt-get-install-deb View File

@@ -8,20 +8,26 @@ setupenvironment
configarchitecture 'amd64' 'i386'

# regression test for #754904
testfailureequal 'E: Unsupported file /dev/null given on commandline' aptget install -qq /dev/null

# only consider .deb files
cat > foo.rpm <<EOF
I'm not a deb, I'm a teapot.
EOF
testfailureequal 'E: Unsupported file ./foo.rpm given on commandline' aptget install -qq ./foo.rpm
for exe in apt aptget; do
for cmd in install remove purge upgrade full-upgrade; do
testfailureequal 'E: Unsupported file /dev/null given on commandline' $exe $cmd -qq /dev/null
testfailureequal 'E: Unsupported file ./foo.rpm given on commandline' $exe $cmd -qq ./foo.rpm
done
done

# and ensure we fail for invalid debs
mv foo.rpm foo.deb
testfailuremsg "E: Sub-process Popen returned an error code (2)
for exe in apt aptget; do
for cmd in install remove purge upgrade full-upgrade; do
testfailuremsg "E: Sub-process Popen returned an error code (2)
E: Encountered a section with no Package: header
E: Problem with MergeList ${TMPWORKINGDIRECTORY}/foo.deb
E: The package lists or status file could not be parsed or opened." aptget install ./foo.deb
E: The package lists or status file could not be parsed or opened." $exe $cmd ./foo.deb
done
done

buildsimplenativepackage 'foo' 'i386,amd64' '1.0'

@@ -40,6 +46,20 @@ The following packages have unmet dependencies:
foo : Conflicts: foo:i386 but 1.0 is to be installed
E: Unable to correct problems, you have held broken packages." aptget install ./incoming/foo_1.0_i386.deb ./incoming/foo_1.0_amd64.deb -s

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
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'
testsuccess aptget install ./incoming/foo_1.0_i386.deb -o Debug::pkgCacheGen=1
testdpkginstalled 'foo:i386'
@@ -123,6 +143,9 @@ createpkg 'leading-newline' '

'
createpkg 'trailing-newline' '' '
'
createpkg 'double-trailing-newline' '' '

'

echo 'Package: /pkg-/
@@ -132,6 +155,7 @@ Pin-Priority: 501' > rootdir/etc/apt/preferences.d/pinit
testsuccess aptget install ./incoming/pkg-as-it-should-be_0_all.deb
testsuccess aptget install "$(readlink -f ./incoming/pkg-leading-newline_0_all.deb)"
testsuccess aptget install ./incoming/pkg-trailing-newline_0_all.deb
testsuccess aptget install ./incoming/pkg-double-trailing-newline_0_all.deb

testempty apt clean
if [ "$(id -u)" = '0' ]; then


Loading…
Cancel
Save