Преглед на файлове

* merged ddtp support

Patches applied:

 * michael.vogt@ubuntu.com--2005/apt--ddtp--0--base-0
   tag of otavio@debian.org--2005/apt--ddtp--0.6--patch-14

 * michael.vogt@ubuntu.com--2005/apt--ddtp--0--patch-1
   * fixed a problem when it comes to the cache rebuilding

 * michael.vogt@ubuntu.com--2005/apt--ddtp--0--patch-2
   * try harder to get the correct language code

 * michael.vogt@ubuntu.com--2005/apt--ddtp--0--patch-3
   * fix for output of the description and the debTranslationsIndex::Exists()

 * michael.vogt@ubuntu.com--2005/apt--ddtp--0--patch-4
   * made the translation downloading work

 * michael.vogt@ubuntu.com--2005/apt--ddtp--0--patch-5
   * FindInCache() uses the correct file now

 * michael.vogt@ubuntu.com--2005/apt--ddtp--0--patch-6
   * don't throw any more warnings

 * michael.vogt@ubuntu.com--2005/apt--ddtp--0--patch-7
   * merged with otavoi

 * michael.vogt@ubuntu.com--2005/apt--ddtp--0--patch-8
   * merged with otavios branch

 * michael.vogt@ubuntu.com--2005/apt--ddtp--0--patch-9
   * code cleanups (thanks matt!), moved UsePackage before the description list build in pkgcachegen to catch MMap errors early

 * michael.vogt@ubuntu.com--2005/apt--ddtp--0--patch-10
   * added a BUGS file with known problem, added apt-cdrom support for translated package descriptions

 * michael.vogt@ubuntu.com--2005/apt--ddtp--0--patch-11
   * updated with mainline

 * michael.vogt@ubuntu.com--2005/apt--ddtp--0--patch-12
   * added README.ddtp

 * michael.vogt@ubuntu.com--2005/apt--ddtp--0--patch-13
   * merged with apt--mvo

 * michael.vogt@ubuntu.com--2005/apt--ddtp--0--patch-14
   * added DDTP::URL-Remap. KILL THIS FEATURE once ddtp support is offical 

 * michael.vogt@ubuntu.com--2005/apt--ddtp--0--patch-15
   * remvoed the remap feature again, dosn't work anyway

 * otavio@debian.org--2005/apt--ddtp--0.6--base-0
   tag of apt@packages.debian.org/apt--main--0--patch-71

 * otavio@debian.org--2005/apt--ddtp--0.6--patch-1
   Port DDTP to APT 0.6 branch

 * otavio@debian.org--2005/apt--ddtp--0.6--patch-2
   Fix sintax error on apt-cache

 * otavio@debian.org--2005/apt--ddtp--0.6--patch-3
   Remove a unused var.

 * otavio@debian.org--2005/apt--ddtp--0.6--patch-4
   Fix problems due APT and structural changes.

 * otavio@debian.org--2005/apt--ddtp--0.6--patch-5
   Fix problems due APT and structural changes.

 * otavio@debian.org--2005/apt--ddtp--0.6--patch-6
   Sync with apt@packages.debian.org/apt--main--0--patch-74

 * otavio@debian.org--2005/apt--ddtp--0.6--patch-7
   Sync with apt@packages.debian.org/apt--main--0--patch-75

 * otavio@debian.org--2005/apt--ddtp--0.6--patch-8
   Sync with apt--main--0--patch-76

 * otavio@debian.org--2005/apt--ddtp--0.6--patch-9
   Remote a changelog entry added by mistake while merging.

 * otavio@debian.org--2005/apt--ddtp--0.6--patch-10
   Sync with apt--main--0--patch-78

 * otavio@debian.org--2005/apt--ddtp--0.6--patch-11
   Revert fixes changes to move these to apt--fixes--0 branch.

 * otavio@debian.org--2005/apt--ddtp--0.6--patch-12
   Another fix included here by mistake. Moving it to apt--fixes--0 branch.

 * otavio@debian.org--2005/apt--ddtp--0.6--patch-13
   Merge last changes from apt--main--0.

 * otavio@debian.org--2005/apt--ddtp--0.6--patch-14
   Add FindInCache method to skip the rebuild of cache every time.

 * otavio@debian.org--2005/apt--ddtp--0.6--patch-15
   Merge changes did by Michael Vogt to solve some rebuilding mistakes.

 * otavio@debian.org--2005/apt--ddtp--0.6--patch-16
   Does't show Description twice

 * otavio@debian.org--2005/apt--ddtp--0.6--patch-17
   Merge last fixes did by Michael but preserve my version of apt-cache.cc fix.

 * otavio@debian.org--2005/apt--ddtp--0.6--patch-18
   Revert changes did by mistake on translation files.

 * otavio@debian.org--2005/apt--ddtp--0.6--patch-19
   Merge last changes did from upstream side.

 * otavio@debian.org--2005/apt--ddtp--0.6--patch-20
   Sync with apt--main--0--patch-87
Michael Vogt преди 21 години
родител
ревизия
c511502fce

+ 8 - 0
BUGS

@@ -0,0 +1,8 @@
+
+DDTP problems:
+--------------
+- apt-get update clean the /var/lib/apt/lists dir 
+  from all Translation-$index that are not in the current
+  enviroment or Translations apt variable
+- there needs to be a list of locales (pt, sv, en) that need
+  both language and country code to get the right file

+ 74 - 0
README.ddtp

@@ -0,0 +1,74 @@
+TODO:
+- URL-Remap for the translation files (to hack around the problem that
+  they are not on any ftp server yet but only on http://ddtp.debian.org/)
+
+Here is the original announcement of the ddtp support:
+
+* To: debian-devel-announce@lists.debian.org
+* Subject: Translate files
+* From: Michael Bramer <grisu@debian.org>
+* Date: Sun, 6 Oct 2002 21:56:06 +0200
+* Mail-followup-to: debian-devel@lists.debian.org
+* Message-id: <20021006195605.GA30516@home.debsupport.de>
+* Old-return-path: <michael@home.debsupport.de>
+* User-agent: Mutt/1.3.28i
+
+Hello all
+
+After some discussion between Anthony Towns (a ftpmaster), Jason
+Gunthorpe (APT Developer) and some DDTP Coordinators we find a way to
+transfer the translated package descriptions from the archive to the
+user. 
+
+The translated descriptions need to be downloadable befor any
+installation process, like the other package meta information. We
+choose a new file per languages with all translated package
+descriptions. The package system can download one or more of this
+files at 'apt-get update' time and know the translations.
+
+The new files are names 'Translate-$lang' and the file have this
+rfc822-format:
+  Package: &lt;package-name&gt;
+  Description-md5: &lt;the md5 checksum of the english description&gt;
+  Description-$lang.$encoding: &lt;translated headline&gt;
+   &lt;translated section&gt;
+
+The encoding of the Description is 'UTF-8' in all languages normal.
+The files will be located at 'debian/dists/sid/main/i18n/' on the ftp
+server (for all architecture). In addition of the plain
+'Translate-$lang' file, there will be a 'gz' and a 'bz2' version and
+in future also the new incremental format version.
+
+The &lt;the md5 checksum of the english description&gt; is the md5 checksum
+of the full english description, without the 'Description: '-tag and
+with all spaces and newlines. Look at this example:
+ Description: XXX
+  YYY
+  .
+  ZZZ
+is md5(&quot;XXX\n YYY\n .\n ZZZ\n&quot;) (perl-syntax).
+
+
+A future APT version will download one or some 'Translate-$lang'
+file(s) at 'update'-time. After this download it show a translated
+description instead of the english form, if it found a translated
+description of the package with the right md5 chechsum. The enviroment
+of the user will controlled this process (LANG, LANGUAGE, LC_MESSAGES,
+etc). With this the package system will never show a outdated
+translation.
+
+The translations come all from the DDTP. A daily process on
+ddtp.debian.org make new 'Translated-$lang' files and a script on
+ftp-master request this files and move this to the debian archive.
+Now the first files are accessable at 
+	<a  href="http://ddtp.debian.org/pdesc/translatefiles/">http://ddtp.debian.org/pdesc/translatefiles/</a>
+
+If you found wrong translations, please read the guides on
+ddtp.debian.org, make a better translation and send this per mail to
+the DDTP server. Don't bug the package maintainer!
+
+Thanks
+Grisu
+-- 
+Michael Bramer  -  a Debian Linux Developer      <a  href="http://www.debsupport.de">http://www.debsupport.de</a>
+PGP: finger grisu@db.debian.org  -- Linux Sysadmin   -- Use Debian Linux

+ 29 - 0
apt-pkg/acquire-item.cc

@@ -308,6 +308,35 @@ void pkgAcqIndex::Done(string Message,unsigned long Size,string MD5,
    Mode = decompProg;
    Mode = decompProg;
 }
 }
 
 
+// AcqIndexTrans::pkgAcqIndexTrans - Constructor			/*{{{*/
+// ---------------------------------------------------------------------
+/* The Translation file is added to the queue */
+pkgAcqIndexTrans::pkgAcqIndexTrans(pkgAcquire *Owner,
+			    string URI,string URIDesc,string ShortDesc) :
+                      pkgAcqIndex(Owner, URI, URIDesc, ShortDesc, "", "")
+{
+}
+
+									/*}}}*/
+// AcqIndexTrans::Failed - Silence failure messages for missing files	/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void pkgAcqIndexTrans::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
+{
+   if (Cnf->LocalOnly == true || 
+       StringToBool(LookupTag(Message,"Transient-Failure"),false) == false)
+   {      
+      // Ignore this
+      Status = StatDone;
+      Complete = false;
+      Dequeue();
+      return;
+   }
+   
+   Item::Failed(Message,Cnf);
+}
+									/*}}}*/
+
 pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner,
 pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner,
 			     string URI,string URIDesc,string ShortDesc,
 			     string URI,string URIDesc,string ShortDesc,
 			     string MetaIndexURI, string MetaIndexURIDesc,
 			     string MetaIndexURI, string MetaIndexURIDesc,

+ 12 - 2
apt-pkg/acquire-item.h

@@ -9,8 +9,8 @@
    the Owner Acquire class. Derived classes will then call QueueURI to 
    the Owner Acquire class. Derived classes will then call QueueURI to 
    register all the URI's they wish to fetch at the initial moment.   
    register all the URI's they wish to fetch at the initial moment.   
    
    
-   Two item classes are provided to provide functionality for downloading
-   of Index files and downloading of Packages.
+   Three item classes are provided to provide functionality for
+   downloading of Index, Translation and Packages files.
    
    
    A Archive class is provided for downloading .deb files. It does Md5
    A Archive class is provided for downloading .deb files. It does Md5
    checking and source location as well as a retry algorithm.
    checking and source location as well as a retry algorithm.
@@ -107,6 +107,16 @@ class pkgAcqIndex : public pkgAcquire::Item
 	       string ShortDesct, string ExpectedMD5, string compressExt="");
 	       string ShortDesct, string ExpectedMD5, string compressExt="");
 };
 };
 
 
+// Item class for translated package index files
+class pkgAcqIndexTrans : public pkgAcqIndex
+{
+   public:
+  
+   virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
+   pkgAcqIndexTrans(pkgAcquire *Owner,string URI,string URIDesc,
+		    string ShortDesct);
+};
+
 struct IndexTarget
 struct IndexTarget
 {
 {
    string URI;
    string URI;

+ 82 - 1
apt-pkg/cacheiterators.h

@@ -99,7 +99,7 @@ class pkgCache::VerIterator
 {
 {
    Version *Ver;
    Version *Ver;
    pkgCache *Owner;
    pkgCache *Owner;
-   
+
    void _dummy();
    void _dummy();
    
    
    public:
    public:
@@ -128,6 +128,7 @@ class pkgCache::VerIterator
    inline const char *Section() const {return Ver->Section == 0?0:Owner->StrP + Ver->Section;};
    inline const char *Section() const {return Ver->Section == 0?0:Owner->StrP + Ver->Section;};
    inline const char *Arch() const {return Ver->Arch == 0?0:Owner->StrP + Ver->Arch;};
    inline const char *Arch() const {return Ver->Arch == 0?0:Owner->StrP + Ver->Arch;};
    inline PkgIterator ParentPkg() const {return PkgIterator(*Owner,Owner->PkgP + Ver->ParentPkg);};
    inline PkgIterator ParentPkg() const {return PkgIterator(*Owner,Owner->PkgP + Ver->ParentPkg);};
+   inline DescIterator DescriptionList() const;
    inline DepIterator DependsList() const;
    inline DepIterator DependsList() const;
    inline PrvIterator ProvidesList() const;
    inline PrvIterator ProvidesList() const;
    inline VerFileIterator FileList() const;
    inline VerFileIterator FileList() const;
@@ -148,6 +149,50 @@ class pkgCache::VerIterator
    };
    };
 };
 };
 
 
+// Description Iterator
+class pkgCache::DescIterator
+{
+   Description *Desc;
+   pkgCache *Owner;
+   
+   void _dummy();
+   
+   public:
+
+   // Iteration
+   void operator ++(int) {if (Desc != Owner->DescP) Desc = Owner->DescP + Desc->NextDesc;};
+   inline void operator ++() {operator ++(0);};
+   inline bool end() const {return Desc == Owner->DescP?true:false;};
+   inline void operator =(const DescIterator &B) {Desc = B.Desc; Owner = B.Owner;};
+   
+   // Comparison
+   inline bool operator ==(const DescIterator &B) const {return Desc == B.Desc;};
+   inline bool operator !=(const DescIterator &B) const {return Desc != B.Desc;};
+   int CompareDesc(const DescIterator &B) const;
+   
+   // Accessors
+   inline Description *operator ->() {return Desc;};
+   inline Description const *operator ->() const {return Desc;};
+   inline Description &operator *() {return *Desc;};
+   inline Description const &operator *() const {return *Desc;};
+   inline operator Description *() {return Desc == Owner->DescP?0:Desc;};
+   inline operator Description const *() const {return Desc == Owner->DescP?0:Desc;};
+   inline pkgCache *Cache() {return Owner;};
+      
+   inline const char *LanguageCode() const {return Owner->StrP + Desc->language_code;};
+   inline const char *md5() const {return Owner->StrP + Desc->md5sum;};
+   inline DescFileIterator FileList() const;
+   inline unsigned long Index() const {return Desc - Owner->DescP;};
+
+   inline DescIterator() : Desc(0), Owner(0) {};   
+   inline DescIterator(pkgCache &Owner,Description *Trg = 0) : Desc(Trg), 
+              Owner(&Owner) 
+   { 
+      if (Desc == 0)
+	 Desc = Owner.DescP;
+   };
+};
+
 // Dependency iterator
 // Dependency iterator
 class pkgCache::DepIterator
 class pkgCache::DepIterator
 {
 {
@@ -338,6 +383,38 @@ class pkgCache::VerFileIterator
    inline VerFileIterator(pkgCache &Owner,VerFile *Trg) : Owner(&Owner), FileP(Trg) {};
    inline VerFileIterator(pkgCache &Owner,VerFile *Trg) : Owner(&Owner), FileP(Trg) {};
 };
 };
 
 
+// Description File 
+class pkgCache::DescFileIterator
+{
+   pkgCache *Owner;
+   DescFile *FileP;
+
+   public:
+
+   // Iteration
+   void operator ++(int) {if (FileP != Owner->DescFileP) FileP = Owner->DescFileP + FileP->NextFile;};
+   inline void operator ++() {operator ++(0);};
+   inline bool end() const {return FileP == Owner->DescFileP?true:false;};
+
+   // Comparison
+   inline bool operator ==(const DescFileIterator &B) const {return FileP == B.FileP;};
+   inline bool operator !=(const DescFileIterator &B) const {return FileP != B.FileP;};
+			   
+   // Accessors
+   inline DescFile *operator ->() {return FileP;};
+   inline DescFile const *operator ->() const {return FileP;};
+   inline DescFile const &operator *() const {return *FileP;};
+   inline operator DescFile *() {return FileP == Owner->DescFileP?0:FileP;};
+   inline operator DescFile const *() const {return FileP == Owner->DescFileP?0:FileP;};
+   inline pkgCache *Cache() {return Owner;};
+  
+   inline PkgFileIterator File() const {return PkgFileIterator(*Owner,FileP->File + Owner->PkgFileP);};
+   inline unsigned long Index() const {return FileP - Owner->DescFileP;};
+      
+   inline DescFileIterator() : Owner(0), FileP(0) {};
+   inline DescFileIterator(pkgCache &Owner,DescFile *Trg) : Owner(&Owner), FileP(Trg) {};
+};
+
 // Inlined Begin functions cant be in the class because of order problems
 // Inlined Begin functions cant be in the class because of order problems
 inline pkgCache::VerIterator pkgCache::PkgIterator::VersionList() const
 inline pkgCache::VerIterator pkgCache::PkgIterator::VersionList() const
        {return VerIterator(*Owner,Owner->VerP + Pkg->VersionList);};
        {return VerIterator(*Owner,Owner->VerP + Pkg->VersionList);};
@@ -347,11 +424,15 @@ inline pkgCache::DepIterator pkgCache::PkgIterator::RevDependsList() const
        {return DepIterator(*Owner,Owner->DepP + Pkg->RevDepends,Pkg);};
        {return DepIterator(*Owner,Owner->DepP + Pkg->RevDepends,Pkg);};
 inline pkgCache::PrvIterator pkgCache::PkgIterator::ProvidesList() const
 inline pkgCache::PrvIterator pkgCache::PkgIterator::ProvidesList() const
        {return PrvIterator(*Owner,Owner->ProvideP + Pkg->ProvidesList,Pkg);};
        {return PrvIterator(*Owner,Owner->ProvideP + Pkg->ProvidesList,Pkg);};
+inline pkgCache::DescIterator pkgCache::VerIterator::DescriptionList() const
+       {return DescIterator(*Owner,Owner->DescP + Ver->DescriptionList);};
 inline pkgCache::PrvIterator pkgCache::VerIterator::ProvidesList() const
 inline pkgCache::PrvIterator pkgCache::VerIterator::ProvidesList() const
        {return PrvIterator(*Owner,Owner->ProvideP + Ver->ProvidesList,Ver);};
        {return PrvIterator(*Owner,Owner->ProvideP + Ver->ProvidesList,Ver);};
 inline pkgCache::DepIterator pkgCache::VerIterator::DependsList() const
 inline pkgCache::DepIterator pkgCache::VerIterator::DependsList() const
        {return DepIterator(*Owner,Owner->DepP + Ver->DependsList,Ver);};
        {return DepIterator(*Owner,Owner->DepP + Ver->DependsList,Ver);};
 inline pkgCache::VerFileIterator pkgCache::VerIterator::FileList() const
 inline pkgCache::VerFileIterator pkgCache::VerIterator::FileList() const
        {return VerFileIterator(*Owner,Owner->VerFileP + Ver->FileList);};
        {return VerFileIterator(*Owner,Owner->VerFileP + Ver->FileList);};
+inline pkgCache::DescFileIterator pkgCache::DescIterator::FileList() const
+       {return DescFileIterator(*Owner,Owner->DescFileP + Desc->FileList);};
 
 
 #endif
 #endif

+ 38 - 9
apt-pkg/cdrom.cc

@@ -30,12 +30,16 @@ using namespace std;
    search that short circuits when it his a package file in the dir.
    search that short circuits when it his a package file in the dir.
    This speeds it up greatly as the majority of the size is in the
    This speeds it up greatly as the majority of the size is in the
    binary-* sub dirs. */
    binary-* sub dirs. */
-bool pkgCdrom::FindPackages(string CD,vector<string> &List,
-			    vector<string> &SList, vector<string> &SigList,
+bool pkgCdrom::FindPackages(string CD,
+			    vector<string> &List,
+			    vector<string> &SList, 
+			    vector<string> &SigList,
+			    vector<string> &TransList,
 			    string &InfoDir, pkgCdromStatus *log,
 			    string &InfoDir, pkgCdromStatus *log,
 			    unsigned int Depth)
 			    unsigned int Depth)
 {
 {
    static ino_t Inodes[9];
    static ino_t Inodes[9];
+   DIR *D;
 
 
    // if we have a look we "pulse" now
    // if we have a look we "pulse" now
    if(log)
    if(log)
@@ -90,8 +94,28 @@ bool pkgCdrom::FindPackages(string CD,vector<string> &List,
       if (_config->FindB("APT::CDROM::Thorough",false) == false)
       if (_config->FindB("APT::CDROM::Thorough",false) == false)
 	 return true;
 	 return true;
    }
    }
+
+   // see if we find translatin indexes
+   if (stat("i18n",&Buf) == 0)
+   {
+      D = opendir("i18n");
+      for (struct dirent *Dir = readdir(D); Dir != 0; Dir = readdir(D))
+      {
+	 if(strstr(Dir->d_name,"Translation") != NULL) 
+	 {
+	    if (_config->FindB("Debug::aptcdrom",false) == true)
+	       std::clog << "found translations: " << Dir->d_name << "\n";
+	    string file = Dir->d_name;
+	    if(file.substr(file.size()-3,file.size()) == ".gz")
+	       file = file.substr(0,file.size()-3);
+	    TransList.push_back(CD+"i18n/"+ file);
+	 }
+      }
+      closedir(D);
+   }
+
    
    
-   DIR *D = opendir(".");
+   D = opendir(".");
    if (D == 0)
    if (D == 0)
       return _error->Errno("opendir","Unable to read %s",CD.c_str());
       return _error->Errno("opendir","Unable to read %s",CD.c_str());
    
    
@@ -127,7 +151,7 @@ bool pkgCdrom::FindPackages(string CD,vector<string> &List,
       Inodes[Depth] = Buf.st_ino;
       Inodes[Depth] = Buf.st_ino;
 
 
       // Descend
       // Descend
-      if (FindPackages(CD + Dir->d_name,List,SList,SigList,InfoDir,log,Depth+1) == false)
+      if (FindPackages(CD + Dir->d_name,List,SList,SigList,TransList,InfoDir,log,Depth+1) == false)
 	 break;
 	 break;
 
 
       if (chdir(CD.c_str()) != 0)
       if (chdir(CD.c_str()) != 0)
@@ -612,9 +636,10 @@ bool pkgCdrom::Add(pkgCdromStatus *log)
    vector<string> List;
    vector<string> List;
    vector<string> SourceList;
    vector<string> SourceList;
    vector<string> SigList;
    vector<string> SigList;
+   vector<string> TransList;
    string StartDir = SafeGetCWD();
    string StartDir = SafeGetCWD();
    string InfoDir;
    string InfoDir;
-   if (FindPackages(CDROM,List,SourceList, SigList,InfoDir,log) == false)
+   if (FindPackages(CDROM,List,SourceList, SigList,TransList,InfoDir,log) == false)
    {
    {
       log->Update("\n");
       log->Update("\n");
       return false;
       return false;
@@ -642,11 +667,13 @@ bool pkgCdrom::Add(pkgCdromStatus *log)
    DropRepeats(List,"Packages");
    DropRepeats(List,"Packages");
    DropRepeats(SourceList,"Sources");
    DropRepeats(SourceList,"Sources");
    DropRepeats(SigList,"Release.gpg");
    DropRepeats(SigList,"Release.gpg");
+   DropRepeats(TransList,"");
    if(log) {
    if(log) {
       msg.str("");
       msg.str("");
-      ioprintf(msg, _("Found %i package indexes, %i source indexes and "
-		      "%i signatures\n"), 
-	       List.size(), SourceList.size(), SigList.size());
+      ioprintf(msg, _("Found %i package indexes, %i source indexes, "
+		      "%i translation indexes and %i signatures\n"), 
+	       List.size(), SourceList.size(), TransList.size(),
+	       SigList.size());
       log->Update(msg.str(), STEP_SCAN);
       log->Update(msg.str(), STEP_SCAN);
    }
    }
 
 
@@ -736,8 +763,10 @@ bool pkgCdrom::Add(pkgCdromStatus *log)
    // Copy the package files to the state directory
    // Copy the package files to the state directory
    PackageCopy Copy;
    PackageCopy Copy;
    SourceCopy SrcCopy;
    SourceCopy SrcCopy;
+   TranslationsCopy TransCopy;
    if (Copy.CopyPackages(CDROM,Name,List, log) == false ||
    if (Copy.CopyPackages(CDROM,Name,List, log) == false ||
-       SrcCopy.CopyPackages(CDROM,Name,SourceList, log) == false)
+       SrcCopy.CopyPackages(CDROM,Name,SourceList, log) == false ||
+       TransCopy.CopyTranslations(CDROM,Name,TransList, log) == false)
       return false;
       return false;
 
 
    // reduce the List so that it takes less space in sources.list
    // reduce the List so that it takes less space in sources.list

+ 5 - 2
apt-pkg/cdrom.h

@@ -50,8 +50,11 @@ class pkgCdrom
    };
    };
 
 
 
 
-   bool FindPackages(string CD,vector<string> &List,
-		     vector<string> &SList, vector<string> &SigList,
+   bool FindPackages(string CD,
+		     vector<string> &List,
+		     vector<string> &SList, 
+		     vector<string> &SigList,
+		     vector<string> &TransList,
 		     string &InfoDir, pkgCdromStatus *log,
 		     string &InfoDir, pkgCdromStatus *log,
 		     unsigned int Depth = 0);
 		     unsigned int Depth = 0);
    bool DropBinaryArch(vector<string> &List);
    bool DropBinaryArch(vector<string> &List);

+ 44 - 1
apt-pkg/contrib/strutl.cc

@@ -32,12 +32,55 @@
 #include <regex.h>
 #include <regex.h>
 #include <errno.h>
 #include <errno.h>
 #include <stdarg.h>
 #include <stdarg.h>
+#include <iconv.h>
 
 
 #include "config.h"
 #include "config.h"
 
 
 using namespace std;
 using namespace std;
 									/*}}}*/
 									/*}}}*/
 
 
+// UTF8ToCodeset - Convert some UTF-8 string for some codeset   	/*{{{*/
+// ---------------------------------------------------------------------
+/* This is handy to use before display some information for enduser  */
+bool UTF8ToCodeset(const char *codeset, const string &orig, string *dest)
+{
+  iconv_t cd;
+  const char *inbuf;
+  char *inptr, *outbuf, *outptr;
+  size_t insize, outsize;
+  
+  cd = iconv_open(codeset, "UTF-8");
+  if (cd == (iconv_t)(-1)) {
+     // Something went wrong
+     if (errno == EINVAL)
+	_error->Error("conversion from 'UTF-8' to '%s' not available",
+               codeset);
+     else
+	perror("iconv_open");
+     
+     // Clean the destination string
+     *dest = "";
+     
+     return false;
+  }
+
+  insize = outsize = orig.size();
+  inbuf = orig.data();
+  inptr = (char *)inbuf;
+  outbuf = new char[insize+1];
+  outptr = outbuf;
+
+  iconv(cd, &inptr, &insize, &outptr, &outsize);
+  *outptr = '\0';
+
+  *dest = outbuf;
+  delete[] outbuf;
+  
+  iconv_close(cd);
+
+  return true;
+}
+									/*}}}*/
 // strstrip - Remove white space from the front and back of a string	/*{{{*/
 // strstrip - Remove white space from the front and back of a string	/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* This is handy to use when parsing a file. It also removes \n's left 
 /* This is handy to use when parsing a file. It also removes \n's left 
@@ -357,7 +400,7 @@ string URItoFileName(string URI)
    U.Access = "";
    U.Access = "";
    
    
    // "\x00-\x20{}|\\\\^\\[\\]<>\"\x7F-\xFF";
    // "\x00-\x20{}|\\\\^\\[\\]<>\"\x7F-\xFF";
-   URI = QuoteString(U,"\\|{}[]<>\"^~_=!@#$%^&*");
+   URI = QuoteString(U,"\\|{}[]<>\"^~=!@#$%^&*");
    string::iterator J = URI.begin();
    string::iterator J = URI.begin();
    for (; J != URI.end(); J++)
    for (; J != URI.end(); J++)
       if (*J == '/') 
       if (*J == '/') 

+ 2 - 1
apt-pkg/contrib/strutl.h

@@ -38,7 +38,8 @@ using std::ostream;
 #define APT_FORMAT2
 #define APT_FORMAT2
 #define APT_FORMAT3
 #define APT_FORMAT3
 #endif    
 #endif    
-    
+
+bool UTF8ToCodeset(const char *codeset, const string &orig, string *dest);
 char *_strstrip(char *String);
 char *_strstrip(char *String);
 char *_strtabexpand(char *String,size_t Len);
 char *_strtabexpand(char *String,size_t Len);
 bool ParseQuoteWord(const char *&String,string &Res);
 bool ParseQuoteWord(const char *&String,string &Res);

+ 174 - 0
apt-pkg/deb/debindexfile.cc

@@ -320,6 +320,170 @@ pkgCache::PkgFileIterator debPackagesIndex::FindInCache(pkgCache &Cache) const
 }
 }
 									/*}}}*/
 									/*}}}*/
 
 
+// TranslationsIndex::debTranslationsIndex - Contructor			/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+debTranslationsIndex::debTranslationsIndex(string URI,string Dist,string Section) : 
+                  pkgIndexFile(true), URI(URI), Dist(Dist), Section(Section)
+{
+}
+									/*}}}*/
+// TranslationIndex::Trans* - Return the URI to the translation files	/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+inline string debTranslationsIndex::IndexFile(const char *Type) const
+{
+   return _config->FindDir("Dir::State::lists") + URItoFileName(IndexURI(Type));
+}
+string debTranslationsIndex::IndexURI(const char *Type) const
+{
+   string Res;
+   if (Dist[Dist.size() - 1] == '/')
+   {
+      if (Dist != "/")
+	 Res = URI + Dist;
+      else 
+	 Res = URI;
+   }
+   else
+      Res = URI + "dists/" + Dist + '/' + Section +
+      "/i18n/Translation-";
+   
+   Res += Type;
+   return Res;
+}
+									/*}}}*/
+// TranslationsIndex::GetIndexes - Fetch the index files		/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool debTranslationsIndex::GetIndexes(pkgAcquire *Owner) const
+{
+   if (TranslationsAvailable()) {
+     string TranslationFile = "Translation-" + LanguageCode();
+     new pkgAcqIndexTrans(Owner, IndexURI(LanguageCode().c_str()),
+			  Info(TranslationFile.c_str()),
+			  TranslationFile);
+   }
+
+   return true;
+}
+									/*}}}*/
+// TranslationsIndex::Describe - Give a descriptive path to the index	/*{{{*/
+// ---------------------------------------------------------------------
+/* This should help the user find the index in the sources.list and
+   in the filesystem for problem solving */
+string debTranslationsIndex::Describe(bool Short) const
+{   
+   char S[300];
+   if (Short == true)
+      snprintf(S,sizeof(S),"%s",Info(TranslationFile().c_str()).c_str());
+   else
+      snprintf(S,sizeof(S),"%s (%s)",Info(TranslationFile().c_str()).c_str(),
+	       IndexFile(LanguageCode().c_str()).c_str());
+   return S;
+}
+									/*}}}*/
+// TranslationsIndex::Info - One liner describing the index URI		/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+string debTranslationsIndex::Info(const char *Type) const 
+{
+   string Info = ::URI::SiteOnly(URI) + ' ';
+   if (Dist[Dist.size() - 1] == '/')
+   {
+      if (Dist != "/")
+	 Info += Dist;
+   }
+   else
+      Info += Dist + '/' + Section;   
+   Info += " ";
+   Info += Type;
+   return Info;
+}
+									/*}}}*/
+bool debTranslationsIndex::HasPackages() const
+{
+   if(!TranslationsAvailable())
+      return false;
+   
+   return FileExists(IndexFile(LanguageCode().c_str()));
+}
+
+// TranslationsIndex::Exists - Check if the index is available		/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool debTranslationsIndex::Exists() const
+{
+   return FileExists(IndexFile(LanguageCode().c_str()));
+}
+									/*}}}*/
+// TranslationsIndex::Size - Return the size of the index		/*{{{*/
+// ---------------------------------------------------------------------
+/* This is really only used for progress reporting. */
+unsigned long debTranslationsIndex::Size() const
+{
+   struct stat S;
+   if (stat(IndexFile(LanguageCode().c_str()).c_str(),&S) != 0)
+      return 0;
+   return S.st_size;
+}
+									/*}}}*/
+// TranslationsIndex::Merge - Load the index file into a cache		/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const
+{
+   // Check the translation file, if in use
+   string TranslationFile = IndexFile(LanguageCode().c_str());
+   if (TranslationsAvailable() && FileExists(TranslationFile))
+   {
+     FileFd Trans(TranslationFile,FileFd::ReadOnly);
+     debListParser TransParser(&Trans);
+     if (_error->PendingError() == true)
+       return false;
+     
+     Prog.SubProgress(0, Info(TranslationFile.c_str()));
+     if (Gen.SelectFile(TranslationFile,string(),*this) == false)
+       return _error->Error("Problem with SelectFile %s",TranslationFile.c_str());
+
+     // Store the IMS information
+     pkgCache::PkgFileIterator TransFile = Gen.GetCurFile();
+     struct stat TransSt;
+     if (fstat(Trans.Fd(),&TransSt) != 0)
+       return _error->Errno("fstat","Failed to stat");
+     TransFile->Size = TransSt.st_size;
+     TransFile->mtime = TransSt.st_mtime;
+   
+     if (Gen.MergeList(TransParser) == false)
+       return _error->Error("Problem with MergeList %s",TranslationFile.c_str());
+   }
+
+   return true;
+}
+									/*}}}*/
+// TranslationsIndex::FindInCache - Find this index				/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+pkgCache::PkgFileIterator debTranslationsIndex::FindInCache(pkgCache &Cache) const
+{
+   string FileName = IndexFile(LanguageCode().c_str());
+   
+   pkgCache::PkgFileIterator File = Cache.FileBegin();
+   for (; File.end() == false; File++)
+   {
+      if (FileName != File.FileName())
+	 continue;
+
+      struct stat St;
+      if (stat(File.FileName(),&St) != 0)
+	 return pkgCache::PkgFileIterator(Cache);
+      if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
+	 return pkgCache::PkgFileIterator(Cache);
+      return File;
+   }   
+   return File;
+}
+									/*}}}*/
 // StatusIndex::debStatusIndex - Constructor				/*{{{*/
 // StatusIndex::debStatusIndex - Constructor				/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
@@ -416,6 +580,11 @@ class debIFTypePkg : public pkgIndexFile::Type
    };
    };
    debIFTypePkg() {Label = "Debian Package Index";};
    debIFTypePkg() {Label = "Debian Package Index";};
 };
 };
+class debIFTypeTrans : public debIFTypePkg
+{
+   public:
+   debIFTypeTrans() {Label = "Debian Translation Index";};
+};
 class debIFTypeStatus : public pkgIndexFile::Type
 class debIFTypeStatus : public pkgIndexFile::Type
 {
 {
    public:
    public:
@@ -428,6 +597,7 @@ class debIFTypeStatus : public pkgIndexFile::Type
 };
 };
 static debIFTypeSrc _apt_Src;
 static debIFTypeSrc _apt_Src;
 static debIFTypePkg _apt_Pkg;
 static debIFTypePkg _apt_Pkg;
+static debIFTypeTrans _apt_Trans;
 static debIFTypeStatus _apt_Status;
 static debIFTypeStatus _apt_Status;
 
 
 const pkgIndexFile::Type *debSourcesIndex::GetType() const
 const pkgIndexFile::Type *debSourcesIndex::GetType() const
@@ -438,6 +608,10 @@ const pkgIndexFile::Type *debPackagesIndex::GetType() const
 {
 {
    return &_apt_Pkg;
    return &_apt_Pkg;
 }
 }
+const pkgIndexFile::Type *debTranslationsIndex::GetType() const
+{
+   return &_apt_Trans;
+}
 const pkgIndexFile::Type *debStatusIndex::GetType() const
 const pkgIndexFile::Type *debStatusIndex::GetType() const
 {
 {
    return &_apt_Status;
    return &_apt_Status;

+ 30 - 0
apt-pkg/deb/debindexfile.h

@@ -74,6 +74,36 @@ class debPackagesIndex : public pkgIndexFile
    debPackagesIndex(string URI,string Dist,string Section,bool Trusted);
    debPackagesIndex(string URI,string Dist,string Section,bool Trusted);
 };
 };
 
 
+class debTranslationsIndex : public pkgIndexFile
+{
+   string URI;
+   string Dist;
+   string Section;
+   
+   string Info(const char *Type) const;
+   string IndexFile(const char *Type) const;
+   string IndexURI(const char *Type) const;
+
+   inline string TranslationFile() const {return "Translation-" + LanguageCode();};
+
+   public:
+   
+   virtual const Type *GetType() const;
+
+   // Interface for acquire
+   virtual string Describe(bool Short) const;   
+   virtual bool GetIndexes(pkgAcquire *Owner) const;
+   
+   // Interface for the Cache Generator
+   virtual bool Exists() const;
+   virtual bool HasPackages() const;
+   virtual unsigned long Size() const;
+   virtual bool Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const;
+   virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const;
+
+   debTranslationsIndex(string URI,string Dist,string Section);
+};
+
 class debSourcesIndex : public pkgIndexFile
 class debSourcesIndex : public pkgIndexFile
 {
 {
    string URI;
    string URI;

+ 43 - 0
apt-pkg/deb/deblistparser.cc

@@ -15,6 +15,7 @@
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/crc-16.h>
 #include <apt-pkg/crc-16.h>
+#include <apt-pkg/md5.h>
 
 
 #include <ctype.h>
 #include <ctype.h>
 
 
@@ -117,6 +118,48 @@ bool debListParser::NewVersion(pkgCache::VerIterator Ver)
    return true;
    return true;
 }
 }
 									/*}}}*/
 									/*}}}*/
+// ListParser::Description - Return the description string		/*{{{*/
+// ---------------------------------------------------------------------
+/* This is to return the string describing the package in debian
+   form. If this returns the blank string then the entry is assumed to
+   only describe package properties */
+string debListParser::Description()
+{
+   if (DescriptionLanguage().empty())
+      return Section.FindS("Description");
+   else
+      return Section.FindS(("Description-" + pkgIndexFile::LanguageCode()).c_str());
+}
+                                                                        /*}}}*/
+// ListParser::DescriptionLanguage - Return the description lang string	/*{{{*/
+// ---------------------------------------------------------------------
+/* This is to return the string describing the language of
+   description. If this returns the blank string then the entry is
+   assumed to describe original description. */
+string debListParser::DescriptionLanguage()
+{
+   return Section.FindS("Description").empty() ? pkgIndexFile::LanguageCode() : "";
+}
+                                                                        /*}}}*/
+// ListParser::Description - Return the description_md5 MD5SumValue	/*{{{*/
+// ---------------------------------------------------------------------
+/* This is to return the md5 string to allow the check if it is the right
+   description. If no Description-md5 is found in the section it will be
+   calculated.
+ */
+MD5SumValue debListParser::Description_md5()
+{
+   string value = Section.FindS("Description-md5");
+
+   if (value.empty()) 
+   {
+      MD5Summation md5;
+      md5.Add((Description() + "\n").c_str());
+      return md5.Result();
+   } else
+      return MD5SumValue(value);
+}
+                                                                        /*}}}*/
 // ListParser::UsePackage - Update a package structure			/*{{{*/
 // ListParser::UsePackage - Update a package structure			/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* This is called to update the package with any new information 
 /* This is called to update the package with any new information 

+ 4 - 0
apt-pkg/deb/deblistparser.h

@@ -12,6 +12,7 @@
 #define PKGLIB_DEBLISTPARSER_H
 #define PKGLIB_DEBLISTPARSER_H
 
 
 #include <apt-pkg/pkgcachegen.h>
 #include <apt-pkg/pkgcachegen.h>
+#include <apt-pkg/indexfile.h>
 #include <apt-pkg/tagfile.h>
 #include <apt-pkg/tagfile.h>
 
 
 class debListParser : public pkgCacheGenerator::ListParser
 class debListParser : public pkgCacheGenerator::ListParser
@@ -47,6 +48,9 @@ class debListParser : public pkgCacheGenerator::ListParser
    virtual string Package();
    virtual string Package();
    virtual string Version();
    virtual string Version();
    virtual bool NewVersion(pkgCache::VerIterator Ver);
    virtual bool NewVersion(pkgCache::VerIterator Ver);
+   virtual string Description();
+   virtual string DescriptionLanguage();
+   virtual MD5SumValue Description_md5();
    virtual unsigned short VersionHash();
    virtual unsigned short VersionHash();
    virtual bool UsePackage(pkgCache::PkgIterator Pkg,
    virtual bool UsePackage(pkgCache::PkgIterator Pkg,
 			   pkgCache::VerIterator Ver);
 			   pkgCache::VerIterator Ver);

+ 14 - 1
apt-pkg/deb/debmetaindex.cc

@@ -157,6 +157,14 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool GetAll) const
 		     ComputeIndexTargets(),
 		     ComputeIndexTargets(),
 		     new indexRecords (Dist));
 		     new indexRecords (Dist));
 
 
+   // Queue the translations
+   for (vector<const debSectionEntry *>::const_iterator I = SectionEntries.begin(); 
+	I != SectionEntries.end(); I++) {
+
+      debTranslationsIndex i = debTranslationsIndex(URI,Dist,(*I)->Section);
+      i.GetIndexes(Owner);
+   }
+
    return true;
    return true;
 }
 }
 
 
@@ -177,11 +185,16 @@ vector <pkgIndexFile *> *debReleaseIndex::GetIndexFiles()
 
 
    Indexes = new vector <pkgIndexFile*>;
    Indexes = new vector <pkgIndexFile*>;
    for (vector<const debSectionEntry *>::const_iterator I = SectionEntries.begin(); 
    for (vector<const debSectionEntry *>::const_iterator I = SectionEntries.begin(); 
-	I != SectionEntries.end(); I++)
+	I != SectionEntries.end(); I++) {
       if ((*I)->IsSrc)
       if ((*I)->IsSrc)
          Indexes->push_back(new debSourcesIndex (URI, Dist, (*I)->Section, IsTrusted()));
          Indexes->push_back(new debSourcesIndex (URI, Dist, (*I)->Section, IsTrusted()));
       else 
       else 
+      {
          Indexes->push_back(new debPackagesIndex (URI, Dist, (*I)->Section, IsTrusted()));
          Indexes->push_back(new debPackagesIndex (URI, Dist, (*I)->Section, IsTrusted()));
+	 Indexes->push_back(new debTranslationsIndex(URI, Dist, (*I)->Section));
+      }
+   }
+
    return Indexes;
    return Indexes;
 }
 }
 
 

+ 21 - 2
apt-pkg/deb/debrecords.cc

@@ -12,7 +12,9 @@
 #pragma implementation "apt-pkg/debrecords.h"
 #pragma implementation "apt-pkg/debrecords.h"
 #endif
 #endif
 #include <apt-pkg/debrecords.h>
 #include <apt-pkg/debrecords.h>
+#include <apt-pkg/strutl.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>
+#include <langinfo.h>
 									/*}}}*/
 									/*}}}*/
 
 
 // RecordParser::debRecordParser - Constructor				/*{{{*/
 // RecordParser::debRecordParser - Constructor				/*{{{*/
@@ -30,6 +32,10 @@ debRecordParser::debRecordParser(string FileName,pkgCache &Cache) :
 bool debRecordParser::Jump(pkgCache::VerFileIterator const &Ver)
 bool debRecordParser::Jump(pkgCache::VerFileIterator const &Ver)
 {
 {
    return Tags.Jump(Section,Ver->Offset);
    return Tags.Jump(Section,Ver->Offset);
+}
+bool debRecordParser::Jump(pkgCache::DescFileIterator const &Desc)
+{
+   return Tags.Jump(Section,Desc->Offset);
 }
 }
 									/*}}}*/
 									/*}}}*/
 // RecordParser::FileName - Return the archive filename on the site	/*{{{*/
 // RecordParser::FileName - Return the archive filename on the site	/*{{{*/
@@ -77,7 +83,7 @@ string debRecordParser::Maintainer()
 /* */
 /* */
 string debRecordParser::ShortDesc()
 string debRecordParser::ShortDesc()
 {
 {
-   string Res = Section.FindS("Description");
+   string Res = LongDesc();
    string::size_type Pos = Res.find('\n');
    string::size_type Pos = Res.find('\n');
    if (Pos == string::npos)
    if (Pos == string::npos)
       return Res;
       return Res;
@@ -89,7 +95,20 @@ string debRecordParser::ShortDesc()
 /* */
 /* */
 string debRecordParser::LongDesc()
 string debRecordParser::LongDesc()
 {
 {
-   return Section.FindS("Description");
+  string orig, dest;
+  char *codeset = nl_langinfo(CODESET);
+
+  if (!Section.FindS("Description").empty())
+     orig = Section.FindS("Description").c_str();
+  else 
+     orig = Section.FindS(("Description-" + pkgIndexFile::LanguageCode()).c_str()).c_str();
+
+  if (strcmp(codeset,"UTF-8") != 0) {
+     UTF8ToCodeset(codeset, orig, &dest);
+     orig = dest;
+   }    
+  
+   return orig;
 }
 }
 									/*}}}*/
 									/*}}}*/
 // RecordParser::SourcePkg - Return the source package name if any	/*{{{*/
 // RecordParser::SourcePkg - Return the source package name if any	/*{{{*/

+ 2 - 0
apt-pkg/deb/debrecords.h

@@ -19,6 +19,7 @@
 #endif 
 #endif 
 
 
 #include <apt-pkg/pkgrecords.h>
 #include <apt-pkg/pkgrecords.h>
+#include <apt-pkg/indexfile.h>
 #include <apt-pkg/tagfile.h>
 #include <apt-pkg/tagfile.h>
 
 
 class debRecordParser : public pkgRecords::Parser
 class debRecordParser : public pkgRecords::Parser
@@ -30,6 +31,7 @@ class debRecordParser : public pkgRecords::Parser
    protected:
    protected:
    
    
    virtual bool Jump(pkgCache::VerFileIterator const &Ver);
    virtual bool Jump(pkgCache::VerFileIterator const &Ver);
+   virtual bool Jump(pkgCache::DescFileIterator const &Desc);
    
    
    public:
    public:
 
 

+ 180 - 3
apt-pkg/indexcopy.cc

@@ -32,6 +32,8 @@
 
 
 using namespace std;
 using namespace std;
 
 
+
+
 // IndexCopy::CopyPackages - Copy the package files from the CD		/*{{{*/
 // IndexCopy::CopyPackages - Copy the package files from the CD		/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
@@ -512,10 +514,10 @@ bool SourceCopy::RewriteEntry(FILE *Target,string File)
    fputc('\n',Target);
    fputc('\n',Target);
    return true;
    return true;
 }
 }
-
-
 									/*}}}*/
 									/*}}}*/
-
+// SigVerify::Verify - Verify a files md5sum against its metaindex     	/*{{{*/
+// ---------------------------------------------------------------------
+/* */
 bool SigVerify::Verify(string prefix, string file, indexRecords *MetaIndex)
 bool SigVerify::Verify(string prefix, string file, indexRecords *MetaIndex)
 {
 {
    const indexRecords::checkSum *Record = MetaIndex->Lookup(file);
    const indexRecords::checkSum *Record = MetaIndex->Lookup(file);
@@ -670,3 +672,178 @@ bool SigVerify::CopyAndVerify(string CDROM,string Name,vector<string> &SigList,
 
 
    return true;
    return true;
 }
 }
+
+
+bool TranslationsCopy::CopyTranslations(string CDROM,string Name,vector<string> &List,
+			     pkgCdromStatus *log)
+{
+   OpProgress *Progress = NULL;
+   if (List.size() == 0)
+      return true;
+   
+   if(log) 
+      Progress = log->GetOpProgress();
+   
+   bool Debug = _config->FindB("Debug::aptcdrom",false);
+   
+   // Prepare the progress indicator
+   unsigned long TotalSize = 0;
+   for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
+   {
+      struct stat Buf;
+      if (stat(string(*I).c_str(),&Buf) != 0 &&
+	  stat(string(*I + ".gz").c_str(),&Buf) != 0)
+	 return _error->Errno("stat","Stat failed for %s",
+			      string(*I).c_str());
+      TotalSize += Buf.st_size;
+   }	
+
+   unsigned long CurrentSize = 0;
+   unsigned int NotFound = 0;
+   unsigned int WrongSize = 0;
+   unsigned int Packages = 0;
+   for (vector<string>::iterator I = List.begin(); I != List.end(); I++)
+   {      
+      string OrigPath = string(*I,CDROM.length());
+      unsigned long FileSize = 0;
+      
+      // Open the package file
+      FileFd Pkg;
+      if (FileExists(*I) == true)
+      {
+	 Pkg.Open(*I,FileFd::ReadOnly);
+	 FileSize = Pkg.Size();
+      }      
+      else
+      {
+	 FileFd From(*I + ".gz",FileFd::ReadOnly);
+	 if (_error->PendingError() == true)
+	    return false;
+	 FileSize = From.Size();
+	 
+	 // Get a temp file
+	 FILE *tmp = tmpfile();
+	 if (tmp == 0)
+	    return _error->Errno("tmpfile","Unable to create a tmp file");
+	 Pkg.Fd(dup(fileno(tmp)));
+	 fclose(tmp);
+	 
+	 // Fork gzip
+	 pid_t Process = fork();
+	 if (Process < 0)
+	    return _error->Errno("fork","Couldn't fork gzip");
+	 
+	 // The child
+	 if (Process == 0)
+	 {	    
+	    dup2(From.Fd(),STDIN_FILENO);
+	    dup2(Pkg.Fd(),STDOUT_FILENO);
+	    SetCloseExec(STDIN_FILENO,false);
+	    SetCloseExec(STDOUT_FILENO,false);
+	    
+	    const char *Args[3];
+	    string Tmp =  _config->Find("Dir::bin::gzip","gzip");
+	    Args[0] = Tmp.c_str();
+	    Args[1] = "-d";
+	    Args[2] = 0;
+	    execvp(Args[0],(char **)Args);
+	    exit(100);
+	 }
+	 
+	 // Wait for gzip to finish
+	 if (ExecWait(Process,_config->Find("Dir::bin::gzip","gzip").c_str(),false) == false)
+	    return _error->Error("gzip failed, perhaps the disk is full.");
+	 
+	 Pkg.Seek(0);
+      }
+      pkgTagFile Parser(&Pkg);
+      if (_error->PendingError() == true)
+	 return false;
+      
+      // Open the output file
+      char S[400];
+      snprintf(S,sizeof(S),"cdrom:[%s]/%s",Name.c_str(),
+	       (*I).c_str() + CDROM.length());
+      string TargetF = _config->FindDir("Dir::State::lists") + "partial/";
+      TargetF += URItoFileName(S);
+      if (_config->FindB("APT::CDROM::NoAct",false) == true)
+	 TargetF = "/dev/null";
+      FileFd Target(TargetF,FileFd::WriteEmpty);
+      FILE *TargetFl = fdopen(dup(Target.Fd()),"w");
+      if (_error->PendingError() == true)
+	 return false;
+      if (TargetFl == 0)
+	 return _error->Errno("fdopen","Failed to reopen fd");
+      
+      // Setup the progress meter
+      if(Progress)
+	 Progress->OverallProgress(CurrentSize,TotalSize,FileSize,
+				   string("Reading Translation Indexes"));
+
+      // Parse
+      if(Progress)
+	 Progress->SubProgress(Pkg.Size());
+      pkgTagSection Section;
+      this->Section = &Section;
+      string Prefix;
+      unsigned long Hits = 0;
+      unsigned long Chop = 0;
+      while (Parser.Step(Section) == true)
+      {
+	 if(Progress)
+	    Progress->Progress(Parser.Offset());
+
+	 const char *Start;
+	 const char *Stop;
+	 Section.GetSection(Start,Stop);
+	 fwrite(Start,Stop-Start, 1, TargetFl);
+	 fputc('\n',TargetFl);
+
+	 Packages++;
+	 Hits++;
+      }
+      fclose(TargetFl);
+
+      if (Debug == true)
+	 cout << " Processed by using Prefix '" << Prefix << "' and chop " << Chop << endl;
+	 
+      if (_config->FindB("APT::CDROM::NoAct",false) == false)
+      {
+	 // Move out of the partial directory
+	 Target.Close();
+	 string FinalF = _config->FindDir("Dir::State::lists");
+	 FinalF += URItoFileName(S);
+	 if (rename(TargetF.c_str(),FinalF.c_str()) != 0)
+	    return _error->Errno("rename","Failed to rename");
+      }
+      
+      
+      CurrentSize += FileSize;
+   }   
+   if(Progress)
+      Progress->Done();
+   
+   // Some stats
+   if(log) {
+      stringstream msg;
+      if(NotFound == 0 && WrongSize == 0)
+	 ioprintf(msg, _("Wrote %i records.\n"), Packages);
+      else if (NotFound != 0 && WrongSize == 0)
+	 ioprintf(msg, _("Wrote %i records with %i missing files.\n"), 
+		  Packages, NotFound);
+      else if (NotFound == 0 && WrongSize != 0)
+	 ioprintf(msg, _("Wrote %i records with %i mismatched files\n"), 
+		  Packages, WrongSize);
+      if (NotFound != 0 && WrongSize != 0)
+	 ioprintf(msg, _("Wrote %i records with %i missing files and %i mismatched files\n"), Packages, NotFound, WrongSize);
+   }
+   
+   if (Packages == 0)
+      _error->Warning("No valid records were found.");
+
+   if (NotFound + WrongSize > 10)
+      _error->Warning("Alot of entries were discarded, something may be wrong.\n");
+   
+
+   return true;
+}

+ 13 - 0
apt-pkg/indexcopy.h

@@ -70,6 +70,17 @@ class SourceCopy : public IndexCopy
    public:
    public:
 };
 };
 
 
+class TranslationsCopy
+{
+   protected:
+   pkgTagSection *Section;
+
+   public:
+   bool CopyTranslations(string CDROM,string Name,vector<string> &List,
+			 pkgCdromStatus *log);
+};
+
+
 class SigVerify 
 class SigVerify 
 {
 {
    bool Verify(string prefix,string file, indexRecords *records);
    bool Verify(string prefix,string file, indexRecords *records);
@@ -81,4 +92,6 @@ class SigVerify
 		      vector<string> PkgList,vector<string> SrcList);
 		      vector<string> PkgList,vector<string> SrcList);
 };
 };
 
 
+
+
 #endif
 #endif

+ 60 - 0
apt-pkg/indexfile.cc

@@ -12,8 +12,11 @@
 #pragma implementation "apt-pkg/indexfile.h"
 #pragma implementation "apt-pkg/indexfile.h"
 #endif
 #endif
 
 
+#include <apt-pkg/configuration.h>
 #include <apt-pkg/indexfile.h>
 #include <apt-pkg/indexfile.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>
+
+#include <clocale>
 									/*}}}*/
 									/*}}}*/
 
 
 // Global list of Item supported
 // Global list of Item supported
@@ -67,3 +70,60 @@ string pkgIndexFile::SourceInfo(pkgSrcRecords::Parser const &Record,
    return string();
    return string();
 }
 }
 									/*}}}*/
 									/*}}}*/
+// IndexFile::TranslationsAvailable - Check if will use Translation    /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool pkgIndexFile::TranslationsAvailable()
+{
+  const string Translation = _config->Find("APT::Acquire::Translation");
+  
+  if (Translation.compare("none") != 0)
+    return CheckLanguageCode(LanguageCode().c_str());
+  else
+    return false;
+}
+									/*}}}*/
+// IndexFile::CheckLanguageCode - Check the Language Code   	        /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+/* common cases: de_DE, de_DE@euro, de_DE.UTF-8, de_DE.UTF-8@euro,
+                 de_DE.ISO8859-1, tig_ER
+                 more in /etc/gdm/locale.conf 
+*/
+
+bool pkgIndexFile::CheckLanguageCode(const char *Lang)
+{
+  if (strlen(Lang) == 2 || (strlen(Lang) == 5 && Lang[2] == '_'))
+    return true;
+
+  if (strcmp(Lang,"C") != 0)
+    _error->Warning("Wrong language code %s", Lang);
+
+  return false;
+}
+									/*}}}*/
+// IndexFile::LanguageCode - Return the Language Code            	/*{{{*/
+// ---------------------------------------------------------------------
+/* return the language code */
+string pkgIndexFile::LanguageCode()
+{
+  const string Translation = _config->Find("APT::Acquire::Translation");
+
+  if (Translation.compare("environment") == 0) 
+  {
+     string lang = std::setlocale(LC_MESSAGES,NULL);
+
+     // FIXME: this needs to be added
+     // we have a mapping of the language codes that contains all the language
+     // codes that need the country code as well 
+     // (like pt_BR, pt_PT, sv_SE, zh_*, en_*)
+
+     if(lang.size() > 2)
+	return lang.substr(0,2);
+     else
+	return lang;
+  }
+  else 
+     return Translation;
+}
+									/*}}}*/

+ 6 - 1
apt-pkg/indexfile.h

@@ -5,10 +5,11 @@
 
 
    Index File - Abstraction for an index of archive/source file.
    Index File - Abstraction for an index of archive/source file.
    
    
-   There are 3 primary sorts of index files, all represented by this 
+   There are 4 primary sorts of index files, all represented by this 
    class:
    class:
    
    
    Binary index files 
    Binary index files 
+   Binary translation files 
    Bianry index files decribing the local system
    Bianry index files decribing the local system
    Source index files
    Source index files
    
    
@@ -80,6 +81,10 @@ class pkgIndexFile
    virtual bool MergeFileProvides(pkgCacheGenerator &/*Gen*/,OpProgress &/*Prog*/) const {return true;};
    virtual bool MergeFileProvides(pkgCacheGenerator &/*Gen*/,OpProgress &/*Prog*/) const {return true;};
    virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const;
    virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const;
 
 
+   static bool TranslationsAvailable();
+   static bool CheckLanguageCode(const char *Lang);
+   static string LanguageCode();
+
    bool IsTrusted() const { return Trusted; };
    bool IsTrusted() const { return Trusted; };
    
    
    pkgIndexFile(bool Trusted): Trusted(Trusted) {};
    pkgIndexFile(bool Trusted): Trusted(Trusted) {};

+ 3 - 0
apt-pkg/init.cc

@@ -101,6 +101,9 @@ bool pkgInitConfig(Configuration &Cnf)
       bindtextdomain(textdomain(0),Cnf.FindDir("Dir::Locale").c_str());
       bindtextdomain(textdomain(0),Cnf.FindDir("Dir::Locale").c_str());
    }
    }
 #endif
 #endif
+
+   // Translation
+   Cnf.Set("APT::Acquire::Translation", "environment");
    
    
    return true;
    return true;
 }
 }

+ 11 - 2
apt-pkg/pkgcache.cc

@@ -52,7 +52,7 @@ pkgCache::Header::Header()
    
    
    /* Whenever the structures change the major version should be bumped,
    /* Whenever the structures change the major version should be bumped,
       whenever the generator changes the minor version should be bumped. */
       whenever the generator changes the minor version should be bumped. */
-   MajorVersion = 4;
+   MajorVersion = 5;
    MinorVersion = 0;
    MinorVersion = 0;
    Dirty = false;
    Dirty = false;
    
    
@@ -60,17 +60,22 @@ pkgCache::Header::Header()
    PackageSz = sizeof(pkgCache::Package);
    PackageSz = sizeof(pkgCache::Package);
    PackageFileSz = sizeof(pkgCache::PackageFile);
    PackageFileSz = sizeof(pkgCache::PackageFile);
    VersionSz = sizeof(pkgCache::Version);
    VersionSz = sizeof(pkgCache::Version);
+   DescriptionSz = sizeof(pkgCache::Description);
    DependencySz = sizeof(pkgCache::Dependency);
    DependencySz = sizeof(pkgCache::Dependency);
    ProvidesSz = sizeof(pkgCache::Provides);
    ProvidesSz = sizeof(pkgCache::Provides);
    VerFileSz = sizeof(pkgCache::VerFile);
    VerFileSz = sizeof(pkgCache::VerFile);
+   DescFileSz = sizeof(pkgCache::DescFile);
    
    
    PackageCount = 0;
    PackageCount = 0;
    VersionCount = 0;
    VersionCount = 0;
+   DescriptionCount = 0;
    DependsCount = 0;
    DependsCount = 0;
    PackageFileCount = 0;
    PackageFileCount = 0;
    VerFileCount = 0;
    VerFileCount = 0;
+   DescFileCount = 0;
    ProvidesCount = 0;
    ProvidesCount = 0;
    MaxVerFileSize = 0;
    MaxVerFileSize = 0;
+   MaxDescFileSize = 0;
    
    
    FileList = 0;
    FileList = 0;
    StringList = 0;
    StringList = 0;
@@ -89,8 +94,10 @@ bool pkgCache::Header::CheckSizes(Header &Against) const
        PackageSz == Against.PackageSz &&
        PackageSz == Against.PackageSz &&
        PackageFileSz == Against.PackageFileSz &&
        PackageFileSz == Against.PackageFileSz &&
        VersionSz == Against.VersionSz &&
        VersionSz == Against.VersionSz &&
+       DescriptionSz == Against.DescriptionSz &&
        DependencySz == Against.DependencySz &&
        DependencySz == Against.DependencySz &&
        VerFileSz == Against.VerFileSz &&
        VerFileSz == Against.VerFileSz &&
+       DescFileSz == Against.DescFileSz &&
        ProvidesSz == Against.ProvidesSz)
        ProvidesSz == Against.ProvidesSz)
       return true;
       return true;
    return false;
    return false;
@@ -115,8 +122,10 @@ bool pkgCache::ReMap()
    HeaderP = (Header *)Map.Data();
    HeaderP = (Header *)Map.Data();
    PkgP = (Package *)Map.Data();
    PkgP = (Package *)Map.Data();
    VerFileP = (VerFile *)Map.Data();
    VerFileP = (VerFile *)Map.Data();
+   DescFileP = (DescFile *)Map.Data();
    PkgFileP = (PackageFile *)Map.Data();
    PkgFileP = (PackageFile *)Map.Data();
    VerP = (Version *)Map.Data();
    VerP = (Version *)Map.Data();
+   DescP = (Description *)Map.Data();
    ProvideP = (Provides *)Map.Data();
    ProvideP = (Provides *)Map.Data();
    DepP = (Dependency *)Map.Data();
    DepP = (Dependency *)Map.Data();
    StringItemP = (StringItem *)Map.Data();
    StringItemP = (StringItem *)Map.Data();
@@ -235,11 +244,11 @@ const char *pkgCache::Priority(unsigned char Prio)
    return 0;
    return 0;
 }
 }
 									/*}}}*/
 									/*}}}*/
-
 // Bases for iterator classes						/*{{{*/
 // Bases for iterator classes						/*{{{*/
 void pkgCache::VerIterator::_dummy() {}
 void pkgCache::VerIterator::_dummy() {}
 void pkgCache::DepIterator::_dummy() {}
 void pkgCache::DepIterator::_dummy() {}
 void pkgCache::PrvIterator::_dummy() {}
 void pkgCache::PrvIterator::_dummy() {}
+void pkgCache::DescIterator::_dummy() {}
 									/*}}}*/
 									/*}}}*/
 // PkgIterator::operator ++ - Postfix incr				/*{{{*/
 // PkgIterator::operator ++ - Postfix incr				/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------

+ 42 - 2
apt-pkg/pkgcache.h

@@ -38,24 +38,30 @@ class pkgCache
    struct Package;
    struct Package;
    struct PackageFile;
    struct PackageFile;
    struct Version;
    struct Version;
+   struct Description;
    struct Provides;
    struct Provides;
    struct Dependency;
    struct Dependency;
    struct StringItem;
    struct StringItem;
    struct VerFile;
    struct VerFile;
+   struct DescFile;
    
    
    // Iterators
    // Iterators
    class PkgIterator;
    class PkgIterator;
    class VerIterator;
    class VerIterator;
+   class DescIterator;
    class DepIterator;
    class DepIterator;
    class PrvIterator;
    class PrvIterator;
    class PkgFileIterator;
    class PkgFileIterator;
    class VerFileIterator;
    class VerFileIterator;
+   class DescFileIterator;
    friend class PkgIterator;
    friend class PkgIterator;
    friend class VerIterator;
    friend class VerIterator;
+   friend class DescInterator;
    friend class DepIterator;
    friend class DepIterator;
    friend class PrvIterator;
    friend class PrvIterator;
    friend class PkgFileIterator;
    friend class PkgFileIterator;
    friend class VerFileIterator;
    friend class VerFileIterator;
+   friend class DescFileIterator;
    
    
    class Namespace;
    class Namespace;
    
    
@@ -98,8 +104,10 @@ class pkgCache
    Header *HeaderP;
    Header *HeaderP;
    Package *PkgP;
    Package *PkgP;
    VerFile *VerFileP;
    VerFile *VerFileP;
+   DescFile *DescFileP;
    PackageFile *PkgFileP;
    PackageFile *PkgFileP;
    Version *VerP;
    Version *VerP;
+   Description *DescP;
    Provides *ProvideP;
    Provides *ProvideP;
    Dependency *DepP;
    Dependency *DepP;
    StringItem *StringItemP;
    StringItem *StringItemP;
@@ -151,16 +159,20 @@ struct pkgCache::Header
    unsigned short PackageSz;
    unsigned short PackageSz;
    unsigned short PackageFileSz;
    unsigned short PackageFileSz;
    unsigned short VersionSz;
    unsigned short VersionSz;
+   unsigned short DescriptionSz;
    unsigned short DependencySz;
    unsigned short DependencySz;
    unsigned short ProvidesSz;
    unsigned short ProvidesSz;
    unsigned short VerFileSz;
    unsigned short VerFileSz;
+   unsigned short DescFileSz;
    
    
    // Structure counts
    // Structure counts
    unsigned long PackageCount;
    unsigned long PackageCount;
    unsigned long VersionCount;
    unsigned long VersionCount;
+   unsigned long DescriptionCount;
    unsigned long DependsCount;
    unsigned long DependsCount;
    unsigned long PackageFileCount;
    unsigned long PackageFileCount;
    unsigned long VerFileCount;
    unsigned long VerFileCount;
+   unsigned long DescFileCount;
    unsigned long ProvidesCount;
    unsigned long ProvidesCount;
    
    
    // Offsets
    // Offsets
@@ -169,10 +181,11 @@ struct pkgCache::Header
    map_ptrloc VerSysName;            // StringTable
    map_ptrloc VerSysName;            // StringTable
    map_ptrloc Architecture;          // StringTable
    map_ptrloc Architecture;          // StringTable
    unsigned long MaxVerFileSize;
    unsigned long MaxVerFileSize;
+   unsigned long MaxDescFileSize;
 
 
    /* Allocation pools, there should be one of these for each structure
    /* Allocation pools, there should be one of these for each structure
       excluding the header */
       excluding the header */
-   DynamicMMap::Pool Pools[7];
+   DynamicMMap::Pool Pools[8];
    
    
    // Rapid package name lookup
    // Rapid package name lookup
    map_ptrloc HashTable[2*1048];
    map_ptrloc HashTable[2*1048];
@@ -193,7 +206,7 @@ struct pkgCache::Package
    map_ptrloc NextPackage;       // Package
    map_ptrloc NextPackage;       // Package
    map_ptrloc RevDepends;        // Dependency
    map_ptrloc RevDepends;        // Dependency
    map_ptrloc ProvidesList;      // Provides
    map_ptrloc ProvidesList;      // Provides
-   
+
    // Install/Remove/Purge etc
    // Install/Remove/Purge etc
    unsigned char SelectedState;     // What
    unsigned char SelectedState;     // What
    unsigned char InstState;         // Flags
    unsigned char InstState;         // Flags
@@ -232,6 +245,14 @@ struct pkgCache::VerFile
    unsigned short Size;
    unsigned short Size;
 };
 };
 
 
+struct pkgCache::DescFile
+{
+   map_ptrloc File;           // PackageFile
+   map_ptrloc NextFile;       // PkgVerFile
+   map_ptrloc Offset;         // File offset
+   unsigned short Size;
+};
+
 struct pkgCache::Version
 struct pkgCache::Version
 {
 {
    map_ptrloc VerStr;            // Stringtable
    map_ptrloc VerStr;            // Stringtable
@@ -241,6 +262,7 @@ struct pkgCache::Version
    // Lists
    // Lists
    map_ptrloc FileList;          // VerFile
    map_ptrloc FileList;          // VerFile
    map_ptrloc NextVer;           // Version
    map_ptrloc NextVer;           // Version
+   map_ptrloc DescriptionList;   // Description
    map_ptrloc DependsList;       // Dependency
    map_ptrloc DependsList;       // Dependency
    map_ptrloc ParentPkg;         // Package
    map_ptrloc ParentPkg;         // Package
    map_ptrloc ProvidesList;      // Provides
    map_ptrloc ProvidesList;      // Provides
@@ -252,6 +274,22 @@ struct pkgCache::Version
    unsigned char Priority;
    unsigned char Priority;
 };
 };
 
 
+struct pkgCache::Description
+{
+   // Language Code store the description translation language code. If
+   // the value has a 0 lenght then this is readed using the Package
+   // file else the Translation-CODE are used.
+   map_ptrloc language_code;     // StringTable
+   map_ptrloc md5sum;            // StringTable
+
+   // Linked list 
+   map_ptrloc FileList;          // DescFile
+   map_ptrloc NextDesc;          // Description
+   map_ptrloc ParentPkg;         // Package
+
+   unsigned short ID;
+};
+
 struct pkgCache::Dependency
 struct pkgCache::Dependency
 {
 {
    map_ptrloc Version;         // Stringtable
    map_ptrloc Version;         // Stringtable
@@ -299,11 +337,13 @@ class pkgCache::Namespace
 
 
    typedef pkgCache::PkgIterator PkgIterator;
    typedef pkgCache::PkgIterator PkgIterator;
    typedef pkgCache::VerIterator VerIterator;
    typedef pkgCache::VerIterator VerIterator;
+   typedef pkgCache::DescIterator DescIterator;
    typedef pkgCache::DepIterator DepIterator;
    typedef pkgCache::DepIterator DepIterator;
    typedef pkgCache::PrvIterator PrvIterator;
    typedef pkgCache::PrvIterator PrvIterator;
    typedef pkgCache::PkgFileIterator PkgFileIterator;
    typedef pkgCache::PkgFileIterator PkgFileIterator;
    typedef pkgCache::VerFileIterator VerFileIterator;   
    typedef pkgCache::VerFileIterator VerFileIterator;   
    typedef pkgCache::Version Version;
    typedef pkgCache::Version Version;
+   typedef pkgCache::Description Description;
    typedef pkgCache::Package Package;
    typedef pkgCache::Package Package;
    typedef pkgCache::Header Header;
    typedef pkgCache::Header Header;
    typedef pkgCache::Dep Dep;
    typedef pkgCache::Dep Dep;

+ 111 - 6
apt-pkg/pkgcachegen.cc

@@ -125,16 +125,46 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
       string Version = List.Version();
       string Version = List.Version();
       if (Version.empty() == true)
       if (Version.empty() == true)
       {
       {
+	 // we first process the package, then the descriptions
+	 // (this has the bonus that we get MMap error when we run out
+	 //  of MMap space)
 	 if (List.UsePackage(Pkg,pkgCache::VerIterator(Cache)) == false)
 	 if (List.UsePackage(Pkg,pkgCache::VerIterator(Cache)) == false)
 	    return _error->Error(_("Error occurred while processing %s (UsePackage1)"),
 	    return _error->Error(_("Error occurred while processing %s (UsePackage1)"),
 				 PackageName.c_str());
 				 PackageName.c_str());
+
+ 	 // Find the right version to write the description
+ 	 MD5SumValue CurMd5 = List.Description_md5();
+ 	 pkgCache::VerIterator Ver = Pkg.VersionList();
+ 	 map_ptrloc *LastVer = &Pkg->VersionList;
+
+  	 for (; Ver.end() == false; LastVer = &Ver->NextVer, Ver++) 
+ 	 {
+ 	    pkgCache::DescIterator Desc = Ver.DescriptionList();
+ 	    map_ptrloc *LastDesc = &Ver->DescriptionList;
+
+ 	    for (; Desc.end() == false; LastDesc = &Desc->NextDesc, Desc++)
+	    {
+
+ 	       if (MD5SumValue(Desc.md5()) == CurMd5) 
+               {
+ 		  // Add new description
+ 		  *LastDesc = NewDescription(Desc, List.DescriptionLanguage(), CurMd5, *LastDesc);
+ 		  Desc->ParentPkg = Pkg.Index();
+		  
+ 		  if (NewFileDesc(Desc,List) == false)
+ 		     return _error->Error(_("Error occured while processing %s (NewFileDesc1)"),PackageName.c_str());
+ 		  break;
+ 	       }
+	    }
+ 	 }
+
 	 continue;
 	 continue;
       }
       }
 
 
       pkgCache::VerIterator Ver = Pkg.VersionList();
       pkgCache::VerIterator Ver = Pkg.VersionList();
-      map_ptrloc *Last = &Pkg->VersionList;
+      map_ptrloc *LastVer = &Pkg->VersionList;
       int Res = 1;
       int Res = 1;
-      for (; Ver.end() == false; Last = &Ver->NextVer, Ver++)
+      for (; Ver.end() == false; LastVer = &Ver->NextVer, Ver++)
       {
       {
 	 Res = Cache.VS->CmpVersion(Version,Ver.VerStr());
 	 Res = Cache.VS->CmpVersion(Version,Ver.VerStr());
 	 if (Res >= 0)
 	 if (Res >= 0)
@@ -168,7 +198,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
       // Skip to the end of the same version set.
       // Skip to the end of the same version set.
       if (Res == 0)
       if (Res == 0)
       {
       {
-	 for (; Ver.end() == false; Last = &Ver->NextVer, Ver++)
+	 for (; Ver.end() == false; LastVer = &Ver->NextVer, Ver++)
 	 {
 	 {
 	    Res = Cache.VS->CmpVersion(Version,Ver.VerStr());
 	    Res = Cache.VS->CmpVersion(Version,Ver.VerStr());
 	    if (Res != 0)
 	    if (Res != 0)
@@ -177,9 +207,10 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
       }
       }
 
 
       // Add a new version
       // Add a new version
-      *Last = NewVersion(Ver,Version,*Last);
+      *LastVer = NewVersion(Ver,Version,*LastVer);
       Ver->ParentPkg = Pkg.Index();
       Ver->ParentPkg = Pkg.Index();
       Ver->Hash = Hash;
       Ver->Hash = Hash;
+
       if (List.NewVersion(Ver) == false)
       if (List.NewVersion(Ver) == false)
 	 return _error->Error(_("Error occurred while processing %s (NewVersion1)"),
 	 return _error->Error(_("Error occurred while processing %s (NewVersion1)"),
 			      PackageName.c_str());
 			      PackageName.c_str());
@@ -199,6 +230,21 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
 	 FoundFileDeps |= List.HasFileDeps();
 	 FoundFileDeps |= List.HasFileDeps();
 	 return true;
 	 return true;
       }      
       }      
+
+      /* Record the Description data. Description data always exist in
+	 Packages and Translation-* files. */
+      pkgCache::DescIterator Desc = Ver.DescriptionList();
+      map_ptrloc *LastDesc = &Ver->DescriptionList;
+      
+      // Skip to the end of description set
+      for (; Desc.end() == false; LastDesc = &Desc->NextDesc, Desc++);
+
+      // Add new description
+      *LastDesc = NewDescription(Desc, List.DescriptionLanguage(), List.Description_md5(), *LastDesc);
+      Desc->ParentPkg = Pkg.Index();
+
+      if (NewFileDesc(Desc,List) == false)
+	 return _error->Error(_("Error occured while processing %s (NewFileDesc2)"),PackageName.c_str());
    }
    }
 
 
    FoundFileDeps |= List.HasFileDeps();
    FoundFileDeps |= List.HasFileDeps();
@@ -209,6 +255,9 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
    if (Cache.HeaderP->VersionCount >= (1ULL<<(sizeof(Cache.VerP->ID)*8))-1)
    if (Cache.HeaderP->VersionCount >= (1ULL<<(sizeof(Cache.VerP->ID)*8))-1)
       return _error->Error(_("Wow, you exceeded the number of versions "
       return _error->Error(_("Wow, you exceeded the number of versions "
 			     "this APT is capable of."));
 			     "this APT is capable of."));
+   if (Cache.HeaderP->DescriptionCount >= (1ULL<<(sizeof(Cache.DescP->ID)*8))-1)
+      return _error->Error(_("Wow, you exceeded the number of descriptions "
+			     "this APT is capable of."));
    if (Cache.HeaderP->DependsCount >= (1ULL<<(sizeof(Cache.DepP->ID)*8))-1ULL)
    if (Cache.HeaderP->DependsCount >= (1ULL<<(sizeof(Cache.DepP->ID)*8))-1ULL)
       return _error->Error(_("Wow, you exceeded the number of dependencies "
       return _error->Error(_("Wow, you exceeded the number of dependencies "
 			     "this APT is capable of."));
 			     "this APT is capable of."));
@@ -271,7 +320,7 @@ bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,string Name)
    Pkg = Cache.FindPkg(Name);
    Pkg = Cache.FindPkg(Name);
    if (Pkg.end() == false)
    if (Pkg.end() == false)
       return true;
       return true;
-       
+
    // Get a structure
    // Get a structure
    unsigned long Package = Map.Allocate(sizeof(pkgCache::Package));
    unsigned long Package = Map.Allocate(sizeof(pkgCache::Package));
    if (Package == 0)
    if (Package == 0)
@@ -349,6 +398,62 @@ unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver,
    return Version;
    return Version;
 }
 }
 									/*}}}*/
 									/*}}}*/
+// CacheGenerator::NewFileDesc - Create a new File<->Desc association	/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool pkgCacheGenerator::NewFileDesc(pkgCache::DescIterator &Desc,
+				   ListParser &List)
+{
+   if (CurrentFile == 0)
+      return true;
+   
+   // Get a structure
+   unsigned long DescFile = Map.Allocate(sizeof(pkgCache::DescFile));
+   if (DescFile == 0)
+      return 0;
+
+   pkgCache::DescFileIterator DF(Cache,Cache.DescFileP + DescFile);
+   DF->File = CurrentFile - Cache.PkgFileP;
+
+   // Link it to the end of the list
+   map_ptrloc *Last = &Desc->FileList;
+   for (pkgCache::DescFileIterator D = Desc.FileList(); D.end() == false; D++)
+      Last = &D->NextFile;
+
+   DF->NextFile = *Last;
+   *Last = DF.Index();
+   
+   DF->Offset = List.Offset();
+   DF->Size = List.Size();
+   if (Cache.HeaderP->MaxDescFileSize < DF->Size)
+      Cache.HeaderP->MaxDescFileSize = DF->Size;
+   Cache.HeaderP->DescFileCount++;
+   
+   return true;
+}
+									/*}}}*/
+// CacheGenerator::NewDescription - Create a new Description		/*{{{*/
+// ---------------------------------------------------------------------
+/* This puts a description structure in the linked list */
+map_ptrloc pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc,
+					    const string &Lang, const MD5SumValue &md5sum,
+					    map_ptrloc Next)
+{
+   // Get a structure
+   map_ptrloc Description = Map.Allocate(sizeof(pkgCache::Description));
+   if (Description == 0)
+      return 0;
+
+   // Fill it in
+   Desc = pkgCache::DescIterator(Cache,Cache.DescP + Description);
+   Desc->NextDesc = Next;
+   Desc->ID = Cache.HeaderP->DescriptionCount++;
+   Desc->language_code = Map.WriteString(Lang);
+   Desc->md5sum = Map.WriteString(md5sum.Value());
+
+   return Description;
+}
+									/*}}}*/
 // ListParser::NewDepends - Create a dependency element			/*{{{*/
 // ListParser::NewDepends - Create a dependency element			/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* This creates a dependency element in the tree. It is linked to the
 /* This creates a dependency element in the tree. It is linked to the
@@ -580,7 +685,7 @@ static bool CheckValidity(string CacheFile, FileIterator Start,
       pkgCache::PkgFileIterator File = (*Start)->FindInCache(Cache);
       pkgCache::PkgFileIterator File = (*Start)->FindInCache(Cache);
       if (File.end() == true)
       if (File.end() == true)
 	 return false;
 	 return false;
-      
+
       Visited[File->ID] = true;
       Visited[File->ID] = true;
    }
    }
    
    

+ 6 - 0
apt-pkg/pkgcachegen.h

@@ -24,6 +24,7 @@
 #endif 
 #endif 
 
 
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/pkgcache.h>
+#include <apt-pkg/md5.h>
 
 
 class pkgSourceList;
 class pkgSourceList;
 class OpProgress;
 class OpProgress;
@@ -55,7 +56,9 @@ class pkgCacheGenerator
    
    
    bool NewPackage(pkgCache::PkgIterator &Pkg,string Pkg);
    bool NewPackage(pkgCache::PkgIterator &Pkg,string Pkg);
    bool NewFileVer(pkgCache::VerIterator &Ver,ListParser &List);
    bool NewFileVer(pkgCache::VerIterator &Ver,ListParser &List);
+   bool NewFileDesc(pkgCache::DescIterator &Desc,ListParser &List);
    unsigned long NewVersion(pkgCache::VerIterator &Ver,string VerStr,unsigned long Next);
    unsigned long NewVersion(pkgCache::VerIterator &Ver,string VerStr,unsigned long Next);
+   map_ptrloc NewDescription(pkgCache::DescIterator &Desc,const string &Lang,const MD5SumValue &md5sum,map_ptrloc Next);
 
 
    public:
    public:
 
 
@@ -107,6 +110,9 @@ class pkgCacheGenerator::ListParser
    virtual string Package() = 0;
    virtual string Package() = 0;
    virtual string Version() = 0;
    virtual string Version() = 0;
    virtual bool NewVersion(pkgCache::VerIterator Ver) = 0;
    virtual bool NewVersion(pkgCache::VerIterator Ver) = 0;
+   virtual string Description() = 0;
+   virtual string DescriptionLanguage() = 0;
+   virtual MD5SumValue Description_md5() = 0;
    virtual unsigned short VersionHash() = 0;
    virtual unsigned short VersionHash() = 0;
    virtual bool UsePackage(pkgCache::PkgIterator Pkg,
    virtual bool UsePackage(pkgCache::PkgIterator Pkg,
 			   pkgCache::VerIterator Ver) = 0;
 			   pkgCache::VerIterator Ver) = 0;

+ 9 - 0
apt-pkg/pkgrecords.cc

@@ -66,3 +66,12 @@ pkgRecords::Parser &pkgRecords::Lookup(pkgCache::VerFileIterator const &Ver)
    return *Files[Ver.File()->ID];
    return *Files[Ver.File()->ID];
 }
 }
 									/*}}}*/
 									/*}}}*/
+// Records::Lookup - Get a parser for the package description file	/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+pkgRecords::Parser &pkgRecords::Lookup(pkgCache::DescFileIterator const &Desc)
+{
+   Files[Desc.File()->ID]->Jump(Desc);
+   return *Files[Desc.File()->ID];
+}
+									/*}}}*/

+ 2 - 0
apt-pkg/pkgrecords.h

@@ -39,6 +39,7 @@ class pkgRecords
 
 
    // Lookup function
    // Lookup function
    Parser &Lookup(pkgCache::VerFileIterator const &Ver);
    Parser &Lookup(pkgCache::VerFileIterator const &Ver);
+   Parser &Lookup(pkgCache::DescFileIterator const &Desc);
 
 
    // Construct destruct
    // Construct destruct
    pkgRecords(pkgCache &Cache);
    pkgRecords(pkgCache &Cache);
@@ -50,6 +51,7 @@ class pkgRecords::Parser
    protected:
    protected:
    
    
    virtual bool Jump(pkgCache::VerFileIterator const &Ver) = 0;
    virtual bool Jump(pkgCache::VerFileIterator const &Ver) = 0;
+   virtual bool Jump(pkgCache::DescFileIterator const &Desc) = 0;
    
    
    public:
    public:
    friend class pkgRecords;
    friend class pkgRecords;

+ 84 - 22
cmdline/apt-cache.cc

@@ -71,6 +71,12 @@ void LocalitySort(pkgCache::VerFile **begin,
 {   
 {   
    qsort(begin,Count,Size,LocalityCompare);
    qsort(begin,Count,Size,LocalityCompare);
 }
 }
+
+void LocalitySort(pkgCache::DescFile **begin,
+		  unsigned long Count,size_t Size)
+{   
+   qsort(begin,Count,Size,LocalityCompare);
+}
 									/*}}}*/
 									/*}}}*/
 // UnMet - Show unmet dependencies					/*{{{*/
 // UnMet - Show unmet dependencies					/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
@@ -182,7 +188,14 @@ bool DumpPackage(CommandLine &CmdL)
       {
       {
 	 cout << Cur.VerStr();
 	 cout << Cur.VerStr();
 	 for (pkgCache::VerFileIterator Vf = Cur.FileList(); Vf.end() == false; Vf++)
 	 for (pkgCache::VerFileIterator Vf = Cur.FileList(); Vf.end() == false; Vf++)
-	    cout << "(" << Vf.File().FileName() << ")";
+	    cout << " (" << Vf.File().FileName() << ")";
+	 cout << endl;
+	 for (pkgCache::DescIterator D = Cur.DescriptionList(); D.end() == false; D++)
+	 {
+	    cout << " Description Language: " << D.LanguageCode() << endl
+		 << "                 File: " << D.FileList().File().FileName() << endl
+		 << "                  MD5: " << D.md5() << endl;
+	 }
 	 cout << endl;
 	 cout << endl;
       }
       }
       
       
@@ -277,11 +290,15 @@ bool Stats(CommandLine &Cmd)
    
    
    cout << _("Total distinct versions: ") << Cache.Head().VersionCount << " (" <<
    cout << _("Total distinct versions: ") << Cache.Head().VersionCount << " (" <<
       SizeToStr(Cache.Head().VersionCount*Cache.Head().VersionSz) << ')' << endl;
       SizeToStr(Cache.Head().VersionCount*Cache.Head().VersionSz) << ')' << endl;
+   cout << _("Total Distinct Descriptions: ") << Cache.Head().DescriptionCount << " (" <<
+      SizeToStr(Cache.Head().DescriptionCount*Cache.Head().DescriptionSz) << ')' << endl;
    cout << _("Total dependencies: ") << Cache.Head().DependsCount << " (" << 
    cout << _("Total dependencies: ") << Cache.Head().DependsCount << " (" << 
       SizeToStr(Cache.Head().DependsCount*Cache.Head().DependencySz) << ')' << endl;
       SizeToStr(Cache.Head().DependsCount*Cache.Head().DependencySz) << ')' << endl;
    
    
    cout << _("Total ver/file relations: ") << Cache.Head().VerFileCount << " (" <<
    cout << _("Total ver/file relations: ") << Cache.Head().VerFileCount << " (" <<
       SizeToStr(Cache.Head().VerFileCount*Cache.Head().VerFileSz) << ')' << endl;
       SizeToStr(Cache.Head().VerFileCount*Cache.Head().VerFileSz) << ')' << endl;
+   cout << _("Total Desc/File relations: ") << Cache.Head().DescFileCount << " (" <<
+      SizeToStr(Cache.Head().DescFileCount*Cache.Head().DescFileSz) << ')' << endl;
    cout << _("Total Provides mappings: ") << Cache.Head().ProvidesCount << " (" <<
    cout << _("Total Provides mappings: ") << Cache.Head().ProvidesCount << " (" <<
       SizeToStr(Cache.Head().ProvidesCount*Cache.Head().ProvidesSz) << ')' << endl;
       SizeToStr(Cache.Head().ProvidesCount*Cache.Head().ProvidesSz) << ')' << endl;
    
    
@@ -344,6 +361,12 @@ bool Dump(CommandLine &Cmd)
 	 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; D++)
 	 for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; D++)
 	    cout << "  Depends: " << D.TargetPkg().Name() << ' ' << 
 	    cout << "  Depends: " << D.TargetPkg().Name() << ' ' << 
 	                     DeNull(D.TargetVer()) << endl;
 	                     DeNull(D.TargetVer()) << endl;
+	 for (pkgCache::DescIterator D = V.DescriptionList(); D.end() == false; D++)
+	 {
+	    cout << " Description Language: " << D.LanguageCode() << endl
+		 << "                 File: " << D.FileList().File().FileName() << endl
+		 << "                  MD5: " << D.md5() << endl;
+	 } 
       }      
       }      
    }
    }
 
 
@@ -1192,17 +1215,56 @@ bool DisplayRecord(pkgCache::VerIterator V)
    if (_error->PendingError() == true)
    if (_error->PendingError() == true)
       return false;
       return false;
    
    
-   // Read the record and then write it out again.
+   // Read the record
    unsigned char *Buffer = new unsigned char[GCache->HeaderP->MaxVerFileSize+1];
    unsigned char *Buffer = new unsigned char[GCache->HeaderP->MaxVerFileSize+1];
    Buffer[V.FileList()->Size] = '\n';
    Buffer[V.FileList()->Size] = '\n';
    if (PkgF.Seek(V.FileList()->Offset) == false ||
    if (PkgF.Seek(V.FileList()->Offset) == false ||
-       PkgF.Read(Buffer,V.FileList()->Size) == false ||
-       fwrite(Buffer,1,V.FileList()->Size+1,stdout) < (size_t)(V.FileList()->Size+1))
+       PkgF.Read(Buffer,V.FileList()->Size) == false)
    {
    {
       delete [] Buffer;
       delete [] Buffer;
       return false;
       return false;
    }
    }
-   
+
+   // Get a pointer to start of Description field
+   const unsigned char *DescP = (unsigned char*)strstr((char*)Buffer, "Description:");
+
+   // Write all but Description
+   if (fwrite(Buffer,1,DescP - Buffer-1,stdout) < (size_t)(DescP - Buffer-1))
+   {
+      delete [] Buffer;
+      return false;
+   }
+
+   // Show the right description
+   pkgRecords Recs(*GCache);
+   pkgCache::DescIterator DescDefault = V.DescriptionList();
+   pkgCache::DescIterator Desc = DescDefault;
+   for (; Desc.end() == false; Desc++)
+      if (pkgIndexFile::LanguageCode() == Desc.LanguageCode())
+	 break;
+   if (Desc.end() == true) Desc = DescDefault;
+
+   pkgRecords::Parser &P = Recs.Lookup(Desc.FileList());
+   cout << "Description" << ( (strcmp(Desc.LanguageCode(),"") != 0) ? "-" : "" ) << Desc.LanguageCode() << ": " << P.LongDesc();
+
+   // Find the first field after the description (if there is any)
+   for(DescP++;DescP != &Buffer[V.FileList()->Size];DescP++) 
+   {
+      if(*DescP == '\n' && *(DescP+1) != ' ') 
+      {
+	 // 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)) 
+	 {
+	    delete [] Buffer;
+	    return false;
+	 }
+
+	 break;
+      }
+   }
+   // write a final newline (after the description)
+   cout<<endl;
    delete [] Buffer;
    delete [] Buffer;
 
 
    return true;
    return true;
@@ -1211,9 +1273,9 @@ bool DisplayRecord(pkgCache::VerIterator V)
 // Search - Perform a search						/*{{{*/
 // Search - Perform a search						/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* This searches the package names and pacakge descriptions for a pattern */
 /* This searches the package names and pacakge descriptions for a pattern */
-struct ExVerFile
+struct ExDescFile
 {
 {
-   pkgCache::VerFile *Vf;
+   pkgCache::DescFile *Df;
    bool NameMatch;
    bool NameMatch;
 };
 };
 
 
@@ -1253,35 +1315,35 @@ bool Search(CommandLine &CmdL)
       return false;
       return false;
    }
    }
    
    
-   ExVerFile *VFList = new ExVerFile[Cache.HeaderP->PackageCount+1];
-   memset(VFList,0,sizeof(*VFList)*Cache.HeaderP->PackageCount+1);
+   ExDescFile *DFList = new ExDescFile[Cache.HeaderP->PackageCount+1];
+   memset(DFList,0,sizeof(*DFList)*Cache.HeaderP->PackageCount+1);
 
 
    // Map versions that we want to write out onto the VerList array.
    // Map versions that we want to write out onto the VerList array.
    for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
    for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
    {
    {
-      VFList[P->ID].NameMatch = NumPatterns != 0;
+      DFList[P->ID].NameMatch = NumPatterns != 0;
       for (unsigned I = 0; I != NumPatterns; I++)
       for (unsigned I = 0; I != NumPatterns; I++)
       {
       {
 	 if (regexec(&Patterns[I],P.Name(),0,0,0) == 0)
 	 if (regexec(&Patterns[I],P.Name(),0,0,0) == 0)
-	    VFList[P->ID].NameMatch &= true;
+	    DFList[P->ID].NameMatch &= true;
 	 else
 	 else
-	    VFList[P->ID].NameMatch = false;
+	    DFList[P->ID].NameMatch = false;
       }
       }
         
         
       // Doing names only, drop any that dont match..
       // Doing names only, drop any that dont match..
-      if (NamesOnly == true && VFList[P->ID].NameMatch == false)
+      if (NamesOnly == true && DFList[P->ID].NameMatch == false)
 	 continue;
 	 continue;
 	 
 	 
       // Find the proper version to use. 
       // Find the proper version to use. 
       pkgCache::VerIterator V = Plcy.GetCandidateVer(P);
       pkgCache::VerIterator V = Plcy.GetCandidateVer(P);
       if (V.end() == false)
       if (V.end() == false)
-	 VFList[P->ID].Vf = V.FileList();
+	 DFList[P->ID].Df = V.DescriptionList().FileList();
    }
    }
       
       
    // Include all the packages that provide matching names too
    // Include all the packages that provide matching names too
    for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
    for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
    {
    {
-      if (VFList[P->ID].NameMatch == false)
+      if (DFList[P->ID].NameMatch == false)
 	 continue;
 	 continue;
 
 
       for (pkgCache::PrvIterator Prv = P.ProvidesList() ; Prv.end() == false; Prv++)
       for (pkgCache::PrvIterator Prv = P.ProvidesList() ; Prv.end() == false; Prv++)
@@ -1289,18 +1351,18 @@ bool Search(CommandLine &CmdL)
 	 pkgCache::VerIterator V = Plcy.GetCandidateVer(Prv.OwnerPkg());
 	 pkgCache::VerIterator V = Plcy.GetCandidateVer(Prv.OwnerPkg());
 	 if (V.end() == false)
 	 if (V.end() == false)
 	 {
 	 {
-	    VFList[Prv.OwnerPkg()->ID].Vf = V.FileList();
-	    VFList[Prv.OwnerPkg()->ID].NameMatch = true;
+	    DFList[Prv.OwnerPkg()->ID].Df = V.DescriptionList().FileList();
+	    DFList[Prv.OwnerPkg()->ID].NameMatch = true;
 	 }
 	 }
       }
       }
    }
    }
-
-   LocalitySort(&VFList->Vf,Cache.HeaderP->PackageCount,sizeof(*VFList));
+   
+   LocalitySort(&DFList->Df,Cache.HeaderP->PackageCount,sizeof(*DFList));
 
 
    // Iterate over all the version records and check them
    // Iterate over all the version records and check them
-   for (ExVerFile *J = VFList; J->Vf != 0; J++)
+   for (ExDescFile *J = DFList; J->Df != 0; J++)
    {
    {
-      pkgRecords::Parser &P = Recs.Lookup(pkgCache::VerFileIterator(Cache,J->Vf));
+      pkgRecords::Parser &P = Recs.Lookup(pkgCache::DescFileIterator(Cache,J->Df));
 
 
       bool Match = true;
       bool Match = true;
       if (J->NameMatch == false)
       if (J->NameMatch == false)
@@ -1331,7 +1393,7 @@ bool Search(CommandLine &CmdL)
       }
       }
    }
    }
    
    
-   delete [] VFList;
+   delete [] DFList;
    for (unsigned I = 0; I != NumPatterns; I++)
    for (unsigned I = 0; I != NumPatterns; I++)
       regfree(&Patterns[I]);
       regfree(&Patterns[I]);
    if (ferror(stdout))
    if (ferror(stdout))

+ 1 - 0
debian/changelog

@@ -98,6 +98,7 @@ apt (0.6.38) unstable; urgency=low
   
   
  -- Matt Zimmerman <mdz@debian.org>  Sat, 25 Jun 2005 09:51:00 -0700
  -- Matt Zimmerman <mdz@debian.org>  Sat, 25 Jun 2005 09:51:00 -0700
 
 
+>>>>>>> MERGE-SOURCE
 apt (0.6.37) breezy; urgency=low
 apt (0.6.37) breezy; urgency=low
 
 
   * Merge bubulle@debian.org--2005/apt--main--0 up to patch-81
   * Merge bubulle@debian.org--2005/apt--main--0 up to patch-81