Przeglądaj źródła

Merge branch 'debian/sid' into debian/experimental

Conflicts:
	apt-private/private-list.cc
	configure.ac
	debian/apt.install.in
	debian/changelog
Michael Vogt 12 lat temu
rodzic
commit
fce69e7a0f
100 zmienionych plików z 3013 dodań i 1337 usunięć
  1. 6 0
      .gitignore
  2. 1 1
      .travis.yml
  3. 0 9
      BUGS
  4. 1 1
      COMPILING
  5. 2 1
      Makefile
  6. 2 2
      README.ddtp
  7. 1 1
      README.make
  8. 1 1
      README.progress-reporting
  9. 1 1
      abicheck/run_abi_test
  10. 4 4
      apt-inst/contrib/arfile.cc
  11. 18 14
      apt-inst/contrib/extracttar.cc
  12. 23 18
      apt-inst/deb/debfile.cc
  13. 1 0
      apt-inst/deb/debfile.h
  14. 10 11
      apt-inst/dirstream.cc
  15. 2 2
      apt-inst/extract.cc
  16. 2 2
      apt-inst/filelist.cc
  17. 238 68
      apt-pkg/acquire-item.cc
  18. 116 3
      apt-pkg/acquire-item.h
  19. 7 2
      apt-pkg/acquire-worker.cc
  20. 3 3
      apt-pkg/acquire.cc
  21. 6 316
      apt-pkg/algorithms.cc
  22. 8 12
      apt-pkg/algorithms.h
  23. 8 8
      apt-pkg/aptconfiguration.cc
  24. 5 5
      apt-pkg/aptconfiguration.h
  25. 3 3
      apt-pkg/cacheiterators.h
  26. 28 3
      apt-pkg/cacheset.cc
  27. 6 0
      apt-pkg/cacheset.h
  28. 64 91
      apt-pkg/cdrom.cc
  29. 5 1
      apt-pkg/cdrom.h
  30. 1 1
      apt-pkg/clean.cc
  31. 2 2
      apt-pkg/contrib/cdromutl.cc
  32. 2 1
      apt-pkg/contrib/cmndline.cc
  33. 1 1
      apt-pkg/contrib/crc-16.cc
  34. 1 1
      apt-pkg/contrib/error.h
  35. 118 74
      apt-pkg/contrib/fileutl.cc
  36. 5 0
      apt-pkg/contrib/fileutl.h
  37. 8 15
      apt-pkg/contrib/gpgv.cc
  38. 1 1
      apt-pkg/contrib/gpgv.h
  39. 23 7
      apt-pkg/contrib/hashes.cc
  40. 8 1
      apt-pkg/contrib/hashes.h
  41. 3 4
      apt-pkg/contrib/hashsum.cc
  42. 1 1
      apt-pkg/contrib/macros.h
  43. 1 1
      apt-pkg/contrib/md5.h
  44. 7 1
      apt-pkg/contrib/mmap.cc
  45. 2 2
      apt-pkg/contrib/mmap.h
  46. 1 1
      apt-pkg/contrib/progress.h
  47. 1 1
      apt-pkg/contrib/sha2_internal.cc
  48. 61 5
      apt-pkg/contrib/strutl.cc
  49. 32 1
      apt-pkg/contrib/strutl.h
  50. 3 5
      apt-pkg/deb/deblistparser.cc
  51. 16 1
      apt-pkg/deb/debmetaindex.cc
  52. 7 0
      apt-pkg/deb/debmetaindex.h
  53. 3 3
      apt-pkg/deb/debsrcrecords.h
  54. 1 1
      apt-pkg/deb/debsystem.cc
  55. 2 2
      apt-pkg/deb/debversion.cc
  56. 433 292
      apt-pkg/deb/dpkgpm.cc
  57. 30 2
      apt-pkg/deb/dpkgpm.h
  58. 20 9
      apt-pkg/depcache.cc
  59. 2 2
      apt-pkg/depcache.h
  60. 3 3
      apt-pkg/edsp.h
  61. 4 4
      apt-pkg/indexfile.h
  62. 5 0
      apt-pkg/indexrecords.cc
  63. 1 0
      apt-pkg/indexrecords.h
  64. 2 10
      apt-pkg/init.cc
  65. 375 0
      apt-pkg/install-progress.cc
  66. 156 0
      apt-pkg/install-progress.h
  67. 4 2
      apt-pkg/makefile
  68. 17 7
      apt-pkg/metaindex.h
  69. 4 4
      apt-pkg/orderlist.cc
  70. 66 21
      apt-pkg/packagemanager.cc
  71. 24 1
      apt-pkg/packagemanager.h
  72. 2 2
      apt-pkg/pkgcache.cc
  73. 1 1
      apt-pkg/pkgcache.h
  74. 2 2
      apt-pkg/pkgsystem.h
  75. 4 0
      apt-pkg/policy.cc
  76. 131 10
      apt-pkg/sourcelist.cc
  77. 9 1
      apt-pkg/sourcelist.h
  78. 3 2
      apt-pkg/srcrecords.cc
  79. 68 45
      apt-pkg/tagfile.cc
  80. 1 1
      apt-pkg/tagfile.h
  81. 126 0
      apt-pkg/update.cc
  82. 21 0
      apt-pkg/update.h
  83. 263 0
      apt-pkg/upgrade.cc
  84. 30 0
      apt-pkg/upgrade.h
  85. 5 2
      apt-private/acqprogress.cc
  86. 1 1
      apt-private/acqprogress.h
  87. 1 1
      apt-private/makefile
  88. 1 0
      apt-private/private-cachefile.cc
  89. 9 0
      apt-private/private-cacheset.cc
  90. 5 0
      apt-private/private-cacheset.h
  91. 20 5
      apt-private/private-cmndline.cc
  92. 96 0
      apt-private/private-download.cc
  93. 9 0
      apt-private/private-download.h
  94. 72 109
      apt-private/private-install.cc
  95. 6 0
      apt-private/private-install.h
  96. 26 21
      apt-private/private-list.cc
  97. 60 52
      apt-private/private-output.cc
  98. 3 2
      apt-private/private-output.h
  99. 9 7
      apt-private/private-search.cc
  100. 0 0
      apt-private/private-show.cc

+ 6 - 0
.gitignore

@@ -1,3 +1,4 @@
+*~
 # build artifacts
 /aclocal.m4
 /autom4te.cache/
@@ -31,7 +32,12 @@
 /debian/apt-transport-https/
 
 # generated from *.in files
+/cmdline/apt-key
+/doc/apt-vendor.ent
 /doc/examples/sources.list
 /debian/libapt-pkg*.install
 /debian/libapt-inst*.install
 /debian/libapt-pkg-dev.install
+/vendor/current
+/vendor/debian/sources.list
+/vendor/ubuntu/sources.list

+ 1 - 1
.travis.yml

@@ -1,5 +1,5 @@
 language: cpp
 before_install:
  - sudo apt-get update -q
- - sudo apt-get install -q dpkg-dev debhelper libdb-dev gettext libcurl4-gnutls-dev zlib1g-dev libbz2-dev xsltproc docbook-xsl docbook-xml po4a autotools-dev autoconf automake doxygen debiandoc-sgml
+ - sudo apt-get install -q --no-install-recommends dpkg-dev debhelper libdb-dev gettext libcurl4-gnutls-dev zlib1g-dev libbz2-dev xsltproc docbook-xsl docbook-xml po4a autotools-dev autoconf automake doxygen debiandoc-sgml stunnel4
 script: make && make test && test/integration/run-tests

+ 0 - 9
BUGS

@@ -1,9 +0,0 @@
-
-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
COMPILING

@@ -27,7 +27,7 @@ I am not interested in making 'ultra portable code'. I will accept patches
 to make the code that already exists conform more to SUS or POSIX, but
 I don't really care if your not-SUS OS doesn't work. It is simply too
 much work to maintain patches for dysfunctional OSs. I highly suggest you
-contact your vendor and express intrest in a conforming C library.
+contact your vendor and express interest in a conforming C library.
 
 That said, there are lots of finicky problems that must be dealt with even
 between the supported OS's. Primarily the path I choose to take is to put

+ 2 - 1
Makefile

@@ -11,6 +11,7 @@ default: startup all
 
 .PHONY: headers library clean veryclean all binary program doc test update-po
 all headers library clean veryclean binary program doc manpages debiandoc test update-po startup dirs:
+	$(MAKE) -C vendor $@
 	$(MAKE) -C apt-pkg $@
 	$(MAKE) -C apt-inst $@
 	$(MAKE) -C apt-private $@
@@ -20,7 +21,7 @@ all headers library clean veryclean binary program doc manpages debiandoc test u
 	$(MAKE) -C dselect $@
 	$(MAKE) -C doc $@
 	$(MAKE) -C po $@
-	$(MAKE) -C test $@ 
+	$(MAKE) -C test $@
 
 all headers library clean veryclean binary program doc manpages debiandoc test update-po: startup dirs
 

+ 2 - 2
README.ddtp

@@ -52,7 +52,7 @@ is md5("XXX\n YYY\n .\n ZZZ\n") (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
+description of the package with the right md5 chechsum. The environment
 of the user will controlled this process (LANG, LANGUAGE, LC_MESSAGES,
 etc). With this the package system will never show a outdated
 translation.
@@ -60,7 +60,7 @@ 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 
+Now the first files are accessible 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

+ 1 - 1
README.make

@@ -25,7 +25,7 @@ of these parameters will have an immediate effect. The use of makefile.in
 and configure substitutions across build makefiles is not used at all.
 
 Furthermore, the make system runs with a current directory equal to the
-source directory irregardless of the destination directory. This means
+source directory regardless of the destination directory. This means
 #include "" and #include <> work as expected and more importantly
 running 'make' in the source directory will work as expected. The
 environment variable or make parameter 'BUILD' sets the build directory.

+ 1 - 1
README.progress-reporting

@@ -2,7 +2,7 @@ Install-progress reporting
 --------------------------
 
 If the apt options: "APT::Status-Fd" is set, apt will send status
-reports to that fd. The status information is seperated with a ':', 
+reports to that fd. The status information is separated with a ':',
 there are the following status conditions:
 
 status = {"pmstatus", "dlstatus", "conffile-prompt", "error", "media-change" } 

+ 1 - 1
abicheck/run_abi_test

@@ -16,4 +16,4 @@ sed s#@installed_libapt@#$LIBPATH# apt_installed.xml.in > apt_installed.xml
 BUILDPATH=$(readlink -f ../build)
 sed s#@build_path@#$BUILDPATH# apt_build.xml.in > apt_build.xml
 
-abi-compliance-checker -l apt -d1 apt_installed.xml -d2 apt_build.xml
+abi-compliance-checker -l apt -d1 apt_installed.xml -d2 apt_build.xml $@

+ 4 - 4
apt-inst/contrib/arfile.cc

@@ -6,7 +6,7 @@
    AR File - Handle an 'AR' archive
    
    AR Archives have plain text headers at the start of each file
-   section. The headers are aligned on a 2 byte boundry.
+   section. The headers are aligned on a 2 byte boundary.
    
    Information about the structure of AR files can be found in ar(5)
    on a BSD system, or in the binutils source.
@@ -64,7 +64,7 @@ ARArchive::~ARArchive()
    byte plain text header then the file data, another header, data, etc */
 bool ARArchive::LoadHeaders()
 {
-   signed long Left = File.Size();
+   off_t Left = File.Size();
    
    // Check the magic byte
    char Magic[8];
@@ -123,7 +123,7 @@ bool ARArchive::LoadHeaders()
       }
 
       // Account for the AR header alignment 
-      unsigned Skip = Memb->Size % 2;
+      off_t Skip = Memb->Size % 2;
       
       // Add it to the list
       Memb->Next = List;
@@ -131,7 +131,7 @@ bool ARArchive::LoadHeaders()
       Memb->Start = File.Tell();
       if (File.Skip(Memb->Size + Skip) == false)
 	 return false;
-      if (Left < (signed)(Memb->Size + Skip))
+      if (Left < (off_t)(Memb->Size + Skip))
 	 return _error->Error(_("Archive is too short"));
       Left -= Memb->Size + Skip;
    }   

+ 18 - 14
apt-inst/contrib/extracttar.cc

@@ -6,7 +6,7 @@
    Extract a Tar - Tar Extractor
 
    Some performance measurements showed that zlib performed quite poorly
-   in comparision to a forked gzip process. This tar extractor makes use
+   in comparison to a forked gzip process. This tar extractor makes use
    of the fact that dup'd file descriptors have the same seek pointer
    and that gzip will not read past the end of a compressed stream, 
    even if there is more data. We use the dup property to track extraction
@@ -111,6 +111,12 @@ bool ExtractTar::Done(bool Force)
    gzip will efficiently ignore the extra bits. */
 bool ExtractTar::StartGzip()
 {
+   if (DecompressProg.empty())
+   {
+      InFd.OpenDescriptor(File.Fd(), FileFd::ReadOnly, FileFd::None, false);
+      return true;
+   }
+
    int Pipes[2];
    if (pipe(Pipes) != 0)
       return _error->Errno("pipe",_("Failed to create pipes"));
@@ -161,8 +167,8 @@ bool ExtractTar::Go(pkgDirStream &Stream)
       return false;
    
    // Loop over all blocks
-   string LastLongLink;
-   string LastLongName;
+   string LastLongLink, ItemLink;
+   string LastLongName, ItemName;
    while (1)
    {
       bool BadRecord = false;      
@@ -208,25 +214,23 @@ bool ExtractTar::Go(pkgDirStream &Stream)
 	  StrToNum(Tar->Major,Itm.Major,sizeof(Tar->Major),8) == false ||
 	  StrToNum(Tar->Minor,Itm.Minor,sizeof(Tar->Minor),8) == false)
 	 return _error->Error(_("Corrupted archive"));
-      
-      // Grab the filename
+
+      // Grab the filename and link target: use last long name if one was
+      // set, otherwise use the header value as-is, but remember that it may
+      // fill the entire 100-byte block and needs to be zero-terminated.
+      // See Debian Bug #689582.
       if (LastLongName.empty() == false)
 	 Itm.Name = (char *)LastLongName.c_str();
       else
-      {
-	 Tar->Name[sizeof(Tar->Name)-1] = 0;
-	 Itm.Name = Tar->Name;
-      }      
+	 Itm.Name = (char *)ItemName.assign(Tar->Name, sizeof(Tar->Name)).c_str();
       if (Itm.Name[0] == '.' && Itm.Name[1] == '/' && Itm.Name[2] != 0)
 	 Itm.Name += 2;
-      
-      // Grab the link target
-      Tar->Name[sizeof(Tar->LinkName)-1] = 0;
-      Itm.LinkTarget = Tar->LinkName;
 
       if (LastLongLink.empty() == false)
 	 Itm.LinkTarget = (char *)LastLongLink.c_str();
-      
+      else
+	 Itm.LinkTarget = (char *)ItemLink.assign(Tar->LinkName, sizeof(Tar->LinkName)).c_str();
+
       // Convert the type over
       switch (Tar->LinkFlag)
       {

+ 23 - 18
apt-inst/deb/debfile.cc

@@ -42,17 +42,19 @@ debDebFile::debDebFile(FileFd &File) : File(File), AR(File)
       return;
    }
 
-   if (!CheckMember("control.tar.gz")) {
-      _error->Error(_("This is not a valid DEB archive, missing '%s' member"), "control.tar.gz");
+   if (!CheckMember("control.tar") &&
+       !CheckMember("control.tar.gz") &&
+       !CheckMember("control.tar.xz")) {
+      _error->Error(_("This is not a valid DEB archive, missing '%s' member"), "control.tar");
       return;
    }
 
-   if (!CheckMember("data.tar.gz") &&
+   if (!CheckMember("data.tar") &&
+       !CheckMember("data.tar.gz") &&
        !CheckMember("data.tar.bz2") &&
        !CheckMember("data.tar.lzma") &&
        !CheckMember("data.tar.xz")) {
-      // FIXME: add data.tar.xz here - adding it now would require a Translation round for a very small gain
-      _error->Error(_("This is not a valid DEB archive, it has no '%s', '%s' or '%s' member"), "data.tar.gz", "data.tar.bz2", "data.tar.lzma");
+      _error->Error(_("This is not a valid DEB archive, missing '%s' member"), "data.tar");
       return;
    }
 }
@@ -89,30 +91,32 @@ const ARArchive::Member *debDebFile::GotoMember(const char *Name)
    return Member;
 }
 									/*}}}*/
-// DebFile::ExtractArchive - Extract the archive data itself		/*{{{*/
+// DebFile::ExtractTarMember - Extract the contents of a tar member	/*{{{*/
 // ---------------------------------------------------------------------
 /* Simple wrapper around tar.. */
-bool debDebFile::ExtractArchive(pkgDirStream &Stream)
+bool debDebFile::ExtractTarMember(pkgDirStream &Stream,const char *Name)
 {
    // Get the archive member
    const ARArchive::Member *Member = NULL;
    std::string Compressor;
 
-   std::string const data = "data.tar";
    std::vector<APT::Configuration::Compressor> compressor = APT::Configuration::getCompressors();
    for (std::vector<APT::Configuration::Compressor>::const_iterator c = compressor.begin();
 	c != compressor.end(); ++c)
    {
-      Member = AR.FindMember(std::string(data).append(c->Extension).c_str());
+      Member = AR.FindMember(std::string(Name).append(c->Extension).c_str());
       if (Member == NULL)
 	 continue;
       Compressor = c->Binary;
       break;
    }
 
+   if (Member == NULL)
+      Member = AR.FindMember(std::string(Name).c_str());
+
    if (Member == NULL)
    {
-      std::string ext = "data.tar.{";
+      std::string ext = std::string(Name) + ".{";
       for (std::vector<APT::Configuration::Compressor>::const_iterator c = compressor.begin();
 	   c != compressor.end(); ++c)
 	 ext.append(c->Extension.substr(1));
@@ -130,6 +134,14 @@ bool debDebFile::ExtractArchive(pkgDirStream &Stream)
    return Tar.Go(Stream);
 }
 									/*}}}*/
+// DebFile::ExtractArchive - Extract the archive data itself		/*{{{*/
+// ---------------------------------------------------------------------
+/* Simple wrapper around DebFile::ExtractTarMember. */
+bool debDebFile::ExtractArchive(pkgDirStream &Stream)
+{
+   return ExtractTarMember(Stream, "data.tar");
+}
+									/*}}}*/
 
 // DebFile::ControlExtract::DoItem - Control Tar Extraction		/*{{{*/
 // ---------------------------------------------------------------------
@@ -195,14 +207,7 @@ bool debDebFile::MemControlExtract::Process(Item &Itm,const unsigned char *Data,
    it parses it into a tag section parser. */
 bool debDebFile::MemControlExtract::Read(debDebFile &Deb)
 {
-   // Get the archive member and positition the file 
-   const ARArchive::Member *Member = Deb.GotoMember("control.tar.gz");
-   if (Member == 0)
-      return false;
-
-   // Extract it.
-   ExtractTar Tar(Deb.GetFile(),Member->Size,"gzip");
-   if (Tar.Go(*this) == false)
+   if (Deb.ExtractTarMember(*this, "control.tar") == false)
       return false;
 
    if (Control == 0)

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

@@ -48,6 +48,7 @@ class debDebFile
    class ControlExtract;
    class MemControlExtract;
 
+   bool ExtractTarMember(pkgDirStream &Stream, const char *Name);
    bool ExtractArchive(pkgDirStream &Stream);
    const ARArchive::Member *GotoMember(const char *Name);
    inline FileFd &GetFile() {return File;};

+ 10 - 11
apt-inst/dirstream.cc

@@ -19,8 +19,8 @@
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <sys/time.h>
 #include <errno.h>
-#include <utime.h>
 #include <unistd.h>
 #include <apti18n.h>
 									/*}}}*/
@@ -93,19 +93,18 @@ bool pkgDirStream::FinishedFile(Item &Itm,int Fd)
 {
    if (Fd < 0)
       return true;
-   
-   if (close(Fd) != 0)
-      return _error->Errno("close",_("Failed to close file %s"),Itm.Name);
 
    /* Set the modification times. The only way it can fail is if someone
       has futzed with our file, which is intolerable :> */
-   struct utimbuf Time;
-   Time.actime = Itm.MTime;
-   Time.modtime = Itm.MTime;
-   if (utime(Itm.Name,&Time) != 0)
-      _error->Errno("utime",_("Failed to close file %s"),Itm.Name);
-   
-   return true;   
+   struct timeval times[2];
+   times[0].tv_sec = times[1].tv_sec = Itm.MTime;
+   times[0].tv_usec = times[1].tv_usec = 0;
+   if (utimes(Itm.Name, times) != 0)
+      _error->Errno("utimes", "Failed to set modification time for %s",Itm.Name);
+
+   if (close(Fd) != 0)
+      return _error->Errno("close",_("Failed to close file %s"),Itm.Name);
+   return true;
 }
 									/*}}}*/
 // DirStream::Fail - Failed processing a file				/*{{{*/

+ 2 - 2
apt-inst/extract.cc

@@ -10,7 +10,7 @@
    object is unpacked to '.dpkg.new' then the original is hardlinked to
    '.dpkg.tmp' and finally the new object is renamed to overwrite the old
    one. From an external perspective the file never ceased to exist.
-   After the archive has been sucessfully unpacked the .dpkg.tmp files 
+   After the archive has been successfully unpacked the .dpkg.tmp files
    are erased. A failure causes all the .dpkg.tmp files to be restored.
    
    Decisions about unpacking go like this:
@@ -22,7 +22,7 @@
         [Note, this is reduced to only check if a file was expected to be
          there]
       - If the existing link/file is not a directory then it is replaced
-        irregardless
+        regardless
       - If the existing link/directory is being replaced by a directory then
         absolutely nothing happens.
       - If the existing link/directory is being replaced by a link then

+ 2 - 2
apt-inst/filelist.cc

@@ -5,14 +5,14 @@
 
    File Listing - Manages a Cache of File -> Package names.
 
-   Diversions add some signficant complexity to the system. To keep 
+   Diversions add some significant complexity to the system. To keep
    storage space down in the very special case of a diverted file no
    extra bytes are allocated in the Node structure. Instead a diversion
    is inserted directly into the hash table and its flag bit set. Every
    lookup for that filename will always return the diversion.
    
    The hash buckets are stored in sorted form, with diversions having 
-   the higest sort order. Identical files are assigned the same file
+   the highest sort order. Identical files are assigned the same file
    pointer, thus after a search all of the nodes owning that file can be
    found by iterating down the bucket.
    

+ 238 - 68
apt-pkg/acquire-item.cc

@@ -129,7 +129,7 @@ void pkgAcquire::Item::Done(string Message,unsigned long long Size,string Hash,
 									/*}}}*/
 // Acquire::Item::Rename - Rename a file				/*{{{*/
 // ---------------------------------------------------------------------
-/* This helper function is used by alot of item methods as thier final
+/* This helper function is used by a lot of item methods as their final
    step */
 void pkgAcquire::Item::Rename(string From,string To)
 {
@@ -143,6 +143,32 @@ void pkgAcquire::Item::Rename(string From,string To)
    }   
 }
 									/*}}}*/
+bool pkgAcquire::Item::RenameOnError(pkgAcquire::Item::RenameOnErrorState const error)/*{{{*/
+{
+   if(FileExists(DestFile))
+      Rename(DestFile, DestFile + ".FAILED");
+
+   switch (error)
+   {
+      case HashSumMismatch:
+	 ErrorText = _("Hash Sum mismatch");
+	 Status = StatAuthError;
+	 ReportMirrorFailure("HashChecksumFailure");
+	 break;
+      case SizeMismatch:
+	 ErrorText = _("Size mismatch");
+	 Status = StatAuthError;
+	 ReportMirrorFailure("SizeFailure");
+	 break;
+      case InvalidFormat:
+	 ErrorText = _("Invalid file format");
+	 Status = StatError;
+	 // do not report as usually its not the mirrors fault, but Portal/Proxy
+	 break;
+   }
+   return false;
+}
+									/*}}}*/
 // Acquire::Item::ReportMirrorFailure					/*{{{*/
 // ---------------------------------------------------------------------
 void pkgAcquire::Item::ReportMirrorFailure(string FailCode)
@@ -273,7 +299,7 @@ void pkgAcqSubIndex::Done(string Message,unsigned long long Size,string Md5Hash,
       return;
    }
 
-   // sucess in downloading the index
+   // success in downloading the index
    // rename the index
    if(Debug)
       std::clog << "Renaming: " << DestFile << " -> " << FinalFile << std::endl;
@@ -301,7 +327,7 @@ bool pkgAcqSubIndex::ParseIndex(string const &IndexFile)		/*{{{*/
 									/*}}}*/
 // AcqDiffIndex::AcqDiffIndex - Constructor				/*{{{*/
 // ---------------------------------------------------------------------
-/* Get the DiffIndex file first and see if there are patches availabe 
+/* Get the DiffIndex file first and see if there are patches available
  * 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
@@ -343,10 +369,10 @@ pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner,
       return;
    }
 
-   if(Debug) 
-      std::clog << "pkgAcqIndexDiffs::pkgAcqIndexDiffs(): " 
-		<< CurrentPackagesFile << std::endl;
-   
+   if(Debug)
+      std::clog << "pkgAcqDiffIndex::pkgAcqDiffIndex(): "
+	 << CurrentPackagesFile << std::endl;
+
    QueueURI(Desc);
 
 }
@@ -372,8 +398,8 @@ string pkgAcqDiffIndex::Custom600Headers()
 bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile)		/*{{{*/
 {
    if(Debug)
-      std::clog << "pkgAcqIndexDiffs::ParseIndexDiff() " << IndexDiffFile 
-		<< std::endl;
+      std::clog << "pkgAcqDiffIndex::ParseIndexDiff() " << IndexDiffFile
+	 << std::endl;
 
    pkgTagSection Tags;
    string ServerSha1;
@@ -400,16 +426,18 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile)		/*{{{*/
       SHA1.AddFD(fd);
       string const local_sha1 = SHA1.Result();
 
-      if(local_sha1 == ServerSha1) 
+      if(local_sha1 == ServerSha1)
       {
-	 // we have the same sha1 as the server
+	 // we have the same sha1 as the server so we are done here
 	 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 
+	 // list cleanup needs to know that this file as well as the already
+	 // present index is ours, so we create an empty diff to save it for us
+	 new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc,
+	       ExpectedHash, ServerSha1, available_patches);
+	 return true;
+      }
+      else
       {
 	 if(Debug)
 	    std::clog << "SHA1-Current: " << ServerSha1 << " and we start at "<< fd.Name() << " " << fd.Size() << " " << local_sha1 << std::endl;
@@ -470,14 +498,37 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile)		/*{{{*/
       }
 
       // we have something, queue the next diff
-      if(found) 
+      if(found)
       {
 	 // queue the diffs
 	 string::size_type const last_space = Description.rfind(" ");
 	 if(last_space != string::npos)
 	    Description.erase(last_space, Description.size()-last_space);
-	 new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc,
-			      ExpectedHash, ServerSha1, available_patches);
+
+	 /* decide if we should download patches one by one or in one go:
+	    The first is good if the server merges patches, but many don't so client
+	    based merging can be attempt in which case the second is better.
+	    "bad things" will happen if patches are merged on the server,
+	    but client side merging is attempt as well */
+	 bool pdiff_merge = _config->FindB("Acquire::PDiffs::Merge", true);
+	 if (pdiff_merge == true)
+	 {
+	    // reprepro adds this flag if it has merged patches on the server
+	    std::string const precedence = Tags.FindS("X-Patch-Precedence");
+	    pdiff_merge = (precedence != "merged");
+	 }
+
+	 if (pdiff_merge == false)
+	    new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc,
+		  ExpectedHash, ServerSha1, available_patches);
+	 else
+	 {
+	    std::vector<pkgAcqIndexMergeDiffs*> *diffs = new std::vector<pkgAcqIndexMergeDiffs*>(available_patches.size());
+	    for(size_t i = 0; i < available_patches.size(); ++i)
+	       (*diffs)[i] = new pkgAcqIndexMergeDiffs(Owner, RealURI, Description, Desc.ShortDesc, ExpectedHash,
+		     available_patches[i], diffs);
+	 }
+
 	 Complete = false;
 	 Status = StatDone;
 	 Dequeue();
@@ -497,7 +548,7 @@ 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;
+		<< "Falling back to normal index file acquire" << std::endl;
 
    new pkgAcqIndex(Owner, RealURI, Description, Desc.ShortDesc, 
 		   ExpectedHash);
@@ -518,7 +569,7 @@ void pkgAcqDiffIndex::Done(string Message,unsigned long long Size,string Md5Hash
    string FinalFile;
    FinalFile = _config->FindDir("Dir::State::lists")+URItoFileName(RealURI);
 
-   // sucess in downloading the index
+   // success in downloading the index
    // rename the index
    FinalFile += string(".IndexDiff");
    if(Debug)
@@ -577,7 +628,7 @@ 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;
+		<< "Falling back to normal index file acquire" << std::endl;
    new pkgAcqIndex(Owner, RealURI, Description,Desc.ShortDesc, 
 		   ExpectedHash);
    Finish();
@@ -595,9 +646,7 @@ void pkgAcqIndexDiffs::Finish(bool allDone)
 
       if(!ExpectedHash.empty() && !ExpectedHash.VerifyFile(DestFile))
       {
-	 Status = StatAuthError;
-	 ErrorText = _("MD5Sum mismatch");
-	 Rename(DestFile,DestFile + ".FAILED");
+	 RenameOnError(HashSumMismatch);
 	 Dequeue();
 	 return;
       }
@@ -684,7 +733,7 @@ void pkgAcqIndexDiffs::Done(string Message,unsigned long long Size,string Md5Has
    string FinalFile;
    FinalFile = _config->FindDir("Dir::State::lists")+URItoFileName(RealURI);
 
-   // sucess in downloading a diff, enter ApplyDiff state
+   // success in downloading a diff, enter ApplyDiff state
    if(State == StateFetchDiff)
    {
 
@@ -708,6 +757,7 @@ void pkgAcqIndexDiffs::Done(string Message,unsigned long long Size,string Md5Has
    {
       // remove the just applied patch
       available_patches.erase(available_patches.begin());
+      unlink((FinalFile + ".ed").c_str());
 
       // move into place
       if(Debug) 
@@ -728,6 +778,131 @@ void pkgAcqIndexDiffs::Done(string Message,unsigned long long Size,string Md5Has
    }
 }
 									/*}}}*/
+// AcqIndexMergeDiffs::AcqIndexMergeDiffs - Constructor			/*{{{*/
+pkgAcqIndexMergeDiffs::pkgAcqIndexMergeDiffs(pkgAcquire *Owner,
+				   string const &URI, string const &URIDesc,
+				   string const &ShortDesc, HashString const &ExpectedHash,
+				   DiffInfo const &patch,
+				   std::vector<pkgAcqIndexMergeDiffs*> const * const allPatches)
+   : Item(Owner), RealURI(URI), ExpectedHash(ExpectedHash),
+     patch(patch),allPatches(allPatches), State(StateFetchDiff)
+{
+
+   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;
+
+   Desc.URI = string(RealURI) + ".diff/" + patch.file + ".gz";
+   Desc.Description = Description + " " + patch.file + string(".pdiff");
+   DestFile = _config->FindDir("Dir::State::lists") + "partial/";
+   DestFile += URItoFileName(RealURI + ".diff/" + patch.file);
+
+   if(Debug)
+      std::clog << "pkgAcqIndexMergeDiffs: " << Desc.URI << std::endl;
+
+   QueueURI(Desc);
+}
+									/*}}}*/
+void pkgAcqIndexMergeDiffs::Failed(string Message,pkgAcquire::MethodConfig *Cnf)/*{{{*/
+{
+   if(Debug)
+      std::clog << "pkgAcqIndexMergeDiffs failed: " << Desc.URI << " with " << Message << std::endl;
+   Complete = false;
+   Status = StatDone;
+   Dequeue();
+
+   // check if we are the first to fail, otherwise we are done here
+   State = StateDoneDiff;
+   for (std::vector<pkgAcqIndexMergeDiffs *>::const_iterator I = allPatches->begin();
+	 I != allPatches->end(); ++I)
+      if ((*I)->State == StateErrorDiff)
+	 return;
+
+   // first failure means we should fallback
+   State = StateErrorDiff;
+   std::clog << "Falling back to normal index file acquire" << std::endl;
+   new pkgAcqIndex(Owner, RealURI, Description,Desc.ShortDesc,
+		   ExpectedHash);
+}
+									/*}}}*/
+void pkgAcqIndexMergeDiffs::Done(string Message,unsigned long long Size,string Md5Hash,	/*{{{*/
+			    pkgAcquire::MethodConfig *Cnf)
+{
+   if(Debug)
+      std::clog << "pkgAcqIndexMergeDiffs::Done(): " << Desc.URI << std::endl;
+
+   Item::Done(Message,Size,Md5Hash,Cnf);
+
+   string const FinalFile = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI);
+
+   if (State == StateFetchDiff)
+   {
+      // rred expects the patch as $FinalFile.ed.$patchname.gz
+      Rename(DestFile, FinalFile + ".ed." + patch.file + ".gz");
+
+      // check if this is the last completed diff
+      State = StateDoneDiff;
+      for (std::vector<pkgAcqIndexMergeDiffs *>::const_iterator I = allPatches->begin();
+	    I != allPatches->end(); ++I)
+	 if ((*I)->State != StateDoneDiff)
+	 {
+	    if(Debug)
+	       std::clog << "Not the last done diff in the batch: " << Desc.URI << std::endl;
+	    return;
+	 }
+
+      // this is the last completed diff, so we are ready to apply now
+      State = StateApplyDiff;
+
+      if(Debug)
+	 std::clog << "Sending to rred method: " << FinalFile << std::endl;
+
+      Local = true;
+      Desc.URI = "rred:" + FinalFile;
+      QueueURI(Desc);
+      Mode = "rred";
+      return;
+   }
+   // success in download/apply all diffs, clean up
+   else if (State == StateApplyDiff)
+   {
+      // see if we really got the expected file
+      if(!ExpectedHash.empty() && !ExpectedHash.VerifyFile(DestFile))
+      {
+	 RenameOnError(HashSumMismatch);
+	 return;
+      }
+
+      // move the result 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);
+
+      // otherwise lists cleanup will eat the file
+      DestFile = FinalFile;
+
+      // ensure the ed's are gone regardless of list-cleanup
+      for (std::vector<pkgAcqIndexMergeDiffs *>::const_iterator I = allPatches->begin();
+	    I != allPatches->end(); ++I)
+      {
+	    std::string patch = FinalFile + ".ed." + (*I)->patch.file + ".gz";
+	    unlink(patch.c_str());
+      }
+
+      // all set and done
+      Complete = true;
+      if(Debug)
+	 std::clog << "allDone: " << DestFile << "\n" << std::endl;
+   }
+}
+									/*}}}*/
 // AcqIndex::AcqIndex - Constructor					/*{{{*/
 // ---------------------------------------------------------------------
 /* The package file is added to the queue and a second class is 
@@ -866,10 +1041,7 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,string Hash,
 
       if (!ExpectedHash.empty() && ExpectedHash.toStr() != Hash)
       {
-         Status = StatAuthError;
-         ErrorText = _("Hash Sum mismatch");
-         Rename(DestFile,DestFile + ".FAILED");
-	 ReportMirrorFailure("HashChecksumFailure");
+	 RenameOnError(HashSumMismatch);
          return;
       }
 
@@ -878,22 +1050,18 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,string Hash,
       if (Verify == true)
       {
 	 FileFd fd(DestFile, FileFd::ReadOnly);
-	 pkgTagSection sec;
-	 pkgTagFile tag(&fd);
-
-         // Only test for correctness if the file is not empty (empty is ok)
-         if (fd.Size() > 0) {
-            if (_error->PendingError() || !tag.Step(sec)) {
-               Status = StatError;
-               _error->DumpErrors();
-               Rename(DestFile,DestFile + ".FAILED");
-               return;
-            } else if (!sec.Exists("Package")) {
-               Status = StatError;
-               ErrorText = ("Encountered a section with no Package: header");
-               Rename(DestFile,DestFile + ".FAILED");
-               return;
-            }
+	 // Only test for correctness if the file is not empty (empty is ok)
+	 if (fd.FileSize() > 0)
+	 {
+	    pkgTagSection sec;
+	    pkgTagFile tag(&fd);
+
+	    // all our current indexes have a field 'Package' in each section
+	    if (_error->PendingError() == true || tag.Step(sec) == false || sec.Exists("Package") == false)
+	    {
+	       RenameOnError(InvalidFormat);
+	       return;
+	    }
          }
       }
        
@@ -984,6 +1152,8 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,string Hash,
    DestFile += ".decomp";
    Desc.URI = decompProg + ":" + FileName;
    QueueURI(Desc);
+
+   // FIXME: this points to a c++ string that goes out of scope
    Mode = decompProg.c_str();
 }
 									/*}}}*/
@@ -1070,7 +1240,7 @@ pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner,				/*{{{*/
    if (RealFileExists(Final) == true)
    {
       // File was already in place.  It needs to be re-downloaded/verified
-      // because Release might have changed, we do give it a differnt
+      // because Release might have changed, we do give it a different
       // name than DestFile because otherwise the http method will
       // send If-Range requests and there are too many broken servers
       // out there that do not understand them
@@ -1728,34 +1898,40 @@ pkgAcqArchive::pkgAcqArchive(pkgAcquire *Owner,pkgSourceList *Sources,
    }
 
    // check if we have one trusted source for the package. if so, switch
-   // to "TrustedOnly" mode
+   // to "TrustedOnly" mode - but only if not in AllowUnauthenticated mode
+   bool const allowUnauth = _config->FindB("APT::Get::AllowUnauthenticated", false);
+   bool const debugAuth = _config->FindB("Debug::pkgAcquire::Auth", false);
+   bool seenUntrusted = false;
    for (pkgCache::VerFileIterator i = Version.FileList(); i.end() == false; ++i)
    {
       pkgIndexFile *Index;
       if (Sources->FindIndex(i.File(),Index) == false)
          continue;
-      if (_config->FindB("Debug::pkgAcquire::Auth", false))
-      {
+
+      if (debugAuth == true)
          std::cerr << "Checking index: " << Index->Describe()
-                   << "(Trusted=" << Index->IsTrusted() << ")\n";
-      }
-      if (Index->IsTrusted()) {
+                   << "(Trusted=" << Index->IsTrusted() << ")" << std::endl;
+
+      if (Index->IsTrusted() == true)
+      {
          Trusted = true;
-	 break;
+	 if (allowUnauth == false)
+	    break;
       }
+      else
+         seenUntrusted = true;
    }
 
    // "allow-unauthenticated" restores apts old fetching behaviour
    // that means that e.g. unauthenticated file:// uris are higher
    // priority than authenticated http:// uris
-   if (_config->FindB("APT::Get::AllowUnauthenticated",false) == true)
+   if (allowUnauth == true && seenUntrusted == true)
       Trusted = false;
 
    // Select a source
    if (QueueNext() == false && _error->PendingError() == false)
-      _error->Error(_("I wasn't able to locate a file for the %s package. "
-		    "This might mean you need to manually fix this package."),
-		    Version.ParentPkg().Name());
+      _error->Error(_("Can't find a source to download version '%s' of '%s'"),
+		    Version.VerStr(), Version.ParentPkg().FullName(false).c_str());
 }
 									/*}}}*/
 // AcqArchive::QueueNext - Queue the next file source			/*{{{*/
@@ -1856,7 +2032,7 @@ bool pkgAcqArchive::QueueNext()
 	    return true;
 	 }
 	 
-	 /* Hmm, we have a file and its size does not match, this shouldnt
+	 /* Hmm, we have a file and its size does not match, this shouldn't
 	    happen.. */
 	 unlink(FinalFile.c_str());
       }
@@ -1909,18 +2085,14 @@ void pkgAcqArchive::Done(string Message,unsigned long long Size,string CalcHash,
    // Check the size
    if (Size != Version->Size)
    {
-      Status = StatError;
-      ErrorText = _("Size mismatch");
+      RenameOnError(SizeMismatch);
       return;
    }
    
    // Check the hash
    if(ExpectedHash.toStr() != CalcHash)
    {
-      Status = StatError;
-      ErrorText = _("Hash Sum mismatch");
-      if(FileExists(DestFile))
-	 Rename(DestFile,DestFile + ".FAILED");
+      RenameOnError(HashSumMismatch);
       return;
    }
 
@@ -2060,9 +2232,7 @@ void pkgAcqFile::Done(string Message,unsigned long long Size,string CalcHash,
    // Check the hash
    if(!ExpectedHash.empty() && ExpectedHash.toStr() != CalcHash)
    {
-      Status = StatError;
-      ErrorText = _("Hash Sum mismatch");
-      Rename(DestFile,DestFile + ".FAILED");
+      RenameOnError(HashSumMismatch);
       return;
    }
    

+ 116 - 3
apt-pkg/acquire-item.h

@@ -83,7 +83,7 @@ class pkgAcquire::Item : public WeakPointable
     *  overwritten.
     */
    void Rename(std::string From,std::string To);
-   
+
    public:
 
    /** \brief The current status of this item. */
@@ -281,6 +281,21 @@ class pkgAcquire::Item : public WeakPointable
     *  pkgAcquire::Remove.
     */
    virtual ~Item();
+
+   protected:
+
+   enum RenameOnErrorState {
+      HashSumMismatch,
+      SizeMismatch,
+      InvalidFormat
+   };
+
+   /** \brief Rename failed file and set error
+    *
+    * \param state respresenting the error we encountered
+    * \param errorMsg a message describing the error
+    */
+   bool RenameOnError(RenameOnErrorState const state);
 };
 									/*}}}*/
 /** \brief Information about an index patch (aka diff). */		/*{{{*/
@@ -414,7 +429,105 @@ class pkgAcqDiffIndex : public pkgAcquire::Item
 		   std::string ShortDesc, HashString ExpectedHash);
 };
 									/*}}}*/
-/** \brief An item that is responsible for fetching all the patches	{{{
+/** \brief An item that is responsible for fetching client-merge patches {{{
+ *  that need to be applied to a given package index file.
+ *
+ *  Instead of downloading and applying each patch one by one like its
+ *  sister #pkgAcqIndexDiffs this class will download all patches at once
+ *  and call rred with all the patches downloaded once. Rred will then
+ *  merge and apply them in one go, which should be a lot faster – but is
+ *  incompatible with server-based merges of patches like reprepro can do.
+ *
+ *  \sa pkgAcqDiffIndex, pkgAcqIndex
+ */
+class pkgAcqIndexMergeDiffs : public pkgAcquire::Item
+{
+   protected:
+
+   /** \brief If \b true, debugging output will be written to
+    *  std::clog.
+    */
+   bool Debug;
+
+   /** \brief description of the item that is currently being
+    *  downloaded.
+    */
+   pkgAcquire::ItemDesc Desc;
+
+   /** \brief URI of the package index file that is being
+    *  reconstructed.
+    */
+   std::string RealURI;
+
+   /** \brief HashSum of the package index file that is being
+    *  reconstructed.
+    */
+   HashString ExpectedHash;
+
+   /** \brief description of the file being downloaded. */
+   std::string Description;
+
+   /** \brief information about the current patch */
+   struct DiffInfo const patch;
+
+   /** \brief list of all download items for the patches */
+   std::vector<pkgAcqIndexMergeDiffs*> const * const allPatches;
+
+   /** The current status of this patch. */
+   enum DiffState
+   {
+      /** \brief The diff is currently being fetched. */
+      StateFetchDiff,
+
+      /** \brief The diff is currently being applied. */
+      StateApplyDiff,
+
+      /** \brief the work with this diff is done */
+      StateDoneDiff,
+
+      /** \brief something bad happened and fallback was triggered */
+      StateErrorDiff
+   } 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(std::string Message,pkgAcquire::MethodConfig *Cnf);
+
+   virtual void Done(std::string Message,unsigned long long Size,std::string Md5Hash,
+		     pkgAcquire::MethodConfig *Cnf);
+   virtual std::string DescURI() {return RealURI + "Index";};
+
+   /** \brief Create an index merge-diff item.
+    *
+    *  \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 ExpectedHash 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 patch contains infos about the patch this item is supposed
+    *  to download which were read from the index
+    *
+    *  \param allPatches contains all related items so that each item can
+    *  check if it was the last one to complete the download step
+    */
+   pkgAcqIndexMergeDiffs(pkgAcquire *Owner,std::string const &URI,std::string const &URIDesc,
+		    std::string const &ShortDesc, HashString const &ExpectedHash,
+		    DiffInfo const &patch, std::vector<pkgAcqIndexMergeDiffs*> const * const allPatches);
+};
+									/*}}}*/
+/** \brief An item that is responsible for fetching server-merge patches {{{
  *  that need to be applied to a given package index file.
  *
  *  After downloading and applying a single patch, this item will
@@ -982,7 +1095,7 @@ class pkgAcqArchive : public pkgAcquire::Item
     *
     *  \param Version The package version to download.
     *
-    *  \param StoreFilename A location in which the actual filename of
+    *  \param[out] 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.

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

@@ -109,7 +109,12 @@ bool pkgAcquire::Worker::Start()
    // Get the method path
    string Method = _config->FindDir("Dir::Bin::Methods") + Access;
    if (FileExists(Method) == false)
-      return _error->Error(_("The method driver %s could not be found."),Method.c_str());
+   {
+      _error->Error(_("The method driver %s could not be found."),Method.c_str());
+      if (Access == "https")
+	 _error->Notice(_("Is the package %s installed?"), "apt-transport-https");
+      return false;
+   }
 
    if (Debug == true)
       clog << "Starting method '" << Method << '\'' << endl;
@@ -563,7 +568,7 @@ bool pkgAcquire::Worker::InFdReady()
 									/*}}}*/
 // Worker::MethodFailure - Called when the method fails			/*{{{*/
 // ---------------------------------------------------------------------
-/* This is called when the method is belived to have failed, probably because
+/* This is called when the method is believed to have failed, probably because
    read returned -1. */
 bool pkgAcquire::Worker::MethodFailure()
 {

+ 3 - 3
apt-pkg/acquire.cc

@@ -5,9 +5,9 @@
 
    Acquire - File Acquiration
 
-   The core element for the schedual system is the concept of a named
+   The core element for the schedule system is the concept of a named
    queue. Each queue is unique and each queue has a name derived from the
-   URI. The degree of paralization can be controled by how the queue
+   URI. The degree of paralization can be controlled by how the queue
    name is derived from the URI.
    
    ##################################################################### */
@@ -175,7 +175,7 @@ void pkgAcquire::Add(Worker *Work)
 // ---------------------------------------------------------------------
 /* A worker has died. This can not be done while the select loop is running
    as it would require that RunFds could handling a changing list state and
-   it cant.. */
+   it can't.. */
 void pkgAcquire::Remove(Worker *Work)
 {
    if (Running == true)

+ 6 - 316
apt-pkg/algorithms.cc

@@ -336,217 +336,6 @@ bool pkgFixBroken(pkgDepCache &Cache)
    return Fix.Resolve(true);
 }
 									/*}}}*/
-// DistUpgrade - Distribution upgrade					/*{{{*/
-// ---------------------------------------------------------------------
-/* This autoinstalls every package and then force installs every 
-   pre-existing package. This creates the initial set of conditions which 
-   most likely contain problems because too many things were installed.
-   
-   The problem resolver is used to resolve the problems.
- */
-bool pkgDistUpgrade(pkgDepCache &Cache)
-{
-   std::string const solver = _config->Find("APT::Solver", "internal");
-   if (solver != "internal") {
-      OpTextProgress Prog(*_config);
-      return EDSP::ResolveExternal(solver.c_str(), Cache, false, true, false, &Prog);
-   }
-
-   pkgDepCache::ActionGroup group(Cache);
-
-   /* Upgrade all installed packages first without autoinst to help the resolver
-      in versioned or-groups to upgrade the old solver instead of installing
-      a new one (if the old solver is not the first one [anymore]) */
-   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
-      if (I->CurrentVer != 0)
-	 Cache.MarkInstall(I, false, 0, false);
-
-   /* Auto upgrade all installed packages, this provides the basis 
-      for the installation */
-   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
-      if (I->CurrentVer != 0)
-	 Cache.MarkInstall(I, true, 0, false);
-
-   /* Now, install each essential package which is not installed
-      (and not provided by another package in the same name group) */
-   std::string essential = _config->Find("pkgCacheGen::Essential", "all");
-   if (essential == "all")
-   {
-      for (pkgCache::GrpIterator G = Cache.GrpBegin(); G.end() == false; ++G)
-      {
-	 bool isEssential = false;
-	 bool instEssential = false;
-	 for (pkgCache::PkgIterator P = G.PackageList(); P.end() == false; P = G.NextPkg(P))
-	 {
-	    if ((P->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential)
-	       continue;
-	    isEssential = true;
-	    if (Cache[P].Install() == true)
-	    {
-	       instEssential = true;
-	       break;
-	    }
-	 }
-	 if (isEssential == false || instEssential == true)
-	    continue;
-	 pkgCache::PkgIterator P = G.FindPreferredPkg();
-	 Cache.MarkInstall(P, true, 0, false);
-      }
-   }
-   else if (essential != "none")
-      for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
-	 if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
-	    Cache.MarkInstall(I, true, 0, false);
-   
-   /* We do it again over all previously installed packages to force 
-      conflict resolution on them all. */
-   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
-      if (I->CurrentVer != 0)
-	 Cache.MarkInstall(I, false, 0, false);
-
-   pkgProblemResolver Fix(&Cache);
-
-   // Hold back held packages.
-   if (_config->FindB("APT::Ignore-Hold",false) == false)
-   {
-      for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
-      {
-	 if (I->SelectedState == pkgCache::State::Hold)
-	 {
-	    Fix.Protect(I);
-	    Cache.MarkKeep(I, false, false);
-	 }
-      }
-   }
-   
-   return Fix.Resolve();
-}
-									/*}}}*/
-// AllUpgrade - Upgrade as many packages as possible			/*{{{*/
-// ---------------------------------------------------------------------
-/* Right now the system must be consistent before this can be called.
-   It also will not change packages marked for install, it only tries
-   to install packages not marked for install */
-bool pkgAllUpgrade(pkgDepCache &Cache)
-{
-   std::string const solver = _config->Find("APT::Solver", "internal");
-   if (solver != "internal") {
-      OpTextProgress Prog(*_config);
-      return EDSP::ResolveExternal(solver.c_str(), Cache, true, false, false, &Prog);
-   }
-
-   pkgDepCache::ActionGroup group(Cache);
-
-   pkgProblemResolver Fix(&Cache);
-
-   if (Cache.BrokenCount() != 0)
-      return false;
-   
-   // Upgrade all installed packages
-   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
-   {
-      if (Cache[I].Install() == true)
-	 Fix.Protect(I);
-	  
-      if (_config->FindB("APT::Ignore-Hold",false) == false)
-	 if (I->SelectedState == pkgCache::State::Hold)
-	    continue;
-      
-      if (I->CurrentVer != 0 && Cache[I].InstallVer != 0)
-	 Cache.MarkInstall(I, false, 0, false);
-   }
-      
-   return Fix.ResolveByKeep();
-}
-									/*}}}*/
-// AllUpgradeNoDelete - Upgrade without removing packages		/*{{{*/
-// ---------------------------------------------------------------------
-/* Right now the system must be consistent before this can be called.
- * Upgrade as much as possible without deleting anything (useful for
- * stable systems)
- */
-bool pkgAllUpgradeNoDelete(pkgDepCache &Cache)
-{
-   pkgDepCache::ActionGroup group(Cache);
-
-   pkgProblemResolver Fix(&Cache);
-
-   if (Cache.BrokenCount() != 0)
-      return false;
-
-   // provide the initial set of stuff we want to upgrade by marking
-   // all upgradable packages for upgrade
-   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
-   {
-      if (I->CurrentVer != 0 && Cache[I].InstallVer != 0)
-      {
-         if (_config->FindB("APT::Ignore-Hold",false) == false)
-            if (I->SelectedState == pkgCache::State::Hold)
-               continue;
-
-	 Cache.MarkInstall(I, false, 0, false);
-      }
-   }
-
-   // then let auto-install loose
-   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
-      if (Cache[I].Install())
-	 Cache.MarkInstall(I, true, 0, false);
-
-   // ... but it may remove stuff, we we need to clean up afterwards again
-   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
-      if (Cache[I].Delete() == true)
-	 Cache.MarkKeep(I, false, false);
-
-   // resolve remaining issues via keep
-   return Fix.ResolveByKeep();
-}
-									/*}}}*/
-// MinimizeUpgrade - Minimizes the set of packages to be upgraded	/*{{{*/
-// ---------------------------------------------------------------------
-/* This simply goes over the entire set of packages and tries to keep 
-   each package marked for upgrade. If a conflict is generated then 
-   the package is restored. */
-bool pkgMinimizeUpgrade(pkgDepCache &Cache)
-{   
-   pkgDepCache::ActionGroup group(Cache);
-
-   if (Cache.BrokenCount() != 0)
-      return false;
-   
-   // We loop for 10 tries to get the minimal set size.
-   bool Change = false;
-   unsigned int Count = 0;
-   do
-   {
-      Change = false;
-      for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
-      {
-	 // Not interesting
-	 if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true)
-	    continue;
-
-	 // Keep it and see if that is OK
-	 Cache.MarkKeep(I, false, false);
-	 if (Cache.BrokenCount() != 0)
-	    Cache.MarkInstall(I, false, 0, false);
-	 else
-	 {
-	    // If keep didnt actually do anything then there was no change..
-	    if (Cache[I].Upgrade() == false)
-	       Change = true;
-	 }	 
-      }      
-      ++Count;
-   }
-   while (Change == true && Count < 10);
-
-   if (Cache.BrokenCount() != 0)
-      return _error->Error("Internal Error in pkgMinimizeUpgrade");
-   
-   return true;
-}
-									/*}}}*/
 // ProblemResolver::pkgProblemResolver - Constructor			/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -635,7 +424,7 @@ void pkgProblemResolver::MakeScores()
       /* This is arbitrary, it should be high enough to elevate an
          essantial package above most other packages but low enough
 	 to allow an obsolete essential packages to be removed by
-	 a conflicts on a powerfull normal package (ie libc6) */
+	 a conflicts on a powerful normal package (ie libc6) */
       if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential
 	  || (I->Flags & pkgCache::Flag::Important) == pkgCache::Flag::Important)
 	 Score += PrioEssentials;
@@ -652,7 +441,7 @@ void pkgProblemResolver::MakeScores()
 	 Score += PrioInstalledAndNotObsolete;
    }
 
-   // Now that we have the base scores we go and propogate dependencies
+   // Now that we have the base scores we go and propagate dependencies
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
    {
       if (Cache[I].InstallVer == 0)
@@ -696,7 +485,7 @@ void pkgProblemResolver::MakeScores()
       }      
    }
 
-   /* Now we propogate along provides. This makes the packages that 
+   /* Now we propagate along provides. This makes the packages that
       provide important packages extremely important */
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
    {
@@ -851,7 +640,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
    adjusting the package will inflict. 
       
    It goes from highest score to lowest and corrects all of the breaks by 
-   keeping or removing the dependant packages. If that fails then it removes
+   keeping or removing the dependent packages. If that fails then it removes
    the package itself and goes on. The routine should be able to intelligently
    go from any broken state to a fixed state. 
  
@@ -1041,7 +830,7 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix)
 
 	    /* Look across the version list. If there are no possible
 	       targets then we keep the package and bail. This is necessary
-	       if a package has a dep on another package that cant be found */
+	       if a package has a dep on another package that can't be found */
 	    SPtrArray<pkgCache::Version *> VList = Start.AllTargets();
 	    if (*VList == 0 && (Flags[I->ID] & Protected) != Protected &&
 		Start.IsNegative() == false &&
@@ -1394,7 +1183,7 @@ bool pkgProblemResolver::ResolveByKeepInternal()
          continue;
 
       /* Keep the package. If this works then great, otherwise we have
-       	 to be significantly more agressive and manipulate its dependencies */
+	 to be significantly more aggressive and manipulate its dependencies */
       if ((Flags[I->ID] & Protected) == 0)
       {
 	 if (Debug == true)
@@ -1548,102 +1337,3 @@ void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List)
    qsort(List,Count,sizeof(*List),PrioComp);
 }
 									/*}}}*/
-// ListUpdate - construct Fetcher and update the cache files		/*{{{*/
-// ---------------------------------------------------------------------
-/* This is a simple wrapper to update the cache. it will fetch stuff
- * from the network (or any other sources defined in sources.list)
- */
-bool ListUpdate(pkgAcquireStatus &Stat, 
-		pkgSourceList &List, 
-		int PulseInterval)
-{
-   pkgAcquire Fetcher;
-   if (Fetcher.Setup(&Stat, _config->FindDir("Dir::State::Lists")) == false)
-      return false;
-
-   // Populate it with the source selection
-   if (List.GetIndexes(&Fetcher) == false)
-	 return false;
-
-   return AcquireUpdate(Fetcher, PulseInterval, true);
-}
-									/*}}}*/
-// AcquireUpdate - take Fetcher and update the cache files		/*{{{*/
-// ---------------------------------------------------------------------
-/* This is a simple wrapper to update the cache with a provided acquire
- * If you only need control over Status and the used SourcesList use
- * ListUpdate method instead.
- */
-bool AcquireUpdate(pkgAcquire &Fetcher, int const PulseInterval,
-		   bool const RunUpdateScripts, bool const ListCleanup)
-{
-   // Run scripts
-   if (RunUpdateScripts == true)
-      RunScripts("APT::Update::Pre-Invoke");
-
-   pkgAcquire::RunResult res;
-   if(PulseInterval > 0)
-      res = Fetcher.Run(PulseInterval);
-   else
-      res = Fetcher.Run();
-
-   if (res == pkgAcquire::Failed)
-      return false;
-
-   bool Failed = false;
-   bool TransientNetworkFailure = false;
-   for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); 
-	I != Fetcher.ItemsEnd(); ++I)
-   {
-      if ((*I)->Status == pkgAcquire::Item::StatDone)
-	 continue;
-
-      (*I)->Finished();
-
-      ::URI uri((*I)->DescURI());
-      uri.User.clear();
-      uri.Password.clear();
-      string descUri = string(uri);
-      _error->Warning(_("Failed to fetch %s  %s\n"), descUri.c_str(),
-	      (*I)->ErrorText.c_str());
-
-      if ((*I)->Status == pkgAcquire::Item::StatTransientNetworkError) 
-      {
-	 TransientNetworkFailure = true;
-	 continue;
-      }
-
-      Failed = true;
-   }
-   
-   // Clean out any old list files
-   // Keep "APT::Get::List-Cleanup" name for compatibility, but
-   // this is really a global option for the APT library now
-   if (!TransientNetworkFailure && !Failed && ListCleanup == true &&
-       (_config->FindB("APT::Get::List-Cleanup",true) == true &&
-	_config->FindB("APT::List-Cleanup",true) == true))
-   {
-      if (Fetcher.Clean(_config->FindDir("Dir::State::lists")) == false ||
-	  Fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/") == false)
-	 // something went wrong with the clean
-	 return false;
-   }
-   
-   if (TransientNetworkFailure == true)
-      _error->Warning(_("Some index files failed to download. They have been ignored, or old ones used instead."));
-   else if (Failed == true)
-      return _error->Error(_("Some index files failed to download. They have been ignored, or old ones used instead."));
-
-
-   // Run the success scripts if all was fine
-   if (RunUpdateScripts == true)
-   {
-      if(!TransientNetworkFailure && !Failed)
-	 RunScripts("APT::Update::Post-Invoke-Success");
-
-      // Run the other scripts
-      RunScripts("APT::Update::Post-Invoke");
-   }
-   return true;
-}
-									/*}}}*/

+ 8 - 12
apt-pkg/algorithms.h

@@ -10,7 +10,7 @@
    see all of the effects of an upgrade run.
 
    pkgDistUpgrade computes an upgrade that causes as many packages as
-   possible to move to the newest verison.
+   possible to move to the newest version.
    
    pkgApplyStatus sets the target state based on the content of the status
    field in the status file. It is important to get proper crash recovery.
@@ -43,7 +43,12 @@
 using std::ostream;
 #endif
 
-class pkgAcquireStatus;
+#ifndef APT_9_CLEANER_HEADERS
+// include pkg{DistUpgrade,AllUpgrade,MiniizeUpgrade} here for compatibility
+#include <apt-pkg/upgrade.h>
+#include <apt-pkg/update.h>
+#endif
+
 
 class pkgSimulate : public pkgPackageManager				/*{{{*/
 {
@@ -85,6 +90,7 @@ private:
 									/*}}}*/
 class pkgProblemResolver						/*{{{*/
 {
+ private:
    /** \brief dpointer placeholder (for later in case we need it) */
    void *d;
 
@@ -140,20 +146,10 @@ class pkgProblemResolver						/*{{{*/
    ~pkgProblemResolver();
 };
 									/*}}}*/
-bool pkgDistUpgrade(pkgDepCache &Cache);
 bool pkgApplyStatus(pkgDepCache &Cache);
 bool pkgFixBroken(pkgDepCache &Cache);
 
-bool pkgAllUpgrade(pkgDepCache &Cache);
-
-bool pkgAllUpgradeNoDelete(pkgDepCache &Cache);
-
-bool pkgMinimizeUpgrade(pkgDepCache &Cache);
-
 void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List);
 
-bool ListUpdate(pkgAcquireStatus &progress, pkgSourceList &List, int PulseInterval=0);
-bool AcquireUpdate(pkgAcquire &Fetcher, int const PulseInterval = 0,
-		   bool const RunUpdateScripts = true, bool const ListCleanup = true);
 
 #endif

+ 8 - 8
apt-pkg/aptconfiguration.cc

@@ -27,9 +27,9 @@
 #include <vector>
 									/*}}}*/
 namespace APT {
-// getCompressionTypes - Return Vector of usbale compressiontypes	/*{{{*/
+// getCompressionTypes - Return Vector of usable compressiontypes	/*{{{*/
 // ---------------------------------------------------------------------
-/* return a vector of compression types in the prefered order. */
+/* return a vector of compression types in the preferred order. */
 std::vector<std::string>
 const Configuration::getCompressionTypes(bool const &Cached) {
 	static std::vector<std::string> types;
@@ -109,7 +109,7 @@ const Configuration::getCompressionTypes(bool const &Cached) {
 									/*}}}*/
 // GetLanguages - Return Vector of Language Codes			/*{{{*/
 // ---------------------------------------------------------------------
-/* return a vector of language codes in the prefered order.
+/* return a vector of language codes in the preferred order.
    the special word "environment" will be replaced with the long and the short
    code of the local settings and it will be insured that this will not add
    duplicates. So in an german local the setting "environment, de_DE, en, de"
@@ -141,7 +141,7 @@ std::vector<std::string> const Configuration::getLanguages(bool const &All,
 	// so they will be all included in the Cache.
 	std::vector<string> builtin;
 	DIR *D = opendir(_config->FindDir("Dir::State::lists").c_str());
-	if (D != 0) {
+	if (D != NULL) {
 		builtin.push_back("none");
 		for (struct dirent *Ent = readdir(D); Ent != 0; Ent = readdir(D)) {
 			string const name = SubstVar(Ent->d_name, "%5f", "_");
@@ -166,8 +166,8 @@ std::vector<std::string> const Configuration::getLanguages(bool const &All,
 				continue;
 			builtin.push_back(c);
 		}
+		closedir(D);
 	}
-	closedir(D);
 
 	// FIXME: Remove support for the old APT::Acquire::Translation
 	// it was undocumented and so it should be not very widthly used
@@ -330,7 +330,7 @@ bool const Configuration::checkLanguage(std::string Lang, bool const All) {
 	return (std::find(langs.begin(), langs.end(), Lang) != langs.end());
 }
 									/*}}}*/
-// getArchitectures - Return Vector of prefered Architectures		/*{{{*/
+// getArchitectures - Return Vector of preferred Architectures		/*{{{*/
 std::vector<std::string> const Configuration::getArchitectures(bool const &Cached) {
 	using std::string;
 
@@ -392,7 +392,7 @@ std::vector<std::string> const Configuration::getArchitectures(bool const &Cache
 			dup2(nullfd, STDIN_FILENO);
 			dup2(external[1], STDOUT_FILENO);
 			dup2(nullfd, STDERR_FILENO);
-			if (chrootDir != "/" && chroot(chrootDir.c_str()) != 0)
+			if (chrootDir != "/" && chroot(chrootDir.c_str()) != 0 && chdir("/") != 0)
 				_error->WarningE("getArchitecture", "Couldn't chroot into %s for dpkg --print-foreign-architectures", chrootDir.c_str());
 			execvp(Args[0], (char**) &Args[0]);
 			_error->WarningE("getArchitecture", "Can't detect foreign architectures supported by dpkg!");
@@ -453,7 +453,7 @@ void Configuration::setDefaultConfigurationForCompressors() {
 	_config->CndSet("Dir::Bin::bzip2", "/bin/bzip2");
 	_config->CndSet("Dir::Bin::xz", "/usr/bin/xz");
 	if (FileExists(_config->FindFile("Dir::Bin::xz")) == true) {
-		_config->Clear("Dir::Bin::lzma");
+		_config->Set("Dir::Bin::lzma", _config->FindFile("Dir::Bin::xz"));
 		_config->Set("APT::Compressor::lzma::Binary", "xz");
 		if (_config->Exists("APT::Compressor::lzma::CompressArg") == false) {
 			_config->Set("APT::Compressor::lzma::CompressArg::", "--format=lzma");

+ 5 - 5
apt-pkg/aptconfiguration.h

@@ -37,14 +37,14 @@ public:									/*{{{*/
 	 *  \param Cached saves the result so we need to calculated it only once
 	 *                this parameter should ony be used for testing purposes.
 	 *
-	 *  \return a vector of the compression types in the prefered usage order
+	 *  \return a vector of the compression types in the preferred usage order
 	 */
 	std::vector<std::string> static const getCompressionTypes(bool const &Cached = true);
 
 	/** \brief Returns a vector of Language Codes
 	 *
 	 *  Languages can be defined with their two or five chars long code.
-	 *  This methods handles the various ways to set the prefered codes,
+	 *  This methods handles the various ways to set the preferred codes,
 	 *  honors the environment and ensures that the codes are not listed twice.
 	 *
 	 *  The special word "environment" will be replaced with the long and the short
@@ -52,7 +52,7 @@ public:									/*{{{*/
 	 *  duplicates. So in an german local the setting "environment, de_DE, en, de"
 	 *  will result in "de_DE, de, en".
 	 *
-	 *  Another special word is "none" which separates the prefered from all codes
+	 *  Another special word is "none" which separates the preferred from all codes
 	 *  in this setting. So setting and method can be used to get codes the user want
 	 *  to see or to get all language codes APT (should) have Translations available.
 	 *
@@ -62,7 +62,7 @@ public:									/*{{{*/
 	 *  \param Locale don't get the locale from the system but use this one instead
 	 *                this parameter should ony be used for testing purposes.
 	 *
-	 *  \return a vector of (all) Language Codes in the prefered usage order
+	 *  \return a vector of (all) Language Codes in the preferred usage order
 	 */
 	std::vector<std::string> static const getLanguages(bool const &All = false,
 			bool const &Cached = true, char const ** const Locale = 0);
@@ -80,7 +80,7 @@ public:									/*{{{*/
 	 *  \param Cached saves the result so we need to calculated it only once
 	 *                this parameter should ony be used for testing purposes.
 	 *
-	 *  \return a vector of Architectures in prefered order
+	 *  \return a vector of Architectures in preferred order
 	 */
 	std::vector<std::string> static const getArchitectures(bool const &Cached = true);
 

+ 3 - 3
apt-pkg/cacheiterators.h

@@ -46,7 +46,7 @@ template<typename Str, typename Itr> class pkgCache::Iterator :
 	 *  The implementation of this method should be pretty short
 	 *  as it will only return the Pointer into the mmap stored
 	 *  in the owner but the name of this pointer is different for
-	 *  each stucture and we want to abstract here at least for the
+	 *  each structure and we want to abstract here at least for the
 	 *  basic methods from the actual structure.
 	 *  \return Pointer to the first structure of this type
 	 */
@@ -198,7 +198,7 @@ class pkgCache::VerIterator : public Iterator<Version, VerIterator> {
 	/** \brief compares two version and returns if they are similar
 
 	    This method should be used to identify if two pseudo versions are
-	    refering to the same "real" version */
+	    referring to the same "real" version */
 	inline bool SimilarVer(const VerIterator &B) const {
 		return (B.end() == false && S->Hash == B->Hash && strcmp(VerStr(), B.VerStr()) == 0);
 	};
@@ -419,7 +419,7 @@ class pkgCache::DescFileIterator : public Iterator<DescFile, DescFileIterator> {
 	inline DescFileIterator(pkgCache &Owner,DescFile *Trg) : Iterator<DescFile, DescFileIterator>(Owner, Trg) {};
 };
 									/*}}}*/
-// Inlined Begin functions cant be in the class because of order problems /*{{{*/
+// Inlined Begin functions can't be in the class because of order problems /*{{{*/
 inline pkgCache::PkgIterator pkgCache::GrpIterator::PackageList() const
        {return PkgIterator(*Owner,Owner->PkgP + S->FirstPackage);};
 inline pkgCache::VerIterator pkgCache::PkgIterator::VersionList() const

+ 28 - 3
apt-pkg/cacheset.cc

@@ -73,6 +73,8 @@ bool PackageContainerInterface::FromTask(PackageContainerInterface * const pci,
 		const char *start, *end;
 		parser.GetRec(start,end);
 		unsigned int const length = end - start;
+		if (unlikely(length == 0))
+		   continue;
 		char buf[length];
 		strncpy(buf, start, length);
 		buf[length-1] = '\0';
@@ -202,12 +204,20 @@ PackageContainerInterface::FromFnmatch(PackageContainerInterface * const pci,
 		}
 
 		pci->insert(Pkg);
+#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
+		helper.showFnmatchSelection(Pkg, pattern);
+#else
 		helper.showRegExSelection(Pkg, pattern);
+#endif
 		found = true;
 	}
 
 	if (found == false) {
-		helper.canNotFindRegEx(pci, Cache, pattern);
+#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
+		helper.canNotFindFnmatch(pci, Cache, pattern);
+#else
+                helper.canNotFindRegEx(pci, Cache, pattern);
+#endif
 		pci->setConstructor(UNKNOWN);
 		return false;
 	}
@@ -302,7 +312,9 @@ bool PackageContainerInterface::FromString(PackageContainerInterface * const pci
 
 	if (FromGroup(pci, Cache, str, helper) == false &&
 		 FromTask(pci, Cache, str, helper) == false &&
-		 FromFnmatch(pci, Cache, str, helper) == false &&
+#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
+		 FromFnmatch(pci, Cache, str, helper) == false)
+#endif
 		 FromRegEx(pci, Cache, str, helper) == false)
 	{
 		helper.canNotFindPackage(pci, Cache, str);
@@ -586,7 +598,13 @@ void CacheSetHelper::canNotFindRegEx(PackageContainerInterface * const pci, pkgC
 	if (ShowError == true)
 		_error->Insert(ErrorType, _("Couldn't find any package by regex '%s'"), pattern.c_str());
 }
-									/*}}}*/
+#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
+// canNotFindFnmatch - handle the case no package is found by a fnmatch	/*{{{*/
+void CacheSetHelper::canNotFindFnmatch(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern) {
+	if (ShowError == true)
+		_error->Insert(ErrorType, _("Couldn't find any package by glob '%s'"), pattern.c_str());
+}
+#endif									/*}}}*/
 // canNotFindPackage - handle the case no package is found from a string/*{{{*/
 void CacheSetHelper::canNotFindPackage(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string const &str) {
 }
@@ -646,6 +664,13 @@ void CacheSetHelper::showRegExSelection(pkgCache::PkgIterator const &pkg,
 					std::string const &pattern) {
 }
 									/*}}}*/
+#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
+// showFnmatchSelection							/*{{{*/
+void CacheSetHelper::showFnmatchSelection(pkgCache::PkgIterator const &pkg,
+                                          std::string const &pattern) {
+}
+									/*}}}*/
+#endif
 // showSelectedVersion							/*{{{*/
 void CacheSetHelper::showSelectedVersion(pkgCache::PkgIterator const &Pkg,
 					 pkgCache::VerIterator const Ver,

+ 6 - 0
apt-pkg/cacheset.h

@@ -48,11 +48,17 @@ public:									/*{{{*/
 
 	virtual void showTaskSelection(pkgCache::PkgIterator const &pkg, std::string const &pattern);
 	virtual void showRegExSelection(pkgCache::PkgIterator const &pkg, std::string const &pattern);
+#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
+	virtual void showFnmatchSelection(pkgCache::PkgIterator const &pkg, std::string const &pattern);
+#endif
 	virtual void showSelectedVersion(pkgCache::PkgIterator const &Pkg, pkgCache::VerIterator const Ver,
 				 std::string const &ver, bool const verIsRel);
 
 	virtual void canNotFindTask(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern);
 	virtual void canNotFindRegEx(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern);
+#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
+	virtual void canNotFindFnmatch(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern);
+#endif
 	virtual void canNotFindPackage(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string const &str);
 
 	virtual void canNotFindAllVer(VersionContainerInterface * const vci, pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg);

+ 64 - 91
apt-pkg/cdrom.cc

@@ -561,45 +561,65 @@ bool pkgCdrom::WriteSourceList(string Name,vector<string> &List,bool Source)
    return true;
 }
 									/*}}}*/
-bool pkgCdrom::Ident(string &ident, pkgCdromStatus *log)		/*{{{*/
+bool pkgCdrom::MountAndIdentCDROM(Configuration &Database, std::string &CDROM, std::string &ident, pkgCdromStatus * const log)/*{{{*/
 {
-   stringstream msg;
-
    // Startup
-   string CDROM = _config->FindDir("Acquire::cdrom::mount");
+   CDROM = _config->FindDir("Acquire::cdrom::mount");
    if (CDROM[0] == '.')
       CDROM= SafeGetCWD() + '/' + CDROM;
 
    if (log != NULL)
    {
-      msg.str("");
-      ioprintf(msg, _("Using CD-ROM mount point %s\nMounting CD-ROM\n"),
-		      CDROM.c_str());
-      log->Update(msg.str());
+      string msg;
+      log->SetTotal(STEP_LAST);
+      strprintf(msg, _("Using CD-ROM mount point %s\n"), CDROM.c_str());
+      log->Update(msg, STEP_PREPARE);
+   }
+
+   // Unmount the CD and get the user to put in the one they want
+   if (_config->FindB("APT::CDROM::NoMount", false) == false)
+   {
+      if(log != NULL)
+	 log->Update(_("Unmounting CD-ROM\n"), STEP_UNMOUNT);
+      UnmountCdrom(CDROM);
+
+      if(log != NULL)
+      {
+	 log->Update(_("Waiting for disc...\n"), STEP_WAIT);
+	 if(!log->ChangeCdrom()) {
+	    // user aborted
+	    return false;
+	 }
+      }
+
+      // Mount the new CDROM
+      if(log != NULL)
+	 log->Update(_("Mounting CD-ROM...\n"), STEP_MOUNT);
+
+      if (MountCdrom(CDROM) == false)
+	 return _error->Error("Failed to mount the cdrom.");
    }
-   if (MountCdrom(CDROM) == false)
-      return _error->Error("Failed to mount the cdrom.");
 
    // Hash the CD to get an ID
    if (log != NULL)
-      log->Update(_("Identifying.. "));
-   
+      log->Update(_("Identifying.. "), STEP_IDENT);
 
    if (IdentCdrom(CDROM,ident) == false)
    {
       ident = "";
+      if (log != NULL)
+	 log->Update("\n");
       return false;
    }
 
    if (log != NULL)
    {
-      msg.str("");
-      ioprintf(msg, "[%s]\n",ident.c_str());
-      log->Update(msg.str());
+      string msg;
+      strprintf(msg, "[%s]\n", ident.c_str());
+      log->Update(msg);
    }
 
    // Read the database
-   Configuration Database;
    string DFile = _config->FindFile("Dir::State::cdroms");
    if (FileExists(DFile) == true)
    {
@@ -607,12 +627,22 @@ bool pkgCdrom::Ident(string &ident, pkgCdromStatus *log)		/*{{{*/
 	 return _error->Error("Unable to read the cdrom database %s",
 			      DFile.c_str());
    }
+   return true;
+}
+									/*}}}*/
+bool pkgCdrom::Ident(string &ident, pkgCdromStatus *log)		/*{{{*/
+{
+   Configuration Database;
+   std::string CDROM;
+   if (MountAndIdentCDROM(Database, CDROM, ident, log) == false)
+      return false;
+
    if (log != NULL)
    {
-      msg.str("");
-      ioprintf(msg, _("Stored label: %s\n"),
-      Database.Find("CD::"+ident).c_str());
-      log->Update(msg.str());
+      string msg;
+      strprintf(msg, _("Stored label: %s\n"),
+	    Database.Find("CD::"+ident).c_str());
+      log->Update(msg);
    }
 
    // Unmount and finish
@@ -628,70 +658,13 @@ bool pkgCdrom::Ident(string &ident, pkgCdromStatus *log)		/*{{{*/
 									/*}}}*/
 bool pkgCdrom::Add(pkgCdromStatus *log)					/*{{{*/
 {
-   stringstream msg;
-
-   // Startup
-   string CDROM = _config->FindDir("Acquire::cdrom::mount");
-   if (CDROM[0] == '.')
-      CDROM= SafeGetCWD() + '/' + CDROM;
-   
-   if(log != NULL)
-   {
-      log->SetTotal(STEP_LAST);
-      msg.str("");
-      ioprintf(msg, _("Using CD-ROM mount point %s\n"), CDROM.c_str());
-      log->Update(msg.str(), STEP_PREPARE);
-   }
-
-   // Read the database
    Configuration Database;
-   string DFile = _config->FindFile("Dir::State::cdroms");
-   if (FileExists(DFile) == true)
-   {
-      if (ReadConfigFile(Database,DFile) == false) 
-	 return _error->Error("Unable to read the cdrom database %s",
-			      DFile.c_str());
-   }
-   
-   // Unmount the CD and get the user to put in the one they want
-   if (_config->FindB("APT::CDROM::NoMount",false) == false)
-   {
-      if(log != NULL)
-	 log->Update(_("Unmounting CD-ROM\n"), STEP_UNMOUNT);
-      UnmountCdrom(CDROM);
-
-      if(log != NULL)
-      {
-	 log->Update(_("Waiting for disc...\n"), STEP_WAIT);
-	 if(!log->ChangeCdrom()) {
-	    // user aborted
-	    return false; 
-	 }
-      }
-
-      // Mount the new CDROM
-      if(log != NULL)
-	 log->Update(_("Mounting CD-ROM...\n"), STEP_MOUNT);
-
-      if (MountCdrom(CDROM) == false)
-	 return _error->Error("Failed to mount the cdrom.");
-   }
-   
-   // Hash the CD to get an ID
-   if(log != NULL)
-      log->Update(_("Identifying.. "), STEP_IDENT);
-   string ID;
-   if (IdentCdrom(CDROM,ID) == false)
-   {
-      if (log != NULL)
-	 log->Update("\n");
+   std::string ID, CDROM;
+   if (MountAndIdentCDROM(Database, CDROM, ID, log) == false)
       return false;
-   }
+
    if(log != NULL)
-   {
-      log->Update("["+ID+"]\n");
       log->Update(_("Scanning disc for index files..\n"),STEP_SCAN);
-   }
 
    // Get the CD structure
    vector<string> List;
@@ -740,12 +713,12 @@ bool pkgCdrom::Add(pkgCdromStatus *log)					/*{{{*/
    if (_config->FindB("APT::CDROM::DropTranslation", true) == true)
       DropTranslation(TransList);
    if(log != NULL) {
-      msg.str("");
-      ioprintf(msg, _("Found %zu package indexes, %zu source indexes, "
+      string msg;
+      strprintf(msg, _("Found %zu package indexes, %zu source indexes, "
 		      "%zu translation indexes and %zu signatures\n"), 
 	       List.size(), SourceList.size(), TransList.size(),
 	       SigList.size());
-      log->Update(msg.str(), STEP_SCAN);
+      log->Update(msg, STEP_SCAN);
    }
 
    if (List.empty() == true && SourceList.empty() == true) 
@@ -778,9 +751,9 @@ bool pkgCdrom::Add(pkgCdromStatus *log)					/*{{{*/
 	    
 	    if(log != NULL)
 	    {
-	       msg.str("");
-	       ioprintf(msg, _("Found label '%s'\n"), Name.c_str());
-	       log->Update(msg.str());
+	       string msg;
+	       strprintf(msg, _("Found label '%s'\n"), Name.c_str());
+	       log->Update(msg);
 	    }
 	    Database.Set("CD::" + ID + "::Label",Name);
 	 }	 
@@ -824,9 +797,9 @@ bool pkgCdrom::Add(pkgCdromStatus *log)					/*{{{*/
    Database.Set("CD::" + ID,Name);
    if(log != NULL)
    {
-      msg.str("");
-      ioprintf(msg, _("This disc is called: \n'%s'\n"), Name.c_str());
-      log->Update(msg.str());
+      string msg;
+      strprintf(msg, _("This disc is called: \n'%s'\n"), Name.c_str());
+      log->Update(msg);
       log->Update(_("Copying package lists..."), STEP_COPY);
    }
 
@@ -884,7 +857,7 @@ bool pkgCdrom::Add(pkgCdromStatus *log)					/*{{{*/
 
       if(log != NULL)
       {
-	 msg.str("");
+	 stringstream msg;
 	 msg << "deb cdrom:[" << Name << "]/" << string(*I,0,Space) << 
 	    " " << string(*I,Space+1) << endl;
 	 log->Update(msg.str());
@@ -902,7 +875,7 @@ bool pkgCdrom::Add(pkgCdromStatus *log)					/*{{{*/
       }
 
       if(log != NULL) {
-	 msg.str("");
+	 stringstream msg;
 	 msg << "deb-src cdrom:[" << Name << "]/" << string(*I,0,Space) << 
 	    " " << string(*I,Space+1) << endl;
 	 log->Update(msg.str());

+ 5 - 1
apt-pkg/cdrom.h

@@ -69,6 +69,10 @@ class pkgCdrom								/*{{{*/
  public:
    bool Ident(std::string &ident, pkgCdromStatus *log);
    bool Add(pkgCdromStatus *log);
+
+ private:
+   bool MountAndIdentCDROM(Configuration &Database, std::string &CDROM,
+	 std::string &ident, pkgCdromStatus * const log);
 };
 									/*}}}*/
 
@@ -84,7 +88,7 @@ struct CdromDevice							/*{{{*/
 class pkgUdevCdromDevices						/*{{{*/
 {
  protected:
-   // libudev dlopen stucture
+   // libudev dlopen structure
    void *libudev_handle;
    struct udev* (*udev_new)(void);
    int (*udev_enumerate_add_match_property)(struct udev_enumerate *udev_enumerate, const char *property, const char *value);

+ 1 - 1
apt-pkg/clean.cc

@@ -105,7 +105,7 @@ bool pkgArchiveCleaner::Go(std::string Dir,pkgCache &Cache)
 	       break;
 	    }
 	    
-	    // See if this verison matches the file
+	    // See if this version matches the file
 	    if (IsFetchable == true && Ver == V.VerStr())
 	       break;
 	 }

+ 2 - 2
apt-pkg/contrib/cdromutl.cc

@@ -47,8 +47,8 @@ bool IsMounted(string &Path)
    if (Path[Path.length() - 1] != '/')
       Path += '/';
    
-   /* First we check if the path is actualy mounted, we do this by
-      stating the path and the previous directory (carefull of links!)
+   /* First we check if the path is actually mounted, we do this by
+      stating the path and the previous directory (careful of links!)
       and comparing their device fields. */
    struct stat Buf,Buf2;
    if (stat(Path.c_str(),&Buf) != 0 || 

+ 2 - 1
apt-pkg/contrib/cmndline.cc

@@ -293,7 +293,7 @@ bool CommandLine::HandleOpt(int &I,int argc,const char *argv[],
    // Look for an argument.
    while (1)
    {
-      // Look at preceeding text
+      // Look at preceding text
       char Buffer[300];
       if (Argument == 0)
       {
@@ -397,6 +397,7 @@ bool CommandLine::DispatchArg(Dispatch *Map,bool NoMatch)
 void CommandLine::SaveInConfig(unsigned int const &argc, char const * const * const argv)
 {
    char cmdline[100 + argc * 50];
+   memset(cmdline, 0, sizeof(cmdline));
    unsigned int length = 0;
    bool lastWasOption = false;
    bool closeQuote = false;

+ 1 - 1
apt-pkg/contrib/crc-16.cc

@@ -10,7 +10,7 @@
    Al Longyear <longyear@netcom.com>
    
    Modified by Jason Gunthorpe <jgg@debian.org> to fit the local coding
-   style, this code is belived to be in the Public Domain.
+   style, this code is believed to be in the Public Domain.
    
    ##################################################################### */
 									/*}}}*/

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

@@ -229,7 +229,7 @@ public:									/*{{{*/
 	/** \brief is the list empty?
 	 *
 	 *  The default checks if the list is empty or contains only notices,
-	 *  if you want to check if also no notices happend set the parameter
+	 *  if you want to check if also no notices happened set the parameter
 	 *  flag to \b false.
 	 *
 	 *  \param WithoutNotice does notices count, default is \b true, so no

+ 118 - 74
apt-pkg/contrib/fileutl.cc

@@ -222,7 +222,7 @@ int GetLock(string File,bool Errors)
    int FD = open(File.c_str(),O_RDWR | O_CREAT | O_NOFOLLOW,0640);
    if (FD < 0)
    {
-      // Read only .. cant have locking problems there.
+      // Read only .. can't have locking problems there.
       if (errno == EROFS)
       {
 	 _error->Warning(_("Not using locking for read only lock file %s"),File.c_str());
@@ -238,7 +238,7 @@ int GetLock(string File,bool Errors)
    }
    SetCloseExec(FD,true);
       
-   // Aquire a write lock
+   // Acquire a write lock
    struct flock fl;
    fl.l_type = F_WRLCK;
    fl.l_whence = SEEK_SET;
@@ -319,7 +319,7 @@ bool CreateDirectory(string const &Parent, string const &Path)
       return false;
 
    // we are not going to create directories "into the blue"
-   if (Path.find(Parent, 0) != 0)
+   if (Path.compare(0, Parent.length(), Parent) != 0)
       return false;
 
    vector<string> const dirs = VectorizeString(Path.substr(Parent.size()), '/');
@@ -465,7 +465,7 @@ std::vector<string> GetListOfFilesInDir(string const &Dir, std::vector<string> c
       const char *C = Ent->d_name;
       for (; *C != 0; ++C)
 	 if (isalpha(*C) == 0 && isdigit(*C) == 0
-	     && *C != '_' && *C != '-') {
+	     && *C != '_' && *C != '-' && *C != ':') {
 	    // no required extension -> dot is a bad character
 	    if (*C == '.' && Ext.empty() == false)
 	       continue;
@@ -656,9 +656,9 @@ string flNoLink(string File)
    while (1)
    {
       // Read the link
-      int Res;
+      ssize_t Res;
       if ((Res = readlink(NFile.c_str(),Buffer,sizeof(Buffer))) <= 0 || 
-	  (unsigned)Res >= sizeof(Buffer))
+	  (size_t)Res >= sizeof(Buffer))
 	  return File;
       
       // Append or replace the previous path
@@ -760,12 +760,42 @@ bool WaitFd(int Fd,bool write,unsigned long timeout)
    return true;
 }
 									/*}}}*/
+// MergeKeepFdsFromConfiguration - Merge APT::Keep-Fds configuration	/*{{{*/
+// ---------------------------------------------------------------------
+/* This is used to merge the APT::Keep-Fds with the provided KeepFDs
+ * set.
+ */
+void MergeKeepFdsFromConfiguration(std::set<int> &KeepFDs)
+{
+      Configuration::Item const *Opts = _config->Tree("APT::Keep-Fds");
+      if (Opts != 0 && Opts->Child != 0)
+      {
+	 Opts = Opts->Child;
+	 for (; Opts != 0; Opts = Opts->Next)
+	 {
+	    if (Opts->Value.empty() == true)
+	       continue;
+	    int fd = atoi(Opts->Value.c_str());
+	    KeepFDs.insert(fd);
+	 }
+      }
+}
+									/*}}}*/
 // ExecFork - Magical fork that sanitizes the context before execing	/*{{{*/
 // ---------------------------------------------------------------------
 /* This is used if you want to cleanse the environment for the forked 
    child, it fixes up the important signals and nukes all of the fds,
    otherwise acts like normal fork. */
 pid_t ExecFork()
+{
+      set<int> KeepFDs;
+      // we need to merge the Keep-Fds as external tools like 
+      // debconf-apt-progress use it
+      MergeKeepFdsFromConfiguration(KeepFDs);
+      return ExecFork(KeepFDs);
+}
+
+pid_t ExecFork(std::set<int> KeepFDs)
 {
    // Fork off the process
    pid_t Process = fork();
@@ -786,22 +816,8 @@ pid_t ExecFork()
       signal(SIGCONT,SIG_DFL);
       signal(SIGTSTP,SIG_DFL);
 
-      set<int> KeepFDs;
-      Configuration::Item const *Opts = _config->Tree("APT::Keep-Fds");
-      if (Opts != 0 && Opts->Child != 0)
-      {
-	 Opts = Opts->Child;
-	 for (; Opts != 0; Opts = Opts->Next)
-	 {
-	    if (Opts->Value.empty() == true)
-	       continue;
-	    int fd = atoi(Opts->Value.c_str());
-	    KeepFDs.insert(fd);
-	 }
-      }
-
       // Close all of our FDs - just in case
-      for (int K = 3; K != 40; K++)
+      for (int K = 3; K != sysconf(_SC_OPEN_MAX); K++)
       {
 	 if(KeepFDs.find(K) == KeepFDs.end())
 	    fcntl(K,F_SETFD,FD_CLOEXEC);
@@ -966,9 +982,6 @@ bool FileFd::Open(string FileName,unsigned int const Mode,APT::Configuration::Co
    if ((Mode & Atomic) == Atomic)
    {
       Flags |= Replace;
-      char *name = strdup((FileName + ".XXXXXX").c_str());
-      TemporaryFileName = string(mktemp(name));
-      free(name);
    }
    else if ((Mode & (Exclusive | Create)) == (Exclusive | Create))
    {
@@ -991,11 +1004,24 @@ bool FileFd::Open(string FileName,unsigned int const Mode,APT::Configuration::Co
    if_FLAGGED_SET(Create, O_CREAT);
    if_FLAGGED_SET(Empty, O_TRUNC);
    if_FLAGGED_SET(Exclusive, O_EXCL);
-   else if_FLAGGED_SET(Atomic, O_EXCL);
    #undef if_FLAGGED_SET
 
-   if (TemporaryFileName.empty() == false)
-      iFd = open(TemporaryFileName.c_str(), fileflags, Perms);
+   if ((Mode & Atomic) == Atomic)
+   {
+      char *name = strdup((FileName + ".XXXXXX").c_str());
+
+      if((iFd = mkstemp(name)) == -1)
+      {
+          free(name);
+          return FileFdErrno("mkstemp", "Could not create temporary file for %s", FileName.c_str());
+      }
+
+      TemporaryFileName = string(name);
+      free(name);
+
+      if(Perms != 600 && fchmod(iFd, Perms) == -1)
+          return FileFdErrno("fchmod", "Could not change permissions for temporary file %s", TemporaryFileName.c_str());
+   }
    else
       iFd = open(FileName.c_str(), fileflags, Perms);
 
@@ -1250,11 +1276,11 @@ FileFd::~FileFd()
 									/*}}}*/
 // FileFd::Read - Read a bit of the file				/*{{{*/
 // ---------------------------------------------------------------------
-/* We are carefull to handle interruption by a signal while reading 
+/* We are careful to handle interruption by a signal while reading
    gracefully. */
 bool FileFd::Read(void *To,unsigned long long Size,unsigned long long *Actual)
 {
-   int Res;
+   ssize_t Res;
    errno = 0;
    if (Actual != 0)
       *Actual = 0;
@@ -1354,7 +1380,7 @@ char* FileFd::ReadLine(char *To, unsigned long long const Size)
 /* */
 bool FileFd::Write(const void *From,unsigned long long Size)
 {
-   int Res;
+   ssize_t Res;
    errno = 0;
    do
    {
@@ -1408,7 +1434,7 @@ bool FileFd::Write(const void *From,unsigned long long Size)
 }
 bool FileFd::Write(int Fd, const void *From, unsigned long long Size)
 {
-   int Res;
+   ssize_t Res;
    errno = 0;
    do
    {
@@ -1481,14 +1507,14 @@ bool FileFd::Seek(unsigned long long To)
       d->seekpos = To;
       return true;
    }
-   int res;
+   off_t res;
 #ifdef HAVE_ZLIB
    if (d != NULL && d->gz)
       res = gzseek(d->gz,To,SEEK_SET);
    else
 #endif
       res = lseek(iFd,To,SEEK_SET);
-   if (res != (signed)To)
+   if (res != (off_t)To)
       return FileFdError("Unable to seek to %llu", To);
 
    if (d != NULL)
@@ -1519,7 +1545,7 @@ bool FileFd::Skip(unsigned long long Over)
       return true;
    }
 
-   int res;
+   off_t res;
 #ifdef HAVE_ZLIB
    if (d != NULL && d->gz != NULL)
       res = gzseek(d->gz,Over,SEEK_CUR);
@@ -1539,6 +1565,9 @@ bool FileFd::Skip(unsigned long long Over)
 /* */
 bool FileFd::Truncate(unsigned long long To)
 {
+   // truncating /dev/null is always successful - as we get an error otherwise
+   if (To == 0 && FileName == "/dev/null")
+      return true;
 #if defined HAVE_ZLIB || defined HAVE_BZ2
    if (d != NULL && (d->gz != NULL || d->bz2 != NULL))
       return FileFdError("Truncating compressed files is not implemented (%s)", FileName.c_str());
@@ -1579,29 +1608,55 @@ unsigned long long FileFd::Tell()
    return Res;
 }
 									/*}}}*/
-// FileFd::FileSize - Return the size of the file			/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-unsigned long long FileFd::FileSize()
+static bool StatFileFd(char const * const msg, int const iFd, std::string const &FileName, struct stat &Buf, FileFdPrivate * const d) /*{{{*/
 {
-   struct stat Buf;
-   if ((d == NULL || d->pipe == false) && fstat(iFd,&Buf) != 0)
-      return FileFdErrno("fstat","Unable to determine the file size");
+   bool ispipe = (d != NULL && d->pipe == true);
+   if (ispipe == false)
+   {
+      if (fstat(iFd,&Buf) != 0)
+	 // higher-level code will generate more meaningful messages,
+	 // even translated this would be meaningless for users
+	 return _error->Errno("fstat", "Unable to determine %s for fd %i", msg, iFd);
+      ispipe = S_ISFIFO(Buf.st_mode);
+   }
 
    // for compressor pipes st_size is undefined and at 'best' zero
-   if ((d != NULL && d->pipe == true) || S_ISFIFO(Buf.st_mode))
+   if (ispipe == true)
    {
       // we set it here, too, as we get the info here for free
       // in theory the Open-methods should take care of it already
       if (d != NULL)
 	 d->pipe = true;
       if (stat(FileName.c_str(), &Buf) != 0)
-	 return FileFdErrno("stat","Unable to determine the file size");
+	 return _error->Errno("fstat", "Unable to determine %s for file %s", msg, FileName.c_str());
+   }
+   return true;
+}
+									/*}}}*/
+// FileFd::FileSize - Return the size of the file			/*{{{*/
+unsigned long long FileFd::FileSize()
+{
+   struct stat Buf;
+   if (StatFileFd("file size", iFd, FileName, Buf, d) == false)
+   {
+      Flags |= Fail;
+      return 0;
    }
-
    return Buf.st_size;
 }
 									/*}}}*/
+// FileFd::ModificationTime - Return the time of last touch		/*{{{*/
+time_t FileFd::ModificationTime()
+{
+   struct stat Buf;
+   if (StatFileFd("modification time", iFd, FileName, Buf, d) == false)
+   {
+      Flags |= Fail;
+      return 0;
+   }
+   return Buf.st_mtime;
+}
+									/*}}}*/
 // FileFd::Size - Return the size of the content in the file		/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -1673,35 +1728,6 @@ unsigned long long FileFd::Size()
    return size;
 }
 									/*}}}*/
-// FileFd::ModificationTime - Return the time of last touch		/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-time_t FileFd::ModificationTime()
-{
-   struct stat Buf;
-   if ((d == NULL || d->pipe == false) && fstat(iFd,&Buf) != 0)
-   {
-      FileFdErrno("fstat","Unable to determine the modification time of file %s", FileName.c_str());
-      return 0;
-   }
-
-   // for compressor pipes st_size is undefined and at 'best' zero
-   if ((d != NULL && d->pipe == true) || S_ISFIFO(Buf.st_mode))
-   {
-      // we set it here, too, as we get the info here for free
-      // in theory the Open-methods should take care of it already
-      if (d != NULL)
-	 d->pipe = true;
-      if (stat(FileName.c_str(), &Buf) != 0)
-      {
-	 FileFdErrno("fstat","Unable to determine the modification time of file %s", FileName.c_str());
-	 return 0;
-      }
-   }
-
-   return Buf.st_mtime;
-}
-									/*}}}*/
 // FileFd::Close - Close the file if the close flag is set		/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -1797,7 +1823,8 @@ std::vector<std::string> Glob(std::string const &pattern, int flags)
 {
    std::vector<std::string> result;
    glob_t globbuf;
-   int glob_res, i;
+   int glob_res;
+   unsigned int i;
 
    glob_res = glob(pattern.c_str(),  flags, NULL, &globbuf);
 
@@ -1817,3 +1844,20 @@ std::vector<std::string> Glob(std::string const &pattern, int flags)
    return result;
 }
 									/*}}}*/
+
+std::string GetTempDir()
+{
+   const char *tmpdir = getenv("TMPDIR");
+
+#ifdef P_tmpdir
+   if (!tmpdir)
+      tmpdir = P_tmpdir;
+#endif
+
+   // check that tmpdir is set and exists
+   struct stat st;
+   if (!tmpdir || strlen(tmpdir) == 0 || stat(tmpdir, &st) != 0)
+      tmpdir = "/tmp";
+
+   return string(tmpdir);
+}

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

@@ -26,6 +26,7 @@
 
 #include <string>
 #include <vector>
+#include <set>
 
 #include <zlib.h>
 
@@ -164,6 +165,8 @@ bool DirectoryExists(std::string const &Path) __attrib_const;
 bool CreateDirectory(std::string const &Parent, std::string const &Path);
 time_t GetModificationTime(std::string const &Path);
 
+std::string GetTempDir();
+
 /** \brief Ensure the existence of the given Path
  *
  *  \param Parent directory of the Path directory - a trailing
@@ -182,6 +185,8 @@ void SetCloseExec(int Fd,bool Close);
 void SetNonBlock(int Fd,bool Block);
 bool WaitFd(int Fd,bool write = false,unsigned long timeout = 0);
 pid_t ExecFork();
+pid_t ExecFork(std::set<int> keep_fds);
+void MergeKeepFdsFromConfiguration(std::set<int> &keep_fds);
 bool ExecWait(pid_t Pid,const char *Name,bool Reap = false);
 
 // check if the given file starts with a PGP cleartext signature

+ 8 - 15
apt-pkg/contrib/gpgv.cc

@@ -10,6 +10,7 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <unistd.h>
 
 #include<apt-pkg/configuration.h>
 #include<apt-pkg/error.h>
@@ -21,16 +22,9 @@
 									/*}}}*/
 static char * GenerateTemporaryFileTemplate(const char *basename)	/*{{{*/
 {
-   const char *tmpdir = getenv("TMPDIR");
-#ifdef P_tmpdir
-   if (!tmpdir)
-      tmpdir = P_tmpdir;
-#endif
-   if (!tmpdir)
-      tmpdir = "/tmp";
-
    std::string out;
-   strprintf(out,  "%s/%s.XXXXXX", tmpdir, basename);
+   std::string tmpdir = GetTempDir();
+   strprintf(out,  "%s/%s.XXXXXX", tmpdir.c_str(), basename);
    return strdup(out.c_str());
 }
 									/*}}}*/
@@ -109,12 +103,12 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG,
       }
    }
 
+   enum  { DETACHED, CLEARSIGNED } releaseSignature = (FileGPG != File) ? DETACHED : CLEARSIGNED;
    std::vector<std::string> dataHeader;
    char * sig = NULL;
    char * data = NULL;
 
-   // file with detached signature
-   if (FileGPG != File)
+   if (releaseSignature == DETACHED)
    {
       Args.push_back(FileGPG.c_str());
       Args.push_back(File.c_str());
@@ -187,7 +181,7 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG,
       putenv((char *)"LC_MESSAGES=");
    }
 
-   if (FileGPG != File)
+   if (releaseSignature == DETACHED)
    {
       execvp(gpgvpath.c_str(), (char **) &Args[0]);
       ioprintf(std::cerr, "Couldn't execute %s to check %s", Args[0], File.c_str());
@@ -266,8 +260,7 @@ bool SplitClearSignedFile(std::string const &InFile, FileFd * const ContentFile,
 
    char *buf = NULL;
    size_t buf_size = 0;
-   ssize_t line_len = 0;
-   while ((line_len = getline(&buf, &buf_size, in)) != -1)
+   while (getline(&buf, &buf_size, in) != -1)
    {
       _strrstrip(buf);
       if (found_message_start == false)
@@ -361,7 +354,7 @@ bool OpenMaybeClearSignedFile(std::string const &ClearSignedFileName, FileFd &Me
       return _error->Error("Couldn't open temporary file to work with %s", ClearSignedFileName.c_str());
 
    _error->PushToStack();
-   bool const splitDone = SplitClearSignedFile(ClearSignedFileName.c_str(), &MessageFile, NULL, NULL);
+   bool const splitDone = SplitClearSignedFile(ClearSignedFileName, &MessageFile, NULL, NULL);
    bool const errorDone = _error->PendingError();
    _error->MergeWithStack();
    if (splitDone == false)

+ 1 - 1
apt-pkg/contrib/gpgv.h

@@ -29,7 +29,7 @@
  * for reading. Use #OpenMaybeClearSignedFile to access the message
  * instead to ensure you are only reading signed data.
  *
- * The method does not return, but has some noteable exit-codes:
+ * The method does not return, but has some notable exit-codes:
  * 111 signals an internal error like the inability to execute gpgv,
  * 112 indicates a clear-signed file which doesn't include a message,
  *  which can happen if APT is run while on a network requiring

+ 23 - 7
apt-pkg/contrib/hashes.cc

@@ -54,6 +54,26 @@ HashString::HashString(std::string StringedHash)			/*{{{*/
 }
 									/*}}}*/
 bool HashString::VerifyFile(std::string filename) const			/*{{{*/
+{
+   std::string fileHash = GetHashForFile(filename);
+
+   if(_config->FindB("Debug::Hashes",false) == true)
+      std::clog << "HashString::VerifyFile: got: " << fileHash << " expected: " << toStr() << std::endl;
+
+   return (fileHash == Hash);
+}
+									/*}}}*/
+bool HashString::FromFile(std::string filename)          		/*{{{*/
+{
+   // pick the strongest hash
+   if (Type == "")
+      Type = _SupportedHashes[0];
+
+   Hash = GetHashForFile(filename);
+   return true;
+}
+									/*}}}*/
+std::string HashString::GetHashForFile(std::string filename) const      /*{{{*/
 {
    std::string fileHash;
 
@@ -84,10 +104,7 @@ bool HashString::VerifyFile(std::string filename) const			/*{{{*/
    }
    Fd.Close();
 
-   if(_config->FindB("Debug::Hashes",false) == true)
-      std::clog << "HashString::VerifyFile: got: " << fileHash << " expected: " << toStr() << std::endl;
-
-   return (fileHash == Hash);
+   return fileHash;
 }
 									/*}}}*/
 const char** HashString::SupportedHashes()
@@ -112,13 +129,12 @@ bool Hashes::AddFD(int const Fd,unsigned long long Size, bool const addMD5,
 		   bool const addSHA1, bool const addSHA256, bool const addSHA512)
 {
    unsigned char Buf[64*64];
-   ssize_t Res = 0;
-   int ToEOF = (Size == 0);
+   bool const ToEOF = (Size == 0);
    while (Size != 0 || ToEOF)
    {
       unsigned long long n = sizeof(Buf);
       if (!ToEOF) n = std::min(Size, n);
-      Res = read(Fd,Buf,n);
+      ssize_t const Res = read(Fd,Buf,n);
       if (Res < 0 || (!ToEOF && Res != (ssize_t) n)) // error, or short read
 	 return false;
       if (ToEOF && Res == 0) // EOF

+ 8 - 1
apt-pkg/contrib/hashes.h

@@ -36,7 +36,10 @@ class HashString
  protected:
    std::string Type;
    std::string Hash;
-   static const char * _SupportedHashes[10];
+   static const char* _SupportedHashes[10];
+
+   // internal helper
+   std::string GetHashForFile(std::string filename) const;
 
  public:
    HashString(std::string Type, std::string Hash);
@@ -49,6 +52,10 @@ class HashString
    // verify the given filename against the currently loaded hash
    bool VerifyFile(std::string filename) const;
 
+   // generate a hash string from the given filename
+   bool FromFile(std::string filename);
+
+
    // helper
    std::string toStr() const;                    // convert to str as "type:hash"
    bool empty() const;

+ 3 - 4
apt-pkg/contrib/hashsum.cc

@@ -9,13 +9,12 @@
 /* */
 bool SummationImplementation::AddFD(int const Fd, unsigned long long Size) {
    unsigned char Buf[64 * 64];
-   ssize_t Res = 0;
-   int ToEOF = (Size == 0);
+   bool const ToEOF = (Size == 0);
    while (Size != 0 || ToEOF)
    {
       unsigned long long n = sizeof(Buf);
       if (!ToEOF) n = std::min(Size, n);
-      Res = read(Fd, Buf, n);
+      ssize_t const Res = read(Fd, Buf, n);
       if (Res < 0 || (!ToEOF && Res != (ssize_t) n)) // error, or short read
 	 return false;
       if (ToEOF && Res == 0) // EOF
@@ -27,7 +26,7 @@ bool SummationImplementation::AddFD(int const Fd, unsigned long long Size) {
 }
 bool SummationImplementation::AddFD(FileFd &Fd, unsigned long long Size) {
    unsigned char Buf[64 * 64];
-   bool ToEOF = (Size == 0);
+   bool const ToEOF = (Size == 0);
    while (Size != 0 || ToEOF)
    {
       unsigned long long n = sizeof(Buf);

+ 1 - 1
apt-pkg/contrib/macros.h

@@ -44,7 +44,7 @@
 #define _boundv(a,b,c) b = _bound(a,b,c)
 #define ABS(a) (((a) < (0)) ?-(a) : (a))
 
-/* Usefull count macro, use on an array of things and it will return the
+/* Useful count macro, use on an array of things and it will return the
    number of items in the array */
 #define _count(a) (sizeof(a)/sizeof(a[0]))
 

+ 1 - 1
apt-pkg/contrib/md5.h

@@ -10,7 +10,7 @@
    store a MD5Sum in 16 bytes of memory.
    
    A MD5Sum is used to generate a (hopefully) unique 16 byte number for a
-   block of data. This can be used to gaurd against corruption of a file.
+   block of data. This can be used to guard against corruption of a file.
    MD5 should not be used for tamper protection, use SHA or something more
    secure.
    

+ 7 - 1
apt-pkg/contrib/mmap.cc

@@ -352,6 +352,12 @@ unsigned long DynamicMMap::RawAllocate(unsigned long long Size,unsigned long Aln
    size in the file. */
 unsigned long DynamicMMap::Allocate(unsigned long ItemSize)
 {
+   if (unlikely(ItemSize == 0))
+   {
+      _error->Fatal("Can't allocate an item of size zero");
+      return 0;
+   }
+
    // Look for a matching pool entry
    Pool *I;
    Pool *Empty = 0;
@@ -412,7 +418,7 @@ unsigned long DynamicMMap::WriteString(const char *String,
 
    unsigned long const Result = RawAllocate(Len+1,0);
 
-   if (Result == 0 && _error->PendingError())
+   if (Base == NULL || (Result == 0 && _error->PendingError()))
       return 0;
 
    memcpy((char *)Base + Result,String,Len);

+ 2 - 2
apt-pkg/contrib/mmap.h

@@ -6,7 +6,7 @@
    MMap Class - Provides 'real' mmap or a faked mmap using read().
 
    The purpose of this code is to provide a generic way for clients to
-   access the mmap function. In enviroments that do not support mmap
+   access the mmap function. In environments that do not support mmap
    from file fd's this function will use read and normal allocated 
    memory.
    
@@ -15,7 +15,7 @@
 
    The DynamicMMap class is used to help the on-disk data structure 
    generators. It provides a large allocated workspace and members
-   to allocate space from the workspace in an effecient fashion.
+   to allocate space from the workspace in an efficient fashion.
    
    This source is placed in the Public Domain, do with it what you will
    It was originally written by Jason Gunthorpe.

+ 1 - 1
apt-pkg/contrib/progress.h

@@ -7,7 +7,7 @@
    
    This class allows lengthy operations to communicate their progress 
    to the GUI. The progress model is simple and is not designed to handle
-   the complex case of the multi-activity aquire class.
+   the complex case of the multi-activity acquire class.
    
    The model is based on the concept of an overall operation consisting
    of a series of small sub operations. Each sub operation has it's own

+ 1 - 1
apt-pkg/contrib/sha2_internal.cc

@@ -65,7 +65,7 @@
  * Please make sure that your system defines BYTE_ORDER.  If your
  * architecture is little-endian, make sure it also defines
  * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are
- * equivilent.
+ * equivalent.
  *
  * If your system does not define the above, then you can do so by
  * hand like this:

+ 61 - 5
apt-pkg/contrib/strutl.cc

@@ -36,7 +36,30 @@
 
 using namespace std;
 									/*}}}*/
+// Strip - Remove white space from the front and back of a string       /*{{{*/
+// ---------------------------------------------------------------------
+namespace APT {
+   namespace String {
+std::string Strip(const std::string &s)
+{
+   size_t start = s.find_first_not_of(" \t\n");
+   // only whitespace
+   if (start == string::npos)
+      return "";
+   size_t end = s.find_last_not_of(" \t\n");
+   return s.substr(start, end-start+1);
+}
+
+bool Endswith(const std::string &s, const std::string &end)
+{
+   if (end.size() > s.size())
+      return false;
+   return (s.substr(s.size() - end.size(), s.size()) == end);
+}
 
+}
+}
+									/*}}}*/
 // UTF8ToCodeset - Convert some UTF-8 string for some codeset   	/*{{{*/
 // ---------------------------------------------------------------------
 /* This is handy to use before display some information for enduser  */
@@ -403,7 +426,7 @@ string TimeToStr(unsigned long Sec)
 									/*}}}*/
 // SubstVar - Substitute a string for another string			/*{{{*/
 // ---------------------------------------------------------------------
-/* This replaces all occurances of Subst with Contents in Str. */
+/* This replaces all occurrences of Subst with Contents in Str. */
 string SubstVar(const string &Str,const string &Subst,const string &Contents)
 {
    string::size_type Pos = 0;
@@ -903,7 +926,7 @@ bool FTPMDTMStrToTime(const char* const str,time_t &time)
 									/*}}}*/
 // StrToTime - Converts a string into a time_t				/*{{{*/
 // ---------------------------------------------------------------------
-/* This handles all 3 populare time formats including RFC 1123, RFC 1036
+/* This handles all 3 popular time formats including RFC 1123, RFC 1036
    and the C library asctime format. It requires the GNU library function
    'timegm' to convert a struct tm in UTC to a time_t. For some bizzar
    reason the C library does not provide any such function :< This also
@@ -943,6 +966,8 @@ bool StrToTime(const string &Val,time_t &Result)
    Tm.tm_isdst = 0;
    if (Month[0] != 0)
       Tm.tm_mon = MonthConv(Month);
+   else
+      Tm.tm_mon = 0; // we don't have a month, so pick something
    Tm.tm_year -= 1900;
    
    // Convert to local time and then to GMT
@@ -1116,6 +1141,37 @@ vector<string> VectorizeString(string const &haystack, char const &split)
    return exploded;
 }
 									/*}}}*/
+// StringSplit - split a string into a string vector by token		/*{{{*/
+// ---------------------------------------------------------------------
+/* See header for details.
+ */
+vector<string> StringSplit(std::string const &s, std::string const &sep,
+                           unsigned int maxsplit)
+{
+   vector<string> split;
+   size_t start, pos;
+
+   // no seperator given, this is bogus
+   if(sep.size() == 0)
+      return split;
+
+   start = pos = 0;
+   while (pos != string::npos)
+   {
+      pos = s.find(sep, start);
+      split.push_back(s.substr(start, pos-start));
+      
+      // if maxsplit is reached, the remaining string is the last item
+      if(split.size() >= maxsplit)
+      {
+         split[split.size()-1] = s.substr(start);
+         break;
+      }
+      start = pos+sep.size();
+   }
+   return split;
+}
+									/*}}}*/
 // RegexChoice - Simple regex list/list matcher				/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -1257,7 +1313,7 @@ string StripEpoch(const string &VerStr)
 // tolower_ascii - tolower() function that ignores the locale		/*{{{*/
 // ---------------------------------------------------------------------
 /* This little function is the most called method we have and tries
-   therefore to do the absolut minimum - and is noteable faster than
+   therefore to do the absolut minimum - and is notable faster than
    standard tolower/toupper and as a bonus avoids problems with different
    locales - we only operate on ascii chars anyway. */
 int tolower_ascii(int const c)
@@ -1268,9 +1324,9 @@ int tolower_ascii(int const c)
 }
 									/*}}}*/
 
-// CheckDomainList - See if Host is in a , seperate list		/*{{{*/
+// CheckDomainList - See if Host is in a , separate list		/*{{{*/
 // ---------------------------------------------------------------------
-/* The domain list is a comma seperate list of domains that are suffix
+/* The domain list is a comma separate list of domains that are suffix
    matched against the argument */
 bool CheckDomainList(const string &Host,const string &List)
 {

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

@@ -17,7 +17,7 @@
 #define STRUTL_H
 
 
-
+#include <limits>
 #include <stdlib.h>
 #include <string>
 #include <cstring>
@@ -33,6 +33,14 @@ using std::vector;
 using std::ostream;
 #endif
 
+namespace APT {
+   namespace String {
+      std::string Strip(const std::string &s);
+      bool Endswith(const std::string &s, const std::string &ending);
+   };
+};
+
+
 bool UTF8ToCodeset(const char *codeset, const std::string &orig, std::string *dest);
 char *_strstrip(char *String);
 char *_strrstrip(char *String); // right strip only
@@ -62,9 +70,32 @@ bool StrToNum(const char *Str,unsigned long &Res,unsigned Len,unsigned Base = 0)
 bool StrToNum(const char *Str,unsigned long long &Res,unsigned Len,unsigned Base = 0);
 bool Base256ToNum(const char *Str,unsigned long &Res,unsigned int Len);
 bool Hex2Num(const std::string &Str,unsigned char *Num,unsigned int Length);
+
+// input changing string split
 bool TokSplitString(char Tok,char *Input,char **List,
 		    unsigned long ListMax);
+
+// split a given string by a char
 std::vector<std::string> VectorizeString(std::string const &haystack, char const &split) __attrib_const;
+
+/* \brief Return a vector of strings from string "input" where "sep"
+ * is used as the delimiter string.
+ *
+ * \param input The input string.
+ *
+ * \param sep The seperator to use.
+ *
+ * \param maxsplit (optional) The maximum amount of splitting that
+ * should be done .
+ * 
+ * The optional "maxsplit" argument can be used to limit the splitting,
+ * if used the string is only split on maxsplit places and the last
+ * item in the vector contains the remainder string.
+ */
+std::vector<std::string> StringSplit(std::string const &input, 
+                                     std::string const &sep, 
+                                     unsigned int maxsplit=std::numeric_limits<unsigned int>::max()) __attrib_const;
+
 void ioprintf(std::ostream &out,const char *format,...) __like_printf(2);
 void strprintf(std::string &out,const char *format,...) __like_printf(2);
 char *safe_snprintf(char *Buffer,char *End,const char *Format,...) __like_printf(3);

+ 3 - 5
apt-pkg/deb/deblistparser.cc

@@ -635,7 +635,7 @@ bool debListParser::ParseDepends(pkgCache::VerIterator &Ver,
       string Version;
       unsigned int Op;
 
-      Start = ParseDepends(Start,Stop,Package,Version,Op,false,!MultiArchEnabled);
+      Start = ParseDepends(Start, Stop, Package, Version, Op, false, false);
       if (Start == 0)
 	 return _error->Error("Problem parsing dependency %s",Tag);
       size_t const found = Package.rfind(':');
@@ -717,9 +717,7 @@ bool debListParser::ParseProvides(pkgCache::VerIterator &Ver)
       }
    }
 
-   if (MultiArchEnabled == false)
-      return true;
-   else if ((Ver->MultiArch & pkgCache::Version::Allowed) == pkgCache::Version::Allowed)
+   if ((Ver->MultiArch & pkgCache::Version::Allowed) == pkgCache::Version::Allowed)
    {
       string const Package = string(Ver.ParentPkg().Name()).append(":").append("any");
       return NewProvidesAllArch(Ver, Package, Ver.VerStr());
@@ -760,7 +758,7 @@ bool debListParser::GrabWord(string Word,WordList *List,unsigned char &Out)
 									/*}}}*/
 // ListParser::Step - Move to the next section in the file		/*{{{*/
 // ---------------------------------------------------------------------
-/* This has to be carefull to only process the correct architecture */
+/* This has to be careful to only process the correct architecture */
 bool debListParser::Step()
 {
    iOffset = Tags.Offset();

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

@@ -1,4 +1,3 @@
-// ijones, walters
 #include <config.h>
 
 #include <apt-pkg/debmetaindex.h>
@@ -72,6 +71,22 @@ string debReleaseIndex::MetaIndexURI(const char *Type) const
    return Res;
 }
 
+#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
+std::string debReleaseIndex::LocalFileName() const
+{
+   // see if we have a InRelease file
+   std::string PathInRelease =  MetaIndexFile("InRelease");
+   if (FileExists(PathInRelease))
+      return PathInRelease;
+
+   // and if not return the normal one
+   if (FileExists(PathInRelease))
+      return MetaIndexFile("Release");
+
+   return "";
+}
+#endif
+
 string debReleaseIndex::IndexURISuffix(const char *Type, string const &Section, string const &Arch) const
 {
    string Res ="";

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

@@ -3,6 +3,7 @@
 #define PKGLIB_DEBMETAINDEX_H
 
 #include <apt-pkg/metaindex.h>
+#include <apt-pkg/init.h>
 
 #include <map>
 #include <string>
@@ -39,9 +40,15 @@ class debReleaseIndex : public metaIndex {
    virtual bool GetIndexes(pkgAcquire *Owner, bool const &GetAll=false) const;
    std::vector <struct IndexTarget *>* ComputeIndexTargets() const;
    std::string Info(const char *Type, std::string const &Section, std::string const &Arch="") const;
+
    std::string MetaIndexInfo(const char *Type) const;
    std::string MetaIndexFile(const char *Types) const;
    std::string MetaIndexURI(const char *Type) const;
+
+#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
+   virtual std::string LocalFileName() const;
+#endif
+
    std::string IndexURI(const char *Type, std::string const &Section, std::string const &Arch="native") const;
    std::string IndexURISuffix(const char *Type, std::string const &Section, std::string const &Arch="native") const;
    std::string SourceIndexURI(const char *Type, const std::string &Section) const;

+ 3 - 3
apt-pkg/deb/debsrcrecords.h

@@ -30,7 +30,7 @@ class debSrcRecordParser : public pkgSrcRecords::Parser
    
    public:
 
-   virtual bool Restart() {return Tags.Jump(Sect,0);};
+   virtual bool Restart() {return Jump(0);};
    virtual bool Step() {iOffset = Tags.Offset(); return Tags.Step(Sect);};
    virtual bool Jump(unsigned long const &Off) {iOffset = Off; return Tags.Jump(Sect,Off);};
 
@@ -50,8 +50,8 @@ class debSrcRecordParser : public pkgSrcRecords::Parser
    virtual bool Files(std::vector<pkgSrcRecords::File> &F);
 
    debSrcRecordParser(std::string const &File,pkgIndexFile const *Index) 
-      : Parser(Index), Fd(File,FileFd::ReadOnly, FileFd::Extension), Tags(&Fd,102400), 
-        Buffer(NULL) {}
+      : Parser(Index), Fd(File,FileFd::ReadOnly, FileFd::Extension), Tags(&Fd,102400),
+        iOffset(0), Buffer(NULL) {}
    virtual ~debSrcRecordParser();
 };
 

+ 1 - 1
apt-pkg/deb/debsystem.cc

@@ -193,7 +193,7 @@ bool debSystem::Initialize(Configuration &Cnf)
 									/*}}}*/
 // System::ArchiveSupported - Is a file format supported		/*{{{*/
 // ---------------------------------------------------------------------
-/* The standard name for a deb is 'deb'.. There are no seperate versions
+/* The standard name for a deb is 'deb'.. There are no separate versions
    of .deb to worry about.. */
 bool debSystem::ArchiveSupported(const char *Type)
 {

+ 2 - 2
apt-pkg/deb/debversion.cc

@@ -116,7 +116,7 @@ int debVersioningSystem::CmpFragment(const char *A,const char *AEnd,
       return 1;
    }
 
-   // Shouldnt happen
+   // Shouldn't happen
    return 1;
 }
 									/*}}}*/
@@ -221,7 +221,7 @@ bool debVersioningSystem::CheckDep(const char *PkgVer,
    if (PkgVer == DepVer)
       return Op == pkgCache::Dep::Equals || Op == pkgCache::Dep::LessEq || Op == pkgCache::Dep::GreaterEq;
 
-   // Perform the actual comparision.
+   // Perform the actual comparison.
    int const Res = CmpVersion(PkgVer, DepVer);
    switch (Op)
    {

Plik diff jest za duży
+ 433 - 292
apt-pkg/deb/dpkgpm.cc


+ 30 - 2
apt-pkg/deb/dpkgpm.h

@@ -15,6 +15,7 @@
 #include <map>
 #include <stdio.h>
 #include <apt-pkg/macros.h>
+#include <apt-pkg/init.h>
 
 #ifndef APT_8_CLEANER_HEADERS
 using std::vector;
@@ -23,6 +24,7 @@ using std::map;
 
 class pkgDPkgPMPrivate;
 
+
 class pkgDPkgPM : public pkgPackageManager
 {
    private:
@@ -83,6 +85,11 @@ class pkgDPkgPM : public pkgPackageManager
    __deprecated bool SendV2Pkgs(FILE *F);
    bool SendPkgsInfo(FILE * const F, unsigned int const &Version);
    void WriteHistoryTag(std::string const &tag, std::string value);
+   std::string ExpandShortPackageName(pkgDepCache &Cache,
+                                      const std::string &short_pkgname);
+
+   // Terminal progress 
+   void SendTerminalProgress(float percentage);
 
    // apport integration
    void WriteApportReport(const char *pkgpath, const char *errormsg);
@@ -90,18 +97,39 @@ class pkgDPkgPM : public pkgPackageManager
    // dpkg log
    bool OpenLog();
    bool CloseLog();
+
+   // helper
+   void BuildPackagesProgressMap();
+   void StartPtyMagic();
+   void StopPtyMagic();
    
    // input processing
    void DoStdin(int master);
    void DoTerminalPty(int master);
-   void DoDpkgStatusFd(int statusfd, int OutStatusFd);
-   void ProcessDpkgStatusLine(int OutStatusFd, char *line);
+   void DoDpkgStatusFd(int statusfd);
+   void ProcessDpkgStatusLine(char *line);
+#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR < 13)
+   void DoDpkgStatusFd(int statusfd, int unused) {
+      DoDpkgStatusFd(statusfd);
+   }
+   void ProcessDpkgStatusLine(int unused, char *line) {
+      ProcessDpkgStatusLine(line);
+   }
+#endif
+
 
    // The Actuall installation implementation
    virtual bool Install(PkgIterator Pkg,std::string File);
    virtual bool Configure(PkgIterator Pkg);
    virtual bool Remove(PkgIterator Pkg,bool Purge = false);
+
+#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
+   virtual bool Go(APT::Progress::PackageManager *progress);
+#else
    virtual bool Go(int StatusFd=-1);
+   bool GoNoABIBreak(APT::Progress::PackageManager *progress);
+#endif
+
    virtual void Reset();
    
    public:

+ 20 - 9
apt-pkg/depcache.cc

@@ -789,7 +789,7 @@ bool pkgDepCache::MarkKeep(PkgIterator const &Pkg, bool Soft, bool FromUser,
       // - 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
+      //   for all other use-case this action is rather surprising
    if(FromUser && !P.Marked)
      P.Flags &= ~Flag::Auto;
 #endif
@@ -896,6 +896,7 @@ char const* PrintMode(char const mode)
 	 case pkgDepCache::ModeInstall: return "Install";
 	 case pkgDepCache::ModeKeep: return "Keep";
 	 case pkgDepCache::ModeDelete: return "Delete";
+	 case pkgDepCache::ModeGarbage: return "Garbage";
 	 default: return "UNKNOWN";
 	 }
 }
@@ -1133,8 +1134,13 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
 	    std::clog << OutputInDepth(Depth) << Start << " can't be satisfied!" << std::endl;
 	 if (Start.IsCritical() == false)
 	    continue;
-	 // if the dependency was critical, we can't install it, so remove it again
-	 MarkDelete(Pkg,false,Depth + 1, false);
+	 // if the dependency was critical, we have absolutely no chance to install it,
+	 // so if it wasn't installed remove it again. If it was, discard the candidate
+	 // as the problemresolver will trip over it otherwise trying to install it (#735967)
+	 if (Pkg->CurrentVer == 0)
+	    MarkDelete(Pkg,false,Depth + 1, false);
+	 else
+	    SetCandidateVersion(Pkg.CurrentVer());
 	 return false;
       }
 
@@ -1189,7 +1195,7 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
 	 }
       }
 
-      /* This bit is for processing the possibilty of an install/upgrade
+      /* This bit is for processing the possibility of an install/upgrade
          fixing the problem for "positive" dependencies */
       if (Start.IsNegative() == false && (DepState[Start->ID] & DepCVer) == DepCVer)
       {
@@ -1252,6 +1258,11 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
 	    if (PkgState[Pkg->ID].InstallVer == 0)
 	       continue;
 
+            /* Ignore negative dependencies that we are not going to 
+               get installed */
+            if (PkgState[Pkg->ID].InstallVer != *I)
+               continue;
+
 	    if ((Start->Version != 0 || TrgPkg != Pkg) &&
 		PkgState[Pkg->ID].CandidateVer != PkgState[Pkg->ID].InstallVer &&
 		PkgState[Pkg->ID].CandidateVer != *I &&
@@ -1304,7 +1315,7 @@ bool pkgDepCache::IsInstallOkMultiArchSameVersionSynced(PkgIterator const &Pkg,
       // (simple string-compare as stuff like '1' == '0:1-0' can't happen here)
       if (P->CurrentVer == 0 || strcmp(Pkg.CandVersion(), P.CandVersion()) == 0)
 	 continue;
-      // packages loosing M-A:same can be out-of-sync
+      // packages losing M-A:same can be out-of-sync
       VerIterator CV = PkgState[P->ID].CandidateVerIter(*this);
       if (unlikely(CV.end() == true) ||
 	    (CV->MultiArch & pkgCache::Version::Same) != pkgCache::Version::Same)
@@ -1521,7 +1532,7 @@ bool pkgDepCache::SetCandidateRelease(pkgCache::VerIterator TargetVer,
 	 if (itsFine == false)
 	 {
 	    // change the candidate
-	    Changed.push_back(make_pair(oldCand, TargetVer));
+	    Changed.push_back(make_pair(V, TargetVer));
 	    if (SetCandidateRelease(V, TargetRel, Changed) == false)
 	    {
 	       if (stillOr == false)
@@ -1726,8 +1737,6 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
    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)
    {
@@ -1738,7 +1747,9 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
 	  // be nice even then a required package violates the policy (#583517)
 	  // and do the full mark process also for required packages
 	  (p.CurrentVer().end() != true &&
-	   p.CurrentVer()->Priority == pkgCache::State::Required))
+	   p.CurrentVer()->Priority == pkgCache::State::Required) ||
+	  // packages which can't be changed (like holds) can't be garbage
+	  (IsModeChangeOk(ModeGarbage, p, 0, false) == false))
       {
 	 // the package is installed (and set to keep)
 	 if(PkgState[p->ID].Keep() && !p.CurrentVer().end())

+ 2 - 2
apt-pkg/depcache.h

@@ -15,7 +15,7 @@
    
    This structure is important to support the readonly status of the cache 
    file. When the data is saved the cache will be refereshed from our 
-   internal rep and written to disk. Then the actual persistant data 
+   internal rep and written to disk. Then the actual persistent data
    files will be put on the disk.
 
    Each dependency is compared against 3 target versions to produce to
@@ -128,7 +128,7 @@ class pkgDepCache : protected pkgCache::Namespace
    enum InternalFlags {AutoKept = (1 << 0), Purge = (1 << 1), ReInstall = (1 << 2), Protected = (1 << 3)};
       
    enum VersionTypes {NowVersion, InstallVersion, CandidateVersion};
-   enum ModeList {ModeDelete = 0, ModeKeep = 1, ModeInstall = 2};
+   enum ModeList {ModeDelete = 0, ModeKeep = 1, ModeInstall = 2, ModeGarbage = 3};
 
    /** \brief Represents an active action group.
     *

+ 3 - 3
apt-pkg/edsp.h

@@ -2,7 +2,7 @@
 /** Description \file edsp.h						{{{
    ######################################################################
    Set of methods to help writing and reading everything needed for EDSP
-   with the noteable exception of reading a scenario for conversion into
+   with the notable exception of reading a scenario for conversion into
    a Cache as this is handled by edsp interface for listparser and friends
    ##################################################################### */
 									/*}}}*/
@@ -182,13 +182,13 @@ public:
 	 *  they were unable to calculate a solution for a given task.
 	 *  Obviously they can't send a solution through, so this
 	 *  methods deals with formatting an error message correctly
-	 *  so that the front-ends can recieve and display it.
+	 *  so that the front-ends can receive and display it.
 	 *
 	 *  The first line of the message should be a short description
 	 *  of the error so it can be used for dialog titles or alike
 	 *
 	 *  \param uuid of this error message
-	 *  \param message is free form text to discribe the error
+	 *  \param message is free form text to describe the error
 	 *  \param output the front-end listens for error messages
 	 */
 	bool static WriteError(char const * const uuid, std::string const &message, FILE* output);

+ 4 - 4
apt-pkg/indexfile.h

@@ -10,12 +10,12 @@
    
    Binary index files 
    Binary translation files 
-   Bianry index files decribing the local system
+   Binary index files describing the local system
    Source index files
    
    They are all bundled together here, and the interfaces for 
    sources.list, acquire, cache gen and record parsing all use this class
-   to acess the underlying representation.
+   to access the underlying representation.
    
    ##################################################################### */
 									/*}}}*/
@@ -78,10 +78,10 @@ class pkgIndexFile
    virtual bool Exists() const = 0;
    virtual bool HasPackages() const = 0;
    virtual unsigned long Size() const = 0;
-   virtual bool Merge(pkgCacheGenerator &/*Gen*/,OpProgress* /*Prog*/) const { return false; };
+   virtual bool Merge(pkgCacheGenerator &Gen, OpProgress* Prog) const { return false; };
    __deprecated virtual bool Merge(pkgCacheGenerator &Gen, OpProgress &Prog) const
       { return Merge(Gen, &Prog); };
-   virtual bool MergeFileProvides(pkgCacheGenerator &/*Gen*/,OpProgress* /*Prog*/) const {return true;};
+   virtual bool MergeFileProvides(pkgCacheGenerator &Gen,OpProgress* Prog) const {return true;};
    __deprecated virtual bool MergeFileProvides(pkgCacheGenerator &Gen, OpProgress &Prog) const
       {return MergeFileProvides(Gen, &Prog);};
    virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const;

+ 5 - 0
apt-pkg/indexrecords.cc

@@ -27,6 +27,11 @@ string indexRecords::GetDist() const
    return this->Dist;
 }
 
+string indexRecords::GetSuite() const
+{
+   return this->Suite;
+}
+
 bool indexRecords::CheckDist(const string MaybeDist) const
 {
    return (this->Dist == MaybeDist

+ 1 - 0
apt-pkg/indexrecords.h

@@ -46,6 +46,7 @@ class indexRecords
 
    virtual bool Load(std::string Filename);
    std::string GetDist() const;
+   std::string GetSuite() const;
    time_t GetValidUntil() const;
    virtual bool CheckDist(const std::string MaybeDist) const;
    std::string GetExpectedDist() const;

+ 2 - 10
apt-pkg/init.cc

@@ -44,16 +44,8 @@ bool pkgInitConfig(Configuration &Cnf)
    Cnf.CndSet("APT::Install-Suggests", false);
    Cnf.CndSet("Dir","/");
    
-   // State   
+   // State
    Cnf.CndSet("Dir::State","var/lib/apt/");
-   
-   /* Just in case something goes horribly wrong, we can fall back to the
-      old /var/state paths.. */
-   struct stat St;   
-   if (stat("/var/lib/apt/.",&St) != 0 &&
-       stat("/var/state/apt/.",&St) == 0)
-      Cnf.CndSet("Dir::State","var/state/apt/");
-       
    Cnf.CndSet("Dir::State::lists","lists/");
    Cnf.CndSet("Dir::State::cdroms","cdroms.list");
    Cnf.CndSet("Dir::State::mirrors","mirrors/");
@@ -100,7 +92,7 @@ bool pkgInitConfig(Configuration &Cnf)
    
    // Read an alternate config file
    const char *Cfg = getenv("APT_CONFIG");
-   if (Cfg != 0)
+   if (Cfg != 0 && strlen(Cfg) != 0)
    {
       if (RealFileExists(Cfg) == true)
 	 Res &= ReadConfigFile(Cnf,Cfg);

+ 375 - 0
apt-pkg/install-progress.cc

@@ -0,0 +1,375 @@
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/fileutl.h>
+#include <apt-pkg/strutl.h>
+#include <apt-pkg/install-progress.h>
+
+#include <apti18n.h>
+
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <sstream>
+#include <fcntl.h>
+#include <algorithm>
+#include <stdio.h>
+
+namespace APT {
+namespace Progress {
+
+
+/* Return a APT::Progress::PackageManager based on the global
+ * apt configuration (i.e. APT::Status-Fd and APT::Status-deb822-Fd)
+ */
+PackageManager* PackageManagerProgressFactory()
+{
+   // select the right progress
+   int status_fd = _config->FindI("APT::Status-Fd", -1);
+   int status_deb822_fd = _config->FindI("APT::Status-deb822-Fd", -1);
+
+   APT::Progress::PackageManager *progress = NULL;
+   if (status_deb822_fd > 0)
+      progress = new APT::Progress::PackageManagerProgressDeb822Fd(
+         status_deb822_fd);
+   else if (status_fd > 0)
+      progress = new APT::Progress::PackageManagerProgressFd(status_fd);
+   else if(_config->FindB("Dpkg::Progress-Fancy", false) == true)
+      progress = new APT::Progress::PackageManagerFancy();
+   else if (_config->FindB("Dpkg::Progress", 
+                           _config->FindB("DpkgPM::Progress", false)) == true)
+      progress = new APT::Progress::PackageManagerText();
+   else
+      progress = new APT::Progress::PackageManager();
+   return progress;
+}
+
+bool PackageManager::StatusChanged(std::string PackageName, 
+                                   unsigned int StepsDone,
+                                   unsigned int TotalSteps,
+                                   std::string HumanReadableAction)
+{
+   int reporting_steps = _config->FindI("DpkgPM::Reporting-Steps", 1);
+   percentage = StepsDone/(float)TotalSteps * 100.0;
+   strprintf(progress_str, _("Progress: [%3i%%]"), (int)percentage);
+
+   if(percentage < (last_reported_progress + reporting_steps))
+      return false;
+
+   return true;
+}
+
+PackageManagerProgressFd::PackageManagerProgressFd(int progress_fd)
+   : StepsDone(0), StepsTotal(1)
+{
+   OutStatusFd = progress_fd;
+}
+
+void PackageManagerProgressFd::WriteToStatusFd(std::string s)
+{
+   if(OutStatusFd <= 0)
+      return;
+   FileFd::Write(OutStatusFd, s.c_str(), s.size());   
+}
+
+void PackageManagerProgressFd::StartDpkg()
+{
+   if(OutStatusFd <= 0)
+      return;
+
+   // FIXME: use SetCloseExec here once it taught about throwing
+   //        exceptions instead of doing _exit(100) on failure
+   fcntl(OutStatusFd,F_SETFD,FD_CLOEXEC); 
+
+   // send status information that we are about to fork dpkg
+   std::ostringstream status;
+   status << "pmstatus:dpkg-exec:" 
+          << (StepsDone/float(StepsTotal)*100.0) 
+          << ":" << _("Running dpkg")
+          << std::endl;
+   WriteToStatusFd(status.str());
+}
+
+void PackageManagerProgressFd::Stop()
+{
+}
+
+void PackageManagerProgressFd::Error(std::string PackageName,
+                                     unsigned int StepsDone,
+                                     unsigned int TotalSteps,
+                                     std::string ErrorMessage)
+{
+   std::ostringstream status;
+   status << "pmerror:" << PackageName
+          << ":"  << (StepsDone/float(TotalSteps)*100.0) 
+          << ":" << ErrorMessage
+          << std::endl;
+   WriteToStatusFd(status.str());
+}
+
+void PackageManagerProgressFd::ConffilePrompt(std::string PackageName,
+                                              unsigned int StepsDone,
+                                              unsigned int TotalSteps,
+                                              std::string ConfMessage)
+{
+   std::ostringstream status;
+   status << "pmconffile:" << PackageName
+          << ":"  << (StepsDone/float(TotalSteps)*100.0) 
+          << ":" << ConfMessage
+          << std::endl;
+   WriteToStatusFd(status.str());
+}
+
+
+bool PackageManagerProgressFd::StatusChanged(std::string PackageName, 
+                                             unsigned int xStepsDone,
+                                             unsigned int xTotalSteps,
+                                             std::string pkg_action)
+{
+   StepsDone = xStepsDone;
+   StepsTotal = xTotalSteps;
+
+   // build the status str
+   std::ostringstream status;
+   status << "pmstatus:" << StringSplit(PackageName, ":")[0]
+          << ":"  << (StepsDone/float(StepsTotal)*100.0) 
+          << ":" << pkg_action
+          << std::endl;
+   WriteToStatusFd(status.str());
+
+   if(_config->FindB("Debug::APT::Progress::PackageManagerFd", false) == true)
+      std::cerr << "progress: " << PackageName << " " << xStepsDone
+                << " " << xTotalSteps << " " << pkg_action
+                << std::endl;
+
+
+   return true;
+}
+
+
+PackageManagerProgressDeb822Fd::PackageManagerProgressDeb822Fd(int progress_fd)
+   : StepsDone(0), StepsTotal(1)
+{
+   OutStatusFd = progress_fd;
+}
+
+void PackageManagerProgressDeb822Fd::WriteToStatusFd(std::string s)
+{
+   FileFd::Write(OutStatusFd, s.c_str(), s.size());   
+}
+
+void PackageManagerProgressDeb822Fd::StartDpkg()
+{
+   // FIXME: use SetCloseExec here once it taught about throwing
+   //        exceptions instead of doing _exit(100) on failure
+   fcntl(OutStatusFd,F_SETFD,FD_CLOEXEC); 
+
+   // send status information that we are about to fork dpkg
+   std::ostringstream status;
+   status << "Status: " << "progress" << std::endl
+          << "Percent: " << (StepsDone/float(StepsTotal)*100.0) << std::endl
+          << "Message: " << _("Running dpkg") << std::endl
+          << std::endl;
+   WriteToStatusFd(status.str());
+}
+
+void PackageManagerProgressDeb822Fd::Stop()
+{
+}
+
+void PackageManagerProgressDeb822Fd::Error(std::string PackageName,
+                                     unsigned int StepsDone,
+                                     unsigned int TotalSteps,
+                                     std::string ErrorMessage)
+{
+   std::ostringstream status;
+   status << "Status: " << "Error" << std::endl
+          << "Package:" << PackageName << std::endl
+          << "Percent: "  << (StepsDone/float(TotalSteps)*100.0) << std::endl
+          << "Message: " << ErrorMessage << std::endl
+          << std::endl;
+   WriteToStatusFd(status.str());
+}
+
+void PackageManagerProgressDeb822Fd::ConffilePrompt(std::string PackageName,
+                                              unsigned int StepsDone,
+                                              unsigned int TotalSteps,
+                                              std::string ConfMessage)
+{
+   std::ostringstream status;
+   status << "Status: " << "ConfFile" << std::endl
+          << "Package:" << PackageName << std::endl
+          << "Percent: "  << (StepsDone/float(TotalSteps)*100.0) << std::endl
+          << "Message: " << ConfMessage << std::endl
+          << std::endl;
+   WriteToStatusFd(status.str());
+}
+
+
+bool PackageManagerProgressDeb822Fd::StatusChanged(std::string PackageName, 
+                                             unsigned int xStepsDone,
+                                             unsigned int xTotalSteps,
+                                             std::string message)
+{
+   StepsDone = xStepsDone;
+   StepsTotal = xTotalSteps;
+
+   // build the status str
+   std::ostringstream status;
+   status << "Status: " << "progress" << std::endl
+          << "Package: " << PackageName << std::endl
+          << "Percent: "  << (StepsDone/float(StepsTotal)*100.0) << std::endl
+          << "Message: " << message << std::endl
+          << std::endl;
+   WriteToStatusFd(status.str());
+
+   return true;
+}
+
+
+PackageManagerFancy::PackageManagerFancy()
+   : child_pty(-1)
+{
+   // setup terminal size
+   old_SIGWINCH = signal(SIGWINCH, PackageManagerFancy::staticSIGWINCH);
+   instances.push_back(this);
+}
+std::vector<PackageManagerFancy*> PackageManagerFancy::instances;
+
+PackageManagerFancy::~PackageManagerFancy()
+{
+   instances.erase(find(instances.begin(), instances.end(), this));
+   signal(SIGWINCH, old_SIGWINCH);
+}
+
+void PackageManagerFancy::staticSIGWINCH(int signum)
+{
+   std::vector<PackageManagerFancy *>::const_iterator I;
+   for(I = instances.begin(); I != instances.end(); ++I)
+      (*I)->HandleSIGWINCH(signum);
+}
+
+int PackageManagerFancy::GetNumberTerminalRows()
+{
+   struct winsize win;
+   // FIXME: get from "child_pty" instead?
+   if(ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&win) != 0)
+      return -1;
+
+   if(_config->FindB("Debug::InstallProgress::Fancy", false) == true)
+      std::cerr << "GetNumberTerminalRows: " << win.ws_row << std::endl;
+   
+   return win.ws_row;
+}
+
+void PackageManagerFancy::SetupTerminalScrollArea(int nr_rows)
+{
+     if(_config->FindB("Debug::InstallProgress::Fancy", false) == true)
+        std::cerr << "SetupTerminalScrollArea: " << nr_rows << std::endl;
+
+     // scroll down a bit to avoid visual glitch when the screen
+     // area shrinks by one row
+     std::cout << "\n";
+         
+     // save cursor
+     std::cout << "\033[s";
+         
+     // set scroll region (this will place the cursor in the top left)
+     std::cout << "\033[0;" << nr_rows - 1 << "r";
+            
+     // restore cursor but ensure its inside the scrolling area
+     std::cout << "\033[u";
+     static const char *move_cursor_up = "\033[1A";
+     std::cout << move_cursor_up;
+
+     // ensure its flushed
+     std::flush(std::cout);
+
+     // setup tty size to ensure xterm/linux console are working properly too
+     // see bug #731738
+     struct winsize win;
+     ioctl(child_pty, TIOCGWINSZ, (char *)&win);
+     win.ws_row = nr_rows - 1;
+     ioctl(child_pty, TIOCSWINSZ, (char *)&win);
+}
+
+void PackageManagerFancy::HandleSIGWINCH(int)
+{
+   int nr_terminal_rows = GetNumberTerminalRows();
+   SetupTerminalScrollArea(nr_terminal_rows);
+}
+
+void PackageManagerFancy::Start(int a_child_pty)
+{
+   child_pty = a_child_pty;
+   int nr_terminal_rows = GetNumberTerminalRows();
+   if (nr_terminal_rows > 0)
+      SetupTerminalScrollArea(nr_terminal_rows);
+}
+
+void PackageManagerFancy::Stop()
+{
+   int nr_terminal_rows = GetNumberTerminalRows();
+   if (nr_terminal_rows > 0)
+   {
+      SetupTerminalScrollArea(nr_terminal_rows + 1);
+
+      // override the progress line (sledgehammer)
+      static const char* clear_screen_below_cursor = "\033[J";
+      std::cout << clear_screen_below_cursor;
+   }
+   child_pty = -1;
+}
+
+bool PackageManagerFancy::StatusChanged(std::string PackageName, 
+                                        unsigned int StepsDone,
+                                        unsigned int TotalSteps,
+                                        std::string HumanReadableAction)
+{
+   if (!PackageManager::StatusChanged(PackageName, StepsDone, TotalSteps,
+          HumanReadableAction))
+      return false;
+
+   int row = GetNumberTerminalRows();
+
+   static string save_cursor = "\033[s";
+   static string restore_cursor = "\033[u";
+   
+   static string set_bg_color = "\033[42m"; // green
+   static string set_fg_color = "\033[30m"; // black
+   
+   static string restore_bg =  "\033[49m";
+   static string restore_fg = "\033[39m";
+   
+   std::cout << save_cursor
+      // move cursor position to last row
+             << "\033[" << row << ";0f" 
+             << set_bg_color
+             << set_fg_color
+             << progress_str
+             << restore_cursor
+             << restore_bg
+             << restore_fg;
+   std::flush(std::cout);
+   last_reported_progress = percentage;
+
+   return true;
+}
+
+bool PackageManagerText::StatusChanged(std::string PackageName, 
+                                       unsigned int StepsDone,
+                                       unsigned int TotalSteps,
+                                       std::string HumanReadableAction)
+{
+   if (!PackageManager::StatusChanged(PackageName, StepsDone, TotalSteps, HumanReadableAction))
+      return false;
+
+   std::cout << progress_str << "\r\n";
+   std::flush(std::cout);
+                   
+   last_reported_progress = percentage;
+
+   return true;
+}
+
+
+
+}; // namespace progress
+}; // namespace apt

+ 156 - 0
apt-pkg/install-progress.h

@@ -0,0 +1,156 @@
+#ifndef PKGLIB_IPROGRESS_H
+#define PKGLIB_IPROGRESS_H
+
+#include <string>
+#include <unistd.h>
+#include <signal.h>
+#include <vector>
+
+namespace APT {
+namespace Progress {
+
+ class PackageManager;
+ PackageManager* PackageManagerProgressFactory();
+
+ class PackageManager
+ {
+ private:
+    /** \brief dpointer placeholder */
+    void *d;
+
+ protected:
+    std::string progress_str;
+    float percentage;
+    int last_reported_progress;
+
+ public:
+    PackageManager() 
+       : percentage(0.0), last_reported_progress(-1) {};
+    virtual ~PackageManager() {};
+
+    /* Global Start/Stop */
+    virtual void Start(int child_pty=-1) {};
+    virtual void Stop() {};
+
+    /* When dpkg is invoked (may happen multiple times for each 
+     * install/remove block 
+    */
+    virtual void StartDpkg() {};
+
+    virtual pid_t fork() {return fork(); };
+
+    virtual void Pulse() {};
+    virtual long GetPulseInterval() {
+         return 500000;
+    };
+
+    virtual bool StatusChanged(std::string PackageName, 
+                               unsigned int StepsDone,
+                               unsigned int TotalSteps,
+                               std::string HumanReadableAction) ;
+    virtual void Error(std::string PackageName,                                
+                       unsigned int StepsDone,
+                       unsigned int TotalSteps,
+                       std::string ErrorMessage) {};
+    virtual void ConffilePrompt(std::string PackageName,
+                                unsigned int StepsDone,
+                                unsigned int TotalSteps,
+                                std::string ConfMessage) {};
+ };
+
+ class PackageManagerProgressFd : public PackageManager
+ {
+ protected:
+    int OutStatusFd;
+    int StepsDone;
+    int StepsTotal;
+    void WriteToStatusFd(std::string msg);
+
+ public:
+    PackageManagerProgressFd(int progress_fd);
+
+    virtual void StartDpkg();
+    virtual void Stop();
+
+    virtual bool StatusChanged(std::string PackageName, 
+                               unsigned int StepsDone,
+                               unsigned int TotalSteps,
+                               std::string HumanReadableAction);
+    virtual void Error(std::string PackageName,                                
+                       unsigned int StepsDone,
+                       unsigned int TotalSteps,
+                          std::string ErrorMessage);
+    virtual void ConffilePrompt(std::string PackageName,
+                                unsigned int StepsDone,
+                                unsigned int TotalSteps,
+                                   std::string ConfMessage);
+
+ };
+
+ class PackageManagerProgressDeb822Fd : public PackageManager
+ {
+ protected:
+    int OutStatusFd;
+    int StepsDone;
+    int StepsTotal;
+    void WriteToStatusFd(std::string msg);
+
+ public:
+    PackageManagerProgressDeb822Fd(int progress_fd);
+
+    virtual void StartDpkg();
+    virtual void Stop();
+
+    virtual bool StatusChanged(std::string PackageName, 
+                               unsigned int StepsDone,
+                               unsigned int TotalSteps,
+                               std::string HumanReadableAction);
+    virtual void Error(std::string PackageName,                                
+                       unsigned int StepsDone,
+                       unsigned int TotalSteps,
+                          std::string ErrorMessage);
+    virtual void ConffilePrompt(std::string PackageName,
+                                unsigned int StepsDone,
+                                unsigned int TotalSteps,
+                                   std::string ConfMessage);
+ };
+
+ class PackageManagerFancy : public PackageManager
+ {
+ private:
+    static void staticSIGWINCH(int);
+    static std::vector<PackageManagerFancy*> instances;
+
+ protected:
+    void SetupTerminalScrollArea(int nr_rows);
+    void HandleSIGWINCH(int);
+
+    int GetNumberTerminalRows();
+    sighandler_t old_SIGWINCH;
+    int child_pty;
+
+ public:
+    PackageManagerFancy();
+    ~PackageManagerFancy();
+    virtual void Start(int child_pty=-1);
+    virtual void Stop();
+    virtual bool StatusChanged(std::string PackageName, 
+                               unsigned int StepsDone,
+                               unsigned int TotalSteps,
+                               std::string HumanReadableAction);
+ };
+
+ class PackageManagerText : public PackageManager
+ {
+ public:
+    virtual bool StatusChanged(std::string PackageName, 
+                               unsigned int StepsDone,
+                               unsigned int TotalSteps,
+                               std::string HumanReadableAction);
+ };
+
+
+}; // namespace Progress
+}; // namespace APT
+
+#endif

+ 4 - 2
apt-pkg/makefile

@@ -43,7 +43,8 @@ SOURCE+= pkgcache.cc version.cc depcache.cc \
 	 srcrecords.cc cachefile.cc versionmatch.cc policy.cc \
 	 pkgsystem.cc indexfile.cc pkgcachegen.cc acquire-item.cc \
 	 indexrecords.cc vendor.cc vendorlist.cc cdrom.cc indexcopy.cc \
-	 aptconfiguration.cc cachefilter.cc cacheset.cc edsp.cc
+	 aptconfiguration.cc cachefilter.cc cacheset.cc edsp.cc \
+	 install-progress.cc upgrade.cc update.cc
 HEADERS+= algorithms.h depcache.h pkgcachegen.h cacheiterators.h \
 	  orderlist.h sourcelist.h packagemanager.h tagfile.h \
 	  init.h pkgcache.h version.h progress.h pkgrecords.h \
@@ -51,7 +52,8 @@ HEADERS+= algorithms.h depcache.h pkgcachegen.h cacheiterators.h \
 	  clean.h srcrecords.h cachefile.h versionmatch.h policy.h \
 	  pkgsystem.h indexfile.h metaindex.h indexrecords.h vendor.h \
 	  vendorlist.h cdrom.h indexcopy.h aptconfiguration.h \
-	  cachefilter.h cacheset.h edsp.h
+	  cachefilter.h cacheset.h edsp.h install-progress.h \
+	  upgrade.h update.h
 
 # Source code for the debian specific components
 # In theory the deb headers do not need to be exported..

+ 17 - 7
apt-pkg/metaindex.h

@@ -5,6 +5,7 @@
 #include <string>
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/indexfile.h>
+#include <apt-pkg/init.h>
 
 #ifndef APT_8_CLEANER_HEADERS
 #include <apt-pkg/srcrecords.h>
@@ -28,27 +29,36 @@ class metaIndex
 
    public:
 
-   
    // Various accessors
    virtual std::string GetURI() const {return URI;}
    virtual std::string GetDist() const {return Dist;}
    virtual const char* GetType() const {return Type;}
 
+   // interface to to query it
+#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
+   // returns the path of the local file (or "" if its not available)
+   virtual std::string LocalFileName() const {return "";};
+#endif
+
    // Interface for acquire
-   virtual std::string ArchiveURI(std::string const& /*File*/) const = 0;
+   virtual std::string ArchiveURI(std::string const& File) const = 0;
    virtual bool GetIndexes(pkgAcquire *Owner, bool const &GetAll=false) const = 0;
-   
    virtual std::vector<pkgIndexFile *> *GetIndexFiles() = 0; 
    virtual bool IsTrusted() const = 0;
 
-   metaIndex(std::string const &URI, std::string const &Dist, char const * const Type) :
-		Indexes(NULL), Type(Type), URI(URI), Dist(Dist) {
+   metaIndex(std::string const &URI, std::string const &Dist, 
+             char const * const Type) 
+      : Indexes(NULL), Type(Type), URI(URI), Dist(Dist)
+   {
+      /* nothing */
    }
 
-   virtual ~metaIndex() {
+   virtual ~metaIndex() 
+   {
       if (Indexes == 0)
 	 return;
-      for (std::vector<pkgIndexFile *>::iterator I = (*Indexes).begin(); I != (*Indexes).end(); ++I)
+      for (std::vector<pkgIndexFile *>::iterator I = (*Indexes).begin();
+           I != (*Indexes).end(); ++I)
 	 delete *I;
       delete Indexes;
    }

+ 4 - 4
apt-pkg/orderlist.cc

@@ -566,10 +566,10 @@ bool pkgOrderList::VisitProvides(DepIterator D,bool Critical)
 // ---------------------------------------------------------------------
 /* This is the core ordering routine. It calls the set dependency
    consideration functions which then potentialy call this again. Finite
-   depth is achived through the colouring mechinism. */
+   depth is achieved through the colouring mechinism. */
 bool pkgOrderList::VisitNode(PkgIterator Pkg, char const* from)
 {
-   // Looping or irrelevent.
+   // Looping or irrelevant.
    // This should probably trancend not installed packages
    if (Pkg.end() == true || IsFlag(Pkg,Added) == true || 
        IsFlag(Pkg,AddPending) == true || IsFlag(Pkg,InList) == false)
@@ -824,7 +824,7 @@ bool pkgOrderList::DepUnPackPre(DepIterator D)
    The forwards depends loop is designed to bring the packages dependents
    close to the package. This helps reduce deconfigure time. 
    
-   Loops are irrelevent to this. */
+   Loops are irrelevant to this. */
 bool pkgOrderList::DepUnPackDep(DepIterator D)
 {
    
@@ -840,7 +840,7 @@ bool pkgOrderList::DepUnPackDep(DepIterator D)
 		D.ParentPkg().CurrentVer() != D.ParentVer())
 	       continue;
 
-	    // The dep will not break so it is irrelevent.
+	    // The dep will not break so it is irrelevant.
 	    if (CheckDep(D) == true)
 	       continue;
 	    

+ 66 - 21
apt-pkg/packagemanager.cc

@@ -26,7 +26,6 @@
 #include <apt-pkg/sptr.h>
 
 #include <iostream>
-#include <fcntl.h>
 
 #include <apti18n.h>
 									/*}}}*/
@@ -216,7 +215,7 @@ bool pkgPackageManager::CreateOrderList()
    return true;
 }
 									/*}}}*/
-// PM::DepAlwaysTrue - Returns true if this dep is irrelevent		/*{{{*/
+// PM::DepAlwaysTrue - Returns true if this dep is irrelevant		/*{{{*/
 // ---------------------------------------------------------------------
 /* The restriction on provides is to eliminate the case when provides
    are transitioning between valid states [ie exim to smail] */
@@ -244,11 +243,11 @@ bool pkgPackageManager::CheckRConflicts(PkgIterator Pkg,DepIterator D,
 	  D->Type != pkgCache::Dep::Obsoletes)
 	 continue;
 
-      // The package hasnt been changed
+      // The package hasn't been changed
       if (List->IsNow(Pkg) == false)
 	 continue;
       
-      // Ignore self conflicts, ignore conflicts from irrelevent versions
+      // Ignore self conflicts, ignore conflicts from irrelevant versions
       if (D.IsIgnorable(Pkg) || D.ParentVer() != D.ParentPkg().CurrentVer())
 	 continue;
       
@@ -315,7 +314,7 @@ bool pkgPackageManager::ConfigureAll()
    
    Note on failure: This method can fail, without causing any problems. 
    This can happen when using Immediate-Configure-All, SmartUnPack may call
-   SmartConfigure, it may fail because of a complex dependancy situation, but
+   SmartConfigure, it may fail because of a complex dependency situation, but
    a error will only be reported if ConfigureAll fails. This is why some of the
    messages this function reports on failure (return false;) as just warnings
    only shown when debuging*/
@@ -597,7 +596,7 @@ bool pkgPackageManager::SmartRemove(PkgIterator Pkg)
 									/*}}}*/
 // PM::SmartUnPack - Install helper					/*{{{*/
 // ---------------------------------------------------------------------
-/* This puts the system in a state where it can Unpack Pkg, if Pkg is allready
+/* This puts the system in a state where it can Unpack Pkg, if Pkg is already
    unpacked, or when it has been unpacked, if Immediate==true it configures it. */
 bool pkgPackageManager::SmartUnPack(PkgIterator Pkg)
 {
@@ -624,7 +623,7 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c
    /* PreUnpack Checks: This loop checks and attempts to rectify and problems that would prevent the package being unpacked.
       It addresses: PreDepends, Conflicts, Obsoletes and Breaks (DpkgBreaks). Any resolutions that do not require it should
       avoid configuration (calling SmartUnpack with Immediate=true), this is because when unpacking some packages with
-      complex dependancy structures, trying to configure some packages while breaking the loops can complicate things .
+      complex dependency structures, trying to configure some packages while breaking the loops can complicate things .
       This will be either dealt with if the package is configured as a dependency of Pkg (if and when Pkg is configured),
       or by the ConfigureAll call at the end of the for loop in OrderInstall. */
    bool Changed = false;
@@ -791,7 +790,7 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c
 	       {
 		  if (List->IsFlag(BrokenPkg,pkgOrderList::Loop) && PkgLoop)
 		  {
-		     // This dependancy has already been dealt with by another SmartUnPack on Pkg
+		     // This dependency has already been dealt with by another SmartUnPack on Pkg
 		     break;
 		  }
 		  else
@@ -1004,7 +1003,7 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall()
       DoneSomething = true;
       
       if (ImmConfigureAll) {
-         /* ConfigureAll here to pick up and packages left unconfigured becuase they were unpacked in the 
+         /* ConfigureAll here to pick up and packages left unconfigured because they were unpacked in the
             "PreUnpack Checks" section */
          if (!ConfigureAll())
             return Failed; 
@@ -1027,33 +1026,79 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall()
    }
 	 
    return Completed;
+}
+// PM::DoInstallPostFork - compat /*{{{*/
+// ---------------------------------------------------------------------
+									/*}}}*/
+#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
+pkgPackageManager::OrderResult
+pkgPackageManager::DoInstallPostFork(int statusFd)
+{
+   APT::Progress::PackageManager *progress = new
+      APT::Progress::PackageManagerProgressFd(statusFd);
+   pkgPackageManager::OrderResult res = DoInstallPostFork(progress);
+   delete progress;
+   return res;
 }
 									/*}}}*/
 // PM::DoInstallPostFork - Does install part that happens after the fork /*{{{*/
 // ---------------------------------------------------------------------
 pkgPackageManager::OrderResult 
-pkgPackageManager::DoInstallPostFork(int statusFd)
+pkgPackageManager::DoInstallPostFork(APT::Progress::PackageManager *progress)
 {
-      if(statusFd > 0)
-         // FIXME: use SetCloseExec here once it taught about throwing
-	 //        exceptions instead of doing _exit(100) on failure
-	 fcntl(statusFd,F_SETFD,FD_CLOEXEC); 
-      bool goResult = Go(statusFd);
-      if(goResult == false) 
-	 return Failed;
-
-      return Res;
+   bool goResult = Go(progress);
+   if(goResult == false) 
+      return Failed;
+   
+   return Res;
 };
+#else
+pkgPackageManager::OrderResult
+pkgPackageManager::DoInstallPostFork(int statusFd)
+{
+   bool goResult = Go(statusFd);
+   if(goResult == false) 
+      return Failed;
+   
+   return Res;
+}
+#endif
+									/*}}}*/	
+// PM::DoInstall - Does the installation				/*{{{*/
+// ---------------------------------------------------------------------
+/* compat */
+#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
+pkgPackageManager::OrderResult 
+pkgPackageManager::DoInstall(int statusFd)
+{
+    APT::Progress::PackageManager *progress = new
+       APT::Progress::PackageManagerProgressFd(statusFd);
+    OrderResult res = DoInstall(progress);
+    delete progress;
+    return res;
+ }
+#else
+pkgPackageManager::OrderResult pkgPackageManager::DoInstall(int statusFd)
+{
+   if(DoInstallPreFork() == Failed)
+      return Failed;
 
+   return DoInstallPostFork(statusFd);
+}
+#endif
+									/*}}}*/	
 // PM::DoInstall - Does the installation				/*{{{*/
 // ---------------------------------------------------------------------
 /* This uses the filenames in FileNames and the information in the
    DepCache to perform the installation of packages.*/
-pkgPackageManager::OrderResult pkgPackageManager::DoInstall(int statusFd)
+#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
+pkgPackageManager::OrderResult 
+pkgPackageManager::DoInstall(APT::Progress::PackageManager *progress)
 {
    if(DoInstallPreFork() == Failed)
       return Failed;
    
-   return DoInstallPostFork(statusFd);
+   return DoInstallPostFork(progress);
 }
+#endif
 									/*}}}*/	      

+ 24 - 1
apt-pkg/packagemanager.h

@@ -23,7 +23,10 @@
 #ifndef PKGLIB_PACKAGEMANAGER_H
 #define PKGLIB_PACKAGEMANAGER_H
 
+#include <apt-pkg/macros.h>
 #include <apt-pkg/pkgcache.h>
+#include <apt-pkg/install-progress.h>
+#include <apt-pkg/init.h>
 
 #include <string>
 #include <iostream>
@@ -39,6 +42,8 @@ class pkgDepCache;
 class pkgSourceList;
 class pkgOrderList;
 class pkgRecords;
+
+
 class pkgPackageManager : protected pkgCache::Namespace
 {
    public:
@@ -83,7 +88,12 @@ class pkgPackageManager : protected pkgCache::Namespace
    virtual bool Install(PkgIterator /*Pkg*/,std::string /*File*/) {return false;};
    virtual bool Configure(PkgIterator /*Pkg*/) {return false;};
    virtual bool Remove(PkgIterator /*Pkg*/,bool /*Purge*/=false) {return false;};
+#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
+   virtual bool Go(APT::Progress::PackageManager *progress) {return true;};
+#else
    virtual bool Go(int statusFd=-1) {return true;};
+#endif
+
    virtual void Reset() {};
 
    // the result of the operation
@@ -96,7 +106,13 @@ class pkgPackageManager : protected pkgCache::Namespace
 		    pkgRecords *Recs);
 
    // Do the installation 
+#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
+   OrderResult DoInstall(APT::Progress::PackageManager *progress);
+   // compat
+   __deprecated OrderResult DoInstall(int statusFd=-1);
+#else
    OrderResult DoInstall(int statusFd=-1);
+#endif
 
    // stuff that needs to be done before the fork() of a library that
    // uses apt
@@ -104,9 +120,16 @@ class pkgPackageManager : protected pkgCache::Namespace
       Res = OrderInstall();
       return Res;
    };
-
+#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
    // stuff that needs to be done after the fork
+   OrderResult DoInstallPostFork(APT::Progress::PackageManager *progress);
+   // compat
+   __deprecated OrderResult DoInstallPostFork(int statusFd=-1);
+#else
    OrderResult DoInstallPostFork(int statusFd=-1);
+#endif
+
+   // ?
    bool FixMissing();
 
    /** \brief returns all packages dpkg let disappear */

+ 2 - 2
apt-pkg/pkgcache.cc

@@ -8,7 +8,7 @@
    Please see doc/apt-pkg/cache.sgml for a more detailed description of 
    this format. Also be sure to keep that file up-to-date!!
    
-   This is the general utility functions for cache managment. They provide
+   This is the general utility functions for cache management. They provide
    a complete set of accessor functions for the cache. The cacheiterators
    header contains the STL-like iterators that can be used to easially
    navigate the cache as well as seemlessly dereference the mmap'd 
@@ -499,7 +499,7 @@ pkgCache::PkgIterator::CurVersion() const
 // ostream operator to handle string representation of a package	/*{{{*/
 // ---------------------------------------------------------------------
 /* Output name < cur.rent.version -> candid.ate.version | new.est.version > (section)
-   Note that the characters <|>() are all literal above. Versions will be ommited
+   Note that the characters <|>() are all literal above. Versions will be omitted
    if they provide no new information (e.g. there is no newer version than candidate)
    If no version and/or section can be found "none" is used. */
 std::ostream& 

+ 1 - 1
apt-pkg/pkgcache.h

@@ -354,7 +354,7 @@ struct pkgCache::Group
     the hash index of the name in the pkgCache::Header::PkgHashTable
 
     A package can be created for every architecture so package names are
-    not unique, but it is garanteed that packages with the same name
+    not unique, but it is guaranteed that packages with the same name
     are sequencel ordered in the list. Packages with the same name can be
     accessed with the Group.
 */

+ 2 - 2
apt-pkg/pkgsystem.h

@@ -7,7 +7,7 @@
    
    Instances of this class can be thought of as factories or meta-classes
    for a variety of more specialized classes. Together this class and 
-   it's speciallized offspring completely define the environment and how
+   it's specialized offspring completely define the environment and how
    to access resources for a specific system. There are several sub
    areas that are all orthogonal - each system has a unique combination of
    these sub areas:
@@ -23,7 +23,7 @@
        - Selection of local 'status' indexes that make up the pkgCache.
       
    It is important to note that the handling of index files is not a 
-   function of the system. Index files are handled through a seperate 
+   function of the system. Index files are handled through a separate
    abstraction - the only requirement is that the index files have the
    same idea of versioning as the target system.
    

+ 4 - 0
apt-pkg/policy.cc

@@ -405,6 +405,10 @@ bool ReadPinFile(pkgPolicy &Plcy,string File)
    PreferenceSection Tags;
    while (TF.Step(Tags) == true)
    {
+      // can happen when there are only comments in a record
+      if (Tags.Count() == 0)
+         continue;
+
       string Name = Tags.FindS("Package");
       if (Name.empty() == true)
 	 return _error->Error(_("Invalid record in the preferences file %s, no Package header"), File.c_str());

+ 131 - 10
apt-pkg/sourcelist.cc

@@ -17,8 +17,10 @@
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/metaindex.h>
 #include <apt-pkg/indexfile.h>
+#include <apt-pkg/tagfile.h>
 
 #include <fstream>
+#include <algorithm>
 
 #include <apti18n.h>
 									/*}}}*/
@@ -70,6 +72,69 @@ bool pkgSourceList::Type::FixupURI(string &URI) const
    return true;
 }
 									/*}}}*/
+bool pkgSourceList::Type::ParseStanza(vector<metaIndex *> &List,
+                                      pkgTagSection &Tags,
+                                      int i,
+                                      FileFd &Fd)
+{
+   map<string, string> Options;
+
+   string Enabled = Tags.FindS("Enabled");
+   if (Enabled.size() > 0 && StringToBool(Enabled) == false)
+      return true;
+   
+   // Define external/internal options
+   const char* option_deb822[] = { 
+      "Architectures", "Architectures-Add", "Architectures-Remove", "Trusted",
+   };
+   const char* option_internal[] = { 
+      "arch", "arch+", "arch-", "trusted",
+   };
+   for (unsigned int j=0; j < sizeof(option_deb822)/sizeof(char*); j++)
+      if (Tags.Exists(option_deb822[j]))
+      {
+         // for deb822 the " " is the delimiter, but the backend expects ","
+         std::string option = Tags.FindS(option_deb822[j]);
+         std::replace(option.begin(), option.end(), ' ', ',');
+         Options[option_internal[j]] = option;
+      }
+   
+   // now create one item per suite/section
+   string Suite = Tags.FindS("Suites");
+   Suite = SubstVar(Suite,"$(ARCH)",_config->Find("APT::Architecture"));
+   string const Section = Tags.FindS("Sections");
+   string URIS = Tags.FindS("URIs");
+
+   std::vector<std::string> list_uris = StringSplit(URIS, " ");
+   std::vector<std::string> list_dist = StringSplit(Suite, " ");
+   std::vector<std::string> list_section = StringSplit(Section, " ");
+   
+   for (std::vector<std::string>::const_iterator U = list_uris.begin();
+        U != list_uris.end(); U++)
+   {
+      std::string URI = (*U);
+      if (!FixupURI(URI))
+      {
+         _error->Error(_("Malformed stanza %u in source list %s (URI parse)"),i,Fd.Name().c_str());
+         return false;
+      }
+
+      for (std::vector<std::string>::const_iterator I = list_dist.begin();
+           I != list_dist.end(); I++)
+      {
+         for (std::vector<std::string>::const_iterator J = list_section.begin();
+              J != list_section.end(); J++)
+         {
+            if (CreateItem(List, URI, (*I), (*J), Options) == false)
+            {
+               return false;
+            }
+         }
+      }
+   }
+   return true;
+}
+
 // Type::ParseLine - Parse a single line				/*{{{*/
 // ---------------------------------------------------------------------
 /* This is a generic one that is the 'usual' format for sources.list
@@ -159,7 +224,6 @@ bool pkgSourceList::Type::ParseLine(vector<metaIndex *> &List,
    return true;
 }
 									/*}}}*/
-
 // SourceList::pkgSourceList - Constructors				/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -181,7 +245,6 @@ pkgSourceList::~pkgSourceList()
       delete *I;
 }
 									/*}}}*/
-									/*}}}*/
 // SourceList::ReadMainList - Read the main source list from etc	/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -216,7 +279,6 @@ bool pkgSourceList::ReadMainList()
    return Res;
 }
 									/*}}}*/
-// CNC:2003-03-03 - Needed to preserve backwards compatibility.
 // SourceList::Reset - Clear the sourcelist contents			/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -227,7 +289,6 @@ void pkgSourceList::Reset()
    SrcList.erase(SrcList.begin(),SrcList.end());
 }
 									/*}}}*/
-// CNC:2003-03-03 - Function moved to ReadAppend() and Reset().
 // SourceList::Read - Parse the sourcelist file				/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -241,17 +302,29 @@ bool pkgSourceList::Read(string File)
 // ---------------------------------------------------------------------
 /* */
 bool pkgSourceList::ReadAppend(string File)
+{
+   if (_config->FindB("APT::Sources::Use-Deb822", false) == true)
+   {
+      int lines_parsed =ParseFileDeb822(File);
+      if (lines_parsed < 0)
+         return false;
+      else if (lines_parsed > 0)
+         return true;
+      // no lines parsed  ... fall through and use old style parser
+   }
+   return ParseFileOldStyle(File);
+}
+
+// SourceList::ReadFileOldStyle - Read Traditional style sources.list 	/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool pkgSourceList::ParseFileOldStyle(string File)
 {
    // Open the stream for reading
    ifstream F(File.c_str(),ios::in /*| ios::nocreate*/);
    if (!F != 0)
       return _error->Errno("ifstream::ifstream",_("Opening %s"),File.c_str());
-   
-#if 0 // Now Reset() does this.
-   for (const_iterator I = SrcList.begin(); I != SrcList.end(); I++)
-      delete *I;
-   SrcList.erase(SrcList.begin(),SrcList.end());
-#endif
+
    // CNC:2003-12-10 - 300 is too short.
    char Buffer[1024];
 
@@ -298,6 +371,54 @@ bool pkgSourceList::ReadAppend(string File)
    return true;
 }
 									/*}}}*/
+// SourceList::ParseFileDeb822 - Parse deb822 style sources.list 	/*{{{*/
+// ---------------------------------------------------------------------
+/* Returns: the number of stanzas parsed*/
+int pkgSourceList::ParseFileDeb822(string File)
+{
+   pkgTagSection Tags;
+   unsigned int i=0;
+
+   // see if we can read the file
+   _error->PushToStack();
+   FileFd Fd(File, FileFd::ReadOnly);
+   pkgTagFile Sources(&Fd);
+   if (_error->PendingError() == true)
+   {
+      _error->RevertToStack();
+      return 0;
+   }
+   _error->MergeWithStack();
+   
+   // read step by step
+   while (Sources.Step(Tags) == true)
+   {
+      if(!Tags.Exists("Types")) 
+         continue;
+
+      string const types = Tags.FindS("Types");
+      std::vector<std::string> list_types = StringSplit(types, " ");
+      for (std::vector<std::string>::const_iterator I = list_types.begin();
+        I != list_types.end(); I++)
+      {
+         Type *Parse = Type::GetType((*I).c_str());
+         if (Parse == 0)
+         {
+            _error->Error(_("Type '%s' is not known on stanza %u in source list %s"), (*I).c_str(),i,Fd.Name().c_str());
+            return -1;
+         }
+         
+         if (!Parse->ParseStanza(SrcList, Tags, i, Fd))
+            return -1;
+
+         i++;
+      }
+   }
+
+   // we are done, return the number of stanzas read
+   return i;
+}
+									/*}}}*/
 // SourceList::FindIndex - Get the index associated with a file		/*{{{*/
 // ---------------------------------------------------------------------
 /* */

+ 9 - 1
apt-pkg/sourcelist.h

@@ -31,6 +31,7 @@
 #include <vector>
 #include <map>
 #include <apt-pkg/pkgcache.h>
+#include <apt-pkg/tagfile.h>
 
 #ifndef APT_8_CLEANER_HEADERS
 #include <apt-pkg/metaindex.h>
@@ -60,6 +61,10 @@ class pkgSourceList
       const char *Label;
 
       bool FixupURI(std::string &URI) const;
+      virtual bool ParseStanza(std::vector<metaIndex *> &List,
+                               pkgTagSection &Tags,
+                               int stanza_n,
+                               FileFd &Fd);
       virtual bool ParseLine(std::vector<metaIndex *> &List,
 			     const char *Buffer,
 			     unsigned long const &CurLine,std::string const &File) const;
@@ -75,7 +80,10 @@ class pkgSourceList
    protected:
 
    std::vector<metaIndex *> SrcList;
-   
+
+   int ParseFileDeb822(std::string File);
+   bool ParseFileOldStyle(std::string File);
+
    public:
 
    bool ReadMainList();

+ 3 - 2
apt-pkg/srcrecords.cc

@@ -70,8 +70,9 @@ bool pkgSrcRecords::Restart()
    Current = Files.begin();
    for (std::vector<Parser*>::iterator I = Files.begin();
         I != Files.end(); ++I)
-      (*I)->Restart();
-   
+      if ((*I)->Offset() != 0)
+	 (*I)->Restart();
+
    return true;
 }
 									/*}}}*/

+ 68 - 45
apt-pkg/tagfile.cc

@@ -164,7 +164,7 @@ bool pkgTagFile::Fill()
       unsigned long long const dataSize = d->Size - ((d->End - d->Buffer) + 1);
       if (d->Fd.Read(d->End, dataSize, &Actual) == false)
 	 return false;
-      if (Actual != dataSize || d->Fd.Eof() == true)
+      if (Actual != dataSize)
 	 d->Done = true;
       d->End += Actual;
    }
@@ -207,7 +207,11 @@ bool pkgTagFile::Jump(pkgTagSection &Tag,unsigned long long Offset)
       unsigned long long Dist = Offset - d->iOffset;
       d->Start += Dist;
       d->iOffset += Dist;
-      return Step(Tag);
+      // if we have seen the end, don't ask for more
+      if (d->Done == true)
+	 return Tag.Scan(d->Start, d->End - d->Start);
+      else
+	 return Step(Tag);
    }
 
    // Reposition and reload..
@@ -233,6 +237,16 @@ bool pkgTagFile::Jump(pkgTagSection &Tag,unsigned long long Offset)
    return true;
 }
 									/*}}}*/
+// pkgTagSection::pkgTagSection - Constructor				/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+pkgTagSection::pkgTagSection()
+   : Section(0), TagCount(0), d(NULL), Stop(0)
+{
+   memset(&Indexes, 0, sizeof(Indexes));
+   memset(&AlphaIndexes, 0, sizeof(AlphaIndexes));
+}
+									/*}}}*/
 // TagSection::Scan - Scan for the end of the header information	/*{{{*/
 // ---------------------------------------------------------------------
 /* This looks for the first double new line in the data stream.
@@ -249,7 +263,12 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength)
    TagCount = 0;
    while (TagCount+1 < sizeof(Indexes)/sizeof(Indexes[0]) && Stop < End)
    {
-       TrimRecord(true,End);
+      TrimRecord(true,End);
+
+      // this can happen when TrimRecord trims away the entire Record
+      // (e.g. because it just contains comments)
+      if(Stop == End)
+         return true;
 
       // Start a new index and add it to the hash
       if (isspace(Stop[0]) == 0)
@@ -263,7 +282,9 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength)
       if (Stop == 0)
 	 return false;
 
-      for (; Stop+1 < End && Stop[1] == '\r'; Stop++);
+      for (; Stop+1 < End && Stop[1] == '\r'; Stop++)
+         /* nothing */
+         ;
 
       // Double newline marks the end of the record
       if (Stop+1 < End && Stop[1] == '\n')
@@ -550,52 +571,54 @@ bool TFRewrite(FILE *Output,pkgTagSection const &Tags,const char *Order[],
    }
    
    // Write all all of the tags, in order.
-   for (unsigned int I = 0; Order[I] != 0; I++)
+   if (Order != NULL)
    {
-      bool Rewritten = false;
-      
-      // See if this is a field that needs to be rewritten
-      for (unsigned int J = 0; Rewrite != 0 && Rewrite[J].Tag != 0; J++)
+      for (unsigned int I = 0; Order[I] != 0; I++)
       {
-	 if (strcasecmp(Rewrite[J].Tag,Order[I]) == 0)
-	 {
-	    Visited[J] |= 2;
-	    if (Rewrite[J].Rewrite != 0 && Rewrite[J].Rewrite[0] != 0)
-	    {
-	       if (isspace(Rewrite[J].Rewrite[0]))
-		  fprintf(Output,"%s:%s\n",Rewrite[J].NewTag,Rewrite[J].Rewrite);
-	       else
-		  fprintf(Output,"%s: %s\n",Rewrite[J].NewTag,Rewrite[J].Rewrite);
-	    }
+         bool Rewritten = false;
+         
+         // See if this is a field that needs to be rewritten
+         for (unsigned int J = 0; Rewrite != 0 && Rewrite[J].Tag != 0; J++)
+         {
+            if (strcasecmp(Rewrite[J].Tag,Order[I]) == 0)
+            {
+               Visited[J] |= 2;
+               if (Rewrite[J].Rewrite != 0 && Rewrite[J].Rewrite[0] != 0)
+               {
+                  if (isspace(Rewrite[J].Rewrite[0]))
+                     fprintf(Output,"%s:%s\n",Rewrite[J].NewTag,Rewrite[J].Rewrite);
+                  else
+                     fprintf(Output,"%s: %s\n",Rewrite[J].NewTag,Rewrite[J].Rewrite);
+               }
+               Rewritten = true;
+               break;
+            }
+         }
 	    
-	    Rewritten = true;
-	    break;
-	 }
-      }      
-	    
-      // See if it is in the fragment
-      unsigned Pos;
-      if (Tags.Find(Order[I],Pos) == false)
-	 continue;
-      Visited[Pos] |= 1;
-
-      if (Rewritten == true)
-	 continue;
+         // See if it is in the fragment
+         unsigned Pos;
+         if (Tags.Find(Order[I],Pos) == false)
+            continue;
+         Visited[Pos] |= 1;
+
+         if (Rewritten == true)
+            continue;
       
-      /* Write out this element, taking a moment to rewrite the tag
-         in case of changes of case. */
-      const char *Start;
-      const char *Stop;
-      Tags.Get(Start,Stop,Pos);
+         /* Write out this element, taking a moment to rewrite the tag
+            in case of changes of case. */
+         const char *Start;
+         const char *Stop;
+         Tags.Get(Start,Stop,Pos);
       
-      if (fputs(Order[I],Output) < 0)
-	 return _error->Errno("fputs","IO Error to output");
-      Start += strlen(Order[I]);
-      if (fwrite(Start,Stop - Start,1,Output) != 1)
-	 return _error->Errno("fwrite","IO Error to output");
-      if (Stop[-1] != '\n')
-	 fprintf(Output,"\n");
-   }   
+         if (fputs(Order[I],Output) < 0)
+            return _error->Errno("fputs","IO Error to output");
+         Start += strlen(Order[I]);
+         if (fwrite(Start,Stop - Start,1,Output) != 1)
+            return _error->Errno("fwrite","IO Error to output");
+         if (Stop[-1] != '\n')
+            fprintf(Output,"\n");
+      }
+   }
 
    // Now write all the old tags that were missed.
    for (unsigned int I = 0; I != Tags.Count(); I++)

+ 1 - 1
apt-pkg/tagfile.h

@@ -84,7 +84,7 @@ class pkgTagSection
       Stop = this->Stop;
    };
    
-   pkgTagSection() : Section(0), TagCount(0), d(NULL), Stop(0) {};
+   pkgTagSection();
    virtual ~pkgTagSection() {};
 };
 

+ 126 - 0
apt-pkg/update.cc

@@ -0,0 +1,126 @@
+
+// Include Files							/*{{{*/
+#include <config.h>
+
+#include <apt-pkg/algorithms.h>
+#include <apt-pkg/update.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/version.h>
+#include <apt-pkg/sptr.h>
+#include <apt-pkg/acquire-item.h>
+#include <apt-pkg/edsp.h>
+#include <apt-pkg/sourcelist.h>
+#include <apt-pkg/fileutl.h>
+#include <apt-pkg/progress.h>
+
+#include <sys/types.h>
+#include <cstdlib>
+#include <algorithm>
+#include <iostream>
+#include <stdio.h>
+
+#include <apti18n.h>
+									/*}}}*/
+
+using namespace std;
+
+// ListUpdate - construct Fetcher and update the cache files		/*{{{*/
+// ---------------------------------------------------------------------
+/* This is a simple wrapper to update the cache. it will fetch stuff
+ * from the network (or any other sources defined in sources.list)
+ */
+bool ListUpdate(pkgAcquireStatus &Stat, 
+		pkgSourceList &List, 
+		int PulseInterval)
+{
+   pkgAcquire Fetcher;
+   if (Fetcher.Setup(&Stat, _config->FindDir("Dir::State::Lists")) == false)
+      return false;
+
+   // Populate it with the source selection
+   if (List.GetIndexes(&Fetcher) == false)
+	 return false;
+
+   return AcquireUpdate(Fetcher, PulseInterval, true);
+}
+									/*}}}*/
+// AcquireUpdate - take Fetcher and update the cache files		/*{{{*/
+// ---------------------------------------------------------------------
+/* This is a simple wrapper to update the cache with a provided acquire
+ * If you only need control over Status and the used SourcesList use
+ * ListUpdate method instead.
+ */
+bool AcquireUpdate(pkgAcquire &Fetcher, int const PulseInterval,
+		   bool const RunUpdateScripts, bool const ListCleanup)
+{
+   // Run scripts
+   if (RunUpdateScripts == true)
+      RunScripts("APT::Update::Pre-Invoke");
+
+   pkgAcquire::RunResult res;
+   if(PulseInterval > 0)
+      res = Fetcher.Run(PulseInterval);
+   else
+      res = Fetcher.Run();
+
+   if (res == pkgAcquire::Failed)
+      return false;
+
+   bool Failed = false;
+   bool TransientNetworkFailure = false;
+   for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); 
+	I != Fetcher.ItemsEnd(); ++I)
+   {
+      if ((*I)->Status == pkgAcquire::Item::StatDone)
+	 continue;
+
+      (*I)->Finished();
+
+      ::URI uri((*I)->DescURI());
+      uri.User.clear();
+      uri.Password.clear();
+      string descUri = string(uri);
+      _error->Warning(_("Failed to fetch %s  %s\n"), descUri.c_str(),
+	      (*I)->ErrorText.c_str());
+
+      if ((*I)->Status == pkgAcquire::Item::StatTransientNetworkError) 
+      {
+	 TransientNetworkFailure = true;
+	 continue;
+      }
+
+      Failed = true;
+   }
+   
+   // Clean out any old list files
+   // Keep "APT::Get::List-Cleanup" name for compatibility, but
+   // this is really a global option for the APT library now
+   if (!TransientNetworkFailure && !Failed && ListCleanup == true &&
+       (_config->FindB("APT::Get::List-Cleanup",true) == true &&
+	_config->FindB("APT::List-Cleanup",true) == true))
+   {
+      if (Fetcher.Clean(_config->FindDir("Dir::State::lists")) == false ||
+	  Fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/") == false)
+	 // something went wrong with the clean
+	 return false;
+   }
+   
+   if (TransientNetworkFailure == true)
+      _error->Warning(_("Some index files failed to download. They have been ignored, or old ones used instead."));
+   else if (Failed == true)
+      return _error->Error(_("Some index files failed to download. They have been ignored, or old ones used instead."));
+
+
+   // Run the success scripts if all was fine
+   if (RunUpdateScripts == true)
+   {
+      if(!TransientNetworkFailure && !Failed)
+	 RunScripts("APT::Update::Post-Invoke-Success");
+
+      // Run the other scripts
+      RunScripts("APT::Update::Post-Invoke");
+   }
+   return true;
+}
+									/*}}}*/

+ 21 - 0
apt-pkg/update.h

@@ -0,0 +1,21 @@
+// -*- mode: cpp; mode: fold -*-
+// Description								/*{{{*/
+/* ######################################################################
+
+   Update - ListUpdate releated code
+   
+   ##################################################################### */
+									/*}}}*/
+
+#ifndef PKGLIB_UPDATE_H
+#define PKGLIB_UPDATE_H
+
+class pkgAcquireStatus;
+
+
+bool ListUpdate(pkgAcquireStatus &progress, pkgSourceList &List, int PulseInterval=0);
+bool AcquireUpdate(pkgAcquire &Fetcher, int const PulseInterval = 0,
+		   bool const RunUpdateScripts = true, bool const ListCleanup = true);
+
+
+#endif

+ 263 - 0
apt-pkg/upgrade.cc

@@ -0,0 +1,263 @@
+
+// Include Files							/*{{{*/
+#include <config.h>
+
+#include <apt-pkg/algorithms.h>
+#include <apt-pkg/upgrade.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/version.h>
+#include <apt-pkg/sptr.h>
+#include <apt-pkg/acquire-item.h>
+#include <apt-pkg/edsp.h>
+#include <apt-pkg/sourcelist.h>
+#include <apt-pkg/fileutl.h>
+#include <apt-pkg/progress.h>
+
+#include <sys/types.h>
+#include <cstdlib>
+#include <algorithm>
+#include <iostream>
+#include <stdio.h>
+
+#include <apti18n.h>
+									/*}}}*/
+
+// DistUpgrade - Distribution upgrade					/*{{{*/
+// ---------------------------------------------------------------------
+/* This autoinstalls every package and then force installs every 
+   pre-existing package. This creates the initial set of conditions which 
+   most likely contain problems because too many things were installed.
+   
+   The problem resolver is used to resolve the problems.
+ */
+bool pkgDistUpgrade(pkgDepCache &Cache)
+{
+   std::string const solver = _config->Find("APT::Solver", "internal");
+   if (solver != "internal") {
+      OpTextProgress Prog(*_config);
+      return EDSP::ResolveExternal(solver.c_str(), Cache, false, true, false, &Prog);
+   }
+
+   pkgDepCache::ActionGroup group(Cache);
+
+   /* Upgrade all installed packages first without autoinst to help the resolver
+      in versioned or-groups to upgrade the old solver instead of installing
+      a new one (if the old solver is not the first one [anymore]) */
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
+      if (I->CurrentVer != 0)
+	 Cache.MarkInstall(I, false, 0, false);
+
+   /* Auto upgrade all installed packages, this provides the basis 
+      for the installation */
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
+      if (I->CurrentVer != 0)
+	 Cache.MarkInstall(I, true, 0, false);
+
+   /* Now, install each essential package which is not installed
+      (and not provided by another package in the same name group) */
+   std::string essential = _config->Find("pkgCacheGen::Essential", "all");
+   if (essential == "all")
+   {
+      for (pkgCache::GrpIterator G = Cache.GrpBegin(); G.end() == false; ++G)
+      {
+	 bool isEssential = false;
+	 bool instEssential = false;
+	 for (pkgCache::PkgIterator P = G.PackageList(); P.end() == false; P = G.NextPkg(P))
+	 {
+	    if ((P->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential)
+	       continue;
+	    isEssential = true;
+	    if (Cache[P].Install() == true)
+	    {
+	       instEssential = true;
+	       break;
+	    }
+	 }
+	 if (isEssential == false || instEssential == true)
+	    continue;
+	 pkgCache::PkgIterator P = G.FindPreferredPkg();
+	 Cache.MarkInstall(P, true, 0, false);
+      }
+   }
+   else if (essential != "none")
+      for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
+	 if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
+	    Cache.MarkInstall(I, true, 0, false);
+   
+   /* We do it again over all previously installed packages to force 
+      conflict resolution on them all. */
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
+      if (I->CurrentVer != 0)
+	 Cache.MarkInstall(I, false, 0, false);
+
+   pkgProblemResolver Fix(&Cache);
+
+   // Hold back held packages.
+   if (_config->FindB("APT::Ignore-Hold",false) == false)
+   {
+      for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
+      {
+	 if (I->SelectedState == pkgCache::State::Hold)
+	 {
+	    Fix.Protect(I);
+	    Cache.MarkKeep(I, false, false);
+	 }
+      }
+   }
+   
+   return Fix.Resolve();
+}
+									/*}}}*/
+// AllUpgradeNoNewPackages - Upgrade but no removals or new pkgs        /*{{{*/
+static bool pkgAllUpgradeNoNewPackages(pkgDepCache &Cache)
+{
+   std::string const solver = _config->Find("APT::Solver", "internal");
+   if (solver != "internal") {
+      OpTextProgress Prog(*_config);
+      return EDSP::ResolveExternal(solver.c_str(), Cache, true, false, false, &Prog);
+   }
+
+   pkgDepCache::ActionGroup group(Cache);
+
+   pkgProblemResolver Fix(&Cache);
+
+   if (Cache.BrokenCount() != 0)
+      return false;
+   
+   // Upgrade all installed packages
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
+   {
+      if (Cache[I].Install() == true)
+	 Fix.Protect(I);
+	  
+      if (_config->FindB("APT::Ignore-Hold",false) == false)
+	 if (I->SelectedState == pkgCache::State::Hold)
+	    continue;
+      
+      if (I->CurrentVer != 0 && Cache[I].InstallVer != 0)
+	 Cache.MarkInstall(I, false, 0, false);
+   }
+      
+   return Fix.ResolveByKeep();
+}
+									/*}}}*/
+// AllUpgradeWithNewInstalls - Upgrade + install new packages as needed /*{{{*/
+// ---------------------------------------------------------------------
+/* Right now the system must be consistent before this can be called.
+ * Upgrade as much as possible without deleting anything (useful for
+ * stable systems)
+ */
+static bool pkgAllUpgradeWithNewPackages(pkgDepCache &Cache)
+{
+   pkgDepCache::ActionGroup group(Cache);
+
+   pkgProblemResolver Fix(&Cache);
+
+   if (Cache.BrokenCount() != 0)
+      return false;
+
+   // provide the initial set of stuff we want to upgrade by marking
+   // all upgradable packages for upgrade
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
+   {
+      if (I->CurrentVer != 0 && Cache[I].InstallVer != 0)
+      {
+         if (_config->FindB("APT::Ignore-Hold",false) == false)
+            if (I->SelectedState == pkgCache::State::Hold)
+               continue;
+
+	 Cache.MarkInstall(I, false, 0, false);
+      }
+   }
+
+   // then let auto-install loose
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
+      if (Cache[I].Install())
+	 Cache.MarkInstall(I, true, 0, false);
+
+   // ... but it may remove stuff, we we need to clean up afterwards again
+   for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
+      if (Cache[I].Delete() == true)
+	 Cache.MarkKeep(I, false, false);
+
+   // resolve remaining issues via keep
+   return Fix.ResolveByKeep();
+}
+									/*}}}*/
+// AllUpgrade - Upgrade as many packages as possible			/*{{{*/
+// ---------------------------------------------------------------------
+/* Right now the system must be consistent before this can be called.
+   It also will not change packages marked for install, it only tries
+   to install packages not marked for install */
+bool pkgAllUpgrade(pkgDepCache &Cache)
+{
+   return pkgAllUpgradeNoNewPackages(Cache);
+}
+									/*}}}*/
+// MinimizeUpgrade - Minimizes the set of packages to be upgraded	/*{{{*/
+// ---------------------------------------------------------------------
+/* This simply goes over the entire set of packages and tries to keep 
+   each package marked for upgrade. If a conflict is generated then 
+   the package is restored. */
+bool pkgMinimizeUpgrade(pkgDepCache &Cache)
+{   
+   pkgDepCache::ActionGroup group(Cache);
+
+   if (Cache.BrokenCount() != 0)
+      return false;
+   
+   // We loop for 10 tries to get the minimal set size.
+   bool Change = false;
+   unsigned int Count = 0;
+   do
+   {
+      Change = false;
+      for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; ++I)
+      {
+	 // Not interesting
+	 if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true)
+	    continue;
+
+	 // Keep it and see if that is OK
+	 Cache.MarkKeep(I, false, false);
+	 if (Cache.BrokenCount() != 0)
+	    Cache.MarkInstall(I, false, 0, false);
+	 else
+	 {
+	    // If keep didn't actually do anything then there was no change..
+	    if (Cache[I].Upgrade() == false)
+	       Change = true;
+	 }	 
+      }      
+      ++Count;
+   }
+   while (Change == true && Count < 10);
+
+   if (Cache.BrokenCount() != 0)
+      return _error->Error("Internal Error in pkgMinimizeUpgrade");
+   
+   return true;
+}
+									/*}}}*/
+// APT::Upgrade::Upgrade - Upgrade using a specific strategy     	/*{{{*/
+bool APT::Upgrade::Upgrade(pkgDepCache &Cache, int mode)
+{
+   if (mode == 0) 
+   {
+      return pkgDistUpgrade(Cache);
+   }
+   else if ((mode & ~FORBID_REMOVE_PACKAGES) == 0)
+   {
+      return pkgAllUpgradeWithNewPackages(Cache);
+   } 
+   else if ((mode & ~(FORBID_REMOVE_PACKAGES|FORBID_INSTALL_NEW_PACKAGES)) == 0)
+   {
+      return pkgAllUpgradeNoNewPackages(Cache);
+   }
+   else
+      _error->Error("pkgAllUpgrade called with unsupported mode %i", mode);
+
+   return false;
+}
+									/*}}}*/

+ 30 - 0
apt-pkg/upgrade.h

@@ -0,0 +1,30 @@
+// -*- mode: cpp; mode: fold -*-
+// Description								/*{{{*/
+/* ######################################################################
+
+   Upgrade - Upgrade/DistUpgrade releated code
+   
+   ##################################################################### */
+									/*}}}*/
+
+#ifndef PKGLIB_UPGRADE_H
+#define PKGLIB_UPGRADE_H
+
+namespace APT {
+   namespace Upgrade {
+      // FIXME: make this "enum class UpgradeMode {" once we enable c++11
+      enum UpgradeMode {
+         FORBID_REMOVE_PACKAGES = 1,
+         FORBID_INSTALL_NEW_PACKAGES = 2,
+      };
+      bool Upgrade(pkgDepCache &Cache, int UpgradeMode);
+   }
+}
+
+// please use APT::Upgrade::Upgrade() instead
+bool pkgDistUpgrade(pkgDepCache &Cache);
+bool pkgAllUpgrade(pkgDepCache &Cache);
+bool pkgMinimizeUpgrade(pkgDepCache &Cache);
+
+
+#endif

+ 5 - 2
apt-private/acqprogress.cc

@@ -30,10 +30,13 @@ using namespace std;
 // AcqTextStatus::AcqTextStatus - Constructor				/*{{{*/
 // ---------------------------------------------------------------------
 /* */
-AcqTextStatus::AcqTextStatus(unsigned int &ScreenWidth,unsigned int Quiet) :
-    ScreenWidth(ScreenWidth), ID(0), Quiet(Quiet)
+AcqTextStatus::AcqTextStatus(unsigned int &ScreenWidth,unsigned int const Quiet) :
+    pkgAcquireStatus(), ScreenWidth(ScreenWidth), ID(0), Quiet(Quiet)
 {
    BlankLine[0] = 0;
+   // testcases use it to disable pulses without disabling other user messages
+   if (Quiet == 0 && _config->FindB("quiet::NoUpdate", false) == true)
+      this->Quiet = 1;
 }
 									/*}}}*/
 // AcqTextStatus::Start - Downloading has started			/*{{{*/

+ 1 - 1
apt-private/acqprogress.h

@@ -32,7 +32,7 @@ class AcqTextStatus : public pkgAcquireStatus
    
    bool Pulse(pkgAcquire *Owner);
 
-   AcqTextStatus(unsigned int &ScreenWidth,unsigned int Quiet);
+   AcqTextStatus(unsigned int &ScreenWidth,unsigned int const Quiet);
 };
 
 #endif

+ 1 - 1
apt-private/makefile

@@ -17,7 +17,7 @@ MAJOR=0.0
 MINOR=0
 SLIBS=$(PTHREADLIB) -lapt-pkg
 
-PRIVATES=list install output cachefile cacheset update upgrade cmndline moo search show main
+PRIVATES=list install download output cachefile cacheset update upgrade cmndline moo search show main utils sources
 SOURCE += $(foreach private, $(PRIVATES), private-$(private).cc)
 HEADERS += $(foreach private, $(PRIVATES), private-$(private).h)
 

+ 1 - 0
apt-private/private-cachefile.cc

@@ -2,6 +2,7 @@
 #include<config.h>
 
 #include <apt-pkg/algorithms.h>
+#include <apt-pkg/upgrade.h>
 #include <apt-pkg/error.h>
 
 #include <cstdlib>

+ 9 - 0
apt-private/private-cacheset.cc

@@ -52,6 +52,15 @@ bool GetLocalitySortedVersionSet(pkgCacheFile &CacheFile,
              output_set.insert(policy->GetCandidateVer(P));
          }
       }
+      else if (_config->FindB("APT::Cmd::Manual-Installed") == true)
+      {
+         if (P.CurrentVer() && 
+             ((*DepCache)[P].Flags & pkgCache::Flag::Auto) == false)
+         {
+             pkgPolicy *policy = CacheFile.GetPolicy();
+             output_set.insert(policy->GetCandidateVer(P));
+         }
+      }
       else 
       {
          pkgPolicy *policy = CacheFile.GetPolicy();

+ 5 - 0
apt-private/private-cacheset.h

@@ -101,6 +101,11 @@ public:
 				Pkg.FullName(true).c_str(), pattern.c_str());
 		explicitlyNamed = false;
 	}
+        virtual void showFnmatchSelection(pkgCache::PkgIterator const &Pkg, std::string const &pattern) {
+		ioprintf(out, _("Note, selecting '%s' for glob '%s'\n"),
+				Pkg.FullName(true).c_str(), pattern.c_str());
+		explicitlyNamed = false;
+	}
 	virtual void showRegExSelection(pkgCache::PkgIterator const &Pkg, std::string const &pattern) {
 		ioprintf(out, _("Note, selecting '%s' for regex '%s'\n"),
 				Pkg.FullName(true).c_str(), pattern.c_str());

+ 20 - 5
apt-private/private-cmndline.cc

@@ -62,8 +62,12 @@ bool addArgumentsAPTCache(std::vector<CommandLine::Args> &Args, char const * con
    {
       addArg(0, "all-names", "APT::Cache::AllNames", 0);
    }
+   else if (CmdMatches("unmet"))
+   {
+      addArg('i', "important", "APT::Cache::Important", 0);
+   }
    else if (CmdMatches("gencaches", "showsrc", "showpkg", "stats", "dump",
-	    "dumpavail", "unmet", "showauto", "policy", "madison"))
+	    "dumpavail", "showauto", "policy", "madison"))
       ;
    else
       return false;
@@ -114,9 +118,9 @@ bool addArgumentsAPTConfig(std::vector<CommandLine::Args> &Args, char const * co
 bool addArgumentsAPTGet(std::vector<CommandLine::Args> &Args, char const * const Cmd)/*{{{*/
 {
    if (CmdMatches("install", "remove", "purge", "upgrade", "dist-upgrade",
-	    "deselect-upgrade", "autoremove"))
+	    "dselect-upgrade", "autoremove"))
    {
-      addArg(0, "dpkg-progress", "DpkgPM::Progress", 0);
+      addArg(0, "show-progress", "DpkgPM::Progress", 0);
       addArg('f', "fix-broken", "APT::Get::Fix-Broken", 0);
       addArg(0, "purge", "APT::Get::Purge", 0);
       addArg('V',"verbose-versions","APT::Get::Show-Versions",0);
@@ -125,7 +129,8 @@ bool addArgumentsAPTGet(std::vector<CommandLine::Args> &Args, char const * const
       addArg(0, "solver", "APT::Solver", CommandLine::HasArg);
       if (CmdMatches("upgrade"))
       {
-	 addArg(0, "allow-new", "APT::Get::UpgradeAllowNew", 0);
+         addArg(0, "new-pkgs", "APT::Get::Upgrade-Allow-New", 
+                CommandLine::Boolean);
       }
    }
    else if (CmdMatches("update"))
@@ -144,7 +149,11 @@ bool addArgumentsAPTGet(std::vector<CommandLine::Args> &Args, char const * const
    else if (CmdMatches("build-dep"))
    {
       addArg('a', "host-architecture", "APT::Get::Host-Architecture", CommandLine::HasArg);
+      addArg(0, "purge", "APT::Get::Purge", 0);
       addArg(0, "solver", "APT::Solver", CommandLine::HasArg);
+      // this has no effect *but* sbuild is using it (see LP: #1255806)
+      // once sbuild is fixed, this option can be removed
+      addArg('f', "fix-broken", "APT::Get::Fix-Broken", 0);
    }
    else if (CmdMatches("clean", "autoclean", "check", "download", "changelog") ||
 	    CmdMatches("markauto", "unmarkauto")) // deprecated commands
@@ -217,7 +226,13 @@ bool addArgumentsAPT(std::vector<CommandLine::Args> &Args, char const * const Cm
    {
       addArg(0,"installed","APT::Cmd::Installed",0);
       addArg(0,"upgradable","APT::Cmd::Upgradable",0);
-      addArg('a', "all-versions", "APT::Cmd::AllVersions", 0);
+      addArg(0,"manual-installed","APT::Cmd::Manual-Installed",0);
+      addArg('v', "verbose", "APT::Cmd::List-Include-Summary", 0);
+      addArg('a', "all-versions", "APT::Cmd::All-Versions", 0);
+   }
+   else if (CmdMatches("show"))
+   {
+      addArg('a', "all-versions", "APT::Cache::AllVersions", 0);
    }
    else if (addArgumentsAPTGet(Args, Cmd) || addArgumentsAPTCache(Args, Cmd))
    {

+ 96 - 0
apt-private/private-download.cc

@@ -0,0 +1,96 @@
+// Include Files							/*{{{*/
+#include <config.h>
+
+#include <apt-pkg/acquire.h>
+#include <apt-pkg/acquire-item.h>
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/strutl.h>
+
+#include "private-output.h"
+
+#include <locale.h>
+
+#include <fstream>
+#include <string>
+#include <vector>
+
+#include <apti18n.h>
+									/*}}}*/
+
+// CheckAuth - check if each download comes form a trusted source	/*{{{*/
+bool CheckAuth(pkgAcquire& Fetcher, bool const PromptUser)
+{
+   std::string UntrustedList;
+   for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd(); ++I)
+      if (!(*I)->IsTrusted())
+          UntrustedList += std::string((*I)->ShortDesc()) + " ";
+
+   if (UntrustedList == "")
+      return true;
+
+   ShowList(c2out,_("WARNING: The following packages cannot be authenticated!"),UntrustedList,"");
+
+   if (_config->FindB("APT::Get::AllowUnauthenticated",false) == true)
+   {
+      c2out << _("Authentication warning overridden.\n");
+      return true;
+   }
+
+   if (PromptUser == false)
+      return _error->Error(_("Some packages could not be authenticated"));
+
+   if (_config->FindI("quiet",0) < 2
+       && _config->FindB("APT::Get::Assume-Yes",false) == false)
+   {
+      c2out << _("Install these packages without verification?") << std::flush;
+      if (!YnPrompt(false))
+         return _error->Error(_("Some packages could not be authenticated"));
+
+      return true;
+   }
+   else if (_config->FindB("APT::Get::Force-Yes",false) == true)
+      return true;
+
+   return _error->Error(_("There are problems and -y was used without --force-yes"));
+}
+									/*}}}*/
+bool AcquireRun(pkgAcquire &Fetcher, int const PulseInterval, bool * const Failure, bool * const TransientNetworkFailure)/*{{{*/
+{
+   pkgAcquire::RunResult res;
+   if(PulseInterval > 0)
+      res = Fetcher.Run(PulseInterval);
+   else
+      res = Fetcher.Run();
+
+   if (res == pkgAcquire::Failed)
+      return false;
+
+   for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin();
+	I != Fetcher.ItemsEnd(); ++I)
+   {
+
+      if ((*I)->Status == pkgAcquire::Item::StatDone &&
+	    (*I)->Complete == true)
+	 continue;
+
+      if (TransientNetworkFailure != NULL && (*I)->Status == pkgAcquire::Item::StatIdle)
+      {
+	 *TransientNetworkFailure = true;
+	 continue;
+      }
+
+      ::URI uri((*I)->DescURI());
+      uri.User.clear();
+      uri.Password.clear();
+      std::string descUri = std::string(uri);
+      _error->Error(_("Failed to fetch %s  %s\n"), descUri.c_str(),
+	    (*I)->ErrorText.c_str());
+
+      if (Failure != NULL)
+	 *Failure = true;
+   }
+
+   return true;
+}
+									/*}}}*/

+ 9 - 0
apt-private/private-download.h

@@ -0,0 +1,9 @@
+#ifndef APT_PRIVATE_DOWNLOAD_H
+#define APT_PRIVATE_DOWNLOAD_H
+
+#include <apt-pkg/acquire.h>
+
+bool CheckAuth(pkgAcquire& Fetcher, bool const PromptUser);
+bool AcquireRun(pkgAcquire &Fetcher, int const PulseInterval, bool * const Failure, bool * const TransientNetworkFailure);
+
+#endif

+ 72 - 109
apt-private/private-install.cc

@@ -23,6 +23,8 @@
 #include <apt-pkg/pkgsystem.h>
 #include <apt-pkg/pkgrecords.h>
 #include <apt-pkg/indexfile.h>
+#include <apt-pkg/install-progress.h>
+#include <apt-pkg/init.h>
 
 #include <set>
 #include <locale.h>
@@ -42,6 +44,7 @@
 #include <sstream>
 
 #include "private-install.h"
+#include "private-download.h"
 #include "private-cachefile.h"
 #include "private-output.h"
 #include "private-cacheset.h"
@@ -50,52 +53,6 @@
 #include <apti18n.h>
 									/*}}}*/
 
-// CheckAuth - check if each download comes form a trusted source	/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-static bool CheckAuth(pkgAcquire& Fetcher)
-{
-   std::string UntrustedList;
-   for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd(); ++I)
-   {
-      if (!(*I)->IsTrusted())
-      {
-          UntrustedList += std::string((*I)->ShortDesc()) + " ";
-      }
-   }
-
-   if (UntrustedList == "")
-   {
-      return true;
-   }
-        
-   ShowList(c2out,_("WARNING: The following packages cannot be authenticated!"),UntrustedList,"");
-
-   if (_config->FindB("APT::Get::AllowUnauthenticated",false) == true)
-   {
-      c2out << _("Authentication warning overridden.\n");
-      return true;
-   }
-
-   if (_config->FindI("quiet",0) < 2
-       && _config->FindB("APT::Get::Assume-Yes",false) == false)
-   {
-      c2out << _("Install these packages without verification?") << std::flush;
-      if (!YnPrompt(false))
-         return _error->Error(_("Some packages could not be authenticated"));
-
-      return true;
-   }
-   else if (_config->FindB("APT::Get::Force-Yes",false) == true)
-   {
-      return true;
-   }
-
-   return _error->Error(_("There are problems and -y was used without --force-yes"));
-}
-									/*}}}*/
-
-
 // InstallPackages - Actually download and install the packages		/*{{{*/
 // ---------------------------------------------------------------------
 /* This displays the informative messages describing what is going to 
@@ -148,8 +105,16 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety)
    if (_config->FindB("APT::Get::Simulate") == true)
    {
       pkgSimulate PM(Cache);
+
+#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
+      APT::Progress::PackageManager *progress = APT::Progress::PackageManagerProgressFactory();
+      pkgPackageManager::OrderResult Res = PM.DoInstall(progress);
+      delete progress;
+#else
       int status_fd = _config->FindI("APT::Status-Fd",-1);
       pkgPackageManager::OrderResult Res = PM.DoInstall(status_fd);
+#endif
+
       if (Res == pkgPackageManager::Failed)
 	 return false;
       if (Res != pkgPackageManager::Completed)
@@ -301,12 +266,12 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety)
    {
       pkgAcquire::UriIterator I = Fetcher.UriBegin();
       for (; I != Fetcher.UriEnd(); ++I)
-	 c1out << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << 
+	 std::cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
 	       I->Owner->FileSize << ' ' << I->Owner->HashSum() << std::endl;
       return true;
    }
 
-   if (!CheckAuth(Fetcher))
+   if (!CheckAuth(Fetcher, true))
       return false;
 
    /* Unlock the dpkg lock if we are not going to be doing an install
@@ -338,29 +303,10 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety)
 	    I = Fetcher.ItemsBegin();
 	 }	 
       }
-      
-      if (Fetcher.Run() == pkgAcquire::Failed)
-	 return false;
-      
-      // Print out errors
-      bool Failed = false;
-      for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); ++I)
-      {
-	 if ((*I)->Status == pkgAcquire::Item::StatDone &&
-	     (*I)->Complete == true)
-	    continue;
-	 
-	 if ((*I)->Status == pkgAcquire::Item::StatIdle)
-	 {
-	    Transient = true;
-	    // Failed = true;
-	    continue;
-	 }
 
-	 fprintf(stderr,_("Failed to fetch %s  %s\n"),(*I)->DescURI().c_str(),
-		 (*I)->ErrorText.c_str());
-	 Failed = true;
-      }
+      bool Failed = false;
+      if (AcquireRun(Fetcher, 0, &Failed, &Transient) == false)
+	 return false;
 
       /* If we are in no download mode and missing files and there were
          'failures' then the user must specify -m. Furthermore, there 
@@ -396,8 +342,16 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety)
       }
 
       _system->UnLock();
-      int status_fd = _config->FindI("APT::Status-Fd",-1);
+      
+#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13)
+      APT::Progress::PackageManager *progress = APT::Progress::PackageManagerProgressFactory();
+      pkgPackageManager::OrderResult Res = PM->DoInstall(progress);
+      delete progress;
+#else
+      int status_fd = _config->FindI("APT::Status-Fd", -1);
       pkgPackageManager::OrderResult Res = PM->DoInstall(status_fd);
+#endif
+
       if (Res == pkgPackageManager::Failed || _error->PendingError() == true)
 	 return false;
       if (Res == pkgPackageManager::Completed)
@@ -429,8 +383,6 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety)
    return true;
 }
 									/*}}}*/
-
-
 // DoAutomaticRemove - Remove all automatic unused packages		/*{{{*/
 // ---------------------------------------------------------------------
 /* Remove unused automatic packages */
@@ -504,15 +456,15 @@ bool DoAutomaticRemove(CacheFile &Cache)
       do {
 	 Changed = false;
 	 for (APT::PackageSet::const_iterator Pkg = tooMuch.begin();
-	      Pkg != tooMuch.end() && Changed == false; ++Pkg)
+	      Pkg != tooMuch.end(); ++Pkg)
 	 {
 	    APT::PackageSet too;
 	    too.insert(*Pkg);
 	    for (pkgCache::PrvIterator Prv = Cache[Pkg].CandidateVerIter(Cache).ProvidesList();
 		 Prv.end() == false; ++Prv)
 	       too.insert(Prv.ParentPkg());
-	    for (APT::PackageSet::const_iterator P = too.begin();
-		 P != too.end() && Changed == false; ++P) {
+	    for (APT::PackageSet::const_iterator P = too.begin(); P != too.end(); ++P)
+	    {
 	       for (pkgCache::DepIterator R = P.RevDependsList();
 		    R.end() == false; ++R)
 	       {
@@ -531,7 +483,11 @@ bool DoAutomaticRemove(CacheFile &Cache)
 		 Changed = true;
 		 break;
 	       }
+	       if (Changed == true)
+		  break;
 	    }
+	    if (Changed == true)
+	       break;
 	 }
       } while (Changed == true);
    }
@@ -576,32 +532,28 @@ bool DoAutomaticRemove(CacheFile &Cache)
    return true;
 }
 									/*}}}*/
+// DoCacheManipulationFromCommandLine					/*{{{*/
+static const unsigned short MOD_REMOVE = 1;
+static const unsigned short MOD_INSTALL = 2;
 
-
-
-
-// DoInstall - Install packages from the command line			/*{{{*/
-// ---------------------------------------------------------------------
-/* Install named packages */
-bool DoInstall(CommandLine &CmdL)
+bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache)
 {
-   CacheFile Cache;
-   if (Cache.OpenForInstall() == false || 
-       Cache.CheckDeps(CmdL.FileSize() != 1) == false)
-      return false;
-   
+   std::map<unsigned short, APT::VersionSet> verset;
+   return DoCacheManipulationFromCommandLine(CmdL, Cache, verset);
+}
+bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache,
+                                        std::map<unsigned short, APT::VersionSet> &verset)
+{
+
    // Enter the special broken fixing mode if the user specified arguments
    bool BrokenFix = false;
    if (Cache->BrokenCount() != 0)
       BrokenFix = true;
 
-   pkgProblemResolver* Fix = NULL;
+   SPtr<pkgProblemResolver> Fix;
    if (_config->FindB("APT::Get::CallResolver", true) == true)
       Fix = new pkgProblemResolver(Cache);
 
-   static const unsigned short MOD_REMOVE = 1;
-   static const unsigned short MOD_INSTALL = 2;
-
    unsigned short fallback = MOD_INSTALL;
    if (strcasecmp(CmdL.FileList[0],"remove") == 0)
       fallback = MOD_REMOVE;
@@ -622,14 +574,12 @@ bool DoInstall(CommandLine &CmdL)
    mods.push_back(APT::VersionSet::Modifier(MOD_REMOVE, "-",
 		APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::NEWEST));
    CacheSetHelperAPTGet helper(c0out);
-   std::map<unsigned short, APT::VersionSet> verset = APT::VersionSet::GroupedFromCommandLine(Cache,
+   verset = APT::VersionSet::GroupedFromCommandLine(Cache,
 		CmdL.FileList + 1, mods, fallback, helper);
 
    if (_error->PendingError() == true)
    {
       helper.showVirtualPackageErrors(Cache);
-      if (Fix != NULL)
-	 delete Fix;
       return false;
    }
 
@@ -663,8 +613,6 @@ bool DoInstall(CommandLine &CmdL)
 
       if (_error->PendingError() == true)
       {
-	 if (Fix != NULL)
-	    delete Fix;
 	 return false;
       }
 
@@ -675,8 +623,6 @@ bool DoInstall(CommandLine &CmdL)
       {
 	 c1out << _("You might want to run 'apt-get -f install' to correct these:") << std::endl;
 	 ShowBroken(c1out,Cache,false);
-	 if (Fix != NULL)
-	    delete Fix;
 	 return _error->Error(_("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution)."));
       }
 
@@ -684,7 +630,6 @@ bool DoInstall(CommandLine &CmdL)
       {
 	 // Call the scored problem resolver
 	 Fix->Resolve(true);
-	 delete Fix;
       }
 
       // Now we check the state of the packages,
@@ -718,6 +663,33 @@ bool DoInstall(CommandLine &CmdL)
    if (!DoAutomaticRemove(Cache)) 
       return false;
 
+   // if nothing changed in the cache, but only the automark information
+   // we write the StateFile here, otherwise it will be written in 
+   // cache.commit()
+   if (InstallAction.AutoMarkChanged > 0 &&
+       Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
+       Cache->BadCount() == 0 &&
+       _config->FindB("APT::Get::Simulate",false) == false)
+      Cache->writeStateFile(NULL);
+
+   return true;
+}
+									/*}}}*/
+// DoInstall - Install packages from the command line			/*{{{*/
+// ---------------------------------------------------------------------
+/* Install named packages */
+bool DoInstall(CommandLine &CmdL)
+{
+   CacheFile Cache;
+   if (Cache.OpenForInstall() == false || 
+       Cache.CheckDeps(CmdL.FileSize() != 1) == false)
+      return false;
+
+   std::map<unsigned short, APT::VersionSet> verset;
+
+   if(!DoCacheManipulationFromCommandLine(CmdL, Cache, verset))
+      return false;
+
    /* Print out a list of packages that are going to be installed extra
       to what the user asked */
    if (Cache->InstCount() != verset[MOD_INSTALL].size())
@@ -833,15 +805,6 @@ bool DoInstall(CommandLine &CmdL)
 
    }
 
-   // if nothing changed in the cache, but only the automark information
-   // we write the StateFile here, otherwise it will be written in 
-   // cache.commit()
-   if (InstallAction.AutoMarkChanged > 0 &&
-       Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
-       Cache->BadCount() == 0 &&
-       _config->FindB("APT::Get::Simulate",false) == false)
-      Cache->writeStateFile(NULL);
-
    // See if we need to prompt
    // FIXME: check if really the packages in the set are going to be installed
    if (Cache->InstCount() == verset[MOD_INSTALL].size() && Cache->DelCount() == 0)

+ 6 - 0
apt-private/private-install.h

@@ -14,6 +14,9 @@
 
 bool DoInstall(CommandLine &Cmd);
 
+bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache,
+                                        std::map<unsigned short, APT::VersionSet> &verset);
+bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache);
 
 bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
                         bool Safety = true);
@@ -92,6 +95,9 @@ struct TryToInstall {
 	 Cache->GetDepCache()->SetCandidateVersion(s->first);
 
       bool Success = true;
+      // the Changed list contains:
+      //   first: "new version" 
+      //   second: "what-caused the change" 
       std::list<std::pair<pkgCache::VerIterator, pkgCache::VerIterator> > Changed;
       for (std::list<std::pair<pkgCache::VerIterator, std::string> >::const_iterator s = start.begin();
 		s != start.end(); ++s)

+ 26 - 21
apt-private/private-list.cc

@@ -42,7 +42,7 @@
 #include <apti18n.h>
 									/*}}}*/
 
-struct PackageSortAlphabetic
+struct PackageSortAlphabetic						/*{{{*/
 {
    bool operator () (const pkgCache::PkgIterator &p_lhs, 
                      const pkgCache::PkgIterator &p_rhs)
@@ -52,17 +52,17 @@ struct PackageSortAlphabetic
        return (l_name < r_name);
     }
 };
-
-class PackageNameMatcher : public Matcher
-{
+#ifdef PACKAGE_MATCHER_ABI_COMPAT
+#define PackageMatcher PackageNameMatchesFnmatch
+#endif
   public:
    PackageNameMatcher(const char **patterns)
    {
-      for(int i=0; patterns[i] != NULL; i++)
+      for(int i=0; patterns[i] != NULL; ++i)
       {
          std::string pattern = patterns[i];
          APT::CacheFilter::PackageMatcher *cachefilter = NULL;
-         if(_config->FindB("APT::Cmd::UseRegexp", false) == true)
+         if(_config->FindB("APT::Cmd::Use-Regexp", false) == true)
             cachefilter = new APT::CacheFilter::PackageNameMatchesRegEx(pattern);
          else
             cachefilter = new APT::CacheFilter::PackageNameMatchesFnmatch(pattern);
@@ -71,12 +71,12 @@ class PackageNameMatcher : public Matcher
    }
    virtual ~PackageNameMatcher()
    {
-      for(J=filters.begin(); J != filters.end(); J++)
+      for(J=filters.begin(); J != filters.end(); ++J)
          delete *J;
    }
    virtual bool operator () (const pkgCache::PkgIterator &P) 
    {
-      for(J=filters.begin(); J != filters.end(); J++)
+      for(J=filters.begin(); J != filters.end(); ++J)
       {
          APT::CacheFilter::PackageMatcher *cachefilter = *J;
          if((*cachefilter)(P)) 
@@ -90,17 +90,20 @@ private:
    std::vector<APT::CacheFilter::PackageMatcher*>::const_iterator J;
    #undef PackageMatcher
 };
-
-
-void ListAllVersions(pkgCacheFile &CacheFile, pkgRecords &records, 
+									/*}}}*/
+void ListAllVersions(pkgCacheFile &CacheFile, pkgRecords &records,	/*{{{*/
                      pkgCache::PkgIterator P,    
-                     std::ostream &outs)
+                     std::ostream &outs,
+                     bool include_summary=true)
 {
    for (pkgCache::VerIterator Ver = P.VersionList();
-        Ver.end() == false; Ver++) 
-      ListSingleVersion(CacheFile, records, Ver, outs);
+        Ver.end() == false; ++Ver)
+   {
+      ListSingleVersion(CacheFile, records, Ver, outs, include_summary);
+      outs << "\n";
+   }
 }
-
+									/*}}}*/
 // list - list package based on criteria        			/*{{{*/
 // ---------------------------------------------------------------------
 bool List(CommandLine &Cmd)
@@ -125,24 +128,26 @@ bool List(CommandLine &Cmd)
    std::map<std::string, std::string> output_map;
    std::map<std::string, std::string>::const_iterator K;
 
+   bool includeSummary = _config->FindB("APT::Cmd::List-Include-Summary");
+
    PackageNameMatcher matcher(patterns);
    LocalitySortedVersionSet bag;
-   OpTextProgress progress;
+   OpTextProgress progress(*_config);
    progress.OverallProgress(0,
                             Cache->Head().PackageCount, 
                             Cache->Head().PackageCount,
                             _("Listing"));
    GetLocalitySortedVersionSet(CacheFile, bag, matcher, progress);
-   for (LocalitySortedVersionSet::iterator V = bag.begin(); V != bag.end(); V++)
+   for (LocalitySortedVersionSet::iterator V = bag.begin(); V != bag.end(); ++V)
    {
       std::stringstream outs;
-      if(_config->FindB("APT::Cmd::AllVersions", false) == true)
+      if(_config->FindB("APT::Cmd::All-Versions", false) == true)
       {
-         ListAllVersions(CacheFile, records, V.ParentPkg(), outs);
+         ListAllVersions(CacheFile, records, V.ParentPkg(), outs, includeSummary);
          output_map.insert(std::make_pair<std::string, std::string>(
             V.ParentPkg().Name(), outs.str()));
       } else {
-         ListSingleVersion(CacheFile, records, V, outs);
+         ListSingleVersion(CacheFile, records, V, outs, includeSummary);
          output_map.insert(std::make_pair<std::string, std::string>(
                            V.ParentPkg().Name(), outs.str()));
       }
@@ -150,7 +155,7 @@ bool List(CommandLine &Cmd)
 
    // FIXME: SORT! and make sorting flexible (alphabetic, by pkg status)
    // output the sorted map
-   for (K = output_map.begin(); K != output_map.end(); K++)
+   for (K = output_map.begin(); K != output_map.end(); ++K)
       std::cout << (*K).second << std::endl;
 
 

+ 60 - 52
apt-private/private-output.cc

@@ -28,9 +28,11 @@ std::ostream c2out(0);
 std::ofstream devnull("/dev/null");
 unsigned int ScreenWidth = 80 - 1; /* - 1 for the cursor */
 
-
-bool InitOutput()
+bool InitOutput()							/*{{{*/
 {
+   if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1)
+      _config->Set("quiet","1");
+
    c0out.rdbuf(cout.rdbuf());
    c1out.rdbuf(cout.rdbuf());
    c2out.rdbuf(cout.rdbuf());
@@ -60,8 +62,8 @@ bool InitOutput()
 
    return true;
 }
-
-std::string GetArchiveSuite(pkgCacheFile &CacheFile, pkgCache::VerIterator ver)
+									/*}}}*/
+std::string GetArchiveSuite(pkgCacheFile &CacheFile, pkgCache::VerIterator ver) /*{{{*/
 {
    std::string suite = "";
    if (ver && ver.FileList() && ver.FileList())
@@ -69,16 +71,18 @@ std::string GetArchiveSuite(pkgCacheFile &CacheFile, pkgCache::VerIterator ver)
       pkgCache::VerFileIterator VF = ver.FileList();
       for (; VF.end() == false ; ++VF)
       {
-         // XXX: how to figure out the relevant suite? if its in multiple ones?
-         suite = suite + "," + VF.File().Archive();
+         if(VF.File() == NULL || VF.File().Archive() == NULL)
+            suite = suite + "," + _("unknown");
+         else
+            suite = suite + "," + VF.File().Archive();
          //suite = VF.File().Archive();
       }
       suite = suite.erase(0, 1);
    }
    return suite;
 }
-
-std::string GetFlagsStr(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)
+									/*}}}*/
+std::string GetFlagsStr(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/
 {
    pkgDepCache *DepCache = CacheFile.GetDepCache();
    pkgDepCache::StateCache &state = (*DepCache)[P];
@@ -94,32 +98,34 @@ std::string GetFlagsStr(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)
       flags_str = "-";
    return flags_str;
 }
-
-std::string GetCandidateVersion(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)
+									/*}}}*/
+std::string GetCandidateVersion(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/
 {
    pkgPolicy *policy = CacheFile.GetPolicy();
    pkgCache::VerIterator cand = policy->GetCandidateVer(P);
 
    return cand ? cand.VerStr() : "(none)";
 }
-
-std::string GetInstalledVersion(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)
+									/*}}}*/
+std::string GetInstalledVersion(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/
 {
    pkgCache::VerIterator inst = P.CurrentVer();
 
    return inst ? inst.VerStr() : "(none)";
 }
-
-std::string GetVersion(pkgCacheFile &CacheFile, pkgCache::VerIterator V)
+									/*}}}*/
+std::string GetVersion(pkgCacheFile &CacheFile, pkgCache::VerIterator V)/*{{{*/
 {
    pkgCache::PkgIterator P = V.ParentPkg();
    if (V == P.CurrentVer())
    {
+      std::string inst_str = DeNull(V.VerStr());
+#if 0 // FIXME: do we want this or something like this?
       pkgDepCache *DepCache = CacheFile.GetDepCache();
       pkgDepCache::StateCache &state = (*DepCache)[P];
-      std::string inst_str = DeNull(V.VerStr());
       if (state.Upgradable())
          return "**"+inst_str;
+#endif
       return inst_str;
    }
 
@@ -127,8 +133,8 @@ std::string GetVersion(pkgCacheFile &CacheFile, pkgCache::VerIterator V)
       return DeNull(V.VerStr());
    return "(none)";
 }
-
-std::string GetArchitecture(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)
+									/*}}}*/
+std::string GetArchitecture(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/
 {
    pkgPolicy *policy = CacheFile.GetPolicy();
    pkgCache::VerIterator inst = P.CurrentVer();
@@ -136,8 +142,8 @@ std::string GetArchitecture(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)
    
    return inst ? inst.Arch() : cand.Arch();
 }
-
-std::string GetShortDescription(pkgCacheFile &CacheFile, pkgRecords &records, pkgCache::PkgIterator P)
+									/*}}}*/
+std::string GetShortDescription(pkgCacheFile &CacheFile, pkgRecords &records, pkgCache::PkgIterator P)/*{{{*/
 {
    pkgPolicy *policy = CacheFile.GetPolicy();
 
@@ -157,9 +163,10 @@ std::string GetShortDescription(pkgCacheFile &CacheFile, pkgRecords &records, pk
    }
    return ShortDescription;
 }
-
-void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records, 
-                       pkgCache::VerIterator V, std::ostream &out)
+									/*}}}*/
+void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records,	/*{{{*/
+                       pkgCache::VerIterator V, std::ostream &out,
+                       bool include_summary)
 {
    pkgCache::PkgIterator P = V.ParentPkg();
 
@@ -186,52 +193,53 @@ void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records,
       // raring/linux-kernel version [upradable: new-version]
       //    description
       pkgPolicy *policy = CacheFile.GetPolicy();
-      out << std::setiosflags(std::ios::left)
-          << _config->Find("APT::Color::Highlight", "")
-          << name_str 
-          << _config->Find("APT::Color::Neutral", "")
-          << "/" << suite
-          << " ";
+      std::string VersionStr = GetVersion(CacheFile, V);
+      std::string CandidateVerStr = GetCandidateVersion(CacheFile, P);
+      std::string InstalledVerStr = GetInstalledVersion(CacheFile, P);
+      std::string StatusStr;
       if(P.CurrentVer() == V && state.Upgradable()) {
-         out << GetVersion(CacheFile, V)
-             << " "
-             << "[" << _("installed,upgradable to: ")
-             << GetCandidateVersion(CacheFile, P) << "]";
+         strprintf(StatusStr, _("[installed,upgradable to: %s]"),
+                   CandidateVerStr.c_str());
       } else if (P.CurrentVer() == V) {
-         out << GetVersion(CacheFile, V)
-             << " ";
          if(!V.Downloadable())
-            out << _("[installed,local]");
+            StatusStr = _("[installed,local]");
          else
             if(V.Automatic() && state.Garbage)
-                  out << _("[installed,auto-removable]");
+               StatusStr = _("[installed,auto-removable]");
             else if (state.Flags & pkgCache::Flag::Auto)
-               out << _("[installed,automatic]");
+               StatusStr = _("[installed,automatic]");
             else
-               out << _("[installed]");
+               StatusStr = _("[installed]");
       } else if (P.CurrentVer() && 
                  policy->GetCandidateVer(P) == V && 
                  state.Upgradable()) {
-         out << GetVersion(CacheFile, V)
-             << " "
-             << _("[upgradable from: ")
-             << GetInstalledVersion(CacheFile, P) << "]";
+            strprintf(StatusStr, _("[upgradable from: %s]"),
+                      InstalledVerStr.c_str());
       } else {
          if (V.ParentPkg()->CurrentState == pkgCache::State::ConfigFiles)
-            out << GetVersion(CacheFile, V) 
-                << " "
-                << _("[residual-config]");
+            StatusStr = _("[residual-config]");
          else
-            out << GetVersion(CacheFile, V);
+            StatusStr = "";
+      }
+      out << std::setiosflags(std::ios::left)
+          << _config->Find("APT::Color::Highlight", "")
+          << name_str 
+          << _config->Find("APT::Color::Neutral", "")
+          << "/" << suite
+          << " "
+          << VersionStr << " " 
+          << GetArchitecture(CacheFile, P);
+      if (StatusStr != "") 
+         out << " " << StatusStr;
+      if (include_summary)
+      {
+         out << std::endl 
+             << "  " << GetShortDescription(CacheFile, records, P)
+             << std::endl;
       }
-      out << " " << GetArchitecture(CacheFile, P) << " ";
-      out << std::endl 
-                << "    " << GetShortDescription(CacheFile, records, P)
-                << std::endl;
    }
 }
-
-
+									/*}}}*/
 // ShowList - Show a list						/*{{{*/
 // ---------------------------------------------------------------------
 /* This prints out a string of space separated words with a title and 

+ 3 - 2
apt-private/private-output.h

@@ -24,10 +24,11 @@ extern unsigned int ScreenWidth;
 
 bool InitOutput();
 void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records, 
-                       pkgCache::VerIterator V, std::ostream &out);
-
+                       pkgCache::VerIterator V, std::ostream &out,
+                       bool include_summary=true);
 
 
+// helper to describe global state
 bool ShowList(std::ostream &out, std::string Title, std::string List,
               std::string VersionsList);
 void ShowBroken(std::ostream &out,CacheFile &Cache,bool Now);

+ 9 - 7
apt-private/private-search.cc

@@ -1,3 +1,4 @@
+// Includes								/*{{{*/
 #include <apt-pkg/error.h>
 #include <apt-pkg/cachefile.h>
 #include <apt-pkg/cachefilter.h>
@@ -34,9 +35,9 @@
 
 #include "private-search.h"
 #include "private-cacheset.h"
+									/*}}}*/
 
-
-bool FullTextSearch(CommandLine &CmdL)
+bool FullTextSearch(CommandLine &CmdL)					/*{{{*/
 {
    pkgCacheFile CacheFile;
    pkgCache *Cache = CacheFile.GetPkgCache();
@@ -52,7 +53,7 @@ bool FullTextSearch(CommandLine &CmdL)
    std::map<std::string, std::string>::const_iterator K;
 
    LocalitySortedVersionSet bag;
-   OpTextProgress progress;
+   OpTextProgress progress(*_config);
    progress.OverallProgress(0, 100, 50,  _("Sorting"));
    GetLocalitySortedVersionSet(CacheFile, bag, progress);
    LocalitySortedVersionSet::iterator V = bag.begin();
@@ -60,18 +61,18 @@ bool FullTextSearch(CommandLine &CmdL)
    progress.OverallProgress(50, 100, 50,  _("Full Text Search"));
    progress.SubProgress(bag.size());
    int Done = 0;
-   for ( ;V != bag.end(); V++)
+   for ( ;V != bag.end(); ++V)
    {
       if (Done%500 == 0)
          progress.Progress(Done);
-      Done++;
+      ++Done;
       
       int i;
       pkgCache::DescIterator Desc = V.TranslatedDescription();
       pkgRecords::Parser &parser = records.Lookup(Desc.FileList());
      
       bool all_found = true;
-      for(i=0; patterns[i] != NULL; i++) 
+      for(i=0; patterns[i] != NULL; ++i)
       {
          // FIXME: use regexp instead of simple find()
          const char *pattern = patterns[i];
@@ -92,8 +93,9 @@ bool FullTextSearch(CommandLine &CmdL)
 
    // FIXME: SORT! and make sorting flexible (alphabetic, by pkg status)
    // output the sorted map
-   for (K = output_map.begin(); K != output_map.end(); K++)
+   for (K = output_map.begin(); K != output_map.end(); ++K)
       std::cout << (*K).second << std::endl;
 
    return true;
 }
+									/*}}}*/

+ 0 - 0
apt-private/private-show.cc


Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików