Przeglądaj źródła

merge from the mvo branch

Michael Vogt 16 lat temu
rodzic
commit
51f9f4d78d
100 zmienionych plików z 2410 dodań i 4650 usunięć
  1. 0 2
      .bzr-builddeb/default.conf.orig
  2. 22 0
      .bzrignore
  3. 0 4
      .cvsignore
  4. 16 135
      COPYING
  5. 3 3
      apt-inst/contrib/arfile.cc
  6. 3 1
      apt-inst/makefile
  7. 75 92
      apt-pkg/acquire-item.cc
  8. 25 29
      apt-pkg/acquire-item.h
  9. 0 2
      apt-pkg/acquire-method.cc
  10. 2 5
      apt-pkg/acquire.cc
  11. 13 13
      apt-pkg/acquire.h
  12. 73 37
      apt-pkg/algorithms.cc
  13. 4 4
      apt-pkg/algorithms.h
  14. 90 0
      apt-pkg/aptconfiguration.cc
  15. 46 0
      apt-pkg/aptconfiguration.h
  16. 4 5
      apt-pkg/cachefile.cc
  17. 30 20
      apt-pkg/cacheiterators.h
  18. 15 19
      apt-pkg/cdrom.cc
  19. 8 8
      apt-pkg/cdrom.h
  20. 0 1
      apt-pkg/clean.cc
  21. 30 21
      apt-pkg/contrib/cdromutl.cc
  22. 27 5
      apt-pkg/contrib/configuration.cc
  23. 3 0
      apt-pkg/contrib/configuration.h
  24. 7 6
      apt-pkg/contrib/error.cc
  25. 2 0
      apt-pkg/contrib/fileutl.cc
  26. 13 11
      apt-pkg/contrib/hashes.cc
  27. 9 4
      apt-pkg/contrib/md5.cc
  28. 86 34
      apt-pkg/contrib/mmap.cc
  29. 2 0
      apt-pkg/contrib/mmap.h
  30. 211 0
      apt-pkg/contrib/netrc.cc
  31. 29 0
      apt-pkg/contrib/netrc.h
  32. 13 19
      apt-pkg/contrib/sha256.cc
  33. 26 4
      apt-pkg/contrib/strutl.cc
  34. 8 6
      apt-pkg/contrib/strutl.h
  35. 4 0
      apt-pkg/deb/deblistparser.cc
  36. 7 0
      apt-pkg/deb/debmetaindex.cc
  37. 1 0
      apt-pkg/deb/debmetaindex.h
  38. 15 1
      apt-pkg/deb/debsrcrecords.cc
  39. 1 0
      apt-pkg/deb/debsrcrecords.h
  40. 2 2
      apt-pkg/deb/debsystem.cc
  41. 220 88
      apt-pkg/deb/dpkgpm.cc
  42. 5 2
      apt-pkg/deb/dpkgpm.h
  43. 118 61
      apt-pkg/depcache.cc
  44. 47 4
      apt-pkg/depcache.h
  45. 14 11
      apt-pkg/indexcopy.cc
  46. 10 12
      apt-pkg/indexcopy.h
  47. 0 1
      apt-pkg/indexfile.cc
  48. 7 7
      apt-pkg/indexrecords.cc
  49. 16 6
      apt-pkg/init.cc
  50. 6 2
      apt-pkg/init.h
  51. 11 11
      apt-pkg/makefile
  52. 7 1
      apt-pkg/metaindex.h
  53. 44 29
      apt-pkg/orderlist.cc
  54. 46 22
      apt-pkg/packagemanager.cc
  55. 1 1
      apt-pkg/packagemanager.h
  56. 61 8
      apt-pkg/pkgcache.cc
  57. 26 25
      apt-pkg/pkgcache.h
  58. 23 19
      apt-pkg/pkgcachegen.cc
  59. 4 4
      apt-pkg/pkgcachegen.h
  60. 4 4
      apt-pkg/pkgrecords.h
  61. 82 2
      apt-pkg/policy.cc
  62. 1 0
      apt-pkg/policy.h
  63. 10 3
      apt-pkg/sourcelist.cc
  64. 16 5
      apt-pkg/tagfile.cc
  65. 4 1
      apt-pkg/tagfile.h
  66. 10 9
      apt-pkg/vendorlist.cc
  67. 24 13
      apt-pkg/versionmatch.cc
  68. 13 8
      apt-pkg/versionmatch.h
  69. 0 1526
      buildlib/config.guess
  70. 1 0
      buildlib/config.h.in
  71. 0 1658
      buildlib/config.sub
  72. 7 1
      buildlib/configure.mak
  73. 12 14
      buildlib/defaults.mak
  74. 4 9
      buildlib/environment.mak.in
  75. 1 1
      buildlib/library.mak
  76. 21 0
      buildlib/libversion.mak
  77. 1 1
      buildlib/manpage.mak
  78. 61 0
      buildlib/po4a_manpage.mak
  79. 0 45
      buildlib/sgml_manpage.mak
  80. 2 1
      buildlib/sizetable
  81. 0 50
      buildlib/tools.m4
  82. 0 45
      buildlib/xml_manpage.mak
  83. 0 42
      buildlib/yodl_manpage.mak
  84. 14 15
      cmdline/apt-cache.cc
  85. 4 8
      cmdline/apt-cdrom.cc
  86. 2 2
      cmdline/apt-config.cc
  87. 2 2
      cmdline/apt-extracttemplates.cc
  88. 244 139
      cmdline/apt-get.cc
  89. 11 7
      cmdline/apt-key
  90. 10 5
      cmdline/apt-mark
  91. 4 4
      cmdline/apt-sortpkgs.cc
  92. 9 10
      configure.in
  93. 0 13
      debian/.cvsignore
  94. 43 0
      debian/NEWS
  95. 0 18
      debian/NEWS.Debian
  96. 0 6
      debian/apt-utils.manpages
  97. 1 0
      debian/apt.conf.autoremove
  98. 200 176
      debian/apt.cron.daily
  99. 1 0
      debian/apt.dirs
  100. 0 0
      debian/apt.logrotate

+ 0 - 2
.bzr-builddeb/default.conf.orig

@@ -1,2 +0,0 @@
-[BUILDDEB]
-native = true

+ 22 - 0
.bzrignore

@@ -0,0 +1,22 @@
+# temporary and backup files
+*~
+*.bak
+*.rej
+
+# buildrelated files/dirs
+aclocal.m4
+autom4te.cache/
+build/
+configure
+
+# generated files in the progress to build all
+# apt man pages and other documentation
+doc/*.1
+doc/*.5
+doc/*.8
+doc/*/*.1
+doc/*/*.5
+doc/*/*.8
+doc/*/apt.ent
+doc/*/*.xml
+doc/*/*.sgml

+ 0 - 4
.cvsignore

@@ -1,4 +0,0 @@
-autom4te.cache
-aclocal.m4
-configure
-build

+ 16 - 135
COPYING

@@ -1,142 +1,23 @@
 Apt is copyright 1997, 1998, 1999 Jason Gunthorpe and others.
+Apt is currently developed by APT Development Team <deity@lists.debian.org>.
 
-Apt is licensed under the terms of the GNU General Public License (GPL),
-version 2.0 or later, as published by the Free Software Foundation.  See
-the file COPYING.GPL [included], /usr/share/common-licenses/GPL, or
-<http://www.gnu.org/copyleft/gpl.txt> for the terms of the latest version
-of the GNU General Public License.
-
-In addition, prior to November 15th, 2000, apt may be distributed under
-terms identical to the above with the following addition:
-
-Works using apt may link against the GUI library "libqt", copyright by
-Troll Tech AS, Norway, provided that:
-
-1. The version of "libqt" is licensed under the terms of the "Qt Free Edition
-   License" published by Troll Tech AS.  The license terms identified as
-   the Qt Free Edition License below are the only such terms under which
-   distribution of works derived from both apt and "libqt" are permitted;
-
-and
-
-2. The source code of the version of "libqt" used is
-
-   a) Distributed with the binary version;
-
-   or
-
-   b) Downloadable by anyone, without fee, using a publicly-announced
-      URL on the Internet, for a duration of at least three years
-      starting with distribution of the binary version.
-
-On and after November 15th, 2000, the above additional terms lose all
-force, and apt will be licensed only under the terms of the GNU General
-Public License, version 2.0 or later.
-
-      _______________________________________________________________
-
-The following text, up to the text of the Qt Free Edition License, is
-informational and not part of the license terms on apt.
-
-Modifications to apt in either source or compiled form must be licensed
-under the terms of the GNU General Public License, version 2.0 (or later),
-but need not include the above clause permitting usage of the "libqt"
-library under the Qt Free Edition License.  Note that removal of this
-clause will result in software which is not licensed for binary
-redistribution linked against software governed by the Qt Free Edition
-License.  In the event that a version of "libqt" is released that is
-licensed under terms that do not conflict with the GPL, the additional
-clause above is not required to grant permission for distribution of works
-that are derived from both apt and "libqt".
-
-No part of apt is licensed under the Qt Free Edition License.  The terms
-below are provided to help identify the circumstances under which the
-"libqt" library may be used with apt (or a work derived from both).  The
-terms below are copied from the LICENSE file of the qt-1.44 distribution,
-as of November 10th, 1999.
-
-      _______________________________________________________________
-
-                        QT FREE EDITION LICENSE
+License: GPLv2+
 
-Copyright (C) 1992-1999 Troll Tech AS. All rights reserved. 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
 
-This is the license for Qt Free Edition version 1.44; it covers private use,
-use of third-party application programs based on Qt, and development of
-free software for the free software community. 
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
 
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
 
-                      COPYRIGHT AND RESTRICTIONS
-
-The Qt toolkit is a product of Troll Tech AS. The Qt Free Edition is limited
-to use with the X Window System. 
-
-You may copy this version of the Qt Free Edition provided that the entire
-archive is distributed unchanged and as a whole, including this notice. 
-
-You may use this version of the Qt Free Edition to compile, link and run
-application programs legally developed by third parties. 
-
-You may use the Qt Free Edition to create application programs
-provided that: 
-
-      You accept this license. 
-      Your software does not require modifications to Qt Free Edition.
-      You satisfy ONE of the following three requirements 
-      EITHER 
-            Users of your software can freely obtain source code for the
-            software, freely modify the source code (possibly with
-            restrictions on copyright notices, attributions and legal
-            responsibility), and freely redistribute original or modified
-            versions of the software. 
-      OR 
-            Your software is distributed under the GNU GENERAL
-            PUBLIC LICENSE, version 2 or later, as defined by the
-            Free Software Foundation. 
-      OR 
-            Your software is distributed under the GNU LIBRARY
-            GENERAL PUBLIC LICENSE, version 2 or later, as
-            defined by the Free Software Foundation. 
-
-If you are paid to develop something with Qt Free Edition or it is a part of
-your job the following conditions also apply: 
-
-      Your software must not require libraries, programs, data or
-      documentation that are not available outside your organization in
-      order to compile or use. 
-      If and when your organization starts using the software, you must
-      notify Troll Tech AS of the following: 
-            Your organization's name and purpose. 
-            The software's name and purpose. 
-            The software's license. 
-            That your organization considers the software to be free
-            software. 
-
-You may also use the Qt Free Edition to create reusable components
-(such as libraries) provided that you accept the terms above, and in
-addition that: 
-
-      Your components' license includes the following text: 
-
-            [Your package] requires the Qt library, which is
-            copyright Troll Tech AS. Freely distributable
-            programs may generally use Qt Free Edition free of
-            charge, see [README.QT] for details. 
-
-      README.QT is distributed along with your components. 
-      Qt Free Edition is not distributed as an integral part of your
-      components. 
-
-                       LIMITATIONS OF LIABILITY
-
-Troll Tech AS makes no obligation under this license to support or
-upgrade Qt Free Edition, or assist in the use of Qt Free Edition. 
-
-In no event shall Troll Tech AS be liable for any lost revenue or profits or
-other direct, indirect, special, incidental or consequential damages, even
-if Troll Tech has been advised of the possibility of such damages. 
+See /usr/share/common-licenses/GPL-2, or
+<http://www.gnu.org/copyleft/gpl.txt> for the terms of the latest version
+of the GNU General Public License.
 
-QT FREE EDITION IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND,
-INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
-PARTICULAR PURPOSE.
-      _______________________________________________________________

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

@@ -87,7 +87,7 @@ bool ARArchive::LoadHeaders()
 	  StrToNum(Head.Size,Memb->Size,sizeof(Head.Size)) == false)
       {
 	 delete Memb;
-	 return _error->Error(_("Invalid archive member header"));
+	 return _error->Error(_("Invalid archive member header %s"), Head.Name);
       }
 	 
       // Check for an extra long name string
@@ -96,7 +96,7 @@ bool ARArchive::LoadHeaders()
 	 char S[300];
 	 unsigned long Len;
 	 if (StrToNum(Head.Name+3,Len,sizeof(Head.Size)-3) == false ||
-	     Len >= strlen(S))
+	     Len >= sizeof(S))
 	 {
 	    delete Memb;
 	    return _error->Error(_("Invalid archive member header"));
@@ -111,7 +111,7 @@ bool ARArchive::LoadHeaders()
       else
       {
 	 unsigned int I = sizeof(Head.Name) - 1;
-	 for (; Head.Name[I] == ' '; I--);
+	 for (; Head.Name[I] == ' ' || Head.Name[I] == '/'; I--);
 	 Memb->Name = string(Head.Name,I+1);
       }
 

+ 3 - 1
apt-inst/makefile

@@ -9,9 +9,11 @@ HEADER_TARGETDIRS = apt-pkg
 # Bring in the default rules
 include ../buildlib/defaults.mak
 
+# The library name and version (indirectly used from init.h)
+include ../buildlib/libversion.mak
+
 # The library name
 LIBRARY=apt-inst
-LIBEXT=$(GLIBC_VER)$(LIBSTDCPP_VER)
 MAJOR=1.1
 MINOR=0
 SLIBS=$(PTHREADLIB) -lapt-pkg

+ 75 - 92
apt-pkg/acquire-item.cc

@@ -15,6 +15,7 @@
 // Include Files							/*{{{*/
 #include <apt-pkg/acquire-item.h>
 #include <apt-pkg/configuration.h>
+#include <apt-pkg/aptconfiguration.h>
 #include <apt-pkg/sourcelist.h>
 #include <apt-pkg/vendorlist.h>
 #include <apt-pkg/error.h>
@@ -131,9 +132,7 @@ void pkgAcquire::Item::Rename(string From,string To)
    }   
 }
 									/*}}}*/
-
-
-// AcqDiffIndex::AcqDiffIndex - Constructor			
+// AcqDiffIndex::AcqDiffIndex - Constructor				/*{{{*/
 // ---------------------------------------------------------------------
 /* Get the DiffIndex file first and see if there are patches availabe 
  * If so, create a pkgAcqIndexDiffs fetcher that will get and apply the
@@ -184,7 +183,7 @@ pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner,
    QueueURI(Desc);
 
 }
-
+									/*}}}*/
 // AcqIndex::Custom600Headers - Insert custom request headers		/*{{{*/
 // ---------------------------------------------------------------------
 /* The only header we use is the last-modified header. */
@@ -202,9 +201,8 @@ string pkgAcqDiffIndex::Custom600Headers()
    
    return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
 }
-
-
-bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile)
+									/*}}}*/
+bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile)		/*{{{*/
 {
    if(Debug)
       std::clog << "pkgAcqIndexDiffs::ParseIndexDiff() " << IndexDiffFile 
@@ -291,8 +289,8 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile)
       std::clog << "Can't find a patch in the index file" << std::endl;
    return false;
 }
-
-void pkgAcqDiffIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
+									/*}}}*/
+void pkgAcqDiffIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)	/*{{{*/
 {
    if(Debug)
       std::clog << "pkgAcqDiffIndex failed: " << Desc.URI << std::endl
@@ -305,8 +303,8 @@ void pkgAcqDiffIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
    Status = StatDone;
    Dequeue();
 }
-
-void pkgAcqDiffIndex::Done(string Message,unsigned long Size,string Md5Hash,
+									/*}}}*/
+void pkgAcqDiffIndex::Done(string Message,unsigned long Size,string Md5Hash,	/*{{{*/
 			   pkgAcquire::MethodConfig *Cnf)
 {
    if(Debug)
@@ -335,10 +333,8 @@ void pkgAcqDiffIndex::Done(string Message,unsigned long Size,string Md5Hash,
    Dequeue();
    return;
 }
-
-
-
-// AcqIndexDiffs::AcqIndexDiffs - Constructor			
+									/*}}}*/
+// AcqIndexDiffs::AcqIndexDiffs - Constructor				/*{{{*/
 // ---------------------------------------------------------------------
 /* The package diff is added to the queue. one object is constructed
  * for each diff and the index
@@ -372,9 +368,8 @@ pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire *Owner,
       QueueNextDiff();
    }
 }
-
-
-void pkgAcqIndexDiffs::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
+									/*}}}*/
+void pkgAcqIndexDiffs::Failed(string Message,pkgAcquire::MethodConfig *Cnf)	/*{{{*/
 {
    if(Debug)
       std::clog << "pkgAcqIndexDiffs failed: " << Desc.URI << std::endl
@@ -383,9 +378,8 @@ void pkgAcqIndexDiffs::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
 		   ExpectedHash);
    Finish();
 }
-
-
-// helper that cleans the item out of the fetcher queue
+									/*}}}*/
+// Finish - helper that cleans the item out of the fetcher queue	/*{{{*/
 void pkgAcqIndexDiffs::Finish(bool allDone)
 {
    // we restore the original name, this is required, otherwise
@@ -420,10 +414,8 @@ void pkgAcqIndexDiffs::Finish(bool allDone)
    Dequeue();
    return;
 }
-
-
-
-bool pkgAcqIndexDiffs::QueueNextDiff()
+									/*}}}*/
+bool pkgAcqIndexDiffs::QueueNextDiff()					/*{{{*/
 {
 
    // calc sha1 of the just patched file
@@ -469,10 +461,8 @@ bool pkgAcqIndexDiffs::QueueNextDiff()
 
    return true;
 }
-
-
-
-void pkgAcqIndexDiffs::Done(string Message,unsigned long Size,string Md5Hash,
+									/*}}}*/
+void pkgAcqIndexDiffs::Done(string Message,unsigned long Size,string Md5Hash,	/*{{{*/
 			    pkgAcquire::MethodConfig *Cnf)
 {
    if(Debug)
@@ -543,8 +533,7 @@ void pkgAcqIndexDiffs::Done(string Message,unsigned long Size,string Md5Hash,
 	 return Finish(true);
    }
 }
-
-
+									/*}}}*/
 // AcqIndex::AcqIndex - Constructor					/*{{{*/
 // ---------------------------------------------------------------------
 /* The package file is added to the queue and a second class is 
@@ -563,13 +552,14 @@ pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner,
    if(comprExt.empty()) 
    {
       // autoselect the compression method
-      if(FileExists("/bin/bzip2")) 
-	 CompressionExtension = ".bz2";
-      else 
-	 CompressionExtension = ".gz";
-   } else {
-      CompressionExtension = (comprExt == "plain" ? "" : comprExt);
+      std::vector<std::string> types = APT::Configuration::getCompressionTypes();
+      if (types.empty() == true)
+	 comprExt = "plain";
+      else
+	 comprExt = "." + types[0];
    }
+   CompressionExtension = ((comprExt == "plain" || comprExt == ".") ? "" : comprExt);
+
    Desc.URI = URI + CompressionExtension;
 
    Desc.Description = URIDesc;
@@ -594,27 +584,29 @@ string pkgAcqIndex::Custom600Headers()
    return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
 }
 									/*}}}*/
-
-void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
+void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)	/*{{{*/
 {
-   bool descChanged = false;
-   // no .bz2 found, retry with .gz
-   if(Desc.URI.substr(Desc.URI.size()-3) == "bz2") {
-      Desc.URI = Desc.URI.substr(0,Desc.URI.size()-3) + "gz";
-
-      new pkgAcqIndex(Owner, RealURI, Desc.Description,Desc.ShortDesc,
-		      ExpectedHash, string(".gz"));
-	  descChanged = true;
-   }
-   // no .gz found, retry with uncompressed
-   else if(Desc.URI.substr(Desc.URI.size()-2) == "gz") {
-      Desc.URI = Desc.URI.substr(0,Desc.URI.size()-2);
+   std::vector<std::string> types = APT::Configuration::getCompressionTypes();
 
-      new pkgAcqIndex(Owner, RealURI, Desc.Description,Desc.ShortDesc,
-		      ExpectedHash, string("plain"));
-	  descChanged = true;
-   }
-   if (descChanged) {
+   for (std::vector<std::string>::const_iterator t = types.begin();
+	t != types.end(); t++)
+   {
+      // jump over all already tried compression types
+      const unsigned int nameLen = Desc.URI.size() - (*t).size();
+      if(Desc.URI.substr(nameLen) != *t)
+	 continue;
+
+      // we want to try it with the next extension (and make sure to 
+      // not skip over the end)
+      t++;
+      if (t == types.end())
+	 break;
+
+      // queue new download
+      Desc.URI = Desc.URI.substr(0, nameLen) + *t;
+      new pkgAcqIndex(Owner, RealURI, Desc.Description, Desc.ShortDesc,
+      ExpectedHash, string(".").append(*t));
+      
       Status = StatDone;
       Complete = false;
       Dequeue();
@@ -630,8 +622,7 @@ void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
 
    Item::Failed(Message,Cnf);
 }
-
-
+									/*}}}*/
 // AcqIndex::Done - Finished a fetch					/*{{{*/
 // ---------------------------------------------------------------------
 /* This goes through a number of states.. On the initial fetch the
@@ -712,11 +703,11 @@ void pkgAcqIndex::Done(string Message,unsigned long Size,string Hash,
       Local = true;
    
    string compExt = flExtension(flNotDir(URI(Desc.URI).Path));
-   const char *decompProg;
-   if(compExt == "bz2") 
-      decompProg = "bzip2";
-   else if(compExt == "gz") 
-      decompProg = "gzip";
+   string decompProg;
+
+   // get the binary name for your used compression type
+   decompProg = _config->Find(string("Acquire::CompressionTypes::").append(compExt),"");
+   if(decompProg.empty() == false);
    // flExtensions returns the full name if no extension is found
    // this is why we have this complicated compare operation here
    // FIMXE: add a new flJustExtension() that return "" if no
@@ -731,11 +722,11 @@ void pkgAcqIndex::Done(string Message,unsigned long Size,string Hash,
 
    Decompression = true;
    DestFile += ".decomp";
-   Desc.URI = string(decompProg) + ":" + FileName;
+   Desc.URI = decompProg + ":" + FileName;
    QueueURI(Desc);
-   Mode = decompProg;
+   Mode = decompProg.c_str();
 }
-
+									/*}}}*/
 // AcqIndexTrans::pkgAcqIndexTrans - Constructor			/*{{{*/
 // ---------------------------------------------------------------------
 /* The Translation file is added to the queue */
@@ -744,7 +735,6 @@ pkgAcqIndexTrans::pkgAcqIndexTrans(pkgAcquire *Owner,
   : pkgAcqIndex(Owner, URI, URIDesc, ShortDesc, HashString(), "")
 {
 }
-
 									/*}}}*/
 // AcqIndexTrans::Failed - Silence failure messages for missing files	/*{{{*/
 // ---------------------------------------------------------------------
@@ -764,8 +754,7 @@ void pkgAcqIndexTrans::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
    Item::Failed(Message,Cnf);
 }
 									/*}}}*/
-
-pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner,
+pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner,				/*{{{*/
 			     string URI,string URIDesc,string ShortDesc,
 			     string MetaIndexURI, string MetaIndexURIDesc,
 			     string MetaIndexShortDesc,
@@ -854,7 +843,7 @@ void pkgAcqMetaSig::Done(string Message,unsigned long Size,string MD5,
 
 }
 									/*}}}*/
-void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
+void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)/*{{{*/
 {
    string Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI);
 
@@ -890,8 +879,8 @@ void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
    
    Item::Failed(Message,Cnf);
 }
-
-pkgAcqMetaIndex::pkgAcqMetaIndex(pkgAcquire *Owner,
+									/*}}}*/
+pkgAcqMetaIndex::pkgAcqMetaIndex(pkgAcquire *Owner,			/*{{{*/
 				 string URI,string URIDesc,string ShortDesc,
 				 string SigFile,
 				 const vector<struct IndexTarget*>* IndexTargets,
@@ -910,7 +899,6 @@ pkgAcqMetaIndex::pkgAcqMetaIndex(pkgAcquire *Owner,
 
    QueueURI(Desc);
 }
-
 									/*}}}*/
 // pkgAcqMetaIndex::Custom600Headers - Insert custom request headers	/*{{{*/
 // ---------------------------------------------------------------------
@@ -926,8 +914,8 @@ string pkgAcqMetaIndex::Custom600Headers()
    
    return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
 }
-
-void pkgAcqMetaIndex::Done(string Message,unsigned long Size,string Hash,
+									/*}}}*/
+void pkgAcqMetaIndex::Done(string Message,unsigned long Size,string Hash,	/*{{{*/
 			   pkgAcquire::MethodConfig *Cfg)
 {
    Item::Done(Message,Size,Hash,Cfg);
@@ -968,8 +956,8 @@ void pkgAcqMetaIndex::Done(string Message,unsigned long Size,string Hash,
       }
    }
 }
-
-void pkgAcqMetaIndex::RetrievalDone(string Message)
+									/*}}}*/
+void pkgAcqMetaIndex::RetrievalDone(string Message)			/*{{{*/
 {
    // We have just finished downloading a Release file (it is not
    // verified yet)
@@ -1007,8 +995,8 @@ void pkgAcqMetaIndex::RetrievalDone(string Message)
    chmod(FinalFile.c_str(),0644);
    DestFile = FinalFile;
 }
-
-void pkgAcqMetaIndex::AuthDone(string Message)
+									/*}}}*/
+void pkgAcqMetaIndex::AuthDone(string Message)				/*{{{*/
 {
    // At this point, the gpgv method has succeeded, so there is a
    // valid signature from a key in the trusted keyring.  We
@@ -1041,8 +1029,8 @@ void pkgAcqMetaIndex::AuthDone(string Message)
    Rename(SigFile,VerifiedSigFile);
    chmod(VerifiedSigFile.c_str(),0644);
 }
-
-void pkgAcqMetaIndex::QueueIndexes(bool verify)
+									/*}}}*/
+void pkgAcqMetaIndex::QueueIndexes(bool verify)				/*{{{*/
 {
    for (vector <struct IndexTarget*>::const_iterator Target = IndexTargets->begin();
         Target != IndexTargets->end();
@@ -1084,8 +1072,8 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify)
 			    (*Target)->ShortDesc, ExpectedIndexHash);
    }
 }
-
-bool pkgAcqMetaIndex::VerifyVendor(string Message)
+									/*}}}*/
+bool pkgAcqMetaIndex::VerifyVendor(string Message)			/*{{{*/
 {
 //    // Maybe this should be made available from above so we don't have
 //    // to read and parse it every time?
@@ -1171,9 +1159,8 @@ bool pkgAcqMetaIndex::VerifyVendor(string Message)
 
    return true;
 }
-       								/*}}}*/
-// pkgAcqMetaIndex::Failed - no Release file present or no signature
-//      file present	                                        /*{{{*/
+									/*}}}*/
+// pkgAcqMetaIndex::Failed - no Release file present or no signature file present	/*{{{*/
 // ---------------------------------------------------------------------
 /* */
 void pkgAcqMetaIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
@@ -1210,9 +1197,7 @@ void pkgAcqMetaIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
    // back to queueing Packages files without verification
    QueueIndexes(false);
 }
-
 									/*}}}*/
-
 // AcqArchive::AcqArchive - Constructor					/*{{{*/
 // ---------------------------------------------------------------------
 /* This just sets up the initial fetch environment and queues the first
@@ -1495,14 +1480,13 @@ void pkgAcqArchive::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
    }
 }
 									/*}}}*/
-// AcqArchive::IsTrusted - Determine whether this archive comes from a
-// trusted source							/*{{{*/
+// AcqArchive::IsTrusted - Determine whether this archive comes from a trusted source /*{{{*/
 // ---------------------------------------------------------------------
 bool pkgAcqArchive::IsTrusted()
 {
    return Trusted;
 }
-
+									/*}}}*/
 // AcqArchive::Finished - Fetching has finished, tidy up		/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -1514,7 +1498,6 @@ void pkgAcqArchive::Finished()
    StoreFilename = string();
 }
 									/*}}}*/
-
 // AcqFile::pkgAcqFile - Constructor					/*{{{*/
 // ---------------------------------------------------------------------
 /* The file is added to the queue */

+ 25 - 29
apt-pkg/acquire-item.h

@@ -34,7 +34,7 @@
  *  \file acquire-item.h
  */
 
-/** \brief Represents the process by which a pkgAcquire object should
+/** \brief Represents the process by which a pkgAcquire object should	{{{
  *  retrieve a file or a collection of files.
  *
  *  By convention, Item subclasses should insert themselves into the
@@ -261,8 +261,8 @@ class pkgAcquire::Item
     */
    virtual ~Item();
 };
-
-/** \brief Information about an index patch (aka diff). */
+									/*}}}*/
+/** \brief Information about an index patch (aka diff). */		/*{{{*/
 struct DiffInfo {
    /** The filename of the diff. */
    string file;
@@ -273,8 +273,8 @@ struct DiffInfo {
    /** The size of the diff. */
    unsigned long size;
 };
-
-/** \brief An item that is responsible for fetching an index file of
+									/*}}}*/
+/** \brief An item that is responsible for fetching an index file of	{{{
  *  package list diffs and starting the package list's download.
  *
  *  This item downloads the Index file and parses it, then enqueues
@@ -348,8 +348,8 @@ class pkgAcqDiffIndex : public pkgAcquire::Item
    pkgAcqDiffIndex(pkgAcquire *Owner,string URI,string URIDesc,
 		   string ShortDesc, HashString ExpectedHash);
 };
-
-/** \brief An item that is responsible for fetching all the patches
+									/*}}}*/
+/** \brief An item that is responsible for fetching all the patches	{{{
  *  that need to be applied to a given package index file.
  *
  *  After downloading and applying a single patch, this item will
@@ -477,8 +477,8 @@ class pkgAcqIndexDiffs : public pkgAcquire::Item
 		    string ShortDesc, HashString ExpectedHash,
 		    vector<DiffInfo> diffs=vector<DiffInfo>());
 };
-
-/** \brief An acquire item that is responsible for fetching an index
+									/*}}}*/
+/** \brief An acquire item that is responsible for fetching an index	{{{
  *  file (e.g., Packages or Sources).
  *
  *  \sa pkgAcqDiffIndex, pkgAcqIndexDiffs, pkgAcqIndexTrans
@@ -540,13 +540,15 @@ class pkgAcqIndex : public pkgAcquire::Item
     *
     *  \param compressExt The compression-related extension with which
     *  this index file should be downloaded, or "" to autodetect
-    *  (".bz2" is used if bzip2 is installed, ".gz" otherwise).
+    *  Compression types can be set with config Acquire::CompressionTypes,
+    *  default is ".lzma" or ".bz2" (if the needed binaries are present)
+    *  fallback is ".gz" or none.
     */
    pkgAcqIndex(pkgAcquire *Owner,string URI,string URIDesc,
 	       string ShortDesc, HashString ExpectedHash, string compressExt="");
 };
-
-/** \brief An acquire item that is responsible for fetching a
+									/*}}}*/
+/** \brief An acquire item that is responsible for fetching a		{{{
  *  translated index file.
  *
  *  The only difference from pkgAcqIndex is that transient failures
@@ -569,18 +571,12 @@ class pkgAcqIndexTrans : public pkgAcqIndex
     *  \param URIDesc A "URI-style" description of this index file.
     *
     *  \param ShortDesc A brief description of this index file.
-    *
-    *  \param ExpectedHash The expected hashsum of this index file.
-    *
-    *  \param compressExt The compression-related extension with which
-    *  this index file should be downloaded, or "" to autodetect
-    *  (".bz2" is used if bzip2 is installed, ".gz" otherwise).
     */
    pkgAcqIndexTrans(pkgAcquire *Owner,string URI,string URIDesc,
 		    string ShortDesc);
 };
-
-/** \brief Information about an index file. */
+									/*}}}*/
+/** \brief Information about an index file. */				/*{{{*/
 struct IndexTarget
 {
    /** \brief A URI from which the index file can be downloaded. */
@@ -597,8 +593,8 @@ struct IndexTarget
     */
    string MetaKey;
 };
-
-/** \brief An acquire item that downloads the detached signature
+									/*}}}*/
+/** \brief An acquire item that downloads the detached signature	{{{
  *  of a meta-index (Release) file, then queues up the release
  *  file itself.
  *
@@ -660,8 +656,8 @@ class pkgAcqMetaSig : public pkgAcquire::Item
 		 const vector<struct IndexTarget*>* IndexTargets,
 		 indexRecords* MetaIndexParser);
 };
-
-/** \brief An item that is responsible for downloading the meta-index
+									/*}}}*/
+/** \brief An item that is responsible for downloading the meta-index	{{{
  *  file (i.e., Release) itself and verifying its signature.
  *
  *  Once the download and verification are complete, the downloads of
@@ -756,8 +752,8 @@ class pkgAcqMetaIndex : public pkgAcquire::Item
 		   const vector<struct IndexTarget*>* IndexTargets,
 		   indexRecords* MetaIndexParser);
 };
-
-/** \brief An item that is responsible for fetching a package file.
+									/*}}}*/
+/** \brief An item that is responsible for fetching a package file.	{{{
  *
  *  If the package file already exists in the cache, nothing will be
  *  done.
@@ -840,8 +836,8 @@ class pkgAcqArchive : public pkgAcquire::Item
 		 pkgRecords *Recs,pkgCache::VerIterator const &Version,
 		 string &StoreFilename);
 };
-
-/** \brief Retrieve an arbitrary file to the current directory.
+									/*}}}*/
+/** \brief Retrieve an arbitrary file to the current directory.		{{{
  *
  *  The file is retrieved even if it is accessed via a URL type that
  *  normally is a NOP, such as "file".  If the download fails, the
@@ -902,7 +898,7 @@ class pkgAcqFile : public pkgAcquire::Item
 	      string Desc, string ShortDesc,
 	      const string &DestDir="", const string &DestFilename="");
 };
-
+									/*}}}*/
 /** @} */
 
 #endif

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

@@ -446,7 +446,6 @@ void pkgAcqMethod::Status(const char *Format,...)
       exit(100);
 }
 									/*}}}*/
-
 // AcqMethod::Redirect - Send a redirect message                       /*{{{*/
 // ---------------------------------------------------------------------
 /* This method sends the redirect message and also manipulates the queue
@@ -478,7 +477,6 @@ void pkgAcqMethod::Redirect(const string &NewURI)
       QueueBack = I->Next;
 }
                                                                         /*}}}*/
-
 // AcqMethod::FetchResult::FetchResult - Constructor			/*{{{*/
 // ---------------------------------------------------------------------
 /* */

+ 2 - 5
apt-pkg/acquire.cc

@@ -266,7 +266,7 @@ pkgAcquire::MethodConfig *pkgAcquire::GetConfig(string Access)
       return 0;
 
    /* if a method uses DownloadLimit, we switch to SingleInstance mode */
-   if(_config->FindI("Acquire::"+Access+"::DlLimit",0) > 0)
+   if(_config->FindI("Acquire::"+Access+"::Dl-Limit",0) > 0)
       Conf->SingleInstance = true;
     
    return Conf;
@@ -485,7 +485,7 @@ double pkgAcquire::PartialPresent()
 	 Total += (*I)->PartialSize;
    return Total;
 }
-
+									/*}}}*/
 // Acquire::UriBegin - Start iterator for the uri list			/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -502,7 +502,6 @@ pkgAcquire::UriIterator pkgAcquire::UriEnd()
    return UriIterator(0);
 }
 									/*}}}*/
-
 // Acquire::MethodConfig::MethodConfig - Constructor			/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -516,7 +515,6 @@ pkgAcquire::MethodConfig::MethodConfig()
    Next = 0;
 }
 									/*}}}*/
-
 // Queue::Queue - Constructor						/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -728,7 +726,6 @@ void pkgAcquire::Queue::Bump()
    Cycle();
 }
 									/*}}}*/
-
 // AcquireStatus::pkgAcquireStatus - Constructor			/*{{{*/
 // ---------------------------------------------------------------------
 /* */

+ 13 - 13
apt-pkg/acquire.h

@@ -30,7 +30,7 @@
    ##################################################################### */
 									/*}}}*/
 
-/** \defgroup acquire Acquire system
+/** \defgroup acquire Acquire system					{{{
  *
  *  \brief The Acquire system is responsible for retrieving files from
  *  local or remote URIs and postprocessing them (for instance,
@@ -54,7 +54,7 @@
  *  once, but it is not clear what its behavior in this case is, and
  *  no subclass of pkgAcquire::Item seems to actually use this
  *  capability.
- */
+ */									/*}}}*/
 
 /** \addtogroup acquire
  *
@@ -78,7 +78,7 @@ using std::string;
 
 class pkgAcquireStatus;
 
-/** \brief The core download scheduler.
+/** \brief The core download scheduler.					{{{
  *
  *  This class represents an ongoing download.  It manages the lists
  *  of active and pending downloads and handles setting up and tearing
@@ -366,8 +366,8 @@ struct pkgAcquire::ItemDesc
    /** brief The underlying item which is to be downloaded. */
    Item *Owner;
 };
-
-/** \brief A single download queue in a pkgAcquire object.
+									/*}}}*/
+/** \brief A single download queue in a pkgAcquire object.		{{{
  *
  *  \todo Why so many protected values?
  */
@@ -528,8 +528,8 @@ class pkgAcquire::Queue
     */
    ~Queue();
 };
-
-/** \brief Iterates over all the URIs being fetched by a pkgAcquire object. */
+									/*}}}*/
+/** \brief Iterates over all the URIs being fetched by a pkgAcquire object.	{{{*/
 class pkgAcquire::UriIterator
 {
    /** The next queue to iterate over. */
@@ -539,7 +539,7 @@ class pkgAcquire::UriIterator
    
    public:
    
-   inline void operator ++() {operator ++();};
+   inline void operator ++() {operator ++(0);};
 
    void operator ++(int)
    {
@@ -568,8 +568,8 @@ class pkgAcquire::UriIterator
       }
    }   
 };
-
-/** \brief Information about the properties of a single acquire method. */
+									/*}}}*/
+/** \brief Information about the properties of a single acquire method.	{{{*/
 struct pkgAcquire::MethodConfig
 {
    /** \brief The next link on the acquire method list.
@@ -621,8 +621,8 @@ struct pkgAcquire::MethodConfig
     */
    MethodConfig();
 };
-
-/** \brief A monitor object for downloads controlled by the pkgAcquire class.
+									/*}}}*/
+/** \brief A monitor object for downloads controlled by the pkgAcquire class.	{{{
  *
  *  \todo Why protected members?
  *
@@ -762,7 +762,7 @@ class pkgAcquireStatus
    pkgAcquireStatus();
    virtual ~pkgAcquireStatus() {};
 };
-
+									/*}}}*/
 /** @} */
 
 #endif

+ 73 - 37
apt-pkg/algorithms.cc

@@ -442,7 +442,6 @@ bool pkgMinimizeUpgrade(pkgDepCache &Cache)
    return true;
 }
 									/*}}}*/
-
 // ProblemResolver::pkgProblemResolver - Constructor			/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -489,6 +488,36 @@ void pkgProblemResolver::MakeScores()
    unsigned long Size = Cache.Head().PackageCount;
    memset(Scores,0,sizeof(*Scores)*Size);
 
+   // Important Required Standard Optional Extra
+   signed short PrioMap[] = {
+      0,
+      _config->FindI("pkgProblemResolver::Scores::Important",3),
+      _config->FindI("pkgProblemResolver::Scores::Required",2),
+      _config->FindI("pkgProblemResolver::Scores::Standard",1),
+      _config->FindI("pkgProblemResolver::Scores::Optional",-1),
+      _config->FindI("pkgProblemResolver::Scores::Extra",-2)
+   };
+   signed short PrioEssentials = _config->FindI("pkgProblemResolver::Scores::Essentials",100);
+   signed short PrioInstalledAndNotObsolete = _config->FindI("pkgProblemResolver::Scores::NotObsolete",1);
+   signed short PrioDepends = _config->FindI("pkgProblemResolver::Scores::Depends",1);
+   signed short PrioRecommends = _config->FindI("pkgProblemResolver::Scores::Recommends",1);
+   signed short AddProtected = _config->FindI("pkgProblemResolver::Scores::AddProtected",10000);
+   signed short AddEssential = _config->FindI("pkgProblemResolver::Scores::AddEssential",5000);
+
+   if (_config->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
+      clog << "Settings used to calculate pkgProblemResolver::Scores::" << endl
+         << "  Important => " << PrioMap[1] << endl
+         << "  Required => " << PrioMap[2] << endl
+         << "  Standard => " << PrioMap[3] << endl
+         << "  Optional => " << PrioMap[4] << endl
+         << "  Extra => " << PrioMap[5] << endl
+         << "  Essentials => " << PrioEssentials << endl
+         << "  InstalledAndNotObsolete => " << PrioInstalledAndNotObsolete << endl
+         << "  Depends => " << PrioDepends << endl
+         << "  Recommends => " << PrioRecommends << endl
+         << "  AddProtected => " << AddProtected << endl
+         << "  AddEssential => " << AddEssential << endl;
+
    // Generate the base scores for a package based on its properties
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
    {
@@ -502,11 +531,9 @@ void pkgProblemResolver::MakeScores()
 	 to allow an obsolete essential packages to be removed by
 	 a conflicts on a powerfull normal package (ie libc6) */
       if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
-	 Score += 100;
+	 Score += PrioEssentials;
 
       // We transform the priority
-      // Important Required Standard Optional Extra
-      signed short PrioMap[] = {0,3,2,1,-1,-2};
       if (Cache[I].InstVerIter(Cache)->Priority <= 5)
 	 Score += PrioMap[Cache[I].InstVerIter(Cache)->Priority];
       
@@ -515,7 +542,7 @@ void pkgProblemResolver::MakeScores()
 	 if those are not obsolete
       */
       if (I->CurrentVer != 0 && Cache[I].CandidateVer != 0 && Cache[I].CandidateVerIter(Cache).Downloadable())
-	 Score += 1;
+	 Score += PrioInstalledAndNotObsolete;
    }
 
    // Now that we have the base scores we go and propogate dependencies
@@ -527,9 +554,10 @@ void pkgProblemResolver::MakeScores()
       for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false; D++)
       {
 	 if (D->Type == pkgCache::Dep::Depends || 
-	     D->Type == pkgCache::Dep::PreDepends || 
-	     D->Type == pkgCache::Dep::Recommends) 
-	    Scores[D.TargetPkg()->ID]++;
+	     D->Type == pkgCache::Dep::PreDepends)
+	    Scores[D.TargetPkg()->ID] += PrioDepends;
+	 else if (D->Type == pkgCache::Dep::Recommends)
+	    Scores[D.TargetPkg()->ID] += PrioRecommends;
       }
    }   
    
@@ -576,10 +604,10 @@ void pkgProblemResolver::MakeScores()
    for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
    {
       if ((Flags[I->ID] & Protected) != 0)
-	 Scores[I->ID] += 10000;
+	 Scores[I->ID] += AddProtected;
       if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
-	 Scores[I->ID] += 5000;
-   }   
+	 Scores[I->ID] += AddEssential;
+   }
 }
 									/*}}}*/
 // ProblemResolver::DoUpgrade - Attempt to upgrade this package		/*{{{*/
@@ -755,19 +783,21 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
       *PEnd++ = I;
    This = this;
    qsort(PList,PEnd - PList,sizeof(*PList),&ScoreSort);
-   
-/* for (pkgCache::Package **K = PList; K != PEnd; K++)
-      if (Scores[(*K)->ID] != 0)
-      {
-	 pkgCache::PkgIterator Pkg(Cache,*K);
-	 clog << Scores[(*K)->ID] << ' ' << Pkg.Name() <<
-	    ' ' << (pkgCache::Version *)Pkg.CurrentVer() << ' ' << 
-	    Cache[Pkg].InstallVer << ' ' << Cache[Pkg].CandidateVer << endl;
-      } */
+
+   if (_config->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
+   {
+      clog << "Show Scores" << endl;
+      for (pkgCache::Package **K = PList; K != PEnd; K++)
+         if (Scores[(*K)->ID] != 0)
+         {
+           pkgCache::PkgIterator Pkg(Cache,*K);
+           clog << Scores[(*K)->ID] << ' ' << Pkg << std::endl;
+         }
+   }
 
    if (Debug == true)
       clog << "Starting 2" << endl;
-   
+
    /* Now consider all broken packages. For each broken package we either
       remove the package or fix it's problem. We do this once, it should
       not be possible for a loop to form (that is a < b < c and fixing b by
@@ -882,7 +912,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 	    }
 	    
 	    if (Debug == true)
-	       clog << "Package " << I.Name() << " has broken dep on " << Start.TargetPkg().Name() << endl;
+	       clog << "Package " << I.Name() << " has broken " << Start.DepType() << " on " << Start.TargetPkg().Name() << endl;
 
 	    /* Look across the version list. If there are no possible
 	       targets then we keep the package and bail. This is necessary
@@ -964,12 +994,9 @@ bool pkgProblemResolver::Resolve(bool BrokenFix)
 			   if (Debug == true)
 			      clog << "  Removing " << I.Name() << " rather than change " << Start.TargetPkg().Name() << endl;
 			   Cache.MarkDelete(I);
-			   if (Counter > 1)
-			   {
-			      if (Scores[Pkg->ID] > Scores[I->ID])
-				 Scores[I->ID] = Scores[Pkg->ID];
-			   }			   
-			}			
+			   if (Counter > 1 && Scores[Pkg->ID] > Scores[I->ID])
+			      Scores[I->ID] = Scores[Pkg->ID];
+			}
 		     }
 		  }
 		  		  
@@ -1141,9 +1168,6 @@ bool pkgProblemResolver::ResolveByKeep()
 
    unsigned long Size = Cache.Head().PackageCount;
 
-   if (Debug == true)      
-      clog << "Entering ResolveByKeep" << endl;
-   
    MakeScores();
    
    /* We have to order the packages so that the broken fixing pass 
@@ -1156,7 +1180,21 @@ bool pkgProblemResolver::ResolveByKeep()
       *PEnd++ = I;
    This = this;
    qsort(PList,PEnd - PList,sizeof(*PList),&ScoreSort);
-   
+
+   if (_config->FindB("Debug::pkgProblemResolver::ShowScores",false) == true)
+   {
+      clog << "Show Scores" << endl;
+      for (pkgCache::Package **K = PList; K != PEnd; K++)
+         if (Scores[(*K)->ID] != 0)
+         {
+           pkgCache::PkgIterator Pkg(Cache,*K);
+           clog << Scores[(*K)->ID] << ' ' << Pkg << std::endl;
+         }
+   }
+
+   if (Debug == true)
+      clog << "Entering ResolveByKeep" << endl;
+
    // Consider each broken package 
    pkgCache::Package **LastStop = 0;
    for (pkgCache::Package **K = PList; K != PEnd; K++)
@@ -1202,8 +1240,8 @@ bool pkgProblemResolver::ResolveByKeep()
 	 while (true)
 	 {
 	    if (Debug == true)
-	       clog << "Package " << I.Name() << " has broken dep on " << Start.TargetPkg().Name() << endl;
-	    
+	       clog << "Package " << I.Name() << " has broken " << Start.DepType() << " on " << Start.TargetPkg().Name() << endl;
+
 	    // Look at all the possible provides on this package
 	    SPtrArray<pkgCache::Version *> VList = Start.AllTargets();
 	    for (pkgCache::Version **V = VList; *V != 0; V++)
@@ -1219,7 +1257,7 @@ bool pkgProblemResolver::ResolveByKeep()
 	       if ((Flags[I->ID] & Protected) == 0)
 	       {
 		  if (Debug == true)
-		     clog << "  Keeping Package " << Pkg.Name() << " due to dep" << endl;
+		     clog << "  Keeping Package " << Pkg.Name() << " due to " << Start.DepType() << endl;
 		  Cache.MarkKeep(Pkg, false, false);
 	       }
 	       
@@ -1276,7 +1314,6 @@ void pkgProblemResolver::InstallProtect()
    }   
 }
 									/*}}}*/
-
 // PrioSortList - Sort a list of versions by priority			/*{{{*/
 // ---------------------------------------------------------------------
 /* This is ment to be used in conjunction with AllTargets to get a list 
@@ -1307,7 +1344,6 @@ void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List)
    qsort(List,Count,sizeof(*List),PrioComp);
 }
 									/*}}}*/
-
 // CacheFile::ListUpdate - update the cache files                    	/*{{{*/
 // ---------------------------------------------------------------------
 /* This is a simple wrapper to update the cache. it will fetch stuff

+ 4 - 4
apt-pkg/algorithms.h

@@ -39,7 +39,7 @@
 
 using std::ostream;
 
-class pkgSimulate : public pkgPackageManager
+class pkgSimulate : public pkgPackageManager				/*{{{*/
 {
    protected:
 
@@ -75,8 +75,8 @@ private:
 
    pkgSimulate(pkgDepCache *Cache);
 };
-
-class pkgProblemResolver
+									/*}}}*/
+class pkgProblemResolver						/*{{{*/
 {
    pkgDepCache &Cache;
    typedef pkgCache::PkgIterator PkgIterator;
@@ -124,7 +124,7 @@ class pkgProblemResolver
    pkgProblemResolver(pkgDepCache *Cache);
    ~pkgProblemResolver();
 };
-
+									/*}}}*/
 bool pkgDistUpgrade(pkgDepCache &Cache);
 bool pkgApplyStatus(pkgDepCache &Cache);
 bool pkgFixBroken(pkgDepCache &Cache);

+ 90 - 0
apt-pkg/aptconfiguration.cc

@@ -0,0 +1,90 @@
+// -*- mode: cpp; mode: fold -*-
+// Description								/*{{{*/
+/* ######################################################################
+
+   Provide access methods to various configuration settings,
+   setup defaults and returns validate settings.
+
+   ##################################################################### */
+									/*}}}*/
+// Include Files							/*{{{*/
+#include <apt-pkg/fileutl.h>
+#include <apt-pkg/aptconfiguration.h>
+#include <apt-pkg/configuration.h>
+
+#include <vector>
+#include <string>
+#include <algorithm>
+									/*}}}*/
+namespace APT {
+// getCompressionTypes - Return Vector of usbale compressiontypes	/*{{{*/
+// ---------------------------------------------------------------------
+/* return a vector of compression types in the prefered order. */
+std::vector<std::string>
+const Configuration::getCompressionTypes(bool const &Cached) {
+	static std::vector<std::string> types;
+	if (types.empty() == false) {
+		if (Cached == true)
+			return types;
+		else
+			types.clear();
+	}
+
+	// setup the defaults for the compressiontypes => method mapping
+	_config->CndSet("Acquire::CompressionTypes::bz2","bzip2");
+	_config->CndSet("Acquire::CompressionTypes::lzma","lzma");
+	_config->CndSet("Acquire::CompressionTypes::gz","gzip");
+
+	// Set default application paths to check for optional compression types
+	_config->CndSet("Dir::Bin::lzma", "/usr/bin/lzma");
+	_config->CndSet("Dir::Bin::bzip2", "/bin/bzip2");
+
+	// accept non-list order as override setting for config settings on commandline
+	std::string const overrideOrder = _config->Find("Acquire::CompressionTypes::Order","");
+	if (overrideOrder.empty() == false)
+		types.push_back(overrideOrder);
+
+	// load the order setting into our vector
+	std::vector<std::string> const order = _config->FindVector("Acquire::CompressionTypes::Order");
+	for (std::vector<std::string>::const_iterator o = order.begin();
+	     o != order.end(); o++) {
+		if ((*o).empty() == true)
+			continue;
+		// ignore types we have no method ready to use
+		if (_config->Exists(string("Acquire::CompressionTypes::").append(*o)) == false)
+			continue;
+		// ignore types we have no app ready to use
+		string const appsetting = string("Dir::Bin::").append(*o);
+		if (_config->Exists(appsetting) == true) {
+			std::string const app = _config->FindFile(appsetting.c_str(), "");
+			if (app.empty() == false && FileExists(app) == false)
+				continue;
+		}
+		types.push_back(*o);
+	}
+
+	// move again over the option tree to add all missing compression types
+	::Configuration::Item const *Types = _config->Tree("Acquire::CompressionTypes");
+	if (Types != 0)
+		Types = Types->Child;
+
+	for (; Types != 0; Types = Types->Next) {
+		if (Types->Tag == "Order" || Types->Tag.empty() == true)
+			continue;
+		// ignore types we already have in the vector
+		if (std::find(types.begin(),types.end(),Types->Tag) != types.end())
+			continue;
+		// ignore types we have no app ready to use
+		string const appsetting = string("Dir::Bin::").append(Types->Value);
+		if (appsetting.empty() == false && _config->Exists(appsetting) == true) {
+			std::string const app = _config->FindFile(appsetting.c_str(), "");
+			if (app.empty() == false && FileExists(app) == false)
+				continue;
+		}
+		types.push_back(Types->Tag);
+	}
+
+	return types;
+}
+									/*}}}*/
+}

+ 46 - 0
apt-pkg/aptconfiguration.h

@@ -0,0 +1,46 @@
+// -*- mode: cpp; mode: fold -*-
+// Description								/*{{{*/
+/** \class APT::Configuration
+ *  \brief Provide access methods to various configuration settings
+ *
+ *  This class and their methods providing a layer around the usual access
+ *  methods with _config to ensure that settings are correct and to be able
+ *  to set defaults without the need to recheck it in every method again.
+ */
+									/*}}}*/
+#ifndef APT_CONFIGURATION_H
+#define APT_CONFIGURATION_H
+// Include Files							/*{{{*/
+#include <string>
+#include <vector>
+									/*}}}*/
+namespace APT {
+class Configuration {							/*{{{*/
+public:									/*{{{*/
+	/** \brief Returns a vector of usable Compression Types
+	 *
+	 *  Files can be compressed in various ways to decrease the size of the
+	 *  download. Therefore the Acquiremethods support a few compression types
+	 *  and some archives provide also a few different types. This option
+	 *  group exists to give the user the choice to prefer one type over the
+	 *  other (some compression types are very resource intensive - great if you
+	 *  have a limited download, bad if you have a really lowpowered hardware.)
+	 *
+	 *  This method ensures that the defaults are set and checks at runtime
+	 *  if the type can be used. E.g. the current default is to prefer bzip2
+	 *  over lzma and gz - if the bzip2 binary is not available it has not much
+	 *  sense in downloading the bz2 file, therefore we will not return bz2 as
+	 *  a usable compression type. The availability is checked with the settings
+	 *  in the Dir::Bin group.
+	 *
+	 *  \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 (all) Language Codes in the prefered usage order
+	 */
+	std::vector<std::string> static const getCompressionTypes(bool const &Cached = true);
+									/*}}}*/
+};
+									/*}}}*/
+}
+#endif

+ 4 - 5
apt-pkg/cachefile.cc

@@ -24,7 +24,6 @@
     
 #include <apti18n.h>
 									/*}}}*/
-
 // CacheFile::CacheFile - Constructor					/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -49,6 +48,7 @@ pkgCacheFile::~pkgCacheFile()
 /* */
 bool pkgCacheFile::BuildCaches(OpProgress &Progress,bool WithLock)
 {
+   const bool ErrorWasEmpty = _error->empty();
    if (WithLock == true)
       if (_system->Lock() == false)
 	 return false;
@@ -71,7 +71,7 @@ bool pkgCacheFile::BuildCaches(OpProgress &Progress,bool WithLock)
       return _error->Error(_("The package lists or status file could not be parsed or opened."));
 
    /* This sux, remove it someday */
-   if (_error->empty() == false)
+   if (ErrorWasEmpty == true && _error->empty() == false)
       _error->Warning(_("You may want to run apt-get update to correct these problems"));
 
    Cache = new pkgCache(Map);
@@ -92,7 +92,8 @@ bool pkgCacheFile::Open(OpProgress &Progress,bool WithLock)
    Policy = new pkgPolicy(Cache);
    if (_error->PendingError() == true)
       return false;
-   if (ReadPinFile(*Policy) == false)
+
+   if (ReadPinFile(*Policy) == false || ReadPinDir(*Policy) == false)
       return false;
    
    // Create the dependency cache
@@ -108,8 +109,6 @@ bool pkgCacheFile::Open(OpProgress &Progress,bool WithLock)
    return true;
 }
 									/*}}}*/
-
-
 // CacheFile::Close - close the cache files				/*{{{*/
 // ---------------------------------------------------------------------
 /* */

+ 30 - 20
apt-pkg/cacheiterators.h

@@ -32,7 +32,7 @@
 #define PKGLIB_CACHEITERATORS_H
 
 
-// Package Iterator
+// Package Iterator							/*{{{*/
 class pkgCache::PkgIterator
 {
    friend class pkgCache;
@@ -80,7 +80,13 @@ class pkgCache::PkgIterator
    inline PrvIterator ProvidesList() const;
    inline unsigned long Index() const {return Pkg - Owner->PkgP;};
    OkState State() const;
-   
+
+   //Nice printable representation
+   friend std::ostream& operator<<(std::ostream& out, pkgCache::PkgIterator Pkg);
+
+   const char *CandVersion() const;
+   const char *CurVersion() const;
+
    // Constructors
    inline PkgIterator(pkgCache &Owner,Package *Trg) : Pkg(Trg), Owner(&Owner),
           HashIndex(0) 
@@ -90,8 +96,8 @@ class pkgCache::PkgIterator
    };
    inline PkgIterator() : Pkg(0), Owner(0), HashIndex(0) {};
 };
-
-// Version Iterator
+									/*}}}*/
+// Version Iterator							/*{{{*/
 class pkgCache::VerIterator
 {
    Version *Ver;
@@ -111,7 +117,10 @@ class pkgCache::VerIterator
    inline bool operator ==(const VerIterator &B) const {return Ver == B.Ver;};
    inline bool operator !=(const VerIterator &B) const {return Ver != B.Ver;};
    int CompareVer(const VerIterator &B) const;
-   
+
+   // Testing
+   inline bool IsGood() const { return Ver && Owner && ! end();};
+
    // Accessors
    inline Version *operator ->() {return Ver;};
    inline Version const *operator ->() const {return Ver;};
@@ -146,8 +155,8 @@ class pkgCache::VerIterator
 	 Ver = Owner.VerP;
    };
 };
-
-// Description Iterator
+									/*}}}*/
+// Description Iterator							/*{{{*/
 class pkgCache::DescIterator
 {
    Description *Desc;
@@ -190,8 +199,8 @@ class pkgCache::DescIterator
 	 Desc = Owner.DescP;
    };
 };
-
-// Dependency iterator
+									/*}}}*/
+// Dependency iterator							/*{{{*/
 class pkgCache::DepIterator
 {
    Dependency *Dep;
@@ -249,8 +258,8 @@ class pkgCache::DepIterator
    };
    inline DepIterator() : Dep(0), Type(DepVer), Owner(0) {};
 };
-
-// Provides iterator
+									/*}}}*/
+// Provides iterator							/*{{{*/
 class pkgCache::PrvIterator
 {
    Provides *Prv;
@@ -302,8 +311,8 @@ class pkgCache::PrvIterator
 	 Prv = Owner.ProvideP;
    };
 };
-
-// Package file 
+									/*}}}*/
+// Package file								/*{{{*/
 class pkgCache::PkgFileIterator
 {
    pkgCache *Owner;
@@ -333,6 +342,7 @@ class pkgCache::PkgFileIterator
    inline const char *Component() const {return File->Component == 0?0:Owner->StrP + File->Component;};
    inline const char *Version() const {return File->Version == 0?0:Owner->StrP + File->Version;};
    inline const char *Origin() const {return File->Origin == 0?0:Owner->StrP + File->Origin;};
+   inline const char *Codename() const {return File->Codename ==0?0:Owner->StrP + File->Codename;};
    inline const char *Label() const {return File->Label == 0?0:Owner->StrP + File->Label;};
    inline const char *Site() const {return File->Site == 0?0:Owner->StrP + File->Site;};
    inline const char *Architecture() const {return File->Architecture == 0?0:Owner->StrP + File->Architecture;};
@@ -348,8 +358,8 @@ class pkgCache::PkgFileIterator
    inline PkgFileIterator(pkgCache &Owner) : Owner(&Owner), File(Owner.PkgFileP) {};
    inline PkgFileIterator(pkgCache &Owner,PackageFile *Trg) : Owner(&Owner), File(Trg) {};
 };
-
-// Version File 
+									/*}}}*/
+// Version File								/*{{{*/
 class pkgCache::VerFileIterator
 {
    pkgCache *Owner;
@@ -380,8 +390,8 @@ class pkgCache::VerFileIterator
    inline VerFileIterator() : Owner(0), FileP(0) {};
    inline VerFileIterator(pkgCache &Owner,VerFile *Trg) : Owner(&Owner), FileP(Trg) {};
 };
-
-// Description File 
+									/*}}}*/
+// Description File							/*{{{*/
 class pkgCache::DescFileIterator
 {
    pkgCache *Owner;
@@ -412,8 +422,8 @@ class pkgCache::DescFileIterator
    inline DescFileIterator() : Owner(0), FileP(0) {};
    inline DescFileIterator(pkgCache &Owner,DescFile *Trg) : Owner(&Owner), FileP(Trg) {};
 };
-
-// Inlined Begin functions cant be in the class because of order problems
+									/*}}}*/
+// Inlined Begin functions cant be in the class because of order problems /*{{{*/
 inline pkgCache::VerIterator pkgCache::PkgIterator::VersionList() const
        {return VerIterator(*Owner,Owner->VerP + Pkg->VersionList);};
 inline pkgCache::VerIterator pkgCache::PkgIterator::CurrentVer() const
@@ -432,5 +442,5 @@ inline pkgCache::VerFileIterator pkgCache::VerIterator::FileList() const
        {return VerFileIterator(*Owner,Owner->VerFileP + Ver->FileList);};
 inline pkgCache::DescFileIterator pkgCache::DescIterator::FileList() const
        {return DescFileIterator(*Owner,Owner->DescFileP + Desc->FileList);};
-
+									/*}}}*/
 #endif

+ 15 - 19
apt-pkg/cdrom.cc

@@ -160,7 +160,7 @@ bool pkgCdrom::FindPackages(string CD,
    
    return !_error->PendingError();
 }
-
+									/*}}}*/
 // Score - We compute a 'score' for a path				/*{{{*/
 // ---------------------------------------------------------------------
 /* Paths are scored based on how close they come to what I consider
@@ -210,7 +210,6 @@ int pkgCdrom::Score(string Path)
 
    return Res;
 }
-
 									/*}}}*/
 // DropBinaryArch - Dump dirs with a string like /binary-<foo>/		/*{{{*/
 // ---------------------------------------------------------------------
@@ -248,8 +247,7 @@ bool pkgCdrom::DropBinaryArch(vector<string> &List)
    
    return true;
 }
-
-
+									/*}}}*/
 // DropRepeats - Drop repeated files resulting from symlinks		/*{{{*/
 // ---------------------------------------------------------------------
 /* Here we go and stat every file that we found and strip dup inodes. */
@@ -304,7 +302,6 @@ bool pkgCdrom::DropRepeats(vector<string> &List,const char *Name)
    return true;
 }
 									/*}}}*/
-
 // ReduceSourceList - Takes the path list and reduces it		/*{{{*/
 // ---------------------------------------------------------------------
 /* This takes the list of source list expressed entires and collects
@@ -513,9 +510,8 @@ bool pkgCdrom::WriteSourceList(string Name,vector<string> &List,bool Source)
    
    return true;
 }
-
-
-bool pkgCdrom::Ident(string &ident, pkgCdromStatus *log)
+									/*}}}*/
+bool pkgCdrom::Ident(string &ident, pkgCdromStatus *log)		/*{{{*/
 {
    stringstream msg;
 
@@ -573,9 +569,8 @@ bool pkgCdrom::Ident(string &ident, pkgCdromStatus *log)
 
    return true;
 }
-
-
-bool pkgCdrom::Add(pkgCdromStatus *log)
+									/*}}}*/
+bool pkgCdrom::Add(pkgCdromStatus *log)					/*{{{*/
 {
    stringstream msg;
 
@@ -844,16 +839,16 @@ bool pkgCdrom::Add(pkgCdromStatus *log)
 
    return true;
 }
-
-
-pkgUdevCdromDevices::pkgUdevCdromDevices() 
+									/*}}}*/
+pkgUdevCdromDevices::pkgUdevCdromDevices()                     		/*{{{*/
    : libudev_handle(NULL)
 {
 
 }
+									/*}}}*/
 
 bool
-pkgUdevCdromDevices::Dlopen()
+pkgUdevCdromDevices::Dlopen()                     		        /*{{{*/
 {
    // alread open
    if(libudev_handle != NULL)
@@ -880,9 +875,9 @@ pkgUdevCdromDevices::Dlopen()
 
    return true;
 }
-
+									/*}}}*/
 vector<CdromDevice>
-pkgUdevCdromDevices::Scan()
+pkgUdevCdromDevices::Scan()                                             /*{{{*/
 {
    vector<CdromDevice> cdrom_devices;
    struct udev_enumerate *enumerate;
@@ -922,9 +917,10 @@ pkgUdevCdromDevices::Scan()
    } 
    return cdrom_devices;
 }
+									/*}}}*/
 
-
-pkgUdevCdromDevices::~pkgUdevCdromDevices()
+pkgUdevCdromDevices::~pkgUdevCdromDevices()                             /*{{{*/
 { 
    dlclose(libudev_handle);
 }
+									/*}}}*/

+ 8 - 8
apt-pkg/cdrom.h

@@ -8,7 +8,7 @@
 
 using namespace std;
 
-class pkgCdromStatus
+class pkgCdromStatus							/*{{{*/
 {
  protected:
    int totalSteps;
@@ -29,8 +29,8 @@ class pkgCdromStatus
    // Progress indicator for the Index rewriter
    virtual OpProgress* GetOpProgress() {return NULL; };
 };
-
-class pkgCdrom 
+									/*}}}*/
+class pkgCdrom								/*{{{*/
 {
  protected:
    enum {
@@ -65,17 +65,18 @@ class pkgCdrom
    bool Ident(string &ident, pkgCdromStatus *log);
    bool Add(pkgCdromStatus *log);
 };
+									/*}}}*/
 
 
 // class that uses libudev to find cdrom devices dynamically
-struct CdromDevice
+struct CdromDevice							/*{{{*/
 {
    string DeviceName;
    bool Mounted;
    string MountPath;
 };
-
-class pkgUdevCdromDevices
+									/*}}}*/
+class pkgUdevCdromDevices						/*{{{*/
 {
  protected:
    // libudev dlopen stucture
@@ -101,7 +102,6 @@ class pkgUdevCdromDevices
    bool Dlopen();
    vector<CdromDevice> Scan();
 };
-
-
+									/*}}}*/
 
 #endif

+ 0 - 1
apt-pkg/clean.cc

@@ -19,7 +19,6 @@
 #include <sys/stat.h>
 #include <unistd.h>
 									/*}}}*/
-
 // ArchiveCleaner::Go - Perform smart cleanup of the archive		/*{{{*/
 // ---------------------------------------------------------------------
 /* Scan the directory for files to erase, we check the version information

+ 30 - 21
apt-pkg/contrib/cdromutl.cc

@@ -64,35 +64,44 @@ bool UnmountCdrom(string Path)
 {
    if (IsMounted(Path) == false)
       return true;
-   
-   int Child = ExecFork();
 
-   // The child
-   if (Child == 0)
+   for (int i=0;i<3;i++)
    {
-      // Make all the fds /dev/null
-      for (int I = 0; I != 3; I++)
-	 dup2(open("/dev/null",O_RDWR),I);
+   
+      int Child = ExecFork();
 
-      if (_config->Exists("Acquire::cdrom::"+Path+"::UMount") == true)
+      // The child
+      if (Child == 0)
       {
-	 if (system(_config->Find("Acquire::cdrom::"+Path+"::UMount").c_str()) != 0)
+	 // Make all the fds /dev/null
+	 for (int I = 0; I != 3; I++)
+	    dup2(open("/dev/null",O_RDWR),I);
+
+	 if (_config->Exists("Acquire::cdrom::"+Path+"::UMount") == true)
+	 {
+	    if (system(_config->Find("Acquire::cdrom::"+Path+"::UMount").c_str()) != 0)
+	       _exit(100);
+	    _exit(0);	 	 
+	 }
+	 else
+	 {
+	    const char *Args[10];
+	    Args[0] = "umount";
+	    Args[1] = Path.c_str();
+	    Args[2] = 0;
+	    execvp(Args[0],(char **)Args);      
 	    _exit(100);
-	 _exit(0);	 	 
+	 }      
       }
-      else
-      {
-	 const char *Args[10];
-	 Args[0] = "umount";
-	 Args[1] = Path.c_str();
-	 Args[2] = 0;
-	 execvp(Args[0],(char **)Args);      
-	 _exit(100);
-      }      
+
+      // if it can not be umounted, give it a bit more time
+      // this can happen when auto-mount magic or fs/cdrom prober attack
+      if (ExecWait(Child,"umount",true) == true)
+	 return true;
+      sleep(1);
    }
 
-   // Wait for mount
-   return ExecWait(Child,"umount",true);
+   return false;
 }
 									/*}}}*/
 // MountCdrom - Mount a cdrom						/*{{{*/

+ 27 - 5
apt-pkg/contrib/configuration.cc

@@ -182,9 +182,9 @@ string Configuration::FindFile(const char *Name,const char *Default) const
    if (Itm == 0 || Itm->Value.empty() == true)
    {
       if (Default == 0)
-	 return "";
+	 return rootDir;
       else
-	 return Default;
+	 return rootDir + Default;
    }
    
    string val = Itm->Value;
@@ -223,6 +223,25 @@ string Configuration::FindDir(const char *Name,const char *Default) const
    return Res;
 }
 									/*}}}*/
+// Configuration::FindVector - Find a vector of values			/*{{{*/
+// ---------------------------------------------------------------------
+/* Returns a vector of config values under the given item */
+vector<string> Configuration::FindVector(const char *Name) const
+{
+   vector<string> Vec;
+   const Item *Top = Lookup(Name);
+   if (Top == NULL)
+      return Vec;
+
+   Item *I = Top->Child;
+   while(I != NULL)
+   {
+      Vec.push_back(I->Value);
+      I = I->Next;
+   }
+   return Vec;
+}
+									/*}}}*/
 // Configuration::FindI - Find an integer value				/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -521,6 +540,7 @@ bool ReadConfigFile(Configuration &Conf,const string &FName,bool AsSectional,
 	  F.getline(Buffer,sizeof(Buffer) / 2);
 
 	  Input += Buffer;
+	  delete[] Buffer;
 	}
       while (F.fail() && !F.eof());
 
@@ -581,9 +601,11 @@ bool ReadConfigFile(Configuration &Conf,const string &FName,bool AsSectional,
 	    InQuote = !InQuote;
 	 if (InQuote == true)
 	    continue;
-	 
-	 if (*I == '/' && I + 1 != End && I[1] == '/')
-         {
+
+	 if ((*I == '/' && I + 1 != End && I[1] == '/') ||
+	     (*I == '#' && strcmp(string(I,I+6).c_str(),"#clear") != 0 &&
+	      strcmp(string(I,I+8).c_str(),"#include") != 0))
+	 {
 	    End = I;
 	    break;
 	 }

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

@@ -31,6 +31,7 @@
 
 
 #include <string>
+#include <vector>
 #include <iostream>
 
 using std::string;
@@ -70,6 +71,8 @@ class Configuration
    string Find(const string Name,const char *Default = 0) const {return Find(Name.c_str(),Default);};
    string FindFile(const char *Name,const char *Default = 0) const;
    string FindDir(const char *Name,const char *Default = 0) const;
+   std::vector<string> FindVector(const string &Name) const;
+   std::vector<string> FindVector(const char *Name) const;
    int FindI(const char *Name,int Default = 0) const;
    int FindI(const string Name,int Default = 0) const {return FindI(Name.c_str(),Default);};
    bool FindB(const char *Name,bool Default = false) const;

+ 7 - 6
apt-pkg/contrib/error.cc

@@ -84,17 +84,17 @@ bool GlobalError::Errno(const char *Function,const char *Description,...)
    char S[400];
    vsnprintf(S,sizeof(S),Description,args);
    snprintf(S + strlen(S),sizeof(S) - strlen(S),
-	    " - %s (%i %s)",Function,errno,strerror(errno));
+	    " - %s (%i: %s)",Function,errno,strerror(errno));
 
    // Put it on the list
    Item *Itm = new Item;
    Itm->Text = S;
    Itm->Error = true;
    Insert(Itm);
-   
+
    PendingFlag = true;
 
-   return false;   
+   return false;
 }
 									/*}}}*/
 // GlobalError::WarningE - Get part of the warn string from errno	/*{{{*/
@@ -112,15 +112,16 @@ bool GlobalError::WarningE(const char *Function,const char *Description,...)
    // sprintf the description
    char S[400];
    vsnprintf(S,sizeof(S),Description,args);
-   snprintf(S + strlen(S),sizeof(S) - strlen(S)," - %s (%i %s)",Function,errno,strerror(errno));
+   snprintf(S + strlen(S),sizeof(S) - strlen(S),
+	    " - %s (%i: %s)",Function,errno,strerror(errno));
 
    // Put it on the list
    Item *Itm = new Item;
    Itm->Text = S;
    Itm->Error = false;
    Insert(Itm);
-   
-   return false;   
+
+   return false;
 }
 									/*}}}*/
 // GlobalError::Error - Add an error to the list			/*{{{*/

+ 2 - 0
apt-pkg/contrib/fileutl.cc

@@ -451,10 +451,12 @@ bool ExecWait(pid_t Pid,const char *Name,bool Reap)
       if (Reap == true)
 	 return false;
       if (WIFSIGNALED(Status) != 0)
+      {
 	 if( WTERMSIG(Status) == SIGSEGV)
 	    return _error->Error(_("Sub-process %s received a segmentation fault."),Name);
 	 else 
 	    return _error->Error(_("Sub-process %s received signal %u."),Name, WTERMSIG(Status));
+      }
 
       if (WIFEXITED(Status) != 0)
 	 return _error->Error(_("Sub-process %s returned an error code (%u)"),Name,WEXITSTATUS(Status));

+ 13 - 11
apt-pkg/contrib/hashes.cc

@@ -34,7 +34,7 @@ HashString::HashString(string Type, string Hash) : Type(Type), Hash(Hash)
 {
 }
 
-HashString::HashString(string StringedHash)
+HashString::HashString(string StringedHash)				/*{{{*/
 {
    // legacy: md5sum without "MD5Sum:" prefix
    if (StringedHash.find(":") == string::npos && StringedHash.size() == 32)
@@ -50,9 +50,8 @@ HashString::HashString(string StringedHash)
    if(_config->FindB("Debug::Hashes",false) == true)
       std::clog << "HashString(string): " << Type << " : " << Hash << std::endl;
 }
-
-
-bool HashString::VerifyFile(string filename) const
+									/*}}}*/
+bool HashString::VerifyFile(string filename) const			/*{{{*/
 {
    FileFd fd;
    MD5Summation MD5;
@@ -83,7 +82,7 @@ bool HashString::VerifyFile(string filename) const
 
    return (fileHash == Hash);
 }
-
+									/*}}}*/
 const char** HashString::SupportedHashes()
 {
    return _SupportedHashes;
@@ -94,13 +93,11 @@ bool HashString::empty() const
    return (Type.empty() || Hash.empty());
 }
 
-
 string HashString::toStr() const
 {
    return Type+string(":")+Hash;
 }
 
-
 // Hashes::AddFD - Add the contents of the FD				/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -108,11 +105,16 @@ bool Hashes::AddFD(int Fd,unsigned long Size)
 {
    unsigned char Buf[64*64];
    int Res = 0;
-   while (Size != 0)
+   int ToEOF = (Size == 0);
+   while (Size != 0 || ToEOF)
    {
-      Res = read(Fd,Buf,min(Size,(unsigned long)sizeof(Buf)));
-      if (Res < 0 || (unsigned)Res != min(Size,(unsigned long)sizeof(Buf)))
-	 return false;
+      unsigned n = sizeof(Buf);
+      if (!ToEOF) n = min(Size,(unsigned long)n);
+      Res = read(Fd,Buf,n);
+      if (Res < 0 || (!ToEOF && (unsigned) Res != n)) // error, or short read
+         return false;
+      if (ToEOF && Res == 0) // EOF
+         break;
       Size -= Res;
       MD5.Add(Buf,Res);
       SHA1.Add(Buf,Res);

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

@@ -294,11 +294,16 @@ bool MD5Summation::AddFD(int Fd,unsigned long Size)
 {
    unsigned char Buf[64*64];
    int Res = 0;
-   while (Size != 0)
+   int ToEOF = (Size == 0);
+   while (Size != 0 || ToEOF)
    {
-      Res = read(Fd,Buf,min(Size,(unsigned long)sizeof(Buf)));
-      if (Res < 0 || (unsigned)Res != min(Size,(unsigned long)sizeof(Buf)))
-	 return false;
+      unsigned n = sizeof(Buf);
+      if (!ToEOF) n = min(Size,(unsigned long)n);
+      Res = read(Fd,Buf,n);
+      if (Res < 0 || (!ToEOF && (unsigned) Res != n)) // error, or short read
+         return false;
+      if (ToEOF && Res == 0) // EOF
+         break;
       Size -= Res;
       Add(Buf,Res);
    }

+ 86 - 34
apt-pkg/contrib/mmap.cc

@@ -13,11 +13,6 @@
    libc6 generates warnings -- which should be errors, g++ isn't properly
    strict.
    
-   The configure test notes that some OS's have broken private mmap's
-   so on those OS's we can't use mmap. This means we have to use
-   configure to test mmap and can't rely on the POSIX
-   _POSIX_MAPPED_FILES test.
-   
    ##################################################################### */
 									/*}}}*/
 // Include Files							/*{{{*/
@@ -31,6 +26,7 @@
 #include <sys/stat.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <stdlib.h>
 
 #include <cstring>
    									/*}}}*/
@@ -144,7 +140,7 @@ bool MMap::Sync(unsigned long Start,unsigned long Stop)
 // DynamicMMap::DynamicMMap - Constructor				/*{{{*/
 // ---------------------------------------------------------------------
 /* */
-DynamicMMap::DynamicMMap(FileFd &F,unsigned long Flags,unsigned long WorkSpace) : 
+DynamicMMap::DynamicMMap(FileFd &F,unsigned long Flags,unsigned long WorkSpace) :
              MMap(F,Flags | NoImmMap), Fd(&F), WorkSpace(WorkSpace)
 {
    if (_error->PendingError() == true)
@@ -166,15 +162,34 @@ DynamicMMap::DynamicMMap(FileFd &F,unsigned long Flags,unsigned long WorkSpace)
 									/*}}}*/
 // DynamicMMap::DynamicMMap - Constructor for a non-file backed map	/*{{{*/
 // ---------------------------------------------------------------------
-/* This is just a fancy malloc really.. */
+/* We try here to use mmap to reserve some space - this is much more
+   cooler than the fallback solution to simply allocate a char array
+   and could come in handy later than we are able to grow such an mmap */
 DynamicMMap::DynamicMMap(unsigned long Flags,unsigned long WorkSpace) :
              MMap(Flags | NoImmMap | UnMapped), Fd(0), WorkSpace(WorkSpace)
 {
    if (_error->PendingError() == true)
       return;
-   
+
+#ifdef _POSIX_MAPPED_FILES
+   // Set the permissions.
+   int Prot = PROT_READ;
+   int Map = MAP_PRIVATE | MAP_ANONYMOUS;
+   if ((Flags & ReadOnly) != ReadOnly)
+      Prot |= PROT_WRITE;
+   if ((Flags & Public) == Public)
+      Map = MAP_SHARED | MAP_ANONYMOUS;
+
+   // use anonymous mmap() to get the memory
+   Base = (unsigned char*) mmap(0, WorkSpace, Prot, Map, -1, 0);
+
+   if(Base == MAP_FAILED)
+      _error->Errno("DynamicMMap",_("Couldn't make mmap of %lu bytes"),WorkSpace);
+#else
+   // fallback to a static allocated space
    Base = new unsigned char[WorkSpace];
    memset(Base,0,WorkSpace);
+#endif
    iSize = 0;
 }
 									/*}}}*/
@@ -185,7 +200,11 @@ DynamicMMap::~DynamicMMap()
 {
    if (Fd == 0)
    {
+#ifdef _POSIX_MAPPED_FILES
+      munmap(Base, WorkSpace);
+#else
       delete [] (unsigned char *)Base;
+#endif
       return;
    }
    
@@ -204,17 +223,19 @@ unsigned long DynamicMMap::RawAllocate(unsigned long Size,unsigned long Aln)
    unsigned long Result = iSize;
    if (Aln != 0)
       Result += Aln - (iSize%Aln);
-   
+
    iSize = Result + Size;
-   
-   // Just in case error check
-   if (Result + Size > WorkSpace)
+
+   // try to grow the buffer
+   while(Result + Size > WorkSpace)
    {
-	  _error->Error(_("Dynamic MMap ran out of room. Please increase the size "
-				  "of APT::Cache-Limit. Current value: %lu. (man 5 apt.conf)"), WorkSpace);
-      return 0;
+      if(!Grow())
+      {
+	 _error->Error(_("Dynamic MMap ran out of room. Please increase the size "
+			 "of APT::Cache-Limit. Current value: %lu. (man 5 apt.conf)"), WorkSpace);
+	 return 0;
+      }
    }
-
    return Result;
 }
 									/*}}}*/
@@ -223,7 +244,7 @@ unsigned long DynamicMMap::RawAllocate(unsigned long Size,unsigned long Aln)
 /* This allocates an Item of size ItemSize so that it is aligned to its
    size in the file. */
 unsigned long DynamicMMap::Allocate(unsigned long ItemSize)
-{   
+{
    // Look for a matching pool entry
    Pool *I;
    Pool *Empty = 0;
@@ -234,7 +255,6 @@ unsigned long DynamicMMap::Allocate(unsigned long ItemSize)
       if (I->ItemSize == ItemSize)
 	 break;
    }
-
    // No pool is allocated, use an unallocated one
    if (I == Pools + PoolCount)
    {
@@ -249,17 +269,24 @@ unsigned long DynamicMMap::Allocate(unsigned long ItemSize)
       I->ItemSize = ItemSize;
       I->Count = 0;
    }
-   
+
+   unsigned long Result = 0;
    // Out of space, allocate some more
    if (I->Count == 0)
    {
-      I->Count = 20*1024/ItemSize;
-      I->Start = RawAllocate(I->Count*ItemSize,ItemSize);
-   }   
+      const unsigned long size = 20*1024;
+      I->Count = size/ItemSize;
+      Result = RawAllocate(size,ItemSize);
+      // Does the allocation failed ?
+      if (Result == 0 && _error->PendingError())
+	 return 0;
+      I->Start = Result;
+   }
+   else
+      Result = I->Start;
 
    I->Count--;
-   unsigned long Result = I->Start;
-   I->Start += ItemSize;  
+   I->Start += ItemSize;
    return Result/ItemSize;
 }
 									/*}}}*/
@@ -269,20 +296,45 @@ unsigned long DynamicMMap::Allocate(unsigned long ItemSize)
 unsigned long DynamicMMap::WriteString(const char *String,
 				       unsigned long Len)
 {
-   unsigned long Result = iSize;
-   // Just in case error check
-   if (Result + Len > WorkSpace)
-   {
-	  _error->Error(_("Dynamic MMap ran out of room. Please increase the size "
-				  "of APT::Cache-Limit. Current value: %lu. (man 5 apt.conf)"), WorkSpace);
-      return 0;
-   }   
-   
    if (Len == (unsigned long)-1)
       Len = strlen(String);
-   iSize += Len + 1;
+
+   unsigned long Result = RawAllocate(Len+1,0);
+
+   if (Result == 0 && _error->PendingError())
+      return 0;
+
    memcpy((char *)Base + Result,String,Len);
    ((char *)Base)[Result + Len] = 0;
    return Result;
 }
 									/*}}}*/
+// DynamicMMap::Grow - Grow the mmap					/*{{{*/
+// ---------------------------------------------------------------------
+/* This method will try to grow the mmap we currently use. This doesn't
+   work most of the time because we can't move the mmap around in the
+   memory for now as this would require to adjust quite a lot of pointers
+   but why we should not at least try to grow it before we give up? */
+bool DynamicMMap::Grow()
+{
+#if defined(_POSIX_MAPPED_FILES) && defined(__linux__)
+   unsigned long newSize = WorkSpace + 1024*1024;
+
+   if(Fd != 0)
+   {
+      Fd->Seek(newSize - 1);
+      char C = 0;
+      Fd->Write(&C,sizeof(C));
+   }
+
+   Base = mremap(Base, WorkSpace, newSize, 0);
+   if(Base == MAP_FAILED)
+      return false;
+
+   WorkSpace = newSize;
+   return true;
+#else
+   return false;
+#endif
+}
+									/*}}}*/

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

@@ -84,6 +84,8 @@ class DynamicMMap : public MMap
    unsigned long WorkSpace;
    Pool *Pools;
    unsigned int PoolCount;
+
+   bool Grow();
    
    public:
 

+ 211 - 0
apt-pkg/contrib/netrc.cc

@@ -0,0 +1,211 @@
+// -*- mode: cpp; mode: fold -*-
+// Description								/*{{{*/
+// $Id: netrc.c,v 1.38 2007-11-07 09:21:35 bagder Exp $
+/* ######################################################################
+
+   netrc file parser - returns the login and password of a give host in
+                       a specified netrc-type file
+
+   Originally written by Daniel Stenberg, <daniel@haxx.se>, et al. and
+   placed into the Public Domain, do with it what you will.
+
+   ##################################################################### */
+									/*}}}*/
+
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/fileutl.h>
+#include <iostream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pwd.h>
+
+#include "netrc.h"
+
+
+/* Get user and password from .netrc when given a machine name */
+
+enum {
+  NOTHING,
+  HOSTFOUND,    /* the 'machine' keyword was found */
+  HOSTCOMPLETE, /* the machine name following the keyword was found too */
+  HOSTVALID,    /* this is "our" machine! */
+  HOSTEND /* LAST enum */
+};
+
+/* make sure we have room for at least this size: */
+#define LOGINSIZE 64
+#define PASSWORDSIZE 64
+#define NETRC DOT_CHAR "netrc"
+
+/* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */
+int parsenetrc (char *host, char *login, char *password, char *netrcfile = NULL)
+{
+  FILE *file;
+  int retcode = 1;
+  int specific_login = (login[0] != 0);
+  char *home = NULL;
+  bool netrc_alloc = false;
+  int state = NOTHING;
+
+  char state_login = 0;        /* Found a login keyword */
+  char state_password = 0;     /* Found a password keyword */
+  int state_our_login = false;  /* With specific_login,
+                                   found *our* login name */
+
+  if (!netrcfile) {
+    home = getenv ("HOME"); /* portable environment reader */
+
+    if (!home) {
+      struct passwd *pw;
+      pw = getpwuid (geteuid ());
+      if(pw)
+        home = pw->pw_dir;
+    }
+
+    if (!home)
+      return -1;
+
+    asprintf (&netrcfile, "%s%s%s", home, DIR_CHAR, NETRC);
+    if(!netrcfile)
+      return -1;
+    else
+      netrc_alloc = true;
+  }
+
+  file = fopen (netrcfile, "r");
+  if(file) {
+    char *tok;
+    char *tok_buf;
+    bool done = false;
+    char netrcbuffer[256];
+
+    while (!done && fgets(netrcbuffer, sizeof (netrcbuffer), file)) {
+      tok = strtok_r (netrcbuffer, " \t\n", &tok_buf);
+      while (!done && tok) {
+        if(login[0] && password[0]) {
+          done = true;
+          break;
+        }
+
+        switch(state) {
+        case NOTHING:
+          if (!strcasecmp ("machine", tok)) {
+            /* the next tok is the machine name, this is in itself the
+               delimiter that starts the stuff entered for this machine,
+               after this we need to search for 'login' and
+               'password'. */
+            state = HOSTFOUND;
+          }
+          break;
+        case HOSTFOUND:
+	   /* extended definition of a "machine" if we have a "/"
+	      we match the start of the string (host.startswith(token) */
+	  if ((strchr(host, '/') && strstr(host, tok) == host) ||
+	      (!strcasecmp (host, tok))) {
+            /* and yes, this is our host! */
+            state = HOSTVALID;
+            retcode = 0; /* we did find our host */
+          }
+          else
+            /* not our host */
+            state = NOTHING;
+          break;
+        case HOSTVALID:
+          /* we are now parsing sub-keywords concerning "our" host */
+          if (state_login) {
+            if (specific_login)
+              state_our_login = !strcasecmp (login, tok);
+            else
+              strncpy (login, tok, LOGINSIZE - 1);
+            state_login = 0;
+          } else if (state_password) {
+            if (state_our_login || !specific_login)
+              strncpy (password, tok, PASSWORDSIZE - 1);
+            state_password = 0;
+          } else if (!strcasecmp ("login", tok))
+            state_login = 1;
+          else if (!strcasecmp ("password", tok))
+            state_password = 1;
+          else if(!strcasecmp ("machine", tok)) {
+            /* ok, there's machine here go => */
+            state = HOSTFOUND;
+            state_our_login = false;
+          }
+          break;
+        } /* switch (state) */
+
+        tok = strtok_r (NULL, " \t\n", &tok_buf);
+      } /* while(tok) */
+    } /* while fgets() */
+
+    fclose(file);
+  }
+
+  if (netrc_alloc)
+    free(netrcfile);
+
+  return retcode;
+}
+
+void maybe_add_auth (URI &Uri, string NetRCFile)
+{
+  if (_config->FindB("Debug::Acquire::netrc", false) == true)
+     std::clog << "maybe_add_auth: " << (string)Uri 
+	       << " " << NetRCFile << std::endl;
+  if (Uri.Password.empty () == true || Uri.User.empty () == true)
+  {
+    if (NetRCFile.empty () == false)
+    {
+      char login[64] = "";
+      char password[64] = "";
+      char *netrcfile = strdupa (NetRCFile.c_str ());
+
+      // first check for a generic host based netrc entry
+      char *host = strdupa (Uri.Host.c_str ());
+      if (host && parsenetrc (host, login, password, netrcfile) == 0)
+      {
+	 if (_config->FindB("Debug::Acquire::netrc", false) == true)
+	    std::clog << "host: " << host 
+		      << " user: " << login
+		      << " pass-size: " << strlen(password)
+		      << std::endl;
+        Uri.User = string (login);
+        Uri.Password = string (password);
+	return;
+      }
+
+      // if host did not work, try Host+Path next, this will trigger
+      // a lookup uri.startswith(host) in the netrc file parser (because
+      // of the "/"
+      char *hostpath = strdupa (string(Uri.Host+Uri.Path).c_str ());
+      if (hostpath && parsenetrc (hostpath, login, password, netrcfile) == 0)
+      {
+	 if (_config->FindB("Debug::Acquire::netrc", false) == true)
+	    std::clog << "hostpath: " << hostpath
+		      << " user: " << login
+		      << " pass-size: " << strlen(password)
+		      << std::endl;
+	 Uri.User = string (login);
+	 Uri.Password = string (password);
+	 return;
+      }
+    }
+  }
+}
+
+#ifdef DEBUG
+int main(int argc, char* argv[])
+{
+  char login[64] = "";
+  char password[64] = "";
+
+  if(argc < 2)
+    return -1;
+
+  if(0 == parsenetrc (argv[1], login, password, argv[2])) {
+    printf("HOST: %s LOGIN: %s PASSWORD: %s\n", argv[1], login, password);
+  }
+}
+#endif

+ 29 - 0
apt-pkg/contrib/netrc.h

@@ -0,0 +1,29 @@
+// -*- mode: cpp; mode: fold -*-
+// Description								/*{{{*/
+// $Id: netrc.h,v 1.11 2004/01/07 09:19:35 bagder Exp $
+/* ######################################################################
+
+   netrc file parser - returns the login and password of a give host in
+                       a specified netrc-type file
+
+   Originally written by Daniel Stenberg, <daniel@haxx.se>, et al. and
+   placed into the Public Domain, do with it what you will.
+
+   ##################################################################### */
+									/*}}}*/
+#ifndef NETRC_H
+#define NETRC_H
+
+#include <apt-pkg/strutl.h>
+
+#define DOT_CHAR "."
+#define DIR_CHAR "/"
+
+// Assume: password[0]=0, host[0] != 0.
+// If login[0] = 0, search for login and password within a machine section
+// in the netrc.
+// If login[0] != 0, search for password within machine and login.
+int parsenetrc (char *host, char *login, char *password, char *filename);
+
+void maybe_add_auth (URI &Uri, string NetRCFile);
+#endif

+ 13 - 19
apt-pkg/contrib/sha256.cc

@@ -1,5 +1,5 @@
 /*
- * Cryptographic API.
+ * Cryptographic API.							{{{
  *
  * SHA-256, as specified in
  * http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf
@@ -17,7 +17,7 @@
  * Software Foundation; either version 2 of the License, or (at your option) 
  * any later version.
  *
- */
+ */									/*}}}*/
 
 #ifdef __GNUG__
 #pragma implementation "apt-pkg/sha256.h"
@@ -65,20 +65,20 @@ static inline u32 Maj(u32 x, u32 y, u32 z)
 #define H6         0x1f83d9ab
 #define H7         0x5be0cd19
 
-static inline void LOAD_OP(int I, u32 *W, const u8 *input)
+static inline void LOAD_OP(int I, u32 *W, const u8 *input)		/*{{{*/
 {
 	W[I] = (  ((u32) input[I * 4 + 0] << 24)
 		| ((u32) input[I * 4 + 1] << 16)
 		| ((u32) input[I * 4 + 2] << 8)
 		| ((u32) input[I * 4 + 3]));
 }
-
+									/*}}}*/
 static inline void BLEND_OP(int I, u32 *W)
 {
         W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16];
 }
 
-static void sha256_transform(u32 *state, const u8 *input)
+static void sha256_transform(u32 *state, const u8 *input)		/*{{{*/
 {
         u32 a, b, c, d, e, f, g, h, t1, t2;
         u32 W[64];
@@ -240,8 +240,8 @@ static void sha256_transform(u32 *state, const u8 *input)
         a = b = c = d = e = f = g = h = t1 = t2 = 0;
         memset(W, 0, 64 * sizeof(u32));
 }
-
-SHA256Summation::SHA256Summation()
+									/*}}}*/
+SHA256Summation::SHA256Summation()					/*{{{*/
 {
         Sum.state[0] = H0;
         Sum.state[1] = H1;
@@ -255,8 +255,8 @@ SHA256Summation::SHA256Summation()
         memset(Sum.buf, 0, sizeof(Sum.buf));
         Done = false;
 }
-
-bool SHA256Summation::Add(const u8 *data, unsigned long len)
+									/*}}}*/
+bool SHA256Summation::Add(const u8 *data, unsigned long len)		/*{{{*/
 {
         struct sha256_ctx *sctx = &Sum;
         unsigned int i, index, part_len;
@@ -291,8 +291,8 @@ bool SHA256Summation::Add(const u8 *data, unsigned long len)
 
         return true;
 }
-
-SHA256SumValue SHA256Summation::Result()
+									/*}}}*/
+SHA256SumValue SHA256Summation::Result()				/*{{{*/
 {
    struct sha256_ctx *sctx = &Sum;
    if (!Done) {
@@ -340,7 +340,7 @@ SHA256SumValue SHA256Summation::Result()
 
    return res;
 }
-
+									/*}}}*/
 // SHA256SumValue::SHA256SumValue - Constructs the sum from a string   /*{{{*/
 // ---------------------------------------------------------------------
 /* The string form of a SHA256 is a 64 character hex number */
@@ -349,7 +349,6 @@ SHA256SumValue::SHA256SumValue(string Str)
    memset(Sum,0,sizeof(Sum));
    Set(Str);
 }
-
                                                                        /*}}}*/
 // SHA256SumValue::SHA256SumValue - Default constructor                /*{{{*/
 // ---------------------------------------------------------------------
@@ -358,7 +357,6 @@ SHA256SumValue::SHA256SumValue()
 {
    memset(Sum,0,sizeof(Sum));
 }
-
                                                                        /*}}}*/
 // SHA256SumValue::Set - Set the sum from a string                     /*{{{*/
 // ---------------------------------------------------------------------
@@ -391,9 +389,7 @@ string SHA256SumValue::Value() const
 
    return string(Result);
 }
-
-
-
+									/*}}}*/
 // SHA256SumValue::operator == - Comparator                            /*{{{*/
 // ---------------------------------------------------------------------
 /* Call memcmp on the buffer */
@@ -402,8 +398,6 @@ bool SHA256SumValue::operator == (const SHA256SumValue & rhs) const
    return memcmp(Sum,rhs.Sum,sizeof(Sum)) == 0;
 }
                                                                        /*}}}*/
-
-
 // SHA256Summation::AddFD - Add content of file into the checksum      /*{{{*/
 // ---------------------------------------------------------------------
 /* */

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

@@ -67,9 +67,20 @@ bool UTF8ToCodeset(const char *codeset, const string &orig, string *dest)
   outbuf = new char[insize+1];
   outptr = outbuf;
 
-  iconv(cd, &inptr, &insize, &outptr, &outsize);
-  *outptr = '\0';
+  while (insize != 0)
+  {
+     size_t const err = iconv(cd, &inptr, &insize, &outptr, &outsize);
+     if (err == (size_t)(-1))
+     {
+	insize--;
+	outsize++;
+	inptr++;
+	*outptr = '?';
+	outptr++;
+     }
+  }
 
+  *outptr = '\0';
   *dest = outbuf;
   delete[] outbuf;
   
@@ -304,13 +315,13 @@ string SizeToStr(double Size)
    {
       if (ASize < 100 && I != 0)
       {
-         sprintf(S,"%.1f%c",ASize,Ext[I]);
+         sprintf(S,"%'.1f%c",ASize,Ext[I]);
 	 break;
       }
       
       if (ASize < 10000)
       {
-         sprintf(S,"%.0f%c",ASize,Ext[I]);
+         sprintf(S,"%'.0f%c",ASize,Ext[I]);
 	 break;
       }
       ASize /= 1000.0;
@@ -387,6 +398,17 @@ string SubstVar(string Str,const struct SubstVar *Vars)
    return Str;
 }
 									/*}}}*/
+// OutputInDepth - return a string with separator multiplied with depth /*{{{*/
+// ---------------------------------------------------------------------
+/* Returns a string with the supplied separator depth + 1 times in it */
+std::string OutputInDepth(const unsigned long Depth, const char* Separator)
+{
+   std::string output = "";
+   for(unsigned long d=Depth+1; d > 0; d--)
+      output.append(Separator);
+   return output;
+}
+									/*}}}*/
 // URItoFileName - Convert the uri into a unique file name		/*{{{*/
 // ---------------------------------------------------------------------
 /* This converts a URI into a safe filename. It quotes all unsafe characters

+ 8 - 6
apt-pkg/contrib/strutl.h

@@ -48,6 +48,7 @@ string DeQuoteString(const string &Str);
 string SizeToStr(double Bytes);
 string TimeToStr(unsigned long Sec);
 string Base64Encode(const string &Str);
+string OutputInDepth(const unsigned long Depth, const char* Separator="  ");
 string URItoFileName(const string &URI);
 string TimeRFC1123(time_t Date);
 bool StrToTime(const string &Val,time_t &Result);
@@ -65,16 +66,17 @@ bool CheckDomainList(const string &Host, const string &List);
 int tolower_ascii(int c);
 
 #define APT_MKSTRCMP(name,func) \
+inline int name(const char *A,const char *B) {return func(A,A+strlen(A),B,B+strlen(B));}; \
 inline int name(const char *A,const char *AEnd,const char *B) {return func(A,AEnd,B,B+strlen(B));}; \
-inline int name(string A,const char *B) {return func(A.c_str(),A.c_str()+A.length(),B,B+strlen(B));}; \
-inline int name(string A,string B) {return func(A.c_str(),A.c_str()+A.length(),B.c_str(),B.c_str()+B.length());}; \
-inline int name(string A,const char *B,const char *BEnd) {return func(A.c_str(),A.c_str()+A.length(),B,BEnd);}; 
+inline int name(const string& A,const char *B) {return func(A.c_str(),A.c_str()+A.length(),B,B+strlen(B));}; \
+inline int name(const string& A,const string& B) {return func(A.c_str(),A.c_str()+A.length(),B.c_str(),B.c_str()+B.length());}; \
+inline int name(const string& A,const char *B,const char *BEnd) {return func(A.c_str(),A.c_str()+A.length(),B,BEnd);};
 
 #define APT_MKSTRCMP2(name,func) \
 inline int name(const char *A,const char *AEnd,const char *B) {return func(A,AEnd,B,B+strlen(B));}; \
-inline int name(string A,const char *B) {return func(A.begin(),A.end(),B,B+strlen(B));}; \
-inline int name(string A,string B) {return func(A.begin(),A.end(),B.begin(),B.end());}; \
-inline int name(string A,const char *B,const char *BEnd) {return func(A.begin(),A.end(),B,BEnd);}; 
+inline int name(const string& A,const char *B) {return func(A.begin(),A.end(),B,B+strlen(B));}; \
+inline int name(const string& A,const string& B) {return func(A.begin(),A.end(),B.begin(),B.end());}; \
+inline int name(const string& A,const char *B,const char *BEnd) {return func(A.begin(),A.end(),B,BEnd);};
 
 int stringcmp(const char *A,const char *AEnd,const char *B,const char *BEnd);
 int stringcasecmp(const char *A,const char *AEnd,const char *B,const char *BEnd);

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

@@ -109,6 +109,8 @@ bool debListParser::NewVersion(pkgCache::VerIterator Ver)
       return false;
    if (ParseDepends(Ver,"Replaces",pkgCache::Dep::Replaces) == false)
       return false;
+   if (ParseDepends(Ver,"Enhances",pkgCache::Dep::Enhances) == false)
+      return false;
 
    // Obsolete.
    if (ParseDepends(Ver,"Optional",pkgCache::Dep::Suggests) == false)
@@ -637,6 +639,8 @@ bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator FileI,
       FileI->Version = WriteUniqString(Start,Stop - Start);
    if (Section.Find("Origin",Start,Stop) == true)
       FileI->Origin = WriteUniqString(Start,Stop - Start);
+   if (Section.Find("Codename",Start,Stop) == true)
+      FileI->Codename = WriteUniqString(Start,Stop - Start);
    if (Section.Find("Label",Start,Stop) == true)
       FileI->Label = WriteUniqString(Start,Stop - Start);
    if (Section.Find("Architecture",Start,Stop) == true)

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

@@ -115,6 +115,13 @@ debReleaseIndex::debReleaseIndex(string URI,string Dist)
    this->Type = "deb";
 }
 
+debReleaseIndex::~debReleaseIndex()
+{
+   for (vector<const debSectionEntry *>::const_iterator I = SectionEntries.begin();
+	I != SectionEntries.end(); I++)
+      delete *I;
+}
+
 vector <struct IndexTarget *>* debReleaseIndex::ComputeIndexTargets() const
 {
    vector <struct IndexTarget *>* IndexTargets = new vector <IndexTarget *>;

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

@@ -22,6 +22,7 @@ class debReleaseIndex : public metaIndex {
    public:
 
    debReleaseIndex(string URI, string Dist);
+   ~debReleaseIndex();
 
    virtual string ArchiveURI(string File) const {return URI + File;};
    virtual bool GetIndexes(pkgAcquire *Owner, bool GetAll=false) const;

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

@@ -135,9 +135,15 @@ bool debSrcRecordParser::Files(vector<pkgSrcRecords::File> &List)
 	 string::size_type Tmp = F.Path.rfind('.',Pos);
 	 if (Tmp == string::npos)
 	    break;
+	 if (F.Type == "tar") {
+	    // source v3 has extension 'debian.tar.*' instead of 'diff.*'
+	    if (string(F.Path, Tmp+1, Pos-Tmp) == "debian")
+	       F.Type = "diff";
+	    break;
+	 }
 	 F.Type = string(F.Path,Tmp+1,Pos-Tmp);
 	 
-	 if (F.Type == "gz" || F.Type == "bz2" || F.Type == "lzma")
+	 if (F.Type == "gz" || F.Type == "bz2" || F.Type == "lzma" || F.Type == "tar")
 	 {
 	    Pos = Tmp-1;
 	    continue;
@@ -152,3 +158,11 @@ bool debSrcRecordParser::Files(vector<pkgSrcRecords::File> &List)
    return true;
 }
 									/*}}}*/
+// SrcRecordParser::~SrcRecordParser - Destructor			/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+debSrcRecordParser::~debSrcRecordParser()
+{
+   delete[] Buffer;
+}
+									/*}}}*/

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

@@ -50,6 +50,7 @@ class debSrcRecordParser : public pkgSrcRecords::Parser
    debSrcRecordParser(string File,pkgIndexFile const *Index) 
       : Parser(Index), Fd(File,FileFd::ReadOnly), Tags(&Fd,102400), 
         Buffer(0), BufSize(0) {}
+   ~debSrcRecordParser();
 };
 
 #endif

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

@@ -17,8 +17,8 @@
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/fileutl.h>
-#include <apti18n.h>    
-
+#include <apti18n.h>
+    
 #include <sys/types.h>
 #include <unistd.h>
 #include <dirent.h>

+ 220 - 88
apt-pkg/deb/dpkgpm.cc

@@ -49,6 +49,7 @@ namespace
     std::make_pair("install",   N_("Installing %s")),
     std::make_pair("configure", N_("Configuring %s")),
     std::make_pair("remove",    N_("Removing %s")),
+    std::make_pair("purge",    N_("Completely removing %s")),
     std::make_pair("trigproc",  N_("Running post-installation trigger %s"))
   };
 
@@ -134,8 +135,14 @@ bool pkgDPkgPM::Configure(PkgIterator Pkg)
 {
    if (Pkg.end() == true)
       return false;
-   
-   List.push_back(Item(Item::Configure,Pkg));
+
+   List.push_back(Item(Item::Configure, Pkg));
+
+   // Use triggers for config calls if we configure "smart"
+   // as otherwise Pre-Depends will not be satisfied, see #526774
+   if (_config->FindB("DPkg::TriggersPending", false) == true)
+      List.push_back(Item(Item::TriggersPending, PkgIterator()));
+
    return true;
 }
 									/*}}}*/
@@ -190,6 +197,9 @@ bool pkgDPkgPM::SendV2Pkgs(FILE *F)
    // Write out the package actions in order.
    for (vector<Item>::iterator I = List.begin(); I != List.end(); I++)
    {
+      if(I->Pkg.end() == true)
+	 continue;
+
       pkgDepCache::StateCache &S = Cache[I->Pkg];
       
       fprintf(F,"%s ",I->Pkg.Name());
@@ -378,10 +388,11 @@ void pkgDPkgPM::DoTerminalPty(int master)
  */
 void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
 {
+   bool const Debug = _config->FindB("Debug::pkgDPkgProgressReporting",false);
    // the status we output
    ostringstream status;
 
-   if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
+   if (Debug == true)
       std::clog << "got from dpkg '" << line << "'" << std::endl;
 
 
@@ -396,6 +407,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
       'processing: install: pkg'
       'processing: configure: pkg'
       'processing: remove: pkg'
+      'processing: purge: pkg' - but for apt is it a ignored "unknown" action
       'processing: trigproc: trigger'
 	    
    */
@@ -408,28 +420,28 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
    TokSplitString(':', line, list, sizeof(list)/sizeof(list[0]));
    if( list[0] == NULL || list[1] == NULL || list[2] == NULL) 
    {
-      if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
+      if (Debug == true)
 	 std::clog << "ignoring line: not enough ':'" << std::endl;
       return;
    }
-   char *pkg = list[1];
-   char *action = _strstrip(list[2]);
+   const char* const pkg = list[1];
+   const char* action = _strstrip(list[2]);
 
    // 'processing' from dpkg looks like
    // 'processing: action: pkg'
    if(strncmp(list[0], "processing", strlen("processing")) == 0)
    {
       char s[200];
-      char *pkg_or_trigger = _strstrip(list[2]);
-      action =_strstrip( list[1]);
+      const char* const pkg_or_trigger = _strstrip(list[2]);
+      action = _strstrip( list[1]);
       const std::pair<const char *, const char *> * const iter =
 	std::find_if(PackageProcessingOpsBegin,
 		     PackageProcessingOpsEnd,
 		     MatchProcessingOp(action));
       if(iter == PackageProcessingOpsEnd)
       {
-	 if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
-	    std::clog << "ignoring unknwon action: " << action << std::endl;
+	 if (Debug == true)
+	    std::clog << "ignoring unknown action: " << action << std::endl;
 	 return;
       }
       snprintf(s, sizeof(s), _(iter->second), pkg_or_trigger);
@@ -440,7 +452,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
 	     << endl;
       if(OutStatusFd > 0)
 	 write(OutStatusFd, status.str().c_str(), status.str().size());
-      if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
+      if (Debug == true)
 	 std::clog << "send: '" << status.str() << "'" << endl;
       return;
    }
@@ -453,11 +465,11 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
 	     << endl;
       if(OutStatusFd > 0)
 	 write(OutStatusFd, status.str().c_str(), status.str().size());
-      if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
+      if (Debug == true)
 	 std::clog << "send: '" << status.str() << "'" << endl;
       return;
    }
-   if(strncmp(action,"conffile",strlen("conffile")) == 0)
+   else if(strncmp(action,"conffile",strlen("conffile")) == 0)
    {
       status << "pmconffile:" << list[1]
 	     << ":"  << (PackagesDone/float(PackagesTotal)*100.0) 
@@ -465,12 +477,12 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
 	     << endl;
       if(OutStatusFd > 0)
 	 write(OutStatusFd, status.str().c_str(), status.str().size());
-      if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
+      if (Debug == true)
 	 std::clog << "send: '" << status.str() << "'" << endl;
       return;
    }
 
-   vector<struct DpkgState> &states = PackageOps[pkg];
+   vector<struct DpkgState> const &states = PackageOps[pkg];
    const char *next_action = NULL;
    if(PackageOpsDone[pkg] < states.size())
       next_action = states[PackageOpsDone[pkg]].state;
@@ -493,15 +505,15 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line)
 	     << endl;
       if(OutStatusFd > 0)
 	 write(OutStatusFd, status.str().c_str(), status.str().size());
-      if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true)
+      if (Debug == true)
 	 std::clog << "send: '" << status.str() << "'" << endl;
    }
-   if (_config->FindB("Debug::pkgDPkgProgressReporting",false) == true) 
+   if (Debug == true) 
       std::clog << "(parsed from dpkg) pkg: " << pkg 
 		<< " action: " << action << endl;
 }
-
-// DPkgPM::DoDpkgStatusFd                                           	/*{{{*/
+									/*}}}*/
+// DPkgPM::DoDpkgStatusFd						/*{{{*/
 // ---------------------------------------------------------------------
 /*
  */
@@ -538,47 +550,106 @@ void pkgDPkgPM::DoDpkgStatusFd(int statusfd, int OutStatusFd)
    dpkgbuf_pos = dpkgbuf+dpkgbuf_pos-p;
 }
 									/*}}}*/
-
+// DPkgPM::WriteHistoryTag						/*{{{*/
+void pkgDPkgPM::WriteHistoryTag(string tag, string value)
+{
+   if (value.size() > 0)
+   {
+      // poor mans rstrip(", ")
+      if (value[value.size()-2] == ',' && value[value.size()-1] == ' ')
+	 value.erase(value.size() - 2, 2);
+      fprintf(history_out, "%s: %s\n", tag.c_str(), value.c_str());
+   }
+}									/*}}}*/
+// DPkgPM::OpenLog							/*{{{*/
 bool pkgDPkgPM::OpenLog()
 {
    string logdir = _config->FindDir("Dir::Log");
    if(not FileExists(logdir))
       return _error->Error(_("Directory '%s' missing"), logdir.c_str());
+
+   // get current time
+   char timestr[200];
+   time_t t = time(NULL);
+   struct tm *tmp = localtime(&t);
+   strftime(timestr, sizeof(timestr), "%F  %T", tmp);
+
+   // open terminal log
    string logfile_name = flCombine(logdir,
 				   _config->Find("Dir::Log::Terminal"));
    if (!logfile_name.empty())
    {
       term_out = fopen(logfile_name.c_str(),"a");
       chmod(logfile_name.c_str(), 0600);
-      // output current time
-      char outstr[200];
-      time_t t = time(NULL);
-      struct tm *tmp = localtime(&t);
-      strftime(outstr, sizeof(outstr), "%F  %T", tmp);
-      fprintf(term_out, "\nLog started: ");
-      fprintf(term_out, "%s", outstr);
+      fprintf(term_out, "\n\nLog started: ");
+      fprintf(term_out, "%s", timestr);
       fprintf(term_out, "\n");
    }
+
+   // write 
+   string history_name = flCombine(logdir,
+				   _config->Find("Dir::Log::History"));
+   if (!history_name.empty())
+   {
+      history_out = fopen(history_name.c_str(),"a");
+      chmod(history_name.c_str(), 0644);
+      fprintf(history_out, "\nStart-Date: %s\n", timestr);
+      string remove, purge, install, upgrade, downgrade;
+      for (pkgCache::PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
+      {
+	 if (Cache[I].NewInstall())
+	    install += I.Name() + string(" (") + Cache[I].CandVersion + string("), ");
+	 else if (Cache[I].Upgrade())
+	    upgrade += I.Name() + string(" (") + Cache[I].CurVersion + string(", ") + Cache[I].CandVersion + string("), ");
+	 else if (Cache[I].Downgrade())
+	    downgrade += I.Name() + string(" (") + Cache[I].CurVersion + string(", ") + Cache[I].CandVersion + string("), ");
+	 else if (Cache[I].Delete())
+	 {
+	    if ((Cache[I].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge)
+	       purge += I.Name() + string(" (") + Cache[I].CurVersion + string("), ");	    
+	    else
+	       remove += I.Name() + string(" (") + Cache[I].CurVersion + string("), ");	    
+	 }
+      }
+      WriteHistoryTag("Install", install);
+      WriteHistoryTag("Upgrade", upgrade);
+      WriteHistoryTag("Downgrade",downgrade);
+      WriteHistoryTag("Remove",remove);
+      WriteHistoryTag("Purge",purge);
+      fflush(history_out);
+   }
+   
    return true;
 }
-
+									/*}}}*/
+// DPkg::CloseLog							/*{{{*/
 bool pkgDPkgPM::CloseLog()
 {
+   char timestr[200];
+   time_t t = time(NULL);
+   struct tm *tmp = localtime(&t);
+   strftime(timestr, sizeof(timestr), "%F  %T", tmp);
+
    if(term_out)
    {
-      char outstr[200];
-      time_t t = time(NULL);
-      struct tm *tmp = localtime(&t);
-      strftime(outstr, sizeof(outstr), "%F  %T", tmp);
       fprintf(term_out, "Log ended: ");
-      fprintf(term_out, "%s", outstr);
+      fprintf(term_out, "%s", timestr);
       fprintf(term_out, "\n");
       fclose(term_out);
    }
    term_out = NULL;
+
+   if(history_out)
+   {
+      if (dpkg_error.size() > 0)
+	 fprintf(history_out, "Error: %s\n", dpkg_error.c_str());
+      fprintf(history_out, "End-Date: %s\n", timestr);
+      fclose(history_out);
+   }
+
    return true;
 }
-
+									/*}}}*/
 /*{{{*/
 // This implements a racy version of pselect for those architectures
 // that don't have a working implementation.
@@ -600,7 +671,6 @@ static int racy_pselect(int nfds, fd_set *readfds, fd_set *writefds,
    return retval;
 }
 /*}}}*/
-
 // DPkgPM::Go - Run the sequence					/*{{{*/
 // ---------------------------------------------------------------------
 /* This globs the operations and calls dpkg 
@@ -617,9 +687,9 @@ bool pkgDPkgPM::Go(int OutStatusFd)
    sigset_t sigmask;
    sigset_t original_sigmask;
 
-   unsigned int MaxArgs = _config->FindI("Dpkg::MaxArgs",8*1024);   
-   unsigned int MaxArgBytes = _config->FindI("Dpkg::MaxArgBytes",32*1024);
-   bool NoTriggers = _config->FindB("DPkg::NoTriggers",false);
+   unsigned int const MaxArgs = _config->FindI("Dpkg::MaxArgs",8*1024);
+   unsigned int const MaxArgBytes = _config->FindI("Dpkg::MaxArgBytes",32*1024);
+   bool const NoTriggers = _config->FindB("DPkg::NoTriggers", false);
 
    if (RunScripts("DPkg::Pre-Invoke") == false)
       return false;
@@ -627,6 +697,13 @@ bool pkgDPkgPM::Go(int OutStatusFd)
    if (RunScriptsWithPkgs("DPkg::Pre-Install-Pkgs") == false)
       return false;
 
+   // support subpressing of triggers processing for special
+   // cases like d-i that runs the triggers handling manually
+   bool const SmartConf = (_config->Find("PackageManager::Configure", "all") != "all");
+   bool const TriggersPending = _config->FindB("DPkg::TriggersPending", false);
+   if (_config->FindB("DPkg::ConfigurePending", SmartConf) == true)
+      List.push_back(Item(Item::ConfigurePending, PkgIterator()));
+
    // map the dpkg states to the operations that are performed
    // (this is sorted in the same way as Item::Ops)
    static const struct DpkgState DpkgStatesOpMap[][7] = {
@@ -640,20 +717,12 @@ bool pkgDPkgPM::Go(int OutStatusFd)
       { 
 	 {"unpacked",N_("Preparing to configure %s") },
 	 {"half-configured", N_("Configuring %s") },
-#if 0
-	 {"triggers-awaited", N_("Processing triggers for %s") },
-	 {"triggers-pending", N_("Processing triggers for %s") },
-#endif
 	 { "installed", N_("Installed %s")},
 	 {NULL, NULL}
       },
       // Remove operation
       { 
 	 {"half-configured", N_("Preparing for removal of %s")},
-#if 0
-	 {"triggers-awaited", N_("Preparing for removal of %s")},
-	 {"triggers-pending", N_("Preparing for removal of %s")},
-#endif
 	 {"half-installed", N_("Removing %s")},
 	 {"config-files",  N_("Removed %s")},
 	 {NULL, NULL}
@@ -670,16 +739,19 @@ bool pkgDPkgPM::Go(int OutStatusFd)
    // that will be [installed|configured|removed|purged] and add
    // them to the PackageOps map (the dpkg states it goes through)
    // and the PackageOpsTranslations (human readable strings)
-   for (vector<Item>::iterator I = List.begin(); I != List.end();I++)
+   for (vector<Item>::const_iterator I = List.begin(); I != List.end();I++)
    {
-      string name = (*I).Pkg.Name();
+      if((*I).Pkg.end() == true)
+	 continue;
+
+      string const name = (*I).Pkg.Name();
       PackageOpsDone[name] = 0;
       for(int i=0; (DpkgStatesOpMap[(*I).Op][i]).state != NULL;  i++) 
       {
 	 PackageOps[name].push_back(DpkgStatesOpMap[(*I).Op][i]);
 	 PackagesTotal++;
       }
-   }   
+   }
 
    stdin_is_dev_null = false;
 
@@ -687,19 +759,42 @@ bool pkgDPkgPM::Go(int OutStatusFd)
    OpenLog();
 
    // this loop is runs once per operation
-   for (vector<Item>::iterator I = List.begin(); I != List.end();)
+   for (vector<Item>::const_iterator I = List.begin(); I != List.end();)
    {
-      vector<Item>::iterator J = I;
-      for (; J != List.end() && J->Op == I->Op; J++);
+      // Do all actions with the same Op in one run
+      vector<Item>::const_iterator J = I;
+      if (TriggersPending == true)
+	 for (; J != List.end(); J++)
+	 {
+	    if (J->Op == I->Op)
+	       continue;
+	    if (J->Op != Item::TriggersPending)
+	       break;
+	    vector<Item>::const_iterator T = J + 1;
+	    if (T != List.end() && T->Op == I->Op)
+	       continue;
+	    break;
+	 }
+      else
+	 for (; J != List.end() && J->Op == I->Op; J++)
+	    /* nothing */;
 
       // Generate the argument list
       const char *Args[MaxArgs + 50];
+      
+      // Now check if we are within the MaxArgs limit
+      //
+      // this code below is problematic, because it may happen that
+      // the argument list is split in a way that A depends on B
+      // and they are in the same "--configure A B" run
+      // - with the split they may now be configured in different
+      //   runs 
       if (J - I > (signed)MaxArgs)
 	 J = I + MaxArgs;
       
       unsigned int n = 0;
       unsigned long Size = 0;
-      string Tmp = _config->Find("Dir::Bin::dpkg","dpkg");
+      string const Tmp = _config->Find("Dir::Bin::dpkg","dpkg");
       Args[n++] = Tmp.c_str();
       Size += strlen(Args[n-1]);
       
@@ -749,11 +844,23 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 	 
 	 case Item::Configure:
 	 Args[n++] = "--configure";
-	 if (NoTriggers)
-	    Args[n++] = "--no-triggers";
 	 Size += strlen(Args[n-1]);
 	 break;
-	 
+
+	 case Item::ConfigurePending:
+	 Args[n++] = "--configure";
+	 Size += strlen(Args[n-1]);
+	 Args[n++] = "--pending";
+	 Size += strlen(Args[n-1]);
+	 break;
+
+	 case Item::TriggersPending:
+	 Args[n++] = "--triggers-only";
+	 Size += strlen(Args[n-1]);
+	 Args[n++] = "--pending";
+	 Size += strlen(Args[n-1]);
+	 break;
+
 	 case Item::Install:
 	 Args[n++] = "--unpack";
 	 Size += strlen(Args[n-1]);
@@ -761,7 +868,14 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 	 Size += strlen(Args[n-1]);
 	 break;
       }
-      
+
+      if (NoTriggers == true && I->Op != Item::TriggersPending &&
+	  I->Op != Item::ConfigurePending)
+      {
+	 Args[n++] = "--no-triggers";
+	 Size += strlen(Args[n-1]);
+      }
+
       // Write in the file or package names
       if (I->Op == Item::Install)
       {
@@ -777,6 +891,8 @@ bool pkgDPkgPM::Go(int OutStatusFd)
       {
 	 for (;I != J && Size < MaxArgBytes; I++)
 	 {
+	    if((*I).Pkg.end() == true)
+	       continue;
 	    Args[n++] = I->Pkg.Name();
 	    Size += strlen(Args[n-1]);
 	 }	 
@@ -808,32 +924,36 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 
       struct	termios tt;
       struct	winsize win;
-      int	master;
-      int	slave;
+      int	master = -1;
+      int	slave = -1;
 
-      // FIXME: setup sensible signal handling (*ick*)
-      tcgetattr(0, &tt);
-      ioctl(0, TIOCGWINSZ, (char *)&win);
-      if (openpty(&master, &slave, NULL, &tt, &win) < 0) 
+      // if tcgetattr does not return zero there was a error
+      // and we do not do any pty magic
+      if (tcgetattr(0, &tt) == 0)
       {
-	 const char *s = _("Can not write log, openpty() "
-			   "failed (/dev/pts not mounted?)\n");
-	 fprintf(stderr, "%s",s);
-	 fprintf(term_out, "%s",s);
-	 master = slave = -1;
-      }  else {
-	 struct termios rtt;
-	 rtt = tt;
-	 cfmakeraw(&rtt);
-	 rtt.c_lflag &= ~ECHO;
-	 // block SIGTTOU during tcsetattr to prevent a hang if
-	 // the process is a member of the background process group
-	 // http://www.opengroup.org/onlinepubs/000095399/functions/tcsetattr.html
-	 sigemptyset(&sigmask);
-	 sigaddset(&sigmask, SIGTTOU);
-	 sigprocmask(SIG_BLOCK,&sigmask, &original_sigmask);
-	 tcsetattr(0, TCSAFLUSH, &rtt);
-	 sigprocmask(SIG_SETMASK, &original_sigmask, 0);
+	 ioctl(0, TIOCGWINSZ, (char *)&win);
+	 if (openpty(&master, &slave, NULL, &tt, &win) < 0) 
+	 {
+	    const char *s = _("Can not write log, openpty() "
+	                      "failed (/dev/pts not mounted?)\n");
+	    fprintf(stderr, "%s",s);
+            if(term_out)
+              fprintf(term_out, "%s",s);
+	    master = slave = -1;
+	 }  else {
+	    struct termios rtt;
+	    rtt = tt;
+	    cfmakeraw(&rtt);
+	    rtt.c_lflag &= ~ECHO;
+	    // block SIGTTOU during tcsetattr to prevent a hang if
+	    // the process is a member of the background process group
+	    // http://www.opengroup.org/onlinepubs/000095399/functions/tcsetattr.html
+	    sigemptyset(&sigmask);
+	    sigaddset(&sigmask, SIGTTOU);
+	    sigprocmask(SIG_BLOCK,&sigmask, &original_sigmask);
+	    tcsetattr(0, TCSAFLUSH, &rtt);
+	    sigprocmask(SIG_SETMASK, &original_sigmask, 0);
+	 }
       }
 
        // Fork dpkg
@@ -865,6 +985,15 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 	 }
 	 close(fd[0]); // close the read end of the pipe
 
+	 if (_config->FindDir("DPkg::Chroot-Directory","/") != "/") 
+	 {
+	    std::cerr << "Chrooting into " 
+		      << _config->FindDir("DPkg::Chroot-Directory") 
+		      << std::endl;
+	    if (chroot(_config->FindDir("DPkg::Chroot-Directory","/").c_str()) != 0)
+	       _exit(100);
+	 }
+
 	 if (chdir(_config->FindDir("DPkg::Run-Directory","/").c_str()) != 0)
 	    _exit(100);
 	 
@@ -903,11 +1032,9 @@ bool pkgDPkgPM::Go(int OutStatusFd)
       int Status = 0;
 
       // we read from dpkg here
-      int _dpkgin = fd[0];
+      int const _dpkgin = fd[0];
       close(fd[1]);                        // close the write end of the pipe
 
-      // the result of the waitpid call
-      int res;
       if(slave > 0)
 	 close(slave);
 
@@ -915,6 +1042,8 @@ bool pkgDPkgPM::Go(int OutStatusFd)
       sigemptyset(&sigmask);
       sigprocmask(SIG_BLOCK,&sigmask,&original_sigmask);
 
+      // the result of the waitpid call
+      int res;
       int select_ret;
       while ((res=waitpid(Child,&Status, WNOHANG)) != Child) {
 	 if(res < 0) {
@@ -981,17 +1110,20 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 	 // if it was set to "keep-dpkg-runing" then we won't return
 	 // here but keep the loop going and just report it as a error
 	 // for later
-	 bool stopOnError = _config->FindB("Dpkg::StopOnError",true);
+	 bool const stopOnError = _config->FindB("Dpkg::StopOnError",true);
 	 
 	 if(stopOnError)
 	    RunScripts("DPkg::Post-Invoke");
 
 	 if (WIFSIGNALED(Status) != 0 && WTERMSIG(Status) == SIGSEGV) 
-	    _error->Error("Sub-process %s received a segmentation fault.",Args[0]);
+	    strprintf(dpkg_error, "Sub-process %s received a segmentation fault.",Args[0]);
 	 else if (WIFEXITED(Status) != 0)
-	    _error->Error("Sub-process %s returned an error code (%u)",Args[0],WEXITSTATUS(Status));
+	    strprintf(dpkg_error, "Sub-process %s returned an error code (%u)",Args[0],WEXITSTATUS(Status));
 	 else 
-	    _error->Error("Sub-process %s exited unexpectedly",Args[0]);
+	    strprintf(dpkg_error, "Sub-process %s exited unexpectedly",Args[0]);
+
+	 if(dpkg_error.size() > 0)
+	    _error->Error(dpkg_error.c_str());
 
 	 if(stopOnError) 
 	 {

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

@@ -29,7 +29,9 @@ class pkgDPkgPM : public pkgPackageManager
    char dpkgbuf[1024];
    int dpkgbuf_pos;
    FILE *term_out;
-   
+   FILE *history_out;
+   string dpkg_error;
+
    protected:
 
    // progress reporting
@@ -53,7 +55,7 @@ class pkgDPkgPM : public pkgPackageManager
   
    struct Item
    {
-      enum Ops {Install, Configure, Remove, Purge} Op;
+      enum Ops {Install, Configure, Remove, Purge, ConfigurePending, TriggersPending} Op;
       string File;
       PkgIterator Pkg;
       Item(Ops Op,PkgIterator Pkg,string File = "") : Op(Op),
@@ -66,6 +68,7 @@ class pkgDPkgPM : public pkgPackageManager
    // Helpers
    bool RunScriptsWithPkgs(const char *Cnf);
    bool SendV2Pkgs(FILE *F);
+   void WriteHistoryTag(string tag, string value);
 
    // dpkg log
    bool OpenLog();

+ 118 - 61
apt-pkg/depcache.cc

@@ -15,6 +15,7 @@
 #include <apt-pkg/algorithms.h>
 
 #include <apt-pkg/fileutl.h>
+#include <apt-pkg/strutl.h>
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/pkgsystem.h>
 #include <apt-pkg/tagfile.h>
@@ -26,8 +27,8 @@
 #include <sys/stat.h>
 
 #include <apti18n.h>    
-
-// helper for Install-Recommends-Sections and Never-MarkAuto-Sections
+									/*}}}*/
+// helper for Install-Recommends-Sections and Never-MarkAuto-Sections	/*{{{*/
 static bool 
 ConfigValueInSubTree(const char* SubTree, const char *needle)
 {
@@ -46,9 +47,8 @@ ConfigValueInSubTree(const char* SubTree, const char *needle)
    }
    return false;
 }
-
-
-pkgDepCache::ActionGroup::ActionGroup(pkgDepCache &cache) :
+									/*}}}*/
+pkgDepCache::ActionGroup::ActionGroup(pkgDepCache &cache) :		/*{{{*/
   cache(cache), released(false)
 {
   ++cache.group_level;
@@ -76,13 +76,15 @@ pkgDepCache::ActionGroup::~ActionGroup()
 {
   release();
 }
-
+									/*}}}*/
 // DepCache::pkgDepCache - Constructors					/*{{{*/
 // ---------------------------------------------------------------------
 /* */
 pkgDepCache::pkgDepCache(pkgCache *pCache,Policy *Plcy) :
   group_level(0), Cache(pCache), PkgState(0), DepState(0)
 {
+   DebugMarker = _config->FindB("Debug::pkgDepCache::Marker", false);
+   DebugAutoInstall = _config->FindB("Debug::pkgDepCache::AutoInstall", false);
    delLocalPolicy = 0;
    LocalPolicy = Plcy;
    if (LocalPolicy == 0)
@@ -127,7 +129,7 @@ bool pkgDepCache::Init(OpProgress *Prog)
    int Done = 0;
    for (PkgIterator I = PkgBegin(); I.end() != true; I++,Done++)
    {
-      if (Prog != 0)
+      if (Prog != 0 && Done%20 == 0)
 	 Prog->Progress(Done);
       
       // Find the proper cache slot
@@ -159,8 +161,7 @@ bool pkgDepCache::Init(OpProgress *Prog)
    return true;
 } 
 									/*}}}*/
-
-bool pkgDepCache::readStateFile(OpProgress *Prog)
+bool pkgDepCache::readStateFile(OpProgress *Prog)			/*{{{*/
 {
    FileFd state_file;
    string state = _config->FindDir("Dir::State") + "extended_states";
@@ -174,6 +175,7 @@ bool pkgDepCache::readStateFile(OpProgress *Prog)
       pkgTagFile tagfile(&state_file);
       pkgTagSection section;
       int amt=0;
+      bool debug_autoremove=_config->FindB("Debug::pkgAutoRemove",false);
       while(tagfile.Step(section)) {
 	 string pkgname = section.FindS("Package");
 	 pkgCache::PkgIterator pkg=Cache->FindPkg(pkgname);
@@ -183,7 +185,7 @@ bool pkgDepCache::readStateFile(OpProgress *Prog)
 	    short reason = section.FindI("Auto-Installed", 0);
 	    if(reason > 0)
 	       PkgState[pkg->ID].Flags  |= Flag::Auto;
-	    if(_config->FindB("Debug::pkgAutoRemove",false))
+	    if(debug_autoremove)
 	       std::cout << "Auto-Installed : " << pkgname << std::endl;
 	    amt+=section.size();
 	    if(Prog != NULL)
@@ -198,10 +200,12 @@ bool pkgDepCache::readStateFile(OpProgress *Prog)
 
    return true;
 }
-
-bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly)
+									/*}}}*/
+bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly)	/*{{{*/
 {
-   if(_config->FindB("Debug::pkgAutoRemove",false))
+   bool debug_autoremove = _config->FindB("Debug::pkgAutoRemove",false);
+   
+   if(debug_autoremove)
       std::clog << "pkgDepCache::writeStateFile()" << std::endl;
 
    FileFd StateFile;
@@ -239,7 +243,7 @@ bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly)
 	    continue;
 	 bool newAuto = (PkgState[pkg->ID].Flags & Flag::Auto);
 	 if(_config->FindB("Debug::pkgAutoRemove",false))
-	    std::clog << "Update exisiting AutoInstall info: " 
+	    std::clog << "Update existing AutoInstall info: " 
 		      << pkg.Name() << std::endl;
 	 TFRewriteData rewrite[2];
 	 rewrite[0].Tag = "Auto-Installed";
@@ -256,14 +260,14 @@ bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly)
    for(pkgCache::PkgIterator pkg=Cache->PkgBegin(); !pkg.end(); pkg++) {
       if(PkgState[pkg->ID].Flags & Flag::Auto) {
 	 if (pkgs_seen.find(pkg.Name()) != pkgs_seen.end()) {
-	    if(_config->FindB("Debug::pkgAutoRemove",false))
+	    if(debug_autoremove)
 	       std::clog << "Skipping already written " << pkg.Name() << std::endl;
 	    continue;
 	 }
          // skip not installed ones if requested
          if(InstalledOnly && pkg->CurrentVer == 0)
             continue;
-	 if(_config->FindB("Debug::pkgAutoRemove",false))
+	 if(debug_autoremove)
 	    std::clog << "Writing new AutoInstall: " 
 		      << pkg.Name() << std::endl;
 	 ostr.str(string(""));
@@ -281,7 +285,7 @@ bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly)
 
    return true;
 }
-
+									/*}}}*/
 // DepCache::CheckDep - Checks a single dependency			/*{{{*/
 // ---------------------------------------------------------------------
 /* This first checks the dependency against the main target package and
@@ -699,13 +703,12 @@ void pkgDepCache::Update(PkgIterator const &Pkg)
 	   P.end() != true; P++)
 	 Update(P.ParentPkg().RevDependsList());
 }
-
 									/*}}}*/
-
 // DepCache::MarkKeep - Put the package in the keep state		/*{{{*/
 // ---------------------------------------------------------------------
 /* */
-void pkgDepCache::MarkKeep(PkgIterator const &Pkg, bool Soft, bool FromUser)
+void pkgDepCache::MarkKeep(PkgIterator const &Pkg, bool Soft, bool FromUser,
+                           unsigned long Depth)
 {
    // Simplifies other routines.
    if (Pkg.end() == true)
@@ -746,6 +749,9 @@ void pkgDepCache::MarkKeep(PkgIterator const &Pkg, bool Soft, bool FromUser)
      P.Flags &= ~Flag::Auto;
 #endif
 
+   if (DebugMarker == true)
+      std::clog << OutputInDepth(Depth) << "MarkKeep " << Pkg << " FU=" << FromUser << std::endl;
+
    RemoveSizes(Pkg);
    RemoveStates(Pkg);
 
@@ -765,7 +771,8 @@ void pkgDepCache::MarkKeep(PkgIterator const &Pkg, bool Soft, bool FromUser)
 // DepCache::MarkDelete - Put the package in the delete state		/*{{{*/
 // ---------------------------------------------------------------------
 /* */
-void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge)
+void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge,
+                             unsigned long Depth, bool FromUser)
 {
    // Simplifies other routines.
    if (Pkg.end() == true)
@@ -787,6 +794,13 @@ void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge)
    if (Pkg->VersionList == 0)
       return;
 
+   // check if we are allowed to install the package
+   if (IsDeleteOk(Pkg,rPurge,Depth,FromUser) == false)
+      return;
+
+   if (DebugMarker == true)
+      std::clog << OutputInDepth(Depth) << "MarkDelete " << Pkg << " FU=" << FromUser << std::endl;
+
    RemoveSizes(Pkg);
    RemoveStates(Pkg);
    
@@ -801,6 +815,23 @@ void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge)
    AddSizes(Pkg);
 }
 									/*}}}*/
+// DepCache::IsDeleteOk - check if it is ok to remove this package	/*{{{*/
+// ---------------------------------------------------------------------
+/* The default implementation just honors dpkg hold
+   But an application using this library can override this method
+   to control the MarkDelete behaviour */
+bool pkgDepCache::IsDeleteOk(PkgIterator const &Pkg,bool rPurge,
+			      unsigned long Depth, bool FromUser)
+{
+   if (FromUser == false && Pkg->SelectedState == pkgCache::State::Hold && _config->FindB("APT::Ignore-Hold",false) == false)
+   {
+      if (DebugMarker == true)
+	 std::clog << OutputInDepth(Depth) << "Hold prevents MarkDelete of " << Pkg << " FU=" << FromUser << std::endl;
+      return false;
+   }
+   return true;
+}
+									/*}}}*/
 // DepCache::MarkInstall - Put the package in the install state		/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -826,7 +857,7 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
 	P.CandidateVer == (Version *)Pkg.CurrentVer()))
    {
       if (P.CandidateVer == (Version *)Pkg.CurrentVer() && P.InstallVer == 0)
-	 MarkKeep(Pkg, false, FromUser);
+	 MarkKeep(Pkg, false, FromUser, Depth+1);
       return;
    }
 
@@ -836,6 +867,11 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
    // We dont even try to install virtual packages..
    if (Pkg->VersionList == 0)
       return;
+
+   // check if we are allowed to install the package
+   if (IsInstallOk(Pkg,AutoInst,Depth,FromUser) == false)
+      return;
+
    /* Target the candidate version and remove the autoflag. We reset the
       autoflag below if this was called recursively. Otherwise the user
       should have the ability to de-auto a package by changing its state */
@@ -864,10 +900,13 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
    AddStates(Pkg);
    Update(Pkg);
    AddSizes(Pkg);
-   
+
    if (AutoInst == false)
       return;
 
+   if (DebugMarker == true)
+      std::clog << OutputInDepth(Depth) << "MarkInstall " << Pkg << " FU=" << FromUser << std::endl;
+
    DepIterator Dep = P.InstVerIter(*this).DependsList();
    for (; Dep.end() != true;)
    {
@@ -937,12 +976,12 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
 	 }
       }
       if(isNewImportantDep)
-	 if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
-	    std::clog << "new important dependency: " 
+	 if(DebugAutoInstall == true)
+	    std::clog << OutputInDepth(Depth) << "new important dependency: "
 		      << Start.TargetPkg().Name() << std::endl;
       if(isPreviouslySatisfiedImportantDep)
-	if(_config->FindB("Debug::pkgDepCache::AutoInstall", false) == true)
-	  std::clog << "previously satisfied important dependency on "
+	if(DebugAutoInstall == true)
+	  std::clog << OutputInDepth(Depth) << "previously satisfied important dependency on "
 		    << Start.TargetPkg().Name() << std::endl;
 
       // skip important deps if the package is already installed
@@ -991,17 +1030,18 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
 	    }
 	 }
 	 
-	 if (InstPkg.end() == false) 
+	 if (InstPkg.end() == false)
 	 {
-	    if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
-	       std::clog << "Installing " << InstPkg.Name() 
-			 << " as dep of " << Pkg.Name() 
+	    if(DebugAutoInstall == true)
+	       std::clog << OutputInDepth(Depth) << "Installing " << InstPkg.Name()
+			 << " as " << Start.DepType() << " of " << Pkg.Name()
 			 << std::endl;
  	    // now check if we should consider it a automatic dependency or not
  	    if(Pkg.Section() && ConfigValueInSubTree("APT::Never-MarkAuto-Sections", Pkg.Section()))
  	    {
- 	       if(_config->FindB("Debug::pkgDepCache::AutoInstall",false) == true)
- 		  std::clog << "Setting NOT as auto-installed (direct dep of pkg in APT::Never-MarkAuto-Sections)" << std::endl;
+	       if(DebugAutoInstall == true)
+		  std::clog << OutputInDepth(Depth) << "Setting NOT as auto-installed (direct "
+                            << Start.DepType() << " of pkg in APT::Never-MarkAuto-Sections)" << std::endl;
  	       MarkInstall(InstPkg,true,Depth + 1, true);
  	    }
  	    else 
@@ -1028,16 +1068,32 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
 	    PkgIterator Pkg = Ver.ParentPkg();
 
 	    if (Start->Type != Dep::DpkgBreaks)
-	       MarkDelete(Pkg);
-	    else
-	       if (PkgState[Pkg->ID].CandidateVer != *I)
-		  MarkInstall(Pkg,true,Depth + 1, false, ForceImportantDeps);
+	       MarkDelete(Pkg,false,Depth + 1, false);
+	    else if (PkgState[Pkg->ID].CandidateVer != *I)
+	       MarkInstall(Pkg,true,Depth + 1, false, ForceImportantDeps);
 	 }
 	 continue;
       }      
    }
 }
 									/*}}}*/
+// DepCache::IsInstallOk - check if it is ok to install this package	/*{{{*/
+// ---------------------------------------------------------------------
+/* The default implementation just honors dpkg hold
+   But an application using this library can override this method
+   to control the MarkInstall behaviour */
+bool pkgDepCache::IsInstallOk(PkgIterator const &Pkg,bool AutoInst,
+			      unsigned long Depth, bool FromUser)
+{
+   if (FromUser == false && Pkg->SelectedState == pkgCache::State::Hold && _config->FindB("APT::Ignore-Hold",false) == false)
+   {
+      if (DebugMarker == true)
+	 std::clog << OutputInDepth(Depth) << "Hold prevents MarkInstall of " << Pkg << " FU=" << FromUser << std::endl;
+      return false;
+   }
+   return true;
+}
+									/*}}}*/
 // DepCache::SetReInstall - Set the reinstallation flag			/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -1137,7 +1193,6 @@ const char *pkgDepCache::StateCache::StripEpoch(const char *Ver)
    return Ver;
 }
 									/*}}}*/
-
 // Policy::GetCandidateVer - Returns the Candidate install version	/*{{{*/
 // ---------------------------------------------------------------------
 /* The default just returns the highest available version that is not
@@ -1174,7 +1229,6 @@ pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator Pkg)
    return Last;
 }
 									/*}}}*/
-
 // Policy::IsImportantDep - True if the dependency is important		/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -1200,8 +1254,7 @@ bool pkgDepCache::Policy::IsImportantDep(DepIterator Dep)
    return false;
 }
 									/*}}}*/
-
-pkgDepCache::DefaultRootSetFunc::DefaultRootSetFunc()
+pkgDepCache::DefaultRootSetFunc::DefaultRootSetFunc()			/*{{{*/
   : constructedSuccessfully(false)
 {
   Configuration::Item const *Opts;
@@ -1230,8 +1283,8 @@ pkgDepCache::DefaultRootSetFunc::DefaultRootSetFunc()
 
   constructedSuccessfully = true;
 }
-
-pkgDepCache::DefaultRootSetFunc::~DefaultRootSetFunc()
+									/*}}}*/
+pkgDepCache::DefaultRootSetFunc::~DefaultRootSetFunc()			/*{{{*/
 {
   for(unsigned int i = 0; i < rootSetRegexp.size(); i++)
     {
@@ -1239,9 +1292,8 @@ pkgDepCache::DefaultRootSetFunc::~DefaultRootSetFunc()
       delete rootSetRegexp[i];
     }
 }
-
-
-bool pkgDepCache::DefaultRootSetFunc::InRootSet(const pkgCache::PkgIterator &pkg)
+									/*}}}*/
+bool pkgDepCache::DefaultRootSetFunc::InRootSet(const pkgCache::PkgIterator &pkg) /*{{{*/
 {
    for(unsigned int i = 0; i < rootSetRegexp.size(); i++)
       if (regexec(rootSetRegexp[i], pkg.Name(), 0, 0, 0) == 0)
@@ -1249,8 +1301,8 @@ bool pkgDepCache::DefaultRootSetFunc::InRootSet(const pkgCache::PkgIterator &pkg
 
    return false;
 }
-
-pkgDepCache::InRootSetFunc *pkgDepCache::GetRootSetFunc()
+									/*}}}*/
+pkgDepCache::InRootSetFunc *pkgDepCache::GetRootSetFunc()		/*{{{*/
 {
   DefaultRootSetFunc *f = new DefaultRootSetFunc;
   if(f->wasConstructedSuccessfully())
@@ -1261,7 +1313,7 @@ pkgDepCache::InRootSetFunc *pkgDepCache::GetRootSetFunc()
       return NULL;
     }
 }
-
+									/*}}}*/
 bool pkgDepCache::MarkFollowsRecommends()
 {
   return _config->FindB("APT::AutoRemove::RecommendsImportant", true);
@@ -1272,11 +1324,12 @@ bool pkgDepCache::MarkFollowsSuggests()
   return _config->FindB("APT::AutoRemove::SuggestsImportant", false);
 }
 
-// the main mark algorithm
+// pkgDepCache::MarkRequired - the main mark algorithm			/*{{{*/
 bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
 {
    bool follow_recommends;
    bool follow_suggests;
+   bool debug_autoremove = _config->FindB("Debug::pkgAutoRemove",false);
 
    // init the states
    for(PkgIterator p = PkgBegin(); !p.end(); ++p)
@@ -1285,8 +1338,7 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
       PkgState[p->ID].Garbage = false;
 
       // debug output
-      if(_config->FindB("Debug::pkgAutoRemove",false) 
-	 && PkgState[p->ID].Flags & Flag::Auto)
+      if(debug_autoremove && PkgState[p->ID].Flags & Flag::Auto)
   	 std::clog << "AutoDep: " << p.Name() << std::endl;
    }
 
@@ -1317,8 +1369,8 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
 
    return true;
 }
-
-// mark a single package in Mark-and-Sweep
+									/*}}}*/
+// MarkPackage - mark a single package in Mark-and-Sweep		/*{{{*/
 void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
 			      const pkgCache::VerIterator &ver,
 			      bool follow_recommends,
@@ -1357,7 +1409,9 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
    if(state.Marked)
       return;
 
-   if(_config->FindB("Debug::pkgAutoRemove",false))
+   bool debug_autoremove = _config->FindB("Debug::pkgAutoRemove", false);
+   
+   if(debug_autoremove)
      {
        std::clog << "Marking: " << pkg.Name();
        if(!ver.end())
@@ -1388,7 +1442,7 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
 	   {
 	      if(_system->VS->CheckDep(V.VerStr(), d->CompareOp, d.TargetVer()))
 	      {
-		if(_config->FindB("Debug::pkgAutoRemove",false))
+		if(debug_autoremove)
 		  {
 		    std::clog << "Following dep: " << d.ParentPkg().Name()
 			      << " " << d.ParentVer().VerStr() << " "
@@ -1412,7 +1466,7 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
 	      if(_system->VS->CheckDep(prv.ProvideVersion(), d->CompareOp, 
 				       d.TargetVer()))
 	      {
-		if(_config->FindB("Debug::pkgAutoRemove",false))
+		if(debug_autoremove)
 		  {
 		    std::clog << "Following dep: " << d.ParentPkg().Name()
 			      << " " << d.ParentVer().VerStr() << " "
@@ -1437,12 +1491,14 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
      }
    }
 }
-
-bool pkgDepCache::Sweep()
+									/*}}}*/
+bool pkgDepCache::Sweep()						/*{{{*/
 {
+   bool debug_autoremove = _config->FindB("Debug::pkgAutoRemove",false);
+
    // do the sweep
    for(PkgIterator p=PkgBegin(); !p.end(); ++p)
-  {
+   {
      StateCache &state=PkgState[p->ID];
 
      // skip required packages
@@ -1454,10 +1510,11 @@ bool pkgDepCache::Sweep()
      if(!state.Marked && (!p.CurrentVer().end() || state.Install()))
      {
 	state.Garbage=true;
-	if(_config->FindB("Debug::pkgAutoRemove",false))
+	if(debug_autoremove)
 	   std::cout << "Garbage: " << p.Name() << std::endl;
      }
   }   
 
    return true;
 }
+									/*}}}*/

+ 47 - 4
apt-pkg/depcache.h

@@ -294,7 +294,10 @@ class pkgDepCache : protected pkgCache::Namespace
    unsigned long iBrokenCount;
    unsigned long iPolicyBrokenCount;
    unsigned long iBadCount;
-   
+
+   bool DebugMarker;
+   bool DebugAutoInstall;
+
    Policy *delLocalPolicy;           // For memory clean up..
    Policy *LocalPolicy;
    
@@ -387,18 +390,58 @@ class pkgDepCache : protected pkgCache::Namespace
     */
    // @{
    void MarkKeep(PkgIterator const &Pkg, bool Soft = false,
-		 bool FromUser = true);
-   void MarkDelete(PkgIterator const &Pkg,bool Purge = false);
+		 bool FromUser = true, unsigned long Depth = 0);
+   void MarkDelete(PkgIterator const &Pkg, bool Purge = false,
+                   unsigned long Depth = 0, bool FromUser = true);
    void MarkInstall(PkgIterator const &Pkg,bool AutoInst = true,
 		    unsigned long Depth = 0, bool FromUser = true,
 		    bool ForceImportantDeps = false);
+
    void SetReInstall(PkgIterator const &Pkg,bool To);
    void SetCandidateVersion(VerIterator TargetVer);
 
    /** Set the "is automatically installed" flag of Pkg. */
    void MarkAuto(const PkgIterator &Pkg, bool Auto);
    // @}
-   
+
+   /** \return \b true if it's OK for MarkInstall to install
+    *  the given package.
+    *
+    *  See the default implementation for a simple example how this
+    *  method can be used.
+    *  Overriding implementations should use the hold-state-flag to cache
+    *  results from previous checks of this package - also it should
+    *  be used if the default resolver implementation is also used to
+    *  ensure that these packages are handled like "normal" dpkg holds.
+    *
+    *  The parameters are the same as in the calling MarkInstall:
+    *  \param Pkg       the package that MarkInstall wants to install.
+    *  \param AutoInst  needs a previous MarkInstall this package?
+    *  \param Depth     recursive deep of this Marker call
+    *  \param FromUser  was the install requested by the user?
+    */
+   virtual bool IsInstallOk(const PkgIterator &Pkg,bool AutoInst = true,
+			    unsigned long Depth = 0, bool FromUser = true);
+
+   /** \return \b true if it's OK for MarkDelete to remove
+    *  the given package.
+    *
+    *  See the default implementation for a simple example how this
+    *  method can be used.
+    *  Overriding implementations should use the hold-state-flag to cache
+    *  results from previous checks of this package - also it should
+    *  be used if the default resolver implementation is also used to
+    *  ensure that these packages are handled like "normal" dpkg holds.
+    *
+    *  The parameters are the same as in the calling MarkDelete:
+    *  \param Pkg       the package that MarkDelete wants to remove.
+    *  \param Purge     should we purge instead of "only" remove?
+    *  \param Depth     recursive deep of this Marker call
+    *  \param FromUser  was the remove requested by the user?
+    */
+   virtual bool IsDeleteOk(const PkgIterator &Pkg,bool Purge = false,
+			    unsigned long Depth = 0, bool FromUser = true);
+
    // This is for debuging
    void Update(OpProgress *Prog = 0);
 

+ 14 - 11
apt-pkg/indexcopy.cc

@@ -527,19 +527,19 @@ bool SigVerify::Verify(string prefix, string file, indexRecords *MetaIndex)
    // (non-existing files are not considered a error)
    if(!FileExists(prefix+file))
    {
-      _error->Warning("Skipping non-exisiting file %s", string(prefix+file).c_str());
+      _error->Warning(_("Skipping nonexistent file %s"), string(prefix+file).c_str());
       return true;
    }
 
    if (!Record) 
    {
-      _error->Warning("Can't find authentication record for: %s",file.c_str());
+      _error->Warning(_("Can't find authentication record for: %s"), file.c_str());
       return false;
    }
 
    if (!Record->Hash.VerifyFile(prefix+file))
    {
-      _error->Warning("Hash mismatch for: %s",file.c_str());
+      _error->Warning(_("Hash mismatch for: %s"),file.c_str());
       return false;
    }
 
@@ -551,8 +551,8 @@ bool SigVerify::Verify(string prefix, string file, indexRecords *MetaIndex)
 
    return true;
 }
-
-bool SigVerify::CopyMetaIndex(string CDROM, string CDName, 
+									/*}}}*/
+bool SigVerify::CopyMetaIndex(string CDROM, string CDName,		/*{{{*/
 			      string prefix, string file)
 {
       char S[400];
@@ -572,8 +572,8 @@ bool SigVerify::CopyMetaIndex(string CDROM, string CDName,
    
       return true;
 }
-
-bool SigVerify::CopyAndVerify(string CDROM,string Name,vector<string> &SigList,
+									/*}}}*/
+bool SigVerify::CopyAndVerify(string CDROM,string Name,vector<string> &SigList,	/*{{{*/
 			      vector<string> PkgList,vector<string> SrcList)
 {
    if (SigList.size() == 0)
@@ -592,7 +592,10 @@ bool SigVerify::CopyAndVerify(string CDROM,string Name,vector<string> &SigList,
 
       // a Release.gpg without a Release should never happen
       if(!FileExists(*I+"Release"))
+      {
+	 delete MetaIndex;
 	 continue;
+      }
 
 
       // verify the gpg signature of "Release"
@@ -675,10 +678,9 @@ bool SigVerify::CopyAndVerify(string CDROM,string Name,vector<string> &SigList,
 
    return true;
 }
-
-
-bool TranslationsCopy::CopyTranslations(string CDROM,string Name,vector<string> &List,
-			     pkgCdromStatus *log)
+									/*}}}*/
+bool TranslationsCopy::CopyTranslations(string CDROM,string Name,	/*{{{*/
+				vector<string> &List, pkgCdromStatus *log)
 {
    OpProgress *Progress = NULL;
    if (List.size() == 0)
@@ -850,3 +852,4 @@ bool TranslationsCopy::CopyTranslations(string CDROM,string Name,vector<string>
 
    return true;
 }
+									/*}}}*/

+ 10 - 12
apt-pkg/indexcopy.h

@@ -22,7 +22,7 @@ class FileFd;
 class indexRecords;
 class pkgCdromStatus;
 
-class IndexCopy
+class IndexCopy								/*{{{*/
 {
    protected:
    
@@ -45,8 +45,8 @@ class IndexCopy
 		     pkgCdromStatus *log);
    virtual ~IndexCopy() {};
 };
-
-class PackageCopy : public IndexCopy
+									/*}}}*/
+class PackageCopy : public IndexCopy					/*{{{*/
 {
    protected:
    
@@ -57,8 +57,8 @@ class PackageCopy : public IndexCopy
    
    public:
 };
-
-class SourceCopy : public IndexCopy
+									/*}}}*/
+class SourceCopy : public IndexCopy					/*{{{*/
 {
    protected:
    
@@ -69,8 +69,8 @@ class SourceCopy : public IndexCopy
    
    public:
 };
-
-class TranslationsCopy
+									/*}}}*/
+class TranslationsCopy							/*{{{*/
 {
    protected:
    pkgTagSection *Section;
@@ -79,9 +79,8 @@ class TranslationsCopy
    bool CopyTranslations(string CDROM,string Name,vector<string> &List,
 			 pkgCdromStatus *log);
 };
-
-
-class SigVerify 
+									/*}}}*/
+class SigVerify								/*{{{*/
 {
    bool Verify(string prefix,string file, indexRecords *records);
    bool CopyMetaIndex(string CDROM, string CDName, 
@@ -91,7 +90,6 @@ class SigVerify
    bool CopyAndVerify(string CDROM,string Name,vector<string> &SigList,
 		      vector<string> PkgList,vector<string> SrcList);
 };
-
-
+									/*}}}*/
 
 #endif

+ 0 - 1
apt-pkg/indexfile.cc

@@ -41,7 +41,6 @@ pkgIndexFile::Type *pkgIndexFile::Type::GetType(const char *Type)
    return 0;
 }
 									/*}}}*/
-    
 // IndexFile::ArchiveInfo - Stub					/*{{{*/
 // ---------------------------------------------------------------------
 /* */

+ 7 - 7
apt-pkg/indexrecords.cc

@@ -9,7 +9,7 @@
 #include <apt-pkg/strutl.h>
 #include <apti18n.h>
 #include <sys/stat.h>
-
+									/*}}}*/
 string indexRecords::GetDist() const
 {
    return this->Dist;
@@ -31,7 +31,7 @@ const indexRecords::checkSum *indexRecords::Lookup(const string MetaKey)
    return Entries[MetaKey];
 }
 
-bool indexRecords::Load(const string Filename)
+bool indexRecords::Load(const string Filename)				/*{{{*/
 {
    FileFd Fd(Filename, FileFd::ReadOnly);
    pkgTagFile TagFile(&Fd, Fd.Size() + 256); // XXX
@@ -85,8 +85,8 @@ bool indexRecords::Load(const string Filename)
    string Strdate = Section.FindS("Date"); // FIXME: verify this somehow?
    return true;
 }
-
-vector<string> indexRecords::MetaKeys()
+									/*}}}*/
+vector<string> indexRecords::MetaKeys()					/*{{{*/
 {
    std::vector<std::string> keys;
    std::map<string,checkSum *>::iterator I = Entries.begin();
@@ -96,8 +96,8 @@ vector<string> indexRecords::MetaKeys()
    }
    return keys;
 }
-
-bool indexRecords::parseSumData(const char *&Start, const char *End,
+									/*}}}*/
+bool indexRecords::parseSumData(const char *&Start, const char *End,	/*{{{*/
 				   string &Name, string &Hash, size_t &Size)
 {
    Name = "";
@@ -154,7 +154,7 @@ bool indexRecords::parseSumData(const char *&Start, const char *End,
    Start = EntryEnd; //prepare for the next round
    return true;
 }
-
+									/*}}}*/
 indexRecords::indexRecords()
 {
 }

+ 16 - 6
apt-pkg/init.cc

@@ -65,13 +65,16 @@ bool pkgInitConfig(Configuration &Cnf)
    Cnf.Set("Dir::Etc::vendorlist","vendors.list");
    Cnf.Set("Dir::Etc::vendorparts","vendors.list.d");
    Cnf.Set("Dir::Etc::main","apt.conf");
+   Cnf.Set("Dir::ETc::netrc", "auth.conf");
    Cnf.Set("Dir::Etc::parts","apt.conf.d");
    Cnf.Set("Dir::Etc::preferences","preferences");
+   Cnf.Set("Dir::Etc::preferencesparts","preferences.d");
    Cnf.Set("Dir::Bin::methods","/usr/lib/apt/methods");
 
    // State   
    Cnf.Set("Dir::Log","var/log/apt");
    Cnf.Set("Dir::Log::Terminal","term.log");
+   Cnf.Set("Dir::Log::History","history.log");
 
    // Translation
    Cnf.Set("APT::Acquire::Translation", "environment");
@@ -80,22 +83,29 @@ bool pkgInitConfig(Configuration &Cnf)
    
    // Read an alternate config file
    const char *Cfg = getenv("APT_CONFIG");
-   if (Cfg != 0 && FileExists(Cfg) == true)
-      Res &= ReadConfigFile(Cnf,Cfg);
-   
+   if (Cfg != 0)
+   {
+      if (FileExists(Cfg) == true)
+	 Res &= ReadConfigFile(Cnf,Cfg);
+      else
+	 _error->WarningE("FileExists",_("Unable to read %s"),Cfg);
+   }
+
    // Read the configuration parts dir
    string Parts = Cnf.FindDir("Dir::Etc::parts");
    if (FileExists(Parts) == true)
       Res &= ReadConfigDir(Cnf,Parts);
-      
+   else
+      _error->WarningE("FileExists",_("Unable to read %s"),Parts.c_str());
+
    // Read the main config file
    string FName = Cnf.FindFile("Dir::Etc::main");
    if (FileExists(FName) == true)
       Res &= ReadConfigFile(Cnf,FName);
-   
+
    if (Res == false)
       return false;
-   
+
    if (Cnf.FindB("Debug::pkgInitConfig",false) == true)
       Cnf.Dump();
    

+ 6 - 2
apt-pkg/init.h

@@ -16,9 +16,13 @@
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/pkgsystem.h>
 
-// See the makefile
+// These lines are extracted by the makefiles and the buildsystem
+// Increasing MAJOR or MINOR results in the need of recompiling all
+// reverse-dependencies of libapt-pkg against the new SONAME.
+// Non-ABI-Breaks should only increase RELEASE number.
+// See also buildlib/libversion.mak
 #define APT_PKG_MAJOR 4
-#define APT_PKG_MINOR 6
+#define APT_PKG_MINOR 8
 #define APT_PKG_RELEASE 0
     
 extern const char *pkgVersion;

+ 11 - 11
apt-pkg/makefile

@@ -9,23 +9,22 @@ HEADER_TARGETDIRS = apt-pkg
 # Bring in the default rules
 include ../buildlib/defaults.mak
 
-# The library name, don't forget to update init.h and the copy in 
-# methods/makefile - FIXME
+# The library name and version (indirectly used from init.h)
+include ../buildlib/libversion.mak
 LIBRARY=apt-pkg
-LIBEXT=$(GLIBC_VER)$(LIBSTDCPP_VER)
-MAJOR=4.7
-MINOR=0
+MAJOR=$(LIBAPTPKG_MAJOR)
+MINOR=$(LIBAPTPKG_RELEASE)
 SLIBS=$(PTHREADLIB) $(INTLLIBS) -lutil -ldl
-APT_DOMAIN:=libapt-pkg$(MAJOR)
+APT_DOMAIN:=libapt-pkg$(LIBAPTPKG_MAJOR)
 
 # Source code for the contributed non-core things
 SOURCE = contrib/mmap.cc contrib/error.cc contrib/strutl.cc \
          contrib/configuration.cc contrib/progress.cc contrib/cmndline.cc \
 	 contrib/md5.cc contrib/sha1.cc contrib/sha256.cc contrib/hashes.cc \
-	 contrib/cdromutl.cc contrib/crc-16.cc \
+	 contrib/cdromutl.cc contrib/crc-16.cc contrib/netrc.cc \
 	 contrib/fileutl.cc 
-HEADERS = mmap.h error.h configuration.h fileutl.h  cmndline.h \
-	  md5.h crc-16.h cdromutl.h strutl.h sptr.h sha1.h sha256.h hashes.h
+HEADERS = mmap.h error.h configuration.h fileutl.h  cmndline.h netrc.h\
+	  md5.h crc-16.h cdromutl.h strutl.h sptr.h sha1.h sha256.h hashes.h 
 
 # Source code for the core main library
 SOURCE+= pkgcache.cc version.cc depcache.cc \
@@ -34,14 +33,15 @@ SOURCE+= pkgcache.cc version.cc depcache.cc \
 	 acquire-worker.cc acquire-method.cc init.cc clean.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
+	 indexrecords.cc vendor.cc vendorlist.cc cdrom.cc indexcopy.cc \
+	 aptconfiguration.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 \
 	  acquire.h acquire-worker.h acquire-item.h acquire-method.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
+          vendorlist.h cdrom.h indexcopy.h aptconfiguration.h
 
 # Source code for the debian specific components
 # In theory the deb headers do not need to be exported..

+ 7 - 1
apt-pkg/metaindex.h

@@ -39,7 +39,13 @@ class metaIndex
    virtual vector<pkgIndexFile *> *GetIndexFiles() = 0; 
    virtual bool IsTrusted() const = 0;
 
-   virtual ~metaIndex() {};
+   virtual ~metaIndex() {
+      if (Indexes == 0)
+	 return;
+      for (vector<pkgIndexFile *>::iterator I = (*Indexes).begin(); I != (*Indexes).end(); ++I)
+	 delete *I;
+      delete Indexes;
+   }
 };
 
 #endif

+ 44 - 29
apt-pkg/orderlist.cc

@@ -129,7 +129,6 @@ bool pkgOrderList::IsMissing(PkgIterator Pkg)
    return true;
 }
 									/*}}}*/
-
 // OrderList::DoRun - Does an order run					/*{{{*/
 // ---------------------------------------------------------------------
 /* The caller is expeted to have setup the desired probe state */
@@ -175,22 +174,35 @@ bool pkgOrderList::DoRun()
 bool pkgOrderList::OrderCritical()
 {
    FileList = 0;
-   
-   Primary = &pkgOrderList::DepUnPackPre;
+
+   Primary = &pkgOrderList::DepUnPackPreD;
    Secondary = 0;
    RevDepends = 0;
    Remove = 0;
    LoopCount = 0;
-   
+
    // Sort
    Me = this;
-   qsort(List,End - List,sizeof(*List),&OrderCompareB);   
-   
+   qsort(List,End - List,sizeof(*List),&OrderCompareB);
+
    if (DoRun() == false)
       return false;
-   
+
    if (LoopCount != 0)
       return _error->Error("Fatal, predepends looping detected");
+
+   if (Debug == true)
+   {
+      clog << "** Critical Unpack ordering done" << endl;
+
+      for (iterator I = List; I != End; I++)
+      {
+	 PkgIterator P(Cache,*I);
+	 if (IsNow(P) == true)
+	    clog << "  " << P.Name() << ' ' << IsMissing(P) << ',' << IsFlag(P,After) << endl;
+      }
+   }
+
    return true;
 }
 									/*}}}*/
@@ -206,7 +218,7 @@ bool pkgOrderList::OrderUnpack(string *FileList)
    if (FileList != 0)
    {
       WipeFlags(After);
-      
+
       // Set the inlist flag
       for (iterator I = List; I != End; I++)
       {
@@ -215,7 +227,7 @@ bool pkgOrderList::OrderUnpack(string *FileList)
 	     Flag(*I,After);
       }
    }
-   
+
    Primary = &pkgOrderList::DepUnPackCrit;
    Secondary = &pkgOrderList::DepConfigure;
    RevDepends = &pkgOrderList::DepUnPackDep;
@@ -230,7 +242,7 @@ bool pkgOrderList::OrderUnpack(string *FileList)
       clog << "** Pass A" << endl;
    if (DoRun() == false)
       return false;
-   
+
    if (Debug == true)
       clog << "** Pass B" << endl;
    Secondary = 0;
@@ -244,7 +256,7 @@ bool pkgOrderList::OrderUnpack(string *FileList)
    Remove = 0;             // Otherwise the libreadline remove problem occures
    if (DoRun() == false)
       return false;
-      
+
    if (Debug == true)
       clog << "** Pass D" << endl;
    LoopCount = 0;
@@ -260,9 +272,9 @@ bool pkgOrderList::OrderUnpack(string *FileList)
       {
 	 PkgIterator P(Cache,*I);
 	 if (IsNow(P) == true)
-	    clog << P.Name() << ' ' << IsMissing(P) << ',' << IsFlag(P,After) << endl;
+	    clog << "  " << P.Name() << ' ' << IsMissing(P) << ',' << IsFlag(P,After) << endl;
       }
-   }   
+   }
 
    return true;
 }
@@ -282,35 +294,40 @@ bool pkgOrderList::OrderConfigure()
    return DoRun();
 }
 									/*}}}*/
-
 // OrderList::Score - Score the package for sorting			/*{{{*/
 // ---------------------------------------------------------------------
 /* Higher scores order earlier */
 int pkgOrderList::Score(PkgIterator Pkg)
 {
+   static int const ScoreDelete = _config->FindI("OrderList::Score::Delete", 500);
+
    // Removal is always done first
    if (Cache[Pkg].Delete() == true)
-      return 200;
-   
+      return ScoreDelete;
+
    // This should never happen..
    if (Cache[Pkg].InstVerIter(Cache).end() == true)
       return -1;
-   
+
+   static int const ScoreEssential = _config->FindI("OrderList::Score::Essential", 200);
+   static int const ScoreImmediate = _config->FindI("OrderList::Score::Immediate", 10);
+   static int const ScorePreDepends = _config->FindI("OrderList::Score::PreDepends", 50);
+
    int Score = 0;
    if ((Pkg->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
-      Score += 100;
+      Score += ScoreEssential;
 
    if (IsFlag(Pkg,Immediate) == true)
-      Score += 10;
-   
-   for (DepIterator D = Cache[Pkg].InstVerIter(Cache).DependsList(); 
+      Score += ScoreImmediate;
+
+   for (DepIterator D = Cache[Pkg].InstVerIter(Cache).DependsList();
 	D.end() == false; D++)
       if (D->Type == pkgCache::Dep::PreDepends)
       {
-	 Score += 50;
+	 Score += ScorePreDepends;
 	 break;
       }
-      
+
    // Important Required Standard Optional Extra
    signed short PrioMap[] = {0,5,4,3,1,0};
    if (Cache[Pkg].InstVerIter(Cache)->Priority <= 5)
@@ -388,6 +405,7 @@ int pkgOrderList::OrderCompareA(const void *a, const void *b)
    
    int ScoreA = Me->Score(A);
    int ScoreB = Me->Score(B);
+
    if (ScoreA > ScoreB)
       return -1;
    
@@ -424,6 +442,7 @@ int pkgOrderList::OrderCompareB(const void *a, const void *b)
    
    int ScoreA = Me->Score(A);
    int ScoreB = Me->Score(B);
+
    if (ScoreA > ScoreB)
       return -1;
    
@@ -433,7 +452,6 @@ int pkgOrderList::OrderCompareB(const void *a, const void *b)
    return strcmp(A.Name(),B.Name());
 }
 									/*}}}*/
-
 // OrderList::VisitDeps - Visit forward install dependencies		/*{{{*/
 // ---------------------------------------------------------------------
 /* This calls the dependency function for the normal forwards dependencies
@@ -590,7 +608,6 @@ bool pkgOrderList::VisitNode(PkgIterator Pkg)
    return true;
 }
 									/*}}}*/
-
 // OrderList::DepUnPackCrit - Critical UnPacking ordering		/*{{{*/
 // ---------------------------------------------------------------------
 /* Critical unpacking ordering strives to satisfy Conflicts: and 
@@ -668,13 +685,12 @@ bool pkgOrderList::DepUnPackCrit(DepIterator D)
    }   
    return true;
 }
-
+									/*}}}*/
 // OrderList::DepUnPackPreD - Critical UnPacking ordering with depends	/*{{{*/
 // ---------------------------------------------------------------------
 /* Critical PreDepends (also configure immediate and essential) strives to
    ensure not only that all conflicts+predepends are met but that this
-   package will be immediately configurable when it is unpacked. 
-
+   package will be immediately configurable when it is unpacked.
    Loops are preprocessed and logged. */
 bool pkgOrderList::DepUnPackPreD(DepIterator D)
 {
@@ -892,7 +908,6 @@ bool pkgOrderList::DepRemove(DepIterator D)
    return true;
 }
 									/*}}}*/
-
 // OrderList::AddLoop - Add a loop to the loop list			/*{{{*/
 // ---------------------------------------------------------------------
 /* We record the loops. This is a relic since loop breaking is done 

+ 46 - 22
apt-pkg/packagemanager.cc

@@ -26,7 +26,7 @@
 #include <apti18n.h>    
 #include <iostream>
 #include <fcntl.h> 
-
+									/*}}}*/
 using namespace std;
 
 // PM::PackageManager - Constructor					/*{{{*/
@@ -57,7 +57,10 @@ bool pkgPackageManager::GetArchives(pkgAcquire *Owner,pkgSourceList *Sources,
    if (CreateOrderList() == false)
       return false;
    
-   if (List->OrderUnpack() == false)
+   bool const ordering =
+	_config->FindB("PackageManager::UnpackAll",true) ?
+		List->OrderUnpack() : List->OrderCritical();
+   if (ordering == false)
       return _error->Error("Internal ordering error");
 
    for (pkgOrderList::iterator I = List->begin(); I != List->end(); I++)
@@ -117,13 +120,12 @@ bool pkgPackageManager::FixMissing()
    return Resolve.ResolveByKeep() == true && Cache.BrokenCount() == 0;   
 }
 									/*}}}*/
-
 // PM::ImmediateAdd - Add the immediate flag recursivly			/*{{{*/
 // ---------------------------------------------------------------------
 /* This adds the immediate flag to the pkg and recursively to the
    dependendies 
  */
-void pkgPackageManager::ImmediateAdd(PkgIterator I, bool UseInstallVer)
+void pkgPackageManager::ImmediateAdd(PkgIterator I, bool UseInstallVer, unsigned const int &Depth)
 {
    DepIterator D;
    
@@ -144,15 +146,14 @@ void pkgPackageManager::ImmediateAdd(PkgIterator I, bool UseInstallVer)
 	 if(!List->IsFlag(D.TargetPkg(), pkgOrderList::Immediate))
 	 {
 	    if(Debug)
-	       clog << "ImmediateAdd(): Adding Immediate flag to " << I.Name() << endl;
+	       clog << OutputInDepth(Depth) << "ImmediateAdd(): Adding Immediate flag to " << D.TargetPkg() << " cause of " << D.DepType() << " " << I.Name() << endl;
 	    List->Flag(D.TargetPkg(),pkgOrderList::Immediate);
-	    ImmediateAdd(D.TargetPkg(), UseInstallVer);
+	    ImmediateAdd(D.TargetPkg(), UseInstallVer, Depth + 1);
 	 }
       }
    return;
 }
 									/*}}}*/
-
 // PM::CreateOrderList - Create the ordering class			/*{{{*/
 // ---------------------------------------------------------------------
 /* This populates the ordering list with all the packages that are
@@ -165,7 +166,7 @@ bool pkgPackageManager::CreateOrderList()
    delete List;
    List = new pkgOrderList(&Cache);
    
-   bool NoImmConfigure = !_config->FindB("APT::Immediate-Configure",true);
+   static bool const NoImmConfigure = !_config->FindB("APT::Immediate-Configure",true);
    
    // Generate the list of affected packages and sort it
    for (PkgIterator I = Cache.PkgBegin(); I.end() == false; I++)
@@ -268,13 +269,16 @@ bool pkgPackageManager::ConfigureAll()
    
    if (OList.OrderConfigure() == false)
       return false;
-   
+
+   std::string const conf = _config->Find("PackageManager::Configure","all");
+   bool const ConfigurePkgs = (conf == "all");
+
    // Perform the configuring
    for (pkgOrderList::iterator I = OList.begin(); I != OList.end(); I++)
    {
       PkgIterator Pkg(Cache,*I);
       
-      if (Configure(Pkg) == false)
+      if (ConfigurePkgs == true && Configure(Pkg) == false)
 	 return false;
       
       List->Flag(Pkg,pkgOrderList::Configured,pkgOrderList::States);
@@ -289,20 +293,27 @@ bool pkgPackageManager::ConfigureAll()
    of it's dependents. */
 bool pkgPackageManager::SmartConfigure(PkgIterator Pkg)
 {
+   if (Debug == true)
+      clog << "SmartConfigure " << Pkg.Name() << endl;
+
    pkgOrderList OList(&Cache);
 
    if (DepAdd(OList,Pkg) == false)
       return false;
-   
-   if (OList.OrderConfigure() == false)
-      return false;
-   
+
+   static std::string const conf = _config->Find("PackageManager::Configure","all");
+   static bool const ConfigurePkgs = (conf == "all" || conf == "smart");
+
+   if (ConfigurePkgs == true)
+      if (OList.OrderConfigure() == false)
+	 return false;
+
    // Perform the configuring
    for (pkgOrderList::iterator I = OList.begin(); I != OList.end(); I++)
    {
       PkgIterator Pkg(Cache,*I);
       
-      if (Configure(Pkg) == false)
+      if (ConfigurePkgs == true && Configure(Pkg) == false)
 	 return false;
       
       List->Flag(Pkg,pkgOrderList::Configured,pkgOrderList::States);
@@ -310,8 +321,9 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg)
 
    // Sanity Check
    if (List->IsFlag(Pkg,pkgOrderList::Configured) == false)
-      return _error->Error("Internal error, could not immediate configure %s",Pkg.Name());
-   
+      return _error->Error(_("Could not perform immediate configuration on '%s'."
+			"Please see man 5 apt.conf under APT::Immediate-Configure for details. (%d)"),Pkg.Name(),1);
+
    return true;
 }
 									/*}}}*/
@@ -463,7 +475,8 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg)
       List->Flag(Pkg,pkgOrderList::UnPacked,pkgOrderList::States);
       if (List->IsFlag(Pkg,pkgOrderList::Immediate) == true)
 	 if (SmartConfigure(Pkg) == false)
-	    return _error->Error("Internal Error, Could not perform immediate configuration (1) on %s",Pkg.Name());
+	    return _error->Error(_("Could not perform immediate configuration on already unpacked '%s'."
+			"Please see man 5 apt.conf under APT::Immediate-Configure for details."),Pkg.Name());
       return true;
    }
 
@@ -479,6 +492,9 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg)
       
       while (End->Type == pkgCache::Dep::PreDepends)
       {
+	 if (Debug == true)
+	    clog << "PreDepends order for " << Pkg.Name() << std::endl;
+
 	 // Look for possible ok targets.
 	 SPtrArray<Version *> VList = Start.AllTargets();
 	 bool Bad = true;
@@ -492,6 +508,8 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg)
 		Pkg.State() == PkgIterator::NeedsNothing)
 	    {
 	       Bad = false;
+	       if (Debug == true)
+		  clog << "Found ok package " << Pkg.Name() << endl;
 	       continue;
 	    }
 	 }
@@ -507,6 +525,8 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg)
 		(Cache[Pkg].Keep() == true && Pkg.State() == PkgIterator::NeedsNothing))
 	       continue;
 
+	    if (Debug == true)
+	       clog << "Trying to SmartConfigure " << Pkg.Name() << endl;
 	    Bad = !SmartConfigure(Pkg);
 	 }
 
@@ -563,7 +583,8 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg)
    // Perform immedate configuration of the package.
    if (List->IsFlag(Pkg,pkgOrderList::Immediate) == true)
       if (SmartConfigure(Pkg) == false)
-	 return _error->Error("Internal Error, Could not perform immediate configuration (2) on %s",Pkg.Name());
+	 return _error->Error(_("Could not perform immediate configuration on '%s'."
+			"Please see man 5 apt.conf under APT::Immediate-Configure for details. (%d)"),Pkg.Name(),2);
    
    return true;
 }
@@ -579,9 +600,12 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall()
    Reset();
    
    if (Debug == true)
-      clog << "Begining to order" << endl;
+      clog << "Beginning to order" << endl;
 
-   if (List->OrderUnpack(FileNames) == false)
+   bool const ordering =
+	_config->FindB("PackageManager::UnpackAll",true) ?
+		List->OrderUnpack(FileNames) : List->OrderCritical();
+   if (ordering == false)
    {
       _error->Error("Internal ordering error");
       return Failed;
@@ -634,7 +658,7 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall()
 	    return Failed;
       DoneSomething = true;
    }
-   
+
    // Final run through the configure phase
    if (ConfigureAll() == false)
       return Failed;

+ 1 - 1
apt-pkg/packagemanager.h

@@ -49,7 +49,7 @@ class pkgPackageManager : protected pkgCache::Namespace
    bool Debug;
          
    bool DepAdd(pkgOrderList &Order,PkgIterator P,int Depth = 0);
-   void ImmediateAdd(PkgIterator P, bool UseInstallVer);
+   void ImmediateAdd(PkgIterator P, bool UseInstallVer, unsigned const int &Depth = 0);
    virtual OrderResult OrderInstall();
    bool CheckRConflicts(PkgIterator Pkg,DepIterator Dep,const char *Ver);
    bool CreateOrderList();

+ 61 - 8
apt-pkg/pkgcache.cc

@@ -21,6 +21,7 @@
 									/*}}}*/
 // Include Files							/*{{{*/
 #include <apt-pkg/pkgcache.h>
+#include <apt-pkg/policy.h>
 #include <apt-pkg/indexfile.h>
 #include <apt-pkg/version.h>
 #include <apt-pkg/error.h>
@@ -49,7 +50,7 @@ pkgCache::Header::Header()
    
    /* Whenever the structures change the major version should be bumped,
       whenever the generator changes the minor version should be bumped. */
-   MajorVersion = 7;
+   MajorVersion = 8;
    MinorVersion = 0;
    Dirty = false;
    
@@ -223,7 +224,7 @@ const char *pkgCache::DepType(unsigned char Type)
 {
    const char *Types[] = {"",_("Depends"),_("PreDepends"),_("Suggests"),
                           _("Recommends"),_("Conflicts"),_("Replaces"),
-                          _("Obsoletes"),_("Breaks")};
+                          _("Obsoletes"),_("Breaks"), _("Enhances")};
    if (Type < sizeof(Types)/sizeof(*Types))
       return Types[Type];
    return "";
@@ -274,13 +275,13 @@ pkgCache::PkgIterator::OkState pkgCache::PkgIterator::State() const
       return NeedsUnpack;
    
    if (Pkg->CurrentState == pkgCache::State::UnPacked ||
-       Pkg->CurrentState == pkgCache::State::HalfConfigured ||
-      //we don't need to care for triggers awaiting packages
-      //dpkg will deal with them automatically when the 
-      //trigger pending action is run (those packages are usually
-      //in half-configured or triggers-pending state)
+       Pkg->CurrentState == pkgCache::State::HalfConfigured)
+      // we leave triggers alone complettely. dpkg deals with
+      // them in a hard-to-predict manner and if they get 
+      // resolved by dpkg before apt run dpkg --configure on 
+      // the TriggersPending package dpkg returns a error
       //Pkg->CurrentState == pkgCache::State::TriggersAwaited
-       Pkg->CurrentState == pkgCache::State::TriggersPending)
+      //Pkg->CurrentState == pkgCache::State::TriggersPending)
       return NeedsConfigure;
    
    if (Pkg->CurrentState == pkgCache::State::HalfInstalled ||
@@ -290,6 +291,56 @@ pkgCache::PkgIterator::OkState pkgCache::PkgIterator::State() const
    return NeedsNothing;
 }
 									/*}}}*/
+// PkgIterator::CandVersion - Returns the candidate version string	/*{{{*/
+// ---------------------------------------------------------------------
+/* Return string representing of the candidate version. */
+const char *
+pkgCache::PkgIterator::CandVersion() const 
+{
+  //TargetVer is empty, so don't use it.
+  VerIterator version = pkgPolicy::pkgPolicy(Owner).GetCandidateVer(*this);
+  if (version.IsGood())
+    return version.VerStr();
+  return 0;
+};
+									/*}}}*/
+// PkgIterator::CurVersion - Returns the current version string		/*{{{*/
+// ---------------------------------------------------------------------
+/* Return string representing of the current version. */
+const char *
+pkgCache::PkgIterator::CurVersion() const 
+{
+  VerIterator version = CurrentVer();
+  if (version.IsGood())
+    return CurrentVer().VerStr();
+  return 0;
+};
+									/*}}}*/
+// 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
+   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& 
+operator<<(ostream& out, pkgCache::PkgIterator Pkg) 
+{
+   if (Pkg.end() == true)
+      return out << "invalid package";
+
+   string current = string(Pkg.CurVersion() == 0 ? "none" : Pkg.CurVersion());
+   string candidate = string(Pkg.CandVersion() == 0 ? "none" : Pkg.CandVersion());
+   string newest = string(Pkg.VersionList().end() ? "none" : Pkg.VersionList().VerStr());
+
+   out << Pkg.Name() << " < " << current;
+   if (current != candidate)
+      out << " -> " << candidate;
+   if ( newest != "none" && candidate != newest)
+      out << " | " << newest;
+   out << " > ( " << string(Pkg.Section()==0?"none":Pkg.Section()) << " )";
+   return out;
+}
+									/*}}}*/
 // DepIterator::IsCritical - Returns true if the dep is important	/*{{{*/
 // ---------------------------------------------------------------------
 /* Currently critical deps are defined as depends, predepends and
@@ -607,6 +658,8 @@ string pkgCache::PkgFileIterator::RelStr()
       Res = Res + (Res.empty() == true?"o=":",o=")  + Origin();
    if (Archive() != 0)
       Res = Res + (Res.empty() == true?"a=":",a=")  + Archive();
+   if (Codename() != 0)
+      Res = Res + (Res.empty() == true?"n=":",n=")  + Codename();
    if (Label() != 0)
       Res = Res + (Res.empty() == true?"l=":",l=")  + Label();
    if (Component() != 0)

+ 26 - 25
apt-pkg/pkgcache.h

@@ -27,7 +27,7 @@
 using std::string;
     
 class pkgVersioningSystem;
-class pkgCache
+class pkgCache								/*{{{*/
 {
    public:
    // Cache element predeclarations
@@ -70,7 +70,7 @@ class pkgCache
    struct Dep
    {
       enum DepType {Depends=1,PreDepends=2,Suggests=3,Recommends=4,
-	 Conflicts=5,Replaces=6,Obsoletes=7,DpkgBreaks=8};
+	 Conflicts=5,Replaces=6,Obsoletes=7,DpkgBreaks=8,Enhances=9};
       enum DepCompareOp {Or=0x10,NoOp=0,LessEq=0x1,GreaterEq=0x2,Less=0x3,
 	 Greater=0x4,Equals=0x5,NotEquals=0x6};
    };
@@ -146,8 +146,8 @@ class pkgCache
    pkgCache(MMap *Map,bool DoMap = true);
    virtual ~pkgCache() {};
 };
-
-// Header structure
+									/*}}}*/
+// Header structure							/*{{{*/
 struct pkgCache::Header
 {
    // Signature information
@@ -195,8 +195,8 @@ struct pkgCache::Header
    bool CheckSizes(Header &Against) const;
    Header();
 };
-
-struct pkgCache::Package
+									/*}}}*/
+struct pkgCache::Package						/*{{{*/
 {
    // Pointers
    map_ptrloc Name;              // Stringtable
@@ -217,12 +217,13 @@ struct pkgCache::Package
    unsigned int ID;
    unsigned long Flags;
 };
-
-struct pkgCache::PackageFile
+									/*}}}*/
+struct pkgCache::PackageFile						/*{{{*/
 {
    // Names
    map_ptrloc FileName;        // Stringtable
    map_ptrloc Archive;         // Stringtable
+   map_ptrloc Codename;        // Stringtable
    map_ptrloc Component;       // Stringtable
    map_ptrloc Version;         // Stringtable
    map_ptrloc Origin;          // Stringtable
@@ -238,24 +239,24 @@ struct pkgCache::PackageFile
    unsigned int ID;
    time_t mtime;                  // Modification time for the file
 };
-
-struct pkgCache::VerFile
+									/*}}}*/
+struct pkgCache::VerFile						/*{{{*/
 {
    map_ptrloc File;           // PackageFile
    map_ptrloc NextFile;       // PkgVerFile
    map_ptrloc Offset;         // File offset
    unsigned short Size;
 };
-
-struct pkgCache::DescFile
+									/*}}}*/
+struct pkgCache::DescFile						/*{{{*/
 {
    map_ptrloc File;           // PackageFile
    map_ptrloc NextFile;       // PkgVerFile
    map_ptrloc Offset;         // File offset
    unsigned short Size;
 };
-
-struct pkgCache::Version
+									/*}}}*/
+struct pkgCache::Version						/*{{{*/
 {
    map_ptrloc VerStr;            // Stringtable
    map_ptrloc Section;           // StringTable (StringItem)
@@ -275,8 +276,8 @@ struct pkgCache::Version
    unsigned int ID;
    unsigned char Priority;
 };
-
-struct pkgCache::Description
+									/*}}}*/
+struct pkgCache::Description						/*{{{*/
 {
    // Language Code store the description translation language code. If
    // the value has a 0 lenght then this is readed using the Package
@@ -291,8 +292,8 @@ struct pkgCache::Description
 
    unsigned int ID;
 };
-
-struct pkgCache::Dependency
+									/*}}}*/
+struct pkgCache::Dependency						/*{{{*/
 {
    map_ptrloc Version;         // Stringtable
    map_ptrloc Package;         // Package
@@ -305,8 +306,8 @@ struct pkgCache::Dependency
    unsigned char Type;
    unsigned char CompareOp;
 };
-
-struct pkgCache::Provides
+									/*}}}*/
+struct pkgCache::Provides						/*{{{*/
 {
    map_ptrloc ParentPkg;        // Pacakge
    map_ptrloc Version;          // Version
@@ -314,13 +315,13 @@ struct pkgCache::Provides
    map_ptrloc NextProvides;     // Provides
    map_ptrloc NextPkgProv;      // Provides
 };
-
-struct pkgCache::StringItem
+									/*}}}*/
+struct pkgCache::StringItem						/*{{{*/
 {
    map_ptrloc String;        // Stringtable
    map_ptrloc NextItem;      // StringItem
 };
-
+									/*}}}*/
 #include <apt-pkg/cacheiterators.h>
 
 inline pkgCache::PkgIterator pkgCache::PkgBegin() 
@@ -333,7 +334,7 @@ inline pkgCache::PkgFileIterator pkgCache::FileEnd()
        {return PkgFileIterator(*this,PkgFileP);};
 
 // Oh I wish for Real Name Space Support
-class pkgCache::Namespace
+class pkgCache::Namespace						/*{{{*/
 {   
    public:
 
@@ -351,5 +352,5 @@ class pkgCache::Namespace
    typedef pkgCache::Dep Dep;
    typedef pkgCache::Flag Flag;
 };
-
+									/*}}}*/
 #endif

+ 23 - 19
apt-pkg/pkgcachegen.cc

@@ -53,14 +53,16 @@ pkgCacheGenerator::pkgCacheGenerator(DynamicMMap *pMap,OpProgress *Prog) :
    {
       // Setup the map interface..
       Cache.HeaderP = (pkgCache::Header *)Map.Data();
-      Map.RawAllocate(sizeof(pkgCache::Header));
+      if (Map.RawAllocate(sizeof(pkgCache::Header)) == 0 && _error->PendingError() == true)
+	 return;
+
       Map.UsePools(*Cache.HeaderP->Pools,sizeof(Cache.HeaderP->Pools)/sizeof(Cache.HeaderP->Pools[0]));
-      
+
       // Starting header
       *Cache.HeaderP = pkgCache::Header();
       Cache.HeaderP->VerSysName = Map.WriteString(_system->VS->Label);
       Cache.HeaderP->Architecture = Map.WriteString(_config->Find("APT::Architecture"));
-      Cache.ReMap(); 
+      Cache.ReMap();
    }
    else
    {
@@ -135,7 +137,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
  	 pkgCache::VerIterator Ver = Pkg.VersionList();
  	 map_ptrloc *LastVer = &Pkg->VersionList;
 
-  	 for (; Ver.end() == false; LastVer = &Ver->NextVer, Ver++) 
+	 for (; Ver.end() == false; LastVer = &Ver->NextVer, Ver++)
  	 {
  	    pkgCache::DescIterator Desc = Ver.DescriptionList();
  	    map_ptrloc *LastDesc = &Ver->DescriptionList;
@@ -143,7 +145,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
 
 	    // don't add a new description if we have one for the given
 	    // md5 && language
- 	    for ( ; Desc.end() == false; Desc++)
+	    for ( ; Desc.end() == false; Desc++)
 	       if (MD5SumValue(Desc.md5()) == CurMd5 && 
 	           Desc.LanguageCode() == List.DescriptionLanguage())
 		  duplicate=true;
@@ -151,7 +153,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
 	       continue;
 	    
  	    for (Desc = Ver.DescriptionList();
-		 Desc.end() == false; 
+		 Desc.end() == false;
 		 LastDesc = &Desc->NextDesc, Desc++)
 	    {
  	       if (MD5SumValue(Desc.md5()) == CurMd5) 
@@ -160,7 +162,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
  		  *LastDesc = NewDescription(Desc, List.DescriptionLanguage(), CurMd5, *LastDesc);
  		  Desc->ParentPkg = Pkg.Index();
 		  
- 		  if (NewFileDesc(Desc,List) == false)
+		  if ((*LastDesc == 0 && _error->PendingError()) || NewFileDesc(Desc,List) == false)
  		     return _error->Error(_("Error occurred while processing %s (NewFileDesc1)"),PackageName.c_str());
  		  break;
  	       }
@@ -220,7 +222,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
       Ver->ParentPkg = Pkg.Index();
       Ver->Hash = Hash;
 
-      if (List.NewVersion(Ver) == false)
+      if ((*LastVer == 0 && _error->PendingError()) || List.NewVersion(Ver) == false)
 	 return _error->Error(_("Error occurred while processing %s (NewVersion1)"),
 			      PackageName.c_str());
 
@@ -252,7 +254,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List,
       *LastDesc = NewDescription(Desc, List.DescriptionLanguage(), List.Description_md5(), *LastDesc);
       Desc->ParentPkg = Pkg.Index();
 
-      if (NewFileDesc(Desc,List) == false)
+      if ((*LastDesc == 0 && _error->PendingError()) || NewFileDesc(Desc,List) == false)
 	 return _error->Error(_("Error occurred while processing %s (NewFileDesc2)"),PackageName.c_str());
    }
 
@@ -419,7 +421,7 @@ bool pkgCacheGenerator::NewFileDesc(pkgCache::DescIterator &Desc,
    // Get a structure
    unsigned long DescFile = Map.Allocate(sizeof(pkgCache::DescFile));
    if (DescFile == 0)
-      return 0;
+      return false;
 
    pkgCache::DescFileIterator DF(Cache,Cache.DescFileP + DescFile);
    DF->File = CurrentFile - Cache.PkgFileP;
@@ -460,6 +462,8 @@ map_ptrloc pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc,
    Desc->ID = Cache.HeaderP->DescriptionCount++;
    Desc->language_code = Map.WriteString(Lang);
    Desc->md5sum = Map.WriteString(md5sum.Value());
+   if (Desc->language_code == 0 || Desc->md5sum == 0)
+      return 0;
 
    return Description;
 }
@@ -652,7 +656,6 @@ unsigned long pkgCacheGenerator::WriteUniqString(const char *S,
    return ItemP->String;
 }
 									/*}}}*/
-
 // CheckValidity - Check that a cache is up-to-date			/*{{{*/
 // ---------------------------------------------------------------------
 /* This just verifies that each file in the list of index files exists,
@@ -667,7 +670,7 @@ static bool CheckValidity(const string &CacheFile, FileIterator Start,
    
    // Map it
    FileFd CacheF(CacheFile,FileFd::ReadOnly);
-   SPtr<MMap> Map = new MMap(CacheF,MMap::Public | MMap::ReadOnly);
+   SPtr<MMap> Map = new MMap(CacheF,0);
    pkgCache Cache(Map);
    if (_error->PendingError() == true || Map->Size() == 0)
    {
@@ -810,7 +813,7 @@ bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
    unsigned long EndOfSource = Files.size();
    if (_system->AddStatusFiles(Files) == false)
       return false;
-   
+
    // Decide if we can write to the files..
    string CacheFile = _config->FindFile("Dir::Cache::pkgcache");
    string SrcCacheFile = _config->FindFile("Dir::Cache::srcpkgcache");
@@ -851,7 +854,7 @@ bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
    else
    {
       // Just build it in memory..
-      Map = new DynamicMMap(MMap::Public,MapSize);
+      Map = new DynamicMMap(0,MapSize);
    }
    
    // Lets try the source cache.
@@ -862,8 +865,10 @@ bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
    {
       // Preload the map with the source cache
       FileFd SCacheF(SrcCacheFile,FileFd::ReadOnly);
-      if (SCacheF.Read((unsigned char *)Map->Data() + Map->RawAllocate(SCacheF.Size()),
-		       SCacheF.Size()) == false)
+      unsigned long alloc = Map->RawAllocate(SCacheF.Size());
+      if ((alloc == 0 && _error->PendingError())
+		|| SCacheF.Read((unsigned char *)Map->Data() + alloc,
+				SCacheF.Size()) == false)
 	 return false;
 
       TotalSize = ComputeSize(Files.begin()+EndOfSource,Files.end());
@@ -924,7 +929,7 @@ bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
       if (CacheF != 0)
       {
 	 delete Map.UnGuard();
-	 *OutMap = new MMap(*CacheF,MMap::Public | MMap::ReadOnly);
+	 *OutMap = new MMap(*CacheF,0);
       }
       else
       {
@@ -946,8 +951,7 @@ bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **OutMap)
    if (_system->AddStatusFiles(Files) == false)
       return false;
    
-   SPtr<DynamicMMap> Map;   
-   Map = new DynamicMMap(MMap::Public,MapSize);
+   SPtr<DynamicMMap> Map = new DynamicMMap(0,MapSize);
    unsigned long CurrentSize = 0;
    unsigned long TotalSize = 0;
    

+ 4 - 4
apt-pkg/pkgcachegen.h

@@ -28,7 +28,7 @@ class OpProgress;
 class MMap;
 class pkgIndexFile;
 
-class pkgCacheGenerator
+class pkgCacheGenerator							/*{{{*/
 {
    private:
    
@@ -76,8 +76,8 @@ class pkgCacheGenerator
    pkgCacheGenerator(DynamicMMap *Map,OpProgress *Progress);
    ~pkgCacheGenerator();
 };
-
-// This is the abstract package list parser class.
+									/*}}}*/
+// This is the abstract package list parser class.			/*{{{*/
 class pkgCacheGenerator::ListParser
 {
    pkgCacheGenerator *Owner;
@@ -126,7 +126,7 @@ class pkgCacheGenerator::ListParser
    ListParser() : FoundFileDeps(false) {};
    virtual ~ListParser() {};
 };
-
+									/*}}}*/
 bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
 			MMap **OutMap = 0,bool AllowMem = false);
 bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **OutMap);

+ 4 - 4
apt-pkg/pkgrecords.h

@@ -22,7 +22,7 @@
 #include <apt-pkg/fileutl.h>
 #include <vector>
 
-class pkgRecords
+class pkgRecords							/*{{{*/
 {
    public:
    class Parser;
@@ -42,8 +42,8 @@ class pkgRecords
    pkgRecords(pkgCache &Cache);
    ~pkgRecords();
 };
-
-class pkgRecords::Parser
+									/*}}}*/
+class pkgRecords::Parser						/*{{{*/
 {
    protected:
    
@@ -73,5 +73,5 @@ class pkgRecords::Parser
    
    virtual ~Parser() {};
 };
-
+									/*}}}*/
 #endif

+ 82 - 2
apt-pkg/policy.cc

@@ -32,6 +32,9 @@
     
 #include <apti18n.h>
 
+#include <dirent.h>
+#include <sys/stat.h>
+#include <algorithm>
 #include <iostream>
 #include <sstream>
 									/*}}}*/
@@ -120,6 +123,14 @@ pkgCache::VerIterator pkgPolicy::GetCandidateVer(pkgCache::PkgIterator Pkg)
    signed Max = GetPriority(Pkg);
    pkgCache::VerIterator Pref = GetMatch(Pkg);
 
+   // no package = no candidate version
+   if (Pkg.end() == true)
+      return Pref;
+
+   // packages with a pin lower than 0 have no newer candidate than the current version
+   if (Max < 0)
+      return Pkg.CurrentVer();
+
    /* Falling through to the default version.. Setting Max to zero
       effectively excludes everything <= 0 which are the non-automatic
       priorities.. The status file is given a prio of 100 which will exclude
@@ -239,7 +250,76 @@ signed short pkgPolicy::GetPriority(pkgCache::PkgIterator const &Pkg)
    return 0;
 }
 									/*}}}*/
+// PreferenceSection class - Overriding the default TrimRecord method	/*{{{*/
+// ---------------------------------------------------------------------
+/* The preference file is a user generated file so the parser should
+   therefore be a bit more friendly by allowing comments and new lines
+   all over the place rather than forcing a special format */
+class PreferenceSection : public pkgTagSection
+{
+   void TrimRecord(bool BeforeRecord, const char* &End)
+   {
+      for (; Stop < End && (Stop[0] == '\n' || Stop[0] == '\r' || Stop[0] == '#'); Stop++)
+	 if (Stop[0] == '#')
+	    Stop = (const char*) memchr(Stop,'\n',End-Stop);
+   }
+};
+									/*}}}*/
+// ReadPinDir - Load the pin files from this dir into a Policy		/*{{{*/
+// ---------------------------------------------------------------------
+/* This will load each pin file in the given dir into a Policy. If the
+   given dir is empty the dir set in Dir::Etc::PreferencesParts is used.
+   Note also that this method will issue a warning if the dir does not
+   exists but it will return true in this case! */
+bool ReadPinDir(pkgPolicy &Plcy,string Dir)
+{
+   if (Dir.empty() == true)
+      Dir = _config->FindDir("Dir::Etc::PreferencesParts");
+
+   if (FileExists(Dir) == false)
+   {
+      _error->WarningE("FileExists",_("Unable to read %s"),Dir.c_str());
+      return true;
+   }
+
+   DIR *D = opendir(Dir.c_str());
+   if (D == 0)
+      return _error->Errno("opendir",_("Unable to read %s"),Dir.c_str());
+
+   vector<string> List;
 
+   for (struct dirent *Ent = readdir(D); Ent != 0; Ent = readdir(D))
+   {
+      if (Ent->d_name[0] == '.')
+	 continue;
+
+      // Skip bad file names ala run-parts
+      const char *C = Ent->d_name;
+      for (; *C != 0; C++)
+	 if (isalpha(*C) == 0 && isdigit(*C) == 0 && *C != '_' && *C != '-')
+	    break;
+      if (*C != 0)
+	 continue;
+
+      // Make sure it is a file and not something else
+      string File = flCombine(Dir,Ent->d_name);
+      struct stat St;
+      if (stat(File.c_str(),&St) != 0 || S_ISREG(St.st_mode) == 0)
+	 continue;
+
+      List.push_back(File);
+   }
+   closedir(D);
+
+   sort(List.begin(),List.end());
+
+   // Read the files
+   for (vector<string>::const_iterator I = List.begin(); I != List.end(); I++)
+      if (ReadPinFile(Plcy, *I) == false)
+	 return false;
+   return true;
+}
+									/*}}}*/
 // ReadPinFile - Load the pin file into a Policy			/*{{{*/
 // ---------------------------------------------------------------------
 /* I'd like to see the preferences file store more than just pin information
@@ -259,12 +339,12 @@ bool ReadPinFile(pkgPolicy &Plcy,string File)
    if (_error->PendingError() == true)
       return false;
    
-   pkgTagSection Tags;
+   PreferenceSection Tags;
    while (TF.Step(Tags) == true)
    {
       string Name = Tags.FindS("Package");
       if (Name.empty() == true)
-	 return _error->Error(_("Invalid record in the preferences file, no Package header"));
+	 return _error->Error(_("Invalid record in the preferences file %s, no Package header"), File.c_str());
       if (Name == "*")
 	 Name = string();
       

+ 1 - 0
apt-pkg/policy.h

@@ -84,5 +84,6 @@ class pkgPolicy : public pkgDepCache::Policy
 };
 
 bool ReadPinFile(pkgPolicy &Plcy,string File = "");
+bool ReadPinDir(pkgPolicy &Plcy,string Dir = "");
 
 #endif

+ 10 - 3
apt-pkg/sourcelist.cc

@@ -157,13 +157,20 @@ bool pkgSourceList::ReadMainList()
    // CNC:2003-11-28 - Entries in sources.list have priority over
    //                  entries in sources.list.d.
    string Main = _config->FindFile("Dir::Etc::sourcelist");
+   string Parts = _config->FindDir("Dir::Etc::sourceparts");
+   
    if (FileExists(Main) == true)
-      Res &= ReadAppend(Main);   
+      Res &= ReadAppend(Main);
+   else if (FileExists(Parts) == false)
+      // Only warn if there are no sources.list.d.
+      _error->WarningE("FileExists",_("Unable to read %s"),Main.c_str());
 
-   string Parts = _config->FindDir("Dir::Etc::sourceparts");
    if (FileExists(Parts) == true)
       Res &= ReadSourceDir(Parts);
-   
+   else if (FileExists(Main) == false)
+      // Only warn if there is no sources.list file.
+      _error->WarningE("FileExists",_("Unable to read %s"),Parts.c_str());
+
    return Res;
 }
 									/*}}}*/

+ 16 - 5
apt-pkg/tagfile.cc

@@ -81,7 +81,7 @@ bool pkgTagFile::Resize()
    End = Start + EndSize;
    return true;
 }
-
+									/*}}}*/
 // TagFile::Step - Advance to the next section				/*{{{*/
 // ---------------------------------------------------------------------
 /* If the Section Scanner fails we refill the buffer and try again. 
@@ -212,10 +212,12 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength)
 
    if (Stop == 0)
       return false;
-   
+
    TagCount = 0;
    while (TagCount+1 < sizeof(Indexes)/sizeof(Indexes[0]) && Stop < End)
    {
+       TrimRecord(true,End);
+
       // Start a new index and add it to the hash
       if (isspace(Stop[0]) == 0)
       {
@@ -227,14 +229,14 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength)
       
       if (Stop == 0)
 	 return false;
-      
+
       for (; Stop+1 < End && Stop[1] == '\r'; Stop++);
 
       // Double newline marks the end of the record
       if (Stop+1 < End && Stop[1] == '\n')
       {
 	 Indexes[TagCount] = Stop - Section;
-	 for (; Stop < End && (Stop[0] == '\n' || Stop[0] == '\r'); Stop++);
+	 TrimRecord(false,End);
 	 return true;
       }
       
@@ -244,6 +246,16 @@ bool pkgTagSection::Scan(const char *Start,unsigned long MaxLength)
    return false;
 }
 									/*}}}*/
+// TagSection::TrimRecord - Trim off any garbage before/after a record	/*{{{*/
+// ---------------------------------------------------------------------
+/* There should be exactly 2 newline at the end of the record, no more. */
+void pkgTagSection::TrimRecord(bool BeforeRecord, const char*& End)
+{
+   if (BeforeRecord == true)
+      return;
+   for (; Stop < End && (Stop[0] == '\n' || Stop[0] == '\r'); Stop++);
+}
+									/*}}}*/
 // TagSection::Trim - Trim off any trailing garbage			/*{{{*/
 // ---------------------------------------------------------------------
 /* There should be exactly 1 newline at the end of the buffer, no more. */
@@ -390,7 +402,6 @@ bool pkgTagSection::FindFlag(const char *Tag,unsigned long &Flags,
    return true;
 }
 									/*}}}*/
-
 // TFRewrite - Rewrite a control record					/*{{{*/
 // ---------------------------------------------------------------------
 /* This writes the control record to stdout rewriting it as necessary. The

+ 4 - 1
apt-pkg/tagfile.h

@@ -27,7 +27,6 @@
 class pkgTagSection
 {
    const char *Section;
-   const char *Stop;
    
    // We have a limit of 256 tags per section.
    unsigned int Indexes[256];
@@ -35,6 +34,9 @@ class pkgTagSection
    
    unsigned int TagCount;
      
+   protected:
+   const char *Stop;
+
    public:
    
    inline bool operator ==(const pkgTagSection &rhs) {return Section == rhs.Section;};
@@ -49,6 +51,7 @@ class pkgTagSection
    bool Scan(const char *Start,unsigned long MaxLength);
    inline unsigned long size() const {return Stop - Section;};
    void Trim();
+   virtual void TrimRecord(bool BeforeRecord, const char* &End);
    
    inline unsigned int Count() const {return TagCount;};
    inline void Get(const char *&Start,const char *&Stop,unsigned int I) const

+ 10 - 9
apt-pkg/vendorlist.cc

@@ -10,7 +10,7 @@ pkgVendorList::~pkgVendorList()
       delete *I;
 }
 
-// pkgVendorList::ReadMainList - Read list of known package vendors		/*{{{*/
+// pkgVendorList::ReadMainList - Read list of known package vendors	/*{{{*/
 // ---------------------------------------------------------------------
 /* This also scans a directory of vendor files similar to apt.conf.d 
    which can contain the usual suspects of distribution provided data.
@@ -31,8 +31,8 @@ bool pkgVendorList::ReadMainList()
 
    return CreateList(Cnf);
 }
-
-bool pkgVendorList::Read(string File)
+									/*}}}*/
+bool pkgVendorList::Read(string File)					/*{{{*/
 {
    Configuration Cnf;
    if (ReadConfigFile(Cnf,File,true) == false)
@@ -40,8 +40,8 @@ bool pkgVendorList::Read(string File)
 
    return CreateList(Cnf);
 }
-
-bool pkgVendorList::CreateList(Configuration& Cnf)
+									/*}}}*/
+bool pkgVendorList::CreateList(Configuration& Cnf)			/*{{{*/
 {
    for (vector<const Vendor *>::const_iterator I = VendorList.begin(); 
 	I != VendorList.end(); I++)
@@ -110,8 +110,8 @@ bool pkgVendorList::CreateList(Configuration& Cnf)
    
    return !_error->PendingError();
 }
-
-const Vendor* pkgVendorList::LookupFingerprint(string Fingerprint)
+									/*}}}*/
+const Vendor* pkgVendorList::LookupFingerprint(string Fingerprint)	/*{{{*/
 {
    for (const_iterator I = VendorList.begin(); I != VendorList.end(); ++I)
    {
@@ -121,8 +121,8 @@ const Vendor* pkgVendorList::LookupFingerprint(string Fingerprint)
 
    return NULL;
 }
-
-const Vendor* pkgVendorList::FindVendor(const std::vector<string> GPGVOutput)
+									/*}}}*/
+const Vendor* pkgVendorList::FindVendor(const std::vector<string> GPGVOutput)	/*{{{*/
 {
    for (std::vector<string>::const_iterator I = GPGVOutput.begin(); I != GPGVOutput.end(); I++)
    {
@@ -142,3 +142,4 @@ const Vendor* pkgVendorList::FindVendor(const std::vector<string> GPGVOutput)
 
    return NULL;
 }
+									/*}}}*/

+ 24 - 13
apt-pkg/versionmatch.cc

@@ -63,8 +63,8 @@ pkgVersionMatch::pkgVersionMatch(string Data,MatchType Type) : Type(Type)
 	 if (isdigit(Data[0]))
 	    RelVerStr = Data;
 	 else
-	    RelArchive = Data;
-	 
+	    RelRelease = Data;
+
 	 if (RelVerStr.length() > 0 && RelVerStr.end()[-1] == '*')
 	 {
 	    RelVerPrefixMatch = true;
@@ -87,19 +87,21 @@ pkgVersionMatch::pkgVersionMatch(string Data,MatchType Type) : Type(Type)
       {
 	 if (strlen(Fragments[J]) < 3)
 	    continue;
-	    
+
 	 if (stringcasecmp(Fragments[J],Fragments[J]+2,"v=") == 0)
 	    RelVerStr = Fragments[J]+2;
 	 else if (stringcasecmp(Fragments[J],Fragments[J]+2,"o=") == 0)
 	    RelOrigin = Fragments[J]+2;
 	 else if (stringcasecmp(Fragments[J],Fragments[J]+2,"a=") == 0)
 	    RelArchive = Fragments[J]+2;
+	 else if (stringcasecmp(Fragments[J],Fragments[J]+2,"n=") == 0)
+	    RelCodename = Fragments[J]+2;
 	 else if (stringcasecmp(Fragments[J],Fragments[J]+2,"l=") == 0)
 	    RelLabel = Fragments[J]+2;
 	 else if (stringcasecmp(Fragments[J],Fragments[J]+2,"c=") == 0)
 	    RelComponent = Fragments[J]+2;
       }
-      
+
       if (RelVerStr.end()[-1] == '*')
       {
 	 RelVerPrefixMatch = true;
@@ -169,15 +171,16 @@ bool pkgVersionMatch::FileMatch(pkgCache::PkgFileIterator File)
    {
       if (MatchAll == true)
 	 return true;
-      
+
 /*      cout << RelVerStr << ',' << RelOrigin << ',' << RelArchive << ',' << RelLabel << endl;
       cout << File.Version() << ',' << File.Origin() << ',' << File.Archive() << ',' << File.Label() << endl;*/
-      
+
       if (RelVerStr.empty() == true && RelOrigin.empty() == true &&
 	  RelArchive.empty() == true && RelLabel.empty() == true &&
+	  RelRelease.empty() == true && RelCodename.empty() == true &&
 	  RelComponent.empty() == true)
 	 return false;
-      
+
       if (RelVerStr.empty() == false)
 	 if (File->Version == 0 ||
 	     MatchVer(File.Version(),RelVerStr,RelVerPrefixMatch) == false)
@@ -187,11 +190,19 @@ bool pkgVersionMatch::FileMatch(pkgCache::PkgFileIterator File)
 	     stringcasecmp(RelOrigin,File.Origin()) != 0)
 	    return false;
       if (RelArchive.empty() == false)
-      {
-	 if (File->Archive == 0 || 
+	 if (File->Archive == 0 ||
 	     stringcasecmp(RelArchive,File.Archive()) != 0)
-	    return false;
-      }      
+            return false;
+      if (RelCodename.empty() == false)
+	 if (File->Codename == 0 ||
+	     stringcasecmp(RelCodename,File.Codename()) != 0)
+            return false;
+      if (RelRelease.empty() == false)
+	 if ((File->Archive == 0 ||
+	     stringcasecmp(RelRelease,File.Archive()) != 0) &&
+             (File->Codename == 0 ||
+	      stringcasecmp(RelRelease,File.Codename()) != 0))
+	       return false;
       if (RelLabel.empty() == false)
 	 if (File->Label == 0 ||
 	     stringcasecmp(RelLabel,File.Label()) != 0)
@@ -202,7 +213,7 @@ bool pkgVersionMatch::FileMatch(pkgCache::PkgFileIterator File)
 	    return false;
       return true;
    }
-   
+
    if (Type == Origin)
    {
       if (OrSite.empty() == false) {
@@ -213,7 +224,7 @@ bool pkgVersionMatch::FileMatch(pkgCache::PkgFileIterator File)
 	    return false;
       return (OrSite == File.Site());		/* both strings match */
    }
-   
+
    return false;
 }
 									/*}}}*/

+ 13 - 8
apt-pkg/versionmatch.h

@@ -3,29 +3,32 @@
 // $Id: versionmatch.h,v 1.4 2001/05/29 03:07:12 jgg Exp $
 /* ######################################################################
 
-   Version Matching 
-   
+   Version Matching
+
    This module takes a matching string and a type and locates the version
    record that satisfies the constraint described by the matching string.
 
      Version: 1.2*
      Release: o=Debian,v=2.1*,c=main
      Release: v=2.1*
+     Release: a=testing
+     Release: n=squeeze
      Release: *
      Origin: ftp.debian.org
-   
+
    Release may be a complex type that can specify matches for any of:
       Version (v= with prefix)
       Origin (o=)
-      Archive (a=)
+      Archive (a=) eg, unstable, testing, stable
+      Codename (n=) e.g. etch, lenny, squeeze, sid
       Label (l=)
       Component (c=)
    If there are no equals signs in the string then it is scanned in short
-   form - if it starts with a number it is Version otherwise it is an 
-   Archive.
-   
+   form - if it starts with a number it is Version otherwise it is an
+   Archive or a Codename.
+
    Release may be a '*' to match all releases.
-   
+
    ##################################################################### */
 									/*}}}*/
 #ifndef PKGLIB_VERSIONMATCH_H
@@ -47,6 +50,8 @@ class pkgVersionMatch
    string RelVerStr;
    bool RelVerPrefixMatch;
    string RelOrigin;
+   string RelRelease;
+   string RelCodename;
    string RelArchive;
    string RelLabel;
    string RelComponent;

Plik diff jest za duży
+ 0 - 1526
buildlib/config.guess


+ 1 - 0
buildlib/config.h.in

@@ -22,6 +22,7 @@
 /* These two are used by the statvfs shim for glibc2.0 and bsd */
 /* Define if we have sys/vfs.h */
 #undef HAVE_VFS_H
+#undef HAVE_STRUCT_STATFS_F_TYPE
 
 /* Define if we have sys/mount.h */
 #undef HAVE_MOUNT_H

Plik diff jest za duży
+ 0 - 1658
buildlib/config.sub


+ 7 - 1
buildlib/configure.mak

@@ -15,7 +15,13 @@ BUILDDIR=build
 .PHONY: startup
 startup: configure $(BUILDDIR)/config.status $(addprefix $(BUILDDIR)/,$(CONVERTED))
 
-configure: aclocal.m4 configure.in
+# use the files provided from the system instead of carry around
+# and use (most of the time outdated) copycats
+buildlib/config.sub:
+	ln -sf /usr/share/misc/config.sub buildlib/config.sub
+buildlib/config.guess:
+	ln -sf /usr/share/misc/config.guess buildlib/config.guess	
+configure: aclocal.m4 configure.in buildlib/config.guess buildlib/config.sub
 	autoconf
 
 aclocal.m4: $(wildcard buildlib/*.m4)

+ 12 - 14
buildlib/defaults.mak

@@ -6,26 +6,26 @@
 # for it to operate as expected. When included the module generates
 # the requested rules based on the contents of its control variables.
 
-# This works out very well and allows a good degree of flexability.
-# To accomidate some of the features we introduce the concept of 
+# This works out very well and allows a good degree of flexibility.
+# To accommodate some of the features we introduce the concept of 
 # local variables. To do this we use the 'Computed Names' feature of
 # gmake. Each module declares a LOCAL scope and access it with,
 #   $($(LOCAL)-VAR)
-# This works very well but it is important to rembember that within
-# a rule the LOCAL var is unavailble, it will have to be constructed
-# from the information in the rule invokation. For stock rules like 
+# This works very well but it is important to remember that within
+# a rule the LOCAL var is unavailable, it will have to be constructed
+# from the information in the rule invocation. For stock rules like 
 # clean this is simple, we use a local clean rule called clean/$(LOCAL)
 # and then within the rule $(@F) gets back $(LOCAL)! Other rules will
 # have to use some other mechanism (filter perhaps?) The reason such
 # lengths are used is so that each directory can contain several 'instances'
 # of any given module. I notice that the very latest gmake has the concept
 # of local variables for rules. It is possible this feature in conjunction
-# with the generated names will provide a very powerfull solution indeed!
+# with the generated names will provide a very powerful solution indeed!
 
 # A build directory is used by default, all generated items get put into
 # there. However unlike automake this is not done with a VPATH build
 # (vpath builds break the distinction between #include "" and #include <>)
-# but by explicly setting the BUILD variable. Make is invoked from
+# but by explicitly setting the BUILD variable. Make is invoked from
 # within the source itself which is much more compatible with compilation
 # environments.
 ifndef NOISY
@@ -81,9 +81,7 @@ MANPAGE_H = $(BASE)/buildlib/manpage.mak
 PROGRAM_H = $(BASE)/buildlib/program.mak
 PYTHON_H = $(BASE)/buildlib/python.mak
 COPY_H = $(BASE)/buildlib/copy.mak
-YODL_MANPAGE_H = $(BASE)/buildlib/yodl_manpage.mak
-SGML_MANPAGE_H = $(BASE)/buildlib/sgml_manpage.mak
-XML_MANPAGE_H = $(BASE)/buildlib/xml_manpage.mak
+PO4A_MANPAGE_H = $(BASE)/buildlib/po4a_manpage.mak
 FAIL_H = $(BASE)/buildlib/fail.mak
 PODOMAIN_H = $(BASE)/buildlib/podomain.mak
 
@@ -99,12 +97,12 @@ endif
 
 # Source location control
 # SUBDIRS specifies sub components of the module that
-# may be located in subdrictories of the source dir. 
+# may be located in subdirectories of the source dir. 
 # This should be declared before including this file
 SUBDIRS+=
 
 # Header file control. 
-# TARGETDIRS indicitates all of the locations that public headers 
+# TARGETDIRS indicates all of the locations that public headers 
 # will be published to.
 # This should be declared before including this file
 HEADER_TARGETDIRS+=
@@ -133,7 +131,7 @@ dirs:
 	mkdir -p $(patsubst %/,%,$(sort $(MKDIRS)))
 
 # Header file control. We want all published interface headers to go
-# into the build directory from thier source dirs. We setup some
+# into the build directory from their source dirs. We setup some
 # search paths here
 vpath %.h $(SUBDIRS)
 $(INCLUDE)/%.h $(addprefix $(INCLUDE)/,$(addsuffix /%.h,$(HEADER_TARGETDIRS))) : %.h
@@ -142,7 +140,7 @@ $(INCLUDE)/%.h $(addprefix $(INCLUDE)/,$(addsuffix /%.h,$(HEADER_TARGETDIRS))) :
 # Dependency generation. We want to generate a .d file using gnu cpp.
 # For GNU systems the compiler can spit out a .d file while it is compiling,
 # this is specified with the INLINEDEPFLAG. Other systems might have a 
-# makedep program that can be called after compiling, that's illistrated
+# makedep program that can be called after compiling, that's illustrated
 # by the DEPFLAG case.
 # Compile rules are expected to call this macro after calling the compiler
 ifdef GCC3DEP

+ 4 - 9
buildlib/environment.mak.in

@@ -9,8 +9,6 @@ CPPFLAGS+= @CPPFLAGS@ @DEFS@ -D_REENTRANT -Wall
 CXX = @CXX@
 CXXFLAGS+= @CXXFLAGS@
 NUM_PROCS = @NUM_PROCS@
-GLIBC_VER = @GLIBC_VER@
-LIBSTDCPP_VER = @LIBSTDCPP_VER@
 
 # Linker stuff
 PICFLAGS+= -fPIC -DPIC
@@ -30,14 +28,11 @@ DEBIANDOC_TEXT = @DEBIANDOC_TEXT@
 
 DOXYGEN = @DOXYGEN@
 
-# SGML for the man pages
-DOCBOOK2MAN := @DOCBOOK2MAN@
+# xsltproc for the man pages
+XSLTPROC := @XSLTPROC@
 
-# XML for the man pages
-XMLTO := @XMLTO@
-
-# XML for the man pages
-XMLTO := @XMLTO@
+# po4a for the man pages
+PO4A := @PO4A@
 
 # Gettext settings
 GMSGFMT = @GMSGFMT@

+ 1 - 1
buildlib/library.mak

@@ -5,7 +5,7 @@
 # Input
 # $(SOURCE) - The source code to use
 # $(HEADERS) - Exported header files and private header files
-# $(LIBRARY) - The name of the library without lib or .so 
+# $(LIBRARY) - The name of the library without lib or .so
 # $(MAJOR) - The major version number of this library
 # $(MINOR) - The minor version number of this library
 # $(APT_DOMAIN) - The text domain for this library

+ 21 - 0
buildlib/libversion.mak

@@ -0,0 +1,21 @@
+# -*- make -*-
+# Version number of libapt-pkg.
+# Please increase MAJOR with each ABI break,
+# with each non-ABI break to the lib, please increase RELEASE.
+# The versionnumber is extracted from apt-pkg/init.h - see also there.
+LIBAPTPKG_MAJOR=$(shell awk -v ORS='.' '/^\#define APT_PKG_M/ {print $$3}' $(BASE)/apt-pkg/init.h | sed 's/\.$$//')
+LIBAPTPKG_RELEASE=$(shell grep -E '^\#define APT_PKG_RELEASE' $(BASE)/apt-pkg/init.h | cut -d ' ' -f 3)
+
+# Version number of libapt-inst
+# Please increase MAJOR with each ABI break,
+# with each non-ABI break to the lib, please increase MINOR.
+# The versionnumber is extracted from apt-inst/makefile - see also there.
+LIBAPTINST_MAJOR=$(shell egrep '^MAJOR=' $(BASE)/apt-inst/makefile |cut -d '=' -f 2)
+LIBAPTINST_MINOR=$(shell egrep '^MINOR=' $(BASE)/apt-inst/makefile |cut -d '=' -f 2)
+
+# FIXME: In previous releases this lovely variable includes
+# the detected libc and libdc++ version. As this is bogus we
+# want to drop this, but this a ABI break.
+# And we don't want to do this now. So we hardcode a value here,
+# and drop it later on (hopefully as fast as possible).
+LIBEXT=-libc6.9-6

+ 1 - 1
buildlib/manpage.mak

@@ -5,7 +5,7 @@
 # Input
 # $(SOURCE) - The documents to use
 
-# All output is writtin to files in the build doc directory
+# All output is written to files in the build doc directory
 
 # See defaults.mak for information about LOCAL
 

+ 61 - 0
buildlib/po4a_manpage.mak

@@ -0,0 +1,61 @@
+# -*- make -*-
+
+# This handles man pages with po4a. We convert to the respective
+# output in the source directory then copy over to the final dest. This
+# means po4a is only needed if compiling from bzr
+
+# Input
+# $(LC)     - The language code of the translation
+
+# See defaults.mak for information about LOCAL
+
+# generate a list of accepted man page translations
+SOURCE = $(patsubst %.xml,%,$(wildcard *.$(LC).?.xml))
+INCLUDES = apt.ent
+
+# Do not use XMLTO, build the manpages directly with XSLTPROC
+ifdef XSLTPROC
+
+STYLESHEET=../manpage-style.xsl
+
+LOCAL := po4a-manpage-$(firstword $(SOURCE))
+$(LOCAL)-LIST := $(SOURCE)
+
+# Install generation hooks
+doc: $($(LOCAL)-LIST)
+veryclean: veryclean/$(LOCAL)
+
+$($(LOCAL)-LIST) :: % : %.xml $(INCLUDES)
+	echo Creating man page $@
+	$(XSLTPROC) -o $@ $(STYLESHEET) $< # why xsltproc doesn't respect the -o flag here???
+	test -f $(subst .$(LC),,$@) || echo FIXME: xsltproc respect the -o flag now, workaround can be removed
+	mv -f $(subst .$(LC),,$@) $@
+
+# Clean rule
+.PHONY: veryclean/$(LOCAL)
+veryclean/$(LOCAL):
+	-rm -rf $($(@F)-LIST) apt.ent apt.$(LC).8 \
+		$(addsuffix .xml,$($(@F)-LIST)) \
+		offline.$(LC).sgml guide.$(LC).sgml
+
+HAVE_PO4A=yes
+endif
+
+# take care of the rest
+SOURCE := $(SOURCE) $(wildcard apt.$(LC).8)
+INCLUDES :=
+
+ifndef HAVE_PO4A
+# Strip from the source list any man pages we dont have compiled already
+SOURCE := $(wildcard $(SOURCE))
+endif
+
+# Chain to the manpage rule
+ifneq ($(words $(SOURCE)),0)
+include $(MANPAGE_H)
+endif
+
+# Debian Doc SGML Documents
+SOURCE := $(wildcard *.$(LC).sgml)
+DEBIANDOC_HTML_OPTIONS=-l $(LC)
+include $(DEBIANDOC_H)

+ 0 - 45
buildlib/sgml_manpage.mak

@@ -1,45 +0,0 @@
-# -*- make -*-
-
-# This handles man pages in DocBook SGMLL format. We convert to the respective
-# output in the source directory then copy over to the final dest. This
-# means yodl is only needed if compiling from CVS
-
-# Input
-# $(SOURCE) - The documents to use, in the form foo.sect, ie apt-cache.8
-#             the sgml files are called apt-cache.8.sgml
-
-# See defaults.mak for information about LOCAL
-
-# Some local definitions
-ifdef DOCBOOK2MAN
-
-LOCAL := sgml-manpage-$(firstword $(SOURCE))
-$(LOCAL)-LIST := $(SOURCE)
-
-# Install generation hooks
-doc: $($(LOCAL)-LIST)
-veryclean: veryclean/$(LOCAL)
-
-$($(LOCAL)-LIST) :: % : %.sgml $(INCLUDES)
-	echo Creating man page $@
-	$(DOCBOOK2MAN) $<
-
-# Clean rule
-.PHONY: veryclean/$(LOCAL)
-veryclean/$(LOCAL):
-	-rm -rf $($(@F)-LIST)
-
-HAVE_SGML=yes
-endif
-
-INCLUDES :=
-
-ifndef HAVE_SGML
-# Strip from the source list any man pages we dont have compiled already
-SOURCE := $(wildcard $(SOURCE))
-endif
-
-# Chain to the manpage rule
-ifneq ($(words $(SOURCE)),0)
-include $(MANPAGE_H)
-endif

+ 2 - 1
buildlib/sizetable

@@ -11,6 +11,7 @@
 # The format is:-
 # CPU endian sizeof: char, int, short, long
 i386    little  1 4 2 4
+amd64   little  1 4 2 8
 armeb   big     1 4 2 4
 arm     little  1 4 2 4
 alpha   little  1 4 2 8
@@ -21,4 +22,4 @@ m68k    big     1 4 2 4
 powerpc big     1 4 2 4
 mips    big     1 4 2 4
 hppa    big     1 4 2 4
-m32r	big	1 4 2 4
+m32r	big	1 4 2 4

+ 0 - 50
buildlib/tools.m4

@@ -89,56 +89,6 @@ AC_DEFUN(ah_NUM_PROCS,
 	AC_SUBST(NUM_PROCS)
 ])
 
-AC_DEFUN(rc_GLIBC_VER,
-	[AC_MSG_CHECKING([glibc version])
-	AC_CACHE_VAL(ac_cv_glibc_ver,
-	dummy=if$$
-	cat <<_GLIBC_>$dummy.c
-#include <features.h>
-#include <stdio.h>
-#include <stdlib.h>
-int main(int argc, char **argv) { printf("libc6.%d",__GLIBC_MINOR__); exit(0); }
-_GLIBC_
-	${CC-cc} $dummy.c -o $dummy > /dev/null 2>&1
-	if test "$?" = 0; then
-		GLIBC_VER=`./$dummy`
-		AC_MSG_RESULT([$GLIBC_VER])
-		ac_cv_glibc_ver=$GLIBC_VER
-	else
-		AC_MSG_WARN([cannot determine GNU C library minor version number])
-	fi
-	rm -f $dummy $dummy.c
-	)
-	GLIBC_VER="-$ac_cv_glibc_ver"
-	AC_SUBST(GLIBC_VER)
-])
-
-AC_DEFUN(rc_LIBSTDCPP_VER,
-	[AC_MSG_CHECKING([libstdc++ version])
-	dummy=if$$
-	cat <<_LIBSTDCPP_>$dummy.cc
-#include <features.h>
-#include <stdio.h>
-#include <stdlib.h>
-int main(int argc, char **argv) { exit(0); }
-_LIBSTDCPP_
-	${CXX-c++} $dummy.cc -o $dummy > /dev/null 2>&1
-
-	if test "$?" = 0; then
-		soname=`objdump -p ./$dummy |grep NEEDED|grep libstd`
-                LIBSTDCPP_VER=`echo $soname | sed -e 's/.*NEEDED.*libstdc++\(-libc.*\(-.*\)\)\?.so.\(.*\)/\3\2/'`
-	fi
-	rm -f $dummy $dummy.cc
-
-	if test -z "$LIBSTDCPP_VER"; then
-		AC_MSG_WARN([cannot determine standard C++ library version number])
-	else
-		AC_MSG_RESULT([$LIBSTDCPP_VER])
-		LIBSTDCPP_VER="-$LIBSTDCPP_VER"
-	fi
-	AC_SUBST(LIBSTDCPP_VER)
-])
-
 AC_DEFUN(ah_GCC3DEP,[
 	AC_MSG_CHECKING(if $CXX -MD works)
 	touch gcc3dep.cc

+ 0 - 45
buildlib/xml_manpage.mak

@@ -1,45 +0,0 @@
-# -*- make -*-
-
-# This handles man pages in DocBook XML format. We convert to the respective
-# output in the source directory then copy over to the final dest. This
-# means xmlto is only needed if compiling from Arch
-
-# Input
-# $(SOURCE) - The documents to use, in the form foo.sect, ie apt-cache.8
-#             the XML files are called apt-cache.8.xml
-
-# See defaults.mak for information about LOCAL
-
-# Some local definitions
-ifdef XMLTO
-
-LOCAL := xml-manpage-$(firstword $(SOURCE))
-$(LOCAL)-LIST := $(SOURCE)
-
-# Install generation hooks
-doc: $($(LOCAL)-LIST)
-veryclean: veryclean/$(LOCAL)
-
-$($(LOCAL)-LIST) :: % : %.xml $(INCLUDES)
-	echo Creating man page $@
-	$(XMLTO) man $<
-
-# Clean rule
-.PHONY: veryclean/$(LOCAL)
-veryclean/$(LOCAL):
-	-rm -rf $($(@F)-LIST)
-
-HAVE_XMLTO=yes
-endif
-
-INCLUDES :=
-
-ifndef HAVE_XMLTO
-# Strip from the source list any man pages we dont have compiled already
-SOURCE := $(wildcard $(SOURCE))
-endif
-
-# Chain to the manpage rule
-ifneq ($(words $(SOURCE)),0)
-include $(MANPAGE_H)
-endif

+ 0 - 42
buildlib/yodl_manpage.mak

@@ -1,42 +0,0 @@
-# -*- make -*-
-
-# This handles man pages in YODL format. We convert to the respective
-# output in the source directory then copy over to the final dest. This
-# means yodl is only needed if compiling from CVS
-
-# Input
-# $(SOURCE) - The documents to use, in the form foo.sect, ie apt-cache.8
-#             the yodl files are called apt-cache.8.yo
-
-# See defaults.mak for information about LOCAL
-
-# Some local definitions
-ifdef YODL_MAN
-
-LOCAL := yodl-manpage-$(firstword $(SOURCE))
-$(LOCAL)-LIST := $(SOURCE)
-
-# Install generation hooks
-doc: $($(LOCAL)-LIST)
-veryclean: veryclean/$(LOCAL)
-
-$($(LOCAL)-LIST) :: % : %.yo
-	echo Creating man page $@
-	yodl2man -o $@ $<
-
-# Clean rule
-.PHONY: veryclean/$(LOCAL)
-veryclean/$(LOCAL):
-	-rm -rf $($(@F)-LIST)
-
-else
-
-# Strip from the source list any man pages we dont have compiled already
-SOURCE := $(wildcard $(SOURCE))
-
-endif
-
-# Chain to the manpage rule
-ifneq ($(words $(SOURCE)),0)
-include $(MANPAGE_H)
-endif

+ 14 - 15
cmdline/apt-cache.cc

@@ -399,7 +399,7 @@ bool DumpAvail(CommandLine &Cmd)
    pkgCache &Cache = *GCache;
 
    pkgPolicy Plcy(&Cache);
-   if (ReadPinFile(Plcy) == false)
+   if (ReadPinFile(Plcy) == false || ReadPinDir(Plcy) == false)
       return false;
    
    unsigned long Count = Cache.HeaderP->PackageCount+1;
@@ -626,7 +626,7 @@ bool Depends(CommandLine &CmdL)
    
    return true;
 }
-
+									/*}}}*/
 // RDepends - Print out a reverse dependency tree - mbc			/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -714,10 +714,7 @@ bool RDepends(CommandLine &CmdL)
    
    return true;
 }
-
 									/*}}}*/
-
-
 // xvcg - Generate a graph for xvcg					/*{{{*/
 // ---------------------------------------------------------------------
 // Code contributed from Junichi Uekawa <dancer@debian.org> on 20 June 2002.
@@ -932,13 +929,15 @@ bool XVcg(CommandLine &CmdL)
 		Shapes[ShapeMap[Pkg->ID]]);
       
    }
-   
+
+   delete[] Show;
+   delete[] Flags;
+   delete[] ShapeMap;
+
    printf("}\n");
    return true;
 }
 									/*}}}*/
-
-
 // Dotty - Generate a graph for Dotty					/*{{{*/
 // ---------------------------------------------------------------------
 /* Dotty is the graphvis program for generating graphs. It is a fairly
@@ -1274,15 +1273,16 @@ bool DisplayRecord(pkgCache::VerIterator V)
    return true;
 }
 									/*}}}*/
-// Search - Perform a search						/*{{{*/
-// ---------------------------------------------------------------------
-/* This searches the package names and package descriptions for a pattern */
+
 struct ExDescFile
 {
    pkgCache::DescFile *Df;
    bool NameMatch;
 };
 
+// Search - Perform a search						/*{{{*/
+// ---------------------------------------------------------------------
+/* This searches the package names and package descriptions for a pattern */
 bool Search(CommandLine &CmdL)
 {
    pkgCache &Cache = *GCache;
@@ -1519,7 +1519,7 @@ bool Policy(CommandLine &CmdL)
    
    pkgCache &Cache = *GCache;
    pkgPolicy Plcy(&Cache);
-   if (ReadPinFile(Plcy) == false)
+   if (ReadPinFile(Plcy) == false || ReadPinDir(Plcy) == false)
       return false;
    
    // Print out all of the package files
@@ -1696,7 +1696,6 @@ bool Madison(CommandLine &CmdL)
 
    return true;
 }
-
 									/*}}}*/
 // GenCaches - Call the main cache generator				/*{{{*/
 // ---------------------------------------------------------------------
@@ -1770,8 +1769,7 @@ void CacheInitialize()
    _config->Set("help",false);
 }
 									/*}}}*/
-
-int main(int argc,const char *argv[])
+int main(int argc,const char *argv[])					/*{{{*/
 {
    CommandLine::Args Args[] = {
       {'h',"help","help",0},
@@ -1878,3 +1876,4 @@ int main(int argc,const char *argv[])
           
    return 0;
 }
+									/*}}}*/

+ 4 - 8
cmdline/apt-cdrom.cc

@@ -40,8 +40,7 @@
 
 using namespace std;
 
-                                                                        /*{{{*/
-class pkgCdromTextStatus : public pkgCdromStatus
+class pkgCdromTextStatus : public pkgCdromStatus			/*{{{*/
 {
 protected:
    OpTextProgress Progress;
@@ -75,7 +74,7 @@ string pkgCdromTextStatus::PromptLine(const char *Text)
 
 bool pkgCdromTextStatus::AskCdromName(string &name) 
 {
-   cout << _("Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'") << flush;
+   cout << _("Please provide a name for this Disc, such as 'Debian 5.0.3 Disk 1'") << flush;
    name = PromptLine("");
 	 
    return true;
@@ -98,9 +97,7 @@ OpProgress* pkgCdromTextStatus::GetOpProgress()
 { 
    return &Progress; 
 };
-
 									/*}}}*/
-
 // DoAdd - Add a new CDROM						/*{{{*/
 // ---------------------------------------------------------------------
 /* This does the main add bit.. We show some status and things. The
@@ -129,7 +126,6 @@ bool DoIdent(CommandLine &)
    return cdrom.Ident(ident, &log);
 }
 									/*}}}*/
-
 // ShowHelp - Show the help screen					/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -164,8 +160,7 @@ int ShowHelp()
    return 0;
 }
 									/*}}}*/
-
-int main(int argc,const char *argv[])
+int main(int argc,const char *argv[])					/*{{{*/
 {
    CommandLine::Args Args[] = {
       {'h',"help","help",0},
@@ -222,3 +217,4 @@ int main(int argc,const char *argv[])
    
    return 0;
 }
+									/*}}}*/

+ 2 - 2
cmdline/apt-config.cc

@@ -88,8 +88,7 @@ int ShowHelp()
    return 0;
 }
 									/*}}}*/
-
-int main(int argc,const char *argv[])
+int main(int argc,const char *argv[])					/*{{{*/
 {
    CommandLine::Args Args[] = {
       {'h',"help","help",0},
@@ -133,3 +132,4 @@ int main(int argc,const char *argv[])
    
    return 0;
 }
+									/*}}}*/

+ 2 - 2
cmdline/apt-extracttemplates.cc

@@ -348,8 +348,7 @@ bool Go(CommandLine &CmdL)
 	return !_error->PendingError();
 }
 									/*}}}*/
-
-int main(int argc, const char **argv)
+int main(int argc, const char **argv)					/*{{{*/
 {
 	CommandLine::Args Args[] = {
 		{'h',"help","help",0},
@@ -391,3 +390,4 @@ int main(int argc, const char **argv)
 	
 	return 0;
 }
+									/*}}}*/

+ 244 - 139
cmdline/apt-get.cc

@@ -111,6 +111,9 @@ class CacheFile : public pkgCacheFile
 	 return Open(true);
    }
    CacheFile() : List(0) {};
+   ~CacheFile() {
+      delete[] List;
+   }
 };
 									/*}}}*/
 
@@ -594,7 +597,6 @@ void Stats(ostream &out,pkgDepCache &Dep)
 	       Dep.BadCount());
 }
 									/*}}}*/
-
 // CacheFile::NameComp - QSort compare by name				/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -687,7 +689,10 @@ bool CacheFile::CheckDeps(bool AllowBroken)
       
    return true;
 }
-
+									/*}}}*/
+// CheckAuth - check if each download comes form a trusted source	/*{{{*/
+// ---------------------------------------------------------------------
+/* */
 static bool CheckAuth(pkgAcquire& Fetcher)
 {
    string UntrustedList;
@@ -728,10 +733,7 @@ static bool CheckAuth(pkgAcquire& Fetcher)
 
    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 
@@ -860,14 +862,21 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
    {
       struct statvfs Buf;
       string OutputDir = _config->FindDir("Dir::Cache::Archives");
-      if (statvfs(OutputDir.c_str(),&Buf) != 0)
-	 return _error->Errno("statvfs",_("Couldn't determine free space in %s"),
-			      OutputDir.c_str());
-      if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
+      if (statvfs(OutputDir.c_str(),&Buf) != 0) {
+	 if (errno == EOVERFLOW)
+	    return _error->WarningE("statvfs",_("Couldn't determine free space in %s"),
+				 OutputDir.c_str());
+	 else
+	    return _error->Errno("statvfs",_("Couldn't determine free space in %s"),
+				 OutputDir.c_str());
+      } else if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
       {
          struct statfs Stat;
-         if (statfs(OutputDir.c_str(),&Stat) != 0 ||
-			 unsigned(Stat.f_type) != RAMFS_MAGIC)
+         if (statfs(OutputDir.c_str(),&Stat) != 0
+#if HAVE_STRUCT_STATFS_F_TYPE
+             || unsigned(Stat.f_type) != RAMFS_MAGIC
+#endif
+             )
             return _error->Error(_("You don't have enough free space in %s."),
                 OutputDir.c_str());
       }
@@ -1044,17 +1053,42 @@ bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
 		  pkgProblemResolver &Fix,bool Remove,bool BrokenFix,
 		  unsigned int &ExpectedInst,bool AllowFail = true)
 {
-   /* This is a pure virtual package and there is a single available 
-      provides */
-   if (Cache[Pkg].CandidateVer == 0 && Pkg->ProvidesList != 0 &&
-       Pkg.ProvidesList()->NextProvides == 0)
+   /* This is a pure virtual package and there is a single available
+      candidate providing it. */
+   if (Cache[Pkg].CandidateVer == 0 && Pkg->ProvidesList != 0)
    {
-      pkgCache::PkgIterator Tmp = Pkg.ProvidesList().OwnerPkg();
-      ioprintf(c1out,_("Note, selecting %s instead of %s\n"),
-	       Tmp.Name(),Pkg.Name());
-      Pkg = Tmp;
+      pkgCache::PkgIterator Prov;
+      bool found_one = false;
+
+      for (pkgCache::PrvIterator P = Pkg.ProvidesList(); P; P++)
+      {
+	 pkgCache::VerIterator const PVer = P.OwnerVer();
+	 pkgCache::PkgIterator const PPkg = PVer.ParentPkg();
+
+	 /* Ignore versions that are not a candidate. */
+	 if (Cache[PPkg].CandidateVer != PVer)
+	     continue;
+
+	 if (found_one == false)
+	 {
+	    Prov = PPkg;
+	    found_one = true;
+	 }
+	 else if (PPkg != Prov)
+	 {
+	    found_one = false; // we found at least two
+	    break;
+	 }
+      }
+
+      if (found_one == true)
+      {
+	 ioprintf(c1out,_("Note, selecting %s instead of %s\n"),
+		  Prov.Name(),Pkg.Name());
+	 Pkg = Prov;
+      }
    }
-   
+
    // Handle the no-upgrade case
    if (_config->FindB("APT::Get::upgrade",true) == false &&
        Pkg->CurrentVer != 0)
@@ -1213,129 +1247,155 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs,
 			       pkgSrcRecords &SrcRecs,string &Src,
 			       pkgDepCache &Cache)
 {
-   // We want to pull the version off the package specification..
    string VerTag;
+   string DefRel = _config->Find("APT::Default-Release");
    string TmpSrc = Name;
-   string::size_type Slash = TmpSrc.rfind('=');
 
-   // honor default release
-   string DefRel = _config->Find("APT::Default-Release");
-   pkgCache::PkgIterator Pkg = Cache.FindPkg(TmpSrc);
+   // extract the version/release from the pkgname
+   const size_t found = TmpSrc.find_last_of("/=");
+   if (found != string::npos) {
+      if (TmpSrc[found] == '/')
+	 DefRel = TmpSrc.substr(found+1);
+      else
+	 VerTag = TmpSrc.substr(found+1);
+      TmpSrc = TmpSrc.substr(0,found);
+   }
 
-   if (Slash != string::npos)
-   {
-      VerTag = string(TmpSrc.begin() + Slash + 1,TmpSrc.end());
-      TmpSrc = string(TmpSrc.begin(),TmpSrc.begin() + Slash);
-   } 
-   else  if(!Pkg.end() && DefRel.empty() == false)
+   /* Lookup the version of the package we would install if we were to
+      install a version and determine the source package name, then look
+      in the archive for a source package of the same name. */
+   bool MatchSrcOnly = _config->FindB("APT::Get::Only-Source");
+   const pkgCache::PkgIterator Pkg = Cache.FindPkg(TmpSrc);
+   if (MatchSrcOnly == false && Pkg.end() == false) 
    {
-      // we have a default release, try to locate the pkg. we do it like
-      // this because GetCandidateVer() will not "downgrade", that means
-      // "apt-get source -t stable apt" won't work on a unstable system
-      for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; 
-	   Ver++)
+      if(VerTag.empty() == false || DefRel.empty() == false) 
       {
-	 for (pkgCache::VerFileIterator VF = Ver.FileList(); VF.end() == false;
-	      VF++)
+	 // we have a default release, try to locate the pkg. we do it like
+	 // this because GetCandidateVer() will not "downgrade", that means
+	 // "apt-get source -t stable apt" won't work on a unstable system
+	 for (pkgCache::VerIterator Ver = Pkg.VersionList();
+	      Ver.end() == false; Ver++) 
 	 {
-	    /* If this is the status file, and the current version is not the
-	       version in the status file (ie it is not installed, or somesuch)
-	       then it is not a candidate for installation, ever. This weeds
-	       out bogus entries that may be due to config-file states, or
-	       other. */
-	    if ((VF.File()->Flags & pkgCache::Flag::NotSource) == 
-		pkgCache::Flag::NotSource && Pkg.CurrentVer() != Ver)
-	    continue;
-	    
-	    //std::cout << VF.File().Archive() << std::endl;
-	    if(VF.File().Archive() && (VF.File().Archive() == DefRel)) 
+	    for (pkgCache::VerFileIterator VF = Ver.FileList();
+		 VF.end() == false; VF++) 
 	    {
-	       VerTag = Ver.VerStr();
-	       break;
+	       /* If this is the status file, and the current version is not the
+		  version in the status file (ie it is not installed, or somesuch)
+		  then it is not a candidate for installation, ever. This weeds
+		  out bogus entries that may be due to config-file states, or
+		  other. */
+	       if ((VF.File()->Flags & pkgCache::Flag::NotSource) ==
+		   pkgCache::Flag::NotSource && Pkg.CurrentVer() != Ver)
+		  continue;
+
+	       // We match against a concrete version (or a part of this version)
+	       if (VerTag.empty() == false && strncmp(VerTag.c_str(), Ver.VerStr(), VerTag.size()) != 0)
+		  continue;
+
+	       // or we match against a release
+	       if(VerTag.empty() == false ||
+		  (VF.File().Archive() != 0 && VF.File().Archive() == DefRel) ||
+		  (VF.File().Codename() != 0 && VF.File().Codename() == DefRel)) 
+	       {
+		  pkgRecords::Parser &Parse = Recs.Lookup(VF);
+		  Src = Parse.SourcePkg();
+		  // no SourcePkg name, so it is the "binary" name
+		  if (Src.empty() == true)
+		     Src = TmpSrc;
+		  // no Version, so we try the Version of the SourcePkg -
+		  // and after that the version of the binary package
+		  if (VerTag.empty() == true)
+		     VerTag = Parse.SourceVer();
+		  if (VerTag.empty() == true)
+		     VerTag = Ver.VerStr();
+		  break;
+	       }
 	    }
+	    if (Src.empty() == false)
+	       break;
+	 }
+	 if (Src.empty() == true) 
+	 {
+	    // Sources files have no codename information
+	    if (VerTag.empty() == true && DefRel.empty() == false)
+	       _error->Warning(_("Ignore unavailable target release '%s' of package '%s'"), DefRel.c_str(), TmpSrc.c_str());
+	    DefRel.clear();
 	 }
       }
-   }
-
-   /* Lookup the version of the package we would install if we were to
-      install a version and determine the source package name, then look
-      in the archive for a source package of the same name. */
-   if (_config->FindB("APT::Get::Only-Source") == false)
-   {
-      if (Pkg.end() == false)
+      if (Src.empty() == true)
       {
+	 // if we don't have found a fitting package yet so we will
+	 // choose a good candidate and proceed with that.
+	 // Maybe we will find a source later on with the right VerTag
 	 pkgCache::VerIterator Ver = Cache.GetCandidateVer(Pkg);
-	 if (Ver.end() == false)
+	 if (Ver.end() == false) 
 	 {
 	    pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
 	    Src = Parse.SourcePkg();
+	    if (VerTag.empty() == true)
+	       VerTag = Parse.SourceVer();
 	 }
-      }   
+      }
+   }
+
+   if (Src.empty() == true)
+      Src = TmpSrc;
+   else 
+   {
+      /* if we have a source pkg name, make sure to only search
+	 for srcpkg names, otherwise apt gets confused if there
+	 is a binary package "pkg1" and a source package "pkg1"
+	 with the same name but that comes from different packages */
+      MatchSrcOnly = true;
+      if (Src != TmpSrc) 
+      {
+	 ioprintf(c1out, _("Picking '%s' as source package instead of '%s'\n"), Src.c_str(), TmpSrc.c_str());
+      }
    }
 
    // The best hit
    pkgSrcRecords::Parser *Last = 0;
    unsigned long Offset = 0;
    string Version;
-   bool IsMatch = false;
-   bool MatchSrcOnly = false;
 
-   // No source package name..
-   if (Src.empty() == true)
-      Src = TmpSrc;
-   else 
-      // if we have a source pkg name, make sure to only search
-      // for srcpkg names, otherwise apt gets confused if there
-      // is a binary package "pkg1" and a source package "pkg1"
-      // with the same name but that comes from different packages
-      MatchSrcOnly = true;
-   
-   // If we are matching by version then we need exact matches to be happy
-   if (VerTag.empty() == false)
-      IsMatch = true;
-   
    /* Iterate over all of the hits, which includes the resulting
       binary packages in the search */
    pkgSrcRecords::Parser *Parse;
-   SrcRecs.Restart();
-   while ((Parse = SrcRecs.Find(Src.c_str(), MatchSrcOnly)) != 0)
+   while (true) 
    {
-      string Ver = Parse->Version();
-      
-      // show name mismatches
-      if (IsMatch == true && Parse->Package() != Src) 
-	 ioprintf(c1out,  _("No source package '%s' picking '%s' instead\n"), Parse->Package().c_str(), Src.c_str());
-      
-      if (VerTag.empty() == false)
+      SrcRecs.Restart();
+      while ((Parse = SrcRecs.Find(Src.c_str(), MatchSrcOnly)) != 0) 
       {
-	 /* Don't want to fall through because we are doing exact version 
-	    matching. */
-	 if (Cache.VS().CmpVersion(VerTag,Ver) != 0)
+	 const string Ver = Parse->Version();
+
+	 // Ignore all versions which doesn't fit
+	 if (VerTag.empty() == false && strncmp(VerTag.c_str(), Ver.c_str(), VerTag.size()) != 0)
 	    continue;
-	 
-	 Last = Parse;
-	 Offset = Parse->Offset();
-	 break;
+
+	 // Newer version or an exact match? Save the hit
+	 if (Last == 0 || Cache.VS().CmpVersion(Version,Ver) < 0) {
+	    Last = Parse;
+	    Offset = Parse->Offset();
+	    Version = Ver;
+	 }
+
+	 // was the version check above an exact match? If so, we don't need to look further
+	 if (VerTag.empty() == false && VerTag.size() == Ver.size())
+	    break;
       }
-				  
-      // Newer version or an exact match
-      if (Last == 0 || Cache.VS().CmpVersion(Version,Ver) < 0 || 
-	  (Parse->Package() == Src && IsMatch == false))
-      {
-	 IsMatch = Parse->Package() == Src;
-	 Last = Parse;
-	 Offset = Parse->Offset();
-	 Version = Ver;
-      }      
+      if (Last != 0 || VerTag.empty() == true)
+	 break;
+      //if (VerTag.empty() == false && Last == 0)
+      _error->Warning(_("Ignore unavailable version '%s' of package '%s'"), VerTag.c_str(), TmpSrc.c_str());
+      VerTag.clear();
    }
-   
+
    if (Last == 0 || Last->Jump(Offset) == false)
       return 0;
-   
+
    return Last;
 }
 									/*}}}*/
-
 // DoUpdate - Update the package lists					/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -1399,20 +1459,29 @@ bool DoAutomaticRemove(CacheFile &Cache)
    bool Debug = _config->FindI("Debug::pkgAutoRemove",false);
    bool doAutoRemove = _config->FindB("APT::Get::AutomaticRemove", false);
    bool hideAutoRemove = _config->FindB("APT::Get::HideAutoRemove");
-   pkgDepCache::ActionGroup group(*Cache);
 
+   pkgDepCache::ActionGroup group(*Cache);
    if(Debug)
       std::cout << "DoAutomaticRemove()" << std::endl;
 
-   if (_config->FindB("APT::Get::Remove",true) == false &&
-       doAutoRemove == true)
+   // we don't want to autoremove and we don't want to see it, so why calculating?
+   if (doAutoRemove == false && hideAutoRemove == true)
+      return true;
+
+   if (doAutoRemove == true &&
+	_config->FindB("APT::Get::Remove",true) == false)
    {
       c1out << _("We are not supposed to delete stuff, can't start "
 		 "AutoRemover") << std::endl;
-      doAutoRemove = false;
+      return false;
    }
 
+   bool purgePkgs = _config->FindB("APT::Get::Purge", false);
+   bool smallList = (hideAutoRemove == false &&
+	strcasecmp(_config->Find("APT::Get::HideAutoRemove","").c_str(),"small") == 0);
+
    string autoremovelist, autoremoveversions;
+   unsigned long autoRemoveCount = 0;
    // look over the cache to see what can be removed
    for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); ! Pkg.end(); ++Pkg)
    {
@@ -1421,30 +1490,43 @@ bool DoAutomaticRemove(CacheFile &Cache)
 	 if(Pkg.CurrentVer() != 0 || Cache[Pkg].Install())
 	    if(Debug)
 	       std::cout << "We could delete %s" <<  Pkg.Name() << std::endl;
-	  
-	 // only show stuff in the list that is not yet marked for removal
-	 if(Cache[Pkg].Delete() == false) 
-	 {
-	    autoremovelist += string(Pkg.Name()) + " ";
-	    autoremoveversions += string(Cache[Pkg].CandVersion) + "\n";
-	 }
+
 	 if (doAutoRemove)
 	 {
 	    if(Pkg.CurrentVer() != 0 && 
 	       Pkg->CurrentState != pkgCache::State::ConfigFiles)
-	       Cache->MarkDelete(Pkg, _config->FindB("APT::Get::Purge", false));
+	       Cache->MarkDelete(Pkg, purgePkgs);
 	    else
 	       Cache->MarkKeep(Pkg, false, false);
 	 }
+	 else
+	 {
+	    // only show stuff in the list that is not yet marked for removal
+	    if(Cache[Pkg].Delete() == false) 
+	    {
+	       // we don't need to fill the strings if we don't need them
+	       if (smallList == true)
+		  ++autoRemoveCount;
+	       else
+	       {
+		 autoremovelist += string(Pkg.Name()) + " ";
+		 autoremoveversions += string(Cache[Pkg].CandVersion) + "\n";
+	       }
+	    }
+	 }
       }
    }
-   if (!hideAutoRemove) 
-      ShowList(c1out, _("The following packages were automatically installed and are no longer required:"), autoremovelist, autoremoveversions);
-   if (!doAutoRemove && !hideAutoRemove && autoremovelist.size() > 0)
+   // if we don't remove them, we should show them!
+   if (doAutoRemove == false && (autoremovelist.empty() == false || autoRemoveCount != 0))
+   {
+      if (smallList == false)
+	 ShowList(c1out, _("The following packages were automatically installed and are no longer required:"), autoremovelist, autoremoveversions);
+      else
+	 ioprintf(c1out, _("%lu packages were automatically installed and are no longer required.\n"), autoRemoveCount);
       c1out << _("Use 'apt-get autoremove' to remove them.") << std::endl;
-
-   // Now see if we destroyed anything
-   if (Cache->BrokenCount() != 0)
+   }
+   // Now see if we had destroyed anything (if we had done anything)
+   else if (Cache->BrokenCount() != 0)
    {
       c1out << _("Hmm, seems like the AutoRemover destroyed something which really\n"
 	         "shouldn't happen. Please file a bug report against apt.") << endl;
@@ -1457,7 +1539,7 @@ bool DoAutomaticRemove(CacheFile &Cache)
    }
    return true;
 }
-
+									/*}}}*/
 // DoUpgrade - Upgrade all packages					/*{{{*/
 // ---------------------------------------------------------------------
 /* Upgrade all packages without installing new packages or erasing old
@@ -1532,7 +1614,7 @@ bool TryInstallTask(pkgDepCache &Cache, pkgProblemResolver &Fix,
    regfree(&Pattern);
    return res;
 }
-
+									/*}}}*/
 // DoInstall - Install packages from the command line			/*{{{*/
 // ---------------------------------------------------------------------
 /* Install named packages */
@@ -1870,7 +1952,8 @@ bool DoInstall(CommandLine &CmdL)
    // cache.commit()
    if (AutoMarkChanged > 0 &&
        Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
-       Cache->BadCount() == 0)
+       Cache->BadCount() == 0 &&
+       _config->FindB("APT::Get::Simulate",false) == false)
       Cache->writeStateFile(NULL);
 
    // See if we need to prompt
@@ -2171,14 +2254,21 @@ bool DoSource(CommandLine &CmdL)
    // Check for enough free space
    struct statvfs Buf;
    string OutputDir = ".";
-   if (statvfs(OutputDir.c_str(),&Buf) != 0)
-      return _error->Errno("statvfs",_("Couldn't determine free space in %s"),
-			   OutputDir.c_str());
-   if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
+   if (statvfs(OutputDir.c_str(),&Buf) != 0) {
+      if (errno == EOVERFLOW)
+	 return _error->WarningE("statvfs",_("Couldn't determine free space in %s"),
+				OutputDir.c_str());
+      else
+	 return _error->Errno("statvfs",_("Couldn't determine free space in %s"),
+				OutputDir.c_str());
+   } else if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
      {
        struct statfs Stat;
-       if (statfs(OutputDir.c_str(),&Stat) != 0 || 
-           unsigned(Stat.f_type) != RAMFS_MAGIC) 
+       if (statfs(OutputDir.c_str(),&Stat) != 0
+#if HAVE_STRUCT_STATFS_F_TYPE
+           || unsigned(Stat.f_type) != RAMFS_MAGIC
+#endif
+           ) 
           return _error->Error(_("You don't have enough free space in %s"),
               OutputDir.c_str());
       }
@@ -2522,7 +2612,7 @@ bool DoBuildDep(CommandLine &CmdL)
             {
                // We successfully installed something; skip remaining alternatives
                skipAlternatives = hasAlternatives;
-	       if(_config->FindB("APT::Get::Build-Dep-Automatic", true) == true)
+	       if(_config->FindB("APT::Get::Build-Dep-Automatic", false) == true)
 		  Cache->MarkAuto(Pkg, true);
                continue;
             }
@@ -2548,7 +2638,10 @@ bool DoBuildDep(CommandLine &CmdL)
       
       // Now we check the state of the packages,
       if (Cache->BrokenCount() != 0)
-         return _error->Error(_("Build-dependencies for %s could not be satisfied."),*I);
+      {
+	 ShowBroken(cout, Cache, false);
+	 return _error->Error(_("Build-dependencies for %s could not be satisfied."),*I);
+      }
    }
   
    if (InstallPackages(Cache, false, true) == false)
@@ -2698,8 +2791,7 @@ void SigWinch(int)
 #endif
 }
 									/*}}}*/
-
-int main(int argc,const char *argv[])
+int main(int argc,const char *argv[])					/*{{{*/
 {
    CommandLine::Args Args[] = {
       {'h',"help","help",0},
@@ -2729,6 +2821,7 @@ int main(int argc,const char *argv[])
       {0,"force-yes","APT::Get::force-yes",0},
       {0,"print-uris","APT::Get::Print-URIs",0},
       {0,"diff-only","APT::Get::Diff-Only",0},
+      {0,"debian-only","APT::Get::Diff-Only",0},
       {0,"tar-only","APT::Get::Tar-Only",0},
       {0,"dsc-only","APT::Get::Dsc-Only",0},
       {0,"purge","APT::Get::Purge",0},
@@ -2739,7 +2832,6 @@ int main(int argc,const char *argv[])
       {0,"only-source","APT::Get::Only-Source",0},
       {0,"arch-only","APT::Get::Arch-Only",0},
       {0,"auto-remove","APT::Get::AutomaticRemove",0},
-      {0,"build-dep-automatic","APT::Get::Build-Dep-Automatic",0},
       {0,"allow-unauthenticated","APT::Get::AllowUnauthenticated",0},
       {0,"install-recommends","APT::Install-Recommends",CommandLine::Boolean},
       {0,"fix-policy","APT::Get::Fix-Policy-Broken",0},
@@ -2789,7 +2881,19 @@ int main(int argc,const char *argv[])
       ShowHelp(CmdL);
       return 0;
    }
-   
+
+   // simulate user-friendly if apt-get has no root privileges
+   if (getuid() != 0 && _config->FindB("APT::Get::Simulate") == true)
+   {
+      if (_config->FindB("APT::Get::Show-User-Simulation-Note",true) == true)
+	 cout << _("NOTE: This is only a simulation!\n"
+	    "      apt-get needs root privileges for real execution.\n"
+	    "      Keep also in mind that locking is deactivated,\n"
+	    "      so don't depend on the relevance to the real current situation!"
+	 ) << std::endl;
+      _config->Set("Debug::NoLocking",true);
+   }
+
    // Deal with stdout not being a tty
    if (!isatty(STDOUT_FILENO) && _config->FindI("quiet",0) < 1)
       _config->Set("quiet","1");
@@ -2821,3 +2925,4 @@ int main(int argc,const char *argv[])
    
    return 0;   
 }
+									/*}}}*/

+ 11 - 7
cmdline/apt-key

@@ -93,13 +93,17 @@ update() {
     # add any security. we *need* this check on net-update though
     $GPG_CMD --quiet --batch --keyring $ARCHIVE_KEYRING --export | $GPG --import
 
-    # remove no-longer supported/used keys
-    keys=`$GPG_CMD --keyring $REMOVED_KEYS --with-colons --list-keys | grep ^pub | cut -d: -f5`
-    for key in $keys; do
-	if $GPG --list-keys --with-colons | grep ^pub | cut -d: -f5 | grep -q $key; then
-	    $GPG --quiet --batch --delete-key --yes ${key}
-	fi
-    done
+    if [ -r "$REMOVED_KEYS" ]; then
+	# remove no-longer supported/used keys
+	keys=`$GPG_CMD --keyring $REMOVED_KEYS --with-colons --list-keys | grep ^pub | cut -d: -f5`
+	for key in $keys; do
+	    if $GPG --list-keys --with-colons | grep ^pub | cut -d: -f5 | grep -q $key; then
+		$GPG --quiet --batch --delete-key --yes ${key}
+	    fi
+	done
+    else
+	echo "Warning: removed keys keyring  $REMOVED_KEYS missing or not readable" >&2
+    fi
 }
 
 

+ 10 - 5
cmdline/apt-mark

@@ -2,13 +2,14 @@
 
 from optparse import OptionParser
 
+import sys
+import os.path
+    
 try:
     import apt_pkg
 except ImportError:
     print "Error importing apt_pkg, is python-apt installed?"
-    
-import sys
-import os.path
+    sys.exit(1)
     
 actions = { "markauto" : 1,
             "unmarkauto": 0
@@ -31,8 +32,12 @@ def mark_unmark_automatic(filename, action, pkgs):
     " mark or unmark automatic flag"
     # open the statefile
     if os.path.exists(STATE_FILE):
-        tagfile = apt_pkg.ParseTagFile(open(STATE_FILE))
-        outfile = open(STATE_FILE+".tmp","w")
+        try:
+            tagfile = apt_pkg.ParseTagFile(open(STATE_FILE))
+            outfile = open(STATE_FILE+".tmp","w")
+        except IOError, msg:
+            print "%s, are you root?" % (msg)
+            sys.exit(1)
         while tagfile.Step():
             pkgname = tagfile.Section.get("Package")
             autoInst = tagfile.Section.get("Auto-Installed")

+ 4 - 4
cmdline/apt-sortpkgs.cc

@@ -31,7 +31,7 @@
 
 using namespace std;
 
-struct PkgName
+struct PkgName								/*{{{*/
 {
    string Name;
    string Ver;
@@ -55,7 +55,7 @@ struct PkgName
    bool operator >(const PkgName &x) const {return Compare3(x) > 0;};
    bool operator ==(const PkgName &x) const {return Compare3(x) == 0;};
 };
-
+									/*}}}*/
 // DoIt - Sort a single file						/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -161,8 +161,7 @@ int ShowHelp()
    return 0;
 }
 									/*}}}*/
-
-int main(int argc,const char *argv[])
+int main(int argc,const char *argv[])					/*{{{*/
 {
    CommandLine::Args Args[] = {
       {'h',"help","help",0},
@@ -206,3 +205,4 @@ int main(int argc,const char *argv[])
    
    return 0;   
 }
+									/*}}}*/

+ 9 - 10
configure.in

@@ -18,7 +18,7 @@ AC_CONFIG_AUX_DIR(buildlib)
 AC_CONFIG_HEADER(include/config.h:buildlib/config.h.in include/apti18n.h:buildlib/apti18n.h.in)
 
 dnl -- SET THIS TO THE RELEASE VERSION --
-AC_DEFINE_UNQUOTED(VERSION,"0.7.20~exp3")
+AC_DEFINE_UNQUOTED(VERSION,"0.7.25")
 PACKAGE="apt"
 AC_DEFINE_UNQUOTED(PACKAGE,"$PACKAGE")
 AC_SUBST(PACKAGE)
@@ -112,6 +112,10 @@ if test x"$HAVE_STATVFS" != x"yes"; then
    ])
 fi
 
+AC_CHECK_MEMBERS([struct statfs.f_type],,,
+    [$ac_includes_default
+     #include <sys/vfs.h>])
+
 dnl We should use the real timegm function if we have it.
 AC_CHECK_FUNC(timegm,AC_DEFINE(HAVE_TIMEGM))
 AC_SUBST(HAVE_TIMEGM)
@@ -180,11 +184,11 @@ AC_PATH_PROG(DEBIANDOC_TEXT,debiandoc2text)
 dnl Check for doxygen
 AC_PATH_PROG(DOXYGEN, doxygen)
 
-dnl Check for the SGML tools needed to build man pages
-AC_PATH_PROG(DOCBOOK2MAN,docbook2man)
+dnl Check for the XSLTProc tool needed to build man pages together with po4a
+AC_PATH_PROG(XSLTPROC,xsltproc)
 
-dnl Check for the XML tools needed to build man pages
-AC_PATH_PROG(XMLTO,xmlto)
+dnl Check for the po4a tool needed to build man pages
+AC_PATH_PROG(PO4A,po4a)
 
 dnl Check for graphviz
 AC_CHECK_PROG([HAVE_DOT], [dot], [YES], [NO])
@@ -192,12 +196,7 @@ AC_PATH_PROG([DOT], [dot], [])
 DOTDIR=$(dirname $DOT)
 AC_SUBST(DOTDIR)
 
-dnl Check for YODL
-dnl AC_CHECK_PROG(YODL_MAN,yodl2man,"yes","")
-
 ah_NUM_PROCS
-rc_GLIBC_VER
-rc_LIBSTDCPP_VER
 ah_GCC3DEP
 
 dnl It used to be that the user could select translations and that could get

+ 0 - 13
debian/.cvsignore

@@ -1,13 +0,0 @@
-copyright
-apt
-apt-doc
-apt-utils
-apt-utils.substvars
-apt.substvars
-files
-libapt-pkg-dev
-libapt-pkg-doc
-shlibs.local
-shlibs.local.apt
-shlibs.local.apt-utils
-*.debhelper

+ 43 - 0
debian/NEWS

@@ -0,0 +1,43 @@
+apt (0.7.24) unstable; urgency=low
+
+  * Already included in the last version but now with better documentation
+    is the possibility to add/prefer different compression types while
+    downloading archive informations, which can decrease the time needed for
+    update on slow machines. See apt.conf (5) manpage for details.
+  * APT manages his manpage translations now with po4a, thanks to Nicolas
+    François and Kurasawa Nozomu, who also provide the ja translation.
+    Thanks to Christian Perrier we have already a fr translation and
+    a few more are hopefully added in the near future.
+  * This version also introduces some _experimental_ configuration options
+    to make more aggressive use of dpkg's triggers. If you want to help
+    testing these _experimental_ options see apt.conf (5) manpage.
+
+ -- David Kalnischkies <kalnischkies@gmail.com>  Thu, 24 Sep 2009 15:13:16 +0200
+
+apt (0.7.23) unstable; urgency=low
+
+  * Code that determines which proxy to use was changed. Now
+    'Acquire::{http,ftp}::Proxy[::<host>]' options have the highest priority,
+    and '{http,ftp}_proxy' environment variables are used only if options
+    mentioned above are not specified.
+
+ -- Eugene V. Lyubimkin <jackyf.devel@gmail.com>  Thu, 19 Aug 2009 11:26:16 +0200
+
+apt (0.6.44) unstable; urgency=low
+
+  * apt-ftparchive --db now uses Berkeley DB_BTREE instead of DB_HASH. 
+    If you use a database created by an older version of apt, delete 
+    it and allow it to be recreated the next time.
+
+ -- Michael Vogt <mvo@debian.org>  Wed, 26 Apr 2006 12:57:53 +0200
+
+apt (0.5.25) unstable; urgency=low
+
+  * apt-ftparchive --db now uses Berkeley DB version 4.2.  If used with a
+    database created by an older version of apt, an attempt will be made
+    to upgrade the database, but this may not work in all cases.  If your
+    database is not automatically upgraded, delete it and allow it to be
+    recreated the next time.
+
+ -- Matt Zimmerman <mdz@debian.org>  Sat,  8 May 2004 12:38:07 -0700
+

+ 0 - 18
debian/NEWS.Debian

@@ -1,18 +0,0 @@
-apt (0.6.44) unstable; urgency=low
-
-  * apt-ftparchive --db now uses Berkeley DB_BTREE instead of DB_HASH. 
-    If you use a database created by an older version of apt, delete 
-    it and allow it to be recreated the next time.
-
- -- Michael Vogt <mvo@debian.org>  Wed, 26 Apr 2006 12:57:53 +0200
-
-apt (0.5.25) unstable; urgency=low
-
-  * apt-ftparchive --db now uses Berkeley DB version 4.2.  If used with a
-    database created by an older version of apt, an attempt will be made
-    to upgrade the database, but this may not work in all cases.  If your
-    database is not automatically upgraded, delete it and allow it to be
-    recreated the next time.
-
- -- Matt Zimmerman <mdz@debian.org>  Sat,  8 May 2004 12:38:07 -0700
-

+ 0 - 6
debian/apt-utils.manpages

@@ -1,6 +0,0 @@
-doc/apt-extracttemplates.1
-doc/apt-ftparchive.1
-doc/apt-sortpkgs.1
-doc/fr/apt-extracttemplates.fr.1
-doc/fr/apt-ftparchive.fr.1
-doc/fr/apt-sortpkgs.fr.1

+ 1 - 0
debian/apt.conf.autoremove

@@ -4,5 +4,6 @@ APT
   { 
 	"^linux-image.*";  
 	"^linux-restricted-modules.*";
+	"^kfreebsd-image.*";  
   };
 };

+ 200 - 176
debian/apt.cron.daily

@@ -14,6 +14,9 @@
 #  Dir::Cache::Archive "archives/";
 #  - Set package archive directory
 #
+#  APT::Periodic::Enable "1";
+#  - Enable the update/upgrade script (0=disable)
+#
 #  APT::Periodic::BackupArchiveInterval "0";
 #  - Backup after n-days if archive contents changed.(0=disable)
 #
@@ -46,7 +49,10 @@
 #    
 #  APT::Periodic::Download-Upgradeable-Packages "0";
 #  - Do "apt-get upgrade --download-only" every n-days (0=disable)
-# 
+#
+#  APT::Periodic::Download-Upgradeable-Packages-Debdelta "1";
+#  - Use debdelta-upgrade to download updates if available (0=disable)
+#
 #  APT::Periodic::Unattended-Upgrade "0";
 #  - Run the "unattended-upgrade" security upgrade script 
 #    every n-days (0=disabled)
@@ -69,26 +75,50 @@ check_stamp()
     interval="$2"
 
     if [ $interval -eq 0 ]; then
-	debug_echo "check_stamp: interval=0."
+	debug_echo "check_stamp: interval=0"
 	# treat as no time has passed
         return 1
     fi
 
     if [ ! -f $stamp ]; then
-    	update_stamp $stamp
 	debug_echo "check_stamp: missing time stamp file: $stamp."
 	# treat as enough time has passed
         return 0
     fi
 
     # compare midnight today to midnight the day the stamp was updated
-    stamp=$(date -r $stamp '+%s')
+    stamp_file="$stamp"
+    stamp=$(date --date=$(date -r $stamp_file --iso-8601) +%s 2>/dev/null)
+    if [ "$?" != "0" ]; then
+        # Due to some timezones returning 'invalid date' for midnight on
+        # certain dates (eg America/Sao_Paulo), if date returns with error
+        # remove the stamp file and return 0. See coreutils bug:
+        # http://lists.gnu.org/archive/html/bug-coreutils/2007-09/msg00176.html
+        rm -f "$stamp_file"
+        return 0
+    fi
+
+    now=$(date --date=$(date --iso-8601) +%s 2>/dev/null)
+    if [ "$?" != "0" ]; then
+        # As above, due to some timezones returning 'invalid date' for midnight
+        # on certain dates (eg America/Sao_Paulo), if date returns with error
+        # return 0.
+        return 0
+    fi
+
     delta=$(($now-$stamp))
 
     # intervall is in days, convert to sec.
     interval=$(($interval*60*60*24))
     debug_echo "check_stamp: interval=$interval, now=$now, stamp=$stamp, delta=$delta (sec)"
 
+    # remove timestamps a day (or more) in the future and force re-check
+    if [ $stamp -gt $(($now+86400)) ]; then
+         echo "WARNING: file $stamp_file has a timestamp in the future: $stamp"
+         rm -f "$stamp_file"
+         return 0
+    fi
+
     if [ $delta -ge $interval ]; then
         return 0
     fi
@@ -105,18 +135,25 @@ update_stamp()
 # we check here if autoclean was enough sizewise
 check_size_constraints()
 {
-    # min-age in days
     MaxAge=0
-    MinAge=2
-    MaxSize=0
-    CacheDir="var/cache/apt"
-    CacheArchive="archives/"
     eval $(apt-config shell MaxAge APT::Archives::MaxAge)
+    eval $(apt-config shell MaxAge APT::Periodic::MaxAge)
+
+    MinAge=2
     eval $(apt-config shell MinAge APT::Archives::MinAge)
+    eval $(apt-config shell MinAge APT::Periodic::MinAge)
+
+    MaxSize=0
     eval $(apt-config shell MaxSize APT::Archives::MaxSize)
-    eval $(apt-config shell Dir Dir)
+    eval $(apt-config shell MaxSize APT::Periodic::MaxSize)
+
+    CacheDir="var/cache/apt/"
     eval $(apt-config shell CacheDir Dir::Cache)
+    CacheDir=${CacheDir%/}
+
+    CacheArchive="archives/"
     eval $(apt-config shell CacheArchive Dir::Cache::archives)
+    CacheArchive=${CacheArchive%/}
 
     # sanity check
     if [ -z "$CacheDir" -o -z "$CacheArchive" ]; then
@@ -128,9 +165,13 @@ check_size_constraints()
 
     # check age
     if [ ! $MaxAge -eq 0 ] && [ ! $MinAge -eq 0 ]; then
+	debug_echo "aged: ctime <$MaxAge and mtime <$MaxAge and ctime>$MinAge and mtime>$MinAge"
 	find $Cache -name "*.deb"  \( -mtime +$MaxAge -and -ctime +$MaxAge \) -and -not \( -mtime -$MinAge -or -ctime -$MinAge \) -print0 | xargs -r -0 rm -f
     elif [ ! $MaxAge -eq 0 ]; then
+	debug_echo "aged: ctime <$MaxAge and mtime <$MaxAge only"
 	find $Cache -name "*.deb"  -ctime +$MaxAge -and -mtime +$MaxAge -print0 | xargs -r -0 rm -f
+    else
+	debug_echo "skip aging since MaxAge is 0"
     fi
     
     # check size
@@ -148,11 +189,12 @@ check_size_constraints()
 	    size=${du%%/*}
 	    # check if the cache is small enough
 	    if [ $size -lt $MaxSize ]; then
+		debug_echo "end remove by archive size:  size=$size < $MaxSize"
 		break
 	    fi
 
 	    # check for MinAge of the file
-	    if [ ! $MinAge -eq 0 ]; then 
+	    if [ $MinAge -ne 0 ]; then 
 		# check both ctime and mtime 
 		mtime=$(stat -c %Y $file)
 		ctime=$(stat -c %Z $file)
@@ -161,19 +203,94 @@ check_size_constraints()
 		else
 		    delta=$(($now-$ctime))
 		fi
-		#echo "$file ($delta), $MinAge"
 		if [ $delta -le $MinAge ]; then
-		    #echo "Skiping $file (delta=$delta)"
+		    debug_echo "skip remove by archive size:  $file, delta=$delta < $MinAgeSec"
 		    break
+		else
+		    # delete oldest file
+		    debug_echo "remove by archive size: $file, delta=$delta >= $MinAgeSec (sec), size=$size >= $MaxSize"
+		    rm -f $file
 		fi
 	    fi
-
-	    # delete oldest file
-	    rm -f $file
 	done
     fi
 }
 
+# deal with the Apt::Periodic::BackupArchiveInterval
+do_cache_backup()
+{
+    BackupArchiveInterval="$1"
+    if [ $BackupArchiveInterval -eq 0 ]; then
+	return
+    fi
+
+    # Set default values and normalize
+    Dir="/"
+    eval $(apt-config shell Dir Dir)
+    Dir=${Dir%/}
+
+    CacheDir="var/cache/apt/"
+    eval $(apt-config shell CacheDir Dir::Cache)
+    CacheDir=${CacheDir%/}
+    if [ -z "$CacheDir" ]; then
+	debug_echo "practically empty Dir::Cache, exiting"
+	return 0
+    fi
+
+    CacheArchive="archives/"
+    eval $(apt-config shell CacheArchive Dir::Cache::Archives)
+    CacheArchive=${CacheArchive%/}
+    if [ -z "$CacheArchive" ]; then
+	debug_echo "practically empty Dir::Cache::archives, exiting"
+	return 0
+    fi
+
+    BackupLevel=3
+    eval $(apt-config shell BackupLevel APT::Periodic::BackupLevel)
+    if [ $BackupLevel -le 1 ]; then 
+	BackupLevel=2 ; 
+    fi
+    
+    CacheBackup="backup/"
+    eval $(apt-config shell CacheBackup Dir::Cache::Backup)
+    CacheBackup=${CacheBackup%/}
+    if [ -z "$CacheBackup" ]; then
+	echo "practically empty Dir::Cache::Backup, exiting" 1>&2
+	return
+    fi
+
+    Cache="${Dir}/${CacheDir}/${CacheArchive}/"
+    Back="${Dir}/${CacheDir}/${CacheBackup}/"
+    BackX="${Back}${CacheArchive}/"
+    for x in $(seq 0 1 $((${BackupLevel}-1))); do 
+	eval "Back${x}=${Back}${x}/"
+    done
+    
+    # backup after n-days if archive contents changed.
+    # (This uses hardlink to save disk space)
+    BACKUP_ARCHIVE_STAMP=/var/lib/apt/periodic/backup-archive-stamp
+    if check_stamp $BACKUP_ARCHIVE_STAMP $BackupArchiveInterval; then
+	if [ $({(cd $Cache 2>/dev/null; find . -name "*.deb"); (cd $Back0 2>/dev/null;find . -name "*.deb") ;}| sort|uniq -u|wc -l) -ne 0 ]; then
+	    mkdir -p $Back
+	    rm -rf $Back$((${BackupLevel}-1))
+	    for y in $(seq $((${BackupLevel}-1)) -1 1); do 
+		eval BackY=${Back}$y
+		eval BackZ=${Back}$(($y-1))
+		if [ -e $BackZ ]; then 
+		    mv -f $BackZ $BackY ; 
+		fi
+	    done
+	    cp -la $Cache $Back ; mv -f $BackX $Back0
+	    update_stamp $BACKUP_ARCHIVE_STAMP
+	    debug_echo "backup with hardlinks. (success)"
+	else
+	    debug_echo "skip backup since same content."
+	fi
+    else
+	debug_echo "skip backup since too new."
+    fi
+}
+
 # sleep for a random interval of time (default 30min)
 # (some code taken from cron-apt, thanks)
 random_sleep()
@@ -188,6 +305,7 @@ random_sleep()
 	RANDOM=$(dd if=/dev/urandom count=1 2> /dev/null | cksum | cut -c"1-5")
     fi
     TIME=$(($RANDOM % $RandomSleep))
+    debug_echo "sleeping for $TIME seconds"
     sleep $TIME
 }
 
@@ -200,18 +318,25 @@ debug_echo()
     fi
 }
 
-# main
+# ------------------------ main ----------------------------
 
 # check apt-config exstance
 if ! which apt-config >/dev/null ; then
 	exit 0
 fi
 
+# check if the user really wants to do something
+AutoAptEnable=1  # default is yes
+eval $(apt-config shell AutoAptEnable APT::Periodic::Enable)
+
+if [ $AutoAptEnable -eq 0 ]; then
+    exit 0
+fi
+
 # Set VERBOSE mode from  apt-config (or inherit from environment)
+VERBOSE=0
 eval $(apt-config shell VERBOSE APT::Periodic::Verbose)
-if [ -z "$VERBOSE" ]; then
-    VERBOSE="0"
-fi
+debug_echo "verbose level $VERBOSE"
 if [ "$VERBOSE" -le 2 ]; then
     # quiet for 0,1,2
     XSTDOUT=">/dev/null"
@@ -238,74 +363,25 @@ if which on_ac_power >/dev/null; then
     on_ac_power
     POWER=$?
     if [ $POWER -eq 1 ]; then
-	debug_echo "exit: system on main power."
+	debug_echo "exit: system NOT on main power"
 	exit 0
     elif [ $POWER -ne 0 ]; then
-	debug_echo "exit: power status ($POWER) undetermined."
-	exit 0
+	debug_echo "power status ($POWER) undetermined, continuing"
     fi
     debug_echo "system is on main power."
 fi
 
 # check if we can lock the cache and if the cache is clean
-if which apt-get >/dev/null && ! eval apt-get check $XAPTOPT $XSTDERR ; then
+if which apt-get >/dev/null && ! eval apt-get check -f $XAPTOPT $XSTDERR ; then
     debug_echo "error encountered in cron job with \"apt-get check\"."
     exit 0
 fi
-# No need to check for apt-get below
 
 # Global current time in seconds since 1970-01-01 00:00:00 UTC
 now=$(date +%s)
 
-# Set default values and normalize
-Dir="/"
-eval $(apt-config shell Dir Dir)
-Dir=${Dir%/}
-
-CacheDir="var/cache/apt/"
-eval $(apt-config shell CacheDir Dir::Cache)
-CacheDir=${CacheDir%/}
-if [ -z "$CacheDir" ]; then
-    debug_echo "practically empty Dir::Cache, exiting"
-    exit 0
-fi
-
-CacheArchive="archives/"
-eval $(apt-config shell CacheArchive Dir::Cache::Archives)
-CacheArchive=${CacheArchive%/}
-if [ -z "$CacheArchive" ]; then
-    debug_echo "practically empty Dir::Cache::archives, exiting"
-    exit 0
-fi
-
-BackupArchiveInterval=0
-eval $(apt-config shell BackupArchiveInterval APT::Periodic::BackupArchiveInterval)
-
-BackupLevel=3
-eval $(apt-config shell BackupLevel APT::Periodic::BackupLevel)
-if [ $BackupLevel -le 1 ]; then BackupLevel=2 ; fi
-
-CacheBackup="backup/"
-eval $(apt-config shell CacheBackup Dir::Cache::Backup)
-CacheBackup=${CacheBackup%/}
-if [ -z "$CacheBackup" ]; then
-    echo "practically empty Dir::Cache::Backup, exiting" 1>&2
-    exit 0
-fi
-
 # Support old Archive for compatibility.
 # Document only Periodic for all controling parameters of this script.
-MaxAge=0
-eval $(apt-config shell MaxAge APT::Archives::MaxAge)
-eval $(apt-config shell MaxAge APT::Periodic::MaxAge)
-
-MinAge=2
-eval $(apt-config shell MinAge APT::Archives::MinAge)
-eval $(apt-config shell MinAge APT::Periodic::MinAge)
-
-MaxSize=0
-eval $(apt-config shell MaxSize APT::Archives::MaxSize)
-eval $(apt-config shell MaxSize APT::Periodic::MaxSize)
 
 UpdateInterval=0
 eval $(apt-config shell UpdateInterval APT::Periodic::Update-Package-Lists)
@@ -319,95 +395,34 @@ eval $(apt-config shell UnattendedUpgradeInterval APT::Periodic::Unattended-Upgr
 AutocleanInterval=0
 eval $(apt-config shell AutocleanInterval APT::Periodic::AutocleanInterval)
 
-Cache="${Dir}/${CacheDir}/${CacheArchive}/"
-Back="${Dir}/${CacheDir}/${CacheBackup}/"
-BackX="${Back}${CacheArchive}/"
-for x in $(seq 0 1 $((${BackupLevel}-1))); do 
-    eval "Back${x}=${Back}${x}/"
-done
+BackupArchiveInterval=0
+eval $(apt-config shell BackupArchiveInterval APT::Periodic::BackupArchiveInterval)
 
-# check if we actually have to do anything
+Debdelta=1
+eval $(apt-config shell Debdelta APT::Periodic::Download-Upgradeable-Packages-Debdelta)
+
+# check if we actually have to do anything that requires locking the cache
 if [ $UpdateInterval -eq 0 ] &&
    [ $DownloadUpgradeableInterval -eq 0 ] &&
    [ $UnattendedUpgradeInterval -eq 0 ] &&
    [ $BackupArchiveInterval -eq 0 ] &&
    [ $AutocleanInterval -eq 0 ]; then
-    exit 0
-fi
 
+    # check cache size
+    check_size_constraints
 
-# backup after n-days if archive contents changed.
-# (This uses hardlink to save disk space)
-BACKUP_ARCHIVE_STAMP=/var/lib/apt/periodic/backup-archive-stamp
-if check_stamp $BACKUP_ARCHIVE_STAMP $BackupArchiveInterval; then
-    if [ $({(cd $Cache 2>/dev/null; find . -name "*.deb"); (cd $Back0 2>/dev/null;find . -name "*.deb") ;}| sort|uniq -u|wc -l) -ne 0 ]; then
-	mkdir -p $Back
-	rm -rf $Back$((${BackupLevel}-1))
-	for y in $(seq $((${BackupLevel}-1)) -1 1); do 
-	    eval BackY=${Back}$y
-	    eval BackZ=${Back}$(($y-1))
-	    if [ -e $BackZ ]; then mv -f $BackZ $BackY ; fi
-	done
-	cp -la $Cache $Back ; mv -f $BackX $Back0
-	update_stamp $BACKUP_ARCHIVE_STAMP
-	debug_echo "backup with hardlinks. (success)"
-    else
-
-	debug_echo "skip backup since same content."
-    fi
-else
-	debug_echo "skip backup since too new."
-fi
-
-# package archive contnts removal by package age
-if [ $MaxAge -ne 0 ] && [ $MinAge -ne 0 ]; then
-    find $Cache -name "*.deb"  \( -mtime +$MaxAge -and -ctime +$MaxAge \) -and -not \( -mtime -$MinAge -or -ctime -$MinAge \) -print0 | xargs -r -0 rm -f
-    debug_echo "aged: ctime <$MaxAge and mtime <$MaxAge and ctime>$MinAge and mtime>$MinAge"
-elif [ $MaxAge -ne 0 ]; then
-    find $Cache -name "*.deb"  -ctime +$MaxAge -and -mtime +$MaxAge -print0 | xargs -r -0 rm -f
-    debug_echo "aged: ctime <$MaxAge and mtime <$MaxAge only"
-else
-    debug_echo "skip aging since MaxAge is 0"
+    exit 0
 fi
-    
-# package archive contnts removal down to $MaxSize
-if [ $MaxSize -ne 0 ]; then
-
-    MinAgeSec=$(($MinAge*24*60*60))
-
-    # reverse-sort by mtime
-    for file in $(ls -rt $Cache/*.deb 2>/dev/null); do 
-	du=$(du -m -s $Cache)
-	size=${du%%/*}
-	# check if the cache is small enough
-	if [ $size -lt $MaxSize ]; then
-	    debug_echo "end remove by archive size:  size=$size < $MaxSize"
-	    break
-	fi
 
-	# check for MinAge in second of the file
-	if [ $MinAgeSec -ne 0 ]; then 
-	    # check both ctime and mtime 
-	    mtime=$(stat -c %Y $file)
-	    ctime=$(stat -c %Z $file)
-	    if [ $mtime -gt $ctime ]; then
-		delta=$(($now-$mtime))
-	    else
-		delta=$(($now-$ctime))
-	    fi
-	    if [ $delta -le $MinAgeSec ]; then
-		debug_echo "skip remove by archive size:  $file, delta=$delta < $MinAgeSec"
-	    else
-		# delete oldest file
-		debug_echo "remove by archive size: $file, delta=$delta >= $MinAgeSec (sec), size=$size >= $MaxSize"
-		rm -f $file
-	    fi
-	fi
+# deal with BackupArchiveInterval
+do_cache_backup $BackupArchiveInterval
 
-    done
-fi
+# sleep random amount of time to avoid hitting the 
+# mirrors at the same time
+random_sleep
 
 # update package lists
+UPDATED=0
 UPDATE_STAMP=/var/lib/apt/periodic/update-stamp
 if check_stamp $UPDATE_STAMP $UpdateInterval; then
     if eval apt-get $XAPTOPT -y update $XSTDERR; then
@@ -422,50 +437,59 @@ if check_stamp $UPDATE_STAMP $UpdateInterval; then
 	    debug_echo "dbus signal not send (command not available)"
 	fi
 	update_stamp $UPDATE_STAMP
-	# download all upgradeable packages if it is requested
-	DOWNLOAD_UPGRADEABLE_STAMP=/var/lib/apt/periodic/download-upgradeable-stamp
-	if check_stamp $DOWNLOAD_UPGRADEABLE_STAMP $DownloadUpgradeableInterval; then
-	    if eval apt-get $XAPTOPT -y -d dist-upgrade $XSTDERR; then
-		update_stamp $DOWNLOAD_UPGRADEABLE_STAMP
-		debug_echo "download upgradable (success)."
-		# auto upgrade all upgradeable packages
-		UPGRADE_STAMP=/var/lib/apt/periodic/upgrade-stamp
-		if which unattended-upgrade >/dev/null && check_stamp $UPGRADE_STAMP $UnattendedUpgradeInterval; then
-		    if unattended-upgrade $XUUPOPT; then
-			update_stamp $UPGRADE_STAMP
-			debug_echo "unattended-upgrade (success)."
-		    else
-			debug_echo "unattended-upgrade (error)."
-		    fi
-		else
-		    debug_echo "unattended-upgrade (not run)."
-		fi
-	    else
-		debug_echo "download upgradable (error)."
-	    fi
-	else
-	    debug_echo "download upgradable (not run)."
-	fi
+	UPDATED=1
     else
-	debug_echo "download updated metadata (error)."
+	debug_echo "download updated metadata (error)"
     fi
 else
     debug_echo "download updated metadata (not run)."
 fi
+	
+# download all upgradeable packages (if it is requested)
+DOWNLOAD_UPGRADEABLE_STAMP=/var/lib/apt/periodic/download-upgradeable-stamp
+if [ $UPDATED -eq 1 ] && check_stamp $DOWNLOAD_UPGRADEABLE_STAMP $DownloadUpgradeableInterval; then
+    if [ $Debdelta -eq 1 ]; then
+        debdelta-upgrade >/dev/null 2>&1 || true
+    fi
+    if  eval apt-get $XAPTOPT -y -d dist-upgrade $XSTDERR; then
+	update_stamp $DOWNLOAD_UPGRADEABLE_STAMP
+	debug_echo "download upgradable (success)"
+    else
+	debug_echo "download upgradable (error)"
+    fi
+else
+    debug_echo "download upgradable (not run)"
+fi
+
+# auto upgrade all upgradeable packages
+UPGRADE_STAMP=/var/lib/apt/periodic/upgrade-stamp
+if [ $UPDATED -eq 1 ] && which unattended-upgrade >/dev/null && check_stamp $UPGRADE_STAMP $UnattendedUpgradeInterval; then
+    if unattended-upgrade $XUUPOPT; then
+	update_stamp $UPGRADE_STAMP
+	debug_echo "unattended-upgrade (success)"
+    else
+	debug_echo "unattended-upgrade (error)"
+    fi
+else
+    debug_echo "unattended-upgrade (not run)"
+fi
 
 # autoclean package archive
 AUTOCLEAN_STAMP=/var/lib/apt/periodic/autoclean-stamp
 if check_stamp $AUTOCLEAN_STAMP $AutocleanInterval; then
-    if apt-get $XAPTOPT -y autoclean $XSTDERR; then
+    if  eval apt-get $XAPTOPT -y autoclean $XSTDERR; then
 	debug_echo "autoclean (success)."
 	update_stamp $AUTOCLEAN_STAMP
     else
-	debug_echo "autoclean (error)."
+	debug_echo "autoclean (error)"
     fi
 else
-    debug_echo "autoclean (not run)."
+    debug_echo "autoclean (not run)"
 fi
 
+# check cache size 
+check_size_constraints
+
 #
 #     vim: set sts=4 ai :
 #

+ 1 - 0
debian/apt.dirs

@@ -3,6 +3,7 @@ usr/lib/apt/methods
 usr/lib/dpkg/methods/apt
 etc/apt
 etc/apt/apt.conf.d
+etc/apt/preferences.d
 etc/apt/sources.list.d
 etc/logrotate.d
 var/cache/apt/archives/partial

+ 0 - 0
debian/apt.logrotate


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