From 61843f539513b3e661dac55717e6d7cc0b8f9b0c Mon Sep 17 00:00:00 2001
From: David Kalnischkies <kalnischkies@gmail.com>
Date: Thu, 18 Jul 2013 16:52:31 +0200
Subject: skip all Description fields in apt-cache, not just first
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Given a Packages file like:
[…]
Description: foo bar baz
 moo moo moo
Multi-Arch: foreign
Description-md5: 97e204a9f4ad8c681dbd54ec7c505251
[…]

We have to display the Multi-Arch flag field as well as the fields
after the Description-md5, but not this field itself, as we already
have one printed alongside the Description we display.

Closes: 717254
---
 cmdline/apt-cache.cc                               | 52 +++++++++++++++-------
 .../test-bug-712435-missing-descriptions           | 52 +++++++++++++++++++++-
 2 files changed, 86 insertions(+), 18 deletions(-)

diff --git a/cmdline/apt-cache.cc b/cmdline/apt-cache.cc
index fb4467c2c..336ac544b 100644
--- a/cmdline/apt-cache.cc
+++ b/cmdline/apt-cache.cc
@@ -1127,6 +1127,22 @@ bool Dotty(CommandLine &CmdL)
 // ---------------------------------------------------------------------
 /* This displays the package record from the proper package index file. 
    It is not used by DumpAvail for performance reasons. */
+
+static unsigned char const* skipDescriptionFields(unsigned char const * DescP)
+{
+   while ((DescP = (unsigned char*)strchr((char*)DescP, '\n')) != NULL)
+   {
+      if (DescP[1] == ' ')
+	 DescP += 2;
+      else if (strncmp((char*)DescP, "\nDescription", strlen("\nDescription")) == 0)
+	 DescP += strlen("\nDescription");
+      else
+	 break;
+   }
+   if (DescP != NULL)
+      ++DescP;
+   return DescP;
+}
 bool DisplayRecord(pkgCacheFile &CacheFile, pkgCache::VerIterator V)
 {
    pkgCache *Cache = CacheFile.GetPkgCache();
@@ -1184,32 +1200,34 @@ bool DisplayRecord(pkgCacheFile &CacheFile, pkgCache::VerIterator V)
       cout << std::endl << "Description-md5: " << Desc.md5() << std::endl;
 
       // Find the first field after the description (if there is any)
-      while ((DescP = (unsigned char*)strchr((char*)DescP, '\n')) != NULL)
-      {
-	 if (DescP[1] == ' ')
-	    DescP += 2;
-	 else if (strncmp((char*)DescP, "\nDescription", strlen("\nDescription")) == 0)
-	    DescP += strlen("\nDescription");
-	 else
-	    break;
-      }
-      if (DescP != NULL)
-	 ++DescP;
+      DescP = skipDescriptionFields(DescP);
    }
-   // if we have no translation, we found a lonely Description-md5, so don't skip it
+   // else we have no translation, so we found a lonely Description-md5 -> don't skip it
 
-   if (DescP != NULL)
+   // write the rest of the buffer, but skip mixed in Descriptions* fields
+   while (DescP != NULL)
    {
-      // write the rest of the buffer
-      const unsigned char *end=&Buffer[V.FileList()->Size];
-      if (fwrite(DescP,1,end-DescP,stdout) < (size_t)(end-DescP))
+      const unsigned char * const Start = DescP;
+      const unsigned char *End = (unsigned char*)strstr((char*)DescP, "\nDescription");
+      if (End == NULL)
+      {
+	 End = &Buffer[V.FileList()->Size];
+	 DescP = NULL;
+      }
+      else
+      {
+	 ++End; // get the newline into the output
+	 DescP = skipDescriptionFields(End + strlen("Description"));
+      }
+      size_t const length = End - Start;
+      if (fwrite(Start, 1, length, stdout) < length)
       {
 	 delete [] Buffer;
 	 return false;
       }
    }
 
-   // write a final newline (after the description)
+   // write a final newline after the last field
    cout<<endl;
    delete [] Buffer;
 
diff --git a/test/integration/test-bug-712435-missing-descriptions b/test/integration/test-bug-712435-missing-descriptions
index 9b3c2ee50..c61bea452 100755
--- a/test/integration/test-bug-712435-missing-descriptions
+++ b/test/integration/test-bug-712435-missing-descriptions
@@ -52,7 +52,32 @@ $PACKAGESTANZA
 Description-md5: dddddddddddddddddddddddddddddddd
 
 Package: apt-none
-$PACKAGESTANZA" > aptarchive/Packages
+$PACKAGESTANZA
+
+Package: apt-intermixed
+$PACKAGESTANZA
+$DESCRIPTION
+X-Some-Flag: yes
+Description-md5: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+
+Package: apt-intermixed2
+$PACKAGESTANZA
+$DESCRIPTION
+X-Some-Flag: yes
+$TRANSDESCRIPTION
+X-Foo-Flag: Something with a Description
+Description-md5: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+X-Bar-Flag: no
+
+Package: apt-intermixed3
+$PACKAGESTANZA
+$DESCRIPTION
+X-Some-Flag: yes
+$TRANSDESCRIPTION
+X-Foo-Flag: Something with a Description
+X-Bar-Flag: no
+Description-md5: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" > aptarchive/Packages
+
 
 setupaptarchive
 
@@ -87,3 +112,28 @@ Description-md5: dddddddddddddddddddddddddddddddd
 testequal "Package: apt-none
 $PACKAGESTANZA
 " aptcache show apt-none
+
+testequal "Package: apt-intermixed
+$PACKAGESTANZA
+$DESCRIPTION
+Description-md5: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+X-Some-Flag: yes
+" aptcache show apt-intermixed
+
+testequal "Package: apt-intermixed2
+$PACKAGESTANZA
+$DESCRIPTION
+Description-md5: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+X-Some-Flag: yes
+X-Foo-Flag: Something with a Description
+X-Bar-Flag: no
+" aptcache show apt-intermixed2
+
+testequal "Package: apt-intermixed3
+$PACKAGESTANZA
+$DESCRIPTION
+Description-md5: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+X-Some-Flag: yes
+X-Foo-Flag: Something with a Description
+X-Bar-Flag: no
+" aptcache show apt-intermixed3
-- 
cgit v1.2.3