Parcourir la source

Sync with Michael
Reintegrate disappeared po/ku.po and po/uk.po then activate those translations

bubulle@debian.org il y a 19 ans
Parent
commit
90a88b8302
100 fichiers modifiés avec 3924 ajouts et 516 suppressions
  1. 9 0
      BUGS
  2. 1 1
      Makefile
  3. 74 0
      README.ddtp
  4. 0 3
      apt-inst/contrib/arfile.cc
  5. 0 3
      apt-inst/contrib/arfile.h
  6. 0 3
      apt-inst/contrib/extracttar.cc
  7. 0 4
      apt-inst/contrib/extracttar.h
  8. 0 4
      apt-inst/database.cc
  9. 0 4
      apt-inst/database.h
  10. 0 4
      apt-inst/deb/debfile.cc
  11. 0 3
      apt-inst/deb/debfile.h
  12. 0 4
      apt-inst/deb/dpkgdb.cc
  13. 0 3
      apt-inst/deb/dpkgdb.h
  14. 0 4
      apt-inst/dirstream.cc
  15. 0 3
      apt-inst/dirstream.h
  16. 0 3
      apt-inst/extract.cc
  17. 1 3
      apt-inst/extract.h
  18. 0 4
      apt-inst/filelist.cc
  19. 1 3
      apt-inst/filelist.h
  20. 475 16
      apt-pkg/acquire-item.cc
  21. 700 35
      apt-pkg/acquire-item.h
  22. 0 3
      apt-pkg/acquire-method.cc
  23. 9 3
      apt-pkg/acquire-method.h
  24. 7 3
      apt-pkg/acquire-worker.cc
  25. 247 15
      apt-pkg/acquire-worker.h
  26. 0 3
      apt-pkg/acquire.cc
  27. 516 32
      apt-pkg/acquire.h
  28. 94 33
      apt-pkg/algorithms.cc
  29. 0 3
      apt-pkg/algorithms.h
  30. 0 4
      apt-pkg/cachefile.cc
  31. 0 3
      apt-pkg/cachefile.h
  32. 83 4
      apt-pkg/cacheiterators.h
  33. 39 12
      apt-pkg/cdrom.cc
  34. 5 5
      apt-pkg/cdrom.h
  35. 0 4
      apt-pkg/clean.cc
  36. 0 3
      apt-pkg/clean.h
  37. 0 3
      apt-pkg/contrib/cdromutl.cc
  38. 0 4
      apt-pkg/contrib/cdromutl.h
  39. 0 3
      apt-pkg/contrib/cmndline.cc
  40. 1 3
      apt-pkg/contrib/cmndline.h
  41. 0 3
      apt-pkg/contrib/configuration.cc
  42. 1 3
      apt-pkg/contrib/configuration.h
  43. 0 4
      apt-pkg/contrib/crc-16.cc
  44. 0 4
      apt-pkg/contrib/crc-16.h
  45. 0 4
      apt-pkg/contrib/error.cc
  46. 1 3
      apt-pkg/contrib/error.h
  47. 1 3
      apt-pkg/contrib/fileutl.cc
  48. 0 3
      apt-pkg/contrib/fileutl.h
  49. 0 4
      apt-pkg/contrib/hashes.cc
  50. 0 3
      apt-pkg/contrib/hashes.h
  51. 0 4
      apt-pkg/contrib/md5.cc
  52. 0 3
      apt-pkg/contrib/md5.h
  53. 0 4
      apt-pkg/contrib/mmap.cc
  54. 0 3
      apt-pkg/contrib/mmap.h
  55. 0 3
      apt-pkg/contrib/progress.cc
  56. 0 3
      apt-pkg/contrib/progress.h
  57. 0 4
      apt-pkg/contrib/sha1.cc
  58. 0 4
      apt-pkg/contrib/sha1.h
  59. 0 4
      apt-pkg/contrib/sha256.h
  60. 44 4
      apt-pkg/contrib/strutl.cc
  61. 3 4
      apt-pkg/contrib/strutl.h
  62. 174 4
      apt-pkg/deb/debindexfile.cc
  63. 31 3
      apt-pkg/deb/debindexfile.h
  64. 46 0
      apt-pkg/deb/deblistparser.cc
  65. 4 0
      apt-pkg/deb/deblistparser.h
  66. 16 5
      apt-pkg/deb/debmetaindex.cc
  67. 0 4
      apt-pkg/deb/debmetaindex.h
  68. 21 5
      apt-pkg/deb/debrecords.cc
  69. 2 4
      apt-pkg/deb/debrecords.h
  70. 1 5
      apt-pkg/deb/debsrcrecords.cc
  71. 1 4
      apt-pkg/deb/debsrcrecords.h
  72. 0 4
      apt-pkg/deb/debsystem.cc
  73. 0 4
      apt-pkg/deb/debsystem.h
  74. 0 3
      apt-pkg/deb/debversion.cc
  75. 1 3
      apt-pkg/deb/debversion.h
  76. 2 3
      apt-pkg/deb/dpkgpm.cc
  77. 1 5
      apt-pkg/deb/dpkgpm.h
  78. 549 43
      apt-pkg/depcache.cc
  79. 220 7
      apt-pkg/depcache.h
  80. 180 3
      apt-pkg/indexcopy.cc
  81. 13 0
      apt-pkg/indexcopy.h
  82. 63 4
      apt-pkg/indexfile.cc
  83. 6 4
      apt-pkg/indexfile.h
  84. 0 3
      apt-pkg/indexrecords.cc
  85. 1 3
      apt-pkg/indexrecords.h
  86. 6 0
      apt-pkg/init.cc
  87. 2 2
      apt-pkg/init.h
  88. 1 1
      apt-pkg/makefile
  89. 0 3
      apt-pkg/metaindex.h
  90. 16 4
      apt-pkg/orderlist.cc
  91. 0 3
      apt-pkg/orderlist.h
  92. 8 14
      apt-pkg/packagemanager.cc
  93. 30 5
      apt-pkg/packagemanager.h
  94. 36 10
      apt-pkg/pkgcache.cc
  95. 47 6
      apt-pkg/pkgcache.h
  96. 117 12
      apt-pkg/pkgcachegen.cc
  97. 6 3
      apt-pkg/pkgcachegen.h
  98. 9 3
      apt-pkg/pkgrecords.cc
  99. 2 3
      apt-pkg/pkgrecords.h
  100. 0 0
      apt-pkg/pkgsystem.cc

+ 9 - 0
BUGS

@@ -0,0 +1,9 @@
+
+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
+  (is in the code in indexfile::LanguageCode(), just a bit ugly 

+ 1 - 1
Makefile

@@ -26,7 +26,7 @@ maintainer-clean dist-clean distclean pristine sanity: veryclean
 
 
 # The startup target builds the necessary configure scripts. It should
 # The startup target builds the necessary configure scripts. It should
 # be used after a CVS checkout.
 # be used after a CVS checkout.
-CONVERTED=environment.mak include/config.h include/apti18n.h makefile
+CONVERTED=environment.mak include/config.h include/apti18n.h build/doc/Doxyfile makefile
 include buildlib/configure.mak
 include buildlib/configure.mak
 $(BUILDDIR)/include/config.h: buildlib/config.h.in
 $(BUILDDIR)/include/config.h: buildlib/config.h.in
 $(BUILDDIR)/include/apti18n.h: buildlib/apti18n.h.in
 $(BUILDDIR)/include/apti18n.h: buildlib/apti18n.h.in

+ 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

+ 0 - 3
apt-inst/contrib/arfile.cc

@@ -14,9 +14,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/arfile.h"
-#endif
 #include <apt-pkg/arfile.h>
 #include <apt-pkg/arfile.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>

+ 0 - 3
apt-inst/contrib/arfile.h

@@ -15,9 +15,6 @@
 #ifndef PKGLIB_ARFILE_H
 #ifndef PKGLIB_ARFILE_H
 #define PKGLIB_ARFILE_H
 #define PKGLIB_ARFILE_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/arfile.h"
-#endif
 
 
 #include <string>
 #include <string>
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/fileutl.h>

+ 0 - 3
apt-inst/contrib/extracttar.cc

@@ -16,9 +16,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/extracttar.h"
-#endif
 #include <apt-pkg/extracttar.h>
 #include <apt-pkg/extracttar.h>
 
 
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>

+ 0 - 4
apt-inst/contrib/extracttar.h

@@ -14,10 +14,6 @@
 #ifndef PKGLIB_EXTRACTTAR_H
 #ifndef PKGLIB_EXTRACTTAR_H
 #define PKGLIB_EXTRACTTAR_H
 #define PKGLIB_EXTRACTTAR_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/extracttar.h"
-#endif
-
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/dirstream.h>
 #include <apt-pkg/dirstream.h>
 
 

+ 0 - 4
apt-inst/database.cc

@@ -8,10 +8,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/database.h"
-#endif
-
 #include <apt-pkg/database.h>
 #include <apt-pkg/database.h>
 									/*}}}*/
 									/*}}}*/
 
 

+ 0 - 4
apt-inst/database.h

@@ -21,10 +21,6 @@
 #ifndef PKGLIB_DATABASE_H
 #ifndef PKGLIB_DATABASE_H
 #define PKGLIB_DATABASE_H
 #define PKGLIB_DATABASE_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/database.h"
-#endif
-
 #include <apt-pkg/filelist.h>
 #include <apt-pkg/filelist.h>
 #include <apt-pkg/pkgcachegen.h>
 #include <apt-pkg/pkgcachegen.h>
 
 

+ 0 - 4
apt-inst/deb/debfile.cc

@@ -16,10 +16,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/debfile.h"
-#endif
-
 #include <apt-pkg/debfile.h>
 #include <apt-pkg/debfile.h>
 #include <apt-pkg/extracttar.h>
 #include <apt-pkg/extracttar.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>

+ 0 - 3
apt-inst/deb/debfile.h

@@ -23,9 +23,6 @@
 #ifndef PKGLIB_DEBFILE_H
 #ifndef PKGLIB_DEBFILE_H
 #define PKGLIB_DEBFILE_H
 #define PKGLIB_DEBFILE_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/debfile.h"
-#endif
 
 
 #include <apt-pkg/arfile.h>
 #include <apt-pkg/arfile.h>
 #include <apt-pkg/database.h>
 #include <apt-pkg/database.h>

+ 0 - 4
apt-inst/deb/dpkgdb.cc

@@ -13,10 +13,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/dpkgdb.h"
-#endif
-
 #include <apt-pkg/dpkgdb.h>
 #include <apt-pkg/dpkgdb.h>
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>

+ 0 - 3
apt-inst/deb/dpkgdb.h

@@ -19,9 +19,6 @@
 #ifndef PKGLIB_DPKGDB_H
 #ifndef PKGLIB_DPKGDB_H
 #define PKGLIB_DPKGDB_H
 #define PKGLIB_DPKGDB_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/dpkgdb.h"
-#endif
 
 
 #include <apt-pkg/database.h>
 #include <apt-pkg/database.h>
 
 

+ 0 - 4
apt-inst/dirstream.cc

@@ -11,10 +11,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/dirstream.h"
-#endif
-
 #include <apt-pkg/dirstream.h>
 #include <apt-pkg/dirstream.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>
 
 

+ 0 - 3
apt-inst/dirstream.h

@@ -25,9 +25,6 @@
 #ifndef PKGLIB_DIRSTREAM_H
 #ifndef PKGLIB_DIRSTREAM_H
 #define PKGLIB_DIRSTREAM_H
 #define PKGLIB_DIRSTREAM_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/dirstream.h"
-#endif
 
 
 class pkgDirStream
 class pkgDirStream
 { 
 { 

+ 0 - 3
apt-inst/extract.cc

@@ -44,9 +44,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/extract.h"
-#endif
 #include <apt-pkg/extract.h>
 #include <apt-pkg/extract.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/debversion.h>
 #include <apt-pkg/debversion.h>

+ 1 - 3
apt-inst/extract.h

@@ -17,9 +17,7 @@
 #ifndef PKGLIB_EXTRACT_H
 #ifndef PKGLIB_EXTRACT_H
 #define PKGLIB_EXTRACT_H
 #define PKGLIB_EXTRACT_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/extract.h"
-#endif
+
 
 
 #include <apt-pkg/dirstream.h>
 #include <apt-pkg/dirstream.h>
 #include <apt-pkg/filelist.h>
 #include <apt-pkg/filelist.h>

+ 0 - 4
apt-inst/filelist.cc

@@ -32,10 +32,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/filelist.h"
-#endif
-
 #include <apt-pkg/filelist.h>
 #include <apt-pkg/filelist.h>
 #include <apt-pkg/mmap.h>
 #include <apt-pkg/mmap.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>

+ 1 - 3
apt-inst/filelist.h

@@ -28,9 +28,7 @@
 #ifndef PKGLIB_FILELIST_H
 #ifndef PKGLIB_FILELIST_H
 #define PKGLIB_FILELIST_H
 #define PKGLIB_FILELIST_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/filelist.h"
-#endif
+
 
 
 #include <apt-pkg/mmap.h>
 #include <apt-pkg/mmap.h>
 
 

+ 475 - 16
apt-pkg/acquire-item.cc

@@ -13,9 +13,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/acquire-item.h"
-#endif
 #include <apt-pkg/acquire-item.h>
 #include <apt-pkg/acquire-item.h>
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/sourcelist.h>
 #include <apt-pkg/sourcelist.h>
@@ -24,6 +21,8 @@
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/md5.h>
 #include <apt-pkg/md5.h>
+#include <apt-pkg/sha1.h>
+#include <apt-pkg/tagfile.h>
 
 
 #include <apti18n.h>
 #include <apti18n.h>
     
     
@@ -31,6 +30,7 @@
 #include <unistd.h>
 #include <unistd.h>
 #include <errno.h>
 #include <errno.h>
 #include <string>
 #include <string>
+#include <sstream>
 #include <stdio.h>
 #include <stdio.h>
 									/*}}}*/
 									/*}}}*/
 
 
@@ -100,7 +100,8 @@ void pkgAcquire::Item::Done(string Message,unsigned long Size,string,
 {
 {
    // We just downloaded something..
    // We just downloaded something..
    string FileName = LookupTag(Message,"Filename");
    string FileName = LookupTag(Message,"Filename");
-   if (Complete == false && FileName == DestFile)
+   // we only inform the Log class if it was actually not a local thing
+   if (Complete == false && !Local && FileName == DestFile)
    {
    {
       if (Owner->Log != 0)
       if (Owner->Log != 0)
 	 Owner->Log->Fetched(Size,atoi(LookupTag(Message,"Resume-Point","0").c_str()));
 	 Owner->Log->Fetched(Size,atoi(LookupTag(Message,"Resume-Point","0").c_str()));
@@ -131,14 +132,432 @@ void pkgAcquire::Item::Rename(string From,string To)
 }
 }
 									/*}}}*/
 									/*}}}*/
 
 
+
+// AcqDiffIndex::AcqDiffIndex - Constructor			
+// ---------------------------------------------------------------------
+/* Get the DiffIndex file first and see if there are patches availabe 
+ * If so, create a pkgAcqIndexDiffs fetcher that will get and apply the
+ * patches. If anything goes wrong in that process, it will fall back to
+ * the original packages file
+ */
+pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner,
+				 string URI,string URIDesc,string ShortDesc,
+				 string ExpectedMD5)
+   : Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5), Description(URIDesc)
+{
+   
+   Debug = _config->FindB("Debug::pkgAcquire::Diffs",false);
+
+   Desc.Description = URIDesc + "/DiffIndex";
+   Desc.Owner = this;
+   Desc.ShortDesc = ShortDesc;
+   Desc.URI = URI + ".diff/Index";
+
+   DestFile = _config->FindDir("Dir::State::lists") + "partial/";
+   DestFile += URItoFileName(URI) + string(".DiffIndex");
+
+   if(Debug)
+      std::clog << "pkgAcqDiffIndex: " << Desc.URI << std::endl;
+
+   // look for the current package file
+   CurrentPackagesFile = _config->FindDir("Dir::State::lists");
+   CurrentPackagesFile += URItoFileName(RealURI);
+
+   // FIXME: this file:/ check is a hack to prevent fetching
+   //        from local sources. this is really silly, and
+   //        should be fixed cleanly as soon as possible
+   if(!FileExists(CurrentPackagesFile) || 
+      Desc.URI.substr(0,strlen("file:/")) == "file:/")
+   {
+      // we don't have a pkg file or we don't want to queue
+      if(Debug)
+	 std::clog << "No index file, local or canceld by user" << std::endl;
+      Failed("", NULL);
+      return;
+   }
+
+   if(Debug) 
+      std::clog << "pkgAcqIndexDiffs::pkgAcqIndexDiffs(): " 
+		<< CurrentPackagesFile << std::endl;
+   
+   QueueURI(Desc);
+
+}
+
+// AcqIndex::Custom600Headers - Insert custom request headers		/*{{{*/
+// ---------------------------------------------------------------------
+/* The only header we use is the last-modified header. */
+string pkgAcqDiffIndex::Custom600Headers()
+{
+   string Final = _config->FindDir("Dir::State::lists");
+   Final += URItoFileName(RealURI) + string(".IndexDiff");
+   
+   if(Debug)
+      std::clog << "Custom600Header-IMS: " << Final << std::endl;
+
+   struct stat Buf;
+   if (stat(Final.c_str(),&Buf) != 0)
+      return "\nIndex-File: true";
+   
+   return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
+}
+
+
+bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile)
+{
+   if(Debug)
+      std::clog << "pkgAcqIndexDiffs::ParseIndexDiff() " << IndexDiffFile 
+		<< std::endl;
+
+   pkgTagSection Tags;
+   string ServerSha1;
+   vector<DiffInfo> available_patches;
+   
+   FileFd Fd(IndexDiffFile,FileFd::ReadOnly);
+   pkgTagFile TF(&Fd);
+   if (_error->PendingError() == true)
+      return false;
+
+   if(TF.Step(Tags) == true)
+   {
+      string local_sha1;
+      bool found = false;
+      DiffInfo d;
+      string size;
+
+      string tmp = Tags.FindS("SHA1-Current");
+      std::stringstream ss(tmp);
+      ss >> ServerSha1;
+
+      FileFd fd(CurrentPackagesFile, FileFd::ReadOnly);
+      SHA1Summation SHA1;
+      SHA1.AddFD(fd.Fd(), fd.Size());
+      local_sha1 = string(SHA1.Result());
+
+      if(local_sha1 == ServerSha1) 
+      {
+	 // we have the same sha1 as the server
+	 if(Debug)
+	    std::clog << "Package file is up-to-date" << std::endl;
+	 // set found to true, this will queue a pkgAcqIndexDiffs with
+	 // a empty availabe_patches
+	 found = true;
+      } 
+      else 
+      {
+	 if(Debug)
+	    std::clog << "SHA1-Current: " << ServerSha1 << std::endl;
+
+	 // check the historie and see what patches we need
+	 string history = Tags.FindS("SHA1-History");     
+	 std::stringstream hist(history);
+	 while(hist >> d.sha1 >> size >> d.file) 
+	 {
+	    d.size = atoi(size.c_str());
+	    // read until the first match is found
+	    if(d.sha1 == local_sha1) 
+	       found=true;
+	    // from that point on, we probably need all diffs
+	    if(found) 
+	    {
+	       if(Debug)
+		  std::clog << "Need to get diff: " << d.file << std::endl;
+	       available_patches.push_back(d);
+	    }
+	 }
+      }
+
+      // we have something, queue the next diff
+      if(found) 
+      {
+	 // queue the diffs
+	 int last_space = Description.rfind(" ");
+	 if(last_space != string::npos)
+	    Description.erase(last_space, Description.size()-last_space);
+	 new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc,
+			      ExpectedMD5, available_patches);
+	 Complete = false;
+	 Status = StatDone;
+	 Dequeue();
+	 return true;
+      }
+   }
+   
+   // Nothing found, report and return false
+   // Failing here is ok, if we return false later, the full
+   // IndexFile is queued
+   if(Debug)
+      std::clog << "Can't find a patch in the index file" << std::endl;
+   return false;
+}
+
+void pkgAcqDiffIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
+{
+   if(Debug)
+      std::clog << "pkgAcqDiffIndex failed: " << Desc.URI << std::endl
+		<< "Falling back to normal index file aquire" << std::endl;
+
+   new pkgAcqIndex(Owner, RealURI, Description, Desc.ShortDesc, 
+		   ExpectedMD5);
+
+   Complete = false;
+   Status = StatDone;
+   Dequeue();
+}
+
+void pkgAcqDiffIndex::Done(string Message,unsigned long Size,string Md5Hash,
+			   pkgAcquire::MethodConfig *Cnf)
+{
+   if(Debug)
+      std::clog << "pkgAcqDiffIndex::Done(): " << Desc.URI << std::endl;
+
+   Item::Done(Message,Size,Md5Hash,Cnf);
+
+   string FinalFile;
+   FinalFile = _config->FindDir("Dir::State::lists")+URItoFileName(RealURI);
+
+   // sucess in downloading the index
+   // rename the index
+   FinalFile += string(".IndexDiff");
+   if(Debug)
+      std::clog << "Renaming: " << DestFile << " -> " << FinalFile 
+		<< std::endl;
+   Rename(DestFile,FinalFile);
+   chmod(FinalFile.c_str(),0644);
+   DestFile = FinalFile;
+
+   if(!ParseDiffIndex(DestFile))
+      return Failed("", NULL);
+
+   Complete = true;
+   Status = StatDone;
+   Dequeue();
+   return;
+}
+
+
+
+// AcqIndexDiffs::AcqIndexDiffs - Constructor			
+// ---------------------------------------------------------------------
+/* The package diff is added to the queue. one object is constructed
+ * for each diff and the index
+ */
+pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire *Owner,
+				   string URI,string URIDesc,string ShortDesc,
+				   string ExpectedMD5, vector<DiffInfo> diffs)
+   : Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5), 
+     available_patches(diffs)
+{
+   
+   DestFile = _config->FindDir("Dir::State::lists") + "partial/";
+   DestFile += URItoFileName(URI);
+
+   Debug = _config->FindB("Debug::pkgAcquire::Diffs",false);
+
+   Description = URIDesc;
+   Desc.Owner = this;
+   Desc.ShortDesc = ShortDesc;
+
+   if(available_patches.size() == 0) 
+   {
+      // we are done (yeah!)
+      Finish(true);
+   }
+   else
+   {
+      // get the next diff
+      State = StateFetchDiff;
+      QueueNextDiff();
+   }
+}
+
+
+void pkgAcqIndexDiffs::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
+{
+   if(Debug)
+      std::clog << "pkgAcqIndexDiffs failed: " << Desc.URI << std::endl
+		<< "Falling back to normal index file aquire" << std::endl;
+   new pkgAcqIndex(Owner, RealURI, Description,Desc.ShortDesc, 
+		   ExpectedMD5);
+   Finish();
+}
+
+
+// helper that cleans the item out of the fetcher queue
+void pkgAcqIndexDiffs::Finish(bool allDone)
+{
+   // we restore the original name, this is required, otherwise
+   // the file will be cleaned
+   if(allDone) 
+   {
+      DestFile = _config->FindDir("Dir::State::lists");
+      DestFile += URItoFileName(RealURI);
+
+      // do the final md5sum checking
+      MD5Summation sum;
+      FileFd Fd(DestFile, FileFd::ReadOnly);
+      sum.AddFD(Fd.Fd(), Fd.Size());
+      Fd.Close();
+      string MD5 = (string)sum.Result();
+
+      if (!ExpectedMD5.empty() && MD5 != ExpectedMD5)
+      {
+	 Status = StatAuthError;
+	 ErrorText = _("MD5Sum mismatch");
+	 Rename(DestFile,DestFile + ".FAILED");
+	 Dequeue();
+	 return;
+      }
+
+      // this is for the "real" finish
+      Complete = true;
+      Status = StatDone;
+      Dequeue();
+      if(Debug)
+	 std::clog << "\n\nallDone: " << DestFile << "\n" << std::endl;
+      return;
+   }
+
+   if(Debug)
+      std::clog << "Finishing: " << Desc.URI << std::endl;
+   Complete = false;
+   Status = StatDone;
+   Dequeue();
+   return;
+}
+
+
+
+bool pkgAcqIndexDiffs::QueueNextDiff()
+{
+
+   // calc sha1 of the just patched file
+   string FinalFile = _config->FindDir("Dir::State::lists");
+   FinalFile += URItoFileName(RealURI);
+
+   FileFd fd(FinalFile, FileFd::ReadOnly);
+   SHA1Summation SHA1;
+   SHA1.AddFD(fd.Fd(), fd.Size());
+   string local_sha1 = string(SHA1.Result());
+   if(Debug)
+      std::clog << "QueueNextDiff: " 
+		<< FinalFile << " (" << local_sha1 << ")"<<std::endl;
+
+   // remove all patches until the next matching patch is found
+   // this requires the Index file to be ordered
+   for(vector<DiffInfo>::iterator I=available_patches.begin();
+       available_patches.size() > 0 && 
+	  I != available_patches.end() &&
+	  (*I).sha1 != local_sha1; 
+       I++) 
+   {
+      available_patches.erase(I);
+   }
+
+   // error checking and falling back if no patch was found
+   if(available_patches.size() == 0) 
+   { 
+      Failed("", NULL);
+      return false;
+   }
+
+   // queue the right diff
+   Desc.URI = string(RealURI) + ".diff/" + available_patches[0].file + ".gz";
+   Desc.Description = Description + " " + available_patches[0].file + string(".pdiff");
+   DestFile = _config->FindDir("Dir::State::lists") + "partial/";
+   DestFile += URItoFileName(RealURI + ".diff/" + available_patches[0].file);
+
+   if(Debug)
+      std::clog << "pkgAcqIndexDiffs::QueueNextDiff(): " << Desc.URI << std::endl;
+   
+   QueueURI(Desc);
+
+   return true;
+}
+
+
+
+void pkgAcqIndexDiffs::Done(string Message,unsigned long Size,string Md5Hash,
+			    pkgAcquire::MethodConfig *Cnf)
+{
+   if(Debug)
+      std::clog << "pkgAcqIndexDiffs::Done(): " << Desc.URI << std::endl;
+
+   Item::Done(Message,Size,Md5Hash,Cnf);
+
+   string FinalFile;
+   FinalFile = _config->FindDir("Dir::State::lists")+URItoFileName(RealURI);
+
+   // sucess in downloading a diff, enter ApplyDiff state
+   if(State == StateFetchDiff) 
+   {
+
+      if(Debug)
+	 std::clog << "Sending to gzip method: " << FinalFile << std::endl;
+
+      string FileName = LookupTag(Message,"Filename");
+      State = StateUnzipDiff;
+      Local = true;
+      Desc.URI = "gzip:" + FileName;
+      DestFile += ".decomp";
+      QueueURI(Desc);
+      Mode = "gzip";
+      return;
+   } 
+
+   // sucess in downloading a diff, enter ApplyDiff state
+   if(State == StateUnzipDiff) 
+   {
+
+      // rred excepts the patch as $FinalFile.ed
+      Rename(DestFile,FinalFile+".ed");
+
+      if(Debug)
+	 std::clog << "Sending to rred method: " << FinalFile << std::endl;
+
+      State = StateApplyDiff;
+      Local = true;
+      Desc.URI = "rred:" + FinalFile;
+      QueueURI(Desc);
+      Mode = "rred";
+      return;
+   } 
+
+
+   // success in download/apply a diff, queue next (if needed)
+   if(State == StateApplyDiff)
+   {
+      // remove the just applied patch
+      available_patches.erase(available_patches.begin());
+
+      // move into place
+      if(Debug) 
+      {
+	 std::clog << "Moving patched file in place: " << std::endl
+		   << DestFile << " -> " << FinalFile << std::endl;
+      }
+      Rename(DestFile,FinalFile);
+      chmod(FinalFile.c_str(),0644);
+
+      // see if there is more to download
+      if(available_patches.size() > 0) {
+	 new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc,
+			      ExpectedMD5, available_patches);
+	 return Finish();
+      } else 
+	 return Finish(true);
+   }
+}
+
+
 // AcqIndex::AcqIndex - Constructor					/*{{{*/
 // AcqIndex::AcqIndex - Constructor					/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* The package file is added to the queue and a second class is 
 /* The package file is added to the queue and a second class is 
    instantiated to fetch the revision file */   
    instantiated to fetch the revision file */   
 pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner,
 pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner,
 			 string URI,string URIDesc,string ShortDesc,
 			 string URI,string URIDesc,string ShortDesc,
-			 string ExpectedMD5, string comprExt) :
-   Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5)
+			 string ExpectedMD5, string comprExt)
+   : Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5)
 {
 {
    Decompression = false;
    Decompression = false;
    Erase = false;
    Erase = false;
@@ -183,7 +602,6 @@ string pkgAcqIndex::Custom600Headers()
 
 
 void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
 void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
 {
 {
-
    // no .bz2 found, retry with .gz
    // no .bz2 found, retry with .gz
    if(Desc.URI.substr(Desc.URI.size()-3) == "bz2") {
    if(Desc.URI.substr(Desc.URI.size()-3) == "bz2") {
       Desc.URI = Desc.URI.substr(0,Desc.URI.size()-3) + "gz"; 
       Desc.URI = Desc.URI.substr(0,Desc.URI.size()-3) + "gz"; 
@@ -315,6 +733,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,
@@ -328,8 +775,9 @@ pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner,
    DestFile = _config->FindDir("Dir::State::lists") + "partial/";
    DestFile = _config->FindDir("Dir::State::lists") + "partial/";
    DestFile += URItoFileName(URI);
    DestFile += URItoFileName(URI);
 
 
-   // remove any partial downloaded sig-file. it may confuse proxies
-   // and is too small to warrant a partial download anyway
+   // remove any partial downloaded sig-file in partial/. 
+   // it may confuse proxies and is too small to warrant a 
+   // partial download anyway
    unlink(DestFile.c_str());
    unlink(DestFile.c_str());
 
 
    // Create the item
    // Create the item
@@ -396,17 +844,22 @@ void pkgAcqMetaSig::Done(string Message,unsigned long Size,string MD5,
 									/*}}}*/
 									/*}}}*/
 void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
 void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
 {
 {
+   string Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI);
 
 
    // if we get a network error we fail gracefully
    // if we get a network error we fail gracefully
-   if(LookupTag(Message,"FailReason") == "Timeout" || 
-      LookupTag(Message,"FailReason") == "TmpResolveFailure" ||
-      LookupTag(Message,"FailReason") == "ConnectionRefused") {
+   if(Status == StatTransientNetworkError)
+   {
       Item::Failed(Message,Cnf);
       Item::Failed(Message,Cnf);
+      // move the sigfile back on transient network failures 
+      if(FileExists(DestFile))
+ 	 Rename(DestFile,Final);
+
+      // set the status back to , Item::Failed likes to reset it
+      Status = pkgAcquire::Item::StatTransientNetworkError;
       return;
       return;
    }
    }
 
 
    // Delete any existing sigfile when the acquire failed
    // Delete any existing sigfile when the acquire failed
-   string Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI);
    unlink(Final.c_str());
    unlink(Final.c_str());
 
 
    // queue a pkgAcqMetaIndex with no sigfile
    // queue a pkgAcqMetaIndex with no sigfile
@@ -539,6 +992,7 @@ void pkgAcqMetaIndex::RetrievalDone(string Message)
       // Move it into position
       // Move it into position
       Rename(DestFile,FinalFile);
       Rename(DestFile,FinalFile);
    }
    }
+   chmod(FinalFile.c_str(),0644);
    DestFile = FinalFile;
    DestFile = FinalFile;
 }
 }
 
 
@@ -608,9 +1062,14 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify)
          }
          }
       }
       }
       
       
-      // Queue Packages file
-      new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description,
-                      (*Target)->ShortDesc, ExpectedIndexMD5);
+      // Queue Packages file (either diff or full packages files, depending
+      // on the users option)
+      if(_config->FindB("Acquire::PDiffs",true) == true) 
+	 new pkgAcqDiffIndex(Owner, (*Target)->URI, (*Target)->Description,
+			     (*Target)->ShortDesc, ExpectedIndexMD5);
+      else 
+	 new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description,
+			    (*Target)->ShortDesc, ExpectedIndexMD5);
    }
    }
 }
 }
 
 

+ 700 - 35
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.
@@ -27,71 +27,492 @@
 #include <apt-pkg/pkgrecords.h>
 #include <apt-pkg/pkgrecords.h>
 #include <apt-pkg/indexrecords.h>
 #include <apt-pkg/indexrecords.h>
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/acquire-item.h"
-#endif 
 
 
-// Item to acquire
+/** \addtogroup acquire
+ *  @{
+ *
+ *  \file acquire-item.h
+ */
+
+/** \brief Represents the process by which a pkgAcquire object should
+ *  retrieve a file or a collection of files.
+ *
+ *  By convention, Item subclasses should insert themselves into the
+ *  acquire queue when they are created by calling QueueURI(), and
+ *  remove themselves by calling Dequeue() when either Done() or
+ *  Failed() is invoked.  Item objects are also responsible for
+ *  notifying the download progress indicator (accessible via
+ *  #Owner->Log) of their status.
+ *
+ *  \see pkgAcquire
+ */
 class pkgAcquire::Item
 class pkgAcquire::Item
 {  
 {  
    protected:
    protected:
    
    
-   // Some private helper methods for registering URIs
+   /** \brief The acquire object with which this item is associated. */
    pkgAcquire *Owner;
    pkgAcquire *Owner;
+
+   /** \brief Insert this item into its owner's queue.
+    *
+    *  \param ItemDesc Metadata about this item (its URI and
+    *  description).
+    */
    inline void QueueURI(ItemDesc &Item)
    inline void QueueURI(ItemDesc &Item)
                  {Owner->Enqueue(Item);};
                  {Owner->Enqueue(Item);};
+
+   /** \brief Remove this item from its owner's queue. */
    inline void Dequeue() {Owner->Dequeue(this);};
    inline void Dequeue() {Owner->Dequeue(this);};
    
    
-   // Safe rename function with timestamp preservation
+   /** \brief Rename a file without modifying its timestamp.
+    *
+    *  Many item methods call this as their final action.
+    *
+    *  \param From The file to be renamed.
+    *
+    *  \param To The new name of #From.  If #To exists it will be
+    *  overwritten.
+    */
    void Rename(string From,string To);
    void Rename(string From,string To);
    
    
    public:
    public:
 
 
-   // State of the item
-   enum {StatIdle, StatFetching, StatDone, StatError, StatAuthError} Status;
+   /** \brief The current status of this item. */
+   enum ItemState
+     {
+       /** \brief The item is waiting to be downloaded. */
+       StatIdle,
+
+       /** \brief The item is currently being downloaded. */
+       StatFetching,
+
+       /** \brief The item has been successfully downloaded. */
+       StatDone,
+
+       /** \brief An error was encountered while downloading this
+	*  item.
+	*/
+       StatError,
+
+       /** \brief The item was downloaded but its authenticity could
+	*  not be verified.
+	*/
+       StatAuthError,
+
+       /** \brief The item was could not be downloaded because of 
+	*  a transient network error (e.g. network down)
+	*/
+       StatTransientNetworkError
+     } Status;
+
+   /** \brief Contains a textual description of the error encountered
+    *  if #Status is #StatError or #StatAuthError.
+    */
    string ErrorText;
    string ErrorText;
+
+   /** \brief The size of the object to fetch. */
    unsigned long FileSize;
    unsigned long FileSize;
-   unsigned long PartialSize;   
+
+   /** \brief How much of the object was already fetched. */
+   unsigned long PartialSize;
+
+   /** \brief If not \b NULL, contains the name of a subprocess that
+    *  is operating on this object (for instance, "gzip" or "gpgv").
+    */
    const char *Mode;
    const char *Mode;
+
+   /** \brief A client-supplied unique identifier.
+    * 
+    *  This field is initalized to 0; it is meant to be filled in by
+    *  clients that wish to use it to uniquely identify items.
+    *
+    *  \todo it's unused in apt itself
+    */
    unsigned long ID;
    unsigned long ID;
+
+   /** \brief If \b true, the entire object has been successfully fetched.
+    *
+    *  Subclasses should set this to \b true when appropriate.
+    */
    bool Complete;
    bool Complete;
+
+   /** \brief If \b true, the URI of this object is "local".
+    *
+    *  The only effect of this field is to exclude the object from the
+    *  download progress indicator's overall statistics.
+    */
    bool Local;
    bool Local;
 
 
-   // Number of queues we are inserted into
+   /** \brief The number of fetch queues into which this item has been
+    *  inserted.
+    *
+    *  There is one queue for each source from which an item could be
+    *  downloaded.
+    *
+    *  \sa pkgAcquire
+    */
    unsigned int QueueCounter;
    unsigned int QueueCounter;
    
    
-   // File to write the fetch into
+   /** \brief The name of the file into which the retrieved object
+    *  will be written.
+    */
    string DestFile;
    string DestFile;
 
 
-   // Action members invoked by the worker
+   /** \brief Invoked by the acquire worker when the object couldn't
+    *  be fetched.
+    *
+    *  This is a branch of the continuation of the fetch process.
+    *
+    *  \param Message An RFC822-formatted message from the acquire
+    *  method describing what went wrong.  Use LookupTag() to parse
+    *  it.
+    *
+    *  \param Cnf The method via which the worker tried to fetch this object.
+    *
+    *  \sa pkgAcqMethod
+    */
    virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
    virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
+
+   /** \brief Invoked by the acquire worker when the object was
+    *  fetched successfully.
+    *
+    *  Note that the object might \e not have been written to
+    *  DestFile; check for the presence of an Alt-Filename entry in
+    *  Message to find the file to which it was really written.
+    *
+    *  Done is often used to switch from one stage of the processing
+    *  to the next (e.g. fetching, unpacking, copying).  It is one
+    *  branch of the continuation of the fetch process.
+    *
+    *  \param Message Data from the acquire method.  Use LookupTag()
+    *  to parse it.
+    *  \param Size The size of the object that was fetched.
+    *  \param Md5Hash The MD5Sum of the object that was fetched.
+    *  \param Cnf The method via which the object was fetched.
+    *
+    *  \sa pkgAcqMethod
+    */
    virtual void Done(string Message,unsigned long Size,string Md5Hash,
    virtual void Done(string Message,unsigned long Size,string Md5Hash,
 		     pkgAcquire::MethodConfig *Cnf);
 		     pkgAcquire::MethodConfig *Cnf);
+
+   /** \brief Invoked when the worker starts to fetch this object.
+    *
+    *  \param Message RFC822-formatted data from the worker process.
+    *  Use LookupTag() to parse it.
+    *
+    *  \param Size The size of the object being fetched.
+    *
+    *  \sa pkgAcqMethod
+    */
    virtual void Start(string Message,unsigned long Size);
    virtual void Start(string Message,unsigned long Size);
+
+   /** \brief Custom headers to be sent to the fetch process.
+    *
+    *  \return a string containing RFC822-style headers that are to be
+    *  inserted into the 600 URI Acquire message sent to the fetch
+    *  subprocess.  The headers are inserted after a newline-less
+    *  line, so they should (if nonempty) have a leading newline and
+    *  no trailing newline.
+    */
    virtual string Custom600Headers() {return string();};
    virtual string Custom600Headers() {return string();};
+
+   /** \brief A "descriptive" URI-like string.
+    *
+    *  \return a URI that should be used to describe what is being fetched.
+    */
    virtual string DescURI() = 0;
    virtual string DescURI() = 0;
+   /** \brief Short item description.
+    *
+    *  \return a brief description of the object being fetched.
+    */
    virtual string ShortDesc() {return DescURI();}
    virtual string ShortDesc() {return DescURI();}
+
+   /** \brief Invoked by the worker when the download is completely done. */
    virtual void Finished() {};
    virtual void Finished() {};
    
    
-   // Inquire functions
+   /** \brief MD5Sum.
+    *
+    *  \return the MD5Sum of this object, if applicable; otherwise, an
+    *  empty string.
+    */
    virtual string MD5Sum() {return string();};
    virtual string MD5Sum() {return string();};
+
+   /** \return the acquire process with which this item is associated. */
    pkgAcquire *GetOwner() {return Owner;};
    pkgAcquire *GetOwner() {return Owner;};
+
+   /** \return \b true if this object is being fetched from a trusted source. */
    virtual bool IsTrusted() {return false;};
    virtual bool IsTrusted() {return false;};
-   
+
+   /** \brief Initialize an item.
+    *
+    *  Adds the item to the list of items known to the acquire
+    *  process, but does not place it into any fetch queues (you must
+    *  manually invoke QueueURI() to do so).
+    *
+    *  Initializes all fields of the item other than Owner to 0,
+    *  false, or the empty string.
+    *
+    *  \param Owner The new owner of this item.
+    */
    Item(pkgAcquire *Owner);
    Item(pkgAcquire *Owner);
+
+   /** \brief Remove this item from its owner's queue by invoking
+    *  pkgAcquire::Remove.
+    */
    virtual ~Item();
    virtual ~Item();
 };
 };
 
 
-// Item class for index files
-class pkgAcqIndex : public pkgAcquire::Item
+/** \brief Information about an index patch (aka diff). */
+struct DiffInfo {
+   /** The filename of the diff. */
+   string file;
+
+   /** The sha1 hash of the diff. */
+   string sha1;
+
+   /** The size of the diff. */
+   unsigned long size;
+};
+
+/** \brief An item that is responsible for fetching an index file of
+ *  package list diffs and starting the package list's download.
+ *
+ *  This item downloads the Index file and parses it, then enqueues
+ *  additional downloads of either the individual patches (using
+ *  pkgAcqIndexDiffs) or the entire Packages file (using pkgAcqIndex).
+ *
+ *  \sa pkgAcqIndexDiffs, pkgAcqIndex
+ */
+class pkgAcqDiffIndex : public pkgAcquire::Item
 {
 {
+ protected:
+   /** \brief If \b true, debugging information will be written to std::clog. */
+   bool Debug;
+
+   /** \brief The item that is currently being downloaded. */
+   pkgAcquire::ItemDesc Desc;
+
+   /** \brief The URI of the index file to recreate at our end (either
+    *  by downloading it or by applying partial patches).
+    */
+   string RealURI;
+
+   /** \brief The MD5Sum that the real index file should have after
+    *  all patches have been applied.
+    */
+   string ExpectedMD5;
+
+   /** \brief The index file which will be patched to generate the new
+    *  file.
+    */
+   string CurrentPackagesFile;
+
+   /** \brief A description of the Packages file (stored in
+    *  pkgAcquire::ItemDesc::Description).
+    */
+   string Description;
+
+ public:
+   // Specialized action members
+   virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
+   virtual void Done(string Message,unsigned long Size,string Md5Hash,
+		     pkgAcquire::MethodConfig *Cnf);
+   virtual string DescURI() {return RealURI + "Index";};
+   virtual string Custom600Headers();
+
+   /** \brief Parse the Index file for a set of Packages diffs.
+    *
+    *  Parses the Index file and creates additional download items as
+    *  necessary.
+    *
+    *  \param IndexDiffFile The name of the Index file.
+    *
+    *  \return \b true if the Index file was successfully parsed, \b
+    *  false otherwise.
+    */
+   bool ParseDiffIndex(string IndexDiffFile);
+   
+
+   /** \brief Create a new pkgAcqDiffIndex.
+    *
+    *  \param Owner The Acquire object that owns this item.
+    *
+    *  \param URI The URI of the list file to download.
+    *
+    *  \param URIDesc A long description of the list file to download.
+    *
+    *  \param ShortDesc A short description of the list file to download.
+    *
+    *  \param ExpectedMD5 The list file's MD5 signature.
+    */
+   pkgAcqDiffIndex(pkgAcquire *Owner,string URI,string URIDesc,
+		   string ShortDesc, string ExpectedMD5);
+};
+
+/** \brief An item that is responsible for fetching all the patches
+ *  that need to be applied to a given package index file.
+ *
+ *  After downloading and applying a single patch, this item will
+ *  enqueue a new pkgAcqIndexDiffs to download and apply the remaining
+ *  patches.  If no patch can be found that applies to an intermediate
+ *  file or if one of the patches cannot be downloaded, falls back to
+ *  downloading the entire package index file using pkgAcqIndex.
+ *
+ *  \sa pkgAcqDiffIndex, pkgAcqIndex
+ */
+class pkgAcqIndexDiffs : public pkgAcquire::Item
+{
+   private:
+
+   /** \brief Queue up the next diff download.
+    *
+    *  Search for the next available diff that applies to the file
+    *  that currently exists on disk, and enqueue it by calling
+    *  QueueURI().
+    *
+    *  \return \b true if an applicable diff was found, \b false
+    *  otherwise.
+    */
+   bool QueueNextDiff();
+
+   /** \brief Handle tasks that must be performed after the item
+    *  finishes downloading.
+    *
+    *  Dequeues the item and checks the resulting file's md5sum
+    *  against ExpectedMD5 after the last patch was applied.
+    *  There is no need to check the md5/sha1 after a "normal" 
+    *  patch because QueueNextDiff() will check the sha1 later.
+    *
+    *  \param allDone If \b true, the file was entirely reconstructed,
+    *  and its md5sum is verified. 
+    */
+   void Finish(bool allDone=false);
+
    protected:
    protected:
+
+   /** \brief If \b true, debugging output will be written to
+    *  std::clog.
+    */
+   bool Debug;
+
+   /** \brief A description of the item that is currently being
+    *  downloaded.
+    */
+   pkgAcquire::ItemDesc Desc;
+
+   /** \brief The URI of the package index file that is being
+    *  reconstructed.
+    */
+   string RealURI;
+
+   /** \brief The MD5Sum of the package index file that is being
+    *  reconstructed.
+    */
+   string ExpectedMD5;
+
+   /** A description of the file being downloaded. */
+   string Description;
+
+   /** The patches that remain to be downloaded, including the patch
+    *  being downloaded right now.  This list should be ordered so
+    *  that each diff appears before any diff that depends on it.
+    *
+    *  \todo These are indexed by sha1sum; why not use some sort of
+    *  dictionary instead of relying on ordering and stripping them
+    *  off the front?
+    */
+   vector<DiffInfo> available_patches;
+   /** The current status of this patch. */
+   enum DiffState
+     {
+	/** \brief The diff is in an unknown state. */
+	 StateFetchUnkown,
+
+	 /** \brief The diff is currently being fetched. */
+	 StateFetchDiff,
+	 
+	 /** \brief The diff is currently being uncompressed. */
+	 StateUnzipDiff,
+
+	 /** \brief The diff is currently being applied. */
+	 StateApplyDiff
+   } State;
+
+   public:
    
    
+   /** \brief Called when the patch file failed to be downloaded.
+    *
+    *  This method will fall back to downloading the whole index file
+    *  outright; its arguments are ignored.
+    */
+   virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
+
+   virtual void Done(string Message,unsigned long Size,string Md5Hash,
+		     pkgAcquire::MethodConfig *Cnf);
+   virtual string DescURI() {return RealURI + "Index";};
+
+   /** \brief Create an index diff item.
+    *
+    *  After filling in its basic fields, this invokes Finish(true) if
+    *  #diffs is empty, or QueueNextDiff() otherwise.
+    *
+    *  \param Owner The pkgAcquire object that owns this item.
+    *
+    *  \param URI The URI of the package index file being
+    *  reconstructed.
+    *
+    *  \param URIDesc A long description of this item.
+    *
+    *  \param ShortDesc A brief description of this item.
+    *
+    *  \param ExpectedMD5 The expected md5sum of the completely
+    *  reconstructed package index file; the index file will be tested
+    *  against this value when it is entirely reconstructed.
+    *
+    *  \param diffs The remaining diffs from the index of diffs.  They
+    *  should be ordered so that each diff appears before any diff
+    *  that depends on it.
+    */
+   pkgAcqIndexDiffs(pkgAcquire *Owner,string URI,string URIDesc,
+		    string ShortDesc, string ExpectedMD5,
+		    vector<DiffInfo> diffs=vector<DiffInfo>());
+};
+
+/** \brief An acquire item that is responsible for fetching an index
+ *  file (e.g., Packages or Sources).
+ *
+ *  \sa pkgAcqDiffIndex, pkgAcqIndexDiffs, pkgAcqIndexTrans
+ *
+ *  \todo Why does pkgAcqIndex have protected members?
+ */
+class pkgAcqIndex : public pkgAcquire::Item
+{
+   protected:
+
+   /** \brief If \b true, the index file has been decompressed. */
    bool Decompression;
    bool Decompression;
+
+   /** \brief If \b true, the partially downloaded file will be
+    *  removed when the download completes.
+    */
    bool Erase;
    bool Erase;
+
+   /** \brief The download request that is currently being
+    *   processed.
+    */
    pkgAcquire::ItemDesc Desc;
    pkgAcquire::ItemDesc Desc;
+
+   /** \brief The object that is actually being fetched (minus any
+    *  compression-related extensions).
+    */
    string RealURI;
    string RealURI;
+
+   /** \brief The expected md5sum of the decompressed index file. */
    string ExpectedMD5;
    string ExpectedMD5;
+
+   /** \brief The compression-related file extension that is being
+    *  added to the downloaded file (e.g., ".gz" or ".bz2").
+    */
    string CompressionExtension;
    string CompressionExtension;
 
 
    public:
    public:
@@ -103,26 +524,120 @@ class pkgAcqIndex : public pkgAcquire::Item
    virtual string Custom600Headers();
    virtual string Custom600Headers();
    virtual string DescURI() {return RealURI + CompressionExtension;};
    virtual string DescURI() {return RealURI + CompressionExtension;};
 
 
+   /** \brief Create a pkgAcqIndex.
+    *
+    *  \param Owner The pkgAcquire object with which this item is
+    *  associated.
+    *
+    *  \param URI The URI of the index file that is to be downloaded.
+    *
+    *  \param URIDesc A "URI-style" description of this index file.
+    *
+    *  \param ShortDesc A brief description of this index file.
+    *
+    *  \param ExpectedMD5 The expected md5sum of this index file.
+    *
+    *  \param compressExt The compression-related extension with which
+    *  this index file should be downloaded, or "" to autodetect
+    *  (".bz2" is used if bzip2 is installed, ".gz" otherwise).
+    */
    pkgAcqIndex(pkgAcquire *Owner,string URI,string URIDesc,
    pkgAcqIndex(pkgAcquire *Owner,string URI,string URIDesc,
-	       string ShortDesct, string ExpectedMD5, string compressExt="");
+	       string ShortDesc, string ExpectedMD5, string compressExt="");
+};
+
+/** \brief An acquire item that is responsible for fetching a
+ *  translated index file.
+ *
+ *  The only difference from pkgAcqIndex is that transient failures
+ *  are suppressed: no error occurs if the translated index file is
+ *  missing.
+ */
+class pkgAcqIndexTrans : public pkgAcqIndex
+{
+   public:
+  
+   virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
+
+   /** \brief Create a pkgAcqIndexTrans.
+    *
+    *  \param Owner The pkgAcquire object with which this item is
+    *  associated.
+    *
+    *  \param URI The URI of the index file that is to be downloaded.
+    *
+    *  \param URIDesc A "URI-style" description of this index file.
+    *
+    *  \param ShortDesc A brief description of this index file.
+    *
+    *  \param ExpectedMD5 The expected md5sum of this index file.
+    *
+    *  \param compressExt The compression-related extension with which
+    *  this index file should be downloaded, or "" to autodetect
+    *  (".bz2" is used if bzip2 is installed, ".gz" otherwise).
+    */
+   pkgAcqIndexTrans(pkgAcquire *Owner,string URI,string URIDesc,
+		    string ShortDesc);
 };
 };
 
 
+/** \brief Information about an index file. */
 struct IndexTarget
 struct IndexTarget
 {
 {
+   /** \brief A URI from which the index file can be downloaded. */
    string URI;
    string URI;
+
+   /** \brief A description of the index file. */
    string Description;
    string Description;
+
+   /** \brief A shorter description of the index file. */
    string ShortDesc;
    string ShortDesc;
+
+   /** \brief The key by which this index file should be
+    *  looked up within the meta signature file.
+    */
    string MetaKey;
    string MetaKey;
 };
 };
 
 
-// Item class for index signatures
+/** \brief An acquire item that downloads the detached signature
+ *  of a meta-index (Release) file, then queues up the release
+ *  file itself.
+ *
+ *  \todo Why protected members?
+ *
+ *  \sa pkgAcqMetaIndex
+ */
 class pkgAcqMetaSig : public pkgAcquire::Item
 class pkgAcqMetaSig : public pkgAcquire::Item
 {
 {
    protected:
    protected:
-   
+   /** \brief The fetch request that is currently being processed. */
    pkgAcquire::ItemDesc Desc;
    pkgAcquire::ItemDesc Desc;
-   string RealURI,MetaIndexURI,MetaIndexURIDesc,MetaIndexShortDesc;
+
+   /** \brief The URI of the signature file.  Unlike Desc.URI, this is
+    *  never modified; it is used to determine the file that is being
+    *  downloaded.
+    */
+   string RealURI;
+
+   /** \brief The URI of the meta-index file to be fetched after the signature. */
+   string MetaIndexURI;
+
+   /** \brief A "URI-style" description of the meta-index file to be
+    *  fetched after the signature.
+    */
+   string MetaIndexURIDesc;
+
+   /** \brief A brief description of the meta-index file to be fetched
+    *  after the signature.
+    */
+   string MetaIndexShortDesc;
+
+   /** \brief A package-system-specific parser for the meta-index file. */
    indexRecords* MetaIndexParser;
    indexRecords* MetaIndexParser;
+
+   /** \brief The index files which should be looked up in the meta-index
+    *  and then downloaded.
+    *
+    *  \todo Why a list of pointers instead of a list of structs?
+    */
    const vector<struct IndexTarget*>* IndexTargets;
    const vector<struct IndexTarget*>* IndexTargets;
 
 
    public:
    public:
@@ -134,29 +649,90 @@ class pkgAcqMetaSig : public pkgAcquire::Item
    virtual string Custom600Headers();
    virtual string Custom600Headers();
    virtual string DescURI() {return RealURI; };
    virtual string DescURI() {return RealURI; };
 
 
+   /** \brief Create a new pkgAcqMetaSig. */
    pkgAcqMetaSig(pkgAcquire *Owner,string URI,string URIDesc, string ShortDesc,
    pkgAcqMetaSig(pkgAcquire *Owner,string URI,string URIDesc, string ShortDesc,
 		 string MetaIndexURI, string MetaIndexURIDesc, string MetaIndexShortDesc,
 		 string MetaIndexURI, string MetaIndexURIDesc, string MetaIndexShortDesc,
 		 const vector<struct IndexTarget*>* IndexTargets,
 		 const vector<struct IndexTarget*>* IndexTargets,
 		 indexRecords* MetaIndexParser);
 		 indexRecords* MetaIndexParser);
 };
 };
 
 
-// Item class for index signatures
+/** \brief An item that is responsible for downloading the meta-index
+ *  file (i.e., Release) itself and verifying its signature.
+ *
+ *  Once the download and verification are complete, the downloads of
+ *  the individual index files are queued up using pkgAcqDiffIndex.
+ *  If the meta-index file had a valid signature, the expected md5sums
+ *  of the index files will be the md5sums listed in the meta-index;
+ *  otherwise, the expected md5sums will be "" (causing the
+ *  authentication of the index files to be bypassed).
+ */
 class pkgAcqMetaIndex : public pkgAcquire::Item
 class pkgAcqMetaIndex : public pkgAcquire::Item
 {
 {
    protected:
    protected:
-   
+   /** \brief The fetch command that is currently being processed. */
    pkgAcquire::ItemDesc Desc;
    pkgAcquire::ItemDesc Desc;
-   string RealURI; // FIXME: is this redundant w/ Desc.URI?
+
+   /** \brief The URI that is actually being downloaded; never
+    *  modified by pkgAcqMetaIndex.
+    */
+   string RealURI;
+
+   /** \brief The file in which the signature for this index was stored.
+    *
+    *  If empty, the signature and the md5sums of the individual
+    *  indices will not be checked.
+    */
    string SigFile;
    string SigFile;
+
+   /** \brief The index files to download. */
    const vector<struct IndexTarget*>* IndexTargets;
    const vector<struct IndexTarget*>* IndexTargets;
+
+   /** \brief The parser for the meta-index file. */
    indexRecords* MetaIndexParser;
    indexRecords* MetaIndexParser;
+
+   /** \brief If \b true, the index's signature is currently being verified.
+    */
    bool AuthPass;
    bool AuthPass;
    // required to deal gracefully with problems caused by incorrect ims hits
    // required to deal gracefully with problems caused by incorrect ims hits
    bool IMSHit; 
    bool IMSHit; 
 
 
+   /** \brief Check that the release file is a release file for the
+    *  correct distribution.
+    *
+    *  \return \b true if no fatal errors were encountered.
+    */
    bool VerifyVendor(string Message);
    bool VerifyVendor(string Message);
+
+   /** \brief Called when a file is finished being retrieved.
+    *
+    *  If the file was not downloaded to DestFile, a copy process is
+    *  set up to copy it to DestFile; otherwise, Complete is set to \b
+    *  true and the file is moved to its final location.
+    *
+    *  \param Message The message block received from the fetch
+    *  subprocess.
+    */
    void RetrievalDone(string Message);
    void RetrievalDone(string Message);
+
+   /** \brief Called when authentication succeeded.
+    *
+    *  Sanity-checks the authenticated file, queues up the individual
+    *  index files for download, and saves the signature in the lists
+    *  directory next to the authenticated list file.
+    *
+    *  \param Message The message block received from the fetch
+    *  subprocess.
+    */
    void AuthDone(string Message);
    void AuthDone(string Message);
+
+   /** \brief Starts downloading the individual index files.
+    *
+    *  \param verify If \b true, only indices whose expected md5sum
+    *  can be determined from the meta-index will be downloaded, and
+    *  the md5sums of indices will be checked (reporting
+    *  #StatAuthError if there is a mismatch).  If verify is \b false,
+    *  no md5sum checking will be performed.
+    */
    void QueueIndexes(bool verify);
    void QueueIndexes(bool verify);
    
    
    public:
    public:
@@ -168,6 +744,7 @@ class pkgAcqMetaIndex : public pkgAcquire::Item
    virtual string Custom600Headers();
    virtual string Custom600Headers();
    virtual string DescURI() {return RealURI; };
    virtual string DescURI() {return RealURI; };
 
 
+   /** \brief Create a new pkgAcqMetaIndex. */
    pkgAcqMetaIndex(pkgAcquire *Owner,
    pkgAcqMetaIndex(pkgAcquire *Owner,
 		   string URI,string URIDesc, string ShortDesc,
 		   string URI,string URIDesc, string ShortDesc,
 		   string SigFile,
 		   string SigFile,
@@ -175,28 +752,58 @@ class pkgAcqMetaIndex : public pkgAcquire::Item
 		   indexRecords* MetaIndexParser);
 		   indexRecords* MetaIndexParser);
 };
 };
 
 
-// Item class for archive files
+/** \brief An item that is responsible for fetching a package file.
+ *
+ *  If the package file already exists in the cache, nothing will be
+ *  done.
+ */
 class pkgAcqArchive : public pkgAcquire::Item
 class pkgAcqArchive : public pkgAcquire::Item
 {
 {
    protected:
    protected:
-   
-   // State information for the retry mechanism
+   /** \brief The package version being fetched. */
    pkgCache::VerIterator Version;
    pkgCache::VerIterator Version;
+
+   /** \brief The fetch command that is currently being processed. */
    pkgAcquire::ItemDesc Desc;
    pkgAcquire::ItemDesc Desc;
+
+   /** \brief The list of sources from which to pick archives to
+    *  download this package from.
+    */
    pkgSourceList *Sources;
    pkgSourceList *Sources;
+
+   /** \brief A package records object, used to look up the file
+    *  corresponding to each version of the package.
+    */
    pkgRecords *Recs;
    pkgRecords *Recs;
+
+   /** \brief The md5sum of this package. */
    string MD5;
    string MD5;
+
+   /** \brief A location in which the actual filename of the package
+    *  should be stored.
+    */
    string &StoreFilename;
    string &StoreFilename;
+
+   /** \brief The next file for this version to try to download. */
    pkgCache::VerFileIterator Vf;
    pkgCache::VerFileIterator Vf;
+
+   /** \brief How many (more) times to try to find a new source from
+    *  which to download this package version if it fails.
+    *
+    *  Set from Acquire::Retries.
+    */
    unsigned int Retries;
    unsigned int Retries;
+
+   /** \brief \b true if this version file is being downloaded from a
+    *  trusted source.
+    */
    bool Trusted; 
    bool Trusted; 
 
 
-   // Queue the next available file for download.
+   /** \brief Queue up the next available file for this version. */
    bool QueueNext();
    bool QueueNext();
    
    
    public:
    public:
    
    
-   // Specialized action members
    virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
    virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
    virtual void Done(string Message,unsigned long Size,string Md5Hash,
    virtual void Done(string Message,unsigned long Size,string Md5Hash,
 		     pkgAcquire::MethodConfig *Cnf);
 		     pkgAcquire::MethodConfig *Cnf);
@@ -204,18 +811,49 @@ class pkgAcqArchive : public pkgAcquire::Item
    virtual string DescURI() {return Desc.URI;};
    virtual string DescURI() {return Desc.URI;};
    virtual string ShortDesc() {return Desc.ShortDesc;};
    virtual string ShortDesc() {return Desc.ShortDesc;};
    virtual void Finished();
    virtual void Finished();
+
    virtual bool IsTrusted();
    virtual bool IsTrusted();
    
    
+   /** \brief Create a new pkgAcqArchive.
+    *
+    *  \param Owner The pkgAcquire object with which this item is
+    *  associated.
+    *
+    *  \param Sources The sources from which to download version
+    *  files.
+    *
+    *  \param Recs A package records object, used to look up the file
+    *  corresponding to each version of the package.
+    *
+    *  \param Version The package version to download.
+    *
+    *  \param StoreFilename A location in which the actual filename of
+    *  the package should be stored.  It will be set to a guessed
+    *  basename in the constructor, and filled in with a fully
+    *  qualified filename once the download finishes.
+    */
    pkgAcqArchive(pkgAcquire *Owner,pkgSourceList *Sources,
    pkgAcqArchive(pkgAcquire *Owner,pkgSourceList *Sources,
 		 pkgRecords *Recs,pkgCache::VerIterator const &Version,
 		 pkgRecords *Recs,pkgCache::VerIterator const &Version,
 		 string &StoreFilename);
 		 string &StoreFilename);
 };
 };
 
 
-// Fetch a generic file to the current directory
+/** \brief Retrieve an arbitrary file to the current directory.
+ *
+ *  The file is retrieved even if it is accessed via a URL type that
+ *  normally is a NOP, such as "file".  If the download fails, the
+ *  partial file is renamed to get a ".FAILED" extension.
+ */
 class pkgAcqFile : public pkgAcquire::Item
 class pkgAcqFile : public pkgAcquire::Item
 {
 {
+   /** \brief The currently active download process. */
    pkgAcquire::ItemDesc Desc;
    pkgAcquire::ItemDesc Desc;
+
+   /** \brief The md5sum of the file to download, if it is known. */
    string Md5Hash;
    string Md5Hash;
+
+   /** \brief How many times to retry the download, set from
+    *  Acquire::Retries.
+    */
    unsigned int Retries;
    unsigned int Retries;
    
    
    public:
    public:
@@ -227,13 +865,40 @@ class pkgAcqFile : public pkgAcquire::Item
    virtual string MD5Sum() {return Md5Hash;};
    virtual string MD5Sum() {return Md5Hash;};
    virtual string DescURI() {return Desc.URI;};
    virtual string DescURI() {return Desc.URI;};
 
 
-   // If DestFilename is empty, download to DestDir/<basename> if
-   // DestDir is non-empty, $CWD/<basename> otherwise.  If
-   // DestFilename is NOT empty, DestDir is ignored and DestFilename
-   // is the absolute name to which the file should be downloaded.
+   /** \brief Create a new pkgAcqFile object.
+    *
+    *  \param Owner The pkgAcquire object with which this object is
+    *  associated.
+    *
+    *  \param URI The URI to download.
+    *
+    *  \param MD5 The md5sum of the file to download, if it is known;
+    *  otherwise "".
+    *
+    *  \param Size The size of the file to download, if it is known;
+    *  otherwise 0.
+    *
+    *  \param Desc A description of the file being downloaded.
+    *
+    *  \param ShortDesc A brief description of the file being
+    *  downloaded.
+    *
+    *  \param DestDir The directory the file should be downloaded into.
+    *
+    *  \param DestFilename The filename+path the file is downloaded to.
+    *
+    *
+    * If DestFilename is empty, download to DestDir/<basename> if
+    * DestDir is non-empty, $CWD/<basename> otherwise.  If
+    * DestFilename is NOT empty, DestDir is ignored and DestFilename
+    * is the absolute name to which the file should be downloaded.
+    */
+
    pkgAcqFile(pkgAcquire *Owner, string URI, string MD5, unsigned long Size,
    pkgAcqFile(pkgAcquire *Owner, string URI, string MD5, unsigned long Size,
 	      string Desc, string ShortDesc,
 	      string Desc, string ShortDesc,
 	      const string &DestDir="", const string &DestFilename="");
 	      const string &DestDir="", const string &DestFilename="");
 };
 };
 
 
+/** @} */
+
 #endif
 #endif

+ 0 - 3
apt-pkg/acquire-method.cc

@@ -15,9 +15,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/acquire-method.h"
-#endif
 #include <apt-pkg/acquire-method.h>
 #include <apt-pkg/acquire-method.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/configuration.h>

+ 9 - 3
apt-pkg/acquire-method.h

@@ -10,15 +10,19 @@
    
    
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
+
+/** \addtogroup acquire
+ *  @{
+ *
+ *  \file acquire-method.h
+ */
+
 #ifndef PKGLIB_ACQUIRE_METHOD_H
 #ifndef PKGLIB_ACQUIRE_METHOD_H
 #define PKGLIB_ACQUIRE_METHOD_H
 #define PKGLIB_ACQUIRE_METHOD_H
 
 
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/strutl.h>
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/acquire-method.h"
-#endif 
 
 
 class Hashes;
 class Hashes;
 class pkgAcqMethod
 class pkgAcqMethod
@@ -86,4 +90,6 @@ class pkgAcqMethod
    virtual ~pkgAcqMethod() {};
    virtual ~pkgAcqMethod() {};
 };
 };
 
 
+/** @} */
+
 #endif
 #endif

+ 7 - 3
apt-pkg/acquire-worker.cc

@@ -12,9 +12,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/acquire-worker.h"
-#endif
 #include <apt-pkg/acquire-worker.h>
 #include <apt-pkg/acquire-worker.h>
 #include <apt-pkg/acquire-item.h>
 #include <apt-pkg/acquire-item.h>
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/configuration.h>
@@ -307,6 +304,13 @@ bool pkgAcquire::Worker::RunMessages()
 	    pkgAcquire::Item *Owner = Itm->Owner;
 	    pkgAcquire::Item *Owner = Itm->Owner;
 	    pkgAcquire::ItemDesc Desc = *Itm;
 	    pkgAcquire::ItemDesc Desc = *Itm;
 	    OwnerQ->ItemDone(Itm);
 	    OwnerQ->ItemDone(Itm);
+
+	    // set some status
+	    if(LookupTag(Message,"FailReason") == "Timeout" || 
+	       LookupTag(Message,"FailReason") == "TmpResolveFailure" ||
+	       LookupTag(Message,"FailReason") == "ConnectionRefused") 
+	       Owner->Status = pkgAcquire::Item::StatTransientNetworkError;
+
 	    Owner->Failed(Message,Config);
 	    Owner->Failed(Message,Config);
 	    ItemDone();
 	    ItemDone();
 
 

+ 247 - 15
apt-pkg/acquire-worker.h

@@ -9,16 +9,38 @@
    
    
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
+
+/** \addtogroup acquire
+ *  @{
+ *
+ *  \file acquire-worker.h
+ */
+
 #ifndef PKGLIB_ACQUIRE_WORKER_H
 #ifndef PKGLIB_ACQUIRE_WORKER_H
 #define PKGLIB_ACQUIRE_WORKER_H
 #define PKGLIB_ACQUIRE_WORKER_H
 
 
 #include <apt-pkg/acquire.h>
 #include <apt-pkg/acquire.h>
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/acquire-worker.h"
-#endif 
 
 
-// Interfacing to the method process
+/** \brief A fetch subprocess.
+ *
+ *  A worker process is responsible for one stage of the fetch.  This
+ *  class encapsulates the communications protocol between the master
+ *  process and the worker, from the master end.
+ *
+ *  Each worker is intrinsically placed on two linked lists.  The
+ *  Queue list (maintained in the #NextQueue variable) is maintained
+ *  by the pkgAcquire::Queue class; it represents the set of workers
+ *  assigned to a particular queue.  The Acquire list (maintained in
+ *  the #NextAcquire variable) is maintained by the pkgAcquire class;
+ *  it represents the set of active workers for a particular
+ *  pkgAcquire object.
+ *
+ *  \todo Like everything else in the Acquire system, this has way too
+ *  many protected items.
+ *
+ *  \sa pkgAcqMethod, pkgAcquire::Item, pkgAcquire
+ */
 class pkgAcquire::Worker
 class pkgAcquire::Worker
 {
 {
    friend class pkgAcquire;
    friend class pkgAcquire;
@@ -26,64 +48,274 @@ class pkgAcquire::Worker
    protected:
    protected:
    friend class Queue;
    friend class Queue;
 
 
-   /* Linked list starting at a Queue and a linked list starting
-      at Acquire */
+   /** \brief The next link on the Queue list.
+    *
+    *  \todo This is always NULL; is it just for future use?
+    */
    Worker *NextQueue;
    Worker *NextQueue;
+
+   /** \brief The next link on the Acquire list. */
    Worker *NextAcquire;
    Worker *NextAcquire;
    
    
-   // The access association
+   /** \brief The Queue with which this worker is associated. */
    Queue *OwnerQ;
    Queue *OwnerQ;
+
+   /** \brief The download progress indicator to which progress
+    *  messages should be sent.
+    */
    pkgAcquireStatus *Log;
    pkgAcquireStatus *Log;
+
+   /** \brief The configuration of this method.  On startup, the
+    *  target of this pointer is filled in with basic data about the
+    *  method, as reported by the worker.
+    */
    MethodConfig *Config;
    MethodConfig *Config;
+
+   /** \brief The access method to be used by this worker.
+    *
+    *  \todo Doesn't this duplicate Config->Access?
+    */
    string Access;
    string Access;
 
 
-   // This is the subprocess IPC setup
+   /** \brief The PID of the subprocess. */
    pid_t Process;
    pid_t Process;
+
+   /** \brief A file descriptor connected to the standard output of
+    *  the subprocess.
+    *
+    *  Used to read messages and data from the subprocess.
+    */
    int InFd;
    int InFd;
+
+   /** \brief A file descriptor connected to the standard input of the
+    *  subprocess.
+    *
+    *  Used to send commands and configuration data to the subprocess.
+    */
    int OutFd;
    int OutFd;
+
+   /** \brief Set to \b true if the worker is in a state in which it
+    *  might generate data or command responses.
+    *
+    *  \todo Is this right?  It's a guess.
+    */
    bool InReady;
    bool InReady;
+
+   /** \brief Set to \b true if the worker is in a state in which it
+    *  is legal to send commands to it.
+    *
+    *  \todo Is this right?
+    */
    bool OutReady;
    bool OutReady;
    
    
-   // Various internal things
+   /** If \b true, debugging output will be sent to std::clog. */
    bool Debug;
    bool Debug;
+
+   /** \brief The raw text values of messages received from the
+    *  worker, in sequence.
+    */
    vector<string> MessageQueue;
    vector<string> MessageQueue;
+
+   /** \brief Buffers pending writes to the subprocess.
+    *
+    *  \todo Wouldn't a std::dequeue be more appropriate?
+    */
    string OutQueue;
    string OutQueue;
    
    
-   // Private constructor helper
+   /** \brief Common code for the constructor.
+    *
+    *  Initializes NextQueue and NextAcquire to NULL; Process, InFd,
+    *  and OutFd to -1, OutReady and InReady to \b false, and Debug
+    *  from _config.
+    */
    void Construct();
    void Construct();
    
    
-   // Message handling things
+   /** \brief Retrieve any available messages from the subprocess.
+    *
+    *  The messages are retrieved as in ::ReadMessages(), and
+    *  MessageFailure() is invoked if an error occurs; in particular,
+    *  if the pipe to the subprocess dies unexpectedly while a message
+    *  is being read.
+    *
+    *  \return \b true if the messages were successfully read, \b
+    *  false otherwise.
+    */
    bool ReadMessages();
    bool ReadMessages();
+
+   /** \brief Parse and dispatch pending messages.
+    *
+    *  This dispatches the message in a manner appropriate for its
+    *  type.
+    *
+    *  \todo Several message types lack separate handlers.
+    *
+    *  \sa Capabilities(), SendConfiguration(), MediaChange()
+    */
    bool RunMessages();
    bool RunMessages();
+
+   /** \brief Read and dispatch any pending messages from the
+    *  subprocess.
+    *
+    *  \return \b false if the subprocess died unexpectedly while a
+    *  message was being transmitted.
+    */
    bool InFdReady();
    bool InFdReady();
+
+   /** \brief Send any pending commands to the subprocess.
+    *
+    *  This method will fail if there is no pending output.
+    *
+    *  \return \b true if all commands were succeeded, \b false if an
+    *  error occurred (in which case MethodFailure() will be invoked).
+    */
    bool OutFdReady();
    bool OutFdReady();
    
    
-   // The message handlers
+   /** \brief Handle a 100 Capabilities response from the subprocess.
+    *
+    *  \param Message the raw text of the message from the subprocess.
+    *
+    *  The message will be parsed and its contents used to fill
+    *  #Config.  If #Config is NULL, this routine is a NOP.
+    *
+    *  \return \b true.
+    */
    bool Capabilities(string Message);
    bool Capabilities(string Message);
+
+   /** \brief Send a 601 Configuration message (containing the APT
+    *  configuration) to the subprocess.
+    *
+    *  The APT configuration will be send to the subprocess in a
+    *  message of the following form:
+    *
+    *  <pre>
+    *  601 Configuration
+    *  Config-Item: Fully-Qualified-Item=Val
+    *  Config-Item: Fully-Qualified-Item=Val
+    *  ...
+    *  </pre>
+    *
+    *  \return \b true if the command was successfully sent, \b false
+    *  otherwise.
+    */
    bool SendConfiguration();
    bool SendConfiguration();
+
+   /** \brief Handle a 403 Media Change message.
+    *
+    *  \param Message the raw text of the message; the Media field
+    *  indicates what type of media should be changed, and the Drive
+    *  field indicates where the media is located.
+    *
+    *  Invokes pkgAcquireStatus::MediaChange(Media, Drive) to ask the
+    *  user to swap disks; informs the subprocess of the result (via
+    *  603 Media Changed, with the Failed field set to \b true if the
+    *  user cancelled the media change).
+    */
    bool MediaChange(string Message);
    bool MediaChange(string Message);
    
    
+   /** \brief Invoked when the worked process dies unexpectedly.
+    *
+    *  Waits for the subprocess to terminate and generates an error if
+    *  it terminated abnormally, then closes and blanks out all file
+    *  descriptors.  Discards all pending messages from the
+    *  subprocess.
+    *
+    *  \return \b false.
+    */
    bool MethodFailure();
    bool MethodFailure();
+
+   /** \brief Invoked when a fetch job is completed, either
+    *  successfully or unsuccessfully.
+    *
+    *  Resets the status information for the worker process.
+    */
    void ItemDone();
    void ItemDone();
    
    
    public:
    public:
    
    
-   // The curent method state
+   /** \brief The queue entry that is currently being downloaded. */
    pkgAcquire::Queue::QItem *CurrentItem;
    pkgAcquire::Queue::QItem *CurrentItem;
+
+   /** \brief The most recent status string received from the
+    *  subprocess.
+    */
    string Status;
    string Status;
+
+   /** \brief How many bytes of the file have been downloaded.  Zero
+    *  if the current progress of the file cannot be determined.
+    */
    unsigned long CurrentSize;
    unsigned long CurrentSize;
+
+   /** \brief The total number of bytes to be downloaded.  Zero if the
+    *  total size of the final is unknown.
+    */
    unsigned long TotalSize;
    unsigned long TotalSize;
+
+   /** \brief How much of the file was already downloaded prior to
+    *  starting this worker.
+    */
    unsigned long ResumePoint;
    unsigned long ResumePoint;
    
    
-   // Load the method and do the startup 
+   /** \brief Tell the subprocess to download the given item.
+    *
+    *  \param Item the item to queue up.
+    *  \return \b true if the item was successfully enqueued.
+    *
+    *  Queues up a 600 URI Acquire message for the given item to be
+    *  sent at the next possible moment.  Does \e not flush the output
+    *  queue.
+    */
    bool QueueItem(pkgAcquire::Queue::QItem *Item);
    bool QueueItem(pkgAcquire::Queue::QItem *Item);
+
+   /** \brief Start up the worker and fill in #Config.
+    *
+    *  Reads the first message from the worker, which is assumed to be
+    *  a 100 Capabilities message.
+    *
+    *  \return \b true if all operations completed successfully.
+    */
    bool Start();
    bool Start();
+
+   /** \brief Update the worker statistics (CurrentSize, TotalSize,
+    *  etc).
+    */
    void Pulse();
    void Pulse();
+
+   /** \return The fetch method configuration. */
    inline const MethodConfig *GetConf() const {return Config;};
    inline const MethodConfig *GetConf() const {return Config;};
-   
+
+   /** \brief Create a new Worker to download files.
+    *
+    *  \param OwnerQ The queue into which this worker should be
+    *  placed.
+    *
+    *  \param Config A location in which to store information about
+    *  the fetch method.
+    *
+    *  \param Log The download progress indicator that should be used
+    *  to report the progress of this worker.
+    */
    Worker(Queue *OwnerQ,MethodConfig *Config,pkgAcquireStatus *Log);
    Worker(Queue *OwnerQ,MethodConfig *Config,pkgAcquireStatus *Log);
+
+   /** \brief Create a new Worker that should just retrieve
+    *  information about the fetch method.
+    *
+    *  Nothing in particular forces you to refrain from actually
+    *  downloading stuff, but the various status callbacks won't be
+    *  invoked.
+    *
+    *  \param Config A location in which to store information about
+    *  the fetch method.
+    */
    Worker(MethodConfig *Config);
    Worker(MethodConfig *Config);
+
+   /** \brief Clean up this worker.
+    *
+    *  Closes the file descriptors; if MethodConfig::NeedsCleanup is
+    *  \b false, also rudely interrupts the worker with a SIGINT.
+    */
    ~Worker();
    ~Worker();
 };
 };
 
 
+/** @} */
+
 #endif
 #endif

+ 0 - 3
apt-pkg/acquire.cc

@@ -13,9 +13,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/acquire.h"
-#endif       
 #include <apt-pkg/acquire.h>
 #include <apt-pkg/acquire.h>
 #include <apt-pkg/acquire-item.h>
 #include <apt-pkg/acquire-item.h>
 #include <apt-pkg/acquire-worker.h>
 #include <apt-pkg/acquire-worker.h>

+ 516 - 32
apt-pkg/acquire.h

@@ -29,6 +29,40 @@
    
    
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
+
+/** \defgroup acquire Acquire system
+ *
+ *  \brief The Acquire system is responsible for retrieving files from
+ *  local or remote URIs and postprocessing them (for instance,
+ *  verifying their authenticity).  The core class in this system is
+ *  pkgAcquire, which is responsible for managing the download queues
+ *  during the download.  There is at least one download queue for
+ *  each supported protocol; protocols such as http may provide one
+ *  queue per host.
+ *
+ *  Each file to download is represented by a subclass of
+ *  pkgAcquire::Item.  The files add themselves to the download
+ *  queue(s) by providing their URI information to
+ *  pkgAcquire::Item::QueueURI, which calls pkgAcquire::Enqueue.
+ *
+ *  Once the system is set up, the Run method will spawn subprocesses
+ *  to handle the enqueued URIs; the scheduler will then take items
+ *  from the queues and feed them into the handlers until the queues
+ *  are empty.
+ *
+ *  \todo Acquire supports inserting an object into several queues at
+ *  once, but it is not clear what its behavior in this case is, and
+ *  no subclass of pkgAcquire::Item seems to actually use this
+ *  capability.
+ */
+
+/** \addtogroup acquire
+ *
+ *  @{
+ *
+ *  \file acquire.h
+ */
+
 #ifndef PKGLIB_ACQUIRE_H
 #ifndef PKGLIB_ACQUIRE_H
 #define PKGLIB_ACQUIRE_H
 #define PKGLIB_ACQUIRE_H
 
 
@@ -38,14 +72,20 @@
 using std::vector;
 using std::vector;
 using std::string;
 using std::string;
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/acquire.h"
-#endif 
 
 
 #include <sys/time.h>
 #include <sys/time.h>
 #include <unistd.h>
 #include <unistd.h>
 
 
 class pkgAcquireStatus;
 class pkgAcquireStatus;
+
+/** \brief The core download scheduler.
+ *
+ *  This class represents an ongoing download.  It manages the lists
+ *  of active and pending downloads and handles setting up and tearing
+ *  down download-related structures.
+ *
+ *  \todo Why all the protected data items and methods?
+ */
 class pkgAcquire
 class pkgAcquire
 {   
 {   
    public:
    public:
@@ -60,97 +100,299 @@ class pkgAcquire
 
 
    typedef vector<Item *>::iterator ItemIterator;
    typedef vector<Item *>::iterator ItemIterator;
    typedef vector<Item *>::const_iterator ItemCIterator;
    typedef vector<Item *>::const_iterator ItemCIterator;
-   
+
    protected:
    protected:
    
    
-   // List of items to fetch
+   /** \brief A list of items to download.
+    *
+    *  This is built monotonically as items are created and only
+    *  emptied when the download shuts down.
+    */
    vector<Item *> Items;
    vector<Item *> Items;
    
    
-   // List of active queues and fetched method configuration parameters
+   /** \brief The head of the list of active queues.
+    *
+    *  \todo why a hand-managed list of queues instead of std::list or
+    *  std::set?
+    */
    Queue *Queues;
    Queue *Queues;
+
+   /** \brief The head of the list of active workers.
+    *
+    *  \todo why a hand-managed list of workers instead of std::list
+    *  or std::set?
+    */
    Worker *Workers;
    Worker *Workers;
+
+   /** \brief The head of the list of acquire method configurations.
+    *
+    *  Each protocol (http, ftp, gzip, etc) via which files can be
+    *  fetched can have a representation in this list.  The
+    *  configuration data is filled in by parsing the 100 Capabilities
+    *  string output by a method on startup (see
+    *  pkgAcqMethod::pkgAcqMethod and pkgAcquire::GetConfig).
+    *
+    *  \todo why a hand-managed config dictionary instead of std::map?
+    */
    MethodConfig *Configs;
    MethodConfig *Configs;
+
+   /** \brief The progress indicator for this download. */
    pkgAcquireStatus *Log;
    pkgAcquireStatus *Log;
+
+   /** \brief The total size of the files which are to be fetched.
+    *
+    *  This is not necessarily the total number of bytes to download
+    *  when, e.g., download resumption and list updates via patches
+    *  are taken into account.
+    */
    unsigned long ToFetch;
    unsigned long ToFetch;
 
 
-   // Configurable parameters for the schedular
-   enum {QueueHost,QueueAccess} QueueMode;
+   // Configurable parameters for the scheduler
+
+   /** \brief Represents the queuing strategy for remote URIs. */
+   enum QueueStrategy {
+     /** \brief Generate one queue for each protocol/host combination; downloads from 
+      *  multiple hosts can proceed in parallel.
+      */
+     QueueHost,
+     /** \brief Generate a single queue for each protocol; serialize
+      *  downloads from multiple hosts.
+      */
+     QueueAccess} QueueMode;
+
+   /** \brief If \b true, debugging information will be dumped to std::clog. */
    bool Debug;
    bool Debug;
+   /** \brief If \b true, a download is currently in progress. */
    bool Running;
    bool Running;
-   
+
+   /** \brief Add the given item to the list of items. */
    void Add(Item *Item);
    void Add(Item *Item);
+
+   /** \brief Remove the given item from the list of items. */
    void Remove(Item *Item);
    void Remove(Item *Item);
+
+   /** \brief Add the given worker to the list of workers. */
    void Add(Worker *Work);
    void Add(Worker *Work);
+
+   /** \brief Remove the given worker from the list of workers. */
    void Remove(Worker *Work);
    void Remove(Worker *Work);
    
    
+   /** \brief Insert the given fetch request into the appropriate queue.
+    *
+    *  \param Item The URI to download and the item to download it
+    *  for.  Copied by value into the queue; no reference to Item is
+    *  retained.
+    */
    void Enqueue(ItemDesc &Item);
    void Enqueue(ItemDesc &Item);
+
+   /** \brief Remove all fetch requests for this item from all queues. */
    void Dequeue(Item *Item);
    void Dequeue(Item *Item);
+
+   /** \brief Determine the fetch method and queue of a URI.
+    *
+    *  \param URI The URI to fetch.
+    *
+    *  \param[out] Config A location in which to place the method via
+    *  which the URI is to be fetched.
+    *
+    *  \return the string-name of the queue in which a fetch request
+    *  for the given URI should be placed.
+    */
    string QueueName(string URI,MethodConfig const *&Config);
    string QueueName(string URI,MethodConfig const *&Config);
 
 
-   // FDSET managers for derived classes
+   /** \brief Build up the set of file descriptors upon which select() should
+    *  block.
+    *
+    *  The default implementation inserts the file descriptors
+    *  corresponding to active downloads.
+    *
+    *  \param[out] Fd The largest file descriptor in the generated sets.
+    *
+    *  \param[out] RSet The set of file descriptors that should be
+    *  watched for input.
+    *
+    *  \param[out] WSet The set of file descriptors that should be
+    *  watched for output.
+    */
    virtual void SetFds(int &Fd,fd_set *RSet,fd_set *WSet);
    virtual void SetFds(int &Fd,fd_set *RSet,fd_set *WSet);
+
+   /** Handle input from and output to file descriptors which select()
+    *  has determined are ready.  The default implementation
+    *  dispatches to all active downloads.
+    *
+    *  \param RSet The set of file descriptors that are ready for
+    *  input.
+    *
+    *  \param WSet The set of file descriptors that are ready for
+    *  output.
+    */
    virtual void RunFds(fd_set *RSet,fd_set *WSet);   
    virtual void RunFds(fd_set *RSet,fd_set *WSet);   
 
 
-   // A queue calls this when it dequeues an item
+   /** \brief Check for idle queues with ready-to-fetch items.
+    *
+    *  Called by pkgAcquire::Queue::Done each time an item is dequeued
+    *  but remains on some queues; i.e., another queue should start
+    *  fetching it.
+    */
    void Bump();
    void Bump();
    
    
    public:
    public:
 
 
+   /** \brief Retrieve information about a fetch method by name.
+    *
+    *  \param Access The name of the method to look up.
+    *
+    *  \return the method whose name is Access, or \b NULL if no such method exists.
+    */
    MethodConfig *GetConfig(string Access);
    MethodConfig *GetConfig(string Access);
 
 
-   enum RunResult {Continue,Failed,Cancelled};
+   /** \brief Provides information on how a download terminated. */
+   enum RunResult {
+     /** \brief All files were fetched successfully. */
+     Continue,
+
+     /** \brief Some files failed to download. */
+     Failed,
+
+     /** \brief The download was cancelled by the user (i.e., #Log's
+      *  pkgAcquireStatus::Pulse() method returned \b false).
+      */
+     Cancelled};
 
 
-   RunResult Run(int PulseIntervall=500000);
+   /** \brief Download all the items that have been Add()ed to this
+    *  download process.
+    *
+    *  This method will block until the download completes, invoking
+    *  methods on #Log to report on the progress of the download.
+    *
+    *  \param PulseInterval The method pkgAcquireStatus::Pulse will be
+    *  invoked on #Log at intervals of PulseInterval milliseconds.
+    *
+    *  \return the result of the download.
+    */
+   RunResult Run(int PulseInterval=500000);
+
+   /** \brief Remove all items from this download process, terminate
+    *  all download workers, and empty all queues.
+    */
    void Shutdown();
    void Shutdown();
    
    
-   // Simple iteration mechanism
+   /** \brief Get the first #Worker object.
+    *
+    *  \return the first active worker in this download process.
+    */
    inline Worker *WorkersBegin() {return Workers;};
    inline Worker *WorkersBegin() {return Workers;};
+
+   /** \brief Advance to the next #Worker object.
+    *
+    *  \return the worker immediately following I, or \b NULL if none
+    *  exists.
+    */
    Worker *WorkerStep(Worker *I);
    Worker *WorkerStep(Worker *I);
+
+   /** \brief Get the head of the list of items. */
    inline ItemIterator ItemsBegin() {return Items.begin();};
    inline ItemIterator ItemsBegin() {return Items.begin();};
+
+   /** \brief Get the end iterator of the list of items. */
    inline ItemIterator ItemsEnd() {return Items.end();};
    inline ItemIterator ItemsEnd() {return Items.end();};
    
    
    // Iterate over queued Item URIs
    // Iterate over queued Item URIs
    class UriIterator;
    class UriIterator;
+   /** \brief Get the head of the list of enqueued item URIs.
+    *
+    *  This iterator will step over every element of every active
+    *  queue.
+    */
    UriIterator UriBegin();
    UriIterator UriBegin();
+   /** \brief Get the end iterator of the list of enqueued item URIs. */
    UriIterator UriEnd();
    UriIterator UriEnd();
    
    
-   // Cleans out the download dir
+   /** Deletes each entry in the given directory that is not being
+    *  downloaded by this object.  For instance, when downloading new
+    *  list files, calling Clean() will delete the old ones.
+    *
+    *  \param Dir The directory to be cleaned out.
+    *
+    *  \return \b true if the directory exists and is readable.
+    */
    bool Clean(string Dir);
    bool Clean(string Dir);
 
 
-   // Returns the size of the total download set
+   /** \return the total size in bytes of all the items included in
+    *  this download.
+    */
    double TotalNeeded();
    double TotalNeeded();
+
+   /** \return the size in bytes of all non-local items included in
+    *  this download.
+    */
    double FetchNeeded();
    double FetchNeeded();
+
+   /** \return the amount of data to be fetched that is already
+    *  present on the filesystem.
+    */
    double PartialPresent();
    double PartialPresent();
 
 
+   /** \brief Construct a new pkgAcquire.
+    *
+    *  \param Log The progress indicator associated with this
+    *  download, or \b NULL for none.  This object is not owned by the
+    *  download process and will not be deleted when the pkgAcquire
+    *  object is destroyed.  Naturally, it should live for at least as
+    *  long as the pkgAcquire object does.
+    */
    pkgAcquire(pkgAcquireStatus *Log = 0);
    pkgAcquire(pkgAcquireStatus *Log = 0);
+
+   /** \brief Destroy this pkgAcquire object.
+    *
+    *  Destroys all queue, method, and item objects associated with
+    *  this download.
+    */
    virtual ~pkgAcquire();
    virtual ~pkgAcquire();
 };
 };
 
 
-// Description of an Item+URI
+/** \brief Represents a single download source from which an item
+ *  should be downloaded.
+ *
+ *  An item may have several assocated ItemDescs over its lifetime.
+ */
 struct pkgAcquire::ItemDesc
 struct pkgAcquire::ItemDesc
 {
 {
+   /** \brief The URI from which to download this item. */
    string URI;
    string URI;
+   /** brief A description of this item. */
    string Description;
    string Description;
+   /** brief A shorter description of this item. */
    string ShortDesc;
    string ShortDesc;
+   /** brief The underlying item which is to be downloaded. */
    Item *Owner;
    Item *Owner;
 };
 };
 
 
-// List of possible items queued for download.
+/** \brief A single download queue in a pkgAcquire object.
+ *
+ *  \todo Why so many protected values?
+ */
 class pkgAcquire::Queue
 class pkgAcquire::Queue
 {
 {
    friend class pkgAcquire;
    friend class pkgAcquire;
    friend class pkgAcquire::UriIterator;
    friend class pkgAcquire::UriIterator;
    friend class pkgAcquire::Worker;
    friend class pkgAcquire::Worker;
+
+   /** \brief The next queue in the pkgAcquire object's list of queues. */
    Queue *Next;
    Queue *Next;
    
    
    protected:
    protected:
 
 
-   // Queued item
+   /** \brief A single item placed in this queue. */
    struct QItem : pkgAcquire::ItemDesc
    struct QItem : pkgAcquire::ItemDesc
    {
    {
-      QItem *Next;      
+      /** \brief The next item in the queue. */
+      QItem *Next;
+      /** \brief The worker associated with this item, if any. */
       pkgAcquire::Worker *Worker;
       pkgAcquire::Worker *Worker;
-      
+
+      /** \brief Assign the ItemDesc portion of this QItem from
+       *  another ItemDesc
+       */
       void operator =(pkgAcquire::ItemDesc const &I)
       void operator =(pkgAcquire::ItemDesc const &I)
       {
       {
 	 URI = I.URI;
 	 URI = I.URI;
@@ -160,45 +402,145 @@ class pkgAcquire::Queue
       };
       };
    };
    };
    
    
-   // Name of the queue
+   /** \brief The name of this queue. */
    string Name;
    string Name;
 
 
-   // Items queued into this queue
+   /** \brief The head of the list of items contained in this queue.
+    *
+    *  \todo why a by-hand list instead of an STL structure?
+    */
    QItem *Items;
    QItem *Items;
+
+   /** \brief The head of the list of workers associated with this queue.
+    *
+    *  \todo This is plural because support exists in Queue for
+    *  multiple workers.  However, it does not appear that there is
+    *  any way to actually associate more than one worker with a
+    *  queue.
+    *
+    *  \todo Why not just use a std::set?
+    */
    pkgAcquire::Worker *Workers;
    pkgAcquire::Worker *Workers;
+
+   /** \brief the download scheduler with which this queue is associated. */
    pkgAcquire *Owner;
    pkgAcquire *Owner;
+
+   /** \brief The number of entries in this queue that are currently
+    *  being downloaded.
+    */
    signed long PipeDepth;
    signed long PipeDepth;
+
+   /** \brief The maximum number of entries that this queue will
+    *  attempt to download at once.
+    */
    unsigned long MaxPipeDepth;
    unsigned long MaxPipeDepth;
    
    
    public:
    public:
    
    
-   // Put an item into this queue
+   /** \brief Insert the given fetch request into this queue. 
+    *
+    *  \return \b true if the queuing was successful. May return
+    *  \b false if the Item is already in the queue
+    */
    bool Enqueue(ItemDesc &Item);
    bool Enqueue(ItemDesc &Item);
+
+   /** \brief Remove all fetch requests for the given item from this queue.
+    *
+    *  \return \b true if at least one request was removed from the queue.
+    */
    bool Dequeue(Item *Owner);
    bool Dequeue(Item *Owner);
 
 
-   // Find a Queued item
+   /** \brief Locate an item in this queue.
+    *
+    *  \param URI A URI to match against.
+    *  \param Owner A pkgAcquire::Worker to match against.
+    *
+    *  \return the first item in the queue whose URI is #URI and that
+    *  is being downloaded by #Owner.
+    */
    QItem *FindItem(string URI,pkgAcquire::Worker *Owner);
    QItem *FindItem(string URI,pkgAcquire::Worker *Owner);
+
+   /** Presumably this should start downloading an item?
+    *
+    *  \todo Unimplemented.  Implement it or remove?
+    */
    bool ItemStart(QItem *Itm,unsigned long Size);
    bool ItemStart(QItem *Itm,unsigned long Size);
+
+   /** \brief Remove the given item from this queue and set its state
+    *  to pkgAcquire::Item::StatDone.
+    *
+    *  If this is the only queue containing the item, the item is also
+    *  removed from the main queue by calling pkgAcquire::Dequeue.
+    *
+    *  \param Itm The item to remove.
+    *
+    *  \return \b true if no errors are encountered.
+    */
    bool ItemDone(QItem *Itm);
    bool ItemDone(QItem *Itm);
    
    
+   /** \brief Start the worker process associated with this queue.
+    *
+    *  If a worker process is already associated with this queue,
+    *  this is equivalent to calling Cycle().
+    *
+    *  \return \b true if the startup was successful.
+    */
    bool Startup();
    bool Startup();
+
+   /** \brief Shut down the worker process associated with this queue.
+    *
+    *  \param Final If \b true, then the process is stopped unconditionally.
+    *               Otherwise, it is only stopped if it does not need cleanup
+    *               as indicated by the pkgAcqMethod::NeedsCleanup member of
+    *               its configuration.
+    *
+    *  \return \b true.
+    */
    bool Shutdown(bool Final);
    bool Shutdown(bool Final);
+
+   /** \brief Send idle items to the worker process.
+    *
+    *  Fills up the pipeline by inserting idle items into the worker's queue.
+    */
    bool Cycle();
    bool Cycle();
+
+   /** \brief Check for items that could be enqueued.
+    *
+    *  Call this after an item placed in multiple queues has gone from
+    *  the pkgAcquire::Item::StatFetching state to the
+    *  pkgAcquire::Item::StatIdle state, to possibly refill an empty queue.
+    *  This is an alias for Cycle().
+    *
+    *  \todo Why both this and Cycle()?  Are they expected to be
+    *  different someday?
+    */
    void Bump();
    void Bump();
    
    
+   /** \brief Create a new Queue.
+    *
+    *  \param Name The name of the new queue.
+    *  \param Owner The download process that owns the new queue.
+    */
    Queue(string Name,pkgAcquire *Owner);
    Queue(string Name,pkgAcquire *Owner);
+
+   /** Shut down all the worker processes associated with this queue
+    *  and empty the queue.
+    */
    ~Queue();
    ~Queue();
 };
 };
 
 
+/** \brief Iterates over all the URIs being fetched by a pkgAcquire object. */
 class pkgAcquire::UriIterator
 class pkgAcquire::UriIterator
 {
 {
+   /** The next queue to iterate over. */
    pkgAcquire::Queue *CurQ;
    pkgAcquire::Queue *CurQ;
+   /** The item that we currently point at. */
    pkgAcquire::Queue::QItem *CurItem;
    pkgAcquire::Queue::QItem *CurItem;
    
    
    public:
    public:
    
    
-   // Advance to the next item
    inline void operator ++() {operator ++();};
    inline void operator ++() {operator ++();};
+
    void operator ++(int)
    void operator ++(int)
    {
    {
       CurItem = CurItem->Next;
       CurItem = CurItem->Next;
@@ -209,11 +551,14 @@ class pkgAcquire::UriIterator
       }
       }
    };
    };
    
    
-   // Accessors
    inline pkgAcquire::ItemDesc const *operator ->() const {return CurItem;};
    inline pkgAcquire::ItemDesc const *operator ->() const {return CurItem;};
    inline bool operator !=(UriIterator const &rhs) const {return rhs.CurQ != CurQ || rhs.CurItem != CurItem;};
    inline bool operator !=(UriIterator const &rhs) const {return rhs.CurQ != CurQ || rhs.CurItem != CurItem;};
    inline bool operator ==(UriIterator const &rhs) const {return rhs.CurQ == CurQ && rhs.CurItem == CurItem;};
    inline bool operator ==(UriIterator const &rhs) const {return rhs.CurQ == CurQ && rhs.CurItem == CurItem;};
    
    
+   /** \brief Create a new UriIterator.
+    *
+    *  \param Q The queue over which this UriIterator should iterate.
+    */
    UriIterator(pkgAcquire::Queue *Q) : CurQ(Q), CurItem(0)
    UriIterator(pkgAcquire::Queue *Q) : CurQ(Q), CurItem(0)
    {
    {
       while (CurItem == 0 && CurQ != 0)
       while (CurItem == 0 && CurQ != 0)
@@ -224,61 +569,200 @@ class pkgAcquire::UriIterator
    }   
    }   
 };
 };
 
 
-// Configuration information from each method
+/** \brief Information about the properties of a single acquire method. */
 struct pkgAcquire::MethodConfig
 struct pkgAcquire::MethodConfig
 {
 {
+   /** \brief The next link on the acquire method list.
+    *
+    *  \todo Why not an STL container?
+    */
    MethodConfig *Next;
    MethodConfig *Next;
    
    
+   /** \brief The name of this acquire method (e.g., http). */
    string Access;
    string Access;
 
 
+   /** \brief The implementation version of this acquire method. */
    string Version;
    string Version;
+
+   /** \brief If \b true, only one download queue should be created for this
+    *  method.
+    */
    bool SingleInstance;
    bool SingleInstance;
+
+   /** \brief If \b true, this method supports pipelined downloading. */
    bool Pipeline;
    bool Pipeline;
+
+   /** \brief If \b true, the worker process should send the entire
+    *  APT configuration tree to the fetch subprocess when it starts
+    *  up.
+    */
    bool SendConfig;
    bool SendConfig;
+
+   /** \brief If \b true, this fetch method does not require network access;
+    *  all files are to be acquired from the local disk.
+    */
    bool LocalOnly;
    bool LocalOnly;
+
+   /** \brief If \b true, the subprocess has to carry out some cleanup
+    *  actions before shutting down.
+    *
+    *  For instance, the cdrom method needs to unmount the CD after it
+    *  finishes.
+    */
    bool NeedsCleanup;
    bool NeedsCleanup;
+
+   /** \brief If \b true, this fetch method acquires files from removable media. */
    bool Removable;
    bool Removable;
    
    
+   /** \brief Set up the default method parameters.
+    *
+    *  All fields are initialized to NULL, "", or \b false as
+    *  appropriate.
+    */
    MethodConfig();
    MethodConfig();
 };
 };
 
 
+/** \brief A monitor object for downloads controlled by the pkgAcquire class.
+ *
+ *  \todo Why protected members?
+ *
+ *  \todo Should the double members be uint64_t?
+ */
 class pkgAcquireStatus
 class pkgAcquireStatus
 {
 {
    protected:
    protected:
    
    
+   /** \brief The last time at which this monitor object was updated. */
    struct timeval Time;
    struct timeval Time;
+
+   /** \brief The time at which the download started. */
    struct timeval StartTime;
    struct timeval StartTime;
+
+   /** \brief The number of bytes fetched as of the previous call to
+    *  pkgAcquireStatus::Pulse, including local items.
+    */
    double LastBytes;
    double LastBytes;
+
+   /** \brief The current rate of download as of the most recent call
+    *  to pkgAcquireStatus::Pulse, in bytes per second.
+    */
    double CurrentCPS;
    double CurrentCPS;
+
+   /** \brief The number of bytes fetched as of the most recent call
+    *  to pkgAcquireStatus::Pulse, including local items.
+    */
    double CurrentBytes;
    double CurrentBytes;
+
+   /** \brief The total number of bytes that need to be fetched.
+    *
+    *  \warning This member is inaccurate, as new items might be
+    *  enqueued while the download is in progress!
+    */
    double TotalBytes;
    double TotalBytes;
+
+   /** \brief The total number of bytes accounted for by items that
+    *  were successfully fetched.
+    */
    double FetchedBytes;
    double FetchedBytes;
+
+   /** \brief The amount of time that has elapsed since the download
+    *   started.
+    */
    unsigned long ElapsedTime;
    unsigned long ElapsedTime;
+
+   /** \brief The total number of items that need to be fetched.
+    *
+    *  \warning This member is inaccurate, as new items might be
+    *  enqueued while the download is in progress!
+    */
    unsigned long TotalItems;
    unsigned long TotalItems;
+
+   /** \brief The number of items that have been successfully downloaded. */
    unsigned long CurrentItems;
    unsigned long CurrentItems;
    
    
    public:
    public:
 
 
+   /** \brief If \b true, the download scheduler should call Pulse()
+    *  at the next available opportunity.
+    */
    bool Update;
    bool Update;
+
+   /** \brief If \b true, extra Pulse() invocations will be performed.
+    *
+    *  With this option set, Pulse() will be called every time that a
+    *  download item starts downloading, finishes downloading, or
+    *  terminates with an error.
+    */
    bool MorePulses;
    bool MorePulses;
       
       
-   // Called by items when they have finished a real download
+   /** \brief Invoked when a local or remote file has been completely fetched.
+    *
+    *  \param Size The size of the file fetched.
+    *
+    *  \param ResumePoint How much of the file was already fetched.
+    */
    virtual void Fetched(unsigned long Size,unsigned long ResumePoint);
    virtual void Fetched(unsigned long Size,unsigned long ResumePoint);
    
    
-   // Called to change media
+   /** \brief Invoked when the user should be prompted to change the
+    *         inserted removable media.
+    *
+    *  This method should not return until the user has confirmed to
+    *  the user interface that the media change is complete.
+    *
+    *  \param Media The name of the media type that should be changed.
+    *
+    *  \param Drive The identifying name of the drive whose media
+    *               should be changed.
+    *
+    *  \return \b true if the user confirms the media change, \b
+    *  false if it is cancelled.
+    *
+    *  \todo This is a horrible blocking monster; it should be CPSed
+    *  with prejudice.
+    */
    virtual bool MediaChange(string Media,string Drive) = 0;
    virtual bool MediaChange(string Media,string Drive) = 0;
    
    
-   // Each of these is called by the workers when an event occures
+   /** \brief Invoked when an item is confirmed to be up-to-date.
+
+    * For instance, when an HTTP download is informed that the file on
+    * the server was not modified.
+    */
    virtual void IMSHit(pkgAcquire::ItemDesc &/*Itm*/) {};
    virtual void IMSHit(pkgAcquire::ItemDesc &/*Itm*/) {};
+
+   /** \brief Invoked when some of an item's data is fetched. */
    virtual void Fetch(pkgAcquire::ItemDesc &/*Itm*/) {};
    virtual void Fetch(pkgAcquire::ItemDesc &/*Itm*/) {};
+
+   /** \brief Invoked when an item is successfully and completely fetched. */
    virtual void Done(pkgAcquire::ItemDesc &/*Itm*/) {};
    virtual void Done(pkgAcquire::ItemDesc &/*Itm*/) {};
+
+   /** \brief Invoked when the process of fetching an item encounters
+    *  a fatal error.
+    */
    virtual void Fail(pkgAcquire::ItemDesc &/*Itm*/) {};
    virtual void Fail(pkgAcquire::ItemDesc &/*Itm*/) {};
-   virtual bool Pulse(pkgAcquire *Owner); // returns false on user cancel
+
+   /** \brief Periodically invoked while the Acquire process is underway.
+    *
+    *  Subclasses should first call pkgAcquireStatus::Pulse(), then
+    *  update their status output.  The download process is blocked
+    *  while Pulse() is being called.
+    *
+    *  \return \b false if the user asked to cancel the whole Acquire process.
+    *
+    *  \see pkgAcquire::Run
+    */
+   virtual bool Pulse(pkgAcquire *Owner);
+
+   /** \brief Invoked when the Acquire process starts running. */
    virtual void Start();
    virtual void Start();
+
+   /** \brief Invoked when the Acquire process stops running. */
    virtual void Stop();
    virtual void Stop();
    
    
+   /** \brief Initialize all counters to 0 and the time to the current time. */
    pkgAcquireStatus();
    pkgAcquireStatus();
    virtual ~pkgAcquireStatus() {};
    virtual ~pkgAcquireStatus() {};
 };
 };
 
 
+/** @} */
+
 #endif
 #endif

+ 94 - 33
apt-pkg/algorithms.cc

@@ -14,16 +14,17 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/algorithms.h"
-#endif 
 #include <apt-pkg/algorithms.h>
 #include <apt-pkg/algorithms.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/configuration.h>
+#include <apt-pkg/version.h>
 #include <apt-pkg/sptr.h>
 #include <apt-pkg/sptr.h>
+
     
     
 #include <apti18n.h>
 #include <apti18n.h>
-    
+#include <sys/types.h>
+#include <cstdlib>
+#include <algorithm>
 #include <iostream>
 #include <iostream>
 									/*}}}*/
 									/*}}}*/
 using namespace std;
 using namespace std;
@@ -100,6 +101,7 @@ bool pkgSimulate::Install(PkgIterator iPkg,string /*File*/)
 	 DepIterator End;
 	 DepIterator End;
 	 D.GlobOr(Start,End);
 	 D.GlobOr(Start,End);
 	 if (Start->Type == pkgCache::Dep::Conflicts ||
 	 if (Start->Type == pkgCache::Dep::Conflicts ||
+	     Start->Type == pkgCache::Dep::DpkgBreaks ||
 	     Start->Type == pkgCache::Dep::Obsoletes ||
 	     Start->Type == pkgCache::Dep::Obsoletes ||
 	     End->Type == pkgCache::Dep::PreDepends)
 	     End->Type == pkgCache::Dep::PreDepends)
          {
          {
@@ -149,6 +151,8 @@ bool pkgSimulate::Configure(PkgIterator iPkg)
 	    cout << " Obsoletes:" << D.TargetPkg().Name();
 	    cout << " Obsoletes:" << D.TargetPkg().Name();
 	 else if (D->Type == pkgCache::Dep::Conflicts)
 	 else if (D->Type == pkgCache::Dep::Conflicts)
 	    cout << " Conflicts:" << D.TargetPkg().Name();
 	    cout << " Conflicts:" << D.TargetPkg().Name();
+	 else if (D->Type == pkgCache::Dep::DpkgBreaks)
+	    cout << " Breaks:" << D.TargetPkg().Name();
 	 else
 	 else
 	    cout << " Depends:" << D.TargetPkg().Name();
 	    cout << " Depends:" << D.TargetPkg().Name();
       }	    
       }	    
@@ -220,6 +224,8 @@ void pkgSimulate::ShortBreaks()
    the necessary calculations to deal with the problems. */
    the necessary calculations to deal with the problems. */
 bool pkgApplyStatus(pkgDepCache &Cache)
 bool pkgApplyStatus(pkgDepCache &Cache)
 {
 {
+   pkgDepCache::ActionGroup group(Cache);
+
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
    {
    {
       if (I->VersionList == 0)
       if (I->VersionList == 0)
@@ -230,13 +236,13 @@ bool pkgApplyStatus(pkgDepCache &Cache)
 	  I->InstState == pkgCache::State::HoldReInstReq)
 	  I->InstState == pkgCache::State::HoldReInstReq)
       {
       {
 	 if (I->CurrentVer != 0 && I.CurrentVer().Downloadable() == true)
 	 if (I->CurrentVer != 0 && I.CurrentVer().Downloadable() == true)
-	    Cache.MarkKeep(I);
+	    Cache.MarkKeep(I, false, false);
 	 else
 	 else
 	 {
 	 {
 	    // Is this right? Will dpkg choke on an upgrade?
 	    // Is this right? Will dpkg choke on an upgrade?
 	    if (Cache[I].CandidateVer != 0 &&
 	    if (Cache[I].CandidateVer != 0 &&
 		 Cache[I].CandidateVerIter(Cache).Downloadable() == true)
 		 Cache[I].CandidateVerIter(Cache).Downloadable() == true)
-	       Cache.MarkInstall(I);
+	       Cache.MarkInstall(I, false, 0, false);
 	    else
 	    else
 	       return _error->Error(_("The package %s needs to be reinstalled, "
 	       return _error->Error(_("The package %s needs to be reinstalled, "
 				    "but I can't find an archive for it."),I.Name());
 				    "but I can't find an archive for it."),I.Name());
@@ -253,12 +259,12 @@ bool pkgApplyStatus(pkgDepCache &Cache)
 	 case pkgCache::State::HalfConfigured:
 	 case pkgCache::State::HalfConfigured:
 	 if ((I->CurrentVer != 0 && I.CurrentVer().Downloadable() == true) ||
 	 if ((I->CurrentVer != 0 && I.CurrentVer().Downloadable() == true) ||
 	     I.State() != pkgCache::PkgIterator::NeedsUnpack)
 	     I.State() != pkgCache::PkgIterator::NeedsUnpack)
-	    Cache.MarkKeep(I);
+	    Cache.MarkKeep(I, false, false);
 	 else
 	 else
 	 {
 	 {
 	    if (Cache[I].CandidateVer != 0 &&
 	    if (Cache[I].CandidateVer != 0 &&
 		 Cache[I].CandidateVerIter(Cache).Downloadable() == true)
 		 Cache[I].CandidateVerIter(Cache).Downloadable() == true)
-	       Cache.MarkInstall(I);
+	       Cache.MarkInstall(I, true, 0, false);
 	    else
 	    else
 	       Cache.MarkDelete(I);
 	       Cache.MarkDelete(I);
 	 }
 	 }
@@ -284,10 +290,12 @@ bool pkgApplyStatus(pkgDepCache &Cache)
    on the result. */
    on the result. */
 bool pkgFixBroken(pkgDepCache &Cache)
 bool pkgFixBroken(pkgDepCache &Cache)
 {
 {
+   pkgDepCache::ActionGroup group(Cache);
+
    // Auto upgrade all broken packages
    // Auto upgrade all broken packages
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
       if (Cache[I].NowBroken() == true)
       if (Cache[I].NowBroken() == true)
-	 Cache.MarkInstall(I,true);
+	 Cache.MarkInstall(I, true, 0, false);
    
    
    /* Fix packages that are in a NeedArchive state but don't have a
    /* Fix packages that are in a NeedArchive state but don't have a
       downloadable install version */
       downloadable install version */
@@ -300,7 +308,7 @@ bool pkgFixBroken(pkgDepCache &Cache)
       if (Cache[I].InstVerIter(Cache).Downloadable() == false)
       if (Cache[I].InstVerIter(Cache).Downloadable() == false)
 	 continue;
 	 continue;
 
 
-      Cache.MarkInstall(I,true);      
+      Cache.MarkInstall(I, true, 0, false);
    }
    }
    
    
    pkgProblemResolver Fix(&Cache);
    pkgProblemResolver Fix(&Cache);
@@ -317,23 +325,25 @@ bool pkgFixBroken(pkgDepCache &Cache)
  */
  */
 bool pkgDistUpgrade(pkgDepCache &Cache)
 bool pkgDistUpgrade(pkgDepCache &Cache)
 {
 {
+   pkgDepCache::ActionGroup group(Cache);
+
    /* Auto upgrade all installed packages, this provides the basis 
    /* Auto upgrade all installed packages, this provides the basis 
       for the installation */
       for the installation */
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
       if (I->CurrentVer != 0)
       if (I->CurrentVer != 0)
-	 Cache.MarkInstall(I,true);
+	 Cache.MarkInstall(I, true, 0, false);
 
 
    /* Now, auto upgrade all essential packages - this ensures that
    /* Now, auto upgrade all essential packages - this ensures that
       the essential packages are present and working */
       the essential packages are present and working */
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
       if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
       if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
-	 Cache.MarkInstall(I,true);
+	 Cache.MarkInstall(I, true, 0, false);
    
    
    /* We do it again over all previously installed packages to force 
    /* We do it again over all previously installed packages to force 
       conflict resolution on them all. */
       conflict resolution on them all. */
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
       if (I->CurrentVer != 0)
       if (I->CurrentVer != 0)
-	 Cache.MarkInstall(I,false);
+	 Cache.MarkInstall(I, false, 0, false);
 
 
    pkgProblemResolver Fix(&Cache);
    pkgProblemResolver Fix(&Cache);
 
 
@@ -345,7 +355,7 @@ bool pkgDistUpgrade(pkgDepCache &Cache)
 	 if (I->SelectedState == pkgCache::State::Hold)
 	 if (I->SelectedState == pkgCache::State::Hold)
 	 {
 	 {
 	    Fix.Protect(I);
 	    Fix.Protect(I);
-	    Cache.MarkKeep(I);
+	    Cache.MarkKeep(I, false, false);
 	 }
 	 }
       }
       }
    }
    }
@@ -360,6 +370,8 @@ bool pkgDistUpgrade(pkgDepCache &Cache)
    to install packages not marked for install */
    to install packages not marked for install */
 bool pkgAllUpgrade(pkgDepCache &Cache)
 bool pkgAllUpgrade(pkgDepCache &Cache)
 {
 {
+   pkgDepCache::ActionGroup group(Cache);
+
    pkgProblemResolver Fix(&Cache);
    pkgProblemResolver Fix(&Cache);
 
 
    if (Cache.BrokenCount() != 0)
    if (Cache.BrokenCount() != 0)
@@ -376,7 +388,7 @@ bool pkgAllUpgrade(pkgDepCache &Cache)
 	    continue;
 	    continue;
       
       
       if (I->CurrentVer != 0 && Cache[I].InstallVer != 0)
       if (I->CurrentVer != 0 && Cache[I].InstallVer != 0)
-	 Cache.MarkInstall(I,false);
+	 Cache.MarkInstall(I, false, 0, false);
    }
    }
       
       
    return Fix.ResolveByKeep();
    return Fix.ResolveByKeep();
@@ -389,6 +401,8 @@ bool pkgAllUpgrade(pkgDepCache &Cache)
    the package is restored. */
    the package is restored. */
 bool pkgMinimizeUpgrade(pkgDepCache &Cache)
 bool pkgMinimizeUpgrade(pkgDepCache &Cache)
 {   
 {   
+   pkgDepCache::ActionGroup group(Cache);
+
    if (Cache.BrokenCount() != 0)
    if (Cache.BrokenCount() != 0)
       return false;
       return false;
    
    
@@ -405,9 +419,9 @@ bool pkgMinimizeUpgrade(pkgDepCache &Cache)
 	    continue;
 	    continue;
 
 
 	 // Keep it and see if that is OK
 	 // Keep it and see if that is OK
-	 Cache.MarkKeep(I);
+	 Cache.MarkKeep(I, false, false);
 	 if (Cache.BrokenCount() != 0)
 	 if (Cache.BrokenCount() != 0)
-	    Cache.MarkInstall(I,false);
+	    Cache.MarkInstall(I, false, 0, false);
 	 else
 	 else
 	 {
 	 {
 	    // If keep didnt actually do anything then there was no change..
 	    // If keep didnt actually do anything then there was no change..
@@ -567,6 +581,8 @@ void pkgProblemResolver::MakeScores()
    installable */
    installable */
 bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
 bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
 {
 {
+   pkgDepCache::ActionGroup group(Cache);
+
    if ((Flags[Pkg->ID] & Upgradable) == 0 || Cache[Pkg].Upgradable() == false)
    if ((Flags[Pkg->ID] & Upgradable) == 0 || Cache[Pkg].Upgradable() == false)
       return false;
       return false;
    if ((Flags[Pkg->ID] & Protected) == Protected)
    if ((Flags[Pkg->ID] & Protected) == Protected)
@@ -575,7 +591,7 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
    Flags[Pkg->ID] &= ~Upgradable;
    Flags[Pkg->ID] &= ~Upgradable;
    
    
    bool WasKept = Cache[Pkg].Keep();
    bool WasKept = Cache[Pkg].Keep();
-   Cache.MarkInstall(Pkg,false);
+   Cache.MarkInstall(Pkg, false, 0, false);
 
 
    // This must be a virtual package or something like that.
    // This must be a virtual package or something like that.
    if (Cache[Pkg].InstVerIter(Cache).end() == true)
    if (Cache[Pkg].InstVerIter(Cache).end() == true)
@@ -639,6 +655,7 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
 	       /* We let the algorithm deal with conflicts on its next iteration,
 	       /* We let the algorithm deal with conflicts on its next iteration,
 		it is much smarter than us */
 		it is much smarter than us */
 	       if (Start->Type == pkgCache::Dep::Conflicts || 
 	       if (Start->Type == pkgCache::Dep::Conflicts || 
+		   Start->Type == pkgCache::Dep::DpkgBreaks || 
 		   Start->Type == pkgCache::Dep::Obsoletes)
 		   Start->Type == pkgCache::Dep::Obsoletes)
 		   break;
 		   break;
 	       
 	       
@@ -660,7 +677,7 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
    if (Fail == true)
    if (Fail == true)
    {
    {
       if (WasKept == true)
       if (WasKept == true)
-	 Cache.MarkKeep(Pkg);
+	 Cache.MarkKeep(Pkg, false, false);
       else
       else
 	 Cache.MarkDelete(Pkg);
 	 Cache.MarkDelete(Pkg);
       return false;
       return false;
@@ -687,6 +704,8 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
    upgrade packages to advoid problems. */
    upgrade packages to advoid problems. */
 bool pkgProblemResolver::Resolve(bool BrokenFix)
 bool pkgProblemResolver::Resolve(bool BrokenFix)
 {
 {
+   pkgDepCache::ActionGroup group(Cache);
+
    unsigned long Size = Cache.Head().PackageCount;
    unsigned long Size = Cache.Head().PackageCount;
 
 
    // Record which packages are marked for install
    // Record which packages are marked for install
@@ -702,7 +721,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 	 {
 	 {
 	    if (Cache[I].InstBroken() == true && BrokenFix == true)
 	    if (Cache[I].InstBroken() == true && BrokenFix == true)
 	    {
 	    {
-	       Cache.MarkInstall(I,false);
+	       Cache.MarkInstall(I, false, 0, false);
 	       if (Cache[I].Install() == true)
 	       if (Cache[I].Install() == true)
 		  Again = true;
 		  Again = true;
 	    }
 	    }
@@ -768,14 +787,14 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 	    pkgCache::Version *OldVer = Cache[I].InstallVer;
 	    pkgCache::Version *OldVer = Cache[I].InstallVer;
 	    Flags[I->ID] &= ReInstateTried;
 	    Flags[I->ID] &= ReInstateTried;
 	    
 	    
-	    Cache.MarkInstall(I,false);
+	    Cache.MarkInstall(I, false, 0, false);
 	    if (Cache[I].InstBroken() == true || 
 	    if (Cache[I].InstBroken() == true || 
 		OldBreaks < Cache.BrokenCount())
 		OldBreaks < Cache.BrokenCount())
 	    {
 	    {
 	       if (OldVer == 0)
 	       if (OldVer == 0)
 		  Cache.MarkDelete(I);
 		  Cache.MarkDelete(I);
 	       else
 	       else
-		  Cache.MarkKeep(I);
+		  Cache.MarkKeep(I, false, false);
 	    }	    
 	    }	    
 	    else
 	    else
 	       if (Debug == true)
 	       if (Debug == true)
@@ -820,7 +839,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 		  {
 		  {
 		     if (Debug == true)
 		     if (Debug == true)
 			clog << "  Or group keep for " << I.Name() << endl;
 			clog << "  Or group keep for " << I.Name() << endl;
-		     Cache.MarkKeep(I);
+		     Cache.MarkKeep(I, false, false);
 		     Change = true;
 		     Change = true;
 		  }
 		  }
 	       }
 	       }
@@ -864,6 +883,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 	    SPtrArray<pkgCache::Version *> VList = Start.AllTargets();
 	    SPtrArray<pkgCache::Version *> VList = Start.AllTargets();
 	    if (*VList == 0 && (Flags[I->ID] & Protected) != Protected &&
 	    if (*VList == 0 && (Flags[I->ID] & Protected) != Protected &&
 		Start->Type != pkgCache::Dep::Conflicts &&
 		Start->Type != pkgCache::Dep::Conflicts &&
+		Start->Type != pkgCache::Dep::DpkgBreaks &&
 		Start->Type != pkgCache::Dep::Obsoletes &&
 		Start->Type != pkgCache::Dep::Obsoletes &&
 		Cache[I].NowBroken() == false)
 		Cache[I].NowBroken() == false)
 	    {	       
 	    {	       
@@ -875,7 +895,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 	       }
 	       }
 	       
 	       
 	       Change = true;
 	       Change = true;
-	       Cache.MarkKeep(I);		  
+	       Cache.MarkKeep(I, false, false);
 	       break;
 	       break;
 	    }
 	    }
 	    
 	    
@@ -894,6 +914,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 	       if (Scores[I->ID] <= Scores[Pkg->ID] ||
 	       if (Scores[I->ID] <= Scores[Pkg->ID] ||
 		   ((Cache[Start] & pkgDepCache::DepNow) == 0 &&
 		   ((Cache[Start] & pkgDepCache::DepNow) == 0 &&
 		    End->Type != pkgCache::Dep::Conflicts &&
 		    End->Type != pkgCache::Dep::Conflicts &&
+		    End->Type != pkgCache::Dep::DpkgBreaks &&
 		    End->Type != pkgCache::Dep::Obsoletes))
 		    End->Type != pkgCache::Dep::Obsoletes))
 	       {
 	       {
 		  // Try a little harder to fix protected packages..
 		  // Try a little harder to fix protected packages..
@@ -912,7 +933,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 		  /* See if a keep will do, unless the package is protected,
 		  /* See if a keep will do, unless the package is protected,
 		     then installing it will be necessary */
 		     then installing it will be necessary */
 		  bool Installed = Cache[I].Install();
 		  bool Installed = Cache[I].Install();
-		  Cache.MarkKeep(I);
+		  Cache.MarkKeep(I, false, false);
 		  if (Cache[I].InstBroken() == false)
 		  if (Cache[I].InstBroken() == false)
 		  {
 		  {
 		     // Unwind operation will be keep now
 		     // Unwind operation will be keep now
@@ -921,7 +942,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 		     
 		     
 		     // Restore
 		     // Restore
 		     if (InOr == true && Installed == true)
 		     if (InOr == true && Installed == true)
-			Cache.MarkInstall(I,false);
+			Cache.MarkInstall(I, false, 0, false);
 		     
 		     
 		     if (Debug == true)
 		     if (Debug == true)
 			clog << "  Holding Back " << I.Name() << " rather than change " << Start.TargetPkg().Name() << endl;
 			clog << "  Holding Back " << I.Name() << " rather than change " << Start.TargetPkg().Name() << endl;
@@ -959,7 +980,22 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 		      (Start->Type == pkgCache::Dep::Conflicts ||
 		      (Start->Type == pkgCache::Dep::Conflicts ||
 		       Start->Type == pkgCache::Dep::Obsoletes))
 		       Start->Type == pkgCache::Dep::Obsoletes))
 		     continue;
 		     continue;
-		  
+
+		  if (Start->Type == pkgCache::Dep::DpkgBreaks)
+		  {
+		     /* Would it help if we upgraded? */
+		     if (Cache[End] & pkgDepCache::DepGCVer) {
+			if (Debug)
+			   clog << "  Upgrading " << Pkg.Name() << " due to Breaks field in " << I.Name() << endl;
+			Cache.MarkInstall(Pkg, false, 0, false);
+			continue;
+		     }
+		     if (Debug)
+			clog << "  Will not break " << Pkg.Name() << " as stated in Breaks field in " << I.Name() <<endl;
+		     Cache.MarkKeep(I, false, false);
+		     continue;
+		  }
+
 		  // Skip adding to the kill list if it is protected
 		  // Skip adding to the kill list if it is protected
 		  if ((Flags[Pkg->ID] & Protected) != 0)
 		  if ((Flags[Pkg->ID] & Protected) != 0)
 		     continue;
 		     continue;
@@ -980,6 +1016,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 	    // Hm, nothing can possibly satisify this dep. Nuke it.
 	    // Hm, nothing can possibly satisify this dep. Nuke it.
 	    if (VList[0] == 0 && 
 	    if (VList[0] == 0 && 
 		Start->Type != pkgCache::Dep::Conflicts &&
 		Start->Type != pkgCache::Dep::Conflicts &&
+		Start->Type != pkgCache::Dep::DpkgBreaks &&
 		Start->Type != pkgCache::Dep::Obsoletes &&
 		Start->Type != pkgCache::Dep::Obsoletes &&
 		(Flags[I->ID] & Protected) != Protected)
 		(Flags[I->ID] & Protected) != Protected)
 	    {
 	    {
@@ -993,7 +1030,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 		  
 		  
 		  // Restore
 		  // Restore
 		  if (InOr == true && Installed == true)
 		  if (InOr == true && Installed == true)
-		     Cache.MarkInstall(I,false);
+		     Cache.MarkInstall(I, false, 0, false);
 		  
 		  
 		  if (Debug == true)
 		  if (Debug == true)
 		     clog << "  Holding Back " << I.Name() << " because I can't find " << Start.TargetPkg().Name() << endl;
 		     clog << "  Holding Back " << I.Name() << " because I can't find " << Start.TargetPkg().Name() << endl;
@@ -1038,7 +1075,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 	       {
 	       {
 		  if (Debug == true)
 		  if (Debug == true)
 		     clog << "  Fixing " << I.Name() << " via keep of " << J->Pkg.Name() << endl;
 		     clog << "  Fixing " << I.Name() << " via keep of " << J->Pkg.Name() << endl;
-		  Cache.MarkKeep(J->Pkg);
+		  Cache.MarkKeep(J->Pkg, false, false);
 	       }
 	       }
 
 
 	       if (Counter > 1)
 	       if (Counter > 1)
@@ -1068,6 +1105,20 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
       return _error->Error(_("Unable to correct problems, you have held broken packages."));
       return _error->Error(_("Unable to correct problems, you have held broken packages."));
    }
    }
    
    
+   // set the auto-flags (mvo: I'm not sure if we _really_ need this, but
+   // I didn't managed 
+   pkgCache::PkgIterator I = Cache.PkgBegin();
+   for (;I.end() != true; I++) {
+      if (Cache[I].NewInstall() && !(Flags[I->ID] & PreInstalled)) {
+	 if(_config->FindI("Debug::pkgAutoRemove",false)) {
+	    std::clog << "Resolve installed new pkg: " << I.Name() 
+		      << " (now marking it as auto)" << std::endl;
+	 }
+	 Cache[I].Flags |= pkgCache::Flag::Auto;
+      }
+   }
+
+
    return true;
    return true;
 }
 }
 									/*}}}*/
 									/*}}}*/
@@ -1078,6 +1129,8 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
    system was non-broken previously. */
    system was non-broken previously. */
 bool pkgProblemResolver::ResolveByKeep()
 bool pkgProblemResolver::ResolveByKeep()
 {
 {
+   pkgDepCache::ActionGroup group(Cache);
+
    unsigned long Size = Cache.Head().PackageCount;
    unsigned long Size = Cache.Head().PackageCount;
 
 
    if (Debug == true)      
    if (Debug == true)      
@@ -1111,7 +1164,7 @@ bool pkgProblemResolver::ResolveByKeep()
       {
       {
 	 if (Debug == true)
 	 if (Debug == true)
 	    clog << "Keeping package " << I.Name() << endl;
 	    clog << "Keeping package " << I.Name() << endl;
-	 Cache.MarkKeep(I);
+	 Cache.MarkKeep(I, false, false);
 	 if (Cache[I].InstBroken() == false)
 	 if (Cache[I].InstBroken() == false)
 	 {
 	 {
 	    K = PList - 1;
 	    K = PList - 1;
@@ -1159,7 +1212,7 @@ bool pkgProblemResolver::ResolveByKeep()
 	       {
 	       {
 		  if (Debug == true)
 		  if (Debug == true)
 		     clog << "  Keeping Package " << Pkg.Name() << " due to dep" << endl;
 		     clog << "  Keeping Package " << Pkg.Name() << " due to dep" << endl;
-		  Cache.MarkKeep(Pkg);
+		  Cache.MarkKeep(Pkg, false, false);
 	       }
 	       }
 	       
 	       
 	       if (Cache[I].InstBroken() == false)
 	       if (Cache[I].InstBroken() == false)
@@ -1196,14 +1249,21 @@ bool pkgProblemResolver::ResolveByKeep()
 /* This is used to make sure protected packages are installed */
 /* This is used to make sure protected packages are installed */
 void pkgProblemResolver::InstallProtect()
 void pkgProblemResolver::InstallProtect()
 {
 {
+   pkgDepCache::ActionGroup group(Cache);
+
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
    {
    {
       if ((Flags[I->ID] & Protected) == Protected)
       if ((Flags[I->ID] & Protected) == Protected)
       {
       {
 	 if ((Flags[I->ID] & ToRemove) == ToRemove)
 	 if ((Flags[I->ID] & ToRemove) == ToRemove)
 	    Cache.MarkDelete(I);
 	    Cache.MarkDelete(I);
-	 else
-	    Cache.MarkInstall(I,false);
+	 else 
+	 {
+	    // preserver the information if the package was auto
+	    // or manual installed
+	    bool autoInst = (Cache[I].Flags & pkgCache::Flag::Auto);
+	    Cache.MarkInstall(I, false, 0, !autoInst);
+	 }
       }
       }
    }   
    }   
 }
 }
@@ -1239,3 +1299,4 @@ void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List)
    qsort(List,Count,sizeof(*List),PrioComp);
    qsort(List,Count,sizeof(*List),PrioComp);
 }
 }
 									/*}}}*/
 									/*}}}*/
+

+ 0 - 3
apt-pkg/algorithms.h

@@ -30,9 +30,6 @@
 #ifndef PKGLIB_ALGORITHMS_H
 #ifndef PKGLIB_ALGORITHMS_H
 #define PKGLIB_ALGORITHMS_H
 #define PKGLIB_ALGORITHMS_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/algorithms.h"
-#endif 
 
 
 #include <apt-pkg/packagemanager.h>
 #include <apt-pkg/packagemanager.h>
 #include <apt-pkg/depcache.h>
 #include <apt-pkg/depcache.h>

+ 0 - 4
apt-pkg/cachefile.cc

@@ -12,10 +12,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/cachefile.h"
-#endif
-
 #include <apt-pkg/cachefile.h>
 #include <apt-pkg/cachefile.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/sourcelist.h>
 #include <apt-pkg/sourcelist.h>

+ 0 - 3
apt-pkg/cachefile.h

@@ -17,9 +17,6 @@
 #ifndef PKGLIB_CACHEFILE_H
 #ifndef PKGLIB_CACHEFILE_H
 #define PKGLIB_CACHEFILE_H
 #define PKGLIB_CACHEFILE_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/cachefile.h"
-#endif 
 
 
 #include <apt-pkg/depcache.h>
 #include <apt-pkg/depcache.h>
 
 

+ 83 - 4
apt-pkg/cacheiterators.h

@@ -31,9 +31,6 @@
 #ifndef PKGLIB_CACHEITERATORS_H
 #ifndef PKGLIB_CACHEITERATORS_H
 #define PKGLIB_CACHEITERATORS_H
 #define PKGLIB_CACHEITERATORS_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/cacheiterators.h"
-#endif 
 
 
 // Package Iterator
 // Package Iterator
 class pkgCache::PkgIterator
 class pkgCache::PkgIterator
@@ -99,7 +96,7 @@ class pkgCache::VerIterator
 {
 {
    Version *Ver;
    Version *Ver;
    pkgCache *Owner;
    pkgCache *Owner;
-   
+
    void _dummy();
    void _dummy();
    
    
    public:
    public:
@@ -128,6 +125,8 @@ 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;
+   DescIterator TranslatedDescription() 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 +147,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 +381,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 +422,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

+ 39 - 12
apt-pkg/cdrom.cc

@@ -1,9 +1,6 @@
 /*
 /*
  */
  */
 
 
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/cdrom.h"
-#endif
 #include<apt-pkg/init.h>
 #include<apt-pkg/init.h>
 #include<apt-pkg/error.h>
 #include<apt-pkg/error.h>
 #include<apt-pkg/cdromutl.h>
 #include<apt-pkg/cdromutl.h>
@@ -18,6 +15,7 @@
 #include <dirent.h>
 #include <dirent.h>
 #include <unistd.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <stdio.h>
+#include <algorithm>
 
 
 
 
 #include "indexcopy.h"
 #include "indexcopy.h"
@@ -30,12 +28,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 +92,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 +149,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 +634,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 +665,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);
    }
    }
 
 
@@ -738,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 - 5
apt-pkg/cdrom.h

@@ -5,9 +5,6 @@
 #include<string>
 #include<string>
 #include<vector>
 #include<vector>
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/cdrom.h"
-#endif
 
 
 using namespace std;
 using namespace std;
 
 
@@ -50,8 +47,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);

+ 0 - 4
apt-pkg/clean.cc

@@ -8,10 +8,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Includes								/*{{{*/
 // Includes								/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/clean.h"
-#endif
-
 #include <apt-pkg/clean.h>
 #include <apt-pkg/clean.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>

+ 0 - 3
apt-pkg/clean.h

@@ -10,9 +10,6 @@
 #ifndef APTPKG_CLEAN_H
 #ifndef APTPKG_CLEAN_H
 #define APTPKG_CLEAN_H
 #define APTPKG_CLEAN_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/clean.h"
-#endif 
 
 
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/pkgcache.h>
 
 

+ 0 - 3
apt-pkg/contrib/cdromutl.cc

@@ -10,9 +10,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/cdromutl.h"
-#endif
 #include <apt-pkg/cdromutl.h>
 #include <apt-pkg/cdromutl.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/md5.h>
 #include <apt-pkg/md5.h>

+ 0 - 4
apt-pkg/contrib/cdromutl.h

@@ -14,10 +14,6 @@
 
 
 using std::string;
 using std::string;
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/cdromutl.h"
-#endif 
-
 bool MountCdrom(string Path);
 bool MountCdrom(string Path);
 bool UnmountCdrom(string Path);
 bool UnmountCdrom(string Path);
 bool IdentCdrom(string CD,string &Res,unsigned int Version = 2);
 bool IdentCdrom(string CD,string &Res,unsigned int Version = 2);

+ 0 - 3
apt-pkg/contrib/cmndline.cc

@@ -11,9 +11,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include files							/*{{{*/
 // Include files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/cmndline.h"
-#endif
 #include <apt-pkg/cmndline.h>
 #include <apt-pkg/cmndline.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/strutl.h>

+ 1 - 3
apt-pkg/contrib/cmndline.h

@@ -44,9 +44,7 @@
 #ifndef PKGLIB_CMNDLINE_H
 #ifndef PKGLIB_CMNDLINE_H
 #define PKGLIB_CMNDLINE_H
 #define PKGLIB_CMNDLINE_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/cmndline.h"
-#endif 
+
 
 
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/configuration.h>
 
 

+ 0 - 3
apt-pkg/contrib/configuration.cc

@@ -15,9 +15,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include files							/*{{{*/
 // Include files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/configuration.h"
-#endif
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/strutl.h>

+ 1 - 3
apt-pkg/contrib/configuration.h

@@ -28,9 +28,7 @@
 #ifndef PKGLIB_CONFIGURATION_H
 #ifndef PKGLIB_CONFIGURATION_H
 #define PKGLIB_CONFIGURATION_H
 #define PKGLIB_CONFIGURATION_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/configuration.h"
-#endif 
+
 
 
 #include <string>
 #include <string>
 #include <iostream>
 #include <iostream>

+ 0 - 4
apt-pkg/contrib/crc-16.cc

@@ -15,10 +15,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/crc-16.h"
-#endif
-
 #include <apt-pkg/crc-16.h>
 #include <apt-pkg/crc-16.h>
 									/*}}}*/
 									/*}}}*/
 
 

+ 0 - 4
apt-pkg/contrib/crc-16.h

@@ -10,10 +10,6 @@
 #ifndef APTPKG_CRC16_H
 #ifndef APTPKG_CRC16_H
 #define APTPKG_CRC16_H
 #define APTPKG_CRC16_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/crc-16.h"
-#endif 
-
 #define INIT_FCS  0xffff
 #define INIT_FCS  0xffff
 unsigned short AddCRC16(unsigned short fcs, void const *buf,
 unsigned short AddCRC16(unsigned short fcs, void const *buf,
 			unsigned long len);
 			unsigned long len);

+ 0 - 4
apt-pkg/contrib/error.cc

@@ -14,10 +14,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/error.h"
-#endif 
-
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>
 
 
 #include <iostream>
 #include <iostream>

+ 1 - 3
apt-pkg/contrib/error.h

@@ -40,9 +40,7 @@
 #ifndef PKGLIB_ERROR_H
 #ifndef PKGLIB_ERROR_H
 #define PKGLIB_ERROR_H
 #define PKGLIB_ERROR_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/error.h"
-#endif 
+
 
 
 #ifdef __GNUG__
 #ifdef __GNUG__
 // Methods have a hidden this parameter that is visible to this attribute
 // Methods have a hidden this parameter that is visible to this attribute

+ 1 - 3
apt-pkg/contrib/fileutl.cc

@@ -14,9 +14,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/fileutl.h"
-#endif 
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/sptr.h>
 #include <apt-pkg/sptr.h>
@@ -24,6 +21,7 @@
 
 
 #include <apti18n.h>
 #include <apti18n.h>
 
 
+#include <cstdlib>
 #include <iostream>
 #include <iostream>
 #include <unistd.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <fcntl.h>

+ 0 - 3
apt-pkg/contrib/fileutl.h

@@ -21,9 +21,6 @@
 #ifndef PKGLIB_FILEUTL_H
 #ifndef PKGLIB_FILEUTL_H
 #define PKGLIB_FILEUTL_H
 #define PKGLIB_FILEUTL_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/fileutl.h"
-#endif 
 
 
 #include <string>
 #include <string>
 
 

+ 0 - 4
apt-pkg/contrib/hashes.cc

@@ -11,10 +11,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/hashes.h"
-#endif
-
 #include <apt-pkg/hashes.h>
 #include <apt-pkg/hashes.h>
     
     
 #include <unistd.h>    
 #include <unistd.h>    

+ 0 - 3
apt-pkg/contrib/hashes.h

@@ -13,9 +13,6 @@
 #ifndef APTPKG_HASHES_H
 #ifndef APTPKG_HASHES_H
 #define APTPKG_HASHES_H
 #define APTPKG_HASHES_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/hashes.h"
-#endif 
 
 
 #include <apt-pkg/md5.h>
 #include <apt-pkg/md5.h>
 #include <apt-pkg/sha1.h>
 #include <apt-pkg/sha1.h>

+ 0 - 4
apt-pkg/contrib/md5.cc

@@ -35,10 +35,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/md5.h"
-#endif
-
 #include <apt-pkg/md5.h>
 #include <apt-pkg/md5.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/strutl.h>
 
 

+ 0 - 3
apt-pkg/contrib/md5.h

@@ -23,9 +23,6 @@
 #ifndef APTPKG_MD5_H
 #ifndef APTPKG_MD5_H
 #define APTPKG_MD5_H
 #define APTPKG_MD5_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/md5.h"
-#endif 
 
 
 #include <string>
 #include <string>
 #include <algorithm>
 #include <algorithm>

+ 0 - 4
apt-pkg/contrib/mmap.cc

@@ -21,10 +21,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/mmap.h"
-#endif 
-
 #define _BSD_SOURCE
 #define _BSD_SOURCE
 #include <apt-pkg/mmap.h>
 #include <apt-pkg/mmap.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>

+ 0 - 3
apt-pkg/contrib/mmap.h

@@ -25,9 +25,6 @@
 #ifndef PKGLIB_MMAP_H
 #ifndef PKGLIB_MMAP_H
 #define PKGLIB_MMAP_H
 #define PKGLIB_MMAP_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/mmap.h"
-#endif
 
 
 #include <string>
 #include <string>
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/fileutl.h>

+ 0 - 3
apt-pkg/contrib/progress.cc

@@ -8,9 +8,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/progress.h"
-#endif 
 #include <apt-pkg/progress.h>
 #include <apt-pkg/progress.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/configuration.h>

+ 0 - 3
apt-pkg/contrib/progress.h

@@ -21,9 +21,6 @@
 #ifndef PKGLIB_PROGRESS_H
 #ifndef PKGLIB_PROGRESS_H
 #define PKGLIB_PROGRESS_H
 #define PKGLIB_PROGRESS_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/progress.h"
-#endif 
 
 
 #include <string>
 #include <string>
 #include <sys/time.h>
 #include <sys/time.h>

+ 0 - 4
apt-pkg/contrib/sha1.cc

@@ -29,10 +29,6 @@
  */
  */
 									/*}}} */
 									/*}}} */
 // Include Files                                                        /*{{{*/
 // Include Files                                                        /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/sha1.h"
-#endif
-
 #include <apt-pkg/sha1.h>
 #include <apt-pkg/sha1.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/strutl.h>
 
 

+ 0 - 4
apt-pkg/contrib/sha1.h

@@ -14,10 +14,6 @@
 #ifndef APTPKG_SHA1_H
 #ifndef APTPKG_SHA1_H
 #define APTPKG_SHA1_H
 #define APTPKG_SHA1_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/sha1.h"
-#endif 
-
 #include <string>
 #include <string>
 #include <algorithm>
 #include <algorithm>
 
 

+ 0 - 4
apt-pkg/contrib/sha256.h

@@ -14,10 +14,6 @@
 #ifndef APTPKG_SHA256_H
 #ifndef APTPKG_SHA256_H
 #define APTPKG_SHA256_H
 #define APTPKG_SHA256_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/sha256.h"
-#endif 
-
 #include <string>
 #include <string>
 #include <algorithm>
 #include <algorithm>
 
 

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

@@ -15,10 +15,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Includes								/*{{{*/
 // Includes								/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/strutl.h"
-#endif
-
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>
@@ -28,16 +24,60 @@
 #include <ctype.h>
 #include <ctype.h>
 #include <string.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdio.h>
+#include <algorithm>
 #include <unistd.h>
 #include <unistd.h>
 #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 

+ 3 - 4
apt-pkg/contrib/strutl.h

@@ -16,9 +16,7 @@
 #ifndef STRUTL_H
 #ifndef STRUTL_H
 #define STRUTL_H
 #define STRUTL_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/strutl.h"
-#endif 
+
 
 
 #include <stdlib.h>
 #include <stdlib.h>
 #include <string>
 #include <string>
@@ -38,7 +36,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 - 4
apt-pkg/deb/debindexfile.cc

@@ -9,10 +9,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/debindexfile.h"
-#endif
-
 #include <apt-pkg/debindexfile.h>
 #include <apt-pkg/debindexfile.h>
 #include <apt-pkg/debsrcrecords.h>
 #include <apt-pkg/debsrcrecords.h>
 #include <apt-pkg/deblistparser.h>
 #include <apt-pkg/deblistparser.h>
@@ -320,6 +316,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 +576,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 +593,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 +604,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;

+ 31 - 3
apt-pkg/deb/debindexfile.h

@@ -16,9 +16,7 @@
 #ifndef PKGLIB_DEBINDEXFILE_H
 #ifndef PKGLIB_DEBINDEXFILE_H
 #define PKGLIB_DEBINDEXFILE_H
 #define PKGLIB_DEBINDEXFILE_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/debindexfile.h"
-#endif
+
 
 
 #include <apt-pkg/indexfile.h>
 #include <apt-pkg/indexfile.h>
 
 
@@ -74,6 +72,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;

+ 46 - 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>
 
 
@@ -104,6 +105,8 @@ bool debListParser::NewVersion(pkgCache::VerIterator Ver)
       return false;
       return false;
    if (ParseDepends(Ver,"Conflicts",pkgCache::Dep::Conflicts) == false)
    if (ParseDepends(Ver,"Conflicts",pkgCache::Dep::Conflicts) == false)
       return false;
       return false;
+   if (ParseDepends(Ver,"Breaks",pkgCache::Dep::DpkgBreaks) == false)
+      return false;
    if (ParseDepends(Ver,"Replaces",pkgCache::Dep::Replaces) == false)
    if (ParseDepends(Ver,"Replaces",pkgCache::Dep::Replaces) == false)
       return false;
       return false;
 
 
@@ -117,6 +120,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 
@@ -150,6 +195,7 @@ unsigned short debListParser::VersionHash()
 //                            "Suggests",
 //                            "Suggests",
 //                            "Recommends",
 //                            "Recommends",
                             "Conflicts",
                             "Conflicts",
+                            "Breaks",
                             "Replaces",0};
                             "Replaces",0};
    unsigned long Result = INIT_FCS;
    unsigned long Result = INIT_FCS;
    char S[1024];
    char S[1024];

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

+ 16 - 5
apt-pkg/deb/debmetaindex.cc

@@ -1,9 +1,5 @@
 // ijones, walters
 // ijones, walters
 
 
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/debmetaindex.h"
-#endif
-
 #include <apt-pkg/debmetaindex.h>
 #include <apt-pkg/debmetaindex.h>
 #include <apt-pkg/debindexfile.h>
 #include <apt-pkg/debindexfile.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/strutl.h>
@@ -157,6 +153,16 @@ 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++) {
+
+      if((*I)->IsSrc)
+	 continue;
+      debTranslationsIndex i = debTranslationsIndex(URI,Dist,(*I)->Section);
+      i.GetIndexes(Owner);
+   }
+
    return true;
    return true;
 }
 }
 
 
@@ -181,11 +187,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;
 }
 }
 
 

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

@@ -2,10 +2,6 @@
 #ifndef PKGLIB_DEBMETAINDEX_H
 #ifndef PKGLIB_DEBMETAINDEX_H
 #define PKGLIB_DEBMETAINDEX_H
 #define PKGLIB_DEBMETAINDEX_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/debmetaindex.h"
-#endif
-
 #include <apt-pkg/metaindex.h>
 #include <apt-pkg/metaindex.h>
 #include <apt-pkg/sourcelist.h>
 #include <apt-pkg/sourcelist.h>
 
 

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

@@ -8,11 +8,10 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/debrecords.h"
-#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 +29,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 +80,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 +92,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;
 }
 }
 									/*}}}*/
 									/*}}}*/
 
 

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

@@ -14,11 +14,8 @@
 #ifndef PKGLIB_DEBRECORDS_H
 #ifndef PKGLIB_DEBRECORDS_H
 #define PKGLIB_DEBRECORDS_H
 #define PKGLIB_DEBRECORDS_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/debrecords.h"
-#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 +27,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:
 
 

+ 1 - 5
apt-pkg/deb/debsrcrecords.cc

@@ -9,10 +9,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/debsrcrecords.h"
-#endif 
-
 #include <apt-pkg/deblistparser.h>
 #include <apt-pkg/deblistparser.h>
 #include <apt-pkg/debsrcrecords.h>
 #include <apt-pkg/debsrcrecords.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>
@@ -40,7 +36,7 @@ const char **debSrcRecordParser::Binaries()
    {
    {
       delete [] Buffer;
       delete [] Buffer;
       // allocate new size based on buffer (but never smaller than 4000)
       // allocate new size based on buffer (but never smaller than 4000)
-      BufSize = max((unsigned long)4000, max((unsigned long)Bins.length()+1,2*BufSize));
+      BufSize = max((unsigned int)4000, max((unsigned int)Bins.length()+1,2*BufSize));
       Buffer = new char[BufSize];
       Buffer = new char[BufSize];
    }
    }
 
 

+ 1 - 4
apt-pkg/deb/debsrcrecords.h

@@ -11,9 +11,6 @@
 #ifndef PKGLIB_DEBSRCRECORDS_H
 #ifndef PKGLIB_DEBSRCRECORDS_H
 #define PKGLIB_DEBSRCRECORDS_H
 #define PKGLIB_DEBSRCRECORDS_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/debsrcrecords.h"
-#endif 
 
 
 #include <apt-pkg/srcrecords.h>
 #include <apt-pkg/srcrecords.h>
 #include <apt-pkg/tagfile.h>
 #include <apt-pkg/tagfile.h>
@@ -27,7 +24,7 @@ class debSrcRecordParser : public pkgSrcRecords::Parser
    char *StaticBinList[400];
    char *StaticBinList[400];
    unsigned long iOffset;
    unsigned long iOffset;
    char *Buffer;
    char *Buffer;
-   unsigned long BufSize;
+   unsigned int BufSize;
    
    
    public:
    public:
 
 

+ 0 - 4
apt-pkg/deb/debsystem.cc

@@ -10,10 +10,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/debsystem.h"
-#endif
-
 #include <apt-pkg/debsystem.h>
 #include <apt-pkg/debsystem.h>
 #include <apt-pkg/debversion.h>
 #include <apt-pkg/debversion.h>
 #include <apt-pkg/debindexfile.h>
 #include <apt-pkg/debindexfile.h>

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

@@ -10,10 +10,6 @@
 #ifndef PKGLIB_DEBSYSTEM_H
 #ifndef PKGLIB_DEBSYSTEM_H
 #define PKGLIB_DEBSYSTEM_H
 #define PKGLIB_DEBSYSTEM_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/debsystem.h"
-#endif
-
 #include <apt-pkg/pkgsystem.h>
 #include <apt-pkg/pkgsystem.h>
 
 
 class debStatusIndex;
 class debStatusIndex;

+ 0 - 3
apt-pkg/deb/debversion.cc

@@ -11,9 +11,6 @@
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
 #define APT_COMPATIBILITY 986
 #define APT_COMPATIBILITY 986
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/debversion.h"
-#endif
 
 
 #include <apt-pkg/debversion.h>
 #include <apt-pkg/debversion.h>
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/pkgcache.h>

+ 1 - 3
apt-pkg/deb/debversion.h

@@ -12,9 +12,7 @@
 #ifndef PKGLIB_DEBVERSION_H
 #ifndef PKGLIB_DEBVERSION_H
 #define PKGLIB_DEBVERSION_H
 #define PKGLIB_DEBVERSION_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/debversion.h"
-#endif 
+
 
 
 #include <apt-pkg/version.h>
 #include <apt-pkg/version.h>
     
     

+ 2 - 3
apt-pkg/deb/dpkgpm.cc

@@ -8,9 +8,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Includes								/*{{{*/
 // Includes								/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/dpkgpm.h"
-#endif
 #include <apt-pkg/dpkgpm.h>
 #include <apt-pkg/dpkgpm.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/configuration.h>
@@ -474,6 +471,8 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 	 case Item::Install:
 	 case Item::Install:
 	 Args[n++] = "--unpack";
 	 Args[n++] = "--unpack";
 	 Size += strlen(Args[n-1]);
 	 Size += strlen(Args[n-1]);
+	 Args[n++] = "--auto-deconfigure";
+	 Size += strlen(Args[n-1]);
 	 break;
 	 break;
       }
       }
       
       

+ 1 - 5
apt-pkg/deb/dpkgpm.h

@@ -10,10 +10,6 @@
 #ifndef PKGLIB_DPKGPM_H
 #ifndef PKGLIB_DPKGPM_H
 #define PKGLIB_DPKGPM_H
 #define PKGLIB_DPKGPM_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/dpkgpm.h"
-#endif
-
 #include <apt-pkg/packagemanager.h>
 #include <apt-pkg/packagemanager.h>
 #include <vector>
 #include <vector>
 #include <stdio.h>
 #include <stdio.h>
@@ -47,7 +43,7 @@ class pkgDPkgPM : public pkgPackageManager
    bool RunScripts(const char *Cnf);
    bool RunScripts(const char *Cnf);
    bool RunScriptsWithPkgs(const char *Cnf);
    bool RunScriptsWithPkgs(const char *Cnf);
    bool SendV2Pkgs(FILE *F);
    bool SendV2Pkgs(FILE *F);
-   
+
    // The Actuall installation implementation
    // The Actuall installation implementation
    virtual bool Install(PkgIterator Pkg,string File);
    virtual bool Install(PkgIterator Pkg,string File);
    virtual bool Configure(PkgIterator Pkg);
    virtual bool Configure(PkgIterator Pkg);

+ 549 - 43
apt-pkg/depcache.cc

@@ -8,24 +8,59 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/depcache.h"
-#endif
 #include <apt-pkg/depcache.h>
 #include <apt-pkg/depcache.h>
 #include <apt-pkg/version.h>
 #include <apt-pkg/version.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/sptr.h>
 #include <apt-pkg/sptr.h>
 #include <apt-pkg/algorithms.h>
 #include <apt-pkg/algorithms.h>
+
+#include <apt-pkg/fileutl.h>
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/configuration.h>
+#include <apt-pkg/pkgsystem.h>
+#include <apt-pkg/tagfile.h>
+
+#include <iostream>
+#include <sstream>    
+#include <set>
+
+#include <sys/stat.h>
 
 
 #include <apti18n.h>    
 #include <apti18n.h>    
-									/*}}}*/
+
+pkgDepCache::ActionGroup::ActionGroup(pkgDepCache &cache) :
+  cache(cache), released(false)
+{
+  ++cache.group_level;
+}
+
+void pkgDepCache::ActionGroup::release()
+{
+  if(!released)
+    {
+      if(cache.group_level == 0)
+	std::cerr << "W: Unbalanced action groups, expect badness" << std::endl;
+      else
+	{
+	  --cache.group_level;
+
+	  if(cache.group_level == 0)
+	    cache.MarkAndSweep();
+	}
+
+      released = false;
+    }
+}
+
+pkgDepCache::ActionGroup::~ActionGroup()
+{
+  release();
+}
 
 
 // DepCache::pkgDepCache - Constructors					/*{{{*/
 // DepCache::pkgDepCache - Constructors					/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
 pkgDepCache::pkgDepCache(pkgCache *pCache,Policy *Plcy) :
 pkgDepCache::pkgDepCache(pkgCache *pCache,Policy *Plcy) :
-                Cache(pCache), PkgState(0), DepState(0)
+  group_level(0), Cache(pCache), PkgState(0), DepState(0)
 {
 {
    delLocalPolicy = 0;
    delLocalPolicy = 0;
    LocalPolicy = Plcy;
    LocalPolicy = Plcy;
@@ -48,6 +83,10 @@ pkgDepCache::~pkgDepCache()
 /* This allocats the extension buffers and initializes them. */
 /* This allocats the extension buffers and initializes them. */
 bool pkgDepCache::Init(OpProgress *Prog)
 bool pkgDepCache::Init(OpProgress *Prog)
 {
 {
+   // Suppress mark updates during this operation (just in case) and
+   // run a mark operation when Init terminates.
+   ActionGroup actions(*this);
+
    delete [] PkgState;
    delete [] PkgState;
    delete [] DepState;
    delete [] DepState;
    PkgState = new StateCache[Head().PackageCount];
    PkgState = new StateCache[Head().PackageCount];
@@ -73,7 +112,7 @@ bool pkgDepCache::Init(OpProgress *Prog)
       // Find the proper cache slot
       // Find the proper cache slot
       StateCache &State = PkgState[I->ID];
       StateCache &State = PkgState[I->ID];
       State.iFlags = 0;
       State.iFlags = 0;
-      
+
       // Figure out the install version
       // Figure out the install version
       State.CandidateVer = GetCandidateVer(I);
       State.CandidateVer = GetCandidateVer(I);
       State.InstallVer = I.CurrentVer();
       State.InstallVer = I.CurrentVer();
@@ -95,11 +134,134 @@ bool pkgDepCache::Init(OpProgress *Prog)
 
 
    if(Prog != 0)
    if(Prog != 0)
       Prog->Done();
       Prog->Done();
-   
+
    return true;
    return true;
 } 
 } 
 									/*}}}*/
 									/*}}}*/
 
 
+bool pkgDepCache::readStateFile(OpProgress *Prog)
+{
+   FileFd state_file;
+   string state = _config->FindDir("Dir::State") + "extended_states";
+   if(FileExists(state)) {
+      state_file.Open(state, FileFd::ReadOnly);
+      int file_size = state_file.Size();
+      if(Prog != NULL)
+	 Prog->OverallProgress(0, file_size, 1, 
+			       _("Reading state information"));
+
+      pkgTagFile tagfile(&state_file);
+      pkgTagSection section;
+      int amt=0;
+      while(tagfile.Step(section)) {
+	 string pkgname = section.FindS("Package");
+	 pkgCache::PkgIterator pkg=Cache->FindPkg(pkgname);
+	 // Silently ignore unknown packages and packages with no actual
+	 // version.
+	 if(!pkg.end() && !pkg.VersionList().end()) {
+	    short reason = section.FindI("Auto-Installed", 0);
+	    if(reason > 0)
+	       PkgState[pkg->ID].Flags  |= Flag::Auto;
+	    if(_config->FindB("Debug::pkgAutoRemove",false))
+	       std::cout << "Auto-Installed : " << pkgname << std::endl;
+	    amt+=section.size();
+	    if(Prog != NULL)
+	       Prog->OverallProgress(amt, file_size, 1, 
+				     _("Reading state information"));
+	 }
+	 if(Prog != NULL)
+	    Prog->OverallProgress(file_size, file_size, 1, 
+				  _("Reading state information"));
+      }
+   }
+
+   return true;
+}
+
+bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly)
+{
+   if(_config->FindB("Debug::pkgAutoRemove",false))
+      std::clog << "pkgDepCache::writeStateFile()" << std::endl;
+
+   FileFd StateFile;
+   string state = _config->FindDir("Dir::State") + "extended_states";
+
+   // if it does not exist, create a empty one
+   if(!FileExists(state)) 
+   {
+      StateFile.Open(state, FileFd::WriteEmpty);
+      StateFile.Close();
+   }
+
+   // open it
+   if(!StateFile.Open(state, FileFd::ReadOnly))
+      return _error->Error(_("Failed to open StateFile %s"),
+			   state.c_str());
+
+   FILE *OutFile;
+   string outfile = state + ".tmp";
+   if((OutFile = fopen(outfile.c_str(),"w")) == NULL)
+      return _error->Error(_("Failed to write temporary StateFile %s"),
+			   outfile.c_str());
+
+   // first merge with the existing sections
+   pkgTagFile tagfile(&StateFile);
+   pkgTagSection section;
+   std::set<string> pkgs_seen;
+   const char *nullreorderlist[] = {0};
+   while(tagfile.Step(section)) {
+	 string pkgname = section.FindS("Package");
+	 // Silently ignore unknown packages and packages with no actual
+	 // version.
+	 pkgCache::PkgIterator pkg=Cache->FindPkg(pkgname);
+	 if(pkg.end() || pkg.VersionList().end()) 
+	    continue;
+	 bool oldAuto = section.FindI("Auto-Installed");
+	 bool newAuto = (PkgState[pkg->ID].Flags & Flag::Auto);
+	 if(_config->FindB("Debug::pkgAutoRemove",false))
+	    std::clog << "Update exisiting AutoInstall info: " 
+		      << pkg.Name() << std::endl;
+	 TFRewriteData rewrite[2];
+	 rewrite[0].Tag = "Auto-Installed";
+	 rewrite[0].Rewrite = newAuto ? "1" : "0";
+	 rewrite[0].NewTag = 0;
+	 rewrite[1].Tag = 0;
+	 TFRewrite(OutFile, section, nullreorderlist, rewrite);
+	 fprintf(OutFile,"\n");
+	 pkgs_seen.insert(pkgname);
+   }
+   
+   // then write the ones we have not seen yet
+   std::ostringstream ostr;
+   for(pkgCache::PkgIterator pkg=Cache->PkgBegin(); !pkg.end(); pkg++) {
+      if(PkgState[pkg->ID].Flags & Flag::Auto) {
+	 if (pkgs_seen.find(pkg.Name()) != pkgs_seen.end()) {
+	    if(_config->FindB("Debug::pkgAutoRemove",false))
+	       std::clog << "Skipping already written " << pkg.Name() << std::endl;
+	    continue;
+	 }
+         // skip not installed ones if requested
+         if(InstalledOnly && pkg->CurrentVer == 0)
+            continue;
+	 if(_config->FindB("Debug::pkgAutoRemove",false))
+	    std::clog << "Writing new AutoInstall: " 
+		      << pkg.Name() << std::endl;
+	 ostr.str(string(""));
+	 ostr << "Package: " << pkg.Name() 
+	      << "\nAuto-Installed: 1\n\n";
+	 fprintf(OutFile,ostr.str().c_str());
+	 fprintf(OutFile,"\n");
+      }
+   }
+   fclose(OutFile);
+
+   // move the outfile over the real file and set permissions
+   rename(outfile.c_str(), state.c_str());
+   chmod(state.c_str(), 0644);
+
+   return true;
+}
+
 // DepCache::CheckDep - Checks a single dependency			/*{{{*/
 // DepCache::CheckDep - Checks a single dependency			/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* This first checks the dependency against the main target package and
 /* This first checks the dependency against the main target package and
@@ -114,7 +276,7 @@ bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res)
       we allow it anyhow because dpkg does. Technically it is a packaging
       we allow it anyhow because dpkg does. Technically it is a packaging
       bug. Conflicts may never self match */
       bug. Conflicts may never self match */
    if (Dep.TargetPkg() != Dep.ParentPkg() || 
    if (Dep.TargetPkg() != Dep.ParentPkg() || 
-       (Dep->Type != Dep::Conflicts && Dep->Type != Dep::Obsoletes))
+       (Dep->Type != Dep::Conflicts && Dep->Type != Dep::DpkgBreaks && Dep->Type != Dep::Obsoletes))
    {
    {
       PkgIterator Pkg = Dep.TargetPkg();
       PkgIterator Pkg = Dep.TargetPkg();
       // Check the base package
       // Check the base package
@@ -144,7 +306,8 @@ bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res)
    {
    {
       /* Provides may never be applied against the same package if it is
       /* Provides may never be applied against the same package if it is
          a conflicts. See the comment above. */
          a conflicts. See the comment above. */
-      if (P.OwnerPkg() == Pkg && Dep->Type == Dep::Conflicts)
+      if (P.OwnerPkg() == Pkg &&
+	  (Dep->Type == Dep::Conflicts || Dep->Type == Dep::DpkgBreaks))
 	 continue;
 	 continue;
       
       
       // Check if the provides is a hit
       // Check if the provides is a hit
@@ -240,9 +403,11 @@ void pkgDepCache::AddStates(const PkgIterator &Pkg,int Add)
 {
 {
    StateCache &State = PkgState[Pkg->ID];
    StateCache &State = PkgState[Pkg->ID];
    
    
-   // The Package is broken
+   // The Package is broken (either minimal dep or policy dep)
    if ((State.DepState & DepInstMin) != DepInstMin)
    if ((State.DepState & DepInstMin) != DepInstMin)
       iBrokenCount += Add;
       iBrokenCount += Add;
+   if ((State.DepState & DepInstPolicy) != DepInstPolicy)
+      iPolicyBrokenCount += Add;
    
    
    // Bad state
    // Bad state
    if (Pkg.State() != PkgIterator::NeedsNothing)
    if (Pkg.State() != PkgIterator::NeedsNothing)
@@ -296,7 +461,9 @@ void pkgDepCache::BuildGroupOrs(VerIterator const &V)
 
 
       /* Invert for Conflicts. We have to do this twice to get the
       /* Invert for Conflicts. We have to do this twice to get the
          right sense for a conflicts group */
          right sense for a conflicts group */
-      if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
+      if (D->Type == Dep::Conflicts ||
+	  D->Type == Dep::DpkgBreaks ||
+	  D->Type == Dep::Obsoletes)
 	 State = ~State;
 	 State = ~State;
       
       
       // Add to the group if we are within an or..
       // Add to the group if we are within an or..
@@ -307,7 +474,9 @@ void pkgDepCache::BuildGroupOrs(VerIterator const &V)
 	 Group = 0;
 	 Group = 0;
       
       
       // Invert for Conflicts
       // Invert for Conflicts
-      if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
+      if (D->Type == Dep::Conflicts ||
+	  D->Type == Dep::DpkgBreaks ||
+	  D->Type == Dep::Obsoletes)
 	 State = ~State;
 	 State = ~State;
    }	 
    }	 
 }
 }
@@ -440,7 +609,9 @@ void pkgDepCache::Update(OpProgress *Prog)
 	       Group = 0;
 	       Group = 0;
 
 
 	    // Invert for Conflicts
 	    // Invert for Conflicts
-	    if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
+	    if (D->Type == Dep::Conflicts ||
+		D->Type == Dep::DpkgBreaks ||
+		D->Type == Dep::Obsoletes)
 	       State = ~State;
 	       State = ~State;
 	 }	 
 	 }	 
       }
       }
@@ -453,12 +624,14 @@ void pkgDepCache::Update(OpProgress *Prog)
 
 
    if (Prog != 0)      
    if (Prog != 0)      
       Prog->Progress(Done);
       Prog->Progress(Done);
+
+   readStateFile(Prog);
 }
 }
 									/*}}}*/
 									/*}}}*/
 // DepCache::Update - Update the deps list of a package	   		/*{{{*/
 // DepCache::Update - Update the deps list of a package	   		/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* This is a helper for update that only does the dep portion of the scan. 
 /* This is a helper for update that only does the dep portion of the scan. 
-   It is mainly ment to scan reverse dependencies. */
+   It is mainly meant to scan reverse dependencies. */
 void pkgDepCache::Update(DepIterator D)
 void pkgDepCache::Update(DepIterator D)
 {
 {
    // Update the reverse deps
    // Update the reverse deps
@@ -468,7 +641,9 @@ void pkgDepCache::Update(DepIterator D)
       State = DependencyState(D);
       State = DependencyState(D);
     
     
       // Invert for Conflicts
       // Invert for Conflicts
-      if (D->Type == Dep::Conflicts || D->Type == Dep::Obsoletes)
+      if (D->Type == Dep::Conflicts ||
+	  D->Type == Dep::DpkgBreaks ||
+	  D->Type == Dep::Obsoletes)
 	 State = ~State;
 	 State = ~State;
 
 
       RemoveStates(D.ParentPkg());
       RemoveStates(D.ParentPkg());
@@ -510,7 +685,7 @@ void pkgDepCache::Update(PkgIterator const &Pkg)
 // DepCache::MarkKeep - Put the package in the keep state		/*{{{*/
 // DepCache::MarkKeep - Put the package in the keep state		/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
-void pkgDepCache::MarkKeep(PkgIterator const &Pkg,bool Soft)
+void pkgDepCache::MarkKeep(PkgIterator const &Pkg, bool Soft, bool FromUser)
 {
 {
    // Simplifies other routines.
    // Simplifies other routines.
    if (Pkg.end() == true)
    if (Pkg.end() == true)
@@ -522,6 +697,9 @@ void pkgDepCache::MarkKeep(PkgIterator const &Pkg,bool Soft)
        Pkg.CurrentVer().Downloadable() == false)
        Pkg.CurrentVer().Downloadable() == false)
       return;
       return;
    
    
+   /** \todo Can this be moved later in the method? */
+   ActionGroup group(*this);
+
    /* We changed the soft state all the time so the UI is a bit nicer
    /* We changed the soft state all the time so the UI is a bit nicer
       to use */
       to use */
    StateCache &P = PkgState[Pkg->ID];
    StateCache &P = PkgState[Pkg->ID];
@@ -537,8 +715,17 @@ void pkgDepCache::MarkKeep(PkgIterator const &Pkg,bool Soft)
    // We dont even try to keep virtual packages..
    // We dont even try to keep virtual packages..
    if (Pkg->VersionList == 0)
    if (Pkg->VersionList == 0)
       return;
       return;
-   
-   P.Flags &= ~Flag::Auto;
+#if 0 // reseting the autoflag here means we lose the 
+      // auto-mark information if a user selects a package for removal
+      // but changes  his mind then and sets it for keep again
+      // - this makes sense as default when all Garbage dependencies
+      //   are automatically marked for removal (as aptitude does).
+      //   setting a package for keep then makes it no longer autoinstalled
+      //   for all other use-case this action is rather suprising
+   if(FromUser && !P.Marked)
+     P.Flags &= ~Flag::Auto;
+#endif
+
    RemoveSizes(Pkg);
    RemoveSizes(Pkg);
    RemoveStates(Pkg);
    RemoveStates(Pkg);
 
 
@@ -564,6 +751,8 @@ void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge)
    if (Pkg.end() == true)
    if (Pkg.end() == true)
       return;
       return;
 
 
+   ActionGroup group(*this);
+
    // Check that it is not already marked for delete
    // Check that it is not already marked for delete
    StateCache &P = PkgState[Pkg->ID];
    StateCache &P = PkgState[Pkg->ID];
    P.iFlags &= ~(AutoKept | Purge);
    P.iFlags &= ~(AutoKept | Purge);
@@ -586,7 +775,6 @@ void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge)
    else
    else
       P.Mode = ModeDelete;
       P.Mode = ModeDelete;
    P.InstallVer = 0;
    P.InstallVer = 0;
-   P.Flags &= Flag::Auto;
 
 
    AddStates(Pkg);   
    AddStates(Pkg);   
    Update(Pkg);
    Update(Pkg);
@@ -597,7 +785,8 @@ void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge)
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
 void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
 void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
-			      unsigned long Depth)
+			      unsigned long Depth, bool FromUser,
+			      bool ForceImportantDeps)
 {
 {
    if (Depth > 100)
    if (Depth > 100)
       return;
       return;
@@ -606,26 +795,27 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
    if (Pkg.end() == true)
    if (Pkg.end() == true)
       return;
       return;
    
    
+   ActionGroup group(*this);
+
    /* Check that it is not already marked for install and that it can be 
    /* Check that it is not already marked for install and that it can be 
       installed */
       installed */
    StateCache &P = PkgState[Pkg->ID];
    StateCache &P = PkgState[Pkg->ID];
    P.iFlags &= ~AutoKept;
    P.iFlags &= ~AutoKept;
-   if (P.InstBroken() == false && (P.Mode == ModeInstall ||
+   if ((P.InstPolicyBroken() == false && P.InstBroken() == false) && 
+       (P.Mode == ModeInstall ||
 	P.CandidateVer == (Version *)Pkg.CurrentVer()))
 	P.CandidateVer == (Version *)Pkg.CurrentVer()))
    {
    {
       if (P.CandidateVer == (Version *)Pkg.CurrentVer() && P.InstallVer == 0)
       if (P.CandidateVer == (Version *)Pkg.CurrentVer() && P.InstallVer == 0)
-	 MarkKeep(Pkg);
+	 MarkKeep(Pkg, false, FromUser);
       return;
       return;
    }
    }
 
 
    // See if there is even any possible instalation candidate
    // See if there is even any possible instalation candidate
    if (P.CandidateVer == 0)
    if (P.CandidateVer == 0)
       return;
       return;
-   
    // We dont even try to install virtual packages..
    // We dont even try to install virtual packages..
    if (Pkg->VersionList == 0)
    if (Pkg->VersionList == 0)
       return;
       return;
-   
    /* Target the candidate version and remove the autoflag. We reset the
    /* Target the candidate version and remove the autoflag. We reset the
       autoflag below if this was called recursively. Otherwise the user
       autoflag below if this was called recursively. Otherwise the user
       should have the ability to de-auto a package by changing its state */
       should have the ability to de-auto a package by changing its state */
@@ -634,7 +824,20 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
    
    
    P.Mode = ModeInstall;
    P.Mode = ModeInstall;
    P.InstallVer = P.CandidateVer;
    P.InstallVer = P.CandidateVer;
-   P.Flags &= ~Flag::Auto;
+
+   if(FromUser)
+     {
+       // Set it to manual if it's a new install or cancelling the
+       // removal of a garbage package.
+       if(P.Status == 2 || (!Pkg.CurrentVer().end() && !P.Marked))
+	 P.Flags &= ~Flag::Auto;
+     }
+   else
+     {
+       // Set it to auto if this is a new install.
+       if(P.Status == 2)
+	 P.Flags |= Flag::Auto;
+     }
    if (P.CandidateVer == (Version *)Pkg.CurrentVer())
    if (P.CandidateVer == (Version *)Pkg.CurrentVer())
       P.Mode = ModeKeep;
       P.Mode = ModeKeep;
        
        
@@ -666,10 +869,43 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
 
 
       /* Check if this dep should be consider for install. If it is a user
       /* Check if this dep should be consider for install. If it is a user
          defined important dep and we are installed a new package then 
          defined important dep and we are installed a new package then 
-	 it will be installed. Otherwise we only worry about critical deps */
+	 it will be installed. Otherwise we only check for important
+         deps that have changed from the installed version
+      */
       if (IsImportantDep(Start) == false)
       if (IsImportantDep(Start) == false)
 	 continue;
 	 continue;
-      if (Pkg->CurrentVer != 0 && Start.IsCritical() == false)
+      
+      /* check if any ImportantDep() (but not Critial) where added
+       * since we installed the package
+       */
+      bool isNewImportantDep = false;
+      if(!ForceImportantDeps && !Start.IsCritical())
+      {
+	 bool found=false;
+	 VerIterator instVer = Pkg.CurrentVer();
+	 if(!instVer.end())
+	 {
+	    for (DepIterator D = instVer.DependsList(); D.end() != true; D++)
+	    {
+	       //FIXME: deal better with or-groups(?)
+	       DepIterator LocalStart = D;
+	       
+	       if(IsImportantDep(D) && Start.TargetPkg() == D.TargetPkg())
+		  found=true;
+	    }
+	    // this is a new dep if it was not found to be already
+	    // a important dep of the installed pacakge
+	    isNewImportantDep = !found;
+	 }
+      }
+      if(isNewImportantDep)
+	 if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
+	    std::clog << "new important dependency: " 
+		      << Start.TargetPkg().Name() << std::endl;
+
+      // skip important deps if the package is already installed
+      if (Pkg->CurrentVer != 0 && Start.IsCritical() == false 
+	  && !isNewImportantDep && !ForceImportantDeps)
 	 continue;
 	 continue;
       
       
       /* If we are in an or group locate the first or that can 
       /* If we are in an or group locate the first or that can 
@@ -680,7 +916,8 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
       /* This bit is for processing the possibilty of an install/upgrade
       /* This bit is for processing the possibilty of an install/upgrade
          fixing the problem */
          fixing the problem */
       SPtrArray<Version *> List = Start.AllTargets();
       SPtrArray<Version *> List = Start.AllTargets();
-      if ((DepState[Start->ID] & DepCVer) == DepCVer)
+      if (Start->Type != Dep::DpkgBreaks &&
+	  (DepState[Start->ID] & DepCVer) == DepCVer)
       {
       {
 	 // Right, find the best version to install..
 	 // Right, find the best version to install..
 	 Version **Cur = List;
 	 Version **Cur = List;
@@ -711,33 +948,48 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
 	    }
 	    }
 	 }
 	 }
 	 
 	 
-	 if (InstPkg.end() == false)
+	 if (InstPkg.end() == false) 
 	 {
 	 {
 	    if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
 	    if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
 	       std::clog << "Installing " << InstPkg.Name() 
 	       std::clog << "Installing " << InstPkg.Name() 
 			 << " as dep of " << Pkg.Name() 
 			 << " as dep of " << Pkg.Name() 
 			 << std::endl;
 			 << std::endl;
-	    MarkInstall(InstPkg,true,Depth + 1);
-
-	    // Set the autoflag, after MarkInstall because MarkInstall unsets it
-	    if (P->CurrentVer == 0)
-	       PkgState[InstPkg->ID].Flags |= Flag::Auto;
+ 	    // now check if we should consider it a automatic dependency or not
+ 	    string sec = _config->Find("APT::Never-MarkAuto-Section","");
+ 	    if(Pkg.Section() && (string(Pkg.Section()) ==  sec))
+ 	    {
+ 	       if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
+ 		  std::clog << "Setting NOT as auto-installed because its a direct dep of a package in section " << sec << std::endl;
+ 	       MarkInstall(InstPkg,true,Depth + 1, true);
+ 	    }
+ 	    else 
+ 	    {
+ 	       // mark automatic dependency
+ 	       MarkInstall(InstPkg,true,Depth + 1, false, ForceImportantDeps);
+ 	       // Set the autoflag, after MarkInstall because MarkInstall unsets it
+ 	       if (P->CurrentVer == 0)
+ 		  PkgState[InstPkg->ID].Flags |= Flag::Auto;
+ 	    }
 	 }
 	 }
-	 
 	 continue;
 	 continue;
       }
       }
-      
+
       /* For conflicts we just de-install the package and mark as auto,
       /* For conflicts we just de-install the package and mark as auto,
-         Conflicts may not have or groups */
-      if (Start->Type == Dep::Conflicts || Start->Type == Dep::Obsoletes)
+         Conflicts may not have or groups.  For dpkg's Breaks we try to
+         upgrade the package. */
+      if (Start->Type == Dep::Conflicts || Start->Type == Dep::Obsoletes ||
+	  Start->Type == Dep::DpkgBreaks)
       {
       {
 	 for (Version **I = List; *I != 0; I++)
 	 for (Version **I = List; *I != 0; I++)
 	 {
 	 {
 	    VerIterator Ver(*this,*I);
 	    VerIterator Ver(*this,*I);
 	    PkgIterator Pkg = Ver.ParentPkg();
 	    PkgIterator Pkg = Ver.ParentPkg();
-      
-	    MarkDelete(Pkg);
-	    PkgState[Pkg->ID].Flags |= Flag::Auto;
+
+	    if (Start->Type != Dep::DpkgBreaks)
+	       MarkDelete(Pkg);
+	    else
+	       if (PkgState[Pkg->ID].CandidateVer != *I)
+		  MarkInstall(Pkg,true,Depth + 1, false, ForceImportantDeps);
 	 }
 	 }
 	 continue;
 	 continue;
       }      
       }      
@@ -749,6 +1001,8 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
 /* */
 /* */
 void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To)
 void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To)
 {
 {
+   ActionGroup group(*this);
+
    RemoveSizes(Pkg);
    RemoveSizes(Pkg);
    RemoveStates(Pkg);
    RemoveStates(Pkg);
    
    
@@ -767,9 +1021,11 @@ void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To)
 /* */
 /* */
 void pkgDepCache::SetCandidateVersion(VerIterator TargetVer)
 void pkgDepCache::SetCandidateVersion(VerIterator TargetVer)
 {
 {
+   ActionGroup group(*this);
+
    pkgCache::PkgIterator Pkg = TargetVer.ParentPkg();
    pkgCache::PkgIterator Pkg = TargetVer.ParentPkg();
    StateCache &P = PkgState[Pkg->ID];
    StateCache &P = PkgState[Pkg->ID];
-   
+
    RemoveSizes(Pkg);
    RemoveSizes(Pkg);
    RemoveStates(Pkg);
    RemoveStates(Pkg);
 
 
@@ -782,6 +1038,18 @@ void pkgDepCache::SetCandidateVersion(VerIterator TargetVer)
    Update(Pkg);
    Update(Pkg);
    AddSizes(Pkg);
    AddSizes(Pkg);
 }
 }
+
+void pkgDepCache::MarkAuto(const PkgIterator &Pkg, bool Auto)
+{
+  StateCache &state = PkgState[Pkg->ID];
+
+  ActionGroup group(*this);
+
+  if(Auto)
+    state.Flags |= Flag::Auto;
+  else
+    state.Flags &= ~Flag::Auto;
+}
 									/*}}}*/
 									/*}}}*/
 // StateCache::Update - Compute the various static display things	/*{{{*/
 // StateCache::Update - Compute the various static display things	/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
@@ -869,6 +1137,244 @@ pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator Pkg)
 /* */
 /* */
 bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep)
 bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep)
 {
 {
-   return Dep.IsCritical();
+   if(Dep.IsCritical())
+      return true;
+   else if(Dep->Type == pkgCache::Dep::Recommends) 
+   {
+      if ( _config->FindB("APT::Install-Recommends", false))
+	 return true;
+      // we suport a special mode to only install-recommends for certain
+      // sections
+      // FIXME: this is a meant as a temporarly solution until the 
+      //        recommends are cleaned up
+      string s = _config->Find("APT::Install-Recommends-Section","");
+      if(s.size() > 0) 
+      {
+	 const char *sec = Dep.TargetPkg().Section();
+	 if (sec && strcmp(sec, s.c_str()) == 0)
+	    return true;
+      }
+   }
+   else if(Dep->Type == pkgCache::Dep::Suggests)
+     return _config->FindB("APT::Install-Suggests", false);
+
+   return false;
 }
 }
 									/*}}}*/
 									/*}}}*/
+
+pkgDepCache::DefaultRootSetFunc::DefaultRootSetFunc()
+  : constructedSuccessfully(false)
+{
+  Configuration::Item const *Opts;
+  Opts = _config->Tree("APT::NeverAutoRemove");
+  if (Opts != 0 && Opts->Child != 0)
+    {
+      Opts = Opts->Child;
+      for (; Opts != 0; Opts = Opts->Next)
+	{
+	  if (Opts->Value.empty() == true)
+	    continue;
+
+	  regex_t *p = new regex_t;
+	  if(regcomp(p,Opts->Value.c_str(),
+		     REG_EXTENDED | REG_ICASE | REG_NOSUB) != 0)
+	    {
+	      regfree(p);
+	      delete p;
+	      _error->Error("Regex compilation error for APT::NeverAutoRemove");
+	      return;
+	    }
+
+	  rootSetRegexp.push_back(p);
+	}
+    }
+
+  constructedSuccessfully = true;
+}
+
+pkgDepCache::DefaultRootSetFunc::~DefaultRootSetFunc()
+{
+  for(unsigned int i = 0; i < rootSetRegexp.size(); i++)
+    {
+      regfree(rootSetRegexp[i]);
+      delete rootSetRegexp[i];
+    }
+}
+
+
+bool pkgDepCache::DefaultRootSetFunc::InRootSet(const pkgCache::PkgIterator &pkg)
+{
+   for(unsigned int i = 0; i < rootSetRegexp.size(); i++)
+      if (regexec(rootSetRegexp[i], pkg.Name(), 0, 0, 0) == 0)
+	 return true;
+
+   return false;
+}
+
+pkgDepCache::InRootSetFunc *pkgDepCache::GetRootSetFunc()
+{
+  DefaultRootSetFunc *f = new DefaultRootSetFunc;
+  if(f->wasConstructedSuccessfully())
+    return f;
+  else
+    {
+      delete f;
+      return NULL;
+    }
+}
+
+bool pkgDepCache::MarkFollowsRecommends()
+{
+  return _config->FindB("APT::AutoRemove::RecommendsImportant", true);
+}
+
+bool pkgDepCache::MarkFollowsSuggests()
+{
+  return _config->FindB("APT::AutoRemove::SuggestsImportant", false);
+}
+
+// the main mark algorithm
+bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
+{
+   bool follow_recommends;
+   bool follow_suggests;
+
+   // init the states
+   for(PkgIterator p = PkgBegin(); !p.end(); ++p)
+   {
+      PkgState[p->ID].Marked  = false;
+      PkgState[p->ID].Garbage = false;
+
+      // debug output
+      if(_config->FindB("Debug::pkgAutoRemove",false) 
+	 && PkgState[p->ID].Flags & Flag::Auto)
+  	 std::clog << "AutoDep: " << p.Name() << std::endl;
+   }
+
+   // init vars
+   follow_recommends = MarkFollowsRecommends();
+   follow_suggests   = MarkFollowsSuggests();
+
+
+
+   // do the mark part, this is the core bit of the algorithm
+   for(PkgIterator p = PkgBegin(); !p.end(); ++p)
+   {
+      if(!(PkgState[p->ID].Flags & Flag::Auto) ||
+	  (p->Flags & Flag::Essential) ||
+	  userFunc.InRootSet(p))
+          
+      {
+	 // the package is installed (and set to keep)
+	 if(PkgState[p->ID].Keep() && !p.CurrentVer().end())
+	    MarkPackage(p, p.CurrentVer(),
+			follow_recommends, follow_suggests);
+	 // the package is to be installed 
+	 else if(PkgState[p->ID].Install())
+	    MarkPackage(p, PkgState[p->ID].InstVerIter(*this),
+			follow_recommends, follow_suggests);
+      }
+   }
+
+   return true;
+}
+
+// mark a single package in Mark-and-Sweep
+void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
+			      const pkgCache::VerIterator &ver,
+			      bool follow_recommends,
+			      bool follow_suggests)
+{
+   pkgDepCache::StateCache &state = PkgState[pkg->ID];
+   VerIterator candver            = state.CandidateVerIter(*this);
+   VerIterator instver            = state.InstVerIter(*this);
+
+#if 0
+   // If a package was garbage-collected but is now being marked, we
+   // should re-select it 
+   // For cases when a pkg is set to upgrade and this trigger the
+   // removal of a no-longer used dependency.  if the pkg is set to
+   // keep again later it will result in broken deps
+   if(state.Delete() && state.RemoveReason = Unused) 
+   {
+      if(ver==candver)
+	 mark_install(pkg, false, false, NULL);
+      else if(ver==pkg.CurrentVer())
+	 MarkKeep(pkg, false, false);
+      
+      instver=state.InstVerIter(*this);
+   }
+#endif
+
+   // Ignore versions other than the InstVer, and ignore packages
+   // that are already going to be removed or just left uninstalled.
+   if(!(ver == instver && !instver.end()))
+      return;
+
+   // if we are marked already we are done
+   if(state.Marked)
+      return;
+
+   //std::cout << "Setting Marked for: " << pkg.Name() << std::endl;
+   state.Marked=true;
+
+   if(!ver.end())
+   {
+     for(DepIterator d = ver.DependsList(); !d.end(); ++d)
+     {
+	if(d->Type == Dep::Depends ||
+	   d->Type == Dep::PreDepends ||
+	   (follow_recommends &&
+	    d->Type == Dep::Recommends) ||
+	   (follow_suggests &&
+	    d->Type == Dep::Suggests))
+        {
+	   // Try all versions of this package.
+	   for(VerIterator V = d.TargetPkg().VersionList(); 
+	       !V.end(); ++V)
+	   {
+	      if(_system->VS->CheckDep(V.VerStr(), d->CompareOp, d.TargetVer()))
+	      {
+		 MarkPackage(V.ParentPkg(), V, 
+			     follow_recommends, follow_suggests);
+	      }
+	   }
+	   // Now try virtual packages
+	   for(PrvIterator prv=d.TargetPkg().ProvidesList(); 
+	       !prv.end(); ++prv)
+	   {
+	      if(_system->VS->CheckDep(prv.ProvideVersion(), d->CompareOp, 
+				       d.TargetVer()))
+	      {
+		 MarkPackage(prv.OwnerPkg(), prv.OwnerVer(),
+			     follow_recommends, follow_suggests);
+	      }
+	   }
+	}
+     }
+   }
+}
+
+bool pkgDepCache::Sweep()
+{
+   // do the sweep
+   for(PkgIterator p=PkgBegin(); !p.end(); ++p)
+  {
+     StateCache &state=PkgState[p->ID];
+
+     // skip required packages
+     if (!p.CurrentVer().end() && 
+	 (p.CurrentVer()->Priority == pkgCache::State::Required))
+	continue;
+
+     // if it is not marked and it is installed, it's garbage 
+     if(!state.Marked && (!p.CurrentVer().end() || state.Install()))
+     {
+	state.Garbage=true;
+	if(_config->FindB("Debug::pkgAutoRemove",false))
+	   std::cout << "Garbage: " << p.Name() << std::endl;
+     }
+  }   
+
+   return true;
+}

+ 220 - 7
apt-pkg/depcache.h

@@ -1,4 +1,4 @@
-// -*- mode: cpp; mode: fold -*-
+// -*- mode: c++; mode: fold -*-
 // Description								/*{{{*/
 // Description								/*{{{*/
 // $Id: depcache.h,v 1.14 2001/02/20 07:03:17 jgg Exp $
 // $Id: depcache.h,v 1.14 2001/02/20 07:03:17 jgg Exp $
 /* ######################################################################
 /* ######################################################################
@@ -38,16 +38,75 @@
 #ifndef PKGLIB_DEPCACHE_H
 #ifndef PKGLIB_DEPCACHE_H
 #define PKGLIB_DEPCACHE_H
 #define PKGLIB_DEPCACHE_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/depcache.h"
-#endif
 
 
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/progress.h>
 #include <apt-pkg/progress.h>
 
 
+#include <regex.h>
+
+#include <vector>
+
 class pkgDepCache : protected pkgCache::Namespace
 class pkgDepCache : protected pkgCache::Namespace
 {
 {
    public:
    public:
+
+   /** \brief An arbitrary predicate on packages. */
+   class InRootSetFunc
+   {
+   public:
+     virtual bool InRootSet(const pkgCache::PkgIterator &pkg) {return false;};
+     virtual ~InRootSetFunc() {};
+   };
+
+   private:
+   /** \brief Mark a single package and all its unmarked important
+    *  dependencies during mark-and-sweep.
+    *
+    *  Recursively invokes itself to mark all dependencies of the
+    *  package.
+    *
+    *  \param pkg The package to mark.
+    *
+    *  \param ver The version of the package that is to be marked.
+    *
+    *  \param follow_recommends If \b true, recommendations of the
+    *  package will be recursively marked.
+    *
+    *  \param follow_suggests If \b true, suggestions of the package
+    *  will be recursively marked.
+    */
+   void MarkPackage(const pkgCache::PkgIterator &pkg,
+		    const pkgCache::VerIterator &ver,
+		    bool follow_recommends,
+		    bool follow_suggests);
+
+   /** \brief Update the Marked field of all packages.
+    *
+    *  Each package's StateCache::Marked field will be set to \b true
+    *  if and only if it can be reached from the root set.  By
+    *  default, the root set consists of the set of manually installed
+    *  or essential packages, but it can be extended using the
+    *  parameter #rootFunc.
+    *
+    *  \param rootFunc A callback that can be used to add extra
+    *  packages to the root set.
+    *
+    *  \return \b false if an error occured.
+    */
+   bool MarkRequired(InRootSetFunc &rootFunc);
+
+   /** \brief Set the StateCache::Garbage flag on all packages that
+    *  should be removed.
+    *
+    *  Packages that were not marked by the last call to #MarkRequired
+    *  are tested to see whether they are actually garbage.  If so,
+    *  they are marked as such.
+    *
+    *  \return \b false if an error occured.
+    */
+   bool Sweep();
+
+   public:
    
    
    // These flags are used in DepState
    // These flags are used in DepState
    enum DepFlags {DepNow = (1 << 0),DepInstall = (1 << 1),DepCVer = (1 << 2),
    enum DepFlags {DepNow = (1 << 0),DepInstall = (1 << 1),DepCVer = (1 << 2),
@@ -63,6 +122,84 @@ class pkgDepCache : protected pkgCache::Namespace
       
       
    enum VersionTypes {NowVersion, InstallVersion, CandidateVersion};
    enum VersionTypes {NowVersion, InstallVersion, CandidateVersion};
    enum ModeList {ModeDelete = 0, ModeKeep = 1, ModeInstall = 2};
    enum ModeList {ModeDelete = 0, ModeKeep = 1, ModeInstall = 2};
+
+   /** \brief Represents an active action group.
+    *
+    *  An action group is a group of actions that are currently being
+    *  performed.  While an active group is active, certain routine
+    *  clean-up actions that would normally be performed after every
+    *  cache operation are delayed until the action group is
+    *  completed.  This is necessary primarily to avoid inefficiencies
+    *  when modifying a large number of packages at once.
+    *
+    *  This class represents an active action group.  Creating an
+    *  instance will create an action group; destroying one will
+    *  destroy the corresponding action group.
+    *
+    *  The following operations are suppressed by this class:
+    *
+    *    - Keeping the Marked and Garbage flags up to date.
+    *
+    *  \note This can be used in the future to easily accumulate
+    *  atomic actions for undo or to display "what apt did anyway";
+    *  e.g., change the counter of how many action groups are active
+    *  to a std::set of pointers to them and use those to store
+    *  information about what happened in a group in the group.
+    */
+   class ActionGroup
+   {
+       pkgDepCache &cache;
+
+       bool released;
+
+       /** Action groups are noncopyable. */
+       ActionGroup(const ActionGroup &other);
+   public:
+       /** \brief Create a new ActionGroup.
+	*
+	*  \param cache The cache that this ActionGroup should
+	*  manipulate.
+	*
+	*  As long as this object exists, no automatic cleanup
+	*  operations will be undertaken.
+	*/
+       ActionGroup(pkgDepCache &cache);
+
+       /** \brief Clean up the action group before it is destroyed.
+        *
+        *  If it is destroyed later, no second cleanup wil be run.
+	*/
+       void release();
+
+       /** \brief Destroy the action group.
+	*
+	*  If this is the last action group, the automatic cache
+	*  cleanup operations will be undertaken.
+	*/
+       ~ActionGroup();
+   };
+
+   /** \brief Returns \b true for packages matching a regular
+    *  expression in APT::NeverAutoRemove.
+    */
+   class DefaultRootSetFunc : public InRootSetFunc
+   {
+     std::vector<regex_t *> rootSetRegexp;
+     bool constructedSuccessfully;
+
+   public:
+     DefaultRootSetFunc();
+     ~DefaultRootSetFunc();
+
+     /** \return \b true if the class initialized successfully, \b
+      *  false otherwise.  Used to avoid throwing an exception, since
+      *  APT classes generally don't.
+      */
+     bool wasConstructedSuccessfully() const { return constructedSuccessfully; }
+
+     bool InRootSet(const pkgCache::PkgIterator &pkg);
+   };
+
    struct StateCache
    struct StateCache
    {
    {
       // Epoch stripped text versions of the two version fields
       // Epoch stripped text versions of the two version fields
@@ -79,6 +216,17 @@ class pkgDepCache : protected pkgCache::Namespace
       unsigned short Flags;
       unsigned short Flags;
       unsigned short iFlags;           // Internal flags
       unsigned short iFlags;           // Internal flags
 
 
+      /** \brief \b true if this package can be reached from the root set. */
+      bool Marked;
+
+      /** \brief \b true if this package is unused and should be removed.
+       *
+       *  This differs from !#Marked, because it is possible that some
+       *  unreachable packages will be protected from becoming
+       *  garbage.
+       */
+      bool Garbage;
+
       // Various tree indicators
       // Various tree indicators
       signed char Status;              // -1,0,1,2
       signed char Status;              // -1,0,1,2
       unsigned char Mode;              // ModeList
       unsigned char Mode;              // ModeList
@@ -97,7 +245,9 @@ class pkgDepCache : protected pkgCache::Namespace
       inline bool Downgrade() const {return Status < 0 && Mode == ModeInstall;};
       inline bool Downgrade() const {return Status < 0 && Mode == ModeInstall;};
       inline bool Held() const {return Status != 0 && Keep();};
       inline bool Held() const {return Status != 0 && Keep();};
       inline bool NowBroken() const {return (DepState & DepNowMin) != DepNowMin;};
       inline bool NowBroken() const {return (DepState & DepNowMin) != DepNowMin;};
+      inline bool NowPolicyBroken() const {return (DepState & DepNowPolicy) != DepNowPolicy;};
       inline bool InstBroken() const {return (DepState & DepInstMin) != DepInstMin;};
       inline bool InstBroken() const {return (DepState & DepInstMin) != DepInstMin;};
+      inline bool InstPolicyBroken() const {return (DepState & DepInstPolicy) != DepInstPolicy;};
       inline bool Install() const {return Mode == ModeInstall;};
       inline bool Install() const {return Mode == ModeInstall;};
       inline VerIterator InstVerIter(pkgCache &Cache)
       inline VerIterator InstVerIter(pkgCache &Cache)
                 {return VerIterator(Cache,InstallVer);};
                 {return VerIterator(Cache,InstallVer);};
@@ -119,6 +269,14 @@ class pkgDepCache : protected pkgCache::Namespace
       
       
       virtual ~Policy() {};
       virtual ~Policy() {};
    };
    };
+
+   private:
+   /** The number of open "action groups"; certain post-action
+    *  operations are suppressed if this number is > 0.
+    */
+   int group_level;
+
+   friend class ActionGroup;
      
      
    protected:
    protected:
 
 
@@ -133,6 +291,7 @@ class pkgDepCache : protected pkgCache::Namespace
    unsigned long iDelCount;
    unsigned long iDelCount;
    unsigned long iKeepCount;
    unsigned long iKeepCount;
    unsigned long iBrokenCount;
    unsigned long iBrokenCount;
+   unsigned long iPolicyBrokenCount;
    unsigned long iBadCount;
    unsigned long iBadCount;
    
    
    Policy *delLocalPolicy;           // For memory clean up..
    Policy *delLocalPolicy;           // For memory clean up..
@@ -182,16 +341,69 @@ class pkgDepCache : protected pkgCache::Namespace
    inline StateCache &operator [](PkgIterator const &I) {return PkgState[I->ID];};
    inline StateCache &operator [](PkgIterator const &I) {return PkgState[I->ID];};
    inline unsigned char &operator [](DepIterator const &I) {return DepState[I->ID];};
    inline unsigned char &operator [](DepIterator const &I) {return DepState[I->ID];};
 
 
-   // Manipulators
-   void MarkKeep(PkgIterator const &Pkg,bool Soft = false);
+   /** \return A function identifying packages in the root set other
+    *  than manually installed packages and essential packages, or \b
+    *  NULL if an error occurs.
+    *
+    *  \todo Is this the best place for this function?  Perhaps the
+    *  settings for mark-and-sweep should be stored in a single
+    *  external class?
+    */
+   virtual InRootSetFunc *GetRootSetFunc();
+
+   /** \return \b true if the garbage collector should follow recommendations.
+    */
+   virtual bool MarkFollowsRecommends();
+
+   /** \return \b true if the garbage collector should follow suggestions.
+    */
+   virtual bool MarkFollowsSuggests();
+
+   /** \brief Update the Marked and Garbage fields of all packages.
+    *
+    *  This routine is implicitly invoked after all state manipulators
+    *  and when an ActionGroup is destroyed.  It invokes #MarkRequired
+    *  and #Sweep to do its dirty work.
+    *
+    *  \param rootFunc A predicate that returns \b true for packages
+    *  that should be added to the root set.
+    */
+   bool MarkAndSweep(InRootSetFunc &rootFunc)
+   {
+     return MarkRequired(rootFunc) && Sweep();
+   }
+
+   bool MarkAndSweep()
+   {
+     std::auto_ptr<InRootSetFunc> f(GetRootSetFunc());
+     if(f.get() != NULL)
+       return MarkAndSweep(*f.get());
+     else
+       return false;
+   }
+
+   /** \name State Manipulators
+    */
+   // @{
+   void MarkKeep(PkgIterator const &Pkg, bool Soft = false,
+		 bool FromUser = true);
    void MarkDelete(PkgIterator const &Pkg,bool Purge = false);
    void MarkDelete(PkgIterator const &Pkg,bool Purge = false);
    void MarkInstall(PkgIterator const &Pkg,bool AutoInst = true,
    void MarkInstall(PkgIterator const &Pkg,bool AutoInst = true,
-		    unsigned long Depth = 0);
+		    unsigned long Depth = 0, bool FromUser = true,
+		    bool ForceImportantDeps = false);
    void SetReInstall(PkgIterator const &Pkg,bool To);
    void SetReInstall(PkgIterator const &Pkg,bool To);
    void SetCandidateVersion(VerIterator TargetVer);
    void SetCandidateVersion(VerIterator TargetVer);
+
+   /** Set the "is automatically installed" flag of Pkg. */
+   void MarkAuto(const PkgIterator &Pkg, bool Auto);
+   // @}
    
    
    // This is for debuging
    // This is for debuging
    void Update(OpProgress *Prog = 0);
    void Update(OpProgress *Prog = 0);
+
+   // read persistent states
+   bool readStateFile(OpProgress *prog);
+   bool writeStateFile(OpProgress *prog, bool InstalledOnly=false);
    
    
    // Size queries
    // Size queries
    inline double UsrSize() {return iUsrSize;};
    inline double UsrSize() {return iUsrSize;};
@@ -200,6 +412,7 @@ class pkgDepCache : protected pkgCache::Namespace
    inline unsigned long KeepCount() {return iKeepCount;};
    inline unsigned long KeepCount() {return iKeepCount;};
    inline unsigned long InstCount() {return iInstCount;};
    inline unsigned long InstCount() {return iInstCount;};
    inline unsigned long BrokenCount() {return iBrokenCount;};
    inline unsigned long BrokenCount() {return iBrokenCount;};
+   inline unsigned long PolicyBrokenCount() {return iPolicyBrokenCount;};
    inline unsigned long BadCount() {return iBadCount;};
    inline unsigned long BadCount() {return iBadCount;};
 
 
    bool Init(OpProgress *Prog);
    bool Init(OpProgress *Prog);

+ 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

+ 63 - 4
apt-pkg/indexfile.cc

@@ -8,12 +8,11 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/indexfile.h"
-#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 +66,63 @@ 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);
+
+     // 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_*)
+     char *need_full_langcode[] = { "pt","sv","zh","en", NULL };
+     for(char **s = need_full_langcode;*s != NULL; s++)
+	if(lang.find(*s) == 0)
+	   return lang.substr(0,5);
+     
+     if(lang.size() > 2)
+	return lang.substr(0,2);
+     else
+	return lang;
+  }
+  else 
+     return Translation;
+}
+									/*}}}*/

+ 6 - 4
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
    
    
@@ -21,9 +22,6 @@
 #ifndef PKGLIB_INDEXFILE_H
 #ifndef PKGLIB_INDEXFILE_H
 #define PKGLIB_INDEXFILE_H
 #define PKGLIB_INDEXFILE_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/indexfile.h"
-#endif
 
 
 #include <string>
 #include <string>
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/pkgcache.h>
@@ -80,6 +78,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) {};

+ 0 - 3
apt-pkg/indexrecords.cc

@@ -3,9 +3,6 @@
 // $Id: indexrecords.cc,v 1.1.2.4 2003/12/30 02:11:43 mdz Exp $
 // $Id: indexrecords.cc,v 1.1.2.4 2003/12/30 02:11:43 mdz Exp $
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/indexrecords.h"
-#endif
 #include <apt-pkg/indexrecords.h>
 #include <apt-pkg/indexrecords.h>
 #include <apt-pkg/tagfile.h>
 #include <apt-pkg/tagfile.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>

+ 1 - 3
apt-pkg/indexrecords.h

@@ -5,9 +5,7 @@
 #ifndef PKGLIB_INDEXRECORDS_H
 #ifndef PKGLIB_INDEXRECORDS_H
 #define PKGLIB_INDEXRECORDS_H
 #define PKGLIB_INDEXRECORDS_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/indexrecords.h"
-#endif 
+
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/fileutl.h>
 
 

+ 6 - 0
apt-pkg/init.cc

@@ -14,6 +14,7 @@
 
 
 #include <apti18n.h>
 #include <apti18n.h>
 #include <config.h>
 #include <config.h>
+#include <cstdlib>
 #include <sys/stat.h>
 #include <sys/stat.h>
 									/*}}}*/
 									/*}}}*/
 
 
@@ -40,6 +41,8 @@ bool pkgInitConfig(Configuration &Cnf)
    else
    else
       Cnf.Set("APT::Architecture",COMMON_OS "-" COMMON_CPU);
       Cnf.Set("APT::Architecture",COMMON_OS "-" COMMON_CPU);
    Cnf.Set("APT::Build-Essential::", "build-essential");
    Cnf.Set("APT::Build-Essential::", "build-essential");
+   Cnf.Set("APT::Install-Recommends", false);
+   Cnf.Set("APT::Install-Suggests", false);
    Cnf.Set("Dir","/");
    Cnf.Set("Dir","/");
    
    
    // State   
    // State   
@@ -102,6 +105,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;
 }
 }

+ 2 - 2
apt-pkg/init.h

@@ -17,8 +17,8 @@
 #include <apt-pkg/pkgsystem.h>
 #include <apt-pkg/pkgsystem.h>
 
 
 // See the makefile
 // See the makefile
-#define APT_PKG_MAJOR 3
-#define APT_PKG_MINOR 12
+#define APT_PKG_MAJOR 4
+#define APT_PKG_MINOR 4
 #define APT_PKG_RELEASE 0
 #define APT_PKG_RELEASE 0
     
     
 extern const char *pkgVersion;
 extern const char *pkgVersion;

+ 1 - 1
apt-pkg/makefile

@@ -13,7 +13,7 @@ include ../buildlib/defaults.mak
 # methods/makefile - FIXME
 # methods/makefile - FIXME
 LIBRARY=apt-pkg
 LIBRARY=apt-pkg
 LIBEXT=$(GLIBC_VER)$(LIBSTDCPP_VER)
 LIBEXT=$(GLIBC_VER)$(LIBSTDCPP_VER)
-MAJOR=3.12
+MAJOR=4.4
 MINOR=0
 MINOR=0
 SLIBS=$(PTHREADLIB) $(INTLLIBS)
 SLIBS=$(PTHREADLIB) $(INTLLIBS)
 APT_DOMAIN:=libapt-pkg$(MAJOR)
 APT_DOMAIN:=libapt-pkg$(MAJOR)

+ 0 - 3
apt-pkg/metaindex.h

@@ -1,9 +1,6 @@
 #ifndef PKGLIB_METAINDEX_H
 #ifndef PKGLIB_METAINDEX_H
 #define PKGLIB_METAINDEX_H
 #define PKGLIB_METAINDEX_H
 
 
-/* #ifdef __GNUG__ */
-/* #pragma interface "apt-pkg/metaindex.h" */
-/* #endif */
 
 
 #include <string>
 #include <string>
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/pkgcache.h>

+ 16 - 4
apt-pkg/orderlist.cc

@@ -63,9 +63,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/orderlist.h"
-#endif 
 #include <apt-pkg/orderlist.h>
 #include <apt-pkg/orderlist.h>
 #include <apt-pkg/depcache.h>
 #include <apt-pkg/depcache.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>
@@ -491,11 +488,13 @@ bool pkgOrderList::VisitProvides(DepIterator D,bool Critical)
 	 continue;
 	 continue;
       
       
       if (D->Type != pkgCache::Dep::Conflicts &&
       if (D->Type != pkgCache::Dep::Conflicts &&
+	  D->Type != pkgCache::Dep::DpkgBreaks &&
 	  D->Type != pkgCache::Dep::Obsoletes &&
 	  D->Type != pkgCache::Dep::Obsoletes &&
 	  Cache[Pkg].InstallVer != *I)
 	  Cache[Pkg].InstallVer != *I)
 	 continue;
 	 continue;
       
       
       if ((D->Type == pkgCache::Dep::Conflicts ||
       if ((D->Type == pkgCache::Dep::Conflicts ||
+	   D->Type == pkgCache::Dep::DpkgBreaks ||
 	   D->Type == pkgCache::Dep::Obsoletes) &&
 	   D->Type == pkgCache::Dep::Obsoletes) &&
 	  (Version *)Pkg.CurrentVer() != *I)
 	  (Version *)Pkg.CurrentVer() != *I)
 	 continue;
 	 continue;
@@ -630,6 +629,7 @@ bool pkgOrderList::DepUnPackCrit(DepIterator D)
 	 /* Forward critical dependencies MUST be correct before the 
 	 /* Forward critical dependencies MUST be correct before the 
 	    package can be unpacked. */
 	    package can be unpacked. */
 	 if (D->Type != pkgCache::Dep::Conflicts &&
 	 if (D->Type != pkgCache::Dep::Conflicts &&
+	     D->Type != pkgCache::Dep::DpkgBreaks &&
 	     D->Type != pkgCache::Dep::Obsoletes &&
 	     D->Type != pkgCache::Dep::Obsoletes &&
 	     D->Type != pkgCache::Dep::PreDepends)
 	     D->Type != pkgCache::Dep::PreDepends)
 	    continue;
 	    continue;
@@ -668,7 +668,7 @@ bool pkgOrderList::DepUnPackCrit(DepIterator D)
    }   
    }   
    return true;
    return true;
 }
 }
-									/*}}}*/
+
 // OrderList::DepUnPackPreD - Critical UnPacking ordering with depends	/*{{{*/
 // OrderList::DepUnPackPreD - Critical UnPacking ordering with depends	/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* Critical PreDepends (also configure immediate and essential) strives to
 /* Critical PreDepends (also configure immediate and essential) strives to
@@ -803,9 +803,20 @@ bool pkgOrderList::DepUnPackDep(DepIterator D)
 	       return false;
 	       return false;
 	 }
 	 }
 	 else
 	 else
+	 {
 	    if (D->Type == pkgCache::Dep::Depends)
 	    if (D->Type == pkgCache::Dep::Depends)
 	       if (VisitProvides(D,false) == false)
 	       if (VisitProvides(D,false) == false)
 		  return false;
 		  return false;
+
+	    if (D->Type == pkgCache::Dep::DpkgBreaks)
+	    {
+	       if (CheckDep(D) == true)
+		 continue;
+
+	       if (VisitNode(D.TargetPkg()) == false)
+		 return false;
+	    }
+	 }
       }
       }
    return true;
    return true;
 }
 }
@@ -953,6 +964,7 @@ bool pkgOrderList::CheckDep(DepIterator D)
       /* Conflicts requires that all versions are not present, depends
       /* Conflicts requires that all versions are not present, depends
          just needs one */
          just needs one */
       if (D->Type != pkgCache::Dep::Conflicts && 
       if (D->Type != pkgCache::Dep::Conflicts && 
+	  D->Type != pkgCache::Dep::DpkgBreaks && 
 	  D->Type != pkgCache::Dep::Obsoletes)
 	  D->Type != pkgCache::Dep::Obsoletes)
       {
       {
 	 /* Try to find something that does not have the after flag set
 	 /* Try to find something that does not have the after flag set

+ 0 - 3
apt-pkg/orderlist.h

@@ -16,9 +16,6 @@
 #ifndef PKGLIB_ORDERLIST_H
 #ifndef PKGLIB_ORDERLIST_H
 #define PKGLIB_ORDERLIST_H
 #define PKGLIB_ORDERLIST_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/orderlist.h"
-#endif 
 
 
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/pkgcache.h>
 
 

+ 8 - 14
apt-pkg/packagemanager.cc

@@ -13,10 +13,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/packagemanager.h"
-#endif
-
 #include <apt-pkg/packagemanager.h>
 #include <apt-pkg/packagemanager.h>
 #include <apt-pkg/orderlist.h>
 #include <apt-pkg/orderlist.h>
 #include <apt-pkg/depcache.h>
 #include <apt-pkg/depcache.h>
@@ -95,9 +91,10 @@ bool pkgPackageManager::GetArchives(pkgAcquire *Owner,pkgSourceList *Sources,
    be downloaded. */
    be downloaded. */
 bool pkgPackageManager::FixMissing()
 bool pkgPackageManager::FixMissing()
 {   
 {   
+   pkgDepCache::ActionGroup group(Cache);
    pkgProblemResolver Resolve(&Cache);
    pkgProblemResolver Resolve(&Cache);
    List->SetFileList(FileNames);
    List->SetFileList(FileNames);
-   
+
    bool Bad = false;
    bool Bad = false;
    for (PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
    for (PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
    {
    {
@@ -106,7 +103,7 @@ bool pkgPackageManager::FixMissing()
    
    
       // Okay, this file is missing and we need it. Mark it for keep 
       // Okay, this file is missing and we need it. Mark it for keep 
       Bad = true;
       Bad = true;
-      Cache.MarkKeep(I);
+      Cache.MarkKeep(I, false, false);
    }
    }
  
  
    // We have to empty the list otherwise it will not have the new changes
    // We have to empty the list otherwise it will not have the new changes
@@ -631,14 +628,11 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall()
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* This uses the filenames in FileNames and the information in the
 /* This uses the filenames in FileNames and the information in the
    DepCache to perform the installation of packages.*/
    DepCache to perform the installation of packages.*/
-pkgPackageManager::OrderResult pkgPackageManager::DoInstall(int status_fd)
+pkgPackageManager::OrderResult pkgPackageManager::DoInstall(int statusFd)
 {
 {
-   OrderResult Res = OrderInstall();
-   if(Debug)
-      std::clog << "OrderInstall() returned: " << Res << std::endl;
-   if (Res != Failed)
-      if (Go(status_fd) == false)
-	 return Failed;
-   return Res;
+   if(DoInstallPreFork() == Failed)
+      return Failed;
+   
+   return DoInstallPostFork(statusFd);
 }
 }
 									/*}}}*/
 									/*}}}*/

+ 30 - 5
apt-pkg/packagemanager.h

@@ -23,12 +23,11 @@
 #ifndef PKGLIB_PACKAGEMANAGER_H
 #ifndef PKGLIB_PACKAGEMANAGER_H
 #define PKGLIB_PACKAGEMANAGER_H
 #define PKGLIB_PACKAGEMANAGER_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/packagemanager.h"
-#endif
 
 
 #include <string>
 #include <string>
+#include <iostream>
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/pkgcache.h>
+#include <apt-pkg/depcache.h>
 
 
 using std::string;
 using std::string;
 
 
@@ -70,13 +69,39 @@ class pkgPackageManager : protected pkgCache::Namespace
    virtual bool Remove(PkgIterator /*Pkg*/,bool /*Purge*/=false) {return false;};
    virtual bool Remove(PkgIterator /*Pkg*/,bool /*Purge*/=false) {return false;};
    virtual bool Go(int statusFd=-1) {return true;};
    virtual bool Go(int statusFd=-1) {return true;};
    virtual void Reset() {};
    virtual void Reset() {};
-   
+
+   // the result of the operation
+   OrderResult Res;
+
    public:
    public:
       
       
    // Main action members
    // Main action members
    bool GetArchives(pkgAcquire *Owner,pkgSourceList *Sources,
    bool GetArchives(pkgAcquire *Owner,pkgSourceList *Sources,
 		    pkgRecords *Recs);
 		    pkgRecords *Recs);
-   OrderResult DoInstall(int statusFd=-1); 
+
+   // Do the installation 
+   OrderResult DoInstall(int statusFd=-1);
+
+   // stuff that needs to be done before the fork() of a library that
+   // uses apt
+   OrderResult DoInstallPreFork() {
+      Res = OrderInstall();
+      return Res;
+   };
+
+   // stuff that needs to be done after the fork
+   OrderResult DoInstallPostFork(int statusFd=-1) {
+      bool goResult = Go(statusFd);
+      if(goResult == false) 
+	 return Failed;
+
+      // if all was fine update the state file
+      if(Res == Completed) {
+	 Cache.writeStateFile(NULL);
+      }
+      return Res;
+   };
+
    bool FixMissing();
    bool FixMissing();
    
    
    pkgPackageManager(pkgDepCache *Cache);
    pkgPackageManager(pkgDepCache *Cache);

+ 36 - 10
apt-pkg/pkgcache.cc

@@ -20,12 +20,8 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/pkgcache.h"
-#pragma implementation "apt-pkg/cacheiterators.h"
-#endif 
-
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/pkgcache.h>
+#include <apt-pkg/indexfile.h>
 #include <apt-pkg/version.h>
 #include <apt-pkg/version.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/strutl.h>
@@ -43,6 +39,7 @@
 
 
 using std::string;
 using std::string;
 
 
+
 // Cache::Header::Header - Constructor					/*{{{*/
 // Cache::Header::Header - Constructor					/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* Simply initialize the header */
 /* Simply initialize the header */
@@ -52,7 +49,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 = 6;
    MinorVersion = 0;
    MinorVersion = 0;
    Dirty = false;
    Dirty = false;
    
    
@@ -60,17 +57,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 +91,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 +119,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();
@@ -217,8 +223,8 @@ const char *pkgCache::DepType(unsigned char Type)
 {
 {
    const char *Types[] = {"",_("Depends"),_("PreDepends"),_("Suggests"),
    const char *Types[] = {"",_("Depends"),_("PreDepends"),_("Suggests"),
                           _("Recommends"),_("Conflicts"),_("Replaces"),
                           _("Recommends"),_("Conflicts"),_("Replaces"),
-                          _("Obsoletes")};
-   if (Type < 8)
+                          _("Obsoletes"),_("Breaks")};
+   if (Type < sizeof(Types)/sizeof(*Types))
       return Types[Type];
       return Types[Type];
    return "";
    return "";
 }
 }
@@ -235,11 +241,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				/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
@@ -281,10 +287,11 @@ pkgCache::PkgIterator::OkState pkgCache::PkgIterator::State() const
 // DepIterator::IsCritical - Returns true if the dep is important	/*{{{*/
 // DepIterator::IsCritical - Returns true if the dep is important	/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* Currently critical deps are defined as depends, predepends and
 /* Currently critical deps are defined as depends, predepends and
-   conflicts. */
+   conflicts (including dpkg's Breaks fields). */
 bool pkgCache::DepIterator::IsCritical()
 bool pkgCache::DepIterator::IsCritical()
 {
 {
    if (Dep->Type == pkgCache::Dep::Conflicts ||
    if (Dep->Type == pkgCache::Dep::Conflicts ||
+       Dep->Type == pkgCache::Dep::DpkgBreaks ||
        Dep->Type == pkgCache::Dep::Obsoletes ||
        Dep->Type == pkgCache::Dep::Obsoletes ||
        Dep->Type == pkgCache::Dep::Depends ||
        Dep->Type == pkgCache::Dep::Depends ||
        Dep->Type == pkgCache::Dep::PreDepends)
        Dep->Type == pkgCache::Dep::PreDepends)
@@ -370,6 +377,7 @@ pkgCache::Version **pkgCache::DepIterator::AllTargets()
 	    continue;
 	    continue;
 
 
 	 if ((Dep->Type == pkgCache::Dep::Conflicts ||
 	 if ((Dep->Type == pkgCache::Dep::Conflicts ||
+	      Dep->Type == pkgCache::Dep::DpkgBreaks ||
 	      Dep->Type == pkgCache::Dep::Obsoletes) &&
 	      Dep->Type == pkgCache::Dep::Obsoletes) &&
 	     ParentPkg() == I.ParentPkg())
 	     ParentPkg() == I.ParentPkg())
 	    continue;
 	    continue;
@@ -386,6 +394,7 @@ pkgCache::Version **pkgCache::DepIterator::AllTargets()
 	    continue;
 	    continue;
 	 
 	 
 	 if ((Dep->Type == pkgCache::Dep::Conflicts ||
 	 if ((Dep->Type == pkgCache::Dep::Conflicts ||
+	      Dep->Type == pkgCache::Dep::DpkgBreaks ||
 	      Dep->Type == pkgCache::Dep::Obsoletes) &&
 	      Dep->Type == pkgCache::Dep::Obsoletes) &&
 	     ParentPkg() == I.OwnerPkg())
 	     ParentPkg() == I.OwnerPkg())
 	    continue;
 	    continue;
@@ -599,3 +608,20 @@ string pkgCache::PkgFileIterator::RelStr()
    return Res;
    return Res;
 }
 }
 									/*}}}*/
 									/*}}}*/
+// VerIterator::TranslatedDescription - Return the a DescIter for locale/*{{{*/
+// ---------------------------------------------------------------------
+/* return a DescIter for the current locale or the default if none is 
+ * found
+ */
+pkgCache::DescIterator pkgCache::VerIterator::TranslatedDescription() const
+{
+   pkgCache::DescIterator DescDefault = DescriptionList();
+   pkgCache::DescIterator Desc = DescDefault;
+   for (; Desc.end() == false; Desc++)
+      if (pkgIndexFile::LanguageCode() == Desc.LanguageCode())
+	 break;
+   if (Desc.end() == true) Desc = DescDefault;
+   return Desc;
+};
+
+									/*}}}*/

+ 47 - 6
apt-pkg/pkgcache.h

@@ -19,9 +19,6 @@
 #ifndef PKGLIB_PKGCACHE_H
 #ifndef PKGLIB_PKGCACHE_H
 #define PKGLIB_PKGCACHE_H
 #define PKGLIB_PKGCACHE_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/pkgcache.h"
-#endif 
 
 
 #include <string>
 #include <string>
 #include <time.h>
 #include <time.h>
@@ -38,32 +35,42 @@ 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;
    
    
    // These are all the constants used in the cache structures
    // These are all the constants used in the cache structures
+
+   // WARNING - if you change these lists you must also edit
+   // the stringification in pkgcache.cc and also consider whether
+   // the cache file will become incompatible.
    struct Dep
    struct Dep
    {
    {
       enum DepType {Depends=1,PreDepends=2,Suggests=3,Recommends=4,
       enum DepType {Depends=1,PreDepends=2,Suggests=3,Recommends=4,
-	 Conflicts=5,Replaces=6,Obsoletes=7};
+	 Conflicts=5,Replaces=6,Obsoletes=7,DpkgBreaks=8};
       enum DepCompareOp {Or=0x10,NoOp=0,LessEq=0x1,GreaterEq=0x2,Less=0x3,
       enum DepCompareOp {Or=0x10,NoOp=0,LessEq=0x1,GreaterEq=0x2,Less=0x3,
 	 Greater=0x4,Equals=0x5,NotEquals=0x6};
 	 Greater=0x4,Equals=0x5,NotEquals=0x6};
    };
    };
@@ -98,8 +105,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 +160,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 +182,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 +207,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 +246,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 +263,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 +275,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 +338,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;

+ 117 - 12
apt-pkg/pkgcachegen.cc

@@ -10,10 +10,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/pkgcachegen.h"
-#endif
-
 #define APT_COMPATIBILITY 986
 #define APT_COMPATIBILITY 986
 
 
 #include <apt-pkg/pkgcachegen.h>
 #include <apt-pkg/pkgcachegen.h>
@@ -26,6 +22,8 @@
 #include <apt-pkg/sptr.h>
 #include <apt-pkg/sptr.h>
 #include <apt-pkg/pkgsystem.h>
 #include <apt-pkg/pkgsystem.h>
 
 
+#include <apt-pkg/tagfile.h>
+
 #include <apti18n.h>
 #include <apti18n.h>
 
 
 #include <vector>
 #include <vector>
@@ -125,16 +123,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 +196,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 +205,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 +228,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 +253,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 +318,7 @@ bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const 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 +396,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
@@ -571,8 +674,10 @@ static bool CheckValidity(const string &CacheFile, FileIterator Start,
     
     
       if ((*Start)->Exists() == false)
       if ((*Start)->Exists() == false)
       {
       {
+#if 0 // mvo: we no longer give a message here (Default Sources spec)
 	 _error->WarningE("stat",_("Couldn't stat source package list %s"),
 	 _error->WarningE("stat",_("Couldn't stat source package list %s"),
 			  (*Start)->Describe().c_str());
 			  (*Start)->Describe().c_str());
+#endif
 	 continue;
 	 continue;
       }
       }
 
 
@@ -580,7 +685,7 @@ static bool CheckValidity(const 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;
    }
    }
    
    
@@ -676,7 +781,7 @@ static bool BuildCache(pkgCacheGenerator &Gen,
 bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
 bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
 			MMap **OutMap,bool AllowMem)
 			MMap **OutMap,bool AllowMem)
 {
 {
-   unsigned long MapSize = _config->FindI("APT::Cache-Limit",12*1024*1024);
+   unsigned long MapSize = _config->FindI("APT::Cache-Limit",16*1024*1024);
    
    
    vector<pkgIndexFile *> Files;
    vector<pkgIndexFile *> Files;
    for (vector<metaIndex *>::const_iterator i = List.begin();
    for (vector<metaIndex *>::const_iterator i = List.begin();
@@ -823,7 +928,7 @@ bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
 /* */
 /* */
 bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **OutMap)
 bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **OutMap)
 {
 {
-   unsigned long MapSize = _config->FindI("APT::Cache-Limit",8*1024*1024);
+   unsigned long MapSize = _config->FindI("APT::Cache-Limit",12*1024*1024);
    vector<pkgIndexFile *> Files;
    vector<pkgIndexFile *> Files;
    unsigned long EndOfSource = Files.size();
    unsigned long EndOfSource = Files.size();
    if (_system->AddStatusFiles(Files) == false)
    if (_system->AddStatusFiles(Files) == false)

+ 6 - 3
apt-pkg/pkgcachegen.h

@@ -19,11 +19,9 @@
 #ifndef PKGLIB_PKGCACHEGEN_H
 #ifndef PKGLIB_PKGCACHEGEN_H
 #define PKGLIB_PKGCACHEGEN_H
 #define PKGLIB_PKGCACHEGEN_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/pkgcachegen.h"
-#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 +53,9 @@ class pkgCacheGenerator
    
    
    bool NewPackage(pkgCache::PkgIterator &Pkg,const string &Pkg);
    bool NewPackage(pkgCache::PkgIterator &Pkg,const 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,const string &VerStr,unsigned long Next);
    unsigned long NewVersion(pkgCache::VerIterator &Ver,const string &VerStr,unsigned long Next);
+   map_ptrloc NewDescription(pkgCache::DescIterator &Desc,const string &Lang,const MD5SumValue &md5sum,map_ptrloc Next);
 
 
    public:
    public:
 
 
@@ -108,6 +108,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 - 3
apt-pkg/pkgrecords.cc

@@ -9,9 +9,6 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 // Include Files							/*{{{*/
 // Include Files							/*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/pkgrecords.h"
-#endif
 #include <apt-pkg/pkgrecords.h>
 #include <apt-pkg/pkgrecords.h>
 #include <apt-pkg/indexfile.h>
 #include <apt-pkg/indexfile.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>
@@ -63,3 +60,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 - 3
apt-pkg/pkgrecords.h

@@ -17,9 +17,6 @@
 #ifndef PKGLIB_PKGRECORDS_H
 #ifndef PKGLIB_PKGRECORDS_H
 #define PKGLIB_PKGRECORDS_H
 #define PKGLIB_PKGRECORDS_H
 
 
-#ifdef __GNUG__
-#pragma interface "apt-pkg/pkgrecords.h"
-#endif 
 
 
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/fileutl.h>
@@ -38,6 +35,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);
@@ -49,6 +47,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;

+ 0 - 0
apt-pkg/pkgsystem.cc


Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff